Repository: msupply-foundation/mobile
Pull request #5536: 5535 Exclude requisition made from web entries in mSupply
Author: login: raviSussol
Labels: name: Bug: production
description: Bug was found or believed to be in a live release
name: tester: Anusha
Created: 2025-04-07T12:18:20Z | Merged: 2025-04-28T07:32:35Z

Fixes #5535 

## Change summary
- Removed `wp` and `wf` statuses from requisition schema and its related method to stop processing incoming requisitions made from web entries in the mSupply.
- Fixed data linkage between `Transaction` & 'Requisiton` objects they have been broken from #5407 

## Testing

Steps to reproduce or otherwise test the changes of this PR:

- [ ] Use the built [apk](https://store8.gofile.io/download/web/03f1412e-e1a2-4d0f-9309-89ecaa6dcbbc/mSupplyMobile-8_7_0-universal-release.apk) and install on the tablet and use the mSupply [installers](https://www.dropbox.com/scl/fo/05qk2fibmuhya83gjyadm/AG4NfJEH3gyPFDyyFNjz500?rlkey=yl55kgmfplpmejnyzolpbadon&st=1m00pznf&dl=0) to setup central server.
- [ ] For developers the PR is here : https://github.com/msupply-foundation/msupply/pull/16410
**Brand new mobile setup**
- [ ] Setup any mobile site of Fiji moh with mSupply central server (i.e. use Fiji moh datafile)
- [ ] Note copy Fiji moh mSupply data before you proceed below test cases - you'll need it for other variety of test cases
- [ ] I used `Samabula_pharm` store's site
- [ ] Initialize sync from mSupply to mobile
- [ ] Login to the tablet and goto the supplier requisition and follow test 1
**Mobile upgrade setup**
- [ ] Use you Fiji moh mSupply data from second copy
- [ ] Have a mobile apk version setup lower than `v8.6.8`
- [ ] Setup sync with msupply central server with the above store's site
- [ ] Login to the app and in the Supplier requisition you can now see some blank requisitions
- [ ] Now upgrade the mobile app to `v8.7.0`
- [ ] Login to the app after upgrade and do force sync
- [ ] In the mSupply central server goto the scheduler dashboard window and force run `scheduler_processMessages` scheduler
- [ ] Now in the mobile app again do force sync and follow test 2
- [ ] Now export mobile data. You'll need admin pass `thisisnepal123` enter that and click `Export Data`
- [ ] Open that realm file in realm studio and follow test 3

## Tests
- Test 1
- [ ] Should not display blank or having serial number 0 requisition
- [ ] Also check the customer requisition - should not have any blank or having serial number 0 requisition
- [ ] Please do regression tests related requisitions (both customer and supplier) 
  - [ ] Setup 2 mobile apps and 1 oms site (i.e 1 oms central server with 1 oms remote) and 1 mSupply central server and 1 mSupply remote desktop site
  - [ ] Try creating some invoices (i.e from internal order or supplier requisition or request requisition -> response requisition or customer requisition -> customer invoice or outbound shipment (then via stock transfer) -> supplier invoice or inbound shipment
  - [ ] Do thorough tests on these workflow among OG mobile, oms site, msupply sites and see if there anything gets broken - should be working flawlessly

- Test 2
- [ ] All blank requisitions will be gone in the mobile and requisitions having `wp` status will also be gone from the mSupply
- Test 3
- [ ] In the `Requisition` object goto the `linkedTransaction` field where you can see linked transaction records in it
- [ ] Similarly, in the `Transaction` object goto the `linkedRequisition` field where you can see linked requisition records in there

Linked issue #5535: Invalid Requisition appears to be created due to Finalised  Supplier Invoice
## Invalid Requisition appears to be created due to Finalised  Supplier Invoice

On Mobile setup, It appears that some Finalised `SI` invoice gets processed by the Mobile and invalid requisition are created.  @ujwalSussol  : looked at the data and reviewed the requisition data to work out the flow.  


Cerb Link:

https://cerb.msupply.org/profiles/ticket/CA-5261-QS/conversation
https://cerb.msupply.org/profiles/ticket/XV-9624-ZT/conversation


### To reproduce

Steps to reproduce the behaviour:

1. Perhaps user Fiji MOH  March 22, 2025 data.
2. On Mobile sync out the `Samabula_pharm` store
3. See Error :  Invalid Requisition are created on current date 
4. See Screenshot

![Image](https://github.com/user-attachments/assets/08ba5941-11fa-4869-9c58-297a90d5919a)


What was observed : 

- We have Finalised `SI` that syncs to the mobile
-  Mobile then created invalid Requisition.


### Expected behaviour

'Si' that is of stock transfer should not create a `Requisition`


### Proposed Solution

Fix the bug

### Version and device info

- App version: 8.6.2


### Additional context

Could be related to `RemoteOrder` being `True`, we faced this issue before :  https://github.com/msupply-foundation/mobile/issues/4387       ( It may not be related )
Linked issue comments: user: login: Gwalior-84
created_at: 2025-04-11T07:03:40Z
body: @raviSussol could you please assure me that this upgrade will work as expected after the Legacy mSupply central server is upgraded to v8.07?
author_association: NONE
user: login: raviSussol
created_at: 2025-04-11T11:30:24Z
body: @Gwalior-84 The idea is we upgrade the mSupply central server to `V8.01.11` first and then upgrade mobile app to `v8.7.0`. All blank requisitions should be gone.

author_association: COLLABORATOR
user: login: raviSussol
created_at: 2025-04-28T07:33:19Z
body: Closed as per #5536
author_association: COLLABORATOR

Diff:
diff --git a/dev_scripts/clean.sh b/dev_scripts/clean.sh
index fb200667d..4d1da4f4b 100755
--- a/dev_scripts/clean.sh
+++ b/dev_scripts/clean.sh
@@ -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 &&
diff --git a/package.json b/package.json
index f7f50bdd9..b711822d2 100644
--- a/package.json
+++ b/package.json
@@ -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",
diff --git a/src/dataMigration.js b/src/dataMigration.js
index 265a7da2c..f07686a05 100644
--- a/src/dataMigration.js
+++ b/src/dataMigration.js
@@ -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');
@@ -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;
diff --git a/src/database/DataTypes/Transaction.js b/src/database/DataTypes/Transaction.js
index 79d1cc977..b21f9a385 100644
--- a/src/database/DataTypes/Transaction.js
+++ b/src/database/DataTypes/Transaction.js
@@ -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 },
diff --git a/src/database/schema.js b/src/database/schema.js
index d568d3dbc..a4d95d458 100644
--- a/src/database/schema.js
+++ b/src/database/schema.js
@@ -257,7 +257,7 @@ export const schema = {
     VaccineVialMonitorStatus,
     VaccineVialMonitorStatusLog,
   ],
-  schemaVersion: 30,
+  schemaVersion: 31,
 };
 
 export default schema;
diff --git a/src/sync/incomingSyncUtils.js b/src/sync/incomingSyncUtils.js
index 6874fc2af..163dafe6a 100644
--- a/src/sync/incomingSyncUtils.js
+++ b/src/sync/incomingSyncUtils.js
@@ -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: {
@@ -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,
@@ -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,
@@ -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': {
@@ -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;
@@ -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,
diff --git a/src/sync/outgoingSyncUtils.js b/src/sync/outgoingSyncUtils.js
index cb46ec703..884ee9cf8 100644
--- a/src/sync/outgoingSyncUtils.js
+++ b/src/sync/outgoingSyncUtils.js
@@ -111,12 +111,13 @@ const generateSyncData = (settings, recordType, record) => {
       return nameRecord;
     }
     case 'Requisition': {
+      const status = REQUISITION_STATUSES.translate(record.status, INTERNAL_TO_EXTERNAL);
       return {
         ID: record.id,
         date_entered: getDateString(record.entryDate),
         user_ID: record.enteredById,
         name_ID: record.otherStoreName?.id ?? '',
-        status: REQUISITION_STATUSES.translate(record.status, INTERNAL_TO_EXTERNAL),
+        status: status ?? 'sg', // If undefined, probably means the requisition is new. Set to 'sg'.
         daysToSupply: String(record.daysToSupply),
         store_ID: settings.get(THIS_STORE_ID),
         serial_number: record.serialNumber,
diff --git a/src/sync/syncTranslators.js b/src/sync/syncTranslators.js
index e01f85f1b..041da6a33 100644
--- a/src/sync/syncTranslators.js
+++ b/src/sync/syncTranslators.js
@@ -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',
 });


Reviews:
user: login: copilot-pull-request-reviewer[bot]
body: 

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.


<details>
<summary>Comments suppressed due to low confidence (1)</summary>

**src/sync/incomingSyncUtils.js:683**
* The previous check for the existence of record.periodID was removed, which may lead to unintended behavior if record.periodID is undefined. Consider adding a validation to ensure record.periodID is present before calling getOrCreate.
```
const period = database.getOrCreate('Period', record.periodID);
```
</details>


state: COMMENTED
author_association: NONE
submitted_at: 2025-04-07T12:46:57Z
user: login: anildahalsussol
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-18T05:45:46Z
user: login: anildahalsussol
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-18T05:47:55Z
user: login: anildahalsussol
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-18T05:48:56Z
user: login: anildahalsussol
body: Over all looks good to me. 
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-18T05:50:18Z
user: login: anildahalsussol
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-18T05:54:54Z
user: login: ujwalSussol
body: approved :   But we do need to do a group test to make sure that daily activities are not messed up. 
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T11:12:01Z
user: login: Chris-Petty
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-07-01T22:50:47Z
user: login: raviSussol
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-07-02T00:49:31Z
user: login: andreievg
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-07-02T01:25:23Z
user: login: Chris-Petty
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-07-02T02:03:29Z
user: login: raviSussol
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-07-02T02:32:27Z

Review comments:
path: src/dataMigration.js
user: login: anildahalsussol
body: Makes sense so updating transaction so we dont create any blank requisiton in future and also updating requisition and deleting that too...
created_at: 2025-04-18T05:45:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -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'
path: src/sync/incomingSyncUtils.js
user: login: anildahalsussol
body: Nice so we will not proceed if desired status is not received.
created_at: 2025-04-18T05:47:54Z
author_association: CONTRIBUTOR
diff_hunk: @@ -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';
path: src/sync/syncTranslators.js
user: login: anildahalsussol
body: Nice
created_at: 2025-04-18T05:48:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -286,6 +286,45 @@ const dataMigrations = [
       clearNumberSequences(database);
     },
   },
+  {
+    version: '8.7.0',
path: src/dataMigration.js
user: login: anildahalsussol
body: @raviSussol : I was thinking still WP is mysterious but we are known with another case of creating blank requisition. Is there a place where it can check blank so we dont need to make everytime migrate code?
created_at: 2025-04-18T05:54:54Z
author_association: CONTRIBUTOR
diff_hunk: @@ -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 },
path: src/database/DataTypes/Transaction.js
user: login: Chris-Petty
body: Bro got LLM'd? I can't find an `indexed` property in the realm docs and we've never set this anywhere else in the schema for this repo. That said, I'm surprised realm didn't throw a wobbly, either I haven't found the docs or realm is ignoring this?
created_at: 2025-07-01T22:50:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -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 },
path: src/database/DataTypes/Transaction.js
user: login: raviSussol
body: That's a real property of realm js schema. https://www.mongodb.com/docs/realm-sdks/js/latest/types/Realm.PropertySchema.html. Agree that it hadn't been used before (maybe cause in the lower version before Mongodb owned Realm)? Although I was searching using LLMs for field indexing in the realm (to make realm query quicker for processing huge requisitions like some of our clients have Fiji, Png, CIV, etc) I had literally looked around their official docs to make sure that its not an LLM hallucination until I found that docs.
created_at: 2025-07-02T00:49:31Z
author_association: COLLABORATOR
diff_hunk: @@ -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 },
path: src/database/DataTypes/Transaction.js
user: login: andreievg
body: > to make realm query quicker for processing huge requisitions like some of our clients have Fiji, Png, CIV, etc

