saas-accounting-system

Implement a complete double-entry accounting system inside any SaaS app. Users enter transactions naturally (sales, expenses, inventory) while the system auto-posts journal entries under the hood. Produces both user-friendly reports and technical...

Best use case

saas-accounting-system is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Implement a complete double-entry accounting system inside any SaaS app. Users enter transactions naturally (sales, expenses, inventory) while the system auto-posts journal entries under the hood. Produces both user-friendly reports and technical...

Teams using saas-accounting-system should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/saas-accounting-system/SKILL.md --create-dirs "https://raw.githubusercontent.com/peterbamuhigire/skills-web-dev/main/skills/saas/saas-accounting-system/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/saas-accounting-system/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How saas-accounting-system Compares

Feature / Agentsaas-accounting-systemStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Implement a complete double-entry accounting system inside any SaaS app. Users enter transactions naturally (sales, expenses, inventory) while the system auto-posts journal entries under the hood. Produces both user-friendly reports and technical...

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

## Platform Notes

- Optional helper plugins may help in some environments, but they must not be treated as required for this skill.

# SaaS Accounting System
Acknowledgement: Shared by Peter Bamuhigire, techguypeter.com, +256 784 464178.

<!-- dual-compat-start -->
## Use When

- Implement a complete double-entry accounting system inside any SaaS app. Users enter transactions naturally (sales, expenses, inventory) while the system auto-posts journal entries under the hood. Produces both user-friendly reports and technical...
- The task needs reusable judgment, domain constraints, or a proven workflow rather than ad hoc advice.

## Do Not Use When

- The task is unrelated to `saas-accounting-system` or would be better handled by a more specific companion skill.
- The request only needs a trivial answer and none of this skill's constraints or references materially help.

## Required Inputs

- Gather relevant project context, constraints, and the concrete problem to solve; load `references` only as needed.
- Confirm the desired deliverable: design, code, review, migration plan, audit, or documentation.

## Workflow

- Read this `SKILL.md` first, then load only the referenced deep-dive files that are necessary for the task.
- Apply the ordered guidance, checklists, and decision rules in this skill instead of cherry-picking isolated snippets.
- Produce the deliverable with assumptions, risks, and follow-up work made explicit when they matter.

## Quality Standards

- Keep outputs execution-oriented, concise, and aligned with the repository's baseline engineering standards.
- Preserve compatibility with existing project conventions unless the skill explicitly requires a stronger standard.
- Prefer deterministic, reviewable steps over vague advice or tool-specific magic.

## Anti-Patterns

- Treating examples as copy-paste truth without checking fit, constraints, or failure modes.
- Loading every reference file by default instead of using progressive disclosure.

## Outputs

- A concrete result that fits the task: implementation guidance, review findings, architecture decisions, templates, or generated artifacts.
- Clear assumptions, tradeoffs, or unresolved gaps when the task cannot be completed from available context alone.
- References used, companion skills, or follow-up actions when they materially improve execution.

## Evidence Produced

| Category | Artifact | Format | Example |
|----------|----------|--------|---------|
| Correctness | Double-entry accounting test plan | Markdown doc covering journal balance, period close, and reconciliation scenarios | `docs/accounting/double-entry-tests.md` |
| Data safety | Chart of accounts and posting rules register | Markdown doc per `skill-composition-standards/references/entity-model-template.md` covering accounts, posting rules, and audit-trail requirements | `docs/accounting/coa-register.md` |

## References

- Use the `references/` directory for deep detail after reading the core workflow below.
- Use companion skill `accounting-finance-controller` when the implementation also needs IFRS-aware reporting, management accounting, cost accounting, financial controls, projections, or CFO-grade review beyond the core double-entry engine.
<!-- dual-compat-end -->
## Overview

## Deprecation Note

For new products that handle money, prefer the stricter companion skill `accounting-engine`. This file remains useful as legacy implementation detail, but any guidance here must be read subject to these hard rules:

- All ledger writes go through one `LedgerPostingService`.
- Posted journal lines are append-only and are never updated, deleted, or soft-deleted.
- Corrections use reversing journals.
- Materialized balances are rebuildable caches, not authoritative records.
- Business modules never hardcode account codes or write ledger tables directly.
- IFRS/IFRS for SMEs tenants never use LIFO.

This skill implements a **hidden accounting engine** inside business applications. End users never see debits, credits, or journal entries — they enter sales, record payments, move inventory. Under the hood, every transaction auto-posts balanced journal entries that accountants and auditors can query at any time.

**Philosophy:** Users think in business terms. The system thinks in double-entry.

