zerp — System Overview

zerp (a.k.a. Zyncount) is a multi-tenant, multi-company ERP covering accounting, inventory, manufacturing, HR/payroll, projects, POS, CRM, and recruitment — delivered as a per-tenant NestJS GraphQL backend (zerp-be) plus a per-tenant Next.js admin (zerp-admin). This document set (zerp) is a rebuild-grade requirements capture of that system, organized by domain and flow.

This is the entry point. For the doc index see README. For how the apps are built see architecture; for the tenant model see multi-tenancy; for the module correspondence see module-map.


1. What zerp is

A double-entry accounting core with a full ERP built around it. Scale: ~80 modules / ~277k LOC across the two apps (~37 backend modules, ~45 admin modules). It is sold/operated per tenant; each tenant is a fully isolated installation that can itself run multiple companies and branches.

The product appears tuned for gold/jewellery trading businesses (gold-purity item types, a dormant "Wingold" legacy-ERP export, weight-based POS), on top of a general-purpose ERP foundation.

2. The recurring architectural idea: ledgers, not stored balances

Two of the system's three heaviest engines share one design principle — state is derived by aggregating an append-only ledger, never stored as a mutable running total:

  • Accounting — every financial event becomes balanced AccountTransaction rows (debit/credit legs). An account's balance is always Σ(debits) − Σ(credits) (by account type), never a stored field. Document headers (journal, contra, payment, invoice…) just group their legs. See finance/_overview.
  • Inventory — every inbound/outbound is one Stock row (IN/OUT). On-hand = Σ IN − Σ OUT per item per branch; there is no mutable "current quantity". See inventory/stock.
  • Manufacturing then sits on inventory (material consumption = Stock OUT, finished output = Stock IN) and posts WIP/cost to the GL. See manufacturing/_overview.

This makes movements auditable and reversible (delete a row → the derived total self-corrects).

3. The domains

Domain What it does Doc
Finance Double-entry GL: chart of accounts, journals, payments, contra, tax, notes, cashbook, trade AR/AP finance
Inventory Items/catalog, the stock ledger, purchases, sales, transfers, adjustments, costing (FIFO/AVCO) inventory
Manufacturing BOM, routing, work centers, production orders, MRP, quality, manufacturing accounting manufacturing
HR Employee master, attendance, timesheets, leave, payroll (Malaysian statutory), claims/loans/advances, ESS, training hr
Projects Projects, tasks, milestones, time entries, expenses, members, profitability projects
Recruitment Job postings, applicants, interviews, offers → convert to employee recruitment
Sales / POS Front-of-house terminal over the sales/order engine sales-pos
CRM Customers & suppliers (trading-partner master), KYC crm
Master data Reference data (UOM, currency, tax types, dimensions…), company/branch/store, fiscal periods, exchange rates, config master-data
Assets Fixed-asset register + depreciation assets
Budget Budgets per account/period budget
Subscription/config Plans, feature catalog, feature gating subscription-config
User access The unified users collection, admin users, profile, preferences user-access
Integrations MCP server, Zoom, app version, Wingold integrations

Cross-cutting platform concerns (auth, RBAC, workflow/approvals, audit, notifications, files, reporting, multi-tenancy) live under platform/.

4. How a request flows

operator → zerp-admin (Next.js)
            component → <Feature>Context → gql/query.ts → Apollo Client
                                                              │ GraphQL (bearer JWT)
                                                              ▼
          zerp-be (NestJS)  Resolver → Service → Repository → Mongoose → MongoDB (this tenant's DB)
                            @ApGqlAuthorize (auth+RBAC) · @AuditMeta (audit) · TransactionManager (sessions)

A single business action commonly fans out into multiple ledger writes in one Mongo session — e.g. a sales invoice writes the order + items + Stock(OUT) + GL legs (AR, COGS, revenue, tax) + optional workflow submission + notifications + audit entry.

5. Deployment

Per-tenant PM2 process pair (zerp-<key>-be, zerp-<key>-admin), each with its own MongoDB database, ports, and TZ, started/stopped from the zerp-master control plane. A master DB holds the tenant registry, limits, and feature whitelist. See multi-tenancy.

6. Reading this doc set

Every module doc follows a fixed template (see TEMPLATE.md): purpose → data model → API surface → business rules/calculations → permissions → flows → admin UI → dependencies → gotchas. Docs are code-accurate and cite source files, and deliberately flag gaps, stubs, and bugs found in the code rather than presenting an idealized design. The methodology is in SPEC.md.