# Accounting — Phase 1

Multi-tenant accounting SaaS. Phase 1 covers the core accounting engine: Chart of Accounts, Journal Entries, General Ledger, Balance Sheet, and Profit & Loss.

---

## Requirements

- Node.js 18+
- MariaDB 10.6+

---

## Setup

### 1. Install dependencies

```bash
npm install
```

### 2. Configure environment

```bash
cp .env.example .env
```

Edit `.env` with your MariaDB credentials and a secure JWT secret:

```bash
# Generate a JWT secret
node -e "console.log(require('crypto').randomBytes(64).toString('hex'))"
```

Important production note:

- Set `TRUST_PROXY=1` when the app runs behind a reverse proxy such as Nginx, Apache, Cloudflare, or a load balancer. This allows Express and `express-rate-limit` to use the forwarded client IP correctly.
- Leave `TRUST_PROXY=false` in local development unless you are intentionally testing behind a proxy.

### 3. Create the database

```sql
-- Run in MariaDB as root:
CREATE DATABASE accounting CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'accounting'@'localhost' IDENTIFIED BY 'your_secure_password';
GRANT ALL PRIVILEGES ON accounting.* TO 'accounting'@'localhost';
FLUSH PRIVILEGES;
```

### 4. Run the migration

```bash
npm run migrate
```

This creates all Phase 1 tables.

### 5. Start the server

```bash
# Development (with auto-restart on file changes)
npm run dev

# Production
npm start
```

If you deploy behind a reverse proxy, your production environment should typically include:

```bash
NODE_ENV=production
PORT=3001
TRUST_PROXY=1
ALLOWED_ORIGIN=https://your-domain.com
```

Open `http://localhost:3000` in your browser.

---

## First use

1. Go to `http://localhost:3000`
2. Click **Create Account**
3. Enter your company name, your name, email, and password
4. A default chart of accounts (30+ accounts) is seeded automatically
5. You're in — start creating journal entries

---

## API Reference

All endpoints return:
```json
{ "success": true|false, "data": {}, "error": null|"message" }
```

Authentication header: `Authorization: Bearer <token>`

---

### Auth

#### Register (creates tenant + admin user)
```bash
curl -X POST http://localhost:3000/api/auth/register \
  -H "Content-Type: application/json" \
  -d '{"companyName":"Acme Corp","name":"Jane Smith","email":"jane@acme.com","password":"secret123"}'
```

#### Login
```bash
curl -X POST http://localhost:3000/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"jane@acme.com","password":"secret123"}'
```

#### Get current user
```bash
curl http://localhost:3000/api/auth/me \
  -H "Authorization: Bearer <token>"
```

---

### Chart of Accounts

#### List all accounts
```bash
curl http://localhost:3000/api/accounts \
  -H "Authorization: Bearer <token>"
```

#### Create an account
```bash
curl -X POST http://localhost:3000/api/accounts \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"code":"6000","name":"Travel Expense","type":"expense","parentId":null}'
```

#### Update an account
```bash
curl -X PUT http://localhost:3000/api/accounts/32 \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"code":"6000","name":"Travel and Entertainment","type":"expense"}'
```

#### Delete an account (soft delete)
```bash
curl -X DELETE http://localhost:3000/api/accounts/32 \
  -H "Authorization: Bearer <token>"
```

---

### Journal Entries

#### List entries (with optional filters)
```bash
curl "http://localhost:3000/api/journal?page=1&limit=20&from=2025-01-01&to=2025-12-31" \
  -H "Authorization: Bearer <token>"
```

#### Get a single entry (with lines)
```bash
curl http://localhost:3000/api/journal/1 \
  -H "Authorization: Bearer <token>"
```

#### Create a balanced entry
```bash
# Record $5,000 cash received as sales revenue
curl -X POST http://localhost:3000/api/journal \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "date": "2025-06-15",
    "memo": "Cash sale to customer",
    "lines": [
      {"accountId": 2, "debit": 5000, "credit": 0, "description": "Cash received"},
      {"accountId": 20, "debit": 0, "credit": 5000, "description": "Sales revenue"}
    ]
  }'
```

#### Delete an entry (admin only, soft delete)
```bash
curl -X DELETE http://localhost:3000/api/journal/1 \
  -H "Authorization: Bearer <token>"
```

---

### General Ledger

#### All transactions
```bash
curl "http://localhost:3000/api/ledger?page=1&limit=100" \
  -H "Authorization: Bearer <token>"
```

#### Filter by account and date range
```bash
curl "http://localhost:3000/api/ledger?accountId=2&from=2025-01-01&to=2025-12-31" \
  -H "Authorization: Bearer <token>"
```

---

### Reports

