C
Commas
QA Team Training

ERP Deep Dive: Understanding Commas Inside Out

This guide teaches you everything you need to know about ERP systems and how Commas works under the hood. No accounting background required β€” we explain every concept from scratch using plain language and real-world analogies.

By the end of this session, you will understand what every module does, why financial transactions must always balance, how data flows through the system, and what to look for when testing each feature.

12

Sections

60

Minutes

0

Prerequisites

100%

Practical


1What Is an ERP?

~5 minutes

ERP stands for Enterprise Resource Planning. Despite the intimidating name, the concept is simple: it is a single software system that manages all the core operations of a business in one place.

Think of it this way

Imagine you run a shop. You have one notebook for tracking what you sell (sales), another for what you buy (purchases), another for your bank balance, another for what customers owe you, and another for your employees' salaries. An ERP is like combining all those notebooks into one big book where everything is connected. When you record a sale, it automatically updates your inventory, your bank balance, and what the customer owes you.

What does an ERP manage?

Business AreaWhat It CoversIn Commas
Finance & AccountingGeneral ledger, chart of accounts, financial statementsChart of Accounts, Journals, Trial Balance, P&L, Balance Sheet
SalesQuotes, orders, invoices, receipts, credit notesQuotes > Orders > Invoices > Receipts
PurchasingPurchase orders, bills, goods receipt, returnsPOs > Goods Receipt > Bills > Payments
InventoryStock levels, movements, counts, valuationItems, Stock Levels, Stock Count, Movements
BankingBank accounts, reconciliation, paymentsBank Accounts, Reconciliation, Batch Payments
Tax & ComplianceVAT/GST returns, tax calculationsVAT Returns, VAT Adjustments, Tax Payments
PayrollEmployee management, salary, deductionsEmployees, Pay Runs, Payslips
ReportingFinancial reports, analytics, dashboards49+ reports including Trial Balance, P&L, Balance Sheet
AdministrationUsers, roles, permissions, audit trailUser Management, 70+ Permissions, Audit Log

The Golden Rule of ERP

Everything is connected. When you create a sales invoice in Commas, the system simultaneously: (1) records the sale as revenue, (2) records the VAT owed to the government, (3) records what the customer owes you, and (4) updates the general ledger. This is not four separate actions β€” it is one atomic operation. This interconnectedness is what makes testing an ERP different from testing a simple CRUD app.

How Commas implements this

Commas is a cloud-based, multi-tenant ERP designed specifically for SMEs in Nigeria and South Africa. It runs on Next.js + Supabase (PostgreSQL), uses Row-Level Security for data isolation, and implements double-entry bookkeeping with a central posting engine. Every financial transaction goes through this engine, guaranteeing that the books always balance.

2Double-Entry Bookkeeping

~10 minutes β€” This is the most important concept in the entire system

Double-entry bookkeeping is a 500-year-old system invented in Italy. It is the foundation of every accounting system in the world, including Commas. The core rule is devastatingly simple:

Every transaction has two sides.

For every debit, there must be an equal credit.

Total Debits = Total Credits β€” Always.

Think of it this way

Think of your personal life. You buy a laptop for ₦200,000 using your bank account. Two things happened simultaneously: (1) you gained a laptop (asset goes up), and (2) your bank balance went down by ₦200,000. The money didn't vanish β€” it changed form. Double-entry bookkeeping simply records both sides of every transaction.

Debits and Credits

Forget what "debit" and "credit" mean in everyday language. In accounting, they are simply the left side and right side of a journal entry. Which side increases or decreases depends on the type of account:

Account TypeIncreased ByDecreased ByNormal BalanceExample
AssetDebitCreditDebitBank, Accounts Receivable, Inventory, Equipment
LiabilityCreditDebitCreditAccounts Payable, Loans, VAT Payable
EquityCreditDebitCreditOwner's Capital, Retained Earnings
RevenueCreditDebitCreditSales Revenue, Service Income
ExpenseDebitCreditDebitRent, Salaries, Utilities, Cost of Goods

The DEALER mnemonic

Debits increase DEAL accounts (Dividends, Expenses, Assets, Losses). Credits increase CRIG accounts (Capital, Revenue, Income, Gains). This is all you need to remember.

Example: Recording a Sale

Adebayo Trading sells 10 laptops at ₦100,000 each to a customer on credit (they will pay later). VAT is 7.5%.

