erpnext.accounts.dashboard_fixtures and erpnext.buying.dashboard_fixtures
were removed in 2020 when dashboards were exported to JSON fixtures.
The assets module's dashboard_fixtures.py was left behind unreferenced;
its dashboard, charts and number cards already exist as exported JSON.
StockReservation.transfer_reservation_entries_to() created the transferred SREs without copying stock_uom, in both the entries_to_reserve dict and the extra-items fallback. get_items_to_reserve() already selects the item's stock_uom, so entry.stock_uom is used.
On sites with a global default stock_uom (e.g. "Nos"), frappe's _set_defaults() backfilled the blank field, so the transfer silently stored the wrong UOM for any item whose stock UOM is not the default. On sites without that default the SRE's validate_mandatory() raised "Stock UOM is required", aborting Work Order submission for the Subcontracting Inward Order / Production Plan flows.
(cherry picked from commit 5991ecfa3d)
make_all_scorecards' dedup query used strict bounds, so a single-day
period (supplier created on a month's last day -> start == end under
"Per Month") never matched its own window and was re-created on every
call. The daily refresh_scorecards job would insert a duplicate
submitted period each day for such suppliers, and
test_make_all_scorecards_is_idempotent fails on any date where
nowdate() - 75 days lands on a month end — both nightly server suites
went red on 2026-07-14 (75 days after April 30).
Inclusive bounds cannot false-match adjacent periods: each next period
starts at end_date + 1, so closed intervals never touch.
covers sales order, quotation, sales invoice, delivery note and
purchase order, asserting actual_qty from the row warehouse and
company_total_stock across all warehouses of the company.
company was passed to get_bin_details only for purchase order, so
company_total_stock was never returned for sales order, quotation,
sales invoice and delivery note and the qty (company) column always
read zero. pass ctx.company for every doctype, which also drops the
dependency on doc being supplied.
on the client, set_actual_qty copied only actual_qty out of the
response, so qty (company) never refreshed on a warehouse change. use
frm.call with child so every bin field is applied, pass
include_child_warehouses to match the server, and include quotation.
- allow new rows on scan when pick manually is enabled, since only
then are scanned rows not subject to being overridden by
set_item_locations on save
- stop capping picked qty at the default demand qty (1) for rows
added by the scanner itself, so repeat scans of the same barcode
keep incrementing the row instead of failing with "maximum
quantity scanned"
- ignore barcode uom when matching an existing row if new rows
aren't allowed, since there's no alternate-uom row to fall back to
Seeding a current-dated USD->INR rate makes get_exchange_rate resolve
62.9 on today() instead of hitting the live API, which exposed three
tests that implicitly relied on a different/undefined current rate:
- customer: dropped its own colliding current-dated seed (ignored via
ignore_if_duplicate, and its cleanup deleted the shared seed) and now
asserts the quotation resolves the seeded rate via get_exchange_rate.
- exchange_rate_revaluation: the revalued rate (62.9) is now below the
booked 80, so the revaluation is a loss (debited) rather than a gain;
derive the gain/loss column from the sign instead of assuming a gain.
- purchase_invoice: the receipt rate was an accidental tuple (70,) that
got discarded and recomputed to the seed; set explicit rates with the
receipt above the invoice so the stock exchange difference is a credit,
matching the asserted column.