Skip to content

5535 Exclude requisition made from web entries in mSupply #5536

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Apr 28, 2025
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions dev_scripts/clean.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ echo "Cleaning up temporary files..."
rm -rf $TMPDIR_PACKAGER $TMPDIR_METRO
echo "Cleaning up watchman files..."
npx watchman watch-del-all
echo "Cleaning up android build files..."
rm -rf android/.gradle
rm -rf android/.idea
rm -rf android/app/build
echo "Reinstalling node modules..."
rm -rf node_modules/ &&
yarn cache clean &&
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
},
"name": "mSupplyMobile",
"//": "version must be in the format ${majorNumber}.${minorNumber}.${patchNumber}-rc${releaseCandidateNumber}",
"version": "8.6.9",
"version": "8.7.0",
"private": false,
"license": "MIT",
"description": "Mobile app for use with the mSupply medical inventory control software",
Expand Down
41 changes: 40 additions & 1 deletion src/dataMigration.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ const dataMigrations = [
// as supplying store during initial sync.
if (
settings.get(SETTINGS_KEYS.SUPPLYING_STORE_NAME_ID) ===
'B1938F4FFDC2074DB5408B435ACEB198' ||
'B1938F4FFDC2074DB5408B435ACEB198' ||
settings.get(SETTINGS_KEYS.SUPPLYING_STORE_ID) === '734CC3EC70283A4AABC4E645C8B1E11D'
) {
settings.set(SETTINGS_KEYS.SUPPLYING_STORE_NAME_ID, 'E5D7BB38571C1F428AF397240EEB285F');
Expand Down Expand Up @@ -286,6 +286,45 @@ const dataMigrations = [
clearNumberSequences(database);
},
},
{
version: '8.7.0',
migrate: database => {
try {
// Get all blank request requisitions (i.e requisitions they might have been created
// possibly from web entries - having status 'wp', 'wf' etc in the mSupply) or
// through transactions linked to requisitions they were already deleted from the mSupply
const blankRequisitions = database
.objects('Requisition')
.filtered('otherStoreName == null and status == "new" and type == "request"')
.snapshot();

// Delete all blank request requisitions and their requisition items
database.write(() => {
blankRequisitions.forEach(requisition => {
// Check for linked transactions and unlink them first before deleting it
// to avoid any data integrity issues
const { linkedTransaction } = requisition;
if (linkedTransaction) {
database.update('Transaction', {
id: linkedTransaction.id,
linkedRequisition: null,
});
database.update('Requisition', {
id: requisition.id,
linkedTransaction: null,
});
}

// delete the requisition
database.delete('Requisition', requisition);
});
});
} catch (e) {
// eslint-disable-next-line no-console
console.error('Migration 8.7.0 error:', e.message, e.stack);
}
},
},
];

export default dataMigrations;
1 change: 1 addition & 0 deletions src/database/DataTypes/Transaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,7 @@ Transaction.schema = {
mode: { type: 'string', default: 'store' },
prescriber: { type: 'Prescriber', optional: true },
linkedRequisition: { type: 'Requisition', optional: true },
pendingRequisitionId: { type: 'string', optional: true, indexed: true },
subtotal: { type: 'double', optional: true },
outstanding: { type: 'double', optional: true },
insurancePolicy: { type: 'InsurancePolicy', optional: true },
Expand Down
2 changes: 1 addition & 1 deletion src/database/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ export const schema = {
VaccineVialMonitorStatus,
VaccineVialMonitorStatusLog,
],
schemaVersion: 30,
schemaVersion: 31,
};