#### Dashboard summary
```bash
curl http://localhost:3000/api/reports/dashboard \
  -H "Authorization: Bearer <token>"
```

#### Balance Sheet
```bash
curl "http://localhost:3000/api/reports/balance-sheet?asOf=2025-12-31" \
  -H "Authorization: Bearer <token>"
```

#### Profit & Loss
```bash
curl "http://localhost:3000/api/reports/profit-loss?from=2025-01-01&to=2025-12-31" \
  -H "Authorization: Bearer <token>"
```

---

## Architecture

```
accounting/
├── server.js               # Express app entry point
├── db/
│   ├── index.js            # MariaDB connection pool + transaction helper
│   ├── migrate.js          # Runs migration SQL
│   └── migrations/
│       └── 001_phase1.sql  # Phase 1 schema
├── middleware/
│   └── auth.js             # JWT validation, role guard
├── routes/
│   ├── auth.js             # Register, login, /me
│   ├── accounts.js         # Chart of accounts CRUD
│   ├── journal.js          # Journal entries CRUD (double-entry enforced)
│   ├── ledger.js           # General ledger viewer
│   └── reports.js          # Balance sheet, P&L, dashboard
└── public/
    ├── index.html          # SPA shell
    ├── css/style.css       # All styles
    └── js/
        ├── app.js          # Router, auth flow, nav
        ├── api.js          # Fetch wrapper, toast, modal, formatters
        └── pages/
            ├── dashboard.js
            ├── coa.js
            ├── journal.js
            ├── ledger.js
            └── reports.js
```

### Key design decisions

| Rule | Implementation |
|------|---------------|
| Multi-tenant isolation | `tenant_id` on every table; extracted from JWT, never from client |
| Double-entry integrity | Server enforces `SUM(debit) === SUM(credit)` before insert |
| Monetary precision | `DECIMAL(15,2)` everywhere — never FLOAT |
| Soft deletes | `is_deleted = 1` instead of hard DELETE |
| API envelope | All responses: `{ success, data, error }` |
| Auth | bcrypt (cost 12) + JWT (configurable expiry) |

---

## Roles

| Role | Permissions |
|------|------------|
| `admin` | Full access including deletes |
| `accountant` | Create/edit accounts and journal entries; no delete |

---

---

## Phase 2 — AR/AP Quick Reference

### Customers
```bash
# Create
curl -X POST http://localhost:3000/api/customers \
  -H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
  -d '{"name":"Acme Corp","email":"billing@acme.com","phone":"555-1234"}'

# List
curl http://localhost:3000/api/customers -H "Authorization: Bearer <token>"

# Get with invoice history
curl http://localhost:3000/api/customers/1 -H "Authorization: Bearer <token>"
```

### Invoices
```bash
# Create invoice (auto-posts DR Accounts Receivable / CR Sales Revenue)
curl -X POST http://localhost:3000/api/invoices \
  -H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
  -d '{
    "customerId": 1,
    "issueDate": "2025-06-01",
    "dueDate": "2025-06-30",
    "revenueAccountId": 20,
    "tax": 0,
    "lines": [
      {"description":"Consulting services","quantity":10,"unitPrice":150}
    ]
  }'

# Record payment (auto-posts DR Cash / CR Accounts Receivable)
curl -X POST http://localhost:3000/api/invoices/1/payments \
  -H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
  -d '{"amount":1500,"paymentDate":"2025-06-15","method":"bank_transfer"}'
```

### Vendors & Bills
```bash
# Create vendor
curl -X POST http://localhost:3000/api/vendors \
  -H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
  -d '{"name":"Office Supplies Co","email":"ap@supplies.com"}'

# Create bill (status=received posts DR Expense / CR Accounts Payable)
curl -X POST http://localhost:3000/api/bills \
  -H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
  -d '{
    "vendorId": 1,
    "billDate": "2025-06-01",
    "dueDate": "2025-06-30",
    "status": "received",
    "expenseAccountId": 28,
    "lines": [{"description":"Office supplies","quantity":1,"unitPrice":350}]
  }'

# Pay a bill (posts DR Accounts Payable / CR Cash)
curl -X POST http://localhost:3000/api/bills/1/payments \
  -H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
  -d '{"amount":350,"paymentDate":"2025-06-20","method":"check"}'
```

### Aging Reports
```bash
# AR Aging (what customers owe you)
curl http://localhost:3000/api/reports/ar-aging -H "Authorization: Bearer <token>"

# AP Aging (what you owe vendors)
curl http://localhost:3000/api/reports/ap-aging -H "Authorization: Bearer <token>"
```

---

## Phase 3 Preview

Phase 3 adds bank account management, CSV bank statement import, transaction matching engine, and reconciliation.
