Skip to content

chore: release v16 - #57548

Merged
diptanilsaha merged 79 commits into
version-16from
version-16-hotfix
Jul 28, 2026
Merged

chore: release v16#57548
diptanilsaha merged 79 commits into
version-16from
version-16-hotfix

Conversation

@frappe-pr-bot

Copy link
Copy Markdown
Collaborator

Automated weekly release.

Abdeali099 and others added 30 commits July 8, 2026 10:44
…ion-v16

fix: get reserved batch qty precision from settings (v16)
set_route_options_for_new_doc lived in TransactionController, so doctypes
extending StockController directly (Stock Reconciliation, Stock Entry) missed
the Batch/SABB prefill or duplicated it locally. Move it to StockController
and call it from onload_post_render so all descendants inherit it.

- Batch quick entry from Stock Reconciliation items now prefills Item
- SABB route options unified: warehouse || s_warehouse || t_warehouse,
  so transaction doctypes now also prefill warehouse
- Stock Entry's duplicate handler removed; its onload_post_render now
  calls super

(cherry picked from commit 551559e)
…-57361

refactor: move new-doc route options to StockController (backport #57361)
…57359)

* fix: respect selected BOM when creating work order for variant item

* fix: add type hints to make_work_order
…an issue especially same posting datetime (backport #57380) (#57397)

* fix: Incorrect creation time at the time cancelling an entry causing an issue especially same posting datetime  (#57380)

* fix: shift same-timestamp sibling SLEs when cancelling an entry

update_qty_in_future_sle compared against the reversal SLE's own
creation and skipped same-posting_datetime siblings on cancel, leaving
their qty_after_transaction stale and causing false negative stock
errors.

* fix: revert update_qty_in_future_sle cancel tie-break, it double-counted

(cherry picked from commit 8c0ec3c)

# Conflicts:
#	erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py

* chore: fix conflicts

Fix test case for cancelling stock ledger entries with the same timestamp to ensure correct behavior.

* chore: fix conflicts

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
…llback (backport #57355) (#57385)

feat: make Shipping Rule Cost Center optional with company default fallback (#57355)

feat(shipping-rule): make cost center optional with company default fallback

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 a47f258)

Co-authored-by: Jatin3128 <140256508+Jatin3128@users.noreply.github.com>
A batch is one valuation pool, so consumption is valued at the pooled
rate while slots may carry stale intra-batch detail (e.g. units
reconciled at zero and later merged). Consuming such a slot leaves a
negative value on positive qty. Spread the pool value across the
batch's slots when that happens; non-batchwise slots pool per
warehouse.
…ol-rebalance-v16

fix: rebalance batch slot values at the pooled rate when driven negative (backport #57403)
…-57400

fix: guard against missing is_your_company_address custom field on ad… (backport #57400)
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 62c9f8e)
…-57413

fix: typeerror in get_batches_by_oldest for mixed batch expiry (backport #57413)
The mt940 library exposes ``transaction_reference`` from the :20: tag,
which is the statement-level reference and identical for every
transaction in a statement. The bank-statement-to-CSV conversion was
using it verbatim, so every imported row ended up with the same
reference, making reconciliation impossible.

Read the per-transaction reference from ``customer_reference`` on the
:61: tag instead. Handle two edge cases:

- **Overflow >16 chars.** When a bank emits a single-line :61: whose
  reference exceeds 16 characters, the mt940 regex splits the tail into
  ``extra_details``. Gate the rejoin to cases where
  ``customer_reference`` is exactly at the 16-char MT940 cap; below
  that, ``extra_details`` is genuine supplementary information and must
  not be appended.
- **``NONREF`` sentinel.** The MT940 standard marker for "no customer
  reference". Check it against the un-concatenated value so that a
  ``NONREF`` customer reference with populated ``extra_details`` still
  falls back to ``bank_reference`` instead of returning a junk
  ``NONREFsomething`` value.

Also switch the Description column to ``transaction_details`` (the :86:
tag content) so rows carry their real narrative instead of the mostly
empty :61: supplementary field.

(cherry picked from commit 551d709)
…st-v16

fix: map pick list customer to delivery note when no sales order
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 #57428

(cherry picked from commit 903c87b)
…-57435

fix(accounts): respect user permissions in party dashboard company list (backport #57435)
…old (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.
…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 4e8f5de)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
…-57466

fix: recalculate operating cost on hour rate change in routing (backport #57466)
mihir-kandoi and others added 12 commits July 28, 2026 06:44
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 5548f07)
… (partial backport #56153) (#57527)

Co-authored-by: Mihir Kandoi <kandoimihir@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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 b371527)
…-57528

fix(manufacturing): scope BOM Creator tree children to the parent row (backport #57528)
…-57521

fix(manufacturing): sum semi-FG qty across split job cards (backport #57521)
`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.
* fix: skip stock expense gl entries for non stock items

(cherry picked from commit 747f4df)

* test: use a leaf expense account for the service item invoice
…te-cost-v16

fix(manufacturing): update cost of BOMs created via BOM Creator (backport #57532)
Default WIP, Finished Goods and Scrap Warehouse fields on Company listed
warehouses of every company. Filter them by the current company and
exclude group warehouses, matching the other warehouse fields.

(cherry picked from commit 632113c)

# Conflicts:
#	erpnext/setup/doctype/company/company.js
…-57540

fix(setup): scope manufacturing warehouse filters to company (backport #57540)
@github-actions github-actions Bot added skip-release-notes This PR should not be mentioned in the release notes accounts buying stock labels Jul 28, 2026
@mergify

mergify Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Tick the box to add this pull request to the merge queue (same as @mergifyio queue).

  • Queue this pull request

khushi8112 and others added 8 commits July 28, 2026 18:00
…-57382

fix: map MT940 per-transaction reference from :61: customer_reference (backport #57382)
(cherry picked from commit fa75aa0)

# Conflicts:
#	erpnext/stock/doctype/item/item.json
#	erpnext/stock/doctype/item/item.py
…57551)

Co-authored-by: Diptanil Saha <diptanil@frappe.io>
…Plan (backport #57553) (#57554)

fix(manufacturing): fall back to UOM Conversion Factor in Production Plan

Production Plan read the conversion factor straight off the item's own
UOM child table, so an item with a purchase UOM but no matching row threw
"UOM Conversion factor not found" while Stock Entry silently resolved it
from the item's variant template or the UOM Conversion Factor doctype.
Resolve it the same way, and keep returning None when nothing is
configured anywhere so the missing-setup error still fires.
Co-authored-by: Krishna Pramod Shirsath <91021227+krishna-254@users.noreply.github.com>
Co-authored-by: diptanilsaha <diptanil@frappe.io>
…-57566

fix(item): correct description on deferred revenue/expense (backport #57566)
@github-actions

Copy link
Copy Markdown
Template string changes (50 added, 15 removed, 0 corrected across 1 file(s))

erpnext/locale/main.pot

Status Previous Current
added empty % Complete must be between 0 and 100
added empty 'Verification Link Expiry Duration' must be between 15 to 60 minutes.
added empty A verified appointment cannot be moved back to 'Unverified' status.
added empty Action for Expired Unverified Appointments
removed Actual qty in stock empty
added empty Advance Booking Days is mandatory for Appointment Scheduling.
removed Agent Details empty
added empty An appointment booked through the portal can only be opened via email verification.
added empty Appointment Booking Portal Settings
added empty Appointment can only be scheduled up to {0} day(s) in advance.
added empty Appointment cannot be scheduled for a past time.
added empty Appointment cannot be scheduled on a holiday.
added empty Appointment Confirmed
added empty Appointment has been closed. Please book the appointment again.
added empty Appointment is already verified.
added empty Appointment must be scheduled within the available slot timings.
added empty Appointment Scheduling
added empty Appointment Scheduling needs to be enabled for Appointment Booking through portal.
removed Appointment was created. But no lead was found. Please check the email to confirm empty
added empty Appointments created manually cannot have 'Unverified' status.
removed Bin Qty Recalculated empty
added empty Bin Values Recalculated
added empty Block a new Sales Invoice when the customer's overdue amount exceeds the Overdue Limit set on the customer.
added empty Created through Portal
added empty Credit & Overdue Limits
added empty Delete Permanently
removed Delivered empty
removed Email verification failed. empty
added empty Email Verified
added empty Enable Appointment Booking Through Portal
added empty Holiday List - {0} is not valid for current date.
added empty In Minutes (min: 15 mins, max: 60 mins)
added empty Mark as Closed
added empty New Sales Invoices are blocked when the customer's overdue amount exceeds this. Requires 'Restrict Customer Over Billing' in Accounts Settings.
added empty No availability of slots are found. Please add on Appointment Booking Settings.
added empty Overdue Limit
added empty Overdue Limit Crossed
added empty Overdue Limit crossed for customer {0}. Overdue amount {1} exceeds the allowed limit {2}.
removed Owner empty
added empty Please add a valid Holiday List on Appointment Booking Settings.
added empty Please check your email to confirm the appointment.
added empty Please fill up the Availability of Slots table to enable Appointment Scheduling.
added empty Please select a Holiday List to enable Appointment Scheduling.
removed Projected qty empty
removed Recalculate Bin Qty empty
added empty Recalculate Values
removed Reserved for manufacturing empty
removed Reserved for sale empty
removed Reserved for sub contracting empty
added empty Restrict Customer Over Billing
added empty Role Allowed to Bypass Over Billing Restriction
removed Success Settings empty
added empty The account type of {0} cannot be changed from {1} because stock ledger entries exist against it.
added empty This email was sent from {0}
added empty This link is valid for {0} minutes
added empty This verification link is invalid. Please book the appointment again.
removed Transactions are blocked or warned when outstanding balance exceeds this amount. empty
added empty Transactions are blocked when the outstanding balance exceeds the credit limit. When Restrict Customer Over Billing is enabled, new invoices are also blocked when the customer's overdue amount exceeds the Overdue Limit.
added empty Users with this role can still submit invoices for customers who have crossed their Overdue Limit.
removed Variants empty
added empty Verification Link Expiry Duration
added empty Verification link has expired.
added empty Verification Token
added empty We look forward to meeting you
added empty Your email has been verified and your appointment has been confirmed for {0}

@diptanilsaha
diptanilsaha merged commit eaf95e5 into version-16 Jul 28, 2026
37 of 40 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

accounts buying skip-release-notes This PR should not be mentioned in the release notes stock

Projects

None yet

Development

Successfully merging this pull request may close these issues.