## Core Architecture

```
┌─────────────────────────────────────────────────┐
│  USER LAYER (Friendly)                          │
│  Sales, Purchases, Payments, Inventory, Expenses│
│  → User sees: "Sale #1042 to Customer X: $500"  │
└──────────────────────┬──────────────────────────┘
                       │ auto-posts
┌──────────────────────▼──────────────────────────┐
│  ACCOUNTING ENGINE (Hidden)                     │
│  Journal Entries, Ledger Postings, Trial Balance│
│  → Engine posts: DR Accounts Receivable $500    │
│                  CR Sales Revenue      $500     │
└──────────────────────┬──────────────────────────┘
                       │ aggregates
┌──────────────────────▼──────────────────────────┐
│  REPORTING LAYER (Dual)                         │
│  User Reports: Sales Summary, Aging, P&L Simple │
│  Accountant Reports: Trial Balance, BS, IS, CF  │
└─────────────────────────────────────────────────┘
```

## The Golden Rule

**Every transaction MUST produce balanced journal entries. No exceptions.**

```
SUM(debits) = SUM(credits)  — ALWAYS
```

This is enforced at the database level via stored procedure or trigger. If entries don't balance, the entire transaction rolls back.

## Chart of Accounts (COA)

The COA is the backbone. Every account has a type that determines its normal balance.

| Type | Code Range | Normal Balance | Examples |
|------|-----------|----------------|----------|
| **Asset** | 1000-1999 | Debit | Cash, Bank, AR, Inventory, Equipment |
| **Liability** | 2000-2999 | Credit | AP, Loans, Tax Payable, Unearned Revenue |
| **Equity** | 3000-3999 | Credit | Owner's Equity, Retained Earnings |
| **Revenue** | 4000-4999 | Credit | Sales, Service Income, Interest Income |
| **COGS** | 5000-5999 | Debit | Cost of Goods Sold, Direct Materials |
| **Expense** | 6000-6999 | Debit | Rent, Salaries, Utilities, Marketing |

**Setup rules:**
- Tenant gets a default COA on creation (seeded from template)
- Accounts are tenant-scoped (`franchise_id`)
- Accounts cannot be deleted if they have posted entries
- Sub-accounts supported (e.g., 1100 Cash → 1101 Petty Cash, 1102 Main Bank)

See: `references/chart-of-accounts.md` and `references/accounting-bookkeeping-erp-patterns.md`.

## Auto-Posting Rules

Users never create journal entries manually. Every business transaction has a posting rule.

### Transaction → Journal Entry Map

| User Action | Debit Account | Credit Account |
|------------|---------------|----------------|
| **Record Sale (Invoice)** | Accounts Receivable | Sales Revenue |
| **Record Sale + Tax** | AR + Tax Receivable | Sales Revenue + Tax Payable |
| **Receive Payment (Cash)** | Cash/Bank | Accounts Receivable |
| **Record Purchase** | Inventory/Expense | Accounts Payable |
| **Pay Supplier** | Accounts Payable | Cash/Bank |
| **Record Expense** | Expense Account | Cash/Bank or AP |
| **Inventory Sale (COGS)** | Cost of Goods Sold | Inventory |
| **Stock Adjustment (+)** | Inventory | Inventory Adjustment (Income) |
| **Stock Adjustment (-)** | Inventory Adjustment (Expense) | Inventory |
| **Salary Payment** | Salary Expense | Cash/Bank |
| **Loan Received** | Cash/Bank | Loan Payable |
| **Loan Repayment** | Loan Payable + Interest Exp | Cash/Bank |
| **Depreciation** | Depreciation Expense | Accumulated Depreciation |
| **Customer Refund** | Sales Returns | Cash/Bank or AR |

**Multi-line entries:** A single sale with tax and discount creates 3+ journal lines, all in one entry. The entry MUST balance.

See: `references/journal-posting-rules.md` and `references/accounting-bookkeeping-erp-patterns.md`.

## Void & Reversal Mechanics

**Rule:** Never delete a posted journal entry. Always create a reversing entry.

### Void Process

```
1. User clicks "Void" on a transaction (e.g., Sale Invoice #1042)
2. System marks the original transaction as VOIDED (status change)
3. System auto-creates a REVERSING journal entry:
   - Same accounts, opposite directions
   - Reference: "REVERSAL of JE-{original_id}"
   - Same date OR current date (configurable)
4. Original entry + reversal entry net to ZERO
5. All sub-ledger balances update automatically
```

### Reversal Entry Example

