Sync sales order SAP document numbers back to local orders#21
Merged
Conversation
A SAP sales order create can commit while the response read, the local save, or the short in-request reconciliation window fails. Every failure path then discarded the SAP linkage and reverted the order to Pending, so the order sat stale in the web app against a live SAP document with nothing to re-check it. SO-20260720-0015 hit this: posted as DocNum 78997, still showing Pending locally. Add SalesOrderReconciliationJob, a Quartz sweep on a 2 minute interval that links recent unlinked orders to SAP documents found by U_OrderNumber, reusing the existing duplicate-safe attach path. Scoped to a 7 day lookback and 25 orders per run. Stop the three request-path handlers from discarding a linkage that is already valid: the web auto-post catch, the approve rollback, and PostToSAPAsync, which kept a linked order Approved but still flagged a sync error and rethrew. Each now treats a linked order as a post that succeeded. Widen the in-request reconciliation from 5 linear attempts over ~7.5s to 6 attempts of capped exponential backoff (~25s), which was giving up while SAP was still making the document queryable. Kept short on purpose since it runs under the posting lock; the sweep absorbs anything slower. Give the posting advisory lock a 5s bounded retry so the sweep, which takes the same per-order lock, cannot surface to a user as "already being approved by another request". A genuine concurrent approve runs far longer than 5s and still reports unchanged; the sweep passes TimeSpan.Zero so it always yields to user requests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
The problem
A SAP sales order create can commit while the response read, the local save, or the short in-request reconciliation window fails. Every failure path then discarded the SAP linkage and reverted the order to Pending — so the order sat stale in the web app against a live SAP document, with nothing in the codebase that would ever re-check it.
SO-20260720-0015hit this: posted to SAP as DocNum 78997 (remarks confirm "Approved by Tatenda Chikaka on 20 Jul 2026 09:35"), still showing Pending with no document number locally. Recovery required a human to click Approve again — the pre-create duplicate check would then find and link it — but nothing prompted anyone to do that.What changed
New
SalesOrderReconciliationJob— Quartz sweep on a 2-minute interval that links recent unlinked orders to SAP documents found byU_OrderNumber, reusing the existing duplicate-safe attach path. Scoped to a 7-day lookback and 25 orders per run.Jobs/already had posting jobs for invoices, transfers and incoming payments; sales orders had no equivalent.Three request-path handlers no longer discard a valid linkage — the web auto-post catch, the approve rollback, and
PostToSAPAsync. The last had a subtler variant: its status revert was correctly guarded, but it then set a sync error and rethrew regardless, so a successfully-posted order could end up Approved-with-DocNum yet reported to the caller as a failure. Each now treats a linked order as a post that succeeded.Widened in-request reconciliation — from 5 linear attempts over ~7.5s to 6 attempts of capped exponential backoff (~25s). The old window gave up while SAP was still making the document queryable, which is the likely proximate cause for this 103-line order.
5s bounded retry on the posting advisory lock — the sweep takes the same per-order lock, so without this it could surface to a user as "already being approved by another request". That error message is unchanged byte-for-byte; it now fires only after the full 5s.
Reviewer notes
TimeSpan.Zeroso it always yields to user requests rather than queuing ahead of them.CancellationToken.None, so the delay is not interruptible by a client disconnect. Longer would risk client-side timeouts on an already-failing request. The 2-minute sweep absorbs anything slower.ApprovedByUserId. That information isn't recoverable.SO-20260720-0015is in that state.Verification after deploy
SO-20260720-0015should pick up DocNum 78997 within a few minutes of startup — the job logs at Information when it links anything, so grep the API logs for "linked". Expect the first few runs to be chattier against the Service Layer than steady state if there's a backlog of stale orders in the 7-day window.🤖 Generated with Claude Code