Journal Entry: Sales Invoice #INV-001

Total sale = 10 Γ— ₦100,000 = ₦1,000,000 VAT = ₦1,000,000 Γ— 7.5% = ₦75,000 Total invoice = ₦1,075,000 Date: 2026-05-15 Reference: INV-001 Account Debit (₦) Credit (₦) ───────────────────────────────────────────────────── Accounts Receivable 1,075,000 Sales Revenue 1,000,000 VAT Output 75,000 ───────────────────────────────────────────────────── TOTAL 1,075,000 1,075,000 βœ“ Balanced

What just happened? Three things were recorded in one transaction:

  • Accounts Receivable (asset) went UP by ₦1,075,000 β€” the customer owes us money
  • Sales Revenue (revenue) went UP by ₦1,000,000 β€” we earned income
  • VAT Output (liability) went UP by ₦75,000 β€” we collected tax that we owe the government

Example: Receiving Payment

The customer pays the full ₦1,075,000 into our bank account.

Journal Entry: Receipt #REC-001

Date: 2026-05-20 Reference: REC-001 Account Debit (₦) Credit (₦) ───────────────────────────────────────────────────── Bank (Asset) 1,075,000 Accounts Receivable 1,075,000 ───────────────────────────────────────────────────── TOTAL 1,075,000 1,075,000 βœ“ Balanced

Now: Bank went UP (we received cash), Accounts Receivable went DOWN (customer no longer owes us). The money moved from "owed to us" to "in our bank". Total debits still equal total credits.

How Commas implements this

In Commas, you never manually type journal entries for sales, purchases, or payments. Instead, you create documents (invoices, bills, receipts) and click "Post". The posting engine automatically generates the correct double-entry journal entries behind the scenes. The General Ledger > Journal Entries page shows you what was generated. As a tester, you should verify that every posted document creates a balanced journal entry.

3Chart of Accounts

~7 minutes

The Chart of Accounts (CoA) is the master list of every account in the system. Think of it as the filing system for all money that flows through the business. Every transaction touches at least two accounts from this list.

Think of it this way

If your business were a library, the Chart of Accounts would be the Dewey Decimal System β€” it defines the categories and subcategories where every "book" (transaction) gets filed. Without it, you'd have a pile of transactions with no organization.

The Five Account Types

Every account in the Chart of Accounts belongs to exactly one of five types. These five types are the building blocks of all financial reporting:

Balance Sheet Accounts

These accounts carry forward forever. They represent what you have, what you owe, and what belongs to the owners.

  • 1. Assets β€” What the business owns (cash, equipment, inventory, receivables)
  • 2. Liabilities β€” What the business owes (loans, payables, tax owed)
  • 3. Equity β€” The owner's stake (capital invested + accumulated profits)

Income Statement Accounts

These accounts reset to zero at year-end. They measure performance during a period.

  • 4. Revenue β€” Money earned (sales, services, interest income)
  • 5. Expenses β€” Money spent to earn that revenue (rent, salaries, supplies)

The Accounting Equation

Assets = Liabilities + Equity

This equation must always hold true. If assets are ₦10 million, then liabilities plus equity must also be ₦10 million. The Balance Sheet report proves this. If it doesn't balance, something is seriously wrong.

Account Numbering Convention

Commas auto-generates a Chart of Accounts when you create an organization. Accounts are numbered:

Number RangeTypeExamples
1000 – 1999Assets1000 Cash, 1100 Bank, 1200 Accounts Receivable, 1300 Inventory
2000 – 2999Liabilities2000 Accounts Payable, 2100 VAT Payable, 2200 Loans
3000 – 3999Equity3000 Owner's Capital, 3100 Retained Earnings
4000 – 4999Revenue4000 Sales Revenue, 4100 Service Income, 4200 Interest Income
5000 – 5999Cost of Sales5000 Cost of Goods Sold
6000 – 7999Expenses6000 Salaries, 6100 Rent, 6200 Utilities, 6300 Office Supplies

How Commas implements this

Navigate to General Ledger > Chart of Accounts to see the full list. You can add new accounts, edit existing ones, and see the running balance for each. Accounts can be marked as "header" (grouping only, no transactions posted) or "posting" (accepts transactions). When testing, verify that the default CoA is generated correctly for Nigeria (NGN) and South Africa (ZAR).

