fix(manufacturing): chain Job Card qty defaults to upstream completed output
Problem
In a multi-operation Work Order, once an earlier operation completes with less than the Work Order qty (partial completion and/or process loss), both the Create Job Card dialog and the Complete Job Card dialog on a downstream operation still suggest the full Work Order qty as the quantity to manufacture — not what upstream actually produced.
Job Card.validate_sequence_id() already rejects completing more than a previous operation's completed_qty on submit, so the UI is offering a number it's about to reject.
Fixes #56934
Related reports
Independently reported by other users hitting the same wall:
- #54955 — same partial-completion sequencing pain point (comment from @venkatamandavilli-code: "one of the more frustrating limitations in ERPNext manufacturing... Some ERP systems solve this with an 'overlap' setting at the routing level")
- #57123 — same issue in a batch-size/food-manufacturing context (cooking → filling → sterilization)
Root cause
get_max_completable_qty() already computes the correct ceiling (previous operations' completed/manufactured qty minus what this operation has done so far) and is set on load (job_card.py), but nothing in the client actually reads it — job_card.js's Complete Job Card dialog derives its default purely from for_quantity - total_completed_qty, and work_order.js's Create Job Card dialog derives it from frm.doc.qty - completed_qty - process_loss_qty on the operation row itself, with no reference to earlier operations in the sequence at all.
Fix
- job_card.js's complete_job_card(): cap the "Qty to Manufacture in this Cycle" default at doc.__onload.max_completable_qty.
- work_order.js's make_job_card(): for a not-yet-created Job Card, cap the offered qty at the minimum completed_qty among operations with a lower sequence_id, minus this operation's own completed_qty — mirroring the same math client-side, since this dialog is populated entirely from frm.doc.operations without a server round trip.
Both are minimal, additive caps on an existing suggested value — no change to for_quantity persistence, validation, or the underlying sequence-checking logic.
Test plan
- Traced the exact repro steps from #56934 against the fixed code path — the second Job Card's dialog now offers the correct capped qty, matching get_max_completable_qty().
- pre-commit (prettier, eslint) clean on both changed files.
@mihir-kandoi can you please create a pr.
Source: frappe/erpnext