Proposal: Periodic Costing (month-end weighted average) — feedback welcome before PR

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

2 Likes

We have already implemented this for periodic accounting user.

Thanks @Dipen.Gala — yes, we’re aware of #47512 and PR #48126, and it’s good to see the periodic-accounting direction getting investment in v16.

Just to make sure we’re not talking past each other: the layer we’re proposing is different from what the Periodic Accounting Entry delivers, and the two are complementary.

Periodic Accounting Entry (#48126) solves GL booking for companies with perpetual inventory disabled. It produces Journal Entries that book purchases and closing stock into the books.

What we’re proposing is the costing method itself, for companies that must settle issues at a month-end weighted average. It produces a weighted-average unit cost for each item and warehouse, plus a Stock Reconciliation that re-values the stock ledger.

A Journal Entry can move the total stock GL balance to an expected number, but in a weighted-average audit (Chinese GAAP, Kingdee/UFIDA practice), the number that has to be right is the per-item weighted-average rate. Today, nothing in ERPNext computes that rate.

The two features could even work together: once weighted-average rates are computed and posted, the balance fetched by a periodic accounting entry becomes method-correct.

So the question to maintainers stands, slightly sharpened: is there room for the valuation layer (periodic costing) in core alongside the periodic accounting work, or would you rather keep this as an app?