Commit Graph

58702 Commits

Author SHA1 Message Date
Mihir Kandoi
90288720a9 test(stock): cover a secondary item added without a BOM
A Manufacture entry with a raw material worth 1000, a finished good and a
Scrap row typed in the UI must value the scrap at its own rate and take
that value out of the finished good, leaving no difference.

(cherry picked from commit 7f47361ebd)

# Conflicts:
#	erpnext/stock/doctype/stock_entry/test_stock_entry.py
2026-08-03 09:53:17 +00:00
Mihir Kandoi
46bff320f3 fix(stock): cost a BOM-less secondary item out of the finished good
The legacy scrap checkbox deducted the scrap row's value from the
finished good, so a Manufacture entry balanced. Its replacement, the
Secondary Item Type dropdown, only balances when the row carries a BOM
Secondary Item link, because the cost allocation percentage lives there.
A row typed as Scrap in the UI has no such link, so its value was added
on top of a finished good that already absorbed the whole raw material
cost, and the entry closed with a non-zero difference.

Treat a secondary row with no BOM link the way the legacy scrap item was
treated: deduct its value from the finished good.

The finished good's rate is derived from the other incoming rows, so
those rows must be rated first. Previously the finished good was rated
in row order, ahead of the secondary rows, and picked up their amounts
only on a later validate pass. Rate the finished goods last so a single
pass is correct.

(cherry picked from commit 5e81cd1540)

