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.
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.
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.
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.
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.
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.
* 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>
* fix: use current batch avg rate for outward returns of batchwise valuation batches
* fix: honor zero batch average and avoid duplicate batch classification query
set_dynamic_labels() unconditionally forced update_stock's hidden
property based only on is_debit_note/has_subcontracted, overwriting
whatever Customize Form had set on every refresh. OR it with the
field's original (property-setter-driven) hidden value instead.
* feat: validate stock value and stock closing entry before period closing
* fix: do not accept scoped stock closing entries as period closing prerequisite
* feat: seed batch valuation from stock closing balance and freeze closed-period stock