4The General Ledger

~5 minutes

The General Ledger (GL) is the complete record of every financial transaction that has ever happened in the business. It is the single source of truth. Every report in the system β€” Trial Balance, Income Statement, Balance Sheet β€” is generated by reading from the General Ledger.

Think of it this way

If the Chart of Accounts is the filing system, the General Ledger is the actual filing cabinet with all the documents in it. Each drawer (account) contains every transaction that touched that account, in chronological order.

Journal Entries

The GL is made up of journal entries. Each journal entry has:

  • Date β€” When the transaction occurred
  • Reference β€” The document that caused it (e.g., INV-001, BILL-005)
  • Lines β€” Two or more lines, each hitting a different account with a debit or credit
  • Narration β€” A human-readable description

How Documents Become Journal Entries

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Invoice β”‚ β”‚ Bill β”‚ β”‚ Receipt β”‚ β”‚ (Sales) β”‚ β”‚(Purchase)β”‚ β”‚(Payment) β”‚ β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ POSTING ENGINE β”‚β—„β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ (validates that β”‚ β”‚ debits = creditsβ”‚ β”‚ then inserts) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ GENERAL LEDGER β”‚ ← Single source of truth β”‚ (journal_entriesβ”‚ β”‚ + gl_lines) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β–Όβ”€β”€β” β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β” β”Œβ”€β”€β”€β–Όβ”€β”€β”€β”€β” β”‚Trial β”‚ β”‚Income β”‚ β”‚Balance β”‚ β”‚Balanceβ”‚ β”‚Statementβ”‚ β”‚ Sheet β”‚ β””β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜

How Commas implements this

Navigate to General Ledger > Journal Entries to see all entries. You can also create manual journal entries (for adjustments, corrections, or accruals). When testing, the most critical check is: after posting any document, navigate to Journal Entries and verify that a new balanced entry was created with the correct accounts and amounts.

5Subledgers (The Detail Behind the Summary)

~10 minutes β€” This is where the magic of an ERP really shines

The General Ledger tells you that "Accounts Receivable is ₦5,000,000" but it doesn't tell you which customers owe that money. That's what subledgers are for.

A subledger (also called a subsidiary ledger) is a detailed breakdown of a single GL account. The total of all entries in the subledger must always equal the balance in the corresponding GL account. This is called reconciliation.

Think of it this way

The General Ledger is like a company-wide scorecard: "We are owed ₦5 million." The Customer Subledger is the detailed list: "Customer A owes ₦2M, Customer B owes ₦1.5M, Customer C owes ₦1.5M." The sum of the parts must always equal the whole.

Commas Has Five Subledgers

SubledgerTracksRelated GL AccountKey Reports
Customer LedgerWhat each customer owes you (Accounts Receivable)Accounts Receivable (Asset)Customer Statement, AR Aging, Customer Ledger Entries
Vendor LedgerWhat you owe each supplier (Accounts Payable)Accounts Payable (Liability)Vendor Statement, AP Aging, Vendor Ledger Entries
Bank LedgerEvery transaction in each bank accountBank (Asset)Bank Statement, Bank Reconciliation
Inventory LedgerStock quantities and cost per itemInventory (Asset)Stock Levels, Stock Movements, Valuation Report
VAT LedgerTax collected (output) and tax paid (input)VAT Output / VAT Input (Liability/Asset)VAT Return, VAT Summary

Customer Ledger Deep Dive

Let's trace a full customer lifecycle:

Customer Ledger: Adebayo Trading β†’ Customer 'Lagos Electronics'

Date Document Type Debit (₦) Credit (₦) Balance (₦) ───────────────────────────────────────────────────────────────────────── 2026-05-01 INV-001 Invoice 1,075,000 1,075,000 2026-05-10 REC-001 Receipt 500,000 575,000 2026-05-20 INV-002 Invoice 537,500 1,112,500 2026-05-25 CN-001 Credit Note 107,500 1,005,000 2026-05-30 REC-002 Receipt 1,005,000 0 ───────────────────────────────────────────────────────────────────────── GL Account "Accounts Receivable" balance should = Sum of all customer balances

Vendor Ledger Deep Dive

The vendor ledger works the same way but in reverse β€” it tracks what you owe:

Vendor Ledger: Adebayo Trading β†’ Supplier 'China Imports Ltd'