# Conflicts:
#	erpnext/stock/doctype/stock_entry/stock_entry.py
2026-08-03 09:53:17 +00:00
mergify[bot]
ca6065398c fix(banking): fetch company list from DB instead of boot (backport #57731) (#57739)
fix(banking): fetch company list from DB instead of boot (#57731)

* fix(banking): fetch company list from DB instead of boot

* fix: show error banner for company list fail fetch

(cherry picked from commit abc3da6b97)

Co-authored-by: Nikhil Kothari <nik.kothari22@live.com>
2026-08-03 14:33:46 +05:30
Mihir Kandoi
eeab2a833f Merge pull request #57730 from frappe/mergify/bp/version-16-hotfix/pr-57647
fix(sales): reject sales returns where every item has zero quantity (backport #57647)
2026-08-03 13:44:09 +05:30
Mihir Kandoi
af4aea171b test(sales): import make_sales_return from delivery_note on version-16-hotfix 2026-08-03 13:29:40 +05:30
Mihir Kandoi
a2dfc9e50a Merge pull request #57728 from frappe/mergify/bp/version-16-hotfix/pr-57725
fix(stock): scope over deliver/receive role check to delivery and receipt overflow (backport #57725)
2026-08-03 13:13:22 +05:30
R-Jayaraman
f2a53247c5 test(sales): add coverage for zero-qty return rejection
Greptile flagged that the sales-side zero-qty-return fix had no dedicated
test proving the behavior - the existing suite happened to pass, but
nothing specifically asserted that an all-zero return is rejected while
a normal negative-qty return still succeeds.

Adds two tests covering the doctypes that rely entirely on this check
(no other guard covers them for a non-stock-effect return):
- Delivery Note return with qty 0 -> rejected
- Sales Invoice return with qty 0 (no update_stock) -> rejected

POS Invoice is not covered separately here since it always runs with
update_stock=1, which is already guarded by the pre-existing
validate_zero_qty_for_return_invoices_with_stock check regardless of
this fix.

(cherry picked from commit 732c884633)
2026-08-03 07:35:29 +00:00
R-Jayaraman
aa71cd695b fix(sales): reject sales returns where every item has zero quantity
validate_returned_items() set items_returned=True whenever a row matched
a valid item from the original document, even if its qty was 0. This let
a Sales Invoice, Delivery Note, or POS Invoice return be submitted with
every line at qty=0 - a no-op document with no stock or financial effect
that still consumed a document number and linked back to the original
transaction.

Scoped to the Sales side only: items_returned now flips to True for
Sales Invoice/Delivery Note/POS Invoice only when qty (or received_qty)
is actually negative, so an all-zero sales return correctly hits the
existing "At least one item should be entered with negative quantity"
check. Purchase Invoice, Purchase Receipt, and Subcontracting Receipt
are unchanged.

(cherry picked from commit a3e9d13da3)
2026-08-03 07:35:29 +00:00
Mihir Kandoi
697f68d1d2 fix: resolve version-16 backport conflicts
Keep validate_warehouses() alongside the new
validate_over_delivery_receipt_allowance() call.

Drop test_blanket_order_over_order_aggregated_across_rows: it is develop-only
context the cherry-pick swallowed into the conflict, not part of #57725.

Revert the valuation_method literal to the three options this branch offers -
Standard Cost rode along from a regenerated develop type block.
2026-08-03 12:55:08 +05:30
Mihir Kandoi
246ffee17c Merge pull request #57722 from frappe/mergify/bp/version-16-hotfix/pr-57645
fix(purchase): reject purchase returns where every item has zero quan… (backport #57645)
2026-08-03 12:54:59 +05:30
Mihir Kandoi
e7757f6d0b Merge pull request #57726 from frappe/mergify/bp/version-16-hotfix/pr-57097
fix(stock): read quality inspection readings in the user's number format  (backport #57097)
2026-08-03 12:42:52 +05:30
Mihir Kandoi
10229700c0 test(purchase): drop unrelated sales-return test from the backport
test_sales_return_validates_against_original came in with the new file,
not with the change being backported. It covers a raw-SQL to query-builder
conversion that only exists on develop, and it imports
erpnext.stock.doctype.delivery_note.mapper, a module version-16-hotfix
does not have.
2026-08-03 12:42:10 +05:30
Afsal Syed
6cbf73a326 test(stock): prevent settings leakage in purchase order tests
(cherry picked from commit 99630f40eb)
2026-08-03 07:10:14 +00:00
Afsal Syed
3a0f988a9e test(stock): add test cases verifying stock over delivery role does not bypass order allowance
(cherry picked from commit 0b271e24b6)

# Conflicts:
#	erpnext/manufacturing/doctype/blanket_order/test_blanket_order.py
2026-08-03 07:10:14 +00:00
Afsal Syed
4713ddd55b fix(stock): scope over deliver/receive role check to delivery and receipt overflow
(cherry picked from commit 248873034d)
2026-08-03 07:10:14 +00:00
Afsal Syed
3f3292ca4a fix(stock): validate over delivery/receipt allowance in stock settings
(cherry picked from commit 446ec6030a)

# Conflicts:
#	erpnext/stock/doctype/stock_settings/stock_settings.json
#	erpnext/stock/doctype/stock_settings/stock_settings.py
2026-08-03 07:10:14 +00:00
Mihir Kandoi
656db1c2fe fix(stock): resolve backport conflict in quality inspection imports
The backport left both import hunks unresolved, so the file did not compile.
version-16-hotfix keeps item_query unannotated and still imports cstr, so only
get_number_format_info goes, replaced by NumberFormat; typing.Any is not
carried over because nothing on this branch uses it.
2026-08-03 12:31:55 +05:30
Mihir Kandoi
444dd9e817 test(stock): cover reading number formats end to end
Set the number format on the session user rather than on System Settings: the
code reads the user default, which shadows the global one, so these tests never
exercised the path they were written for. Restoring it in a finally also keeps
a failed assertion from leaving the whole suite in another locale.

Add a table test over every format in NUMBER_FORMAT_MAP, covering the grouped
values and the three formats parse_float used to read as 0, and restore the
formula-based coverage for non-numeric readings.

(cherry picked from commit 00d17ca5db)
2026-08-03 06:56:49 +00:00
Mihir Kandoi
fccf1220f6 fix(stock): accept every number a reading can be written as
parse_float and is_valid_number each re-derived the number grammar, so the
validator accepted strings flt() cannot parse: str.isdigit() lets superscripts
through and lstrip("+-") lets repeated signs through, both then silently scored
as 0. One parse_reading() returning None when float() refuses the value makes
acceptance and conversion true by construction.

The grammar was also wrong for several formats. Where the group separator is
not a dot, a dot-decimal reading such as 1.15 parsed correctly before and is
accepted again. #,### and #.### report no decimal separator at all, which
rejected every fractional reading outright and, for #.###, reread a stored
1.500 as 1500.0; they now fall back to a dot and give up the grouping that
would collide with it.

Only readings that change are checked, so an inspection entered by a user in
one locale stays saveable and submittable by a user in another, and manual
inspection rows keep the free text they were never parsed for.

NumberFormat replaces get_number_format_info, which frappe drops in v16.

(cherry picked from commit 5b5f354090)

# Conflicts:
#	erpnext/stock/doctype/quality_inspection/quality_inspection.py
2026-08-03 06:56:48 +00:00
Sudharsanan11
113b5ecaec test(stock): cover quality inspection readings in every number format
covers the reported case, a 1,15 reading in the space grouped "# ###,##"
format, which was read as 115 and rejected. also covers the dot grouped
comma format, and asserts that a reading written with the wrong separator,
or one that is not a number at all, is now rejected with an error rather
than read as a different value.

(cherry picked from commit b1f188146e)
2026-08-03 06:56:48 +00:00
Sudharsanan11
e2466780b9 test(stock): drop non numeric reading from formula based quality inspection
a numeric reading of "random text" was read as 0 and pulled the mean from
0.6 down to 0.4, which the test then asserted as accepted. such a reading
is now rejected outright, and the test is about formula evaluation, so drop
the row. its assertions are unchanged.

(cherry picked from commit 3752be809f)
2026-08-03 06:56:47 +00:00
Sudharsanan11
3b7fb6851a fix(stock): read quality inspection readings in the user's number format
readings are Data fields, so they are parsed server side. parse_float only
swapped the separators for "#.###,##", so in the space grouped "# ###,##"
(polish) a reading of 1,15 was read as 115, fell outside the acceptance
range and silently rejected the inspection. strip whatever the group
separator is and normalise whatever the decimal separator is instead.

it also read the global number format, while the desk formats numbers with
the user's own. a user whose locale differs from the site therefore typed
readings in a format the server did not parse them with. read the user
default, which falls back to the global one.

a reading that is not a valid number in that format is now rejected with an
error instead of being read as a different number.

(cherry picked from commit e74c0a3cdb)
2026-08-03 06:56:46 +00:00
R-Jayaraman
b0f2704bde test(purchase): add coverage for zero-qty return rejection
(cherry picked from commit cde2963da1)

# Conflicts:
#	erpnext/controllers/tests/test_sales_and_purchase_return.py
2026-08-03 06:17:09 +00:00
R-Jayaraman
032b922f0c fix(purchase): reject purchase returns where every item has zero quantity
validate_returned_items() set items_returned=True whenever a row matched
a valid item from the original document, even if its qty was 0. This let
a Purchase Invoice, Purchase Receipt, or Subcontracting Receipt return be
submitted with every line at qty=0 - a no-op document with no stock or
financial effect that still consumed a document number and linked back
to the original transaction.

Scoped to the Purchase side only: items_returned now flips to True for
Purchase Invoice/Purchase Receipt/Subcontracting Receipt only when qty
(or received_qty) is actually negative, so an all-zero purchase return
correctly hits the existing "At least one item should be entered with
negative quantity" check. Sales Invoice, Delivery Note, and POS Invoice
are unchanged.

Also applies a corresponding check to the item_name-only fallback branch
(for rows without an item_code - Item Code is not mandatory on Purchase
Invoice Item), which previously bypassed this fix entirely and still set
items_returned=True unconditionally regardless of quantity. For that
branch specifically, only qty is checked (not received_qty): with no
linked Item there's no accepted/rejected split, so received_qty carries
no independent meaning and a qty=0 row must be rejected regardless of
its value.

(cherry picked from commit b63066ed44)
2026-08-03 06:17:08 +00:00
MochaMind
833ccd3358 chore: update POT file (#57706) 2026-08-02 14:31:18 +02:00
Mihir Kandoi
4a5c416ee0 Merge pull request #57698 from frappe/mergify/bp/version-16-hotfix/pr-57676
feat: select a supplier per item when creating Purchase Orders from a Material Request (backport #57676)
2026-08-02 12:35:56 +05:30
Mihir Kandoi
4b6a4cc9c5 Merge pull request #57701 from frappe/mergify/bp/version-16-hotfix/pr-57699
fix: prevent duplicate shipping charges without cost center (backport #57699)
2026-08-02 12:29:29 +05:30
Mihir Kandoi
e5f8d0c84b fix: apply the supplier selection to this branch's own mapper module
The backport carried develop's mapper module across whole, while version 16
keeps its mappers in material_request.py. That left two copies of the mapping
layer: the dialog and the new tests reached for the imported module, and
make_purchase_order, which the rest of the branch and the older tests use, never
learned to set the supplier - so test_make_purchase_order_sets_supplier failed.

The feature now sits in material_request.py alongside the mappers it extends,
and the imported module is dropped.
2026-08-02 12:25:22 +05:30
Mihir Kandoi
7f81502cde chore: remove shipping rule comments
(cherry picked from commit 106ecd7120)
2026-08-02 06:49:06 +00:00
Mihir Kandoi
666b6167a1 fix: prevent duplicate shipping charges without cost center
(cherry picked from commit a4134af30b)
2026-08-02 06:49:06 +00:00
Mihir Kandoi
65a53a7012 Merge pull request #57697 from frappe/mergify/bp/version-16-hotfix/pr-57674
fix: preserve UOM conversion factor precision in transactions (backport #57674)
2026-08-02 12:06:19 +05:30
Mihir Kandoi
e98471d9c9 fix: resolve version 16 backport conflicts 2026-08-02 12:03:47 +05:30
Mihir Kandoi
187840b559 fix: label the items table in the supplier selection dialog
The grid template always renders its label line, so leaving the table unlabelled
left an empty line hanging above the description.

(cherry picked from commit 2e72846670)
2026-08-02 06:26:26 +00:00
Mihir Kandoi
2c9db13041 fix: keep the bulk supplier field to half the supplier selection dialog
A lone Link field stretched the full width of the dialog, which reads as a
search bar rather than a field. A column break holds it to half.

(cherry picked from commit 44fdf7bea9)
2026-08-02 06:26:26 +00:00
Mihir Kandoi
9b647bed5c feat: set one supplier across every item in the supplier selection dialog
A Material Request where few items carry a default supplier meant picking the
same supplier row by row. A Supplier field above the table copies its value
into every row, leaving the exceptions to be corrected by hand.

Both pickers skip suppliers that are disabled or barred from Purchase Orders by
their scorecard standing.

(cherry picked from commit e84bf44e51)
2026-08-02 06:26:25 +00:00
Mihir Kandoi
93331a1cf0 fix: warn about existing draft orders before the supplier selection creates more
Creating through the dialog calls the endpoint directly instead of going
through open_mapped_doc, so the draft link guard that every other Create action
runs never fired, and a repeated dialog quietly produced a second set of draft
orders for the same quantity.

(cherry picked from commit f0bb70539d)
2026-08-02 06:26:25 +00:00
Mihir Kandoi
380ee3b013 test: reject the same Material Request item twice in one supplier selection
(cherry picked from commit 8ffe5ba420)
2026-08-02 06:26:25 +00:00
Mihir Kandoi
ea770f6a8e fix: reject the same Material Request item twice in one supplier selection
Each row was checked against the pending quantity on its own, so a payload that
listed one item under two suppliers passed both checks and ordered the pending
quantity twice. The dialog cannot produce that, a direct call to the endpoint
can.

(cherry picked from commit 99d56cc850)
2026-08-02 06:26:25 +00:00
Mihir Kandoi
06a753faf3 fix: escape item code and UOM in the supplier dialog errors
Desk renders a client side message as HTML, so an Item or UOM whose name holds
markup ran as markup in the buyer's session.

(cherry picked from commit 21c6d10ad3)
2026-08-02 06:26:24 +00:00
Mihir Kandoi
e71cef02b3 fix: open the Purchase Order when the supplier selection creates only one
Naming a single order in a message and leaving the buyer to click it is a step
for nothing. The form opens directly when there is one order; the message stays
for the case it was meant for, several orders at once.

(cherry picked from commit 3856eaa35e)
2026-08-02 06:26:24 +00:00
Mihir Kandoi
6096e761b0 test: reject a supplier selection without items
(cherry picked from commit d233fdf198)
2026-08-02 06:26:24 +00:00
Mihir Kandoi
d6ee5436b8 feat: order only the items ticked in the supplier selection dialog
Every row is ticked when the dialog opens, so the common case of ordering
everything is unchanged, and a buyer who wants a partial order unticks what
should wait. Creating with nothing ticked is rejected.

(cherry picked from commit 07445b3675)
2026-08-02 06:26:23 +00:00
Mihir Kandoi
810b9ae28f fix: link the item and spell out the unit in the supplier dialog errors
A bare item code left the buyer to find the item themselves, and a bare number
gave no clue what the limit was counted in. Both messages now link the item and
state the pending quantity in bold with its UOM.

(cherry picked from commit 5a78e2290a)
2026-08-02 06:26:23 +00:00
Mihir Kandoi
6b056ebb36 test: alert when Required By falls back to today
(cherry picked from commit 671c289303)
2026-08-02 06:26:22 +00:00
Mihir Kandoi
1adeb66bdc feat: alert when Required By falls back to today
Items whose requested date has passed silently got today as Required By, which
is a date the buyer never asked for. A toast now says so.

(cherry picked from commit 53e09dfdd6)
2026-08-02 06:26:22 +00:00
Mihir Kandoi
5aaefec747 feat: show the UOM alongside the quantity in the supplier selection dialog
The quantity is meaningless without the unit it is counted in, which the buyer
had to look up on the Material Request itself.

(cherry picked from commit d0cae2eb9c)
2026-08-02 06:26:22 +00:00
Mihir Kandoi
d2fe4b623c fix: list the Purchase Orders created per supplier instead of opening one
Opening one of several created orders hid the rest and moved the buyer off the
Material Request. The created orders are now reported the way Production Plan
reports its documents, as links in a message, and the form stays put.

(cherry picked from commit 6f22551aae)
2026-08-02 06:26:22 +00:00
Mihir Kandoi
d718110216 test: Required By on Purchase Orders created per supplier
Backdates the Material Request item so the mapper drops its schedule date, and
asserts the created order still saves with today as Required By.

(cherry picked from commit 15d10bbaf1)
2026-08-02 06:26:21 +00:00
Mihir Kandoi
f99d66d578 fix: set Required By on Purchase Orders created per supplier
Mapping drops a schedule date that already passed, leaving the buyer to pick a
new one on the Purchase Order form. Nothing fills it in when the orders are
created straight from the supplier selection dialog, so a Material Request
whose required date has gone by failed to save with "Please enter the Required
By".

Items that lose their date now fall back to today, which is the earliest date a
Purchase Order raised today accepts.

(cherry picked from commit d05bd80b1e)
2026-08-02 06:26:21 +00:00
Mihir Kandoi
f19aa957cb test: quantity handling in the supplier selection dialog
Asserts the requested quantity reaches the Purchase Order item and that rows
without a supplier, or with a quantity that is zero, negative or beyond the
pending quantity, are rejected.

(cherry picked from commit 09cfd1fe91)
2026-08-02 06:26:21 +00:00