WorkspaceAccountingSettings
WorkspaceAccountingSettings stores the per-workspace accounting configuration that governs how Well processes invoices, journal entries, and reporting for a given tenant. Each workspace has at most one settings row (enforced by a UNIQUE constraint on workspace_pk), making this effectively a 1-to-1 extension of the Workspace entity. The row is created by the onboarding/setup flow (seed or WorkspaceService) and subsequently updated either by the user via PUT /v1/workspaces/:id/accounting-settings or automatically by WorkspaceSelfIdentityService when invoice-extraction consensus is reached. It anchors the workspace's fiscal identity (base currency, country, accounting framework, business registration details) and configures two LedgerAccount defaults used by the journal-entry posting engine.
| Naming | Value |
|---|---|
| Object | WorkspaceAccountingSettings |
Resource type (JSON:API type) | workspace_accounting_settings |
| Collection / records root | โ (not a records root) |
| REST base | /v1/workspace-accounting-settings |
| Entity class | WorkspaceAccountingSettings |
Internal object. Not currently exposed on the public REST API. The operations below describe the intended contract.
API operations
| Operation | Method & path | Status |
|---|---|---|
| List | GET /v1/workspace-accounting-settings | ๐ก Planned |
| Retrieve | GET /v1/workspace-accounting-settings/{id} | ๐ก Planned |
| Create | POST /v1/workspace-accounting-settings | ๐ก Planned |
| Update | PATCH /v1/workspace-accounting-settings/{id} | ๐ก Planned |
| Delete | DELETE /v1/workspace-accounting-settings/{id} | ๐ก Planned |
Data model
Attributes
| Field | Type | Required | Constraints | Allowed values | Description |
|---|---|---|---|---|---|
| workspace_accounting_settings_id | string (UUID) | โ Yes | unique; default gen_random_uuid() | any valid UUID v4 | Public API identifier for this settings row. |
| base_currency | string (CurrencyCodeEnum) | null | โช No | nativeEnumName: currency_code_enum; nullable | ISO 4217 codes, e.g. EUR, USD, GBP (full set in CurrencyCodeEnum from @wellapp/shared) | The workspace's base accounting currency. Drives exchange-rate selection and multi-currency invoice normalization. |
| country | string (CountryCodeEnum) | null | โช No | nativeEnumName: country_code_enum; nullable | ISO 3166-1 alpha-2 codes, e.g. FR, DE, US (full set in CountryCodeEnum) | Jurisdiction of the workspace's registered entity. Used for tax defaults and accounting-framework recommendations. |
| accounting_framework | string (AccountingFrameworkEnum) | null | โช No | nativeEnumName: accounting_framework_enum; nullable. Note: PostgreSQL enum also retains the deprecated value 'MAR' (cannot be dropped); any existing 'MAR' rows were migrated to 'IFRS'. | PCG | IFRS | US_GAAP | SKR | Chart-of-accounts framework in use. Determines which ledger account plan is available and how journal-entry drafts are structured. |
| fiscal_year_start_month | integer | null | โช No | nullable; CHECK (fiscal_year_start_month >= 1 AND fiscal_year_start_month <= 12) when not null | 1โ12 | Month number (1 = January) on which the workspace's fiscal year begins. Null means not yet configured. |
| tax_id_value | string | null | โช No | length โค 50; nullable | โ | Workspace's tax registration number (e.g. VAT number, SIRET/SIREN, EIN). Extracted from invoices by WorkspaceSelfIdentityService via consensus. |
| tax_id_type | string | null | โช No | length โค 20; nullable | โ | Type label for tax_id_value (e.g. 'VAT', 'SIRET', 'EIN'). |
| registered_name | string | null | โช No | length โค 255; nullable | โ | Full legal registered name of the workspace entity, as it appears on official documents. |
| trade_name | string | null | โช No | length โค 100; nullable | โ | Operating / brand name of the workspace entity, if different from registered_name. |
| registered_value | string | null | โช No | length โค 100; nullable (widened from 50 in Migration20260427100000) | โ | Secondary registration identifier (e.g. SIREN, RCS number) distinct from the tax_id. Stores the plain numeric or alphanumeric value without a type prefix. |
| domain | string | null | โช No | length โค 253; nullable | โ | Primary web domain of the workspace entity (RFC 1035 max 253 chars). Used for identity matching and enrichment. |
| invoice_status_tolerance_pct | string (decimal 6,4) | โ Yes | NOT NULL; DEFAULT 0.0100; CHECK (invoice_status_tolerance_pct >= 0 AND invoice_status_tolerance_pct <= 1) | 0.0000โ1.0000 (inclusive) | Percentage-of-grand-total tolerance band for invoice payment_status recomputation. The larger of (grand_total ร pct) and invoice_status_tolerance_abs is used as the allowable rounding gap, then capped per InvoiceStatusRecomputeService plan ยง4.3. |
| invoice_status_tolerance_abs | string (decimal 12,2) | โ Yes | NOT NULL; DEFAULT 0.50; CHECK (invoice_status_tolerance_abs >= 0) | โฅ 0 | Absolute monetary tolerance (in base_currency) for invoice payment_status recomputation. Used in conjunction with invoice_status_tolerance_pct. |
| created_at | ๐ system โ Date | โ Yes | set once on insert; never updated | โ | Timestamp of row creation. |
| updated_at | ๐ system โ Date | undefined | โช No | set on insert and on every update via onUpdate hook | โ | Timestamp of last modification. |
| deleted_at | Date | null | โช No | nullable; soft-delete sentinel | โ | Soft-delete timestamp. Non-null means the settings row has been logically deleted. All active queries must filter deleted_at IS NULL. |
Relationships
| Name | Type | Required | Description |
|---|---|---|---|
| workspace | to-one (OneToOne owner side) | โ Yes | The workspace this settings row belongs to. This entity owns the foreign key (workspace_pk). The UNIQUE constraint on workspace_pk enforces the 1-to-1 cardinality at the DB level. |
| account_receivable_default | to-one (ManyToOne) | โช No | Default LedgerAccount used for the accounts-receivable line when the posting engine generates journal entries for outbound invoices. Nullable โ if absent, the posting engine falls back to plan-defined defaults. |
| account_payable_default | to-one (ManyToOne) | โช No | Default LedgerAccount used for the accounts-payable line when the posting engine generates journal entries for inbound invoices. Nullable โ if absent, the posting engine falls back to plan-defined defaults. |
System-computed
- workspace_accounting_settings_id: generated via gen_random_uuid() at insert; client must not supply this value.
- created_at: set by MikroORM onCreate hook at insert time; never overwritten.
- updated_at: set by MikroORM onCreate hook at insert and by onUpdate hook on every subsequent flush.
- deleted_at: written only by soft-delete logic; never set via the upsert API path.
- Row creation: WorkspaceService.setupWorkspace() creates the initial row via WorkspaceAccountingSettingsRepository.persist() during workspace onboarding. WorkspaceAccountingSettingsService.upsertByWorkspace() handles all subsequent writes (find-or-create semantics โ it creates the row if absent).
- Identity field auto-population: WorkspaceSelfIdentityService applies an N=2 consensus rule over WorkspaceIdentityExtraction rows before committing values (registered_name, tax_id_value, tax_id_type, registered_value, domain, trade_name, base_currency, country, accounting_framework) to this table automatically.
- accounting_framework PostgreSQL enum retains the deprecated 'MAR' value (removed from application code; cannot be dropped via ALTER TYPE). Any pre-existing 'MAR' rows were migrated to 'IFRS' by Migration20260409200000.
- Tolerance defaults: invoice_status_tolerance_pct defaults to 0.0100 (1%); invoice_status_tolerance_abs defaults to 0.50. Both are application-layer defaults that align with InvoiceStatusRecomputeService plan ยง4.3 caps.
Example
{
"data": {
"type": "workspace_accounting_settings",
"id": "c3a7e291-11b4-4f8a-9f2c-847bde2a0e11",
"attributes": {
"base_currency": "EUR",
"country": "FR",
"accounting_framework": "PCG",
"fiscal_year_start_month": 1,
"tax_id_value": "FR42501234567",
"tax_id_type": "VAT",
"registered_name": "Acme SAS",
"trade_name": "Acme",
"registered_value": "501234567",
"domain": "acme.com",
"invoice_status_tolerance_pct": "0.0100",
"invoice_status_tolerance_abs": "0.50",
"created_at": "2026-01-15T09:22:00.000Z",
"updated_at": "2026-04-03T14:10:55.000Z",
"deleted_at": null
},
"relationships": {
"workspace": {
"data": { "type": "workspaces", "id": "9f3b1c20-55ea-4a1b-b8f0-fe1234abcd99" }
},
"account_receivable_default": {
"data": { "type": "ledger_accounts", "id": "aab10000-0000-0000-0000-000000000001" }
},
"account_payable_default": {
"data": { "type": "ledger_accounts", "id": "aab10000-0000-0000-0000-000000000002" }
}
}
}
}apps/api/src/database/entities/WorkspaceAccountingSettings.ts ยท domain: financial-graph ยท tier: Infrastructure