Greptile: the first line restated the return expression. What is left is the part
that is not visible from the code -- the renderer reads the same key, which is what
stops the item being filtered against one company and drawn pointing at another.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The first navigation item kind contributed by an app that is not frappe, which is
what charter point 6 of frappe/frappe#42226 promised and frappe/frappe#42424 asked
for: an app adds a kind through the same mechanism the framework's own eight go
through, and the framework grows no case for it.
The kind is one folder under `setup/navigation_item_type/default_company/`: the
`Navigation Item Type` record, which arrives at `bench migrate`; `frontend/item.js`
beside it, which arrives at `bench build`; and `default_company.py`, which
`hooks.py` names under `navigation_item_resolvers`. One row in the Setup sidebar
uses it, above the `Company` list.
It points at the company this site works in. That is a destination none of the
eight kinds can express: a `Record` item names its document, and the company's
name is chosen during the setup wizard, so ERPNext has no name to ship. The
renderer computes it from `boot.sysdefaults.company`, which every desk v2 boot
already sends, and the resolver reads the same key -- so the item cannot be
filtered against one company and drawn pointing at another.
The type declares the `Custom` permission rule rather than `Readable DocType`,
and that is the reason it carries server code at all. `Readable DocType` asks
whether a person may read `Company`; the honest question is whether they may open
*this* company, which a `User Permission` decides and which ERPNext sites use
routinely. Measured both ways on a real site: a System Manager pinned to another
company keeps the item under `Readable DocType` and loses it under `Custom`.
The shipped row carries no label on purpose, so the renderer's fallback names the
item after the company itself.
One thing the build found: a `Global Defaults` naming a company somebody has since
deleted makes `has_permission` raise. Left alone, the framework fails the kind
closed and writes an Error Log -- and would write another on every boot of every
session, because the cause is the site's data rather than a passing fault. It is
answered as the same "nothing to point at" an unfinished setup wizard gets. The
leak is invisible to Administrator, who never reaches the document.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Greptile P2, and right: the fixture checks read `resolve_navigation`, which has
already dropped a row naming a missing doctype, a heading over nothing and a
linked item whose sidebar emptied. Against that output they were asserting that
the resolver works, which is frappe's test.
They now read the standard `Rail` and `Sidebar` rows as authored. Checked that
each can fail: an orphan `parent_key` and an empty section both insert happily.
A missing doctype does not -- `link_to` is a Dynamic Link and `_validate_links`
refuses the row at import -- so that test now says what it is actually for, a
doctype removed after the rows were imported.
Adds one: every `parent_key` names a section beside it. An orphan is promoted to
the top level rather than dropped, so it loses its nesting in silence.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The module-primary half of frappe/frappe#42226's charter point 2, opposite CRM's
doctype-primary rail: the same table, the same resolver and the same item kinds,
with modules as the rail's primary items.
One `Rail` record of 20 items -- 18 `Sidebar` items over a module sidebar each,
and two `Module` items for the modules whose sidebar would hold one row or none.
The sidebars are authored, not derived: the module *page* keeps deriving from
module contents and the two lists differ on purpose, which is what desk v1's own
curation already says -- 107 doctypes sit on a module page and not in that
module's sidebar, and 101 sidebar links point outside their module.
The rows are converted from desk v1's module sidebars, which stay untouched and
keep serving v1. 486 v1 rows become 317: `Report`, `Dashboard`, `Workspace` and
`Page` items have no desk v2 destination and are not authored, headings left
over nothing are dropped, and two duplicate rows in Accounts go. `Portal` is on
v1's dock and is not authored at all -- it holds no doctypes, so it has neither
a sidebar to open nor a module page to land on.
ERPNext ships no navigation code: the rows arrive through `sync_for`'s
app-rooted walk at migrate.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix(stock): subtract stock qty of same-document rows from batch availability
filter_batches subtracted a row's transaction-UOM qty from batch quantities that
are in the stock UOM, so a row in an alternate UOM freed less of the batch than
it consumes and the auto-pick could assign a batch that cannot cover the new
row.
* test(stock): cover batch availability with alternate UOM rows
* fix(stock): assign batch_no only when the first batch covers the full qty
The auto-pick loop reduced the requested qty per batch and left the last
visited batch on the row, so a qty spanning batches got a batch that could
not fulfil it and failed at submit with a misleading negative-stock error.
Assign the first batch in pick order only when it alone covers the qty.
Otherwise leave batch_no empty so the auto-created Serial and Batch Bundle
splits the qty across batches at submit.
Batches are queried without qty so filter_batches subtracts rows already in
the document from the uncapped batch quantities. Querying on a copy also
stops get_auto_batch_nos from clearing warehouse on the kwargs later used to
pick serial nos.
Fixes#58640
* test(stock): cover batch auto-pick when qty spans batches
* fix(stock): pick serial nos across batches when no batch covers the qty
With batch_no left empty for a qty that spans batches, the serial pick for a
serialised and batched item filtered on [None] and returned nothing, leaving
the row with neither identity. Skip the batch filter when there is no batch so
the serial nos are picked in the configured order across batches; the bundle
built at submit derives each serial's batch.
* test(stock): cover serial pick across batches for batched serial items
* fix: production plan summary report tree structure and quantities
* feat: production plan visualizer page
* feat: single screen production plan visualizer with material readiness
* fix: show live stock and received status for production plan materials
* fix: remove duplicate border under production plan visualizer header
* fix: drop page head border on production plan visualizer
* fix: add horizontal margin to production plan visualizer
* fix: apply record level permissions and resolve shared material owners
* fix: list shared raw materials under every finished good that needs them
* feat: open linked documents in a side panel from the visualizer
* fix: never fall back to stored qty when warehouse stock is not readable
* fix: include directly consuming finished goods in material ownership
* fix: show each finished good's own share of shared material demand
* fix: match production plan quantities and labels in the visualizer
* fix: resolve nested sub assembly owners when parent link is missing
* fix: keep every matching owner when resolving sub assemblies by item code
* feat: flat work order list in place of the items to manufacture tree
* fix: flatten items to manufacture rows without changing the table design
* fix: align table numbers, units and progress cells
* fix: scope nested owner resolution to the same sales order
* fix: keep quantity columns numeric and move uom to the item line
* fix: recover all finished goods for consolidated sub assembly rows
* fix: scope raw material owners to the same sales order