Are we having performance issues on mobile ?
created_at: 2025-07-02T01:25:23Z
author_association: CONTRIBUTOR
diff_hunk: @@ -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 },
path: src/database/DataTypes/Transaction.js
user: login: Chris-Petty
body: Heh yea I think I wasn't going deep enough couldn't find it in here which is where my initial googling took me, https://www.mongodb.com/docs/atlas/device-sdks/sdk/react-native/. Well I did end up first on some ancient version of the type docs you found like v0.7... thought it looked odd, the OG realm docs were much cleaner than any incarnation that MongoDB has created since 🙄 especially when they're trying to stuff this new Atlas thing down people's throats but have since deprecated it lol.

That said just found it in the [proper docs](https://www.mongodb.com/docs/atlas/device-sdks/sdk/react-native/model-data/define-a-realm-object-model/#index-a-property)! Not sure how I missed it before, though even if you search for it you get results mostly for their PHP Library first haha
created_at: 2025-07-02T02:03:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -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 },
path: src/database/DataTypes/Transaction.js
user: login: raviSussol
body: > > to make realm query quicker for processing huge requisitions like some of our clients have Fiji, Png, CIV, etc
> 
> Are we having performance issues on mobile ?

I haven't caught that so far but I basically used `indexed` property as an idea of relational database here in this case since `pendingRequisitionId` is a mirror representation (or foreign field) of `Requisition.id` (unlike an entire record object linked to a field) which is a primary key and has `indexed` property true by default.
created_at: 2025-07-02T02:32:27Z
author_association: COLLABORATOR

