Commit Graph

3412 Commits

Author SHA1 Message Date
diptanilsaha
dc907add40 fix(payment reconciliation): correct supplier gain/loss posting 2026-08-04 23:58:19 +05:30
Mihir Kandoi
4babce436f Merge pull request #57755 from mihir-kandoi/backport/secondary-item-valuation-fixes
fix(stock): correct secondary item valuation across stock entry purposes
2026-08-03 17:05:54 +05:30
Mihir Kandoi
4ed03748fe fix(stock): correct secondary item valuation across stock entry purposes
Backport of five fixes merged to develop, adapted to this branch, where
the field is still named `type` and the stock entry rate logic has not
been split out of set_basic_rate.

- A secondary row with no BOM link is costed out of the finished good,
  as legacy scrap was. Finished goods are rated last so a single
  validate pass sees the secondary rows' amounts. (#57732)
- Repack no longer flags secondary rows as finished goods, so each side
  takes the share the BOM declares instead of the scrap absorbing the
  finished good's percentage. (#57735)
- A BOM allocation of 0% means the row carries no cost, rather than
  falling through to the item's own valuation rate. (#57736)
- Secondary Item Type no longer waives a quality inspection on purposes
  that do not produce secondary items. (#57737)
- The BOM allocation applies to the consumption entry's cost when the
  raw material cost comes from one. (#57738)

Replaces the individual backports, which could not be cherry-picked
cleanly: every hunk needed rewriting against the pre-rename field and
the un-refactored rate logic.
2026-08-03 16:53:20 +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
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
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
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
Mihir Kandoi
e5999b22c7 fix: preserve UOM conversion factor precision in transactions
calculate_item_values rounds every Float field on an item row to the
site's Float Precision (3 by default), and conversion_factor was one of
them. The factor is a ratio, not a rate: UOM Conversion Factor.value is
stored at precision 9, and Material Request keeps the full value because
it has no currency field and so never runs the calculation.

Mapping a Material Request to a Purchase Order therefore truncated the
factor - 0.453592292 for Pound -> Kg became 0.454 - and stock_qty, which
is recomputed as qty * conversion_factor, drifted from the quantity that
was requested, leaving the Material Request unable to close.

Exclude conversion_factor from the rounded fields on the server and on
the client. Factors below the site precision would otherwise round to
zero outright.

(cherry picked from commit 269cc6ee3b)
2026-08-02 06:25:58 +00:00
diptanilsaha
c7cf9d868b fix(item_variant): added permission checks on enqueue_multiple_variant_creation
(cherry picked from commit 3b0cbc972e)
2026-08-01 15:01:27 +05:30
Poovetha
d104d8e723 fix(projects): include on hold status in project filters and reports
(cherry picked from commit 51a9fc0316)
2026-07-31 11:07:35 +05:30
Mihir Kandoi
04e1ca8226 fix(selling): don't require cancel and delete perms to remove items via Update Items (backport #57419) (#57601)
Row removal called cancel() and delete() on the child row, and both check
permissions against the parent doctype. Dropping a row therefore needed Cancel
and Delete on the order, while the rest of the dialog only needs Write: the
button is gated on has_perm("write"), update_child_qty_rate checks parent
Write, and edits save with ignore_permissions=True.

Set ignore_permissions on the row before cancel/delete so removal sits behind
the same parent Write check as add and edit. validate_child_on_delete is
unchanged, so rows with ordered, received, delivered or billed qty are still
refused.

On version-16-hotfix validate_and_delete_children still lives in
erpnext/controllers/accounts_controller.py, not the extracted
erpnext/accounts/services/child_item_update.py module it was moved to on
develop.

Co-authored-by: Kaushal Shriwas <64089478+kaulith@users.noreply.github.com>
2026-07-29 11:30:36 +00:00
rohitwaghchaure
861c50e727 fix: skip stock expense GL entries for non-stock items (#57518)
* fix: skip stock expense gl entries for non stock items

(cherry picked from commit 747f4df778dca45cf044c02f0e933d3b230b8334)

* test: use a leaf expense account for the service item invoice
2026-07-28 13:00:41 +05:30
pandiyan
a30aac87bf fix: detect the currency column by fieldtype in trends total row
calculate_total_row tested each column with `"Link/Currency" in col`, but
based-on and group-by columns are dicts, so the test checked the dict's keys
and never matched. currency_col_idx stayed None and the grand-total row's
currency cell was left unset, so Total(Amt) rendered with the global default
currency instead of the company's.

Match the dict's fieldtype/options instead. Dict columns are never numeric
and string columns are never Link columns, so the two branches are now
mutually exclusive.
2026-07-28 11:28:07 +05:30
pandiyan
9e5f77b57c fix: use company currency instead of global default in report (backport #56561)
Reports like Sales Order Trends and Purchase Order Trends showed the global
default currency symbol instead of the transacting company's currency.

Threads the company currency through conditions["company_currency"] in
trends.get_columns and uses it for both the chart's currency and the Total
row. The chart now skips the grand-total row by its label instead of by a
falsy first periodic cell, so the already-summed Total row is not added into
the datapoints a second time.

Backport of #56561 (frappe/erpnext). Tests from the original PR are not
included: the trends report test files do not exist on this branch.
2026-07-28 11:08:13 +05:30
rohitwaghchaure
68caa60dfa feat: book Expenses Added To Stock GL entries (backport #57190 + #57475) (#57503)
* fix: exclude landed cost from purchase expense GL entries

* feat: book expenses added to stock GL entries for stock vouchers

* test: enable stock expense gl entries flag for purchase expense test
2026-07-27 18:32:13 +00:00
Mihir Kandoi
95de2374ed fix: get reserved batch qty precision from settings 2026-07-22 14:58:11 +05:30
Afsal Syed
134d63de78 feat(stock): automatically link portal users to their associated contact profiles for customers and suppliers
(cherry picked from commit 337a06dfb6)
2026-07-16 15:44:45 +05:30
mergify[bot]
0817d1064c fix: permission issue (backport #57112) (backport #57142) (#57184)
* fix: permission issue (backport #57112) (#57142)

* fix: permission issue (#57112)

(cherry picked from commit 1fd2faa68d)

# Conflicts:
#	erpnext/controllers/stock_controller.py

* chore: fix conflicts

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
(cherry picked from commit 6b23b007a4)

# Conflicts:
#	erpnext/controllers/stock_controller.py

* chore: fix conflicts

* chore: fix conflicts

---------

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2026-07-15 15:05:17 +05:30
Mihir Kandoi
f3e1b3fca7 fix: round outstanding qty guard consistently with the conflict gate 2026-07-15 12:00:02 +05:30
Mihir Kandoi
555c607f2f fix: exclude fully-delivered reservations from the conflict message 2026-07-15 12:00:02 +05:30
Mihir Kandoi
839fd5e3b6 fix: name every conflicting voucher in the reserved batch error 2026-07-15 12:00:02 +05:30
Mihir Kandoi
56bbca0203 fix: allow delivery when a batch is reserved across multiple sales orders (backport #57169)
validate_reserved_batches compared the voucher's own qty against the
remaining batch qty, so delivering one order's reserved unit threw
Reserved Batch Conflict whenever the remainder exactly matched another
order's reservation. Compare the remaining batch qty against the
aggregated outstanding reserved qty (qty - delivered_qty) of other
vouchers instead, excluding reservations the voucher itself delivers.
2026-07-15 12:00:02 +05:30
rohitwaghchaure
5642359c10 fix: enforce read permission on ledger preview endpoints (#57039)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: diptanilsaha <diptanil@frappe.io>
2026-07-12 09:53:17 +00:00
Vishnu Priya Baskaran
8eb92b8b18 fix(payment reconciliation): honour user permissions on accounting di… (#56560) 2026-07-11 15:04:44 +05:30
pandiyan
b8199d88b6 fix: make trend report based-on and group-by column labels translatable
based_wise_columns_query() and group_wise_column() built column labels as
raw strings, so headers like Item, Item Name, Customer, Supplier, and
Territory never went through the _() translation function and stayed in
English regardless of the user's language, while period and total columns
translated fine. Build these as column dicts with an explicit _()-wrapped
label instead, so they're translated the same way as the rest of the report.

(cherry picked from commit 015fa68fc0)
2026-07-10 12:16:45 +05:30
pandiyan
97cd1e7144 fix: rename variant item_code/item_name when attribute abbreviation changes
Item Attribute abbreviations only got baked into a variant's item_code
and item_name at creation time (make_variant_item_code returns early
once item_code is set). Renaming an abbreviation afterwards left every
existing variant stuck with the stale code, silently out of sync with
its own attribute.

Detect abbreviation renames on Item Attribute save, find every variant
using the affected value, and rebuild+rename its item_code via
frappe.rename_doc so linked records follow along. item_name is rebuilt
in lockstep from the template's item_name, even if it had since been
customized, since both fields are meant to be derived from the same
abbreviation.

(cherry picked from commit c0cfe5f363)
2026-07-09 15:04:03 +00:00
Sudharsanan11
af495ed253 feat(stock): support partial transfer from pick list
Creating a Stock Entry from a Pick List blocked any further entry
(stock_entry_exists) and flipped the pick list to Completed as soon as
one entry existed, so picked stock could not be transferred in parts.

Track transferred_qty per Pick List Item (summed from submitted Stock
Entry rows via a new pick_list_item link, mirroring delivered_qty), add
a Partially Transferred status, and map each new Stock Entry from the
remaining qty so transfers can continue until fully transferred.
2026-07-09 19:20:19 +05:30
mergify[bot]
8c56a5ac0c fix: don't attempt to create SABB for non-serialized / non-batch items (backport #56627) (#56803)
* fix: don't attempt to create SABB for non-serialized / non-batch items (#56627)

* fix: don't attempt to create SABB for non-serialized / non-batch items

* fix(stock): skip serial batch lookup for rows without item code

(cherry picked from commit 5b738b7b0d)

# Conflicts:
#	erpnext/stock/services/serial_batch_bundle_service.py

* chore: resolve conflicts

---------

Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com>
2026-07-03 10:35:43 +05:30
Nabin Hait
0f9405646b Merge pull request #55970 from frappe/mergify/bp/version-16-hotfix/pr-55947
fix(accounts): clear clearance date when amending reconciled voucher (backport #55947)
2026-07-02 13:22:20 +05:30
Sudharsanan11
40ca3b5e5d fix(stock): support quality inspection for stock entry by purpose (backport #56446) 2026-07-01 00:16:21 +05:30
Mihir Kandoi
d2c8df9451 fix: use correct variable to fetch valuation method
(cherry picked from commit 1492c9fbc3)
2026-06-30 15:04:46 +00:00
Mihir Kandoi
5d8f653476 Merge pull request #56604 from frappe/mergify/bp/version-16-hotfix/pr-56231
fix(controllers): fix supplier-RFQ portal list query (wrong column + Postgres DISTINCT) (backport #56231)
2026-06-30 12:03:21 +05:30
pandiyan
41812462b4 fix: set mr status to received when per_received is 100 even if per_ordered < 100
(cherry picked from commit a3c5ef6aa3)
2026-06-30 05:41:09 +00:00
mergify[bot]
0829cb45a8 fix: carry item-level project to Purchase Receipt GL entries (backport #56568) (#56619)
fix: carry item-level project to Purchase Receipt GL entries (#56568)

Purchase Receipt stock and asset GL lines used the item row's cost center
but always fell back to the document-level project, unlike Purchase Invoice
which uses the item-level project. add_gl_entry accepted a project argument
but never wrote it to the GL dict, so the inward, Stock Received But Not
Billed, landed cost, divisional loss, sub-contracting and exchange rate
lines dropped the row's project.

Write project into the GL dict and pass project=item.project on the entries
that were missing it, so project behaves like cost center and matches
Purchase Invoice.

Ticket: 72523
(cherry picked from commit 6f97c7199c)

Co-authored-by: Jatin3128 <140256508+Jatin3128@users.noreply.github.com>
2026-06-29 23:30:48 +05:30
Mihir Kandoi
3abadc7a5f fix(controllers): fix supplier-RFQ portal list query (wrong column + Postgres DISTINCT)
rfq_transaction_list had two defects introduced when it was converted to the query
builder:

1. `party.supplier == party[0]` compared supplier to a column literally named "0"
   (a stray index on the DocType, not the intended `parties[0]` value). This renders
   as `supplier = \`0\`` / `supplier = "0"` and errors on BOTH engines
   (MariaDB: Unknown column '0'; Postgres: column "0" does not exist), so the
   supplier portal RFQ list was completely broken.
2. SELECT DISTINCT ordered by `creation`, which is not in the select list. Postgres
   rejects this ("for SELECT DISTINCT, ORDER BY expressions must appear in select list").

Compare against `parties[0]` and add `creation` to the select list.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
(cherry picked from commit a7d9078bf4)

# Conflicts:
#	erpnext/controllers/tests/test_website_list_for_contact.py
2026-06-29 08:24:18 +00:00
ruthra kumar
1a9fcfb0cc refactor(test): broken test case in accounts controller
(cherry picked from commit 59a69fc497)
2026-06-29 09:41:48 +05:30
ruthra kumar
a8aa73baae refactor(test): remove even more dead code
(cherry picked from commit 3d109571ee)
2026-06-29 09:41:48 +05:30
ruthra kumar
65202d2be1 refactor(tests): reuse persistent master data instead of creating company per test
Replace per-test company creation in setUp() with persistent master data
from BootStrapTestData. Add Test PCV Company to test_records.json so it
becomes a persistent fixture rather than a throwaway created per test run.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit 6e62750c2f)

# Conflicts:
#	erpnext/accounts/report/financial_ratios/test_financial_ratios.py
2026-06-29 09:41:47 +05:30
rohitwaghchaure
6dad1b1ae6 refactor: move Inventory Dimension mandatory check from field-level to server-side (#56451)
* refactor: move Inventory Dimension mandatory check from field-level to server-side

* refactor: split large function

* fix: greptile issue
2026-06-25 20:10:09 +05:30
mergify[bot]
ef3d444a60 fix: rewrite item rate calculation (backport #56315)
Co-authored-by: Harsh Patadia <harsh@Harshs-MacBook-Air.local>
Co-authored-by: Sagar Vora <16315650+sagarvora@users.noreply.github.com>
Co-authored-by: Smit Vora <mailsmitvora@gmail.com>
2026-06-25 09:50:50 +00:00
Mihir Kandoi
a9a371e4a4 Merge pull request #56433 from aerele/backport-56376
fix: skip over-allowance qty validation for non-stock items (backport #56335)
2026-06-24 20:03:15 +05:30
mergify[bot]
e3958ad7bb fix: precision issue causing COGS in inter transfer PR (backport #56420) (#56425)
fix: precision issue causing COGS in inter transfer PR (#56420)

(cherry picked from commit 9b0e1b61f2)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2026-06-24 18:30:32 +05:30
pandiyan
bc313dc09d fix: skip qty over-allowance check for non-stock items only 2026-06-24 18:12:42 +05:30
mergify[bot]
f5d05b969b fix: update round off account functions to accept document context for regional overrides (backport #55758) (#55771)
Co-authored-by: Lakshit Jain <ljain112@gmail.com>
fix: update round off account functions to accept document context for regional overrides (#55758)
2026-06-22 12:30:09 +00:00
Mihir Kandoi
3df7a28476 fix: party specific item doesnt work if there are 2 suppliers with same item
(cherry picked from commit 98f5116a09)
2026-06-22 09:27:40 +00:00