```
Original (Sale Invoice #1042):
  DR  Accounts Receivable    500.00
  CR  Sales Revenue           500.00

Reversal (Void of #1042):
  DR  Sales Revenue           500.00
  CR  Accounts Receivable    500.00

Net effect: ZERO
```

### Partial Void Rules

- Partially paid invoices: Void remaining balance only
- Payment already received: Must void payment first, then invoice
- Inventory already delivered: Must reverse stock movement first
- Cascade protection: System warns if dependent transactions exist

See: `references/void-reversal-patterns.md`

## Database Schema (Core Tables)

```sql
-- Chart of Accounts
accounts (id, franchise_id, code, name, type, parent_id,
          is_active, normal_balance, created_at)

-- Journal Entries (Header)
journal_entries (id, franchise_id, entry_date, reference_type,
                 reference_id, narration, is_reversal, reversed_entry_id,
                 posted_by, status, created_at)

-- Journal Entry Lines (Detail)
journal_entry_lines (id, journal_entry_id, account_id,
                     debit_amount, credit_amount, narration,
                     franchise_id, created_at)

-- Fiscal Periods
fiscal_periods (id, franchise_id, period_name, start_date,
                end_date, status, closed_by, closed_at)

-- Account Balances (Materialized for performance)
account_balances (id, franchise_id, account_id, period_id,
                  opening_balance, debit_total, credit_total,
                  closing_balance, updated_at)
```

**Integrity constraints:**
- `journal_entry_lines.debit_amount` and `credit_amount` are DECIMAL(15,2)
- CHECK constraint: Each line has debit OR credit, never both, never both zero
- Stored procedure validates SUM(debit) = SUM(credit) per entry
- `franchise_id` on every table (multi-tenant isolation)
- `status` enum: DRAFT, POSTED, VOIDED

See: `references/schema-design.md`

## Subledger and Control Account Discipline

Every finance module must reconcile to the general ledger through control accounts:

- Accounts receivable aging must reconcile to the AR control account.
- Accounts payable aging must reconcile to the AP control account.
- Inventory valuation must reconcile to inventory control accounts.
- Fixed asset register net book value must reconcile to asset cost less accumulated depreciation.
- Bank reconciliation must explain the difference between bank statement and book balance.
- Tax schedules must reconcile tax payable/receivable accounts to return-ready evidence.

Do not let users post directly to control accounts except through controlled adjustment workflows with reason, approval, and audit trail.

## Management Accounting Layer

When the system supports manufacturing, services, projects, schools, clinics, retail, or ERP management reporting, add cost-centre, profit-centre, project, branch, department, and product dimensions to postings. Use these dimensions for budgets, flexible budget reports, standard-cost variance, contribution margin, activity-based costing, and management packs without corrupting statutory GL structure.

## Dual Reporting System

### User-Friendly Reports (Non-Accountant)

| Report | What User Sees | Data Source |
|--------|---------------|-------------|
| Sales Summary | Total sales by period, customer, product | Sales transactions |
| Outstanding Invoices | Who owes what, how old | AR sub-ledger |
| Expense Report | Spending by category | Expense transactions |
| Profit & Loss (Simple) | Revenue minus expenses | Income/expense accounts |
| Cash Position | Money in bank/cash | Cash/bank accounts |
| Inventory Value | Stock on hand with cost | Inventory sub-ledger |

### Accountant/Auditor Reports (Technical)

| Report | What It Shows | Source |
|--------|-------------|--------|
| Trial Balance | All account balances (DR/CR columns) | General Ledger |
| Balance Sheet | Assets = Liabilities + Equity | GL (type 1-3) |
| Income Statement | Revenue - COGS - Expenses = Net Income | GL (type 4-6) |
| Cash Flow Statement | Operating + Investing + Financing | Cash account entries |
| General Ledger Detail | Every entry per account | Journal entries |
| Journal Register | All journal entries chronologically | Journal entries |
| Aged Receivables | AR aging (30/60/90/120 days) | AR sub-ledger |
| Aged Payables | AP aging | AP sub-ledger |
| Audit Trail | Who posted what, when | Journal entries + audit log |

See: `references/financial-statements.md`

## Implementation Checklist

### Phase 1: Foundation (Must Complete First)

- [ ] Create `accounts` table with COA seed data
- [ ] Create `journal_entries` and `journal_entry_lines` tables
- [ ] Create `fiscal_periods` table
- [ ] Build balance validation stored procedure
- [ ] Build `postJournalEntry()` service function
- [ ] Write tests: balanced entry passes, unbalanced rejects

