Commit Graph

55728 Commits

Author SHA1 Message Date
Mihir Kandoi
8131af9405 fix: zero-rate repost fallback could still read sibling SLE
When the in-memory running rate is zero, the fallback went through
get_incoming_rate, whose previous-SLE lookup matches the same
posting_datetime and can land on a sibling line of the voucher being
replayed. Replace it with get_previous_sle_of_current_voucher excluding
the current voucher, keeping the get_valuation_rate chain when no
previous entry exists. get_incoming_rate is no longer used in this
module.
2026-08-08 11:12:41 +05:30
Mihir Kandoi
9c8d5ac8a5 test: repost of multi-line moving average return is idempotent
Reposting a return that removes most of the stock across several lines
of the same item must keep every line at the running average and produce
identical results on a second repost. Before the fix the first repost
already drifted, seeding each line from a sibling row of the same
voucher.
2026-08-08 11:12:41 +05:30
Mihir Kandoi
5738cfce79 fix: repost read stale sibling SLE rate for moving average returns
During repost, a return line with recalculate_rate resolved its moving
average rate through get_incoming_rate -> get_previous_sle, which matches
posting_datetime <= and orders by creation desc. For a multi-line return
of the same item, every line shares one posting_datetime, so the query
landed on a sibling line of the same voucher whose stored valuation_rate
was still the previous repost run's output, not the rate before the
voucher.

Each repost run therefore re-seeded the voucher from its own prior
output. The error gain per run is (qty returned at the stale rate) /
(qty remaining after the return), so whenever a return removes most of
the stock the loop diverges instead of converging, alternating sign and
growing until stock_value overflows decimal(21,9) and the repost dies
with 'Out of range value for column stock_value'.

