Skip to content

tanfchrl/LogicaBooks

Repository files navigation

Logica Books

Web-based, single-tenant, production-grade accounting for Indonesian SMBs — a reimagining of Frappe Books on a modern web stack. First-class support for PPh 21 (TER), PPh 23, PPN, Faktur Pajak, Bukti Potong, SPT Masa filings and Coretax exports.

The authoritative engineering spec is SPEC.md. The UI design system is documented in docs/aurora-ui.md.


Highlights

  • Append-only general ledger with reversal-by-append (is_cancelled + reverses_id). No row is ever mutated after posting.
  • Posting engine (internal/accounting/posting) — every document type implements BuildEntries + OnSubmit/OnCancel hooks. One code path for atomicity, balance, and reversal across Sales / Purchase / Payment / Journal / Payroll.
  • Moving-average inventory with pg_advisory_xact_lock(hashtext(item || warehouse)) for safe concurrent submits.
  • Indonesian tax built-in — PMK 168/2023 TER brackets for PPh 21, PPN 11 % e-Faktur with NSFP pool reservation, Coretax-compatible CSV.
  • Role-based access control — resource:action permissions enforced at every endpoint.
  • PDF rendering via a Gotenberg sidecar (HTML → PDF, no headless Chrome in-process).
  • Aurora UI — calm pastel-aurora background, white card surfaces, ⌘K command palette, indigo accent.

Stack

Layer Choice
Backend Go 1.23 (modular monolith)
HTTP chi + huma v2 (OpenAPI 3.1)
ORM Bun + pgx v5
Migrations goose (SQL)
Jobs Asynq (Redis)
DB PostgreSQL 16
Cache / broker Redis 7
Frontend Vite + React 19 + TS strict + TanStack Router / Query / Table / Form
Styling Tailwind v4 (Aurora token set)
PDF Gotenberg sidecar
Reverse proxy Caddy 2
Money type shopspring/decimal (Go) / string-decimal (wire)
Tests testcontainers-go (Postgres + Redis)

Quickstart (Docker Compose)

cp deploy/.env.example deploy/.env
# edit deploy/.env — at minimum set a 48-byte JWT_SECRET
openssl rand -base64 48
docker compose -f deploy/docker-compose.yml --env-file deploy/.env up --build

Then open http://localhost:8080. Default bootstrap admin (dev only):

  • Email: admin@logica.dev
  • Password: ChangeMe-LocalDevPasswordOver12Chars

OpenAPI: http://localhost:8080/api/v1/openapi.json · Stoplight: http://localhost:8080/api/v1/docs

Quickstart (local dev — two processes)

# 1. Sidecars only (Postgres + Redis + Gotenberg)
docker compose -f deploy/docker-compose.yml up -d postgres redis gotenberg

# 2. Backend
go build -o /tmp/lb-server ./cmd/server
set -a; . deploy/.env; set +a
DATABASE_URL=postgres://logica:logica@localhost:5432/logica?sslmode=disable \
REDIS_URL=redis://localhost:6379/0 \
GOTENBERG_URL=http://localhost:3000 \
/tmp/lb-server --serve

# 3. Frontend dev server (hot reload, proxies /api → :8080)
cd web && npm install && npm run dev

Open http://localhost:3001.


Module map