Date Document Type Debit (₦) Credit (₦) Balance (₦) ───────────────────────────────────────────────────────────────────────── 2026-05-02 BILL-001 Bill 2,150,000 2,150,000 2026-05-15 PAY-001 Payment 1,000,000 1,150,000 2026-05-28 PAY-002 Payment 1,150,000 0 ───────────────────────────────────────────────────────────────────────── GL Account "Accounts Payable" balance should = Sum of all vendor balances

Inventory Ledger Deep Dive

The inventory ledger tracks the quantity and cost of each item:

Inventory Ledger: Item 'HP Laptop ProBook 450'

Date Document Type Qty In Qty Out Balance Unit Cost (₦) ────────────────────────────────────────────────────────────────────────────────── 2026-05-02 PO-001 Purchase 50 50 85,000 2026-05-15 INV-001 Sale 10 40 85,000 2026-05-20 INV-002 Sale 5 35 85,000 2026-05-25 ADJ-001 Stock Adjustment -2 33 85,000 ────────────────────────────────────────────────────────────────────────────────── GL Account "Inventory" balance should = Sum of (quantity Γ— unit cost) for all items

The Reconciliation Principle

The sum of every subledger must equal its parent GL account. If the Customer Ledger says customers owe ₦5M total, the Accounts Receivable GL account must also show ₦5M. If they don't match, there's a bug. This is a critical test case for QA.

How Commas implements this

Each subledger has its own section in the sidebar: Customers > Customer Ledger, Suppliers > Vendor Ledger, Banking > Bank Ledger, etc. The posting engine writes to both the GL and the relevant subledger simultaneously. When testing, always verify both: check that the GL entry is balanced AND that the subledger entry matches.

6Financial Statements

~8 minutes

Financial statements are the output of the accounting system. They are generated automatically from the General Ledger data. There are four main statements:

1. Trial Balance

The Trial Balance lists every account and its balance (debit or credit). Its purpose is to prove that total debits = total credits. If they don't match, something was posted incorrectly.

Trial Balance as at 31 May 2026 (simplified)

Account Debit (₦) Credit (₦) ────────────────────────────────────────────────────────── Bank 3,500,000 Accounts Receivable 1,005,000 Inventory 2,805,000 Equipment 500,000 Accounts Payable 1,150,000 VAT Payable 225,000 Owner's Capital 5,000,000 Retained Earnings 200,000 Sales Revenue 3,000,000 Cost of Goods Sold 1,275,000 Salaries Expense 350,000 Rent Expense 100,000 Utilities Expense 40,000 ────────────────────────────────────────────────────────── TOTAL 9,575,000 9,575,000 βœ“

2. Income Statement (Profit & Loss)

The Income Statement answers: "Did we make money or lose money this period?"It shows Revenue minus Expenses = Net Profit (or Loss).

Income Statement: May 2026

₦ ────────────────────────────────────────────── REVENUE Sales Revenue 3,000,000 ────────── Total Revenue 3,000,000 COST OF SALES Cost of Goods Sold 1,275,000 ────────── Gross Profit 1,725,000 OPERATING EXPENSES Salaries 350,000 Rent 100,000 Utilities 40,000 ────────── Total Expenses 490,000 ────────────────────────────────────────────── NET PROFIT 1,235,000 ──────────────────────────────────────────────

3. Balance Sheet

The Balance Sheet is a snapshot of "What do we own, what do we owe, and what's left for the owners?" at a specific moment in time. It must always satisfy:

Assets = Liabilities + Equity

Balance Sheet as at 31 May 2026

₦ ────────────────────────────────────────────── ASSETS Current Assets Bank 3,500,000 Accounts Receivable 1,005,000 Inventory 2,805,000 Non-Current Assets Equipment 500,000 ────────── TOTAL ASSETS 7,810,000 LIABILITIES Current Liabilities Accounts Payable 1,150,000 VAT Payable 225,000 ────────── TOTAL LIABILITIES 1,375,000 EQUITY Owner's Capital 5,000,000 Retained Earnings 200,000 Net Profit (current period) 1,235,000 ────────── TOTAL EQUITY 6,435,000 ────────────────────────────────────────────── LIABILITIES + EQUITY 7,810,000 ────────────────────────────────────────────── BALANCED? βœ“ (7,810,000 = 7,810,000)

