60892 Commits

Author SHA1 Message Date
Mihir Kandoi
0aec62a8dd test: raw material dialog adds a row for its operation despite duplicates 2026-08-08 17:29:59 +05:30
Mihir Kandoi
24f1f3dea8 fix: add raw material to its operation even when another operation uses the item
get_item_details returns the whole Item document, so the dialog row's
name became the item code. get_item_data then matched that item code
against every Components row regardless of operation, so adding an item
already used by another operation silently updated that row's qty
instead of appending one for the target operation — which stayed empty
and failed 'please add raw materials or set a BOM' on submit.

Match the existing row by item code within the same operation: same
operation updates the qty, any other match appends a new row.
2026-08-08 17:29:59 +05:30
Mihir Kandoi
5e0f056284 test: manufacture entry keeps process loss scoped to its own operation 2026-08-08 17:29:59 +05:30
Mihir Kandoi
1b335973b7 fix: scope manufacture entry process loss to its own job card
set_process_loss_qty stamped MAX(process_loss_qty) across every
operation of the work order onto each manufacture entry. With semi
finished goods tracking, one operation's process loss leaked into the
entries of every other operation: validate_fg_completed_qty then
rejected the entry when it had a BOM, or the wrong loss was recorded
silently when it did not, double-counting the loss across operations.

When the entry belongs to a job card, use that job card's loss net of
what its earlier entries already booked. The MAX fallback stays for
work-order level entries without a job card.

Fixes frappe/erpnext#57892
2026-08-08 17:29:59 +05:30
Mihir Kandoi
335dbdaca4 test: previous operation shortfall from process loss gets the right message 2026-08-08 17:29:59 +05:30
Mihir Kandoi
1e22695eae fix: stop asking for a manufacturing entry when process loss explains the shortfall
When a previous operation manufactured less than the current job card
is completing, the error always said 'Submit the manufacturing entry
for the operation first' — even when the entry was already submitted
and the missing quantity was booked as process loss, which made the
advice a dead end.

Sum the process loss of the previous operation's job cards alongside
the manufactured quantity. When manufactured + process loss covers the
requested quantity, say the shortfall is process loss so the user
knows to reduce the completed quantity; keep the submit-first message
for genuinely pending manufacturing entries.
2026-08-08 17:29:59 +05:30
Mihir Kandoi
f61f6523b9 test: WIP warehouse required for work orders tracking semi finished goods 2026-08-08 17:29:59 +05:30
Mihir Kandoi
198eb60df7 fix: require WIP warehouse for work orders tracking semi finished goods
Work orders with track_semi_finished_goods were exempt from the
Work-in-Progress Warehouse requirement in three places: the field's
mandatory_depends_on, the fg_warehouse reqd toggle in the form script,
and validate_warehouse on submit.

The exemption was misleading. The flow still transfers materials to a
WIP warehouse when 'Skip Material Transfer' is unchecked: operations
default their WIP warehouse from the work order, and
set_default_warehouse silently restores the company default after the
user clears the field. Make the field genuinely required instead of
pretending it is optional.
2026-08-08 17:29:59 +05:30
Mihir Kandoi
4b3904c6d7 test: semi FG job card is exempt from the legacy transfer qty check 2026-08-08 17:29:59 +05:30
Mihir Kandoi
6c8f0b9b56 fix: don't demand raw material transfer for semi FG job cards on submit
validate_transfer_qty uses an empty finished_good to detect legacy job
cards, and unlike validate_semi_finished_goods it ignores
skip_material_transfer. A job card tracking semi finished goods whose
operation had no finished_good fell into the legacy branch and could
not be submitted even with 'Skip Material Transfer' checked on the
work order.

Return early for semi FG job cards; validate_semi_finished_goods
already enforces the transfer requirement for them and honours
skip_material_transfer.
2026-08-08 17:29:59 +05:30
Mihir Kandoi
aed7c70b1c test: BOM tracking semi finished goods rejects operations without FG item 2026-08-08 17:29:59 +05:30
Mihir Kandoi
3497a6a6bf fix: require FG / Semi FG Item on operations when tracking semi finished goods
A BOM with track_semi_finished_goods enabled could be saved with no
finished_good on any operation: validate_semi_finished_goods only
checked that one row had 'Is Final Finished Good' set, and a list
containing None passed the emptiness check.

Such a BOM breaks every downstream step. The work order copies the
empty finished_good into its operations, job cards inherit it, and
Make Stock Entry finally fails with 'Item None not found' because the
manufacture entry has no production item.

