06 · Development · Transactions

Write the reject first, then the success

The backend engineer makes one completion-to-stock decide in the same second: post, write the ledger, pending write-back. Either they all stand, or none of them happened. He does not change stock in the browser, and does not insert into Kingdee directly.

Backend code on the screen
  1. 09:10 See the half-success. WIP was already deducted; the work order is still pending shop-floor reporting. Mark the data first. Do not overlay new code.
  2. 11:00 Close the transaction. WIP, finished-goods stock, and work-order state in one transaction. Any step fails, all roll back.
  3. 15:20 Close idempotency. Replay of the same request ID returns the first result and does not insert again.
  4. 17:40 Split write-back. Kingdee timeout retries only write-back, not local stock.

The backend engineer guards whether the rule can be run again

Product writes “over-plan must be blocked.” The backend engineer turns that into server behavior: an unconfirmed request returns a business error and does not change stock; the confirmation number writes in the same transaction; a duplicate submit does not add a second time. The job is not how many APIs. It is that success and failure can both be stated. Permission: only a shift lead can release over-plan. The log: the next day can show who reported this work order at what time. Idempotency: two taps post once. The night-shift over-receive fact is recorded by the business analyst. This role does not rewrite that night.

Boundary with the Frontend engineer: frontend shows the reject reason and does not add stock in the browser. Boundary with the Database engineer: the database engineer owns table shape, indexes, constraints, and backups. The backend engineer decides which tables this business writes, in what order, and what to roll back on failure. Boundary with the Integration engineer: the other side’s fields and direction are matched by integration. Locally, pending write-back must land before write-back. The screen cannot show complete first. Whether Kingdee gets two drafts is integration’s experiment. Backend only guarantees the local transaction is consistent first.

Reject conditions must be callable from tests

Every business reject has a stable error code, a business-readable reason, and a document number. A vague 500 leaves frontend able to show only failure. System fault and business reject must be separate. If a caller writes someone else’s workshop number into the request, it must be rejected and audited, not return an empty list pretending there are no work orders.

How completion-to-stock half-success is closed

The injection workshop reported a work order as complete. The rule: over-plan cannot enter available stock directly. The shift lead double-tapped. The page failed. Day shift found WIP short, finished goods a bit high, the work order still pending shop-floor reporting, and Kingdee had no document. Logs showed the first write already wrote the ledger, write-back timed out, and the transaction did not roll back as a whole. The second was blocked by a unique constraint, but returned a vague failure.

The fix on the server did three things. WIP deduction, finished-goods increase, and work-order state went into one transaction. A duplicate request ID returns the first result. Write-back became an independent queue. Local books go consistent first. Replay that work order: the first posts and leaves pending write-back; the second result does not change; the over-plan part still waits for confirmation and does not enter available qty. Whether the rule allows over-plan is not something backend loosens on its own. He must guarantee the system does not change the books while saying “not allowed.” Work-order number, request ID, workshop, and operator go into the reject log. A log with no document number is, for this role, no log.

If over-plan confirmation happens, the confirmation number must enter the same transaction as the original work order. Confirmation written and stock unchanged, or stock moved and confirmation not written, are both half-success. Permission is checked again on the server: writing someone else’s workshop number into the request must reject and leave an audit. It cannot return an empty list pretending there are no work orders. A vague 500 leaves frontend able to show only failure. Ops and the shift lead will treat both the same way. Separating business reject from system fault is the contract backend gives frontend. Whether Kingdee gets two drafts is still proven by integration with an idempotency key. This role only guarantees local WIP, finished goods, and work-order state stand together first.

Back to the timeline

A posting is half-successful now

Send the document that does not match stock.