### Phase 2: Auto-Posting Integration

- [ ] Wire sales invoice → auto-post AR/Revenue entry
- [ ] Wire payment received → auto-post Cash/AR entry
- [ ] Wire purchase → auto-post Inventory or Expense/AP entry
- [ ] Wire supplier payment → auto-post AP/Cash entry
- [ ] Wire inventory movement → auto-post COGS/Inventory entry
- [ ] Write tests: each transaction type posts correct entries

### Phase 3: Void & Reversal

- [ ] Build void transaction service (creates reversing entry)
- [ ] Handle partial void scenarios
- [ ] Handle cascade dependencies (warn before void)
- [ ] Write tests: void produces net-zero, balances correct

### Phase 4: Reporting

- [ ] Build Trial Balance report (all accounts, DR/CR totals)
- [ ] Build Balance Sheet (Assets = Liabilities + Equity)
- [ ] Build Income Statement (Revenue - Expenses)
- [ ] Build user-friendly summary reports
- [ ] Build audit trail report
- [ ] Write tests: reports match expected values from test data

### Phase 5: Period Management

- [ ] Build period open/close functionality
- [ ] Prevent posting to closed periods
- [ ] Build year-end closing entry (Revenue/Expense → Retained Earnings)
- [ ] Write tests: closed period rejects entries

## Cross-Skill Integration

| Area | Skill | How It Applies |
|------|-------|---------------|
| Database schema | `mysql-best-practices` | DECIMAL(15,2), indexes, FK constraints |
| API endpoints | `api-error-handling` | Consistent error responses for failed postings |
| Multi-tenancy | `multi-tenant-saas-architecture` | franchise_id on all tables |
| UI reports | `webapp-gui-design` | DataTables for ledger, charts for P&L |
| Mobile reports | `jetpack-compose-ui` | Report screens with tables |
| PDF export | `android-pdf-export`, `report-print-pdf` | Financial statement PDFs |
| Security | `vibe-security-skill` | Protect financial data, audit trail |
| Auth | `dual-auth-rbac` | Permission: who can post/void/view reports |
| Inventory link | `inventory-management` | COGS posting on stock movements |
| Testing | `sdlc-testing` | Test every posting rule, every reversal |
| Implementation | `plan-implementation` | Execute accounting phases with TDD |
| Audit | `implementation-status-auditor` | Verify accounting system completeness |

## Anti-Patterns

| Don't | Do Instead |
|-------|-----------|
| Let users enter journal entries directly | Auto-post from business transactions |
| Use FLOAT for money | Use DECIMAL(15,2) always |
| Delete journal entries | Create reversing entries (void) |
| Skip balance validation | Enforce DR=CR in stored procedure |
| Store calculated balances only | Store individual entries, calculate on demand |
| Mix accounting with business logic | Separate accounting engine as its own service layer |
| Hard-code account codes | Use configurable COA with tenant-specific accounts |
| Skip audit trail | Log every posting with user, timestamp, IP |
| Allow posting to closed periods | Enforce period status check before posting |
| Show debits/credits to end users | Show friendly labels (Income, Payment, etc.) |

## Accuracy Guarantee

Every implementation MUST pass these tests:

1. **Balance test:** `SELECT SUM(debit) - SUM(credit) FROM journal_entry_lines` = 0.00
2. **Entry test:** Every journal entry has SUM(debit) = SUM(credit)
3. **Trial Balance test:** Total debits = Total credits
4. **Balance Sheet test:** Assets = Liabilities + Equity
5. **Reversal test:** Voided transaction + reversal nets to zero
6. **Period test:** No entries in closed periods
7. **Tenant test:** No cross-tenant data leakage in any query

## See Also

- `references/chart-of-accounts.md` — COA templates and setup
- `references/journal-posting-rules.md` — Complete posting rules per transaction
- `references/void-reversal-patterns.md` — Void mechanics and edge cases
- `references/financial-statements.md` — Report SQL queries and formats
- `references/schema-design.md` — Complete database schema with constraints
- `references/accounting-bookkeeping-erp-patterns.md` — bookkeeping, subledger control, ERP finance configuration, cost accounting, management reporting, and acceptance tests

Related Skills

saas-tenant-data-portability-and-erasure

8
from peterbamuhigire/skills-web-dev

Use when designing the GDPR/POPIA/CCPA-compliant data export (right to portability) and erasure (right to be forgotten) workflows for a multi-tenant SaaS — cascade through every data store including warehouse/backups, retention policy, requester verification, audit trail, multi-tenant nuances of erasing one tenant's data without affecting others, and the engineering for African market regulations (Uganda DPPA, Kenya DPA, POPIA).

