* fix(stock): carry accounting dimensions from Landed Cost Voucher charges into GL entries
* feat(stock): add accounting dimension fields to Landed Cost Taxes and Charges
The charge row had no dimension fields, so a dimension marked mandatory for
Profit and Loss accounts could not be supplied anywhere on the voucher.
Add the accounting dimensions section, cost center and project, and register
the doctype in accounting_dimension_doctypes so custom dimension fields are
created on it. The section and column break are required for that hook to
place the generated fields correctly.
Cost center deliberately omits the ":Company" default used by Purchase Taxes
and Charges: this child table is also the additional costs table on Stock
Entry and Subcontracting Receipt, and auto-filling it there would change
existing postings.
* refactor(stock): group landed cost charges by expense account and dimensions
get_item_account_wise_lcv_entries keyed its inner map by expense account
alone, so two charge rows posting to the same account - whether in one voucher
or across vouchers - were merged. Amounts accumulated correctly but any
per-row context was lost to whichever row was seen first.
Key the grouping by (expense account, dimension values) and return a list of
charges per receipt item, each carrying its own dimensions, so rows that
differ only by dimension stay distinct.
Dimensions resolve from the charge row first, then the voucher item row.
Blanks are left blank so the GL composers can fall back to the receipt item
and receipt document as before.
* refactor(accounts): allow explicit accounting dimensions on add_gl_entry
get_gl_dict derives dimensions from the parent document and the item row, and
reads only custom dimensions off the item - never cost center or project.
Callers that need to set a dimension from some other source had no way to do
so except by building the args dict by hand.
Add a dimensions argument that is merged into the entry before get_gl_dict is
called, and thread it through the StockController and BaseGLComposer wrappers.
* fix(stock): carry landed cost charge dimensions onto the GL entries
Landed cost charges are posted into the receipt document's ledger, and their
expense account is a Profit and Loss account. Until now the entry took its
dimensions from the receipt item, which cannot know about a voucher created
after it was submitted, so a dimension mandatory for P&L accounts failed.
Take cost center, project and custom dimensions from the charge row, falling
back to the receipt item and receipt document when the row leaves them blank.
Only the leg posting to the charge account is affected; the reclass leg keeps
the item's dimensions so it still nets against the base item entry.
Also skip charges that prorate to zero, and hoist the landed cost lookup in
the Purchase Receipt composer out of the item loop - it was reloading every
voucher once per item.
* fix(stock): report missing mandatory dimensions on the Landed Cost Voucher row
Submitting a voucher re-makes the receipt document's GL entries, so a missing
mandatory dimension surfaced as a GL Entry error naming an account, raised
from the middle of update_landed_cost, with nothing pointing at the row that
caused it.
Check the charge rows during validate instead, against both the mandatory
for P&L / Balance Sheet flags and the per-account Accounting Dimension Filter,
and name the row, the dimension and the account in the message.
The check resolves values through the same fallback chain the GL composers
use, so it does not reject a voucher that would have posted successfully.
* test(stock): cover accounting dimensions on landed cost vouchers
Covers the charge row reaching the GL entry, cost center and project
overriding the receipt item, the blank row still falling back to it, and two
charge rows - and two vouchers - on the same expense account with different
dimensions staying separate entries.
Also covers the mandatory P&L dimension being satisfied from the charge row,
the missing one being reported on the voucher, dimensions surviving a repost,
and each dimension netting to zero on cancellation.
* refactor(lcv): apply custom dimension overrides via .update()
---------
Co-authored-by: nareshkannasln <nareshkannashanmugam@gmail.com>
Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
(cherry picked from commit 918e5a28db)
# Conflicts:
# erpnext/accounts/doctype/purchase_invoice/services/gl_composer.py
# erpnext/accounts/services/base_gl_composer.py
# erpnext/controllers/stock_controller.py
# erpnext/patches.txt
# erpnext/stock/doctype/landed_cost_taxes_and_charges/landed_cost_taxes_and_charges.json
# erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py
# erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py
# erpnext/stock/doctype/purchase_receipt/services/gl_composer.py
# erpnext/stock/doctype/stock_entry/services/gl_composer.py
# erpnext/subcontracting/doctype/subcontracting_receipt/services/gl_composer.py
* feat: validate purchase receipt exchange rate parity on purchase invoice (#58177)
(cherry picked from commit 70a8a2d0c5)
# Conflicts:
# erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
* chore: fix conflicts
Removed assertion for exchange rate discrepancy in purchase invoice test.
* test: fix backport of exchange rate difference test for non stock item
The conflict resolution left behind stale amount/discrepancy lookups
referencing a removed second item row (IndexError in CI and F841 ruff
failures). Align the test with the develop version: single non stock
item, PR at 80 / PI at 70, and assert no exchange gain/loss GL entry.
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>
* fix(subscription): don't reactivate a cancelled subscription
Backport of #57774 to version-15-hotfix.
set_subscription_status() unconditionally set status to Active once
there was no outstanding invoice, with no check for whether the
subscription had been intentionally cancelled. process()'s
cancel_at_period_end check compared posting_date against
getdate(self.end_date), and getdate(None) returns today, so an empty
end_date was silently treated as "cancel now" on every reprocess.
version-15-hotfix does not yet have the Payment Entry -> invoice ->
refresh_subscription_status() hook chain that #57761 reports (that
was added later), and the scheduler already excludes Cancelled
subscriptions, so the exact automatic repro in the issue does not
apply here. The underlying status logic is defective the same way
though, and reachable directly (e.g. any caller invoking the
whitelisted process()/set_subscription_status() on a cancelled
subscription), so fixing it here too rather than leaving the same
class of bug in place.
Related to #57761
* fix(test): avoid tripping the unrelated period-end cancel clause
The test backdated start_date to 2018-01-01, so by the time process()
ran, current_invoice_end was long past. That made the *other* half of
the cancel_at_period_end OR-condition (period end reached) true on
its own, so process() tried to cancel an already-cancelled
subscription and hit cancel_subscription()'s "already cancelled"
guard - unrelated to the empty end_date bug being tested.
Use nowdate() as start_date so current_invoice_end sits safely in the
future, isolating the assertion to the empty end_date guard. Also
drop the fragile intermediate "Unpaid" status assertion, which
wasn't part of what this test verifies.
* fix(subscription): don't let period rollover defeat cancel_at_period_end
process() can advance current_invoice_end to the next period (via
update_subscription_period(), when generating the current period's
invoice) before the cancel_at_period_end check further down runs. For
a subscription with no end_date, that check now compared posting_date
against the already-rolled-forward current_invoice_end, which is
always in the future, so cancel_at_period_end was silently never
honored.
Snapshot current_invoice_end before any rollover and use that in the
check instead, so it still targets the period that just ended.
Fixes the P1 flagged by Greptile review on this PR.
---------
Co-authored-by: test <test@test.com>
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>
* 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>
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>
* 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>
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). Two parts of the original PR are not
included: the Landed Cost Report does not exist on this branch, and the
trends report test files do not exist either.