OBPIH-7437 handle all items skipped during inventory import#5431
OBPIH-7437 handle all items skipped during inventory import#5431ewaterman merged 1 commit intorelease/0.9.5from
Conversation
| // TODO: Consider refactoring this logic to distinguish between products==null and products.?isEmpty(). | ||
| // The former should give the current behaviour (fetch ALL products) and the latter should return an | ||
| // empty list. Existing flows will need to be refactored to default to either passing null or [] | ||
| // depending on their desired behaviour. See OBPIH-7437. |
There was a problem hiding this comment.
As I said in the PR description, a more proper fix would be to change this query to distinguish between an empty list of products and a null list of products. However since we're so close to release I didn't want to break anything else in the system that uses this method so I opted to just put a TODO in for now and fixed it directly for inventory imports only.
| // in InventoryService.getTransactionEntriesBeforeDate is resolved, this will no longer be true.) | ||
| if (!inventoryImportData.products) { | ||
| return | ||
| } |
There was a problem hiding this comment.
I'm not sure if it handles all cases. As far as I'm concerned, we could have X items filled properly and leave only one item blank, and this would make every product to have quantities zeroed out.
If I read the code properly, you only handle a case when you have all items empty.
There was a problem hiding this comment.
Can you say more about why you feel that way?
Any rows/items that are left blank are not included in inventoryImportData.products:
private InventoryImportData parseData(ImportDataCommand command) {
InventoryImportData inventoryImportData = new InventoryImportData()
for (def row in command.data) {
// We've already warned the user during the validation step about any rows with a null QoH, so if there
// are any that are still null at this point, simply ignore them.
if (row.quantity == null) {
continue
}
...
If all rows are empty we get into the situation fixed by this ticket, but if only some of the items are empty and others set a quantity, then inventoryImportData.products will not be empty, and the if (products) condition in InventoryService.getTransactionEntriesBeforeDate will be true, and so it will fetch only the transaction entries for the given products.
List<TransactionEntry> getTransactionEntriesBeforeDate(Location facility, Collection<Product> products, Date date) {
def criteria = TransactionEntry.createCriteria()
return criteria.list {
if (products) {
inventoryItem {
'in'("product", products)
}
}
transaction {
...
}
} as List<TransactionEntry>
}
We use the result of this query to build ProductAvailability records (it does a call to inventoryService.getQuantityAsAvailableItems(transactionEntries)).
We then later only zero out any items whose products were in the import but didn't have a row for their specific item (can happen if a product is in multiple bins/lots and we only import one of those bins/lots):
// For all products in the import, any other bins/lots of those products that exist in the system (ie have
// a product availability entry) but were not in the import should have their quantity set to zero.
Set<String> keysInImport = inventoryImportData.rows.keySet()
for (entry in availableItems) {
AvailableItem availableItem = entry.value
if (keysInImport.contains(entry.key)) {
continue
}
TransactionEntry transactionEntry = new TransactionEntry(
transaction: transaction,
quantity: -availableItem.quantityOnHand,
product: availableItem.inventoryItem.product,
binLocation: availableItem.binLocation,
inventoryItem: availableItem.inventoryItem,
comments: 'Item was not in inventory import file so quantity was assumed to be zero.',
)
transaction.addToTransactionEntries(transactionEntry)
}
Remember that in the above code, availableItems only contains data for the products that were imported, not ALL availableItems.
Maybe you're seeing something that I'm not, but I recorded a video demonstrating the behaviour: Screencast from 2025-08-06 08:29:14 AM.webm
There was a problem hiding this comment.
Ok, I trust you. I just remember I ran into that edge case when I had a few lines filled properly and probably one line not filled.
There was a problem hiding this comment.
hmm I tried again to reproduce it a few different ways with some lines filled out and others not but it always worked correctly after this fix. I'll merge the change in as is but we can keep an eye on it. Thanks for the review
✨ Description of Change
Link to GitHub issue or Jira ticket: https://pihemr.atlassian.net/browse/OBPIH-7437
Description: If an import has no products/items or all the items are skipped due to no quantity being defined, ALL products for the facility were getting zeroed out. This was due to how a query in InventoryService was working (if the given list of products is falsey, fetch ALL transactions).
A more proper fix would be to change the query to distinguish between an empty list of products and a null list of products, but that refactor would have potential knock on effects across users of that query so I opted for the safest option for now since we're so close to release.
📷 Screenshots & Recordings (optional)
Video describing issue: https://jam.dev/c/732d4448-6805-4bbc-9c8f-ef2314d2965c