4. Cash Flow Statement

Shows where cash came from and where it went, categorized into operating activities (daily business), investing activities (buying/selling assets), and financing activities (loans, owner contributions).

How Commas implements this

All four statements are available under Reports in the sidebar. They are generated in real-time from GL data. Key QA checks: (1) Trial Balance must always balance, (2) Balance Sheet equation must hold, (3) Net Profit on the Income Statement must match the "Net Profit" line on the Balance Sheet, (4) reports should respect date range filters.

7Document Flow in Commas

~8 minutes

Commas follows an industry-standard document flow inspired by Microsoft Dynamics Business Central. Documents progress through statuses and can be converted from one type to another.

Sales Flow (Order-to-Cash)

Sales Document Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ QUOTE │───▢│ SALES ORDER │───▢│ INVOICE │───▢│ RECEIPT β”‚ β”‚ (Draft) β”‚ β”‚ (Released) β”‚ β”‚ (Posted) β”‚ β”‚(Applied) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ Direct conversion β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ QUOTE statuses: Draft β†’ Sent β†’ Accepted β†’ Converted ORDER statuses: Draft β†’ Released β†’ Partial β†’ Invoiced β†’ Closed INVOICE statuses: Draft β†’ Posted β†’ Partial β†’ Paid Special flows: β€’ Quote can convert directly to Invoice (skipping Order) β€’ Order supports partial invoicing (invoice some lines now, rest later) β€’ Credit Notes reverse invoices (with GL reversal)

Purchase Flow (Procure-to-Pay)

Purchase Document Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚PURCHASE ORDER │───▢│ GOODS RECEIPT │───▢│ BILL │───▢│ PAYMENT β”‚ β”‚ (Released) β”‚ β”‚ (Received) β”‚ β”‚(Posted)β”‚ β”‚(Applied)β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ PO statuses: Draft β†’ Released β†’ Partial β†’ Received β†’ Closed BILL statuses: Draft β†’ Posted β†’ Partial β†’ Paid Three-Way Matching: PO amount ↔ Goods Receipt quantity ↔ Bill amount (All three must agree before payment is authorized)

Document Statuses Explained

StatusMeaningCan Edit?GL Impact?
DraftDocument is being prepared, not yet finalYesNo β€” nothing posted to GL yet
PostedDocument is finalized and GL entries createdNoYes β€” journal entries created
PartialPartially paid or partially fulfilledNoYes β€” some payments/receipts applied
Paid / ClosedFully settled or completedNoYes β€” fully reconciled
Cancelled / VoidedDocument reversedNoYes β€” reversal entries created

Draft vs Posted β€” The Critical Distinction

A draft document has ZERO financial impact. It's just a saved form. Only when a document is posted does it create journal entries and affect the GL. This is an essential test case: verify that draft documents do NOT appear in financial reports, and posted documents DO.

How Commas implements this

Every document page in Commas follows the same pattern: a list view with status badges, a detail view with action buttons (Post, Pay, Convert), and a form view for creation/editing. The status badge is color-coded: gray for draft, blue for posted, yellow for partial, green for paid/closed, red for cancelled. When testing, verify that all status transitions work correctly and that invalid transitions are blocked (e.g., you cannot edit a posted invoice).

8The Posting Engine

~5 minutes

The posting engine is the heart of Commas. It is a single function that every module calls when a document needs to create financial entries. It guarantees that:

  • Total debits always equal total credits (balanced entries)
  • The correct accounts are used (via Posting Groups)
  • Subledger entries are created alongside GL entries
  • The operation is atomic (all or nothing β€” if any part fails, nothing is saved)

Posting Groups

Posting Groups are configuration rules that tell the posting engine whichGL accounts to use. Instead of hardcoding "when selling goods, credit account 4000", the system looks up the Posting Group:

Posting Group TypePurposeExample Configuration
General Business Posting GroupCategorizes customers/vendors by typeDOMESTIC, FOREIGN, GOVERNMENT
General Product Posting GroupCategorizes items by typeGOODS, SERVICES, MATERIALS
General Posting SetupMaps Business Γ— Product β†’ GL AccountsDOMESTIC + GOODS β†’ Sales Account 4000, COGS Account 5000
Customer Posting GroupMaps customer type β†’ AR accountTRADE β†’ AR Account 1200
Vendor Posting GroupMaps vendor type β†’ AP accountTRADE β†’ AP Account 2000
Inventory Posting GroupMaps item type β†’ inventory GL accountGOODS β†’ Inventory Account 1300