saas-sso-scim-enterprise-auth

8
from peterbamuhigire/skills-web-dev

Use when implementing enterprise auth on a multi-tenant SaaS — SAML 2.0 and OIDC SSO with per-tenant IdP configuration, SCIM 2.0 user provisioning/deprovisioning, custom-domain support with automated TLS, IP allowlists per tenant, audit-log API, and the migration from email-password tenants to IdP-enforced tenants. The price of entry for enterprise SaaS.

saas-seeder

8
from peterbamuhigire/skills-web-dev

Bootstrap a new SaaS from the SaaS Seeder Template: setup database, configure environment, create super admin user, and verify three-tier panel structure. Use when initializing a new multi-tenant SaaS project from this template.

saas-sales-organization

8
from peterbamuhigire/skills-web-dev

Use when designing or scaling a SaaS sales organisation — sales motions, roles (SDR/BDR/AE/CSM/SE), pipeline stages, lead-to-cash, territory design, quota/commission, sales ops fundamentals, onboarding/ramp, and hiring rubrics. Sourced from "Blueprints for a SaaS Sales Organization" (van der Kooij, Pizarro).

saas-rate-limiting-and-quotas

8
from peterbamuhigire/skills-web-dev

Use when designing per-tenant rate limits and quotas — algorithm choice (token bucket, sliding window, leaky bucket, fixed window), where to enforce (edge, gateway, service, DB connection pool, queue), per-plan / per-tier limits, soft vs hard caps, fair-queueing for noisy neighbors, headers and error responses, and how to expose quota usage to the tenant.

saas-lifecycle-email-orchestration

8
from peterbamuhigire/skills-web-dev

Use when designing the six core lifecycle email sequences (welcome/onboarding, behavioral/feature-discovery, upgrade/upsell, retention, reactivation, referral) — trigger contracts, branched automation, suppression rules, PQL/churn-risk triggers, and revenue attribution. Built on top of `saas-transactional-email-infrastructure`. Distinct from `tabler-email-templates` (HTML) and `subscription-billing` (raw billing events).

saas-erp-system-design

8
from peterbamuhigire/skills-web-dev

Use when designing configurable SaaS or ERP platforms with multi-step business workflows, domain modules, approvals, auditability, pricing and entitlements, operational reporting, and tenant-specific variation. Covers domain boundaries, workflow states, extension points, and control design.

saas-entitlements-and-plan-gating

8
from peterbamuhigire/skills-web-dev

Use when designing the entitlements engine that enforces what each plan/tier/tenant can do — feature flags vs entitlements distinction, limits enforcement (seats, API calls, storage, projects, AI tokens), gate placement (UI, API, worker), upgrade-discovery UX, override mechanisms for enterprise contracts, and the runtime that resolves "can this tenant do X right now?" in a few milliseconds.

saas-business-metrics

8
from peterbamuhigire/skills-web-dev

Complete SaaS metrics framework covering revenue (MRR/ARR/ARPU), growth (CAC/LTV/payback), retention (churn/NRR/GRR), engagement, customer satisfaction (NPS/CSAT/CES), unit economics, the Rule of 40, and SaaS finance basics. Use when measuring...

saas-architecture-strategy

8
from peterbamuhigire/skills-web-dev

Use when architecting or evaluating a cloud SaaS product — including choosing multi-tenant patterns, mapping deployment to IaaS, planning scaling and blast-radius isolation, aligning architecture to business capabilities, and reconciling multi-enterprise consumption requirements with operating-model constraints.

saas-admin-backoffice-tooling

8
from peterbamuhigire/skills-web-dev

Use when designing the internal admin / back-office console of a multi-tenant SaaS — tenant impersonation (audited, time-boxed), tenant lifecycle controls (suspend/restore/archive/hard-delete), billing operations (refunds, credits, plan overrides), feature-flag overrides per tenant, bulk actions (mass invite, plan migration, region migration), and the audit-log spine that backs all of it. Distinct from the customer-facing super-admin panel in `multi-tenant-saas-architecture`.

multi-tenant-saas-architecture

8
from peterbamuhigire/skills-web-dev

Use when designing or reviewing a multi-tenant SaaS platform — tenant isolation model, three-panel separation (super admin, franchise admin, end user), zero-trust enforcement, audit trails, and per-tenant permission overrides. Unlike `modular-saas-architecture` which focuses on pluggable business modules, this skill defines the tenancy and auth boundaries that every module inherits.