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.
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.
Purchase Order, Sales Order and Subcontracting Order point title_field at
the party name field, so Document.set_title_field() never rendered their
title template and every new record stored the placeholder verbatim. On
Purchase Order the field is also mandatory, so the junk value is guaranteed.
Drop the dead defaults (and Purchase Order's reqd, which would otherwise
make an always-empty field mandatory) and backfill the affected rows.
* 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 8c0ec3c179)
# Conflicts:
# erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py
* chore: fix conflicts
Fix test cases related to stock ledger entry cancellations and ensure correct handling of same timestamp entries.
* test: use named item in test_cancel_shifts_same_timestamp_delivery_notes
* chore: fix typo
---------
Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
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>
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)
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)
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
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.
fixesfrappe/erpnext#57428
(cherry picked from commit 903c87bcaa)
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)
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.
On cancel, update_entries_after replays every live SLE at the voucher's
posting datetime, but get_previous_sle_of_current_voucher seeded the
replay with the reversal SLE's creation, which resolves to the bucket's
own closing row. The bucket's net qty got double-counted into every
same-datetime row, so later submissions passed negative stock validation
against inflated balances, and the queued repost then rewrote correct
values with allow_negative_stock forced on, silently creating negative
stock. Backports the missing guard from eca71dce54.
Stock Balance builds stock ageing by passing its own SLE rows into
FIFOSlots, whose gates read row.has_batch_no and row.has_serial_no.
The query never selected has_batch_no at all, and read has_serial_no
from the SLE column, which is unset on rows predating v15's bundle
migration (no backfill patch exists). With the flags falsy, incoming
batch/serial stock was queued as plain qty slots while outgoing was
consumed batch/serial-wise, so the shapes never consume each other,
and bundle-based rows resolved no batch details, letting the plain
consume path overwrite batch slots in place (flt(batch_no) reads as
qty 0). Besides wrong ageing figures, sorting the resulting queue
crashed with TypeError: '<' not supported between 'int' and
'datetime.date'.
Select both flags from Item, matching Stock Ageing's own query. Only
this report is affected; develop dropped the sle_entries pass-in in
#44489.
get_single_value inside _revalue_reconciled_batch_slots runs while
rows stream through the unbuffered cursor on MariaDB, killing the
active iterator. Resolve it once in generate() with the other
prefetches.
stock_value_difference / qty equals the new batch rate only when the
reco entry carries the entire batch, as the split out/in reco SLEs and
batches reconciled from zero do. Partial direct-batch_no entries mix a
qty delta with existing stock, so their slots keep prior values.
Plain items need no such guard: the valuation engine collapses the
FIFO stack to qty_after * valuation_rate on every reconciliation, so
rescaling remaining slots at the reco rate matches the ledger. Lock
that with a test.
Batch items take the batch-slot path, which mirrors the same value
arithmetic: the reco's incoming entry dumps the revaluation remainder
on one slot. Rescale each reconciled batch's slots at its post-reco
rate (stock_value_difference / qty of the incoming bundle entry).
A reconciliation's stock_value_difference includes the revaluation of
stock already in the FIFO queue, but the whole amount was attached to
the qty-delta slot while older slots kept pre-revaluation values. A
downward revaluation therefore produced negative bucket values in the
Stock Ageing report, and repeated recos let the queue total drift away
from Stock Balance.
Re-derive every slot value as qty * valuation_rate after processing a
reco SLE, since a reconciliation values the entire balance at its rate.
Covers both single-SLE recos and the zero-out/re-add pair that flows
through the transfer bucket.
Default accounting dimensions were applied from the `company` client
trigger, which reads dimension data fetched asynchronously in
`setup_dimension_filters`. When the trigger fired before that fetch
returned, new documents were left without their default dimensions, and
Sales Order never called `update_dimension` at all.
- Apply defaults from the fetch callback in dimension_tree_filter.js so
they no longer depend on `company`-trigger timing. This fixes the race
for Sales Invoice, Purchase Invoice and Payment Entry, and populates
defaults on new Sales Orders.
- Add a `company()` override on SalesOrderController so the default is
re-applied when the company changes, matching the sibling doctypes.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Stock Summary's sort selector only offered 5 of Bin's 10 qty fields; add
the rest (ordered, requested, planned, reserved for production plan,
reserved stock) and extend get_data's or_filters so bins whose only
nonzero qty is one of the new fields show up when sorted by it. Sort
labels now mirror Bin field labels.
Stock Projected Qty report had a column for every Bin qty field except
reserved_stock; add it.
(cherry picked from commit 59c0c15c2e)
The custom print template formatted debit/credit amounts with
format_currency() without passing a currency, so it fell back to the
company/system default currency (e.g. INR) instead of the selected bank
account's currency. The on-screen report already formats correctly via
the column's account_currency option.
Pass each row's account_currency to format_currency() so the printed/PDF
output matches the on-screen currency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
update_item_rates passed price_not_uom_dependent, a key
get_price_list_rate_for never reads, and omitted conversion_factor, so a
stock-UOM price was never converted to the row UOM. The function's
(historically misnamed) price_list_uom_dependant ctx key carries the
Price List's price_not_uom_dependent value: truthy returns the found
rate as-is, falsy multiplies by conversion_factor.
Also guard on_update with is_new(): has_value_changed returns True when
there is no doc_before_save, so every first save re-wrote item rates.
* fix: consider min order qty in the purchase/transfer flow of production plan (backport #57204)
The transfer flow ignored Consider Minimum Order Qty twice: the JS
handler force-reset the checkbox before fetching items, and the
purchase remainder left after allocating transfers from other
warehouses was never raised to min_order_qty (the check runs on the
total requirement before the split).
Drop the JS reset and apply min order qty to the purchase remainder,
in stock UOM before the purchase UOM conversion.
* test: do not set ignore_existing_ordered_qty; v15 gates the transfer split on it being unset
- allow new rows on scan when pick manually is enabled, since only
then are scanned rows not subject to being overridden by
set_item_locations on save
- stop capping picked qty at the default demand qty (1) for rows
added by the scanner itself, so repeat scans of the same barcode
keep incrementing the row instead of failing with "maximum
quantity scanned"
- ignore barcode uom when matching an existing row if new rows
aren't allowed, since there's no alternate-uom row to fall back to
(cherry picked from commit 3ece4a615d)
* refactor: rename execute_synced_report to execute_snapshot_report
Match the framework rename of the standard report entry point in the
trial balance, P&L, balance sheet, and general ledger reports.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
(cherry picked from commit ba7b6a47c5)
* refactor: rename feature toggle in report master
(cherry picked from commit 981e90e4da)
# Conflicts:
# erpnext/accounts/report/accounts_payable/accounts_payable.json
# erpnext/accounts/report/accounts_receivable/accounts_receivable.json
# erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.json
# erpnext/accounts/report/trial_balance/trial_balance.json
---------
Co-authored-by: ruthra kumar <ruthra@erpnext.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Match the framework rename of the standard report entry point in the
trial balance, P&L, balance sheet, and general ledger reports.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
(cherry picked from commit ba7b6a47c5)
* refactor: reports on duckdb
(cherry picked from commit adb768505a)
* feat(trial-balance): implement execute_duckdb with full parity to normal report
Replaces the placeholder stub with 8 focused functions that mirror the
normal execute() flow using parameterized DuckDB SQL queries: account
fetch, period GL entries, opening balances (with Period Closing Voucher
path), and all filters (cost center, project, finance book, accounting
dimensions). Reuses existing pure-Python processing functions unchanged.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit b1c8e2cb5c)
* refactor(trial-balance): execute_duckdb only reads GL Entry from duckdb
Replaces the previous over-engineered stub with 7 short functions.
Account data, Account Closing Balance, and all metadata come from
frappe.db as normal; only tabGL Entry is read from the duckdb_conn.
Reuses get_opening_balance() for Account Closing Balance unchanged,
reuses all downstream compute helpers (calculate_values, prepare_data,
etc.) unchanged.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit 55862f98f4)
* refactor: maintain sync dependency in report master
(cherry picked from commit 5c536b8ad1)
# Conflicts:
# erpnext/accounts/report/accounts_payable/accounts_payable.json
# erpnext/accounts/report/accounts_receivable/accounts_receivable.json
# erpnext/accounts/report/general_ledger/general_ledger.json
# erpnext/accounts/report/trial_balance/trial_balance.json
* refactor: DB agnostic method names
(cherry picked from commit f40cd41801)
* feat(general-ledger): implement execute_synced_report with full parity to normal report
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit 6b4895bcc9)
# Conflicts:
# erpnext/accounts/report/general_ledger/general_ledger.json
* feat(balance-sheet): implement execute_synced_report with full parity to normal report
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit bb19540816)
# Conflicts:
# erpnext/accounts/report/balance_sheet/balance_sheet.json
* feat(profit-and-loss): implement execute_synced_report with full parity to normal report
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit 6a93baacf0)
# Conflicts:
# erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.json
* refactor: synced reports should be enabled on sites based on requirements
(cherry picked from commit 963bbc8729)
# Conflicts:
# erpnext/accounts/report/general_ledger/general_ledger.json
* chore: resolve conflicts
---------
Co-authored-by: ruthra kumar <ruthra@erpnext.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
fix(stock): correct stock ageing value for moving average and lifo items (#56693)
* fix(stock): recompute moving average item slots
* test(stock): add test to validate the stock value of moving average items
* fix(stock): support lifo valuation in stock ageing report
lifo items were aged as fifo (oldest consumed first), so the report kept the
newest lots on hand and reported the wrong stock value and average age. prefetch
each item's valuation method (it can't be resolved mid-stream without breaking the
unbuffered cursor) and consume from the tail for lifo items. also reuse that shared
lookup in the moving average revaluation pass. scoped to plain items; batch, serial
and same-voucher repack legs stay on fifo.
* test(stock): add test for lifo consumption in stock ageing report
(cherry picked from commit 9cb6610b9e)
# Conflicts:
# erpnext/stock/report/stock_ageing/stock_ageing.py
Co-authored-by: Sudharsanan Ashok <135326972+Sudharsanan11@users.noreply.github.com>
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)
Pick List has no posting_date/posting_time fields, so creating or updating a
Serial and Batch Bundle from a Pick List row crashed with
"TypeError: combine() argument 1 must be datetime.date, not None". Fall back
to today/now when the parent voucher doesn't carry its own posting date.
Fixes#56951
The whitelisted add_serial_batch_ledgers only converted child_row into an
attribute-accessible frappe._dict when it arrived as a JSON string, and doc's
type hint only allowed Document | str. Frappe's JSON API delivers both as
plain dicts (see frappe.app.make_form_dict, which parses the request body
with orjson and only wraps the top-level dict, not nested values), so every
real request was rejected before the handler body ever ran: first with a
FrappeTypeError on doc, and once that's fixed, with an AttributeError on
child_row.serial_and_batch_bundle. parse_json already wraps a plain dict in
frappe._dict (and leaves a real Document instance untouched), so routing
child_row through it unconditionally fixes both.
(cherry picked from commit 8b3caeb578)
* fix: for purchases do voucher based reposting (#56601)
(cherry picked from commit 5523c15ab8)
* chore: fix type hints
* chore: fix test case
* chore: fix linters issue
---------
Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
get_item_warehouse_projected_qty() called frappe.get_doc("Warehouse", ...)
inside the per-bin loop to walk up the warehouse hierarchy, re-fetching the
same parent warehouses over and over on sites with nested warehouses. Preload
the warehouse-to-parent mapping with a single query and walk it in-memory
instead, cutting the DB round-trips from O(bins * hierarchy depth) to one
query.
(cherry picked from commit 6beb3d2509)
Work Order allowed saving with a Planned End Date earlier than the Planned
Start Date without any validation. Add a validate_dates check that throws
when the planned end date precedes the planned start date.
(cherry picked from commit 2ec780cb35)
Backport of frappe/erpnext#56800 (via #56836/#57001). When a Pick List
transfers only some of the required raw materials, the min-fraction
rule keeps material_transferred_for_manufacturing at 0, leaving the
Work Order stuck at "Not Started" even though material is already in
WIP. Treat any submitted pick-list-linked Material Transfer stock
entry as evidence the order has started.
The routing field handler only fetched operations from the routing when
the operations table was empty. When a new BOM version is created (via
"New Version"), operations are copied from the source BOM, so selecting a
different routing left the old operations in place - both in the form and
after saving.
Drop the `!frm.doc.operations.length` guard from the routing handler so
that (re)selecting a routing always refetches the operations from that
routing via the existing get_routing method, which clears and repopulates
the operations table.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
(cherry picked from commit 758a837de4)
update_current_stock() in delivery_note.py used to call
frappe.db.get_value("Bin", ...) separately for every row in items and
every row in packed_items - so a delivery note with 200 items and 200
packed items made 400 separate database calls on every save.
now it groups item codes by warehouse and fetches bin data with one
query per distinct warehouse, then assigns actual_qty/projected_qty to
each row from that result - same values as before, far fewer database
calls, and no cross-product over-fetch across warehouses.
(cherry picked from commit 5da878d25f)
Add regression coverage for the new abbreviation-rename propagation:
a simple item_code rename, item_name derived from a template whose
item_name differs from its item_code, and a manually customized
item_name getting rebuilt rather than left stale.
(cherry picked from commit e718a70b26)
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)
Pick Lists transferred before this feature have transferred_qty = 0 and
their Stock Entry rows carry no pick_list_item link, so the new
is_fully_transferred check would never fire and, with the old
duplicate-entry guard removed, they could be transferred again. Set
transferred_qty = picked_qty for non-Delivery submitted pick lists that
already have a linked Stock Entry so they stay completed and locked.
(cherry picked from commit 903d78cc43)
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.
(cherry picked from commit af495ed253)
# Conflicts:
# erpnext/stock/doctype/pick_list/pick_list.json
# erpnext/stock/doctype/stock_entry/stock_entry.py
Process Period Closing Voucher and Process Period Closing Voucher
Details are trackers how the jobs are processed. Keep transactions on
them very short.
(cherry picked from commit 7e4045e828)
- Update using child table name to avoid scanning whole table, which
eventually leads to mariadb 1020 (REPEATABLE READ).
- Avoid race condition in final summarization
(cherry picked from commit ff6881764b)
the existing test_cost_center_for_manufacture only checks a raw material
row against an item-level override, which is set independently of the
":company" default guard and never exercised the bug.
(cherry picked from commit a168bb7ea4)
the ":company" default pre-filled every row before set_default_cost_center()
ran, so its "if not row.cost_center" guard was always false and the
project/item group/brand priority chain in get_default_cost_center()
never ran.
(cherry picked from commit edfa0a7a1d)
# Conflicts:
# erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json
- restore mutated SLE after test via addCleanup
- explicit return False in has_difference
- comment the fifo_stock_diff guard for non-queue predecessors
(cherry picked from commit ef5f47fafd)
- 'Show Incorrect Entries' always returned an empty result (regression
from #43619); now returns entries from one row before the first
incorrect one
- FIFO queue columns were computed for serialized/batched SLEs that
don't maintain a stock queue, showing false differences; left empty
for such rows
- compare value/valuation differences at currency precision, qty at
float precision
(cherry picked from commit 94ab09e4a3)
# Conflicts:
# erpnext/stock/report/stock_ledger_invariant_check/test_stock_ledger_invariant_check.py
Backport of #41024. Fixed-asset items now resolve expense_account from
the asset category (CWIP account when CWIP accounting is enabled,
otherwise the fixed asset account) for Purchase Receipt, Purchase Order
and Material Request, matching v16 behavior. v15 previously did this only
for Purchase Invoice.
When a reconciled voucher (Payment Entry / Journal Entry / Purchase
Invoice / Sales Invoice) is cancelled, amended and resubmitted, the
stale clearance date was carried into the amended draft because the
framework ignores `no_copy` while amending.
Add a shared `before_insert` hook on AccountsController that clears
`clearance_date` (top-level field and Sales Invoice `payments` rows)
on amendment. Reconciliation still sets the value post-submit via
`frappe.db.set_value`, which bypasses this path.
Manual backport of #55947 to version-15-hotfix (Mergify's auto-backport
#55972 committed conflict markers; this replaces it).
An incoming SLE without resolvable serial/batch details hit the
negative-head branch in _compute_incoming_stock even when the head was
a batch slot, because flt() on the batch number string returns 0.0.
_add_to_negative_fifo_head then crashed with
"TypeError: can only concatenate str (not 'float') to str".
Guard the branch with is_qty_slot, mirroring the existing check in
_add_transfer_slot_to_fifo_queue.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit c47a95a4d2)
* fix: validate reverse GL entries on current date under immutable ledger (#56709)
* fix: validate reverse GL entries on current date under immutable ledger
When Immutable Ledger is enabled, the reverse GL entry is posted on the
current date, but the closed-period checks in make_reverse_gl_entries still
validate against the original (backdated) posting date. This blocks cancelling
a backdated voucher, such as a suspense Journal Entry for a migrated NPA loan,
with a books-closed error even though the reverse entry lands in an open period.
Validate both check_freezing_date and validate_against_pcv against the current
date when Immutable Ledger is enabled. When it is disabled, behaviour is
unchanged.
Follow-up to #55268.
* test: reset frozen till date after reverse entry test
The freeze date set on the company was not reset, so it leaked into the next
test which posts entries in that period. Reset it in a finally block.
* fix: prefer explicit posting_date under immutable ledger
Prefer the posting_date argument before frappe.form_dict and getdate, at both
the validation and the GL entry site, so an explicit date passed by the caller
is honoured and validation still matches the posted date.
(cherry picked from commit cab1b129c0)
# Conflicts:
# erpnext/accounts/general_ledger.py
* fix: resolved conflicts
Removed outdated check for freezing date in general ledger validation.
* fix: Update check_freezing_date function call parameters
* fix: accounts_frozen_till_date to acc_frozen_upto
* test: acc_frozen_upto setting in test_period_closing_voucher
---------
Co-authored-by: Nihantra C. Patel <141945075+Nihantra-Patel@users.noreply.github.com>
fix(stock): value batch/serial return from ledger when original receipt has no bundle (#56631)
* fix(stock): value batch/serial return from ledger when original receipt has no bundle
* test(stock): add test to validate the valuation of serial/batch for return when original receipt has no bundle
(cherry picked from commit 6184c057db)
Co-authored-by: Sudharsanan Ashok <135326972+Sudharsanan11@users.noreply.github.com>
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
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>
The v15 backport (#55776) of #55774 dropped the stock_balance.py changes.
A separate backport left an inline version that sorts/filters the FIFO queue
by itemgetter(1) *before* normalizing, so for batchwise valuation slots
itemgetter(1) reads the count flag instead of the posting date. The queue is
then ordered wrong and earliest_age/latest_age come out swapped.
Extract get_stock_ageing_data, which normalizes before sorting/filtering so
itemgetter(1) is always the posting date, and add the regression test.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
fix: do not allow closing the accounting period for future dates (#56551)
(cherry picked from commit 5e60e4faa7)
Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
The Quality Inspection Parameter DocType did not have `allow_rename`
enabled, so the "Rename" action was hidden from the form's menu
(the 3-dots / ⋮ options). Since the DocType is auto-named from the
`parameter` field (`autoname: field:parameter`), users had no way to
correct or change a parameter's name once created.
Enable `allow_rename` so users can rename a Quality Inspection
Parameter from the form menu.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
(cherry picked from commit adfef48a65)
# Conflicts:
# erpnext/stock/doctype/quality_inspection_parameter/quality_inspection_parameter.json
fix: precision issue causing COGS in inter transfer PR (#56420)
(cherry picked from commit 9b0e1b61f2)
Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
Adds a `pcv_job_timeout` Int field (default 3600s) to Accounts Settings
so admins can tune the enqueue timeout for PCV background jobs without
a code change. All three `frappe.enqueue` calls in
`process_period_closing_voucher.py` now read this value at runtime.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit 13b6c4a165)
# Conflicts:
# erpnext/accounts/doctype/accounts_settings/accounts_settings.json
The item_code field in the Job Card Item child table was optional,
allowing job cards to be saved without a raw material item linked.
Set reqd=1 in the JSON and update the Python type annotation accordingly.
(cherry picked from commit d7e9a97f8a)
Resolved Mergify backport conflicts (PR #55548 / backport of #55484) by
taking the final upstream state: fiscal-year posting_date Between filter
with calendar-year fallback, Timespan filter removed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
fix: clear stale payment rows on non-POS returns so they don't surface in bank reconciliation (#55903)
(cherry picked from commit 322d4dff25)
# Conflicts:
# erpnext/accounts/doctype/sales_invoice/sales_invoice.py
# erpnext/accounts/doctype/sales_invoice/services/pos.py
Co-authored-by: Jatin3128 <140256508+Jatin3128@users.noreply.github.com>
* refactor: posting datetime for SABB (backport #49710 + #50248)
Backport of #49710 "refactor: posting datetime for SABB" to
version-15-hotfix, including the regression fix#50248
"fix: missed refactoring code".
Replaces Serial and Batch Bundle's `posting_date`/`posting_time` with a
single `posting_datetime` field and updates all readers/writers; adds a
patch to populate `posting_datetime` from the linked Stock Ledger Entry
and drop the now-unused single-column indexes.
Adapted to version-15-hotfix where the surrounding stock code had already
moved to `posting_datetime` (SLE) and diverged from develop.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* chore: fix conflicts
* chore: fixed formatting
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
(cherry picked from commit 98caefea88)
* refactor: posting datetime for SABB (backport #49710 + #50248)
Backport of #49710 "refactor: posting datetime for SABB" to
version-15-hotfix, including the regression fix#50248
"fix: missed refactoring code".
Replaces Serial and Batch Bundle's `posting_date`/`posting_time` with a
single `posting_datetime` field and updates all readers/writers; adds a
patch to populate `posting_datetime` from the linked Stock Ledger Entry
and drop the now-unused single-column indexes.
Adapted to version-15-hotfix where the surrounding stock code had already
moved to `posting_datetime` (SLE) and diverged from develop.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* chore: fix conflicts
* chore: fixed formatting
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* fix: updated role based permission for terms and conditions doctype (#55674)
(cherry picked from commit 0ba2961103)
# Conflicts:
# erpnext/setup/doctype/terms_and_conditions/terms_and_conditions.json
* chore: resolve conflicts
---------
Co-authored-by: Diptanil Saha <diptanil@frappe.io>
Backport of #55830 to version-15.
Allow creating a Quality Inspection from Stock Entries of any purpose
(not just Manufacture). check_item_quality_inspection now returns the
items for Stock Entry, and the inspection type is resolved as "Incoming"
for Manufacture / Material Receipt and "Outgoing" otherwise.
Ref: #70945
Display the actual company name in bold within the confirmation dialog
label so users immediately know which company they must type to confirm,
reducing the risk of accidental data loss.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit 87d26a2d67)
fix(bom): fetch routing operations when routing is selected
frm.doc.operations is always an array in Frappe, so !frm.doc.operations
was always false (empty array [] is truthy in JS), causing get_routing()
to never fire when a Routing is selected on a BOM with no existing
operations.
Changed the guard to !frm.doc.operations.length so the fetch triggers
correctly when the operations table is empty.
Also wired the same fetch into the with_operations handler so that
enabling the checkbox after a Routing is already set will populate
operations without requiring the user to re-select the Routing.
Co-authored-by: Umair Sayed <umairsayed@Umairs-MacBook-Air-2.local>
(cherry picked from commit 9249fa89aa)
# Conflicts:
# erpnext/manufacturing/doctype/bom/bom.js
Stock Ageing iterates stock ledger entries through an unbuffered
(streaming) cursor. _get_batchwise_valuation() lazily queried
Batch.use_batchwise_valuation from inside that loop whenever a row
carried the legacy batch_no field, and the nested query invalidated
the active streaming result set — crashing the report (or silently
dropping the remaining rows, depending on the driver version).
Resolve the valuation flags in a single query before entering the
unbuffered cursor block; the lazy lookup now only serves callers that
pass stock ledger entries in directly, where no streaming is active.
Fixes https://github.com/frappe/erpnext/issues/55786
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit 060a5c4eeb)
Rename single-letter query-builder aliases (C, DT) to readable names
(customer, sales) and add report tests covering the column contract,
validation guards, and the days-since-last-order threshold.
(cherry picked from commit 8f15dd4d5d)
"link_filters":"[[\"Asset\",\"status\",\"not in\",[\"Work In Progress\",\"Capitalized\",\"Fully Depreciated\",\"Sold\",\"Scrapped\",\"Cancelled\",null]]]",
"link_filters":"[[\"Asset\",\"status\",\"not in\",[\"Work In Progress\",\"Capitalized\",\"Sold\",\"Scrapped\",\"Cancelled\",null]]]",
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.