Commit Graph

58585 Commits

Author SHA1 Message Date
Mihir Kandoi
feec193d7d Merge pull request #57536 from mihir-kandoi/backport-bom-creator-update-cost-v16
fix(manufacturing): update cost of BOMs created via BOM Creator (backport #57532)
2026-07-28 13:06:27 +05:30
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
Mihir Kandoi
f1a0a5e1bf fix(manufacturing): update cost of BOMs created via BOM Creator
`calculate_rm_cost` skipped rate refresh whenever `bom_creator` was set,
so neither the Update Cost button nor the BOM Update Tool could ever
refresh those BOMs. Every BOM in a multi-level tree carries the field, so
whole trees stayed frozen at their creation rates.

The guard replaced the removed `rm_cost_as_per == "Manual"` check in
0b63dbf, on the assumption that BOM Creator rows hold manual rates. They
do not: BOM Creator recomputes every row from `rm_cost_as_per` on save.
2026-07-28 12:49:21 +05:30
Mihir Kandoi
7eb0eb77aa Merge pull request #57529 from frappe/mergify/bp/version-16-hotfix/pr-57521
fix(manufacturing): sum semi-FG qty across split job cards (backport #57521)
2026-07-28 12:47:43 +05:30
Mihir Kandoi
ca15a14666 test: import make_job_card from work_order module on v16 2026-07-28 12:34:50 +05:30
Mihir Kandoi
afbe1f7e53 Merge pull request #57530 from frappe/mergify/bp/version-16-hotfix/pr-57528
fix(manufacturing): scope BOM Creator tree children to the parent row (backport #57528)
2026-07-28 12:30:24 +05:30
Mihir Kandoi
339bb0b4ea fix(manufacturing): scope BOM Creator tree children to the parent row
The BOM Creator tree identified a node by the parent's item code
(fg_item) instead of the specific BOM Creator Item row, so every
occurrence of a repeated sub-assembly shared one child set: expanding
any one of them listed the raw materials of all of them, and deleting
one wiped the raw materials of its siblings.

Key the tree on fg_reference_id and make the node value the row name,
matching the framework convention that a tree node's value is its
docname. Item code now travels as its own field for the label and for
the fg_item argument sent back on add/convert.

Fixes #57311

(cherry picked from commit b37152752f)
2026-07-28 06:49:59 +00:00
Diptanil Saha
fe6534b888 refactor(postgres): port point_of_sale get_items to the query builder (partial backport #56153) (#57527)
Co-authored-by: Mihir Kandoi <kandoimihir@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-28 12:17:20 +05:30
Mihir Kandoi
ebc8482310 fix(manufacturing): exclude corrective job cards from semi-FG aggregate
(cherry picked from commit bde118e7cf)
2026-07-28 06:44:37 +00:00
Mihir Kandoi
c411b8e471 fix(manufacturing): sum semi-FG qty across split job cards
update_semi_finished_good_details assigned the current job card's
manufactured_qty to Work Order.produced_qty instead of accumulating it,
so a second job card on the same operation overwrote the first. Nothing
corrected it afterwards because StatusService.update_work_order_qty
returns early for track_semi_finished_goods work orders, leaving the
work order stuck below its planned qty with no way to progress.

Aggregate manufactured_qty and completed_qty over the operation's
submitted job cards instead.

(cherry picked from commit 5548f0726a)
2026-07-28 06:44:37 +00:00
Mihir Kandoi
06ba783267 Merge pull request #57523 from aerele/backport-56561-version-16-hotfix
fix: use company currency instead of global default in report (backpo…
2026-07-28 12:13:00 +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
Mihir Kandoi
c7ffe822f1 Merge pull request #57517 from frappe/mergify/bp/version-16-hotfix/pr-57493
fix: stop storing raw title template on subcontracting orders (backport #57493)
2026-07-28 11:09:03 +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
pandiyan
0863c1e05c fix: stop storing raw title template on subcontracting orders
subcontracting order and subcontracting inward order carry a hidden
title field defaulting to "{supplier_name}" / "{customer_name}", while
their title_field points at supplier_name / customer_name. document.
set_title_field() substitutes the template only when title_field is
"title", so every record stores the placeholder verbatim.

drop the dead default and hidden flags, move title into the other info
tab to match purchase order, and add a patch to repair existing rows.

(cherry picked from commit 5008e6126f)
2026-07-28 05:12:49 +00:00
Shllokkk
39d5fd84db fix: update operating cost when propagating workstation hour rate to routing (#57504) 2026-07-28 10:26:47 +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
mergify[bot]
f9b3e42dcd fix(quotation): carry forward communications from opportunity (backport #57507) (#57509)
Co-authored-by: Diptanil Saha <diptanil@frappe.io>
2026-07-27 18:14:11 +00:00
mergify[bot]
59efe7299a fix(stock): narrow legacy serial ledger lookup by item (backport #57499) (#57506)
fix(stock): narrow legacy serial ledger lookup by item (#57499)

Filter legacy Stock Ledger Entry lookups by item code so the existing
item and warehouse index can reduce rows scanned during serial valuation.

(cherry picked from commit 425191e57e)

Co-authored-by: Sudharsanan Ashok <135326972+Sudharsanan11@users.noreply.github.com>
2026-07-27 22:10:00 +05:30
mergify[bot]
3ea19d8eb1 fix(crm): clarify the reason why an opportunity cannot be declared as lost (backport #57495) (#57498)
Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com>
2026-07-27 17:01:21 +02:00
ruthra kumar
1f9c4bc933 Merge pull request #57484 from ruthra-kumar/fix_flaky_err_test
fix(test): flaky test in exchange rate revaluation
2026-07-27 17:09:32 +05:30
ruthra kumar
484ff8e349 fix(test): flaky test in exchange rate revaluation
- remove redundant setup on system settings
2026-07-27 16:57:09 +05:30
mergify[bot]
ad9870acc1 fix(crm): align Opportunity status checks with Quotation statuses (backport #57489) (#57491)
Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com>
2026-07-27 12:22:35 +02:00
Mihir Kandoi
8925585895 Merge pull request #57481 from frappe/mergify/bp/version-16-hotfix/pr-57463
fix(subcontracting): release raw-material reservation when closing a subcontracting order (backport #57463)
2026-07-27 15:01:03 +05:30
Mihir Kandoi
8d511c9b71 Merge pull request #57487 from frappe/mergify/bp/version-16-hotfix/pr-57485
fix: pool batch slot values on every run, not only when negative (backport #57485)
2026-07-27 14:04:17 +05:30
Mihir Kandoi
85925680ac test: assert batch pooling preserves the group total on a repeating rate
(cherry picked from commit 545262c5d4)
2026-07-27 08:24:15 +00:00
Mihir Kandoi
5763378ee1 fix: pool batch slot values on every run, not only when negative
A batch is one valuation pool, so any per-slot value difference within a
batch is stale detail from the report's own age slots, not real valuation.
The rebalance only ran when consumption had already driven a slot negative,
so a batch whose receipts landed at different rates kept a skewed split
across age buckets (one bucket free, another double-priced) while the total
stayed correct.

Drop the negative-slot precondition and always spread a batch's pooled value
over its slots in proportion to qty. Redistribution preserves group totals,
so buckets still sum to Stock Balance; only the split across ages changes.

(cherry picked from commit cedaaa3a00)
2026-07-27 08:24:15 +00:00
Lakshit Jain
c3eac77ee1 Merge pull request #56952 from frappe/mergify/bp/version-16-hotfix/pr-54855
refactor(financial-report): fix row transformation for growth calculations (backport #54855)
2026-07-27 13:31:55 +05:30
Sudharsanan11
008c3b145d test(subcontracting): cover reservation release on closing a subcontracting order
close a partially-received sco with a reserve warehouse and assert the
raw-material reservation is released and projected qty recovers.

(cherry picked from commit e4b8065a69)
2026-07-27 13:01:24 +05:30
Sudharsanan11
ee75fac9d7 fix(subcontracting): release raw-material reservation when closing a subcontracting order
the bin reserved-qty recalc filtered out closed purchase orders but not
closed subcontracting orders, so closing a partially-received sco kept the
reservation for the unreceived qty and left projected qty understated.
apply the same closed-status filter to the subcontracting order path.

(cherry picked from commit db91a79d31)

# Conflicts:
#	erpnext/stock/doctype/bin/bin.py
2026-07-27 13:01:24 +05:30
ruthra kumar
220d005cc2 Merge pull request #57478 from frappe/mergify/bp/version-16-hotfix/pr-57476
refactor: configurable date in reverse ERR journals (backport #57476)
2026-07-27 12:34:16 +05:30
ruthra kumar
ed1a58aa2a ci: debugging 2026-07-27 12:23:33 +05:30
ruthra kumar
2fd1dbd23a refactor(test): manually submit reverse err journal
(cherry picked from commit 1a558ce641)

# Conflicts:
#	erpnext/accounts/doctype/exchange_rate_revaluation/test_exchange_rate_revaluation.py
2026-07-27 11:53:29 +05:30
ruthra kumar
68dcc96527 refactor: configurable date in reverse ERR journals
(cherry picked from commit 0be33e4132)
2026-07-27 06:11:10 +00:00
Shllokkk
708d889036 Merge pull request #57473 from frappe/mergify/bp/version-16-hotfix/pr-57443
fix: rename misleading filter labels in AR/AP reports (backport #57443)
2026-07-26 20:22:08 +05:30
Shllokkk
20e2728037 chore: resolve patches.txt conflict for backport 2026-07-26 19:21:01 +05:30
MochaMind
2359e1610a chore: update POT file (#57470) 2026-07-26 15:45:55 +02:00
Shllokkk
2e5fc38179 fix: migrate stored AR/AP ageing filter to renamed field
(cherry picked from commit f13cd00494)

# Conflicts:
#	erpnext/patches.txt
2026-07-26 11:47:26 +00:00
Shllokkk
6d856fa632 fix: rename misleading filter labels in AR/AP reports
(cherry picked from commit e99425b7c4)
2026-07-26 11:47:26 +00:00
Shllokkk
1802c75ed6 Merge pull request #57468 from frappe/mergify/bp/version-16-hotfix/pr-57466
fix: recalculate operating cost on hour rate change in routing (backport #57466)
2026-07-26 16:27:11 +05:30
Shllokkk
c182b4085b fix: recalculate operating cost on hour rate change in routing
(cherry picked from commit 598f6f0f4e)
2026-07-26 08:37:06 +00:00
mergify[bot]
a0af717234 fix: enable the 'Include Zero Stock Items' filter by default to show zero-stock items in the Stock Balance report (backport #57458) (#57460)
fix: enable the 'Include Zero Stock Items' filter by default to show zero-stock items in the Stock Balance report (#57458)

(cherry picked from commit 4e8f5de5cb)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2026-07-25 08:27:06 +05:30
Jatin3128
d3c5e866f0 feat: block sales invoice submit when customer overdue exceeds threshold (backport #57230, #57298) (#57438)
* feat: block sales invoice submit when customer overdue exceeds threshold (#57230)

* feat: block sales invoice submit when customer overdue exceeds threshold

Adds an opt-in, per-customer Overdue Billing Threshold. When enabled in
Accounts Settings, submitting a Sales Invoice is blocked if the customer's
overdue amount exceeds their threshold, unless the current user holds a
configured bypass role. Modeled on the existing credit limit feature.

- Accounts Settings (Credit Limits tab): enable toggle + bypass role.
- Per-customer threshold on the Customer Credit Limit table, shown only
  when the feature is enabled via a property setter (same mechanism as
  subscription / accounting dimension sections). Table relabeled to
  "Credit & Overdue Limits".
- Overdue is read live from the ledger via get_outstanding_invoices
  (payments already netted), summing Sales Invoices past their due date.
- Enforced in Sales Invoice on_submit, after the credit-limit check;
  returns are exempt.
- validate_credit_limit_on_change no longer trips when a row sets only
  the overdue threshold (credit_limit = 0).

Fixes #52960

* fix: compute overdue amount in company currency and format with fmt_money

get_customer_overdue_amount now sums GL Entry debit - credit grouped per
invoice, which is always booked in company currency, instead of using
get_outstanding_invoices which returns the receivable-account currency.
The threshold is in company currency, so the previous comparison could mix
currencies for customers with a foreign-currency receivable account. This
mirrors how get_customer_outstanding computes the figure for the existing
credit-limit check.

The blocking message now formats both amounts with fmt_money using the
company currency.

Adds a test asserting a 100 USD invoice at a conversion rate of 50 is
counted as 5000 in company currency.

* refactor: drop redundant threshold coercion and dead test cleanup

- Coerce the overdue threshold with flt() once when reading it, instead of
  calling flt() on it at each of the three use sites.
- Remove a no-op set_overdue_billing_threshold() call in the feature-disabled
  block (the threshold was already set to that value) and the trailing reset,
  which is dead since each test is rolled back.

No behaviour change.

* fix: compute overdue amount from payment terms, matching the Overdue status

The overdue amount keyed on Sales Invoice.due_date, which set_due_date() sets
to the LAST payment term. An invoice whose first term was past due and unpaid
was therefore counted as zero, even though ERPNext already shows it as Overdue
in the invoice list. The gate and the UI could disagree.

get_customer_overdue_amount now follows the same rule as is_overdue(): per
invoice, the amount that has fallen due (sum of payment schedule terms past
their due date) minus what has been paid, clamped to the outstanding balance.
Invoices without a schedule (POS, opening) still fall back to the invoice due
date, mirroring is_overdue()'s own guard.

The ledger stays the source of truth for what is unpaid: the outstanding per
invoice is still SUM(debit) - SUM(credit) from GL Entry. base_payment_amount is
always stored in company currency, so no currency conversion is needed and the
comparison against the threshold stays consistent.

Adds a test covering a two-term invoice: only the past-due term counts, and
paying it off clears the overdue amount.

* feat: honour the overdue billing threshold set on the customer group

The threshold lives on Customer Credit Limit, which is also rendered on
Customer Group. A threshold set there was stored but never evaluated, so the
configuration was a silent no-op.

get_overdue_billing_threshold now reads the customer's row and falls back to
its customer group, mirroring get_credit_limit. The group's
bypass_credit_limit_check is deliberately not consulted: it is labelled for the
credit limit check at sales order and is unrelated to overdue billing.

get_customer_group_details also dropped the threshold when copying group rows
onto a customer, because it copied a single hardcoded field per table. It now
copies a list of fields per table, so credit_limit and overdue_billing_threshold
both carry over.

* refactor: clearer labels for the overdue billing control (#57298)

refactor: clearer labels and messages, drop "threshold" wording

User-facing text only, no field or behaviour changes:

- Accounts Settings toggle label -> "Restrict Customer Over Billing".
- Bypass role label -> "Role Allowed to Bypass Over Billing Restriction".
- Customer Credit Limit field label -> "Overdue Limit".
- Rewrote the descriptions and the block message to match and to stop
  saying "threshold".

* fix: treat zero overdue limit as opt-out and isolate settings in test

get_overdue_billing_threshold treated an explicit 0 on the customer's credit
limit row as "not set" and fell back to the customer group. A customer could
not be exempted from the group restriction while keeping a credit limit row,
and every existing row defaults to 0, so enabling the feature on a group blocked
all its customers that had any credit limit row. Guard the group fallback on
"threshold is None" (no row for the company) instead of a falsy check, so an
explicit 0 acts as an opt-out.

test_overdue_billing_threshold_on_submit mutated the Accounts Settings singleton
without restoring it, so a failed assertion mid-test leaked
enable_overdue_billing_threshold and the bypass role into later tests that submit
sales invoices. Wrap the mutations in try/finally and restore the originals.

* fix: let a zero customer overdue limit inherit the group's limit

A 0 on the customer's credit limit row falls back to the customer group again;
only a non-zero value on the customer overrides the group. Reverts the earlier
opt-out interpretation and updates the fallback test to expect the group's limit.
2026-07-24 15:33:26 +05:30
Mihir Kandoi
2b8b6a09dd Merge pull request #57440 from frappe/mergify/bp/version-16-hotfix/pr-57435
fix(accounts): respect user permissions in party dashboard company list (backport #57435)
2026-07-24 15:12:35 +05:30
pandiyan
c79f2e45a8 fix: respect user permissions in party dashboard company list
use frappe.get_list instead of frappe.get_all in get_dashboard_info so
the company list honors user permissions. previously, a party with
invoices across multiple companies would raise "User don't have
permissions to select/read this account" for users restricted to a
subset of companies, since get_party_account was called for companies
the user could not access.

fixes frappe/erpnext#57428

(cherry picked from commit 903c87bcaa)
2026-07-24 09:30:41 +00:00
Mihir Kandoi
ab4b5abb91 Merge pull request #57420 from aerele/backport-57412-customer-pick-list-v16
fix: map pick list customer to delivery note when no sales order
2026-07-24 14:58:23 +05:30
pandiyan
3f6501b4ff fix: map pick list customer to delivery note when no sales order
backport of #57412
2026-07-24 11:12:17 +05:30
Mihir Kandoi
2206e9fe2a Merge pull request #57415 from frappe/mergify/bp/version-16-hotfix/pr-57413
fix: typeerror in get_batches_by_oldest for mixed batch expiry (backport #57413)
2026-07-23 18:38:47 +05:30
pandiyan
bbe7580c9d fix: typeerror in get_batches_by_oldest for mixed batch expiry
sort on (expiry is none, expiry) so a null expiry_date is never
order-compared against a datetime.date, which raised typeerror in
python 3 when a warehouse held both dated and never-expiring batches.

(cherry picked from commit 62c9f8ee3e)
2026-07-23 12:53:51 +00:00
Mihir Kandoi
ef21a9ba9b Merge pull request #57250 from frappe/mergify/bp/version-16-hotfix/pr-57245 2026-07-23 16:25:43 +05:30