Subcontracting Receipt was left out of #57493. Its title_field is "title",
so the template does get rendered on insert, but never again — the title
goes stale as soon as the supplier changes.
Point title_field at supplier_name like Purchase Receipt, and give the
title field the same shape as its subcontracting siblings. Existing rows
already hold a rendered name, so no data patch is needed.
Also guard the whole class of bug: a "{...}" default on a title field is
only ever rendered when title_field is "title".
subcontracting order and subcontracting inward order carry a hidden
title field defaulting to "{supplier_name}" / "{customer_name}", while
their title_field points at supplier_name / customer_name. document.
set_title_field() substitutes the template only when title_field is
"title", so every record stores the placeholder verbatim.
drop the dead default and hidden flags, move title into the other info
tab to match purchase order, and add a patch to repair existing rows.
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.
* feat: inline serial and batch entries editor in Purchase Receipt
* feat: grid-style UX, deferred saves, scan and range options for inline serial batch editor
* feat: extend inline serial batch editor to all bundle doctypes with auto fetch
* fix: address review comments on inline serial batch editor
* fix: escape untrusted values in inline editor alerts
* fix: clear child bundle reference only when the row owns the bundle
* fix: keep inline serial batch editor disabled on existing sites via patch
Add methods=["POST"] to 50 whitelisted functions that create or modify
documents (get_doc followed by insert/save/submit), so they can no
longer be invoked via GET requests.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Same submit()/add_comment-in-except shape as the PO->SCO mapper: on Postgres a failed submit aborts the transaction so the follow-on Comment insert raises InFailedSqlTransaction; MariaDB continues. Savepoint + rollback before add_comment. No-op on MariaDB.
Conservative cleanup of frappe.throw/msgprint messages per the message style
guide; meaning, severity, and .format() arguments are unchanged:
- index bare {} placeholders as {0}/{1}/... so translators can reorder
- move f-strings / .format() / concatenation out of _() (they break gettext
extraction and never translate)
- wrap translatable dynamic values (DocType/Select labels) in _()
- fix grammar and colloquialisms
- drop no-op _() wrapping runtime-built strings
Part of #53976.
Conservative cleanup of frappe.throw/msgprint messages per the message style
guide; meaning, severity, and .format() arguments are unchanged:
- index bare {} placeholders as {0}/{1}/... so translators can reorder
- move f-strings / .format() / concatenation out of _() (they break gettext
extraction and never translate)
- wrap translatable dynamic values (DocType/Select labels) in _()
- fix grammar and colloquialisms
- drop no-op _() wrapping runtime-built strings
Part of #53976.
Use do_not_submit=1 for the service-item and reserve-warehouse validation
tests; they only exercise in-memory validation methods, so submitting the
Subcontracting Order is unnecessary.
calculate_service_costs paired the service_items and items child tables
by list index, which breaks if the tables are not index-aligned (e.g.
populate_items_table skips a service item with zero available qty),
assigning the wrong service cost or raising IndexError. Match by
purchase_order_item instead, and guard against division by zero qty.
Adds a regression test asserting service costs follow purchase_order_item
regardless of table ordering.
Covers previously untested Subcontracting Order paths:
- a Subcontracting Order requires a subcontracting Purchase Order
- service items must be non-stock items
- a supplied item's reserve warehouse must differ from the supplier warehouse
- the Subcontracting Receipt mapper applies BOM process-loss to the received qty
The `skip_transfer` and transfer branches of `validate_manufacture` ran the
same per-item validation loop — look the row up or throw "not a part of",
check overconsumption, guard against duplicates, record — differing only in
the data source (SCIO Received Item vs Work Order Item), the available-qty
basis, the source-warehouse check (skip_transfer only) and the message text.
Split each branch into a small method that builds a normalised
`{item_code: {consumed_qty, available_qty}}` lookup, and share the loop via
`_validate_customer_provided_consumption`. Branch-specific throw messages are
passed as callbacks so the user-facing strings (and their translations) are
unchanged, and the order in which checks fire is preserved. Also drops the
unused `name` column from the skip_transfer query.
Adds a test for the non-skip-transfer manufacture flow (Material Transfer for
Manufacture -> Manufacture), which exercises the Work Order branch that the
existing suite — all of whose manufacture tests set skip_transfer=1 — never
covered. Full subcontracting-inward suite passes on MariaDB and PostgreSQL.
Resolve 4 conflicts from Phase 7 service/mapper extraction vs upstream:
- asset.py: take extraction; repoint dangling make_asset_movement JS to mapper
- job_card: port upstream field_no_map(naming_series) into mapper.make_subcontracting_po
- sales_order: port upstream rows-index fix into mapper.make_delivery_note
- sales_invoice (Phase 7): take service delegations; port upstream SQL->QB/ORM
changes for get_warehouse, get_all_mode_of_payments, get_discounting_status,
clear_unallocated_mode_of_payments, and set_pos_fields(POS DN skip) into services
Repoint all JS method strings and Python imports for mapper functions
across 18 doctypes from the doctype module to its mapper module, and
remove the now-unused re-export shims from each doctype file (keeping
only names used internally).
Move the get_gl_dict/add_gl_entry logic from AccountsController/StockController
into free functions in accounts/services/gl_entry_builder.py with doc as first arg.
BaseGLComposer gains get_gl_dict and add_gl_entry methods that delegate to the free
functions — GL composers now call self.get_gl_dict/self.add_gl_entry directly
without going through the doc. AccountsController and StockController keep thin
shims for backward compatibility with unrefactored callers.
Also move update_gl_dict_with_regional_fields and update_gl_dict_with_app_based_fields
to gl_entry_builder.py, re-exporting them from accounts_controller.py to avoid a
circular import.
Extracts get_gl_entries logic from SubcontractingReceipt,
AssetCapitalization, and AssetRepair into dedicated GL composer classes
under each doctype's services/ package. Each composer follows the
established BaseGLComposer / BaseStockGLComposer pattern, and the
original get_gl_entries becomes a 3-line shim.
- SubcontractingReceiptGLComposer(BaseStockGLComposer): moves
make_item_gl_entries and make_item_gl_entries_for_lcv
- AssetCapitalizationGLComposer(BaseStockGLComposer): moves
get_gl_entries_for_consumed_{stock,asset,service}_items and
get_gl_entries_for_target_item; inventory_account_map/sle_map/precision
become composer instance attributes
- AssetRepairGLComposer(BaseGLComposer): moves
get_gl_entries_for_repair_cost and get_gl_entries_for_consumed_items
(AR inherits AccountsController, not StockController)
All 29 GL snapshot tests and existing doctype test suites (32 SCR,
5 AC, 18 AR) pass.