Use the in-memory running valuation rate that update_entries_after
already tracks for the warehouse at this point in the repost. It is the
authoritative pre-entry state, is immune to sibling rows, and makes the
repost idempotent. The database lookup is kept only as a fallback for a
zero in-memory rate, preserving the existing zero-rate fallback chain.
2026-08-08 11:12:41 +05:30
Mihir Kandoi
b4e8aef2f8 Merge pull request #57721 from frappe/mergify/bp/version-15-hotfix/pr-57645
fix(purchase): reject purchase returns where every item has zero quan… (backport #57645)
2026-08-03 13:05:22 +05:30
Mihir Kandoi
198468aa5a test(purchase): fit the backported test to version-15-hotfix
Drop test_sales_return_validates_against_original: it came in with the new
file rather than with the change being backported, covers a raw-SQL to
query-builder conversion that only exists on develop, and imports
erpnext.stock.doctype.delivery_note.mapper, a module this branch does not
have. Base the remaining tests on FrappeTestCase, since ERPNextTestSuite
does not exist here either.
2026-08-03 12:42:14 +05:30
R-Jayaraman
070a7cfb91 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:16:38 +00:00
R-Jayaraman
8676add875 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:16:37 +00:00
Mihir Kandoi
0f6c6d4df7 Merge pull request #57700 from frappe/mergify/bp/version-15-hotfix/pr-57699
fix: prevent duplicate shipping charges without cost center (backport #57699)
2026-08-02 12:45:29 +05:30
Mihir Kandoi
70da05edb7 fix: resolve version-15 backport conflict 2026-08-02 12:26:50 +05:30
Mihir Kandoi
724eb1aac4 Merge pull request #57696 from frappe/mergify/bp/version-15-hotfix/pr-57674
fix: preserve UOM conversion factor precision in transactions (backport #57674)
2026-08-02 12:23:29 +05:30
Mihir Kandoi
42a2674341 chore: remove shipping rule comments
(cherry picked from commit 106ecd7120)
2026-08-02 06:48:47 +00:00
Mihir Kandoi
a6dff3fc47 fix: prevent duplicate shipping charges without cost center
(cherry picked from commit a4134af30b)

# Conflicts:
#	erpnext/selling/doctype/sales_order/test_sales_order.py
2026-08-02 06:48:47 +00:00
Mihir Kandoi
00df8652e3 fix: resolve version 15 backport conflict 2026-08-02 12:03:47 +05:30
Mihir Kandoi
5a5e20e167 test: fractional conversion factor survives Material Request to Purchase Order
Fails before the fix with 0.45 != 0.453592292 on a site with Float
Precision 2, and 0.454 on the default of 3.

(cherry picked from commit f4d70c2d60)
2026-08-02 06:25:36 +00:00
Mihir Kandoi
4373e295de 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)

# Conflicts:
#	erpnext/controllers/taxes_and_totals.py
2026-08-02 06:25:36 +00:00
Diptanil Saha
8bef78afda Merge pull request #57691 from frappe/mergify/bp/version-15-hotfix/pr-57201
fix: permission checks on various whitelisted methods (backport #57201)
2026-08-01 15:45:53 +05:30
Mihir Kandoi
5b47607bc6 Merge pull request #57665 from frappe/mergify/bp/version-15-hotfix/pr-57658
fix: respect quantity precision in material transfer validation (backport #57658)
2026-08-01 15:34:27 +05:30
diptanilsaha
c38c9d5d9b fix(payment_request): added permission checks on resend_payment_email
(cherry picked from commit 0659bd7049)
2026-08-01 15:27:05 +05:30
diptanilsaha
9cd5997500 fix(item_variant): added permission checks on enqueue_multiple_variant_creation
(cherry picked from commit 3b0cbc972e)
2026-08-01 15:26:59 +05:30
diptanilsaha
338fff20db fix(assets): add permission checks on whitelisted methods on asset_capitalization
(cherry picked from commit 09d721d1be)
2026-08-01 15:25:28 +05:30
Sudharsanan11
f9381cc8f9 test: cover material transfer quantity precision
(cherry picked from commit 59bb56aa8d)
2026-08-01 14:37:32 +05:30
Sudharsanan11
a5ed3a5945 fix: respect quantity precision in material transfer validation
(cherry picked from commit eb969a5866)
2026-08-01 14:37:32 +05:30
mergify[bot]
cf42c52530 fix(quotation): carry forward communications from opportunity at after_insert (backport #57639) (#57642)
Co-authored-by: Diptanil Saha <diptanil@frappe.io>
2026-07-31 20:56:17 +05:30
mergify[bot]
42d53783bb fix(plant_floor): add missing perm check on get_stock_summary (backport #57667) (#57669)
Co-authored-by: Diptanil Saha <diptanil@frappe.io>
2026-07-31 15:26:15 +00:00
Mihir Kandoi
276d023946 Merge pull request #57654 from aerele/backport-57567-version-15-hotfix
fix: guard against None row in get_stock_balance_for (backport #57567)
2026-07-31 18:56:31 +05:30
pandiyan
72f293f131 fix: guard against None row in get_stock_balance_for (backport #57567)
get_stock_balance_for() takes row=None by default, but the batch-tracked
branch dereferenced it unconditionally while the two neighbouring row
accesses already guard. Calling it with a batch_no and no row raised
AttributeError: 'NoneType' object has no attribute 'use_serial_batch_fields'.

semgrep's missing-argument-type-hint rule matches the whole function body,
so touching any line inside it re-fingerprints the pre-existing untyped
arguments and reports them as introduced by this PR. Silenced with
nosemgrep instead of annotating: on a whitelisted method the hints are
enforced at runtime by pydantic, which is not a risk worth taking on v15.
2026-07-31 18:08:25 +05:30
mergify[bot]
b826b7c3e6 fix: use payment entry posting date for received amount exchange rate (backport #57660) (#57662)
Co-authored-by: Diptanil Saha <diptanil@frappe.io>
2026-07-31 12:35:48 +00:00
mergify[bot]
b2918b8bb3 feat: make Shipping Rule Cost Center optional with company default fallback (backport #57355) (#57402)
feat: make Shipping Rule Cost Center optional with company default fallback (#57355)

Cost Center on Shipping Rule is no longer mandatory. When left blank, the
applied shipping tax row falls back to the company default cost center,
avoiding the 'Cost Center is required for Profit and Loss account' error on
submit. The rule's project is also applied to the tax row.

(cherry picked from commit a47f25896b)

Co-authored-by: Jatin3128 <jatinsarna8@gmail.com>
2026-07-31 14:51:43 +05:30
Mihir Kandoi
f727f863bb Merge pull request #57020 from frappe/mergify/bp/version-15-hotfix/pr-57015
fix(stock): pick list serial batch posting date (backport #57015)
2026-07-31 13:40:10 +05:30
mergify[bot]
bb36a4fd08 feat: auto-fill subscription accounting dimensions from plan with item fallback (backport #57615) (#57621)
* feat: auto-fill subscription accounting dimensions from plan with item fallback (#57615)

When a plan is selected in the Subscription's Plans table, the Subscription's
accounting dimensions (cost center and any custom dimensions) auto-fill from the
plan, falling back to the plan item's company default (selling cost center for a
Customer, buying for a Supplier). Only empty fields are filled. Stale async
responses are ignored so a quick re-pick of the plan can't be overwritten.

(cherry picked from commit 7febc28ed6)

# Conflicts:
#	erpnext/accounts/doctype/subscription/subscription.js
#	erpnext/accounts/doctype/subscription/subscription.py
#	erpnext/accounts/doctype/subscription/test_subscription.py

* fix: resolve backport merge conflicts for #57615

---------

Co-authored-by: Jatin3128 <140256508+Jatin3128@users.noreply.github.com>
Co-authored-by: Jatin3128 <jatinsarna8@gmail.com>
2026-07-31 12:38:58 +05:30
mergify[bot]
ebf5a462b3 fix: filter Accounts Receivable by invoice sales partner (backport #57628) (#57646)
fix: filter Accounts Receivable by invoice sales partner (#57628)

Filter Accounts Receivable and AR Summary on the Sales Invoice's own
sales_partner instead of the customer's default_sales_partner, and read
the Sales Partner column from the invoice. Returns are attributed to the
invoice they settle, matching how the Sales Person filter works.

(cherry picked from commit fd7765ac02)

Co-authored-by: Jatin3128 <140256508+Jatin3128@users.noreply.github.com>
2026-07-31 12:05:44 +05:30
Mihir Kandoi
bae02a6212 Merge pull request #57242 from frappe/mergify/bp/version-15-hotfix/pr-57223
fix(projects): include on hold status in project filters and reports (backport #57223)
2026-07-31 11:49:50 +05:30
Poovetha
54390bdeb9 fix(projects): add project filter
(cherry picked from commit 7248961568)
2026-07-31 11:09:53 +05:30
Poovetha
82850fb447 test(projects): add test to ensure on hold project retains status
(cherry picked from commit 79e5ccd370)
2026-07-31 11:09:53 +05:30
Poovetha
478426b436 fix(projects): include on hold status in project filters and reports
(cherry picked from commit 51a9fc0316)
2026-07-31 11:09:53 +05:30
ruthra kumar
83837868a0 Merge pull request #57640 from frappe/mergify/bp/version-15-hotfix/pr-57434
fix: update doc status in period closing voucher (backport #57434)
2026-07-31 10:57:12 +05:30
mergify[bot]
972a990b01 fix: do not fetch a random inventory account when multiple inventory accounts exist (backport #57626) (#57631)
* fix: do not fetch a random inventory account when multiple inventory accounts exist (#57626)

(cherry picked from commit 386a4ac1f0)

# Conflicts:
#	erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py

* chore: fix conflicts

Removed redundant test for valuation taxes in purchase receipt.

* fix: build warehouse account map only when perpetual inventory needs it

For asset purchase receipts or provisional accounting with perpetual
inventory disabled, GL entries do not use warehouse accounts. Building
the full warehouse account map in that case now throws when a company
has multiple inventory accounts and no default, breaking asset receipt
submission. Mirrors the gating on develop.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test: set default inventory account in valuation taxes LCV test

The conflict resolution kept the pre-backport copy of
test_valuation_taxes_lcv_repost_after_billing, which enables perpetual
inventory on _Test Company without configuring a default inventory
account. The test then failed on submit and leaked the perpetual
inventory flag, breaking every stock test that ran after it in the same
process. Restore the cherry-picked version from #57626.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-31 05:11:02 +00:00
nareshkannasln
310b9d4e65 fix: validate account frozen date
(cherry picked from commit b3c2ba5381)
2026-07-31 05:05:37 +00:00
mergify[bot]
68c24f3767 feat: status based bar colors in Work Order gantt view (backport #57634) (#57635)
feat: status based bar colors in Work Order gantt view (#57634)

(cherry picked from commit d59c5e36bc)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2026-07-31 09:59:07 +05:30
Mihir Kandoi
f2ec60b7a5 Merge pull request #57629 from frappe/mergify/bp/version-15-hotfix/pr-57616
fix: seed standard Item Groups under the existing tree root (backport #57616)
2026-07-30 19:46:00 +05:30
Mihir Kandoi
1602639a80 fix: resolve backport conflicts for version-15
install() holds the preset list inline on this branch, so the root is
resolved there instead of in get_preset_records. Dropping the preset-record
test with it -- there is no seam to call without running the whole installer.

The patch test is adapted to this branch: TestItem does not roll back between
tests, so it restores the original root name, and it passes parent_item_group
explicitly since ItemGroup.validate skips root-defaulting under
frappe.flags.in_test.
2026-07-30 19:22:29 +05:30
Mihir Kandoi
848335086c fix: seed standard Item Groups under the existing tree root
install_fixtures always inserted "All Item Groups" as a parentless group.
On a site where another app had already created the root, ItemGroup.validate
re-parented it, leaving a second group-root that held the standard groups
while the real root held everything else.

This is reproducible with the healthcare app on a non-English site: its
after_install seeds the root as _("All Item Groups"), so a pt-BR site gets
"Todos os Grupos de Itens" as the root before the setup wizard runs. The
split predates #57390 -- the old translated-name lookup resolved to the same
root and produced an identical tree.

Resolve the root once with get_root_of (falling back to the canonical English
name on fresh installs) and use it for the root record's exists-guard and the
standard groups' parent, matching Company.create_default_departments.

Patch merges an already-seeded "All Item Groups" into the root it sits under,
lifting its children and repointing every link.

Closes #57581

(cherry picked from commit e7088d8981)

# Conflicts:
#	erpnext/setup/doctype/item_group/test_item_group.py
#	erpnext/setup/setup_wizard/operations/install_fixtures.py
2026-07-30 13:41:45 +00:00
Shllokkk
9a596594da Merge pull request #57619 from Shllokkk/asset-manual-create-valuation-rate-v15
fix: source manually created asset value from valuation rate
2026-07-30 14:58:42 +05:30
Shllokkk
455d6d4ac1 fix: source manually created asset value from valuation rate 2026-07-30 14:31:54 +05:30
mergify[bot]
7cecff9fa4 fix: let Purchase Receipt cancel defer to Frappe's linked-document check (backport #57592) (#57602)
fix: let Purchase Receipt cancel defer to Frappe's linked-document check (#57592)

on_cancel pre-blocked cancellation with its own "Purchase Invoice is
already submitted" guard, duplicating the check Frappe already runs for any
submitted linked document. Drop the guard and the unused check_next_docstatus()
method it mirrored so the receipt defers to the framework: the Cancel All
Documents flow cancels the invoice first and then the receipt, and a direct
cancel is still rejected by Frappe's linked-document check.

Add a regression test that a direct cancel of a receipt with a submitted
invoice is rejected and rolls back, leaving no stray stock or GL entries.

(cherry picked from commit cfe18e8427)

# Conflicts:
#	erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
#	erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py

Co-authored-by: Jatin3128 <140256508+Jatin3128@users.noreply.github.com>
2026-07-30 12:41:53 +05:30
mergify[bot]
94d63ebb49 fix(stock): value batched packed-item returns from the original bundle (backport #57327) (#57510)
fix(stock): value batched packed-item returns from the original bundle  (#57327)

* fix(stock): value batched packed-item returns from the original bundle

when a return delivery note or sales invoice bundle is built via the
use_serial_batch_fields / sle-driven path, its voucher_detail_no keeps the
packed item instead of being remapped to the parent dn/si item. the return
valuation lookup then misses and the bundle values at zero, so the sle
stock_value_difference stays wrong even after a repost.

resolve the original dn/si item via the packed item's parent_detail_docname
when the direct lookup fails, so the return values from the original outward
bundle on both submit and repost.

* test(stock): cover batched packed-item return valuation on repost

(cherry picked from commit d37e905322)

Co-authored-by: Sudharsanan Ashok <135326972+Sudharsanan11@users.noreply.github.com>
2026-07-30 07:02:41 +00:00
mergify[bot]
ade3f791a4 fix(stock): keep manufactured item rate at zero when inputs are free (backport #57334) (#57512)
fix(stock): keep manufactured item rate at zero when inputs are free  (#57334)

* fix(stock): keep manufactured item rate at zero when inputs are free

when a finished item is produced from raw materials consumed at zero
valuation, the incoming rate fell back to the item's own valuation
rate (or BOM cost), valuing free inputs as output and inflating the fg
value on every production run.

add has_consumption_basis() to detect when the consumed cost is known
even if it is zero (consumed rows present, or a consumption entry
exists for the work order). when it is, skip the get_valuation_rate and
BOM-cost fallbacks so a real cost of zero is preserved.

* test(stock): cover manufacture rate for zero-valued raw materials

- manufacture from a free input keeps fg basic_rate and sle
  incoming_rate/stock_value_difference at zero even when the fg already
  carries a valuation in the target warehouse
- material consumption on with no consumption entry does not fall back
  to bom/price-list rate for free inputs
- zero-valued consumption entry keeps the manufacture entry's fg rate
  at zero

(cherry picked from commit 73224d3650)

Co-authored-by: Sudharsanan Ashok <135326972+Sudharsanan11@users.noreply.github.com>
2026-07-30 09:25:52 +05:30
mergify[bot]
967955a926 refactor(accounts): repost accounting ledger (backport #56442) (#57584)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Diptanil Saha <diptanil@frappe.io>
2026-07-29 15:23:30 +05:30
Krishna Pramod Shirsath
71b5f41556 Merge pull request #57589 from frappe/mergify/bp/version-15-hotfix/pr-57314
fix(italy): skip e-invoicing for opening invoices (backport #57314)
2026-07-29 13:44:08 +05:30
Krishna Shirsath
4f07e2503b fix(italy): skip e-invoicing for opening invoices
(cherry picked from commit f328018bfb)
2026-07-29 05:39:23 +00:00