Think of it this way

Posting Groups are like a recipe book for the posting engine. When you post an invoice for selling GOODS to a DOMESTIC customer, the engine looks up the recipe: "DOMESTIC + GOODS β†’ credit Sales Revenue (4000), debit COGS (5000), debit AR (1200)". This makes the system flexible β€” different product types can post to different GL accounts.

Posting Engine Flow

User clicks "Post Invoice" β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Validate document β”‚ ← Check all required fields are present β”‚ (lines, amounts, β”‚ β”‚ customer, dates) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Look up Posting β”‚ ← Determine which GL accounts to use β”‚ Groups (Business + β”‚ β”‚ Product β†’ Accounts) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Build journal entry β”‚ ← Create debit/credit lines β”‚ lines (with VAT β”‚ β”‚ calculation) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Verify debits = β”‚ ← CRITICAL: reject if unbalanced β”‚ credits β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Insert into GL β”‚ ← Write to journal_entries + gl_lines β”‚ + subledger entries β”‚ ← Write to customer_ledger_entries etc. β”‚ + update document β”‚ ← Mark document as "posted" β”‚ (all in one β”‚ β”‚ transaction) β”‚ ← Atomic: all or nothing β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

How Commas implements this

The posting engine lives in lib/services/posting.service.ts. When testing, the key things to verify are: (1) every posted document creates balanced GL entries, (2) the correct GL accounts are used based on Posting Groups, (3) if you misconfigure a Posting Group (leave an account blank), the posting should fail gracefully with an error message, not create partial entries.

9Multi-Tenant Architecture & Security

~5 minutes

Commas is a multi-tenant application. This means multiple companies (organizations) share the same database and application, but each one can only see their own data.

Think of it this way

Think of an apartment building. Everyone lives in the same building (same database), but each tenant has their own apartment with a lock on the door. You can't walk into your neighbor's apartment. That's multi-tenancy.

How Data Isolation Works

Every table in the database has an org_id column. This is the "apartment number". Supabase Row-Level Security (RLS) policies automatically filter data so that users can only see rows where org_id matches their organization.

Row-Level Security Example

Table: invoices ───────────────────────────────────────────────── id org_id invoice_no total ───────────────────────────────────────────────── inv-001 org-AAA INV-001 1,075,000 ← Visible to org-AAA users inv-002 org-AAA INV-002 537,500 ← Visible to org-AAA users inv-003 org-BBB INV-001 2,300,000 ← Visible to org-BBB users inv-004 org-CCC INV-001 750,000 ← Visible to org-CCC users ───────────────────────────────────────────────── When User from org-AAA queries: SELECT * FROM invoices They ONLY see inv-001 and inv-002. RLS hides the rest.

Roles & Permissions

Within each organization, users are assigned roles. Commas has 12 built-in roles:

RoleAccess LevelExample Permissions
OwnerFull access to everythingAll permissions + can delete org, manage billing
AdminFull access to everythingAll permissions except org deletion
Finance ManagerFull financial accessAll financial operations, reports, journals
AccountantDay-to-day accountingInvoices, bills, receipts, journals, reports
Sales UserSales operations onlyQuotes, invoices, receipts, customers
Purchasing UserPurchasing operations onlyPOs, bills, payments, suppliers
Inventory UserInventory operations onlyItems, stock levels, counts, movements
Bank UserBanking operations onlyBank accounts, reconciliation, transfers
Payroll AdminPayroll operationsEmployees, pay runs, payslips
AuditorRead-only access to everythingCan view all data but cannot create or modify
Read OnlyRead-only access to assigned areasView permissions only
MemberBasic accessDashboard and profile only

There are 70+ granular permissions (like view_invoices, create_invoices, post_invoices, delete_invoices) that can be customized per role via the Access Control page.

How Commas implements this

When testing: (1) Create two organizations and verify data is completely isolated between them, (2) Test each role by changing a user's role and verifying they can only access permitted pages, (3) Verify that the Admin > Access Control page correctly shows and toggles permissions, (4) Verify the audit log captures who did what and when.

10Commas Modules Overview

~7 minutes

Here is a complete map of every module in Commas and what it does:

General Ledger

FeatureWhat It DoesKey Test Cases
Chart of AccountsMaster list of all accountsDefault CoA generated, accounts CRUD, balance display
Journal EntriesManual and auto-generated GL entriesCreate manual entry, verify balanced, view auto-generated
Posting GroupsMaps documents to GL accountsBusiness/Product/Customer/Vendor groups configured correctly
Opening BalancesSet initial balances for migrationPost GL/customer/supplier/bank opening balances, verify TB

Sales

FeatureWhat It DoesKey Test Cases
QuotesCreate proposals for customersCRUD, status flow (draft→sent→accepted→converted), convert to invoice/order
Sales OrdersConfirmed orders before invoicingCRUD, release, partial invoicing, full invoicing, convert from quote
InvoicesBills sent to customersCRUD, post (verify GL), email/PDF, credit notes, recurring templates
ReceiptsRecord customer paymentsCreate, apply to invoice, verify bank + AR updated, over/under payment
Credit NotesReverse/adjust invoicesCreate from invoice, post (verify GL reversal), apply to balance
Recurring InvoicesAuto-generate invoices on scheduleCreate template, generate now, verify frequency calculation

Purchasing

FeatureWhat It DoesKey Test Cases
Purchase OrdersOrders sent to suppliersCRUD, release, goods receipt, 3-way matching
Goods ReceiptRecord received inventoryReceive against PO, partial receive, verify stock updated
BillsInvoices from suppliersCRUD, post (verify GL), create from PO
PaymentsPay supplier billsCreate, apply to bill, batch payments, verify bank + AP
Purchase ReturnsReturn goods to suppliersCreate return, auto credit note, verify stock adjustment

Banking

FeatureWhat It DoesKey Test Cases
Bank AccountsManage bank account recordsCRUD, linked GL account, running balance
ReconciliationMatch bank statement to system recordsUpload statement, auto-match, manual match, post differences
TransfersMove money between bank accountsCreate, verify both accounts updated, GL entries balanced
Bank FeedsAuto-import transactionsConnect feed, mapping rules, auto-categorization

Inventory

FeatureWhat It DoesKey Test Cases
ItemsProduct/service catalogCRUD, item categories, units, pricing, posting groups
Stock LevelsCurrent quantity per item per locationVerify updates after sale/purchase, low stock alerts
Stock CountsPhysical inventory verificationCreate count, enter actual qty, post adjustments
Stock MovementsTransfer between locationsCreate movement, verify source/destination updated
BundlesKits / composite itemsCreate bundle with components, verify stock deduction on sale

Other Modules

ModuleFeaturesKey Test Cases
PayrollEmployees, pay runs, payslips, deductionsCreate employee, run payroll, verify deductions, generate payslips
VAT & TaxVAT returns, adjustments, paymentsGenerate return from transactions, file, pay, verify GL
Reports (49+)Trial Balance, P&L, Balance Sheet, aging, etc.Date filters, data accuracy, CSV/PDF export, print
ExpensesExpense claims and petty cashCreate expense, approve, reimburse, verify GL
Debtors ManagementCollections, write-offs, communicationAging buckets, send reminders, write off bad debt
AdministrationUsers, roles, audit log, settingsInvite user, change role, verify permissions, check audit trail
Accountant ToolsExternal accountant portalInvite accountant, shared notes, recurring journals, TB export

11Testing an ERP: What to Look For

~5 minutes

Testing an ERP is fundamentally different from testing a regular web application. Here are the specific things you should always check:

1. Financial Integrity Checks

These are the highest priority. A financial bug can cause real monetary harm to users.

  • ⚠Trial Balance must always balance β€” After any operation, total debits must equal total credits
  • ⚠Balance Sheet equation must hold β€” Assets = Liabilities + Equity, always
  • ⚠Subledger reconciliation β€” Sum of customer balances = AR account balance
  • ⚠VAT calculations β€” 7.5% in Nigeria, 15% in South Africa, applied correctly
  • ⚠No rounding errors β€” Amounts must use proper decimal handling, no floating-point issues

2. Status Flow Checks

  • Documents can only move through valid status transitions (Draft β†’ Posted, not Posted β†’ Draft)
  • Draft documents cannot appear in financial reports
  • Posted documents cannot be edited (only reversed via credit notes)
  • Cancelled documents create reversal entries in the GL