PR comments:
user: login: AnushaUp
created_at: 2025-04-09T11:00:38Z
body: ## Testing
Tested in given APK
Steps to reproduce or otherwise test the changes of this PR:

- [x] Use the built [apk](https://store10.gofile.io/download/web/9a629ee8-ba0b-4221-8d8c-ced6e715564c/mSupplyMobile-8_7_0-rc1-universal-release.apk) and install on the tablet
- [x] Setup any mobile site of Fiji moh with mSupply central server (i.e. use Fiji moh datafile)
- [x] I used `Samabula_pharm` store's site
- [x] Initialize sync from mSupply to mobile
- [x] Login to the tablet and goto the supplier requisition and follow test 1

## Tests
- [x] Should not display blank or having serial number 0 requisition
- [x] Also check the customer requisition - should not have any blank or having serial number 0 requisition
- [ ] Please do regression tests related requisitions (both customer and supplier) 
  - [ ] Setup 2 mobile apps and 1 oms site (i.e 1 oms central server with 1 oms remote) and 1 mSupply central server and 1 mSupply remote desktop site
  - [ ] Try creating some invoices (i.e from internal order or supplier requisition or request requisition -> response requisition or customer requisition -> customer invoice or outbound shipment (then via stock transfer) -> supplier invoice or inbound shipment
  - [ ] Do thorough tests on these workflow among OG mobile, oms site, msupply sites and see if there anything gets broken - should be working flawlessly

author_association: NONE
user: login: anildahalsussol
created_at: 2025-04-18T08:13:28Z
body: As seen while testing wp status requisition seems valid requisition with status fn and also can see linked response requisition and related requisition lines. So not sure should we deleted or if its valid then improve it looking at the response requisition?
author_association: CONTRIBUTOR
user: login: ujwalSussol
created_at: 2025-04-23T13:00:52Z
body: update : was able to set up the Master mobile... 
Now tomorrow will aim to build mobile via this PR.

I am using Node V14.21.3  ( think this is the best that we can do for now )

author_association: CONTRIBUTOR
user: login: ujwalSussol
created_at: 2025-04-24T11:06:11Z
body: @raviSussol   :  The testing I have done, looks positive...

Now I think what we need is a big Group test from @santoshkhanal12   and @AnushaUp and perhaps a few one of of us. 
author_association: CONTRIBUTOR
user: login: raviSussol
created_at: 2025-04-25T04:35:17Z
body: > approved : But we do need to do a group test to make sure that daily activities are not messed up.

Yes that would be great to have other functional or regression tests before releasing the new version.
author_association: COLLABORATOR