@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.
Files changed (124) hide show
  1. package/CHANGELOG.md +27 -5
  2. package/README.md +66 -3
  3. package/dist/server/scripts/seed-admin-context.js +20 -25
  4. package/dist/server/scripts/seed-admin-context.js.map +1 -1
  5. package/dist/server/src/__tests__/db-bootstrap.test.js +7 -2
  6. package/dist/server/src/__tests__/db-bootstrap.test.js.map +1 -1
  7. package/dist/server/src/__tests__/factories/business.d.ts +1 -1
  8. package/dist/server/src/__tests__/factories/financial-account.d.ts +1 -1
  9. package/dist/server/src/__tests__/factories/index.test.js +1 -0
  10. package/dist/server/src/__tests__/factories/index.test.js.map +1 -1
  11. package/dist/server/src/__tests__/factories/tax-category.d.ts +1 -1
  12. package/dist/server/src/__tests__/factories/tax-category.js +1 -1
  13. package/dist/server/src/__tests__/factories/tax-category.js.map +1 -1
  14. package/dist/server/src/__tests__/factories/tax-category.test.js +8 -6
  15. package/dist/server/src/__tests__/factories/tax-category.test.js.map +1 -1
  16. package/dist/server/src/__tests__/helpers/fixture-loader.d.ts +1 -1
  17. package/dist/server/src/__tests__/helpers/fixture-loader.js +25 -52
  18. package/dist/server/src/__tests__/helpers/fixture-loader.js.map +1 -1
  19. package/dist/server/src/__tests__/helpers/migration-verification.d.ts +1 -1
  20. package/dist/server/src/__tests__/helpers/migration-verification.js.map +1 -1
  21. package/dist/server/src/__tests__/helpers/seed-helpers.business.test.js +4 -4
  22. package/dist/server/src/__tests__/helpers/seed-helpers.business.test.js.map +1 -1
  23. package/dist/server/src/__tests__/helpers/seed-helpers.d.ts +9 -9
  24. package/dist/server/src/__tests__/helpers/seed-helpers.js +57 -54
  25. package/dist/server/src/__tests__/helpers/seed-helpers.js.map +1 -1
  26. package/dist/server/src/__tests__/seed-admin-context.integration.test.js +2 -1
  27. package/dist/server/src/__tests__/seed-admin-context.integration.test.js.map +1 -1
  28. package/dist/server/src/demo-fixtures/__tests__/deterministic-uuid.test.js +3 -2
  29. package/dist/server/src/demo-fixtures/__tests__/deterministic-uuid.test.js.map +1 -1
  30. package/dist/server/src/demo-fixtures/__tests__/seed-and-validate.test.d.ts +1 -0
  31. package/dist/server/src/demo-fixtures/__tests__/seed-and-validate.test.js +69 -0
  32. package/dist/server/src/demo-fixtures/__tests__/seed-and-validate.test.js.map +1 -0
  33. package/dist/server/src/demo-fixtures/__tests__/use-case-registry.test.d.ts +1 -0
  34. package/dist/server/src/demo-fixtures/__tests__/use-case-registry.test.js +26 -0
  35. package/dist/server/src/demo-fixtures/__tests__/use-case-registry.test.js.map +1 -0
  36. package/dist/server/src/demo-fixtures/helpers/admin-context.d.ts +10 -0
  37. package/dist/server/src/demo-fixtures/helpers/admin-context.js +40 -0
  38. package/dist/server/src/demo-fixtures/helpers/admin-context.js.map +1 -0
  39. package/dist/server/src/demo-fixtures/helpers/placeholder.d.ts +45 -0
  40. package/dist/server/src/demo-fixtures/helpers/placeholder.js +50 -0
  41. package/dist/server/src/demo-fixtures/helpers/placeholder.js.map +1 -0
  42. package/dist/server/src/demo-fixtures/helpers/seed-exchange-rates.d.ts +21 -0
  43. package/dist/server/src/demo-fixtures/helpers/seed-exchange-rates.js +26 -0
  44. package/dist/server/src/demo-fixtures/helpers/seed-exchange-rates.js.map +1 -0
  45. package/dist/server/src/demo-fixtures/helpers/seed-vat.d.ts +20 -0
  46. package/dist/server/src/demo-fixtures/helpers/seed-vat.js +30 -0
  47. package/dist/server/src/demo-fixtures/helpers/seed-vat.js.map +1 -0
  48. package/dist/server/src/demo-fixtures/use-cases/equity/shareholder-dividend.d.ts +9 -0
  49. package/dist/server/src/demo-fixtures/use-cases/equity/shareholder-dividend.js +86 -0
  50. package/dist/server/src/demo-fixtures/use-cases/equity/shareholder-dividend.js.map +1 -0
  51. package/dist/server/src/demo-fixtures/use-cases/expenses/monthly-expense-foreign-currency.d.ts +12 -0
  52. package/dist/server/src/demo-fixtures/use-cases/expenses/monthly-expense-foreign-currency.js +375 -0
  53. package/dist/server/src/demo-fixtures/use-cases/expenses/monthly-expense-foreign-currency.js.map +1 -0
  54. package/dist/server/src/demo-fixtures/use-cases/income/client-payment-with-refund.d.ts +10 -0
  55. package/dist/server/src/demo-fixtures/use-cases/income/client-payment-with-refund.js +113 -0
  56. package/dist/server/src/demo-fixtures/use-cases/income/client-payment-with-refund.js.map +1 -0
  57. package/dist/server/src/demo-fixtures/use-cases/index.d.ts +41 -0
  58. package/dist/server/src/demo-fixtures/use-cases/index.js +50 -0
  59. package/dist/server/src/demo-fixtures/use-cases/index.js.map +1 -0
  60. package/dist/server/src/demo-fixtures/validate-demo-data.d.ts +1 -0
  61. package/dist/server/src/demo-fixtures/validate-demo-data.js +117 -0
  62. package/dist/server/src/demo-fixtures/validate-demo-data.js.map +1 -0
  63. package/dist/server/src/demo-fixtures/validators/ledger-validators.d.ts +349 -0
  64. package/dist/server/src/demo-fixtures/validators/ledger-validators.js +602 -0
  65. package/dist/server/src/demo-fixtures/validators/ledger-validators.js.map +1 -0
  66. package/dist/server/src/demo-fixtures/validators/ledger-validators.test.d.ts +1 -0
  67. package/dist/server/src/demo-fixtures/validators/ledger-validators.test.js +247 -0
  68. package/dist/server/src/demo-fixtures/validators/ledger-validators.test.js.map +1 -0
  69. package/dist/server/src/demo-fixtures/validators/types.d.ts +69 -0
  70. package/dist/server/src/demo-fixtures/validators/types.js +8 -0
  71. package/dist/server/src/demo-fixtures/validators/types.js.map +1 -0
  72. package/dist/server/src/fixtures/fixture-spec.d.ts +146 -0
  73. package/dist/server/src/fixtures/fixture-spec.js +2 -0
  74. package/dist/server/src/fixtures/fixture-spec.js.map +1 -0
  75. package/dist/server/src/modules/charges-matcher/__tests__/single-match-integration.test.js +4 -0
  76. package/dist/server/src/modules/charges-matcher/__tests__/single-match-integration.test.js.map +1 -1
  77. package/dist/server/src/modules/deel/resolvers/deel.resolvers.js +0 -3
  78. package/dist/server/src/modules/deel/resolvers/deel.resolvers.js.map +1 -1
  79. package/dist/server/src/modules/ledger/__tests__/ledger-scenario-a.integration.test.js +4 -3
  80. package/dist/server/src/modules/ledger/__tests__/ledger-scenario-a.integration.test.js.map +1 -1
  81. package/dist/server/src/modules/ledger/__tests__/ledger-scenario-b.integration.test.js +5 -3
  82. package/dist/server/src/modules/ledger/__tests__/ledger-scenario-b.integration.test.js.map +1 -1
  83. package/dist/server/src/shared/constants.d.ts +1 -0
  84. package/dist/server/src/shared/constants.js +1 -0
  85. package/dist/server/src/shared/constants.js.map +1 -1
  86. package/dist/server/src/shared/helpers/misc.js +2 -2
  87. package/dist/server/src/shared/helpers/misc.js.map +1 -1
  88. package/docs/demo-staging-guide.md +611 -0
  89. package/package.json +6 -3
  90. package/scripts/seed-admin-context.ts +22 -33
  91. package/src/__tests__/db-bootstrap.test.ts +9 -2
  92. package/src/__tests__/factories/business.ts +1 -1
  93. package/src/__tests__/factories/financial-account.ts +1 -1
  94. package/src/__tests__/factories/index.test.ts +1 -0
  95. package/src/__tests__/factories/tax-category.test.ts +8 -6
  96. package/src/__tests__/factories/tax-category.ts +2 -2
  97. package/src/__tests__/helpers/fixture-loader.ts +26 -61
  98. package/src/__tests__/helpers/migration-verification.ts +2 -2
  99. package/src/__tests__/helpers/seed-helpers.business.test.ts +4 -4
  100. package/src/__tests__/helpers/seed-helpers.ts +66 -75
  101. package/src/__tests__/seed-admin-context.integration.test.ts +2 -1
  102. package/src/demo-fixtures/__tests__/deterministic-uuid.test.ts +3 -2
  103. package/src/demo-fixtures/__tests__/seed-and-validate.test.ts +96 -0
  104. package/src/demo-fixtures/__tests__/use-case-registry.test.ts +27 -0
  105. package/src/demo-fixtures/helpers/admin-context.ts +59 -0
  106. package/src/demo-fixtures/helpers/placeholder.ts +50 -0
  107. package/src/demo-fixtures/helpers/seed-exchange-rates.ts +29 -0
  108. package/src/demo-fixtures/helpers/seed-vat.ts +35 -0
  109. package/src/demo-fixtures/use-cases/equity/shareholder-dividend.ts +88 -0
  110. package/src/demo-fixtures/use-cases/expenses/monthly-expense-foreign-currency.ts +377 -0
  111. package/src/demo-fixtures/use-cases/income/client-payment-with-refund.ts +115 -0
  112. package/src/demo-fixtures/use-cases/index.ts +52 -0
  113. package/src/demo-fixtures/validate-demo-data.ts +153 -0
  114. package/src/demo-fixtures/validators/README.md +190 -0
  115. package/src/demo-fixtures/validators/ledger-validators.test.ts +298 -0
  116. package/src/demo-fixtures/validators/ledger-validators.ts +711 -0
  117. package/src/demo-fixtures/validators/types.ts +83 -0
  118. package/src/fixtures/fixture-spec.ts +158 -0
  119. package/src/modules/charges-matcher/__tests__/single-match-integration.test.ts +6 -0
  120. package/src/modules/deel/resolvers/deel.resolvers.ts +0 -3
  121. package/src/modules/ledger/__tests__/ledger-scenario-a.integration.test.ts +4 -3
  122. package/src/modules/ledger/__tests__/ledger-scenario-b.integration.test.ts +6 -3
  123. package/src/shared/constants.ts +2 -0
  124. 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-20251231083050-a0e737863ca2a9fa68506d15357e55d9287972cb",
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.3.2"
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": {