export default schema;
53 changes: 35 additions & 18 deletions src/sync/incomingSyncUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ export const sanityCheckIncomingRecord = (recordType, record) => {
canBeBlank: ['user_ID', 'network_ID'],
},
Requisition: {
cannotBeBlank: ['status', 'type', 'daysToSupply'],
cannotBeBlank: ['name_ID', 'store_ID', 'status', 'type', 'daysToSupply'],
canBeBlank: ['date_entered', 'serial_number', 'requester_reference', 'programID', 'periodID'],
},
RequisitionItem: {
Expand Down Expand Up @@ -675,19 +675,21 @@ export const createOrUpdateRecord = (database, settings, recordType, record) =>
break;
}
case 'Requisition': {
let status = REQUISITION_STATUSES.translate(record.status, EXTERNAL_TO_INTERNAL);
let period;
// If not a special 'wp' or 'wf' status, use the normal status translation.
if (!status) {
status = STATUSES.translate(record.status, EXTERNAL_TO_INTERNAL);
}
if (record.periodID) {
period = database.getOrCreate('Period', record.periodID);
}
if (record.store_ID !== settings.get(THIS_STORE_ID)) break; // Not for this store

const status = REQUISITION_STATUSES.translate(record.status, EXTERNAL_TO_INTERNAL);
if (!status) break; // Must be a requisition status, either 'suggested' or 'finalised'
const period = database.getOrCreate('Period', record.periodID);

// Look for transactions that are waiting for this requisition to be linked
const pendingTransactions = database
.objects('Transaction')
.filtered('pendingRequisitionId == $0', record.ID);
const linkedTransaction = pendingTransactions.length > 0 ? pendingTransactions[0] : null;

internalRecord = {
id: record.ID,
status: REQUISITION_STATUSES.translate(record.status, EXTERNAL_TO_INTERNAL),
status,
entryDate: parseDate(record.date_entered),
daysToSupply: parseNumber(record.daysToSupply),
serialNumber: record.serial_number,
Expand All @@ -703,13 +705,26 @@ export const createOrUpdateRecord = (database, settings, recordType, record) =>
customData: parseJsonString(record.custom_data),
isRemoteOrder: parseBoolean(record.isRemoteOrder),
createdDate: parseDate(record.date_order_received),
linkedTransaction,
};
const requisition = database.update(recordType, internalRecord);

if (linkedTransaction) {
database.update('Transaction', {
id: linkedTransaction.id,
linkedRequisition: requisition,
pendingRequisitionId: null,
});
}
if (period) period.addRequisitionIfUnique(requisition);
break;
}
case 'RequisitionItem': {
const requisition = database.getOrCreate('Requisition', record.requisition_ID);
const requisition = database.get('Requisition', record.requisition_ID);
// Technically, if the requisition is null, this item becomes an orphan record
// and shouldn't be saved.
// But for the history of the requisition and to investigate the orphaned item,
// we will save it.
internalRecord = {
id: record.ID,
requisition,
Expand All @@ -729,9 +744,12 @@ export const createOrUpdateRecord = (database, settings, recordType, record) =>
option: database.getOrCreate('Options', record.optionID),
};
const requisitionItem = database.update(recordType, internalRecord);
// requisitionItem will be an orphan record if it's not unique?
requisition.addItemIfUnique(requisitionItem);
database.save('Requisition', requisition);

if (requisition) {
// requisitionItem will be an orphan record if it's not unique?
requisition.addItemIfUnique(requisitionItem);
database.save('Requisition', requisition);
}
break;
}
case 'Stocktake': {
Expand Down Expand Up @@ -795,9 +813,7 @@ export const createOrUpdateRecord = (database, settings, recordType, record) =>
if (record.store_ID !== settings.get(THIS_STORE_ID)) break; // Not for this store
const otherParty = database.getOrCreate('Name', record.name_ID);
const enteredBy = database.getOrCreate('User', record.user_ID);
const linkedRequisition = record.requisition_ID
? database.get('Requisition', record.requisition_ID)
: null;
const linkedRequisition = database.get('Requisition', record.requisition_ID);
const linkedTransaction = record.linked_transaction_id
? database.getOrCreate('Transaction', record.linked_transaction_id)
: null;
Expand All @@ -822,6 +838,7 @@ export const createOrUpdateRecord = (database, settings, recordType, record) =>
mode: record.mode,
prescriber: database.getOrCreate('Prescriber', record.prescriber_ID),
linkedRequisition,
pendingRequisitionId: record.requisition_ID,
subtotal: parseFloat(record.subtotal),
outstanding: parseFloat(record.total),
insurancePolicy,
Expand Down
3 changes: 1 addition & 2 deletions src/sync/syncTranslators.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,12 +142,11 @@ export const NAME_TYPES = new SyncTranslator({
*/
class RequisitionStatusTranslator extends SyncTranslator {
translate(status, direction) {
if (['cn', 'wf'].includes(status)) return 'finalised';
if (status === 'cn') return 'finalised';
return super.translate(status, direction);
}
}
export const REQUISITION_STATUSES = new RequisitionStatusTranslator({
new: 'wp', // 'wp', 'wf', 'cn' should never be returned in api/v3.
suggested: 'sg',
finalised: 'fn',
});
Expand Down