@happyvertical/smrt-ledgers 0.30.0

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.
@@ -0,0 +1,647 @@
1
+ import { PromptDefinition } from '@happyvertical/smrt-prompts';
2
+ import { ResolvedPromptAI } from '@happyvertical/smrt-prompts';
3
+ import { SmrtClassOptions } from '@happyvertical/smrt-core';
4
+ import { SmrtCollection } from '@happyvertical/smrt-core';
5
+ import { SmrtHierarchical } from '@happyvertical/smrt-core';
6
+ import { SmrtObject } from '@happyvertical/smrt-core';
7
+
8
+ export declare class Account extends SmrtHierarchical {
9
+ /**
10
+ * Tenant ID for multi-tenancy support (nullable for global accounts)
11
+ */
12
+ tenantId: string | null;
13
+ /**
14
+ * Account number (e.g., "1000", "5030")
15
+ */
16
+ number: string;
17
+ /**
18
+ * Account name (e.g., "Cash", "Coffee Expense")
19
+ */
20
+ name: string;
21
+ /**
22
+ * Account description
23
+ */
24
+ description: string;
25
+ /**
26
+ * Account type - one of the 5 core types
27
+ */
28
+ type: AccountType;
29
+ /**
30
+ * Whether the account is active
31
+ */
32
+ active: boolean;
33
+ /**
34
+ * Extensible metadata
35
+ */
36
+ metadata: Record<string, unknown>;
37
+ constructor(options?: AccountOptions);
38
+ /**
39
+ * Check if this is a top-level account (no parent)
40
+ */
41
+ isTopLevel(): boolean;
42
+ /**
43
+ * Check if this is a debit-normal account (Asset, Expense)
44
+ * Debit-normal accounts increase with debits
45
+ */
46
+ isDebitNormal(): boolean;
47
+ /**
48
+ * Check if this is a credit-normal account (Liability, Equity, Revenue)
49
+ * Credit-normal accounts increase with credits
50
+ */
51
+ isCreditNormal(): boolean;
52
+ /**
53
+ * Get full account path (e.g., "Assets > Current > Cash")
54
+ */
55
+ getFullPath(): Promise<string>;
56
+ /**
57
+ * Build tree node for this account and its children
58
+ */
59
+ toTreeNode(): Promise<AccountTreeNode>;
60
+ /**
61
+ * Get the current balance of this account
62
+ */
63
+ getBalance(asOfDate?: Date): Promise<number>;
64
+ /**
65
+ * Create a sub-account under this account
66
+ */
67
+ createChild(options: Omit<AccountOptions, 'parentId' | 'type'>): Promise<Account>;
68
+ }
69
+
70
+ export declare class AccountCollection extends SmrtCollection<Account> {
71
+ static readonly _itemClass: typeof Account;
72
+ /**
73
+ * Find account by number
74
+ *
75
+ * @param number - Account number
76
+ * @returns Account or null
77
+ */
78
+ findByNumber(number: string): Promise<Account | null>;
79
+ /**
80
+ * Find accounts by type
81
+ *
82
+ * @param type - Account type
83
+ * @returns Array of accounts
84
+ */
85
+ findByType(type: AccountType): Promise<Account[]>;
86
+ /**
87
+ * Find all active accounts
88
+ *
89
+ * @returns Array of active accounts
90
+ */
91
+ findActive(): Promise<Account[]>;
92
+ /**
93
+ * Find top-level accounts (no parent)
94
+ *
95
+ * @returns Array of top-level accounts
96
+ */
97
+ findTopLevel(): Promise<Account[]>;
98
+ /**
99
+ * Find direct children of an account
100
+ *
101
+ * @param parentId - Parent account ID
102
+ * @returns Array of child accounts
103
+ */
104
+ findChildren(parentId: string): Promise<Account[]>;
105
+ /**
106
+ * Get the complete account tree
107
+ *
108
+ * @returns AccountTree structure
109
+ */
110
+ getTree(): Promise<AccountTree>;
111
+ /**
112
+ * Get or create an account by number
113
+ *
114
+ * @param number - Account number
115
+ * @param defaults - Default values if creating
116
+ * @returns Account
117
+ */
118
+ getOrCreateByNumber(number: string, defaults?: Partial<{
119
+ name: string;
120
+ description: string;
121
+ type: AccountType;
122
+ parentId: string | null;
123
+ }>): Promise<Account>;
124
+ /**
125
+ * Find accounts grouped by type
126
+ *
127
+ * @returns Record of type to accounts array
128
+ */
129
+ groupByType(): Promise<Record<AccountType, Account[]>>;
130
+ /**
131
+ * Get all descendants of an account recursively
132
+ *
133
+ * @param accountId - Account ID
134
+ * @returns Array of all descendant accounts
135
+ */
136
+ getDescendants(accountId: string): Promise<Account[]>;
137
+ /**
138
+ * Find all accounts belonging to a specific tenant
139
+ *
140
+ * @param tenantId - Tenant ID
141
+ * @returns Array of tenant's accounts
142
+ */
143
+ findByTenant(tenantId: string): Promise<Account[]>;
144
+ /**
145
+ * Find all global accounts (no tenant association)
146
+ *
147
+ * @returns Array of global accounts
148
+ */
149
+ findGlobal(): Promise<Account[]>;
150
+ /**
151
+ * Find accounts for a tenant plus all global accounts
152
+ *
153
+ * @param tenantId - Tenant ID
154
+ * @returns Array of tenant's accounts and global accounts
155
+ */
156
+ findWithGlobals(tenantId: string): Promise<Account[]>;
157
+ }
158
+
159
+ /**
160
+ * Options for creating an Account
161
+ */
162
+ export declare interface AccountOptions extends SmrtClassOptions {
163
+ tenantId?: string | null;
164
+ number?: string;
165
+ name?: string;
166
+ description?: string;
167
+ type?: AccountType;
168
+ parentId?: string | null;
169
+ active?: boolean;
170
+ metadata?: Record<string, unknown>;
171
+ }
172
+
173
+ /**
174
+ * Account tree structure
175
+ */
176
+ export declare interface AccountTree {
177
+ roots: AccountTreeNode[];
178
+ }
179
+
180
+ /**
181
+ * Account tree node for hierarchical display
182
+ */
183
+ export declare interface AccountTreeNode {
184
+ account: Account;
185
+ children: AccountTreeNode[];
186
+ }
187
+
188
+ /**
189
+ * The five core account types in double-entry accounting
190
+ */
191
+ export declare type AccountType = 'asset' | 'liability' | 'equity' | 'revenue' | 'expense';
192
+
193
+ /**
194
+ * Data for creating a complete journal with entries
195
+ */
196
+ export declare interface CreateJournalData {
197
+ date?: Date;
198
+ description: string;
199
+ sourceModule?: string;
200
+ sourceRef?: string | null;
201
+ entries: JournalEntryData[];
202
+ metadata?: Record<string, unknown>;
203
+ }
204
+
205
+ export declare class Journal extends SmrtObject {
206
+ /**
207
+ * Tenant ID for multi-tenancy support (nullable for global journals)
208
+ */
209
+ tenantId: string | null;
210
+ /**
211
+ * Journal number (auto-generated sequence, e.g., "JNL-0001")
212
+ */
213
+ number: string;
214
+ /**
215
+ * Transaction date
216
+ */
217
+ date: Date;
218
+ /**
219
+ * Description of the financial event
220
+ */
221
+ description: string;
222
+ /**
223
+ * Source module that created this journal (e.g., "smrt-commerce", "manual")
224
+ */
225
+ sourceModule: string;
226
+ /**
227
+ * External reference (e.g., order ID, invoice number)
228
+ */
229
+ sourceRef: string | null;
230
+ /**
231
+ * Journal status: draft, posted, voided
232
+ */
233
+ status: JournalStatus;
234
+ /**
235
+ * When the journal was posted (finalized)
236
+ */
237
+ postedAt: Date | null;
238
+ /**
239
+ * When the journal was voided
240
+ */
241
+ voidedAt: Date | null;
242
+ /**
243
+ * Reason for voiding (if voided)
244
+ */
245
+ voidReason: string | null;
246
+ /**
247
+ * Extensible metadata
248
+ */
249
+ metadata: Record<string, unknown>;
250
+ constructor(options?: JournalOptions);
251
+ /**
252
+ * Check if journal is in draft status
253
+ */
254
+ isDraft(): boolean;
255
+ /**
256
+ * Check if journal has been posted
257
+ */
258
+ isPosted(): boolean;
259
+ /**
260
+ * Check if journal has been voided
261
+ */
262
+ isVoided(): boolean;
263
+ /**
264
+ * Check if journal can be modified
265
+ */
266
+ isEditable(): boolean;
267
+ /**
268
+ * Get all entries for this journal
269
+ */
270
+ getEntries(): Promise<JournalEntry[]>;
271
+ /**
272
+ * Calculate total debits
273
+ */
274
+ getTotalDebits(): Promise<number>;
275
+ /**
276
+ * Calculate total credits
277
+ */
278
+ getTotalCredits(): Promise<number>;
279
+ /**
280
+ * Check if journal entries are balanced (debits = credits)
281
+ */
282
+ isBalanced(): Promise<boolean>;
283
+ /**
284
+ * Add an entry to this journal (only if draft)
285
+ */
286
+ addEntry(data: JournalEntryData): Promise<void>;
287
+ /**
288
+ * Post the journal (finalize and make immutable)
289
+ */
290
+ post(): Promise<void>;
291
+ /**
292
+ * Void the journal (mark as cancelled with reason)
293
+ */
294
+ void(reason: string): Promise<void>;
295
+ /**
296
+ * AI-powered: Generate a summary of this journal.
297
+ *
298
+ * Uses the `smrtLedgers.journal.summarize` prompt registered via
299
+ * `@happyvertical/smrt-prompts`, allowing tenant- or instance-level
300
+ * overrides of the template, model, and parameters at runtime.
301
+ *
302
+ * Only non-PII journal fields (number, date, description, status, balanced
303
+ * flag) plus aggregate totals and entry count are sent to the AI provider.
304
+ * Internal foreign-key fields (tenantId, sourceRef, individual entry
305
+ * account IDs) and the extensible `metadata` blob are intentionally
306
+ * excluded.
307
+ *
308
+ * @returns Generated summary text
309
+ */
310
+ summarize(): Promise<string>;
311
+ }
312
+
313
+ export declare class JournalCollection extends SmrtCollection<Journal> {
314
+ static readonly _itemClass: typeof Journal;
315
+ /**
316
+ * Generate next journal number
317
+ *
318
+ * Uses timestamp and random component to avoid collisions
319
+ * in concurrent environments without relying on shared state.
320
+ */
321
+ private generateJournalNumber;
322
+ /**
323
+ * Find journal by number
324
+ *
325
+ * @param number - Journal number
326
+ * @returns Journal or null
327
+ */
328
+ findByNumber(number: string): Promise<Journal | null>;
329
+ /**
330
+ * Find journals by date range
331
+ *
332
+ * @param start - Start date
333
+ * @param end - End date
334
+ * @returns Array of journals
335
+ */
336
+ findByDateRange(start: Date, end: Date): Promise<Journal[]>;
337
+ /**
338
+ * Find journals by source module
339
+ *
340
+ * @param sourceModule - Source module name
341
+ * @returns Array of journals
342
+ */
343
+ findBySource(sourceModule: string): Promise<Journal[]>;
344
+ /**
345
+ * Find journals by status
346
+ *
347
+ * @param status - Journal status
348
+ * @returns Array of journals
349
+ */
350
+ findByStatus(status: JournalStatus): Promise<Journal[]>;
351
+ /**
352
+ * Find draft journals
353
+ *
354
+ * @returns Array of draft journals
355
+ */
356
+ findDrafts(): Promise<Journal[]>;
357
+ /**
358
+ * Find posted journals
359
+ *
360
+ * @returns Array of posted journals
361
+ */
362
+ findPosted(): Promise<Journal[]>;
363
+ /**
364
+ * Create a complete journal with entries
365
+ *
366
+ * @param data - Journal data with entries
367
+ * @returns Created journal
368
+ */
369
+ createWithEntries(data: CreateJournalData): Promise<Journal>;
370
+ /**
371
+ * Post a journal by ID
372
+ *
373
+ * @param journalId - Journal ID
374
+ * @returns Posted journal
375
+ */
376
+ post(journalId: string): Promise<Journal>;
377
+ /**
378
+ * Void a journal by ID
379
+ *
380
+ * @param journalId - Journal ID
381
+ * @param reason - Reason for voiding
382
+ * @returns Voided journal
383
+ */
384
+ void(journalId: string, reason: string): Promise<Journal>;
385
+ /**
386
+ * Find journals by source reference
387
+ *
388
+ * @param sourceRef - External reference
389
+ * @returns Array of journals
390
+ */
391
+ findBySourceRef(sourceRef: string): Promise<Journal[]>;
392
+ /**
393
+ * Get journals for a specific month
394
+ *
395
+ * @param year - Year
396
+ * @param month - Month (1-12)
397
+ * @returns Array of journals
398
+ */
399
+ findByMonth(year: number, month: number): Promise<Journal[]>;
400
+ /**
401
+ * Find all journals belonging to a specific tenant
402
+ *
403
+ * @param tenantId - Tenant ID
404
+ * @returns Array of tenant's journals
405
+ */
406
+ findByTenant(tenantId: string): Promise<Journal[]>;
407
+ /**
408
+ * Find all global journals (no tenant association)
409
+ *
410
+ * @returns Array of global journals
411
+ */
412
+ findGlobal(): Promise<Journal[]>;
413
+ /**
414
+ * Find journals for a tenant plus all global journals
415
+ *
416
+ * @param tenantId - Tenant ID
417
+ * @returns Array of tenant's journals and global journals
418
+ */
419
+ findWithGlobals(tenantId: string): Promise<Journal[]>;
420
+ }
421
+
422
+ export declare class JournalEntry extends SmrtObject {
423
+ /**
424
+ * Tenant ID for multi-tenancy support (nullable for global entries)
425
+ */
426
+ tenantId: string | null;
427
+ /**
428
+ * Parent journal ID (required)
429
+ */
430
+ journalId: string;
431
+ /**
432
+ * Account ID (required)
433
+ */
434
+ accountId: string;
435
+ /**
436
+ * Debit amount (left side)
437
+ */
438
+ debit: number;
439
+ /**
440
+ * Credit amount (right side)
441
+ */
442
+ credit: number;
443
+ /**
444
+ * Currency code (e.g., "USD", "CAD", "EUR")
445
+ */
446
+ currency: string;
447
+ /**
448
+ * Exchange rate to base currency
449
+ */
450
+ exchangeRate: number;
451
+ /**
452
+ * Line memo/description
453
+ */
454
+ memo: string;
455
+ /**
456
+ * Extensible metadata
457
+ */
458
+ metadata: Record<string, unknown>;
459
+ constructor(options?: JournalEntryOptions);
460
+ /**
461
+ * Validate entry before save
462
+ */
463
+ protected validateBeforeSave(): Promise<void>;
464
+ /**
465
+ * Check if this is a debit entry
466
+ */
467
+ isDebit(): boolean;
468
+ /**
469
+ * Check if this is a credit entry
470
+ */
471
+ isCredit(): boolean;
472
+ /**
473
+ * Get the entry amount (positive value regardless of debit/credit)
474
+ */
475
+ getAmount(): number;
476
+ /**
477
+ * Get the amount in base currency
478
+ */
479
+ getBaseAmount(): number;
480
+ /**
481
+ * Get the parent journal
482
+ */
483
+ getJournal(): Promise<Journal | null>;
484
+ /**
485
+ * Get the account
486
+ */
487
+ getAccount(): Promise<Account | null>;
488
+ /**
489
+ * Get a formatted description of this entry
490
+ */
491
+ getDescription(): Promise<string>;
492
+ }
493
+
494
+ export declare class JournalEntryCollection extends SmrtCollection<JournalEntry> {
495
+ static readonly _itemClass: typeof JournalEntry;
496
+ /**
497
+ * Find entries by journal
498
+ *
499
+ * @param journalId - Journal ID
500
+ * @returns Array of entries
501
+ */
502
+ findByJournal(journalId: string): Promise<JournalEntry[]>;
503
+ /**
504
+ * Find entries by account
505
+ *
506
+ * @param accountId - Account ID
507
+ * @returns Array of entries
508
+ */
509
+ findByAccount(accountId: string): Promise<JournalEntry[]>;
510
+ /**
511
+ * Get account balance
512
+ *
513
+ * For debit-normal accounts (Asset, Expense): balance = debits - credits
514
+ * For credit-normal accounts (Liability, Equity, Revenue): balance = credits - debits
515
+ *
516
+ * @param accountId - Account ID
517
+ * @param asOfDate - Optional date to calculate balance as of
518
+ * @returns Account balance
519
+ */
520
+ getAccountBalance(accountId: string, asOfDate?: Date): Promise<number>;
521
+ /**
522
+ * Get trial balance
523
+ *
524
+ * @param asOfDate - Optional date for trial balance
525
+ * @returns Array of trial balance rows
526
+ */
527
+ getTrialBalance(asOfDate?: Date): Promise<TrialBalanceRow[]>;
528
+ /**
529
+ * Get total debits and credits for a date range
530
+ *
531
+ * @param start - Start date
532
+ * @param end - End date
533
+ * @returns Object with totalDebits and totalCredits
534
+ */
535
+ getTotalsForDateRange(start: Date, end: Date): Promise<{
536
+ totalDebits: number;
537
+ totalCredits: number;
538
+ }>;
539
+ /**
540
+ * Get entries for multiple accounts
541
+ *
542
+ * @param accountIds - Array of account IDs
543
+ * @returns Array of entries
544
+ */
545
+ findByAccounts(accountIds: string[]): Promise<JournalEntry[]>;
546
+ /**
547
+ * Get the running balance for an account (list of entries with running total)
548
+ *
549
+ * @param accountId - Account ID
550
+ * @returns Array of entries with running balance
551
+ */
552
+ getAccountLedger(accountId: string): Promise<Array<{
553
+ entry: JournalEntry;
554
+ runningBalance: number;
555
+ }>>;
556
+ /**
557
+ * Find all journal entries belonging to a specific tenant
558
+ *
559
+ * @param tenantId - Tenant ID
560
+ * @returns Array of tenant's journal entries
561
+ */
562
+ findByTenant(tenantId: string): Promise<JournalEntry[]>;
563
+ /**
564
+ * Find all global journal entries (no tenant association)
565
+ *
566
+ * @returns Array of global journal entries
567
+ */
568
+ findGlobal(): Promise<JournalEntry[]>;
569
+ /**
570
+ * Find journal entries for a tenant plus all global entries
571
+ *
572
+ * @param tenantId - Tenant ID
573
+ * @returns Array of tenant's entries and global entries
574
+ */
575
+ findWithGlobals(tenantId: string): Promise<JournalEntry[]>;
576
+ }
577
+
578
+ /**
579
+ * Entry data for creating journal entries
580
+ */
581
+ export declare interface JournalEntryData {
582
+ accountId: string;
583
+ debit?: number;
584
+ credit?: number;
585
+ currency?: string;
586
+ exchangeRate?: number;
587
+ memo?: string;
588
+ }
589
+
590
+ /**
591
+ * Options for creating a JournalEntry
592
+ */
593
+ export declare interface JournalEntryOptions extends SmrtClassOptions {
594
+ tenantId?: string | null;
595
+ journalId?: string;
596
+ accountId?: string;
597
+ debit?: number;
598
+ credit?: number;
599
+ currency?: string;
600
+ exchangeRate?: number;
601
+ memo?: string;
602
+ metadata?: Record<string, unknown>;
603
+ }
604
+
605
+ /**
606
+ * Options for creating a Journal
607
+ */
608
+ export declare interface JournalOptions extends SmrtClassOptions {
609
+ tenantId?: string | null;
610
+ number?: string;
611
+ date?: Date;
612
+ description?: string;
613
+ sourceModule?: string;
614
+ sourceRef?: string | null;
615
+ status?: JournalStatus;
616
+ postedAt?: Date | null;
617
+ voidedAt?: Date | null;
618
+ voidReason?: string | null;
619
+ metadata?: Record<string, unknown>;
620
+ }
621
+
622
+ /**
623
+ * Journal status lifecycle
624
+ */
625
+ export declare type JournalStatus = 'draft' | 'posted' | 'voided';
626
+
627
+ export declare function promptMessageOptions(ai: ResolvedPromptAI): {
628
+ maxTokens?: number | undefined;
629
+ temperature?: number | undefined;
630
+ model?: string | undefined;
631
+ };
632
+
633
+ export declare const smrtLedgersJournalSummarizePrompt: PromptDefinition;
634
+
635
+ /**
636
+ * A row in the trial balance report
637
+ */
638
+ export declare interface TrialBalanceRow {
639
+ accountId: string;
640
+ accountNumber: string;
641
+ accountName: string;
642
+ accountType: AccountType;
643
+ debitBalance: number;
644
+ creditBalance: number;
645
+ }
646
+
647
+ export { }