ERPNext Daily Posting Engine¶
URL: https://mkdocs.justinsforge.com/memory/general/reference_erpnext_daily_post/
name: reference_erpnext_daily_post description: forge_erpnext_daily_post.py, idempotent transaction-level finance.db to ERPNext posting; timer 07:20/13:20; state db + ledger map under data/finance/ type: reference
THE ongoing books pipeline (since 2026-06-10). One Journal Entry per finance.db business
transaction, posted on the real txn date; mid-month P&L is always live in ERPNext.
Replaces the retired one-shot monthly loader forge_erpnext_post_books.py (frozen
migration record; never re-run with --apply, it is not idempotent).
SOURCE CUTOVER 2026-06-17: now reads lifeos, not finance.db¶
- The poster reads its slice from the lifeos finance schema (source of truth), set via
FINANCE_SOURCE=lifeosinforge-erpnext-post.service. Default in code is stillfinance-db(fallback). lifeos is kept live-current by a replication step appended toforge-finance-sync.service(idempotent finance.db->lifeosforge_finance_migrate_to_lifeos.py --apply, after categorize/recurring/holdings/alerts). - Idempotency bridge: lifeos rows carry the original finance.db rowid in
legacy_findb_id(finance.transactions + finance.accounts, migrations 0028/0029, populated by the migrate script). The lifeos read path presents those ids, so JE tagsFINDB-<id>, the ledger map, and the state db stay byte-identical to the old finance.db path. Verified at flip: slice 3346=3346 0 diffs; status/post-dry-run/post--apply/verify identical between sources. - finance.db remains the write lake (SimpleFIN sync + categorize + recurring write there); lifeos mirrors it each sync. Full writer-repoint + finance.db retirement is the later phase.
How it works¶
- Reads the business-slice contract (accounts.scope in WIEB/JWVR/NOVA/SIP/GOC, source
simplefin/bankcsv, superseded=0) from lifeos (see cutover above; finance.db is the
fallback path). Coordination with the finances session via
data/finance/COORDINATION.md. - Classification comes from
forge_books_import.gl_account()(vendor_map.json + code rules +GL_ENTITY_OVERRIDESfor the audit F1/F2 fixes: WIEB rent to 5490, Gusto fee to 5420). - Idempotency: state db
data/finance/erpnext_post_state.db(txn_id primary key, statuses historical/posted/held/cancelled/released) AND each JE carriescheque_no=FINDB-<txn_id>, so ERPNext itself is queryable for duplicates. - Per-account contra ledgers from
data/finance/erpnext_ledger_map.json: checkings to 1205, business cards to globally-numbered 2431-2435, card payments + intra transfers through per-company 2439 clearing (nets to zero when both legs arrive;sweepreclasses aged unpaired legs to 3700 after review). - SEAM 2026-06-08: 3,321 txns seeded status=historical (covered by the migration's
monthly JEs). New txns dated on/before the seam are HELD + notified, never
auto-posted (
release/mark-historicalto resolve). - Superseded flips auto-cancel the posted JE next run; the surviving twin posts fresh.
Operations¶
| Action | Command |
|---|---|
| Quick state | python3 scripts/forge_erpnext_daily_post.py status |
| Post manually | ... post (dry-run) then ... post --apply |
| Consistency check | ... verify (state vs ERPNext + clearing pairing) |
| Release a held txn | ... release --txn-id N / ... mark-historical --txn-id N |
| Clearing sweep | ... sweep then ... sweep --apply |
| Timer | systemctl --user status forge-erpnext-post.timer (07:20/13:20, after finance-sync) |
| Log | logs/erpnext-daily-post.log; failures notify via forge_notify.sh warning |
One-time bootstrap commands already run (do NOT re-run): setup-ledgers --apply,
seed-historical, reclass-seam --apply, opening-corrections --apply.
Balance-sheet tie (established 2026-06-10)¶
Every cash/card ledger ties to real statements to the penny as of the seam: card splits via JEs ACC-JV-2026-00088..90, prior-period opening corrections (RE vs 1205) via ACC-JV-2026-00096..99 (JWVR +865.50, NOVA +8,589.51 = pre-2025 card 1042 debt, GOC -444.53, SIP +276.20; WEOP exact 0). ACC-JV-2026-00091..95 are CANCELLED (first correction attempt used a wrong as-of-seam GL filter; the month-28-dated historical JEs made it undercount; documented in AUDIT-INDEPENDENT-2026-06-10.md).
Full audit + findings (rent-as-draws F1, Gusto-fee F2, JE-5 drift F3, JWVR 1715 stray
F4): /mnt/workspace/Forge/Finance Migration Summer 2026/AUDIT-INDEPENDENT-2026-06-10.md.
Pending Justin review: 2026 YTD rent reclass JE ($5,880 Dr 5490 / Cr 3700, WEOP) and
Gusto-fee reclass ($351.78 Dr 5420 / Cr 2320, WEOP); rules already fixed go-forward.
Settlement gross-up companion (Task C, posted 2026-06-10)¶
forge_erpnext_settlement_grossup.py restates platform revenue to gross (fees 5330,
shipping 5320, sales tax 2315, 1320 Platform Payouts in Transit), keyed
FINDB-GROSSUP-*; cash-basis true-up keeps net P&L = cash. Inputs: consolidated TikTok
CSVs (built by forge_tiktok_statements_consolidate.py from Seller Center xlsx chunks)
+ live Shopify Payments API. It can cancel/re-create FY2025 PCVs. Monthly cadence:
re-run plan --apply after consolidating new TikTok exports (current month always
skipped while accruing); FY2026 needs the year-end true-up. Tie-outs:
SETTLEMENT-GROSSUP-TIEOUT-2026-06-10.md + 1099K-RECONCILIATION-2026-06-10.md in the
Finance Migration workspace folder.
[Fable 5, erpnext-finalize 2026-06-10]