3. Data Isolation Checks

  • Organization A cannot see Organization B's data (test with two browser sessions)
  • Document numbers are unique per organization (both orgs can have INV-001)
  • Switching orgs clears all cached data from the previous org

4. Cross-Module Consistency

  • After posting a sales invoice: check GL, customer ledger, inventory ledger, and VAT ledger
  • After recording a payment: check bank ledger AND the invoice status changed to "Paid"
  • After a stock count adjustment: check inventory GL account matches new valuation
  • After a credit note: check the original invoice balance and the GL reversal

5. Edge Cases

  • Zero-amount invoices and credit notes
  • Overpayments (pay more than the invoice amount)
  • Partial payments across multiple invoices
  • Converting a quote with many line items (10+)
  • Items with 0% VAT rate
  • Deleting the last owner of an organization (should be blocked)
  • Very large amounts (test with amounts over ₦1 billion)
  • Special characters in customer/supplier names
  • Backdated transactions (posting to a previous month)

6. The "Follow the Money" Test

The Ultimate ERP Test

Pick any business scenario (sell goods, buy inventory, pay salaries) and trace the money through every system it touches. If you sell goods on credit and then receive payment, you should be able to see: (1) the invoice, (2) the GL journal entry from the invoice, (3) the customer ledger entry, (4) the receipt, (5) the GL journal entry from the receipt, (6) the bank ledger entry, (7) the invoice status changed to "Paid", (8) the customer balance went to zero. If any link in the chain is missing or wrong, you've found a bug.

12ERP Glossary

Quick reference for terms you will encounter

TermDefinitionExample in Commas
AccountA category for recording transactionsSales Revenue (4000), Bank (1100)
Accounts Payable (AP)Money you owe to suppliersVendor Ledger shows AP per supplier
Accounts Receivable (AR)Money customers owe youCustomer Ledger shows AR per customer
Aging ReportShows overdue amounts by time bucket (30/60/90 days)Reports > AR Aging or AP Aging
Balance SheetSnapshot of Assets, Liabilities, Equity at a point in timeReports > Balance Sheet
BillInvoice FROM a supplier (what you owe them)Purchasing > Bills
Chart of Accounts (CoA)Master list of all accounts in the systemGeneral Ledger > Chart of Accounts
Credit NoteReversal or reduction of an invoiceSales > Credit Notes or Purchasing > Credit Notes
DebitLeft side of a journal entryIncreases assets and expenses
CreditRight side of a journal entryIncreases liabilities, equity, and revenue
Double EntryEvery transaction has equal debits and creditsAll postings in Commas use double-entry
Fiscal YearThe 12-month period used for financial reportingSettings > Organization > Financial Year
General Ledger (GL)Complete record of all financial transactionsGeneral Ledger > Journal Entries
Goods ReceiptRecording that inventory was physically receivedPurchasing > Purchase Orders > Receive
Income StatementRevenue minus Expenses = Profit or LossReports > Income Statement (P&L)
InvoiceBill sent to a customer for goods/servicesSales > Invoices
Journal EntryA set of debit/credit lines that record a transactionGeneral Ledger > Journal Entries
NarrationDescription text on a journal entryAuto-generated or manual description
Opening BalanceStarting balances when migrating to a new systemSettings > Opening Balances
PostingFinalizing a document to create GL entriesClick "Post" on an invoice or bill
Posting GroupConfiguration that maps documents to GL accountsSettings > Posting Groups
Purchase Order (PO)Formal request to buy goods from a supplierPurchasing > Purchase Orders
QuotePrice proposal sent to a customerSales > Quotes
ReceiptRecord of payment received from a customerSales > Receipts
ReconciliationMatching system records to external records (bank statement)Banking > Reconciliation
RLSRow-Level Security β€” database enforces data isolation per orgEvery table filtered by org_id
Sales OrderConfirmed customer order before invoicingSales > Sales Orders
SubledgerDetailed breakdown of a GL account by entityCustomer Ledger, Vendor Ledger, Bank Ledger
Three-Way MatchMatching PO + Goods Receipt + Bill before paymentPurchasing module verification
Trial BalanceList of all account balances (must balance)Reports > Trial Balance
VATValue Added Tax β€” 7.5% Nigeria, 15% South AfricaAuto-calculated on invoices and bills