TJK: Restore stock alert emails broken since upstream PR #2018 (OBPIH-3280)#6
Open
gqcorneby wants to merge 3 commits into
Open
TJK: Restore stock alert emails broken since upstream PR #2018 (OBPIH-3280)#6gqcorneby wants to merge 3 commits into
gqcorneby wants to merge 3 commits into
Conversation
Restores Phase 2 of OBPIH-3280. PR openboxes#2018 replaced inventory_snapshot with product_availability as the live qty source but deleted RefreshInventorySnapshotAfterTransactionJob with an explicit deferred follow-up "need to ETL product availability records to inventory snapshot" — never delivered, leaving stock-alert reports empty for 5+ years. This service listens to RefreshProductAvailabilityEvent (already fires on every Transaction.afterInsert), synchronously refreshes product_availability for the affected products, and copies the rows into inventory_snapshot with date = current_date + 1 — the exact shape the stock-alert compare view expects. INSERT column list and ON DUPLICATE KEY UPDATE behavior match the pre-2020 generateInsertInventorySnapshotStatement; data source is the new event-driven product_availability table, finishing the architectural pivot OBPIH-3280 started. Preserves activity-gated alerting: snapshot rows only appear when transactions happen, so the view's BETWEEN current_date AND current_date + 1 filter still acts as the no-spam gate. Gated by openboxes.jobs.refreshInventorySnapshotAfterTransactionJob.enabled (truthy-check matching the deleted job's pattern). Upstream application.yml still ships this key at true, so default behavior is on. Refs: openboxes#4742, openboxes#2018
Defensive override so the stock-alert ETL keeps running on TJK even if upstream eventually removes the orphan openboxes.jobs.refreshInventorySnapshotAfterTransactionJob.enabled default from application.yml during a future housekeeping pass. The key is read by our InventorySnapshotEtlService (custom code) but the deployment-side override here is what guarantees we don't depend on upstream's default staying around.
- defer ETL to afterCommit so transaction_entry rows are visible before product_availability is recomputed - use forceRefresh=true to purge stale pa rows before reinserting - replace ON DUPLICATE KEY UPDATE with DELETE+INSERT to remove stale (lot, bin) combinations from the snapshot
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
📌 References
🐛 Bug
Stock alert emails (low-stock, out-of-stock, overstock) have been broken upstream since November 2020. Expiry alerts were unaffected.
Upstream PR openboxes#2018 (OBPIH-3280) refactored how live quantity-on-hand is tracked — moving it from
transaction_entryaggregations into theproduct_availabilitytable. That part works correctly (stock cards show accurate QOH). However, the same PR deletedRefreshInventorySnapshotAfterTransactionJob, the job responsible for writing rows intoinventory_snapshot, without delivering the stated Phase 2 follow-up: "need to ETL product availability records to inventory snapshot."The stock-alert view chain (
product_inventory_snapshot_view→product_inventory_extended_view→product_inventory_pivot_view→product_inventory_compare_view) reads exclusively frominventory_snapshot. With nothing writing to it after transactions, the snapshot stays stale and theSendStockAlertsJobfinds nothing to alert on. Upstream issue openboxes#4742 tracks the symptom since July 2024 — open, no comments, no linked PR.📝 Implementation
InventorySnapshotEtlServiceunderorg.pih.warehouse.custom.stockAlertRestore— finishing Phase 2 as custom code rather than rolling back upstream's pivot.product_availabilityremains the live source of truth;inventory_snapshotbecomes a derived projection of it.How it works:
RefreshProductAvailabilityEvent(fired byTransaction.afterInsert/afterUpdate) — same trigger the deleted job usedTransactionSynchronizationManager.afterCommit()sotransaction_entryrows are visible beforeproduct_availabilityis recomputed (running synchronously inside the still-open transaction would race the insert and read stale state)productAvailabilityService.refreshProductsAvailabilitywithforceRefresh=trueto purge stale lot/bin rows before reinsertingcurrent_date + 1, matching whatproduct_inventory_snapshot_viewexpects forcurrent_quantityopenboxes.jobs.refreshInventorySnapshotAfterTransactionJob.enabled(reuses the config key from the deleted job, alreadytrueinapplication.yml)Activity gating is preserved by design: alerts only fire on days with transactions, matching the original intent and avoiding daily-email spam for unchanged stock levels.
✨ Description of Change
A single new service in the
custom/stockAlertRestorepackage. No upstream files modified.🔥 Notes to the tester
SendStockAlertsJobvia Admin > Quartz > Jobs