Derive the finished good where it is unambiguous: an operation that
references a BOM produces that BOM's item, and the final operation
produces the BOM's own item. Otherwise require it on the row, since
each operation's job card books its output through it.
2026-08-08 17:29:59 +05:30
Mihir Kandoi
11a902eb5f Merge pull request #57887 from mihir-kandoi/fix-repost-ma-return-sibling-rate
fix: repost read stale sibling SLE rate for moving average returns
2026-08-08 12:02:24 +05:30
Mihir Kandoi
b3f97cd389 fix: incorrect entry detection in Stock Ledger Invariant Check (#57886) 2026-08-08 05:31:21 +00:00
Mihir Kandoi
97d41867b5 fix: zero-rate repost fallback could still read sibling SLE
When the in-memory running rate is zero, the fallback went through
get_incoming_rate, whose previous-SLE lookup matches the same
posting_datetime and can land on a sibling line of the voucher being
replayed. Replace it with get_previous_sle_of_current_voucher excluding
the current voucher, keeping the get_valuation_rate chain when no
previous entry exists. get_incoming_rate is no longer used in this
module.
2026-08-08 11:00:47 +05:30
Mihir Kandoi
1a47c61b67 test: repost of multi-line moving average return is idempotent
Reposting a return that removes most of the stock across several lines
of the same item must keep every line at the running average and produce
identical results on a second repost. Before the fix the first repost
already drifted, seeding each line from a sibling row of the same
voucher.
2026-08-08 10:53:04 +05:30
Mihir Kandoi
b589a4d335 fix: repost read stale sibling SLE rate for moving average returns
During repost, a return line with recalculate_rate resolved its moving
average rate through get_incoming_rate -> get_previous_sle, which matches
posting_datetime <= and orders by creation desc. For a multi-line return
of the same item, every line shares one posting_datetime, so the query
landed on a sibling line of the same voucher whose stored valuation_rate
was still the previous repost run's output, not the rate before the
voucher.

Each repost run therefore re-seeded the voucher from its own prior
output. The error gain per run is (qty returned at the stale rate) /
(qty remaining after the return), so whenever a return removes most of
the stock the loop diverges instead of converging, alternating sign and
growing until stock_value overflows decimal(21,9) and the repost dies
with 'Out of range value for column stock_value'.

Use the in-memory running valuation rate that update_entries_after
already tracks for the warehouse at this point in the repost. It is the
authoritative pre-entry state, is immune to sibling rows, and makes the
repost idempotent. The database lookup is kept only as a fallback for a
zero in-memory rate, preserving the existing zero-rate fallback chain.
2026-08-08 10:51:13 +05:30
Pandiyan P
55fe269046 fix: allow selecting a warehouse for new items in the update items dialog (#57876) 2026-08-07 17:32:29 +00:00
Mihir Kandoi
5822cef1d9 feat(manufacturing): prompt for qty when creating material request from work order (#57855) 2026-08-07 17:25:51 +00:00
Mihir Kandoi
5e372df533 Merge pull request #57883 from mihir-kandoi/fix-pp-min-order-qty-round-up
fix: order smallest purchase UOM qty that meets min order qty
2026-08-07 22:49:55 +05:30
Mihir Kandoi
1ca06024cb test: marginal min order qty overage raises a toast 2026-08-07 22:36:02 +05:30
Mihir Kandoi
1aa6f8d1a7 feat: warn when ordered qty exceeds min order qty only by UOM rounding
A minimum order qty defined in stock UOM often has no exact
representation in the purchase UOM, so the smallest valid order slightly
exceeds the minimum. Surface that overage on the Purchase Order with a
toast on first save when an item's ordered stock qty is above its
minimum by less than one purchase-UOM step, so the buyer sees the
marginal increase before sending the order. Sub-precision dust stays
silent.
2026-08-07 22:36:02 +05:30
Mihir Kandoi
1b2090820a Merge pull request #57873 from mihir-kandoi/fix-conversion-factor-precision
fix: declare precision 9 on all conversion_factor fields
2026-08-07 22:20:57 +05:30
Mihir Kandoi
e4b66dc731 test: min order qty conversion takes the grid ceiling
Covers both rounding brackets, an exactly representable conversion, the
no-minimum path, and the ceiling through the plan items and materials
from other locations flows.
2026-08-07 22:20:38 +05:30
Mihir Kandoi
ee8eb18daf fix: order smallest purchase UOM qty that meets min order qty
A Production Plan with Consider Minimum Order Qty raises the requirement
to the item's minimum in stock UOM, then converts it to the purchase UOM
with round-to-nearest. Nearest rounding can land below the minimum it
just applied: min order qty 50000 with purchase UOM conversion factor
453.592292197 becomes 110.231, which is 49999.932 in stock UOM, and the
mapped Purchase Order is then rejected by validate_minimum_order_qty.

When the minimum binds and the nearest-rounded value dips below it,
quantize to the smallest representable purchase-UOM quantity whose stock
equivalent meets the minimum, using Decimal grid-ceiling arithmetic.
110.232 converts to 50000.386: demand stays as planned and the overage
is order-unit granularity, the standard MRP lot-sizing outcome. Ordinary
conversions keep the historical round-to-nearest behavior.
2026-08-07 22:20:30 +05:30
Mihir Kandoi
594ff24dae Merge pull request #57879 from mihir-kandoi/remove-dead-mr-po-mapper
refactor: remove unused make_purchase_order_based_on_supplier
2026-08-07 21:03:07 +05:30
Shllokkk
67f4b7a483 Merge pull request #57880 from Shllokkk/guard-clear-reconciliation-patch
fix: guard reconciliation table deletes when tables are missing
2026-08-07 20:03:19 +05:30
Shllokkk
8a2b2a2b68 fix: guard reconciliation table deletes when tables are missing 2026-08-07 19:33:45 +05:30
Mihir Kandoi
8b2946ca6b refactor: remove unused make_purchase_order_based_on_supplier
Its only caller, Purchase Order's get_items_from_open_material_requests,
was deleted in 91e9867fb1 (refactor: Cleanup buying module forms). The
old dotted path was already broken by the move to mapper.py, so no
external caller can be using it either.
2026-08-07 18:42:00 +05:30
Mihir Kandoi
ca5a673409 fix: round computed conversion factors to field precision
The inverse (1 / value) and intermediate-UOM branches of
get_uom_conv_factor returned raw float quotients like
0.4535922921968971, bypassing the precision the docfields now declare.
Same for the client-side back-calculation from an edited stock qty.
Round both to the UOM Conversion Factor value precision.
2026-08-07 17:47:50 +05:30
Mihir Kandoi
69a35a12cb fix: declare precision 9 on all conversion_factor fields
The Float control parses values with the field precision, falling back
to the global float precision when the docfield declares none
(frappe ControlFloat.parse / get_precision). On a site with float
precision 2, a fetched UOM factor of 0.453592292 was written back to
the model as 0.45, silently corrupting every derived quantity by 0.8
percent. A ratio must not inherit display precision meant for
quantities, so declare the same precision 9 the UOM Conversion Factor
master already uses on every transaction-level conversion_factor
field.
2026-08-07 17:31:32 +05:30
Mihir Kandoi
b3300c20a3 Merge pull request #57866 from krishna-254/fix/product-bundle-item-search
fix: optimize product bundle item search
2026-08-07 16:02:51 +05:30
Mihir Kandoi
4e9b069c20 Merge pull request #57861 from mihir-kandoi/fix-uom-integer-check-dust
fix: UOM whole number check truncated instead of rounding
2026-08-07 14:03:26 +05:30
Mihir Kandoi
e6a6458ebe test: UOM whole number check tolerates conversion dust 2026-08-07 13:49:00 +05:30
Mihir Kandoi
a464a6e4a1 fix: UOM whole number check truncated instead of rounding
cint truncates, so a stock_qty of 1999.9998 (dust from qty times
conversion factor) compared as abs(1999 - 2000.0) > epsilon and was
rejected as fractional even though it rounds to a whole number at
field precision, with the error confusingly printing the rounded
value: 'Quantity (2000.0) cannot be a fraction'. Round to field
precision first, then require the result to be a whole number.
Dust above an integer already passed; this fixes the asymmetry for
dust below.
2026-08-07 13:48:38 +05:30
Mihir Kandoi
a219f890df Merge pull request #57859 from mihir-kandoi/fix-po-min-order-qty-precision
fix: compare ordered qty to min order qty at stock_qty precision
2026-08-07 13:46:55 +05:30
Krishna Shirsath
b3867f1428 fix: optimize product bundle item search 2026-08-07 13:44:57 +05:30
Mihir Kandoi
c652f47931 test: min order qty check tolerates UOM conversion dust 2026-08-07 12:51:40 +05:30
Nishka Gosalia
d9e048ece7 Merge pull request #57845 from nishkagosalia/settings-mapping-cleanup
chore: restructure exported files of doctype settings
2026-08-07 12:46:43 +05:30
Mihir Kandoi
98b7407949 fix: compare ordered qty to min order qty at stock_qty precision
stock_qty is stored as raw qty * conversion_factor, so a UOM-converted
order for exactly the minimum (e.g. LB to Kg) produces values like
1999.999999131832 vs a min_order_qty of 2000 and blocks the Purchase
Order. Round both sides to the stock_qty field precision before
comparing, and show the rounded qty in the error message.
2026-08-07 12:44:28 +05:30
Mihir Kandoi
3f8b263014 Merge pull request #57854 from mihir-kandoi/fix/work-order-create-button-group
fix(UX): group work order actions under the Create menu
2026-08-07 04:22:33 +05:30
MochaMind
523d0e4312 fix: sync translations from crowdin (#57842) 2026-08-06 20:03:30 +02:00
Mihir Kandoi
780ab3ba3e fix(UX): group work order actions under the Create menu
Pick List, Material Request, Material Consumption and Additional
Material Transfer were spread across two standalone buttons and a
separate Make menu. Put them all under a single Create menu, and rename
Create Pick List to Pick List since the menu already says Create.
custom_make_buttons is updated to the new label so the connections
shortcut still finds the button.
2026-08-06 23:02:05 +05:30
Mihir Kandoi
e1815cb5a9 Merge pull request #57851 from mihir-kandoi/fix-production-plan-mr-qty-precision
fix: round Production Plan mr_items quantity to field precision
2026-08-06 21:11:10 +05:30
Mihir Kandoi
75145cc72c test: remaining purchase qty is rounded to field precision
Covers the _add_remaining_purchase_request path: partial stock in
another warehouse is allocated as a transfer and the residual purchase
qty goes through the second rounding site.
2026-08-06 20:59:04 +05:30
Mihir Kandoi
f5157bf3c4 test: mr_items quantity is rounded to field precision 2026-08-06 20:49:42 +05:30
Mihir Kandoi
ffc515f046 fix: round production plan mr_items quantity to field precision
The stock-UOM qty is rounded in _accumulate_so_items, but the purchase
UOM conversion divided it by the conversion factor without re-rounding,
storing values like 5738748.300863984 in mr_items.quantity. The raw
value flowed into Material Request qty and the raw materials CSV, and
make_material_request compares quantity to requested_qty with exact
float equality, so any rounding downstream left dust quantities.
2026-08-06 20:48:42 +05:30
Mihir Kandoi
44260b469f refactor: remove unreachable UOM conversion in production plan
The division by conversion_factor in _adjust_required_qty_for_uom sits
directly after frappe.throw inside the same block, so it can never run.
It has been dead since commit 2a8cd05b44 (#27278) re-indented it into
the throw branch; the actual purchase-UOM conversion happens in
_material_request_item_row via _mr_purchase_conversion_factor.
2026-08-06 20:48:19 +05:30
Jatin3128
96a6db7387 feat(accounts): split exchange gain and exchange loss accounts (#57839)
* feat(accounts): split exchange gain and exchange loss accounts

Add optional Exchange Gain Account and Exchange Loss Account fields on
Company. When set, realized FX gain/loss from settling an invoice in a
foreign currency (via Payment Entry, Payment Reconciliation, or a
Journal-Entry-based advance) books to the matching account instead of
the single Exchange Gain/Loss account. Either field left blank falls
back to the existing Exchange Gain/Loss account, so companies that
don't configure the new fields are unaffected.

New companies get "Exchange Gain" and "Exchange Loss" accounts
auto-created in their chart of accounts and auto-assigned to the new
fields, same as the existing Exchange Gain/Loss account provisioning.

The Payment Reconciliation tool's per-allocation "Difference Account"
override in its reconcile dialog continues to work as before; the
split accounts only change the computed default shown there.

* test(account_balance): account for new Exchange Gain account in income report

The new auto-provisioned Exchange Gain account under Indirect Income
now shows up in the Income root type report for _Test Company 2.

---------

Co-authored-by: test <test@test.com>
2026-08-06 17:36:43 +05:30
Suhas Bharadwaj
e0b9351d49 fix: condition check with empty object for falsy case 2026-08-06 16:38:46 +05:30