@accounter/server 0.0.9-alpha-20251231083050-a0e737863ca2a9fa68506d15357e55d9287972cb → 0.0.9-alpha-20251231163357-33d4c33fec5e21dad2e04d1f293f6248d2550588
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -5
- package/README.md +66 -3
- package/dist/server/scripts/seed-admin-context.js +20 -25
- package/dist/server/scripts/seed-admin-context.js.map +1 -1
- package/dist/server/src/__tests__/db-bootstrap.test.js +7 -2
- package/dist/server/src/__tests__/db-bootstrap.test.js.map +1 -1
- package/dist/server/src/__tests__/factories/business.d.ts +1 -1
- package/dist/server/src/__tests__/factories/financial-account.d.ts +1 -1
- package/dist/server/src/__tests__/factories/index.test.js +1 -0
- package/dist/server/src/__tests__/factories/index.test.js.map +1 -1
- package/dist/server/src/__tests__/factories/tax-category.d.ts +1 -1
- package/dist/server/src/__tests__/factories/tax-category.js +1 -1
- package/dist/server/src/__tests__/factories/tax-category.js.map +1 -1
- package/dist/server/src/__tests__/factories/tax-category.test.js +8 -6
- package/dist/server/src/__tests__/factories/tax-category.test.js.map +1 -1
- package/dist/server/src/__tests__/helpers/fixture-loader.d.ts +1 -1
- package/dist/server/src/__tests__/helpers/fixture-loader.js +25 -52
- package/dist/server/src/__tests__/helpers/fixture-loader.js.map +1 -1
- package/dist/server/src/__tests__/helpers/migration-verification.d.ts +1 -1
- package/dist/server/src/__tests__/helpers/migration-verification.js.map +1 -1
- package/dist/server/src/__tests__/helpers/seed-helpers.business.test.js +4 -4
- package/dist/server/src/__tests__/helpers/seed-helpers.business.test.js.map +1 -1
- package/dist/server/src/__tests__/helpers/seed-helpers.d.ts +9 -9
- package/dist/server/src/__tests__/helpers/seed-helpers.js +57 -54
- package/dist/server/src/__tests__/helpers/seed-helpers.js.map +1 -1
- package/dist/server/src/__tests__/seed-admin-context.integration.test.js +2 -1
- package/dist/server/src/__tests__/seed-admin-context.integration.test.js.map +1 -1
- package/dist/server/src/demo-fixtures/__tests__/deterministic-uuid.test.js +3 -2
- package/dist/server/src/demo-fixtures/__tests__/deterministic-uuid.test.js.map +1 -1
- package/dist/server/src/demo-fixtures/__tests__/seed-and-validate.test.d.ts +1 -0
- package/dist/server/src/demo-fixtures/__tests__/seed-and-validate.test.js +69 -0
- package/dist/server/src/demo-fixtures/__tests__/seed-and-validate.test.js.map +1 -0
- package/dist/server/src/demo-fixtures/__tests__/use-case-registry.test.d.ts +1 -0
- package/dist/server/src/demo-fixtures/__tests__/use-case-registry.test.js +26 -0
- package/dist/server/src/demo-fixtures/__tests__/use-case-registry.test.js.map +1 -0
- package/dist/server/src/demo-fixtures/helpers/admin-context.d.ts +10 -0
- package/dist/server/src/demo-fixtures/helpers/admin-context.js +40 -0
- package/dist/server/src/demo-fixtures/helpers/admin-context.js.map +1 -0
- package/dist/server/src/demo-fixtures/helpers/placeholder.d.ts +45 -0
- package/dist/server/src/demo-fixtures/helpers/placeholder.js +50 -0
- package/dist/server/src/demo-fixtures/helpers/placeholder.js.map +1 -0
- package/dist/server/src/demo-fixtures/helpers/seed-exchange-rates.d.ts +21 -0
- package/dist/server/src/demo-fixtures/helpers/seed-exchange-rates.js +26 -0
- package/dist/server/src/demo-fixtures/helpers/seed-exchange-rates.js.map +1 -0
- package/dist/server/src/demo-fixtures/helpers/seed-vat.d.ts +20 -0
- package/dist/server/src/demo-fixtures/helpers/seed-vat.js +30 -0
- package/dist/server/src/demo-fixtures/helpers/seed-vat.js.map +1 -0
- package/dist/server/src/demo-fixtures/use-cases/equity/shareholder-dividend.d.ts +9 -0
- package/dist/server/src/demo-fixtures/use-cases/equity/shareholder-dividend.js +86 -0
- package/dist/server/src/demo-fixtures/use-cases/equity/shareholder-dividend.js.map +1 -0
- package/dist/server/src/demo-fixtures/use-cases/expenses/monthly-expense-foreign-currency.d.ts +12 -0
- package/dist/server/src/demo-fixtures/use-cases/expenses/monthly-expense-foreign-currency.js +375 -0
- package/dist/server/src/demo-fixtures/use-cases/expenses/monthly-expense-foreign-currency.js.map +1 -0
- package/dist/server/src/demo-fixtures/use-cases/income/client-payment-with-refund.d.ts +10 -0
- package/dist/server/src/demo-fixtures/use-cases/income/client-payment-with-refund.js +113 -0
- package/dist/server/src/demo-fixtures/use-cases/income/client-payment-with-refund.js.map +1 -0
- package/dist/server/src/demo-fixtures/use-cases/index.d.ts +41 -0
- package/dist/server/src/demo-fixtures/use-cases/index.js +50 -0
- package/dist/server/src/demo-fixtures/use-cases/index.js.map +1 -0
- package/dist/server/src/demo-fixtures/validate-demo-data.d.ts +1 -0
- package/dist/server/src/demo-fixtures/validate-demo-data.js +117 -0
- package/dist/server/src/demo-fixtures/validate-demo-data.js.map +1 -0
- package/dist/server/src/demo-fixtures/validators/ledger-validators.d.ts +349 -0
- package/dist/server/src/demo-fixtures/validators/ledger-validators.js +602 -0
- package/dist/server/src/demo-fixtures/validators/ledger-validators.js.map +1 -0
- package/dist/server/src/demo-fixtures/validators/ledger-validators.test.d.ts +1 -0
- package/dist/server/src/demo-fixtures/validators/ledger-validators.test.js +247 -0
- package/dist/server/src/demo-fixtures/validators/ledger-validators.test.js.map +1 -0
- package/dist/server/src/demo-fixtures/validators/types.d.ts +69 -0
- package/dist/server/src/demo-fixtures/validators/types.js +8 -0
- package/dist/server/src/demo-fixtures/validators/types.js.map +1 -0
- package/dist/server/src/fixtures/fixture-spec.d.ts +146 -0
- package/dist/server/src/fixtures/fixture-spec.js +2 -0
- package/dist/server/src/fixtures/fixture-spec.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/single-match-integration.test.js +4 -0
- package/dist/server/src/modules/charges-matcher/__tests__/single-match-integration.test.js.map +1 -1
- package/dist/server/src/modules/deel/resolvers/deel.resolvers.js +0 -3
- package/dist/server/src/modules/deel/resolvers/deel.resolvers.js.map +1 -1
- package/dist/server/src/modules/ledger/__tests__/ledger-scenario-a.integration.test.js +4 -3
- package/dist/server/src/modules/ledger/__tests__/ledger-scenario-a.integration.test.js.map +1 -1
- package/dist/server/src/modules/ledger/__tests__/ledger-scenario-b.integration.test.js +5 -3
- package/dist/server/src/modules/ledger/__tests__/ledger-scenario-b.integration.test.js.map +1 -1
- package/dist/server/src/shared/constants.d.ts +1 -0
- package/dist/server/src/shared/constants.js +1 -0
- package/dist/server/src/shared/constants.js.map +1 -1
- package/dist/server/src/shared/helpers/misc.js +2 -2
- package/dist/server/src/shared/helpers/misc.js.map +1 -1
- package/docs/demo-staging-guide.md +611 -0
- package/package.json +6 -3
- package/scripts/seed-admin-context.ts +22 -33
- package/src/__tests__/db-bootstrap.test.ts +9 -2
- package/src/__tests__/factories/business.ts +1 -1
- package/src/__tests__/factories/financial-account.ts +1 -1
- package/src/__tests__/factories/index.test.ts +1 -0
- package/src/__tests__/factories/tax-category.test.ts +8 -6
- package/src/__tests__/factories/tax-category.ts +2 -2
- package/src/__tests__/helpers/fixture-loader.ts +26 -61
- package/src/__tests__/helpers/migration-verification.ts +2 -2
- package/src/__tests__/helpers/seed-helpers.business.test.ts +4 -4
- package/src/__tests__/helpers/seed-helpers.ts +66 -75
- package/src/__tests__/seed-admin-context.integration.test.ts +2 -1
- package/src/demo-fixtures/__tests__/deterministic-uuid.test.ts +3 -2
- package/src/demo-fixtures/__tests__/seed-and-validate.test.ts +96 -0
- package/src/demo-fixtures/__tests__/use-case-registry.test.ts +27 -0
- package/src/demo-fixtures/helpers/admin-context.ts +59 -0
- package/src/demo-fixtures/helpers/placeholder.ts +50 -0
- package/src/demo-fixtures/helpers/seed-exchange-rates.ts +29 -0
- package/src/demo-fixtures/helpers/seed-vat.ts +35 -0
- package/src/demo-fixtures/use-cases/equity/shareholder-dividend.ts +88 -0
- package/src/demo-fixtures/use-cases/expenses/monthly-expense-foreign-currency.ts +377 -0
- package/src/demo-fixtures/use-cases/income/client-payment-with-refund.ts +115 -0
- package/src/demo-fixtures/use-cases/index.ts +52 -0
- package/src/demo-fixtures/validate-demo-data.ts +153 -0
- package/src/demo-fixtures/validators/README.md +190 -0
- package/src/demo-fixtures/validators/ledger-validators.test.ts +298 -0
- package/src/demo-fixtures/validators/ledger-validators.ts +711 -0
- package/src/demo-fixtures/validators/types.ts +83 -0
- package/src/fixtures/fixture-spec.ts +158 -0
- package/src/modules/charges-matcher/__tests__/single-match-integration.test.ts +6 -0
- package/src/modules/deel/resolvers/deel.resolvers.ts +0 -3
- package/src/modules/ledger/__tests__/ledger-scenario-a.integration.test.ts +4 -3
- package/src/modules/ledger/__tests__/ledger-scenario-b.integration.test.ts +6 -3
- package/src/shared/constants.ts +2 -0
- package/src/shared/helpers/misc.ts +2 -3
|
@@ -0,0 +1,611 @@
|
|
|
1
|
+
# Demo / Staging Dataset Developer Guide
|
|
2
|
+
|
|
3
|
+
**Owner**: Accounter Fullstack Team
|
|
4
|
+
**Status**: Active
|
|
5
|
+
**Last Updated**: 2024-11-30
|
|
6
|
+
**Related**: `docs/demo-staging-dataset-spec.md`, `docs/demo-staging-dataset-todo.md`
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Overview
|
|
11
|
+
|
|
12
|
+
The demo staging dataset system provides a **use-case-driven approach** to seeding rich,
|
|
13
|
+
deterministic financial data for staging environments. Each use-case represents a complete financial
|
|
14
|
+
scenario (e.g., "monthly expense with foreign currency", "shareholder dividend", "client payment +
|
|
15
|
+
refund cycle") that can be deployed with a single command.
|
|
16
|
+
|
|
17
|
+
### Key Features
|
|
18
|
+
|
|
19
|
+
- **Deterministic UUIDs**: Stable entity IDs across deploys via UUID v5 generation
|
|
20
|
+
- **Modular Registry**: Self-contained use-case fixtures with metadata
|
|
21
|
+
- **Destructive Reset**: Clean slate on each deploy (domain data only; schema preserved)
|
|
22
|
+
- **Production Safeguards**: Hard refusal to run in production environments
|
|
23
|
+
- **Comprehensive Validation**: Ledger balance checks, entity reconciliation, VAT verification
|
|
24
|
+
|
|
25
|
+
### Architecture Components
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
Use-Case Registry → Seed Orchestrator → Validation Layer
|
|
29
|
+
↓ ↓ ↓
|
|
30
|
+
TypeScript modules scripts/seed-demo validate-demo
|
|
31
|
+
(fixtures + meta) (DB population) (integrity checks)
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Quick Start
|
|
37
|
+
|
|
38
|
+
### Prerequisites
|
|
39
|
+
|
|
40
|
+
- Docker Compose Postgres running locally
|
|
41
|
+
- Migrations applied: `yarn workspace @accounter/migrations migration:run`
|
|
42
|
+
- Environment variables configured (see `.env.example`)
|
|
43
|
+
|
|
44
|
+
### Local Seed & Validate
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# Seed demo data (requires explicit flag)
|
|
48
|
+
ALLOW_DEMO_SEED=1 yarn seed:staging-demo
|
|
49
|
+
|
|
50
|
+
# Validate seeded data
|
|
51
|
+
yarn validate:demo
|
|
52
|
+
|
|
53
|
+
# Combined workflow (recommended)
|
|
54
|
+
ALLOW_DEMO_SEED=1 yarn seed:staging-demo && yarn validate:demo
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Expected Output
|
|
58
|
+
|
|
59
|
+
**Seed Script** (successful run):
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
✅ Connected to database
|
|
63
|
+
🧹 Clearing existing demo data...
|
|
64
|
+
✅ Domain tables cleared
|
|
65
|
+
✅ Seeding countries...
|
|
66
|
+
✅ Seeding FIAT exchange rates...
|
|
67
|
+
✅ Seeding VAT defaults...
|
|
68
|
+
✅ Creating admin business context...
|
|
69
|
+
✅ Admin Business ID: e153a289-b7e7-5735-8379-e62e859c88ab
|
|
70
|
+
📦 Loading 3 use-cases...
|
|
71
|
+
📦 Monthly Expense (Foreign Currency) (monthly-expense-foreign-currency)
|
|
72
|
+
📦 Shareholder Dividend (Q4 2024) (shareholder-dividend)
|
|
73
|
+
📦 Client Payment with Refund (client-payment-with-refund)
|
|
74
|
+
✅ All use-cases seeded successfully
|
|
75
|
+
✅ Updated .env file with DEFAULT_FINANCIAL_ENTITY_ID
|
|
76
|
+
✅ Demo data seed complete
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**Validation Script** (successful run):
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
✅ Demo data validation passed
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Adding a Use-Case
|
|
88
|
+
|
|
89
|
+
Follow these steps to create a new financial scenario fixture:
|
|
90
|
+
|
|
91
|
+
### Step 1: Create Use-Case File
|
|
92
|
+
|
|
93
|
+
Create a new file in the appropriate category folder:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
# Example: Adding a payroll use-case
|
|
97
|
+
touch packages/server/src/demo-fixtures/use-cases/payroll/monthly-salary-payment.ts
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Step 2: Define Use-Case Spec
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
// packages/server/src/demo-fixtures/use-cases/payroll/monthly-salary-payment.ts
|
|
104
|
+
|
|
105
|
+
import { Currency, CountryCode } from '@shared/enums'
|
|
106
|
+
import { makeUUID } from '../../helpers/deterministic-uuid.js'
|
|
107
|
+
import type { UseCaseSpec } from '../../types.js'
|
|
108
|
+
|
|
109
|
+
export const monthlySalaryPayment: UseCaseSpec = {
|
|
110
|
+
id: 'monthly-salary-payment',
|
|
111
|
+
name: 'Monthly Salary Payment',
|
|
112
|
+
description: 'Employee salary payment with tax withholding and social security deductions',
|
|
113
|
+
category: 'payroll',
|
|
114
|
+
fixtures: {
|
|
115
|
+
businesses: [
|
|
116
|
+
{
|
|
117
|
+
id: makeUUID('business', 'employee-john-doe'),
|
|
118
|
+
name: 'John Doe (Employee)',
|
|
119
|
+
country: CountryCode.Isr,
|
|
120
|
+
canSettleWithReceipt: true
|
|
121
|
+
}
|
|
122
|
+
],
|
|
123
|
+
taxCategories: [
|
|
124
|
+
{
|
|
125
|
+
id: makeUUID('tax-category', 'salary-expenses'),
|
|
126
|
+
name: 'Salary Expenses'
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
id: makeUUID('tax-category', 'bank-account-ils'),
|
|
130
|
+
name: 'Bank Account (ILS)'
|
|
131
|
+
}
|
|
132
|
+
],
|
|
133
|
+
financialAccounts: [
|
|
134
|
+
{
|
|
135
|
+
accountNumber: 'PAYROLL-ACCOUNT-001',
|
|
136
|
+
type: 'BANK_ACCOUNT',
|
|
137
|
+
ownerId: '{{ADMIN_BUSINESS_ID}}',
|
|
138
|
+
taxCategoryMappings: [
|
|
139
|
+
{
|
|
140
|
+
currency: Currency.Ils,
|
|
141
|
+
taxCategoryId: makeUUID('tax-category', 'bank-account-ils')
|
|
142
|
+
}
|
|
143
|
+
]
|
|
144
|
+
}
|
|
145
|
+
],
|
|
146
|
+
charges: [
|
|
147
|
+
{
|
|
148
|
+
id: makeUUID('charge', 'salary-payment-2024-11'),
|
|
149
|
+
ownerId: '{{ADMIN_BUSINESS_ID}}',
|
|
150
|
+
userDescription: 'November 2024 salary payment'
|
|
151
|
+
}
|
|
152
|
+
],
|
|
153
|
+
transactions: [
|
|
154
|
+
{
|
|
155
|
+
id: makeUUID('transaction', 'salary-payment-bank-transfer'),
|
|
156
|
+
chargeId: makeUUID('charge', 'salary-payment-2024-11'),
|
|
157
|
+
businessId: makeUUID('business', 'employee-john-doe'),
|
|
158
|
+
accountNumber: 'PAYROLL-ACCOUNT-001',
|
|
159
|
+
amount: '-15000', // 15,000 ILS expense
|
|
160
|
+
currency: Currency.Ils,
|
|
161
|
+
eventDate: '2024-11-30',
|
|
162
|
+
debitDate: '2024-11-30'
|
|
163
|
+
}
|
|
164
|
+
],
|
|
165
|
+
documents: [
|
|
166
|
+
{
|
|
167
|
+
id: makeUUID('document', 'salary-slip-2024-11'),
|
|
168
|
+
chargeId: makeUUID('charge', 'salary-payment-2024-11'),
|
|
169
|
+
creditorId: makeUUID('business', 'employee-john-doe'),
|
|
170
|
+
debtorId: '{{ADMIN_BUSINESS_ID}}',
|
|
171
|
+
serialNumber: 'PAY-2024-11-001',
|
|
172
|
+
type: 'RECEIPT',
|
|
173
|
+
date: '2024-11-30',
|
|
174
|
+
totalAmount: '15000',
|
|
175
|
+
currencyCode: Currency.Ils
|
|
176
|
+
}
|
|
177
|
+
]
|
|
178
|
+
},
|
|
179
|
+
metadata: {
|
|
180
|
+
author: 'your-name',
|
|
181
|
+
createdAt: '2024-11-30',
|
|
182
|
+
updatedAt: '2024-11-30'
|
|
183
|
+
},
|
|
184
|
+
expectations: {
|
|
185
|
+
ledgerRecordCount: 2, // Debit (salary expense) + Credit (bank account)
|
|
186
|
+
totalDebitILS: '15000.00',
|
|
187
|
+
totalCreditILS: '15000.00'
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Step 3: Register Use-Case
|
|
193
|
+
|
|
194
|
+
Update the registry to include your new use-case:
|
|
195
|
+
|
|
196
|
+
```typescript
|
|
197
|
+
// packages/server/src/demo-fixtures/use-cases/index.ts
|
|
198
|
+
|
|
199
|
+
import { monthlyExpenseForeignCurrency } from './expenses/monthly-expense-foreign-currency.js'
|
|
200
|
+
import { shareholderDividend } from './equity/shareholder-dividend.js'
|
|
201
|
+
import { clientPaymentWithRefund } from './income/client-payment-with-refund.js'
|
|
202
|
+
import { monthlySalaryPayment } from './payroll/monthly-salary-payment.js' // Add import
|
|
203
|
+
import type { UseCaseSpec } from '../types.js'
|
|
204
|
+
|
|
205
|
+
export const USE_CASE_REGISTRY: Record<string, UseCaseSpec[]> = {
|
|
206
|
+
expenses: [monthlyExpenseForeignCurrency],
|
|
207
|
+
equity: [shareholderDividend],
|
|
208
|
+
income: [clientPaymentWithRefund],
|
|
209
|
+
payroll: [monthlySalaryPayment] // Add to registry
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export function getAllUseCases(): UseCaseSpec[] {
|
|
213
|
+
return Object.values(USE_CASE_REGISTRY).flat()
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Step 4: Validate Locally
|
|
218
|
+
|
|
219
|
+
Test your new use-case before deploying:
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
# Run TypeScript compiler
|
|
223
|
+
yarn workspace @accounter/server tsc --noEmit
|
|
224
|
+
|
|
225
|
+
# Seed with your new use-case
|
|
226
|
+
ALLOW_DEMO_SEED=1 yarn seed:staging-demo
|
|
227
|
+
|
|
228
|
+
# Validate integrity
|
|
229
|
+
yarn validate:demo
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Step 5: Commit & Deploy
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
git add packages/server/src/demo-fixtures/use-cases/
|
|
236
|
+
git commit -m "feat(demo): add monthly salary payment use-case"
|
|
237
|
+
git push
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
The next staging deploy will automatically include your use-case.
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## Deterministic UUID Best Practices
|
|
245
|
+
|
|
246
|
+
### Naming Conventions
|
|
247
|
+
|
|
248
|
+
**Format**: Always use `kebab-case` for semantic names:
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
// ✅ Good
|
|
252
|
+
makeUUID('business', 'acme-consulting-llc')
|
|
253
|
+
makeUUID('charge', 'consulting-invoice-2024-11')
|
|
254
|
+
makeUUID('transaction', 'bank-transfer-usd-500')
|
|
255
|
+
|
|
256
|
+
// ❌ Bad
|
|
257
|
+
makeUUID('business', 'Acme Consulting LLC')
|
|
258
|
+
makeUUID('charge', 'consulting_invoice_2024_11')
|
|
259
|
+
makeUUID('transaction', 'BankTransfer500')
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Namespace Guidelines
|
|
263
|
+
|
|
264
|
+
**Entity Type as Namespace**: Use the entity type as the namespace to prevent collisions:
|
|
265
|
+
|
|
266
|
+
```typescript
|
|
267
|
+
// ✅ Good - Different entities, different namespaces
|
|
268
|
+
const businessId = makeUUID('business', 'acme-corp')
|
|
269
|
+
const chargeId = makeUUID('charge', 'acme-corp')
|
|
270
|
+
// These produce different UUIDs even with same name
|
|
271
|
+
|
|
272
|
+
// ❌ Bad - Risk of collision
|
|
273
|
+
const businessId = makeUUID('entities', 'acme-corp-business')
|
|
274
|
+
const chargeId = makeUUID('entities', 'acme-corp-charge')
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Stability Rules
|
|
278
|
+
|
|
279
|
+
**Never change a semantic name once deployed**:
|
|
280
|
+
|
|
281
|
+
```typescript
|
|
282
|
+
// ❌ BREAKING: Changing the name breaks external references
|
|
283
|
+
// Old version (deployed):
|
|
284
|
+
makeUUID('business', 'supplier-acme-llc')
|
|
285
|
+
|
|
286
|
+
// New version (breaks UUIDs):
|
|
287
|
+
makeUUID('business', 'supplier-acme-inc') // Different UUID!
|
|
288
|
+
|
|
289
|
+
// ✅ If entity changes, create a new version:
|
|
290
|
+
makeUUID('business', 'supplier-acme-llc-v2')
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### Uniqueness Verification
|
|
294
|
+
|
|
295
|
+
Combine entity type + descriptive name to ensure no collisions:
|
|
296
|
+
|
|
297
|
+
```typescript
|
|
298
|
+
// ✅ Good - Unique combinations
|
|
299
|
+
makeUUID('business', 'us-supplier-acme-llc')
|
|
300
|
+
makeUUID('business', 'uk-supplier-acme-ltd')
|
|
301
|
+
makeUUID('charge', 'november-expense-2024')
|
|
302
|
+
makeUUID('charge', 'december-expense-2024')
|
|
303
|
+
|
|
304
|
+
// ⚠️ Be specific to avoid accidental duplicates
|
|
305
|
+
makeUUID('business', 'supplier-1') // Too generic
|
|
306
|
+
makeUUID('business', 'supplier-2') // Better: 'supplier-acme-llc'
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Placeholder Usage
|
|
310
|
+
|
|
311
|
+
Use `{{ADMIN_BUSINESS_ID}}` for admin context references (resolved at seed time):
|
|
312
|
+
|
|
313
|
+
```typescript
|
|
314
|
+
// ✅ Good - Placeholder for runtime resolution
|
|
315
|
+
charges: [
|
|
316
|
+
{
|
|
317
|
+
id: makeUUID('charge', 'my-charge'),
|
|
318
|
+
ownerId: '{{ADMIN_BUSINESS_ID}}', // Replaced during seed
|
|
319
|
+
userDescription: 'Test charge',
|
|
320
|
+
},
|
|
321
|
+
],
|
|
322
|
+
|
|
323
|
+
// ❌ Bad - Hardcoded UUID breaks determinism
|
|
324
|
+
ownerId: 'e153a289-b7e7-5735-8379-e62e859c88ab', // Don't hardcode
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
## Troubleshooting
|
|
330
|
+
|
|
331
|
+
### Seed Script Issues
|
|
332
|
+
|
|
333
|
+
#### Error: "Refusing to seed demo data in production environment"
|
|
334
|
+
|
|
335
|
+
**Cause**: `NODE_ENV=production` is set.
|
|
336
|
+
|
|
337
|
+
**Solution**: This is intentional protection. Never run seed script in production.
|
|
338
|
+
|
|
339
|
+
```bash
|
|
340
|
+
# For local/staging only
|
|
341
|
+
NODE_ENV=development ALLOW_DEMO_SEED=1 yarn seed:staging-demo
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
#### Error: "ALLOW_DEMO_SEED=1 required to run demo seed"
|
|
347
|
+
|
|
348
|
+
**Cause**: Safety flag not set.
|
|
349
|
+
|
|
350
|
+
**Solution**: Explicitly enable seeding:
|
|
351
|
+
|
|
352
|
+
```bash
|
|
353
|
+
ALLOW_DEMO_SEED=1 yarn seed:staging-demo
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
---
|
|
357
|
+
|
|
358
|
+
#### Error: "Foreign key violation on business_id"
|
|
359
|
+
|
|
360
|
+
**Cause**: Use-case references a business that doesn't exist in fixtures.
|
|
361
|
+
|
|
362
|
+
**Solution**: Ensure all referenced entities are defined in the use-case:
|
|
363
|
+
|
|
364
|
+
```typescript
|
|
365
|
+
// ❌ Bad - Transaction references undefined business
|
|
366
|
+
transactions: [
|
|
367
|
+
{
|
|
368
|
+
businessId: makeUUID('business', 'some-vendor'), // Not in fixtures.businesses!
|
|
369
|
+
// ...
|
|
370
|
+
},
|
|
371
|
+
],
|
|
372
|
+
|
|
373
|
+
// ✅ Good - Business defined in fixtures
|
|
374
|
+
fixtures: {
|
|
375
|
+
businesses: [
|
|
376
|
+
{
|
|
377
|
+
id: makeUUID('business', 'some-vendor'),
|
|
378
|
+
name: 'Some Vendor LLC',
|
|
379
|
+
country: CountryCode.Usa,
|
|
380
|
+
},
|
|
381
|
+
],
|
|
382
|
+
transactions: [
|
|
383
|
+
{
|
|
384
|
+
businessId: makeUUID('business', 'some-vendor'), // Reference exists
|
|
385
|
+
// ...
|
|
386
|
+
},
|
|
387
|
+
],
|
|
388
|
+
},
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
---
|
|
392
|
+
|
|
393
|
+
#### Error: "Fixture insertion failed"
|
|
394
|
+
|
|
395
|
+
**Cause**: Validation failed or database constraint violation.
|
|
396
|
+
|
|
397
|
+
**Solution**: Check detailed error in stack trace. Common issues:
|
|
398
|
+
|
|
399
|
+
1. **Missing required fields**: Ensure all NOT NULL columns have values
|
|
400
|
+
2. **Type mismatch**: Use `Currency.Ils` not `'ILS'` (enums required)
|
|
401
|
+
3. **Invalid dates**: Use ISO format `'2024-11-30'` not `'30/11/2024'`
|
|
402
|
+
4. **Amount format**: Use strings for numeric amounts: `'-500'` not `-500`
|
|
403
|
+
|
|
404
|
+
---
|
|
405
|
+
|
|
406
|
+
### Validation Script Issues
|
|
407
|
+
|
|
408
|
+
#### Error: "Accounter Admin Business entity missing"
|
|
409
|
+
|
|
410
|
+
**Cause**: Admin business context not created during seed.
|
|
411
|
+
|
|
412
|
+
**Solution**: Check `createAdminBusinessContext()` succeeded:
|
|
413
|
+
|
|
414
|
+
```bash
|
|
415
|
+
# Re-run seed with verbose logging
|
|
416
|
+
ALLOW_DEMO_SEED=1 yarn seed:staging-demo 2>&1 | grep -i "admin"
|
|
417
|
+
|
|
418
|
+
# Should see:
|
|
419
|
+
# ✅ Creating admin business context...
|
|
420
|
+
# ✅ Admin Business ID: e153a289-...
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
---
|
|
424
|
+
|
|
425
|
+
#### Error: "Charge count mismatch: expected X, got Y"
|
|
426
|
+
|
|
427
|
+
**Cause**: Seed script didn't insert all use-case charges.
|
|
428
|
+
|
|
429
|
+
**Solution**:
|
|
430
|
+
|
|
431
|
+
1. Check for seed errors (scroll up in terminal output)
|
|
432
|
+
2. Verify all use-cases registered in `use-cases/index.ts`
|
|
433
|
+
3. Re-run seed with clean DB:
|
|
434
|
+
|
|
435
|
+
```bash
|
|
436
|
+
# Reset DB (if needed)
|
|
437
|
+
yarn workspace @accounter/migrations db:reset
|
|
438
|
+
yarn workspace @accounter/migrations migration:run
|
|
439
|
+
|
|
440
|
+
# Re-seed
|
|
441
|
+
ALLOW_DEMO_SEED=1 yarn seed:staging-demo
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
---
|
|
445
|
+
|
|
446
|
+
#### Error: "Ledger unbalanced for charge X"
|
|
447
|
+
|
|
448
|
+
**Cause**: Ledger generation produced unbalanced entries (debits ≠ credits).
|
|
449
|
+
|
|
450
|
+
**Solution**: This indicates a bug in ledger generation logic, not the demo data. File an issue
|
|
451
|
+
with:
|
|
452
|
+
|
|
453
|
+
- Use-case ID
|
|
454
|
+
- Expected vs actual debit/credit totals
|
|
455
|
+
- Ledger records JSON (query DB directly)
|
|
456
|
+
|
|
457
|
+
---
|
|
458
|
+
|
|
459
|
+
### Import/TypeScript Issues
|
|
460
|
+
|
|
461
|
+
#### Error: "Cannot find module '@shared/enums'"
|
|
462
|
+
|
|
463
|
+
**Cause**: Missing or incorrect import path.
|
|
464
|
+
|
|
465
|
+
**Solution**: Ensure enums are imported correctly:
|
|
466
|
+
|
|
467
|
+
```typescript
|
|
468
|
+
// ✅ Good
|
|
469
|
+
import { Currency, CountryCode } from '@shared/enums'
|
|
470
|
+
|
|
471
|
+
// ❌ Bad
|
|
472
|
+
import { Currency } from '../../../shared/enums' // Relative path breaks
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
---
|
|
476
|
+
|
|
477
|
+
#### Error: "Type 'string' is not assignable to type 'Currency'"
|
|
478
|
+
|
|
479
|
+
**Cause**: Using string literals instead of enum values.
|
|
480
|
+
|
|
481
|
+
**Solution**: Use enum values:
|
|
482
|
+
|
|
483
|
+
```typescript
|
|
484
|
+
// ✅ Good
|
|
485
|
+
currency: Currency.Ils,
|
|
486
|
+
currencyCode: Currency.Usd,
|
|
487
|
+
|
|
488
|
+
// ❌ Bad
|
|
489
|
+
currency: 'ILS', // Type error
|
|
490
|
+
currencyCode: 'USD',
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
---
|
|
494
|
+
|
|
495
|
+
### Database Connection Issues
|
|
496
|
+
|
|
497
|
+
#### Error: "ECONNREFUSED 127.0.0.1:5432"
|
|
498
|
+
|
|
499
|
+
**Cause**: Postgres not running or wrong connection settings.
|
|
500
|
+
|
|
501
|
+
**Solution**:
|
|
502
|
+
|
|
503
|
+
```bash
|
|
504
|
+
# Check Postgres running
|
|
505
|
+
docker ps | grep postgres
|
|
506
|
+
|
|
507
|
+
# Start if not running
|
|
508
|
+
docker-compose -f docker/docker-compose.dev.yml up -d
|
|
509
|
+
|
|
510
|
+
# Verify env vars
|
|
511
|
+
cat .env | grep POSTGRES
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
---
|
|
515
|
+
|
|
516
|
+
## Render Build Command Example
|
|
517
|
+
|
|
518
|
+
### Staging Environment Configuration
|
|
519
|
+
|
|
520
|
+
**Build Command** (set in Render dashboard):
|
|
521
|
+
|
|
522
|
+
```bash
|
|
523
|
+
yarn install \
|
|
524
|
+
&& yarn build \
|
|
525
|
+
&& yarn workspace @accounter/migrations migration:run \
|
|
526
|
+
&& ALLOW_DEMO_SEED=1 yarn seed:staging-demo \
|
|
527
|
+
&& yarn validate:demo
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
**Breakdown**:
|
|
531
|
+
|
|
532
|
+
1. `yarn install` - Install dependencies
|
|
533
|
+
2. `yarn build` - Compile TypeScript
|
|
534
|
+
3. `yarn workspace @accounter/migrations migration:run` - Apply schema migrations
|
|
535
|
+
4. `ALLOW_DEMO_SEED=1 yarn seed:staging-demo` - Seed demo data (with safety flag)
|
|
536
|
+
5. `yarn validate:demo` - Verify data integrity (fails deploy if validation errors)
|
|
537
|
+
|
|
538
|
+
### Environment Variables
|
|
539
|
+
|
|
540
|
+
Set these in Render dashboard for staging environment:
|
|
541
|
+
|
|
542
|
+
```bash
|
|
543
|
+
# Database
|
|
544
|
+
POSTGRES_HOST=<render-internal-postgres-host>
|
|
545
|
+
POSTGRES_PORT=5432
|
|
546
|
+
POSTGRES_DB=accounter_staging
|
|
547
|
+
POSTGRES_USER=accounter_user
|
|
548
|
+
POSTGRES_PASSWORD=<secret-from-render>
|
|
549
|
+
POSTGRES_SSL=1
|
|
550
|
+
|
|
551
|
+
# Environment
|
|
552
|
+
NODE_ENV=staging
|
|
553
|
+
ALLOW_DEMO_SEED=1
|
|
554
|
+
|
|
555
|
+
# Auth (set manually in dashboard)
|
|
556
|
+
AUTHORIZED_USERS=demo@accounter.local,admin@accounter.local
|
|
557
|
+
DEFAULT_FINANCIAL_ENTITY_ID=<auto-written-by-seed-script>
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
### Deployment Workflow
|
|
561
|
+
|
|
562
|
+
```
|
|
563
|
+
Git Push → Render Webhook → Build Command Execution:
|
|
564
|
+
1. Install
|
|
565
|
+
2. Build
|
|
566
|
+
3. Migrate
|
|
567
|
+
4. Seed ✅
|
|
568
|
+
5. Validate ✅
|
|
569
|
+
6. Deploy
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
If validation fails (exit code 1), Render will **not deploy** the build, preventing broken data from
|
|
573
|
+
reaching staging.
|
|
574
|
+
|
|
575
|
+
### Post-Deploy Verification
|
|
576
|
+
|
|
577
|
+
After successful deployment, verify via UI:
|
|
578
|
+
|
|
579
|
+
1. Navigate to staging URL: `https://accounter-staging.onrender.com`
|
|
580
|
+
2. Login with `AUTHORIZED_USERS` credentials
|
|
581
|
+
3. Check dashboard for:
|
|
582
|
+
- 3+ charges visible (one per use-case)
|
|
583
|
+
- Transactions in multiple currencies (ILS, USD)
|
|
584
|
+
- Ledger entries balanced
|
|
585
|
+
4. Spot-check foreign currency conversion (e.g., 500 USD → 1750 ILS @ 3.5 rate)
|
|
586
|
+
|
|
587
|
+
---
|
|
588
|
+
|
|
589
|
+
## Additional Resources
|
|
590
|
+
|
|
591
|
+
- **Specification**: `docs/demo-staging-dataset-spec.md` - Complete technical spec
|
|
592
|
+
- **Implementation Plan**: `docs/demo-staging-dataset-prompt-plan.md` - Step-by-step prompts
|
|
593
|
+
- **TODO Checklist**: `docs/demo-staging-dataset-todo.md` - Progress tracking
|
|
594
|
+
- **Fixture Loader**: `packages/server/src/__tests__/helpers/fixture-loader.ts` - DB insertion logic
|
|
595
|
+
- **Validators**: `packages/server/src/demo-fixtures/validators/` - Ledger validation rules
|
|
596
|
+
|
|
597
|
+
---
|
|
598
|
+
|
|
599
|
+
## Support
|
|
600
|
+
|
|
601
|
+
For questions or issues:
|
|
602
|
+
|
|
603
|
+
1. Check this guide's Troubleshooting section
|
|
604
|
+
2. Review seed script logs for detailed error messages
|
|
605
|
+
3. Inspect validation output for specific failures
|
|
606
|
+
4. File an issue with reproducible steps if bug suspected
|
|
607
|
+
|
|
608
|
+
---
|
|
609
|
+
|
|
610
|
+
**Last Updated**: 2024-11-30
|
|
611
|
+
**Maintained By**: Accounter Fullstack Team
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@accounter/server",
|
|
3
|
-
"version": "0.0.9-alpha-
|
|
3
|
+
"version": "0.0.9-alpha-20251231163357-33d4c33fec5e21dad2e04d1f293f6248d2550588",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "",
|
|
6
6
|
"license": "MIT",
|
|
@@ -14,10 +14,12 @@
|
|
|
14
14
|
"pgtyped": "yarn rimraf **/__generated__/*.types.ts; DATABASE_URL=$(node scripts/set-db-url.cjs) pgtyped -c $(node scripts/generate-local-pgconfig.cjs)",
|
|
15
15
|
"pgtyped:watch": "yarn pgtyped -w",
|
|
16
16
|
"seed:admin": "tsx scripts/seed-admin-context.ts",
|
|
17
|
+
"seed:admin-context": "tsx scripts/seed-admin-context.ts",
|
|
17
18
|
"server:build": "yarn build",
|
|
18
19
|
"server:build:prod": "yarn generate && yarn workspaces foreach --all --parallel --include @accounter/green-invoice-graphql --include @accounter/pcn874-generator --include @accounter/shaam-uniform-format-generator --include @accounter/shaam6111-generator run build && yarn build",
|
|
19
20
|
"server:dev": "yarn dev",
|
|
20
|
-
"start": "node dist/server/src/index.js"
|
|
21
|
+
"start": "node dist/server/src/index.js",
|
|
22
|
+
"validate:demo": "tsx src/demo-fixtures/validate-demo-data.ts"
|
|
21
23
|
},
|
|
22
24
|
"dependencies": {
|
|
23
25
|
"@accounter/green-invoice-graphql": "workspace:^",
|
|
@@ -54,7 +56,7 @@
|
|
|
54
56
|
"playwright": "1.57.0",
|
|
55
57
|
"reflect-metadata": "0.2.2",
|
|
56
58
|
"strip-indent": "4.1.1",
|
|
57
|
-
"zod": "4.
|
|
59
|
+
"zod": "4.2.1"
|
|
58
60
|
},
|
|
59
61
|
"devDependencies": {
|
|
60
62
|
"@slonik/pg-driver": "patch:@slonik/pg-driver@npm%3A48.4.1#~/.yarn/patches/@slonik-pg-driver-npm-48.4.1-79145eeaac.patch",
|
|
@@ -67,6 +69,7 @@
|
|
|
67
69
|
"rimraf": "6.1.2",
|
|
68
70
|
"slonik": "48.4.1",
|
|
69
71
|
"tsc-alias": "1.8.16",
|
|
72
|
+
"tsx": "4.20.6",
|
|
70
73
|
"typescript": "5.9.3"
|
|
71
74
|
},
|
|
72
75
|
"publishConfig": {
|