* feat(stock): repost only GL entries from the value comparison report
Adds a "Create GL Reposting Entries" button to the Stock and Account Value
Comparison report, next to the existing "Create Reposting Entries" which is
unchanged. It queues Repost Item Valuation entries with
`repost_only_accounting_ledgers` set, so the General and Payment Ledger are
rebuilt for the selected vouchers while the stock ledgers and valuation rates
are left untouched. This is for the case where stock valuation is already
correct and only the accounting ledger has drifted, which avoids paying for a
full revaluation.
Rows of ledger type "GL Entry" are rejected: they have accounting entries but
no stock ledger entries to rebuild them from, so a GL-only repost would just
wipe their GL. The same restriction is enforced on Repost Item Valuation for
callers outside the report.
Repeated selections are deduplicated, and vouchers that already have a queued
or in-progress GL-only repost are skipped.
* feat(stock): bound GL reposting by a From Date, skip non-stock rows
* fix: batch the pending GL repost lookup and index it on existing sites
* perf: reduce memory consumption during reposting
The reposting queue introduced in #52152 keeps the complete future stock
ledger of every transitively dependent item-warehouse in a single deque.
Each `select *` row is ~3.5KB, so a repost spanning a million entries
needs several GB and gets OOM killed on smaller workers.
- Queue only the identity and sort keys of an entry, and fetch the full
row in batches of 500 just before it is processed
- Move `for update` off the bulk prefetch onto the batch, so millions of
rows are no longer locked for the whole duration of the repost
- Drop the process local document cache and message log at every
checkpoint, neither is evicted within a long running job
* fix: keep recent repost messages and log skipped entries
Trimming `frappe.local.message_log` to empty at every checkpoint discarded
warnings that the Repost Item Valuation failure handler reads back when
building the error log. Keep the most recent messages instead, which bounds
the growth just as well.
Also log when a queued entry is no longer active by the time its batch is
loaded, rather than skipping it silently.
* fix: skip reposts already covered by a Manufacture/Repack dependant repost
While reposting a raw material, the finished goods produced from it are
reposted as dependants, from the posting datetime of the manufacture entry
through to the end of their ledger. A repost queued separately for the same
finished good and warehouse at a later datetime therefore has nothing left to
do, but it was still picked up and walked the same entries again.
Track the item-warehouse combinations pulled in as dependants of a Manufacture
or Repack entry, and mark the redundant queued reposts as Skipped once the
dependants have been reposted. This runs per item being reposted, so the
finished good's queued repost is released without waiting for the whole raw
material repost to finish.
Only 'Item and Warehouse' reposts are skipped. A 'Transaction' repost spans
several item-warehouse combinations, so covering one says nothing about the
rest. Reposts starting before the manufacture entry still have work to do and
are left queued.
* fix: don't lock the whole repost queue prefetch
* test: repost covers every entry once across batches
feat: mark update_serial_batch_entries patch as never skippable (#59147)
(cherry picked from commit aebb160e76)
Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
* fix(stock): use stored posting_datetime for repost boundary
get_stock_ledger_entries re-derived posting_datetime from posting_date and
posting_time on every call, discarding the stored value its callers pass in.
when a row's stored posting_datetime differs from that pair, the replay window
is built from the wrong instant: the row falls outside the range filter and is
never recomputed, while get_previous_sle still selects it as the opening
balance and reuses its stale qty_after_transaction. every later entry inherits
the error, leaving bin qty adrift from the sum of its ledger.
derive the boundary only when the caller has not supplied one.
* fix(stock): match current voucher sle on stored posting_datetime
get_sle_against_current_voucher selected rows with an equality check against a
posting_datetime re-derived from posting_date and posting_time. a row whose
stored posting_datetime differs from that pair matches nothing, so reposting
the voucher silently processes zero entries and the row can never be corrected
through its own voucher.
read the timestamp from the stored row when the sle is known, and derive it
only as a fallback.
* test(stock): cover repost with diverged posting_datetime
add a repack scenario whose incoming entry stores a posting_datetime one
microsecond before its own posting_time. asserts the voucher lookup still
finds that entry, and that reposting replays it instead of reusing its stale
qty_after_transaction, which otherwise left bin qty at 115 against 615 of
recorded movements.
(cherry picked from commit 6cee9c330c)
# Conflicts:
# erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py
* fix: negative stock value for moving average item with mixed batchwise valuation
* chore: remove redundant docstring
* test: restore frappe flags in a finally block
* perf: speed up legacy serial no valuation lookup
* feat: use serial no wise valuation switch on item
* fix: clear stale valuation method cache on item update
* fix: force moving average only when stock transactions exist
* fix: correct serial no wise valuation field description
* fix: add type hints to whitelisted get_incoming_rate args
Rapid successive edits to Net Purchase Amount could fire overlapping
set_finance_book calls; if an older request's response arrived after a
newer one, it could overwrite Finance Books with values computed from
a stale amount. Now the callback only applies a response if the fields
it was based on still match the form's current values.
(cherry picked from commit 5a8126412a)
Previously, checking "Calculate Depreciation" (or picking the Item)
before typing in "Net Purchase Amount" left the Finance Books table
empty, because the depreciation schedule was only built at the moment
those fields already had values. Entering the amount afterward only
updated existing Finance Books rows, so an empty table stayed empty.
Now, entering the amount also builds Finance Books from scratch if it
was left empty, regardless of the order fields were filled in.
(cherry picked from commit 5d1ffa7fca)