The whitelisted endpoint declared trans_items as str, so Frappe's typing
validation raised FrappeTypeError when the client sent the items as a
JSON list. ChildItemUpdater.update already handles both via
frappe.parse_json, so widen the wrapper's hint to str | list.
use frappe.get_list instead of frappe.get_all in get_dashboard_info so
the company list honors user permissions. previously, a party with
invoices across multiple companies would raise "User don't have
permissions to select/read this account" for users restricted to a
subset of companies, since get_party_account was called for companies
the user could not access.
fixesfrappe/erpnext#57428
Address review findings:
- send_proforma_email rejects non-issued proformas, and the tab suppresses the
action for cancelled rows, so a voided document can't be sent to a customer
- mark proforma_pdf as no_copy and disable amendment (a proforma is created
only from a Sales Order), so a copied proforma can't carry the original's PDF
and number
Address review findings:
- make_proforma_invoice: reject a non-submitted Sales Order (the whitelisted
endpoint was previously only JS-gated on docstatus)
- send_proforma_email: throw a clear error when the attached PDF File is missing
instead of passing a null fid to sendmail
sort on (expiry is none, expiry) so a null expiry_date is never
order-compared against a datetime.date, which raised typeerror in
python 3 when a warehouse held both dated and never-expiring batches.
warehouse_name is a Data field shown as stored, and everywhere else
users see the docname, which carries the company abbr ("Stores - F")
and is never translated - a translated bare "Stores" has no display
use, so the identity _ marking from #57392 serves nothing. The
exists-guard keeps the runtime session-translation match that protects
legacy sites from duplicate English warehouses.
A batch is one valuation pool, so consumption is valued at the pooled
rate while slots may carry stale intra-batch detail (e.g. units
reconciled at zero and later merged). Consuming such a slot leaves a
negative value on positive qty. Spread the pool value across the
batch's slots when that happens; non-batchwise slots pool per
warehouse.
* fix: shift same-timestamp sibling SLEs when cancelling an entry
update_qty_in_future_sle compared against the reversal SLE's own
creation and skipped same-posting_datetime siblings on cancel, leaving
their qty_after_transaction stale and causing false negative stock
errors.
* fix: revert update_qty_in_future_sle cancel tie-break, it double-counted
Company.create_default_warehouses stored warehouse_name through the
session _(), so a site set up in a non-English language keeps its
default warehouses under translated names. The opening-stock fallback
in item.py then looks up {"warehouse_name": _("Stores")} from an
arbitrary session and misses the warehouse whenever the lookup
session's language differs from the creation session's.
Create the default warehouses with canonical English names, matching
the identity-_ convention install_fixtures uses for other default
records. The exists-guard also matches the session translation so a
re-run on a legacy site does not insert English duplicates next to
translated warehouses.
The "Stores" fallback lookup moves to get_stores_warehouse, which
tries the canonical name first and falls back to the session
translation so legacy sites keep resolving their translated warehouse.
The setup-wizard and test-bootstrap lookups drop _() since they now
run after English creation (install_fixtures already used identity _,
so its lookup silently missed translated warehouses before this
change).
Same bug class as #57345.
A name lookup misses roots created under a translated name (pre-#49875
setups) or renamed roots. Resolve the first parentless group by lft and
guard against self-parenting when the root itself is saved.
Native JSON request bodies deliver target_doc as a parsed dict, which the
str | Document type hints rejected, breaking every Get Items From button.
Unify all whitelisted mapper endpoint hints to str | dict | Document | None.
Needs frappe#41190 so get_mapped_doc converts the dict target.
_("All Item Groups") resolves in the session language, so for
non-English users the db.exists lookup missed the root (stored in
English) and new groups were saved parentless, becoming uneditable
second roots.
Closes#57345
Company.create_default_departments named and looked up the root
Department via _("All Departments"), which resolves in the session
language. A site set up in a non-English language stores the root
translated, and a company created later from a session in another
language misses it and inserts a second root, corrupting the tree.
Resolve the root once with get_root_of (falling back to the canonical
English name on fresh installs) and reuse it for the root record, the
exists-guard and the child departments' parent.
Also stop translating lookups of records install_fixtures stores under
English names: Price List "Standard Selling" and Print Headings
"Credit Note" / "Debit Note".
Same class as the root Item Group fix (#57386, issue #57345).