Hi everyone,
We’d like to propose contributing a Periodic Costing feature to ERPNext, and we’d love feedback from maintainers and the community before we turn it into a PR. This is not a hypothetical design: everything described below has been running in production for several months as a private app at our company, a precision manufacturer in China, and we’d much rather contribute it upstream than maintain a private fork forever. We’re ready to license the contribution under GPLv3 (find us on GitHub as lgh-hub).
The problem
ERPNext values inventory perpetually: FIFO, Moving Average and LIFO (plus Standard Cost, recently added on develop) all settle a valuation rate at the moment each Stock Ledger Entry is posted. Many manufacturers — especially but not only those following Chinese GAAP — use a periodic method instead: the month-end one-time weighted average (月末一次加权平均法),
the default costing approach in systems like Kingdee and UFIDA:
unit cost = (opening value + inbound value of the month)
/ (opening qty + inbound qty of the month)
COGS and closing stock for the whole month are settled once, at period close. Today ERPNext offers no native path for this: the documented workaround for periodic inventory is manual month-end Journal Entries, which does not re-value the stock ledger and does not satisfy audits, that expect the weighted-average numbers themselves.
We could not find prior art for this in the repo history, the forum, or the Frappe Cloud marketplace — the gap seems real and general (any company that prices issues retroactively at month-end needs it, not only Chinese ones).
Why we do NOT propose a fourth `valuation_method` option
We considered adding “Monthly Weighted Average” next to FIFO / Moving Average / LIFO / Standard Cost, and concluded it’s the wrong shape: SLE valuation is computed incrementally at posting time (`stock_ledger.process_sle`), while a monthly weighted average is mathematically unknown. until the period closes. Forcing it into the enum would require synthesizing placeholder rates on every posting and re-valuing them later anyway — invasive across ~12 core files (`serial_and_batch_bundle`, returns, reposting, reports) for no clean result.
Proposed design
A standalone stock-module doctype, cooperating with Period Closing Voucher the same way
Stock Closing Entry does today (PR #57811) — which we see as the direct precedent for this shape:
1. Periodic Costing (new doctype, company + accounting period + status): computes the weighted-average rate per (item, warehouse) for the month by aggregating Stock Ledger Entries: opening balance + all inbound movements, with a fail-closed guard when the denominator is ~zero. Results stored in a child table for audit.
2. Posting the adjustment through a standard Stock Reconciliation (qty unchanged, valuation rate forced) — so the SLE, Bin and GL entries (under perpetual inventory) all flow through existing, well-tested machinery. The reconciliation is linked back to the Periodic Costing doc; a content digest detects drift between computation and submission.
3. Period-close choreography: PCV gains an optional validation (off by default) that the period’s Periodic Costing is completed and posted before the books are closed — mirroring how PCV already requires a fresh Stock Closing Entry. Backdated stock after closing stays frozen via the existing Stock Closing Entry gating.
4. Manufacturing extras we use in production (candidates for a follow-up PR): precise valuation of subcontracting receipts (finished-good value = Σ consumed raw qty × raw weighted average rate + processing fees apportioned from the PO), and idempotent re-runs guarded by row locks on the draft PCV.
Core changes to existing files would be minimal (~2–3: settings toggle, optional PCV check); everything else is additive under `erpnext/stock/doctype/periodic_costing/`.
What we’d bring
- A calculation engine that has run in production for multiple months and reproduces five months of accepted history with zero key-level differences (4,737 item × warehouse × period keys re-verified in a full month-close rehearsal, including GL round-trip checks).
- Server-side-first implementation, unittests written against the standard ERPNext test
utilities (`make_stock_entry` fixtures), ruff-clean, English UI strings via the translation
system, GPLv3 headers.
- We are prepared to carry the multi-round review effort and maintain the feature after merge.
Questions for maintainers
1. Is a Periodic Costing step (period-end adjustment, not a new valuation method) something you’d consider for core? Or is this better kept as a separate app / Frappe Cloud plugin?
2. If in principle yes: do you prefer the PCV integration as an opt-in validation on PCV
(as sketched) or looser — purely advisory, no PCV change at all in the first PR?
3. Any concerns about the Stock Reconciliation-based adjustment path (rate-only revaluation) being used systematically each month-end?
Happy to share a detailed technical design doc and sample outputs (with identifying item codes renamed) if there’s interest. Thanks!
— lgh-hub