Address review feedback:
- A typed-but-not-selected value passed validation yet was dropped by
get_selected_attributes (reads committed pills only). Treat any pending
input as an error so it is never silently omitted from creation.
- Escape pill / pending values before interpolating them into the HTML
error message.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The 'Create Multiple Variants' dialog rendered one checkbox per attribute
value and read the numeric config from the variant attribute child row. This
broke in several ways:
- A template whose attribute was made numeric after being added kept
numeric_values=0 on the child row, so the dialog treated it as non-numeric,
queried the empty Item Attribute Value table, and showed no values.
- Enumerating a large range (e.g. 1-100000) into checkboxes froze the browser.
Rework the dialog:
- Read numeric_values / from_range / to_range / increment from the Item
Attribute master, and guard increment > 0.
- Replace the checkbox-per-value list with one MultiSelectPills per attribute,
with a search placeholder.
- Stop enumerating numeric ranges: preview the first few values and validate
typed input against the range on demand, so huge ranges stay instant.
- Block variant creation with a modal error if any selected value or pending
input is invalid (out of range, off-increment, or not a number), so garbage
like '00A' can't reach creation.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Marking an attribute numeric hides the Item Attribute Values grid but leaves
its rows in the doc, whose mandatory Attribute Value / Abbreviation block the
save client-side before the server can clear them. Clear the table on the
client too so the save goes through.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Wraps per-(item, warehouse) reposting in repost_future_sle with a session-level advisory lock in front of the existing for-update row locks -- an outer gate that turns lock-order deadlocks into an orderly wait. Postgres/MariaDB only; nullcontext elsewhere. Row locks still enforce correctness. Requires frappe advisory_lock.
Reimplements get_ancestor_boms, BOM.traverse_tree, Task.check_recursion and the BOM Explorer report as single recursive-CTE queries (frappe.qb recursive=True), replacing query-per-node walks (N->1). Task cycle detection now catches cycles at any depth (was capped at 15 nodes). Requires the framework recursive-CTE support (frappe#40464).