Open Accounting Development Guide
Architecture Context
Multi-Tenant Data Flow
Request → Auth Middleware (JWT → user_id, tenant_id, role)
→ Tenant Middleware (sets schema name: "tenant_{uuid}")
→ Handler (validates input, extracts tenant context)
→ Service (business logic, orchestrates repositories)
→ Repository (schema-qualified queries: SELECT FROM {schema}.table)
Layer Responsibilities
| Layer | Owns | Does NOT Own |
|---|---|---|
| Handler | HTTP concerns, input validation, response formatting | Business logic, DB transactions |
| Service | Business rules, orchestration, cross-entity logic | HTTP details, direct SQL |
| Repository | Data access, schema qualification, query building | Business validation, HTTP context |
Key Files for Debugging
- •Tenant context:
internal/auth/middleware.go(JWT extraction) - •Schema routing:
internal/tenant/service.go(schema name generation) - •Demo detection: Check for
demo@example.comuser or demo tenant ID - •Multi-tenant queries: All repositories use
schemaNameparameter for table qualification
Testing Strategy
Decision Tree - Which Test Type?
Is the change in...
├── Repository layer? → Integration test (needs real DB)
│ └── File: internal/{domain}/*_test.go with //go:build integration
│
├── Service layer? → Unit test with mocked repository
│ └── File: internal/{domain}/*_test.go
│
├── Handler layer? → Unit test with mocked service
│ └── File: internal/{domain}/handlers_test.go
│
├── Frontend component? → Vitest component test
│ └── File: frontend/src/tests/components/*.test.ts
│
├── User-facing workflow? → E2E test
│ └── Demo flow? → frontend/e2e/demo-*.spec.ts
│ └── Regular flow? → frontend/e2e/*.spec.ts
Coverage Targets
| Layer | Target |
|---|---|
| Backend (unit + integration) | 90%+ |
| Frontend | 95%+ |
| Critical paths (auth, payments) | 95%+ |
| Demo interface | 100% E2E |
Demo E2E Priority
The demo at open-accounting.up.railway.app is the first impression for users. All demo functionality must have E2E coverage:
- •Login/logout flow
- •Dashboard widgets and navigation
- •CRUD operations (invoices, contacts, payments)
- •Report generation and exports
- •Error states and edge cases
Demo Mode Reference
Credentials
- •Email:
demo@example.com - •Password:
demo123 - •Live demo:
open-accounting.up.railway.app
Demo Data Seeding Flow
Login as demo@example.com → Backend checks if demo tenant exists → If not: creates tenant + schema + seeds demo data → If exists: optionally resets to fresh state (hourly on Railway)
Key Demo Files
| Purpose | Location |
|---|---|
| Seed logic | internal/tenant/demo_seed.go |
| Demo handlers | internal/tenant/handlers.go (demo reset endpoint) |
| E2E tests | frontend/e2e/demo-*.spec.ts |
| Test config | frontend/playwright.config.ts |
| Test reports | frontend/playwright-report-demo/ |
Multi-User Parallel Testing
E2E tests support parallel execution with isolated demo data:
- •Each test worker gets unique demo seed
- •Tenant IDs passed via URL parameters for data isolation
- •Prevents test interference when running in CI
Debugging Demo Issues
- •
Check tenant schema exists:
sqlSELECT schema_name FROM information_schema.schemata WHERE schema_name LIKE 'tenant_%';
- •
Verify seed data: Check
internal/tenant/demo_seed.gofor expected accounts/contacts/invoices - •
Check E2E logs: Review
frontend/playwright-report-demo/for failure screenshots and traces - •
Test locally:
cd frontend && bun run test:e2e:demo
Documentation Checklist
After implementing a feature or fix, update relevant docs:
| Change Type | Update |
|---|---|
| API change | docs/API.md |
| Architecture change | docs/ARCHITECTURE.md |
| Demo behavior change | README.md demo section |
| New E2E test patterns | docs/plans/ design doc |
| Translation keys added | Both messages/en.json and messages/et.json |
Plan Documents
For non-trivial work, create a design doc before implementation:
- •Location:
docs/plans/YYYY-MM-DD-{topic}-design.md - •Purpose: Capture decisions, trade-offs, implementation approach
- •Example:
docs/plans/2026-01-04-demo-data-reset-testing-design.md
Commit Message Format
feat: add new capability fix: resolve bug docs: documentation only test: add or update tests refactor: restructure without behavior change chore: maintenance tasks
Error Handling Patterns
Tenant Validation (Frontend)
All action handlers must validate tenant context and show errors to users:
import { requireTenantId, parseApiError } from '$lib/utils/tenant';
import ErrorAlert from '$lib/components/ErrorAlert.svelte';
// In action handler:
async function doAction() {
const tenantId = requireTenantId($page, (err) => (error = err));
if (!tenantId) return; // Shows error to user automatically
actionLoading = true;
error = '';
try {
await api.someAction(tenantId, ...);
success = 'Action completed';
} catch (err) {
error = parseApiError(err); // Handles 403, 401, network errors
} finally {
actionLoading = false;
}
}
Common Error Types
| Error | Cause | User Message |
|---|---|---|
| No tenant | URL missing ?tenant= param | "Please select an organization first" |
| Access denied | User not member of tenant | "Access denied to this organization" |
| Session expired | JWT expired | "Your session has expired. Please log in again." |
| Network error | API unreachable | "Network error. Please try again." |
Key Files
| Purpose | Location |
|---|---|
| Tenant validation | frontend/src/lib/utils/tenant.ts |
| Error alerts | frontend/src/lib/components/ErrorAlert.svelte |
| Global error page | frontend/src/routes/+error.svelte |
| API error parsing | frontend/src/lib/utils/tenant.ts (parseApiError) |
MCP Server
The project includes an MCP server for AI assistant integration.
Setup
cd mcp-server bun install bun run dev # Development
Add to Claude Code
claude mcp add open-accounting -- npx tsx /path/to/mcp-server/src/index.ts
Environment Variables
OPEN_ACCOUNTING_API_URL=http://localhost:8080 OPEN_ACCOUNTING_API_TOKEN=your-jwt-token
Available Tools
- •
list_invoices- List invoices with filters - •
create_invoice- Create new invoice - •
get_account_balance- Get account balance - •
generate_report- Generate financial reports - •
list_contacts- List customers/vendors - •
record_payment- Record a payment - •
get_chart_of_accounts- Get chart of accounts
Quick Reference
Common Commands
# Backend go test -race -cover ./... # Unit tests go test -tags=integration -race ./... # Integration tests go run ./cmd/api # Start API server # Frontend cd frontend bun run dev # Dev server bun test # Vitest unit tests bun run test:e2e # Playwright E2E bun run test:e2e:demo # Demo-specific E2E bun run check # TypeScript check bun run paraglide # Compile translations
Project URLs (Local)
- •API:
http://localhost:8080 - •Frontend:
http://localhost:5173 - •Swagger:
http://localhost:8080/swagger/