cmd/server/                  Entrypoint — --serve, --worker, --migrate, --seed
internal/
  app/                       DI container + config
  http/                      chi server, huma mount, middleware, rate limit
  auth/                      Argon2id, JWT, refresh cookies, /auth/*
  rbac/                      Resolver + Guards middleware
  accounting/
    coa/                     Chart of Accounts (tree, validation, type guards)
    gl/                      Posting-only GL repo (append + reverse-by-append)
    posting/                 Document interface + transactional engine
    journal/                 Free-form Journal Entry
  sales/                     Sales Invoice + line items + PPN allocator
  purchase/                  Purchase Bill + Input PPN
  payment/                   Receive / Pay + allocation against invoices/bills
  inventory/                 Stock Ledger Entries + moving-average valuation
  item/                      Item master
  party/                     Customer / Supplier / Both
  tax/
    ppn/                     Output / input PPN allocator
    pph21/                   Payroll Run + Slip + PMK 168/2023 TER brackets
    spt/                     SPT Masa PPN + PPh 21 + e-Faktur CSV export
  reports/                   GL · TB · P&L · BS · AR/AP Aging · Sales/Purchase Register
  pdf/                       Gotenberg client + HTML templates
  numbering/                 SINV/BILL/PAY/JE/PR series resolver
  db/                        pgx pool, Bun, goose migrations, seed data
  ratelimit/                 Redis sliding window (Lua)

web/
  app/
    routes/                  TanStack file-router (~22 routes)
    components/
      ui/                    Aurora primitives (Button, Card, Input, Badge, Kbd, Table)
      Sidebar.tsx            240px workspace nav with command-palette trigger
      CommandPalette.tsx     ⌘K palette
      PageHeader.tsx         Top-of-route header on the aurora gradient
    lib/
      queries/               TanStack Query hooks per domain
      api/fetch.ts           Bearer + 401-retry transport
      auth.ts                useMe / login / logout / refresh
      format.ts              id-ID currency / number / date helpers
    styles/globals.css       Tailwind v4 @theme — Aurora tokens
  vite.config.ts             Dev proxy /api → :8080

deploy/
  docker-compose.yml         Dev: app + postgres + redis + gotenberg
  docker-compose.prod.yml    Caddy reverse proxy, real domain, secrets via env
  Caddyfile                  HTTPS termination
  .env.example               Document every required env var

Engineering rules (excerpt — read SPEC.md for the rest)

  • Money never crosses a JSON boundary as a float. Wire format is a string; in Go it's shopspring/decimal; in the DB it's NUMERIC(20, 2).
  • The general ledger is append-only. Cancel by appending the inverse with is_cancelled = true + reverses_id. Never UPDATE/DELETE gl_entry.
  • Every state transition runs in one transaction. The posting engine wraps OnSubmit/OnCancel hooks and the GL writes together.
  • Permissions are enforced at the route, not the UI. Guards.Require("resource", "action") middleware on every protected huma op.
  • Errors that the user can act on return 4xx. Cross-package sentinel errors map to 422/409 via per-handler mapErr. Server faults are 500.
  • All time is UTC. Dates use YYYY-MM-DD; the UI formats with Intl.DateTimeFormat("en-GB") for display.

API surface

GET /api/v1/openapi.json and /api/v1/docs are the source of truth.

Resource families: auth, accounts, parties, items, sales/invoices, purchase/bills, payments, journal-entries, inventory/{ledger,stock-balance}, tax/faktur-pajak, tax/payroll-runs, tax/employees, reports/*. Every list route accepts limit + offset + a filter set documented in OpenAPI.


Testing

# Unit + posting-engine integration (testcontainers-go boots a real Postgres)
go test ./...

# Frontend type check + build
cd web && npx tsc --noEmit && npx vite build

The posting engine has end-to-end tests against a real Postgres for every doctype.


Roadmap

Phase Scope Status
0–2 Foundations, auth, RBAC, masters ✅ Done
3 Journal Entry + posting engine ✅ Done
4 Sales / Purchase / Payments + GL reports ✅ Done
5 Numbering, e-Faktur scaffolding ✅ Done
6 Inventory + moving-average valuation ✅ Done
7 Tax — PPN allocator + PPh 21 TER + SPT Masa ✅ Done
8 Financial reports (TB/P&L/BS/Registers/SPT PPh 21) + CSV / PDF ✅ Done
8.5 Aurora UI revamp ✅ Done
9 Background jobs (Asynq), period close, audit log 🛠️ Open issues
10 Bukti Potong PDF + Coretax XML / API 🛠️ Open issues
11 Bank reconciliation, recurring docs, attachments 🛠️ Open issues
12 Mobile responsive, i18n (id/en switch), dark mode 🛠️ Open issues

See Issues for the live punch list.


Security notes

  • Bootstrap admin credentials only fire when the user table is empty. Once seeded, those env vars do nothing. Change the password and disable seed credentials in production.
  • JWT_SECRET must be ≥ 32 bytes. The server refuses to boot otherwise.
  • Refresh tokens are rotated on every refresh and stored in a Secure; HttpOnly; SameSite=Lax cookie.
  • Argon2id parameters: m=64 MiB, t=3, p=4. Tunable in internal/auth/argon.go.
  • gl_entry is append-only with a Postgres trigger preventing UPDATE / DELETE. Reversal is by inverse-append.

License

AGPL-3.0 — matches upstream Frappe Books (required for a derivative).

About

Web-based, single-tenant, production-grade accounting for Indonesian SMBs. Go + chi + huma v2 + PostgreSQL backend; React 19 + Vite SPA frontend with the Aurora design system. First-class PPh 21 (TER), PPN 11%, e-Faktur, SPT Masa.

Topics

Resources

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors