@happyvertical/smrt-ledgers 0.57.2 → 0.57.4
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/AGENTS.md +9 -0
- package/README.md +73 -0
- package/dist/chunks/{Account-b0RgfbjM.js → Account-IFuMKhPt.js} +42 -8
- package/dist/chunks/Account-IFuMKhPt.js.map +1 -0
- package/dist/chunks/Ledger-DwxK6NRF.js +68 -0
- package/dist/chunks/Ledger-DwxK6NRF.js.map +1 -0
- package/dist/collections/JournalEntries.d.ts +26 -0
- package/dist/collections/JournalEntries.d.ts.map +1 -1
- package/dist/collections/Journals.d.ts.map +1 -1
- package/dist/collections/Ledgers.d.ts +6 -0
- package/dist/collections/Ledgers.d.ts.map +1 -0
- package/dist/collections/index.d.ts +1 -0
- package/dist/collections/index.d.ts.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +380 -17
- package/dist/index.js.map +1 -1
- package/dist/manifest.json +639 -13
- package/dist/models/Account.d.ts +4 -0
- package/dist/models/Account.d.ts.map +1 -1
- package/dist/models/Journal.d.ts +9 -0
- package/dist/models/Journal.d.ts.map +1 -1
- package/dist/models/JournalEntry.d.ts +10 -0
- package/dist/models/JournalEntry.d.ts.map +1 -1
- package/dist/models/Ledger.d.ts +18 -0
- package/dist/models/Ledger.d.ts.map +1 -0
- package/dist/models/index.d.ts +1 -0
- package/dist/models/index.d.ts.map +1 -1
- package/dist/postings.d.ts +33 -0
- package/dist/postings.d.ts.map +1 -0
- package/dist/recipes.d.ts +9 -0
- package/dist/recipes.d.ts.map +1 -1
- package/dist/smrt-knowledge.json +475 -9
- package/dist/types.d.ts +23 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +5 -5
- package/dist/chunks/Account-b0RgfbjM.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { t as
|
|
1
|
+
import { t as Ledger } from "./chunks/Ledger-DwxK6NRF.js";
|
|
2
|
+
import { t as Account } from "./chunks/Account-IFuMKhPt.js";
|
|
2
3
|
import { BALANCE_EPSILON } from "./types.js";
|
|
3
|
-
import { ObjectRegistry, SmrtCollection, SmrtObject, SmrtRecipe, detectEngine, field, foreignKey, smrt } from "@happyvertical/smrt-core";
|
|
4
|
+
import { ObjectRegistry, SmrtCollection, SmrtObject, SmrtRecipe, detectEngine, digestRunOnceContent, field, foreignKey, runOnce, smrt } from "@happyvertical/smrt-core";
|
|
4
5
|
import { definePrompt, resolvePrompt } from "@happyvertical/smrt-prompts";
|
|
5
|
-
import { TenantScoped, queryGlobal, queryWithGlobals, tenantId } from "@happyvertical/smrt-tenancy";
|
|
6
|
+
import { TenantScoped, getTenantId, isSuperAdminBypass, isTenancyEnabled, queryGlobal, queryWithGlobals, tenantId, withTenant, withTenantGlobalRead } from "@happyvertical/smrt-tenancy";
|
|
6
7
|
import { BackfillTracker } from "@happyvertical/smrt-core/migrations";
|
|
7
8
|
//#region \0rolldown/runtime.js
|
|
8
9
|
var __defProp$2 = Object.defineProperty;
|
|
@@ -17,7 +18,7 @@ var __exportAll = (all, no_symbols) => {
|
|
|
17
18
|
};
|
|
18
19
|
//#endregion
|
|
19
20
|
//#region src/__smrt-register__.ts
|
|
20
|
-
ObjectRegistry.registerPackageManifest(JSON.parse(`{"version":"1.0.0","timestamp":0,"packageName":"@happyvertical/smrt-ledgers","packageVersion":"0.57.2","objects":{"@happyvertical/smrt-ledgers:AccountCollection":{"name":"accountcollection","className":"AccountCollection","qualifiedName":"@happyvertical/smrt-ledgers:AccountCollection","collection":"accounts","filePath":"/home/runner/work/smrt/smrt/packages/ledgers/src/collections/Accounts.ts","packageName":"@happyvertical/smrt-ledgers","fields":{},"methods":{"findByNumber":{"name":"findByNumber","async":true,"parameters":[{"name":"number","type":"string","optional":false}],"returnType":"Promise<Account | null>","isStatic":false,"isPublic":true},"findByType":{"name":"findByType","async":true,"parameters":[{"name":"type","type":"AccountType","optional":false}],"returnType":"Promise<Account[]>","isStatic":false,"isPublic":true},"findActive":{"name":"findActive","async":true,"parameters":[],"returnType":"Promise<Account[]>","isStatic":false,"isPublic":true},"findTopLevel":{"name":"findTopLevel","async":true,"parameters":[],"returnType":"Promise<Account[]>","isStatic":false,"isPublic":true},"findChildren":{"name":"findChildren","async":true,"parameters":[{"name":"parentId","type":"string","optional":false}],"returnType":"Promise<Account[]>","isStatic":false,"isPublic":true},"getTree":{"name":"getTree","async":true,"parameters":[],"returnType":"Promise<AccountTree>","isStatic":false,"isPublic":true},"getOrCreateByNumber":{"name":"getOrCreateByNumber","async":true,"parameters":[{"name":"number","type":"string","optional":false},{"name":"defaults","type":"Partial<object>","optional":true,"memberTypes":["string","AccountType","string | null"]}],"returnType":"Promise<Account>","isStatic":false,"isPublic":true},"groupByType":{"name":"groupByType","async":true,"parameters":[],"returnType":"Promise<Record<AccountType, Account[]>>","isStatic":false,"isPublic":true},"getDescendants":{"name":"getDescendants","async":true,"parameters":[{"name":"accountId","type":"string","optional":false}],"returnType":"Promise<Account[]>","isStatic":false,"isPublic":true},"findByTenant":{"name":"findByTenant","async":true,"parameters":[{"name":"tenantId","type":"string","optional":false}],"returnType":"Promise<Account[]>","isStatic":false,"isPublic":true},"findGlobal":{"name":"findGlobal","async":true,"parameters":[],"returnType":"Promise<Account[]>","isStatic":false,"isPublic":true},"findWithGlobals":{"name":"findWithGlobals","async":true,"parameters":[{"name":"tenantId","type":"string","optional":false}],"returnType":"Promise<Account[]>","isStatic":false,"isPublic":true}},"decoratorConfig":{"tableName":"ledger_accounts","api":{"include":["list","get","create","update","delete"]},"mcp":{"include":["list","get","create"]}},"extends":"SmrtCollection","extendsTypeArg":"Account","exportName":"AccountCollection","collectionExportName":"AccountCollectionCollection","schema":{"tableName":"ledger_accounts","ddl":"CREATE TABLE IF NOT EXISTS \\"ledger_accounts\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"parent_id\\" UUID,\\n \\"tenant_id\\" UUID,\\n \\"number\\" TEXT DEFAULT '',\\n \\"name\\" TEXT DEFAULT '',\\n \\"description\\" TEXT DEFAULT '',\\n \\"type\\" TEXT DEFAULT 'asset',\\n \\"active\\" BOOLEAN DEFAULT TRUE,\\n \\"metadata\\" JSON DEFAULT '{}'\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"parent_id":{"type":"UUID","referenceKind":"foreignKey","notNull":false,"unique":false,"foreignKey":{"table":"ledger_accounts","column":"id","onDelete":"NO ACTION","onUpdate":"CASCADE"}},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"number":{"type":"TEXT","notNull":false,"unique":false,"default":""},"name":{"type":"TEXT","notNull":false,"unique":false,"default":""},"description":{"type":"TEXT","notNull":false,"unique":false,"default":""},"type":{"type":"TEXT","notNull":false,"unique":false,"default":"asset"},"active":{"type":"BOOLEAN","notNull":false,"unique":false,"default":true},"metadata":{"type":"JSON","notNull":false,"unique":false,"default":{}}},"indexes":[{"name":"ledger_accounts_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true,"nullsNotDistinct":true},{"name":"ledger_accounts_tenant_id_created_at_idx","columns":["tenant_id","created_at"]},{"name":"ledger_accounts_parent_id_idx","columns":["parent_id"]}],"version":"49630dae"},"importPath":"@happyvertical/smrt-ledgers"},"@happyvertical/smrt-ledgers:JournalEntryCollection":{"name":"journalentrycollection","className":"JournalEntryCollection","qualifiedName":"@happyvertical/smrt-ledgers:JournalEntryCollection","collection":"journalentries","filePath":"/home/runner/work/smrt/smrt/packages/ledgers/src/collections/JournalEntries.ts","packageName":"@happyvertical/smrt-ledgers","fields":{},"methods":{"findByJournal":{"name":"findByJournal","async":true,"parameters":[{"name":"journalId","type":"string","optional":false}],"returnType":"Promise<JournalEntry[]>","isStatic":false,"isPublic":true},"findByAccount":{"name":"findByAccount","async":true,"parameters":[{"name":"accountId","type":"string","optional":false}],"returnType":"Promise<JournalEntry[]>","isStatic":false,"isPublic":true},"getAccountBalance":{"name":"getAccountBalance","async":true,"parameters":[{"name":"accountId","type":"string","optional":false},{"name":"asOfDate","type":"Date","optional":true}],"returnType":"Promise<number>","isStatic":false,"isPublic":true},"getTrialBalance":{"name":"getTrialBalance","async":true,"parameters":[{"name":"asOfDate","type":"Date","optional":true}],"returnType":"Promise<TrialBalanceRow[]>","isStatic":false,"isPublic":true},"getTotalsForDateRange":{"name":"getTotalsForDateRange","async":true,"parameters":[{"name":"start","type":"Date","optional":false},{"name":"end","type":"Date","optional":false}],"returnType":"Promise<object>","isStatic":false,"isPublic":true},"findByAccounts":{"name":"findByAccounts","async":true,"parameters":[{"name":"accountIds","type":"string[]","optional":false}],"returnType":"Promise<JournalEntry[]>","isStatic":false,"isPublic":true},"listPostedMovements":{"name":"listPostedMovements","async":true,"parameters":[{"name":"options","type":"PostedJournalMovementOptions","optional":false}],"returnType":"Promise<PostedJournalMovement[]>","isStatic":false,"isPublic":true},"getAccountLedger":{"name":"getAccountLedger","async":true,"parameters":[{"name":"accountId","type":"string","optional":false}],"returnType":"Promise<Array<object>>","isStatic":false,"isPublic":true},"findByTenant":{"name":"findByTenant","async":true,"parameters":[{"name":"tenantId","type":"string","optional":false}],"returnType":"Promise<JournalEntry[]>","isStatic":false,"isPublic":true},"findGlobal":{"name":"findGlobal","async":true,"parameters":[],"returnType":"Promise<JournalEntry[]>","isStatic":false,"isPublic":true},"findWithGlobals":{"name":"findWithGlobals","async":true,"parameters":[{"name":"tenantId","type":"string","optional":false}],"returnType":"Promise<JournalEntry[]>","isStatic":false,"isPublic":true}},"decoratorConfig":{"api":{"include":["list","get"]},"mcp":{"include":["list","get"]}},"extends":"SmrtCollection","extendsTypeArg":"JournalEntry","exportName":"JournalEntryCollection","collectionExportName":"JournalEntryCollectionCollection","schema":{"tableName":"journal_entries","ddl":"CREATE TABLE IF NOT EXISTS \\"journal_entries\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID,\\n \\"journal_id\\" UUID,\\n \\"account_id\\" UUID,\\n \\"debit\\" REAL DEFAULT 0,\\n \\"credit\\" REAL DEFAULT 0,\\n \\"currency\\" TEXT DEFAULT 'USD',\\n \\"exchange_rate\\" REAL DEFAULT 1,\\n \\"memo\\" TEXT DEFAULT '',\\n \\"metadata\\" JSON DEFAULT '{}'\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"journal_id":{"type":"UUID","referenceKind":"foreignKey","notNull":false,"unique":false,"foreignKey":{"table":"journals","column":"id","onDelete":"NO ACTION","onUpdate":"CASCADE"}},"account_id":{"type":"UUID","referenceKind":"foreignKey","notNull":false,"unique":false,"foreignKey":{"table":"ledger_accounts","column":"id","onDelete":"NO ACTION","onUpdate":"CASCADE"}},"debit":{"type":"REAL","notNull":false,"unique":false,"default":0},"credit":{"type":"REAL","notNull":false,"unique":false,"default":0},"currency":{"type":"TEXT","notNull":false,"unique":false,"default":"USD"},"exchange_rate":{"type":"REAL","notNull":false,"unique":false,"default":1},"memo":{"type":"TEXT","notNull":false,"unique":false,"default":""},"metadata":{"type":"JSON","notNull":false,"unique":false,"default":{}}},"indexes":[{"name":"journal_entries_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true,"nullsNotDistinct":true},{"name":"journal_entries_tenant_id_created_at_idx","columns":["tenant_id","created_at"]},{"name":"journal_entries_journal_id_idx","columns":["journal_id"]},{"name":"journal_entries_account_id_idx","columns":["account_id"]}],"version":"93cdc848"},"importPath":"@happyvertical/smrt-ledgers"},"@happyvertical/smrt-ledgers:JournalCollection":{"name":"journalcollection","className":"JournalCollection","qualifiedName":"@happyvertical/smrt-ledgers:JournalCollection","collection":"journals","filePath":"/home/runner/work/smrt/smrt/packages/ledgers/src/collections/Journals.ts","packageName":"@happyvertical/smrt-ledgers","fields":{},"methods":{"findByNumber":{"name":"findByNumber","async":true,"parameters":[{"name":"number","type":"string","optional":false}],"returnType":"Promise<Journal | null>","isStatic":false,"isPublic":true},"findByDateRange":{"name":"findByDateRange","async":true,"parameters":[{"name":"start","type":"Date","optional":false},{"name":"end","type":"Date","optional":false}],"returnType":"Promise<Journal[]>","isStatic":false,"isPublic":true},"findBySource":{"name":"findBySource","async":true,"parameters":[{"name":"sourceModule","type":"string","optional":false}],"returnType":"Promise<Journal[]>","isStatic":false,"isPublic":true},"findByStatus":{"name":"findByStatus","async":true,"parameters":[{"name":"status","type":"JournalStatus","optional":false}],"returnType":"Promise<Journal[]>","isStatic":false,"isPublic":true},"findDrafts":{"name":"findDrafts","async":true,"parameters":[],"returnType":"Promise<Journal[]>","isStatic":false,"isPublic":true},"findPosted":{"name":"findPosted","async":true,"parameters":[],"returnType":"Promise<Journal[]>","isStatic":false,"isPublic":true},"createWithEntries":{"name":"createWithEntries","async":true,"parameters":[{"name":"data","type":"CreateJournalData","optional":false}],"returnType":"Promise<Journal>","isStatic":false,"isPublic":true},"post":{"name":"post","async":true,"parameters":[{"name":"journalId","type":"string","optional":false}],"returnType":"Promise<Journal>","isStatic":false,"isPublic":true},"void":{"name":"void","async":true,"parameters":[{"name":"journalId","type":"string","optional":false},{"name":"reason","type":"string","optional":false}],"returnType":"Promise<Journal>","isStatic":false,"isPublic":true},"findBySourceRef":{"name":"findBySourceRef","async":true,"parameters":[{"name":"sourceRef","type":"string","optional":false}],"returnType":"Promise<Journal[]>","isStatic":false,"isPublic":true},"findByMonth":{"name":"findByMonth","async":true,"parameters":[{"name":"year","type":"number","optional":false},{"name":"month","type":"number","optional":false}],"returnType":"Promise<Journal[]>","isStatic":false,"isPublic":true},"findByTenant":{"name":"findByTenant","async":true,"parameters":[{"name":"tenantId","type":"string","optional":false}],"returnType":"Promise<Journal[]>","isStatic":false,"isPublic":true},"findGlobal":{"name":"findGlobal","async":true,"parameters":[],"returnType":"Promise<Journal[]>","isStatic":false,"isPublic":true},"findWithGlobals":{"name":"findWithGlobals","async":true,"parameters":[{"name":"tenantId","type":"string","optional":false}],"returnType":"Promise<Journal[]>","isStatic":false,"isPublic":true}},"decoratorConfig":{"api":{"include":["list","get","create"]},"mcp":{"include":["list","get","create"]}},"extends":"SmrtCollection","extendsTypeArg":"Journal","exportName":"JournalCollection","collectionExportName":"JournalCollectionCollection","schema":{"tableName":"journals","ddl":"CREATE TABLE IF NOT EXISTS \\"journals\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID,\\n \\"number\\" TEXT DEFAULT '',\\n \\"date\\" TIMESTAMP,\\n \\"description\\" TEXT DEFAULT '',\\n \\"source_module\\" TEXT DEFAULT '',\\n \\"source_ref\\" TEXT,\\n \\"status\\" TEXT DEFAULT 'draft',\\n \\"posted_at\\" TIMESTAMP,\\n \\"voided_at\\" TIMESTAMP,\\n \\"void_reason\\" TEXT,\\n \\"metadata\\" JSON DEFAULT '{}'\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"number":{"type":"TEXT","notNull":false,"unique":false,"default":""},"date":{"type":"TIMESTAMP","notNull":false,"unique":false},"description":{"type":"TEXT","notNull":false,"unique":false,"default":""},"source_module":{"type":"TEXT","notNull":false,"unique":false,"default":""},"source_ref":{"type":"TEXT","notNull":false,"unique":false},"status":{"type":"TEXT","notNull":false,"unique":false,"default":"draft"},"posted_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"voided_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"void_reason":{"type":"TEXT","notNull":false,"unique":false},"metadata":{"type":"JSON","notNull":false,"unique":false,"default":{}}},"indexes":[{"name":"journals_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true,"nullsNotDistinct":true},{"name":"journals_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"4b51d204"},"importPath":"@happyvertical/smrt-ledgers"},"@happyvertical/smrt-ledgers:Account":{"name":"account","className":"Account","qualifiedName":"@happyvertical/smrt-ledgers:Account","collection":"accounts","filePath":"/home/runner/work/smrt/smrt/packages/ledgers/src/models/Account.ts","packageName":"@happyvertical/smrt-ledgers","fields":{"parentId":{"type":"foreignKey","required":false,"related":"Account","_meta":{"nullable":true}},"tenantId":{"type":"text","required":false,"_meta":{"sqlType":"UUID","nullable":true,"__tenancy":{"isTenantIdField":true,"autoFilter":true,"required":false,"autoPopulate":true,"nullable":true,"mode":"optional","field":"tenantId","allowSuperAdminBypass":false}}},"number":{"type":"text","required":false,"default":"","description":"The account number in your chart of accounts.","_meta":{"description":"The account number in your chart of accounts."}},"name":{"type":"text","required":false,"default":"","description":"What the account is called.","_meta":{"description":"What the account is called."}},"description":{"type":"text","required":false,"default":"","description":"What the account is used for.","_meta":{"description":"What the account is used for."}},"type":{"type":"text","required":false,"default":"asset","description":"asset, liability, equity, revenue or expense.","_meta":{"description":"asset, liability, equity, revenue or expense."},"enum":["asset","liability","equity","revenue","expense"]},"active":{"type":"boolean","required":false,"default":true,"description":"Whether the account is in use; deactivate it instead of deleting it.","_meta":{"description":"Whether the account is in use; deactivate it instead of deleting it."}},"metadata":{"type":"json","required":false,"default":{}}},"methods":{"getParent":{"name":"getParent","async":true,"parameters":[],"returnType":"Promise<this | null>","isStatic":false,"isPublic":true},"getChildren":{"name":"getChildren","async":true,"parameters":[],"returnType":"Promise<this[]>","isStatic":false,"isPublic":true},"getAncestors":{"name":"getAncestors","async":true,"parameters":[],"returnType":"Promise<this[]>","isStatic":false,"isPublic":true},"getDescendants":{"name":"getDescendants","async":true,"parameters":[],"returnType":"Promise<this[]>","isStatic":false,"isPublic":true},"getHierarchy":{"name":"getHierarchy","async":true,"parameters":[],"returnType":"Promise<HierarchyView<this>>","isStatic":false,"isPublic":true},"moveTo":{"name":"moveTo","async":true,"parameters":[{"name":"newParent","type":"this | string | null","optional":false,"unionBranches":[{"type":"this"},{"type":"string"},{"type":"null"}]}],"returnType":"Promise<void>","isStatic":false,"isPublic":true},"isTopLevel":{"name":"isTopLevel","async":false,"parameters":[],"returnType":"boolean","isStatic":false,"isPublic":true},"isDebitNormal":{"name":"isDebitNormal","async":false,"parameters":[],"returnType":"boolean","isStatic":false,"isPublic":true},"isCreditNormal":{"name":"isCreditNormal","async":false,"parameters":[],"returnType":"boolean","isStatic":false,"isPublic":true},"getFullPath":{"name":"getFullPath","async":true,"parameters":[],"returnType":"Promise<string>","isStatic":false,"isPublic":true},"toTreeNode":{"name":"toTreeNode","async":true,"parameters":[],"returnType":"Promise<AccountTreeNode>","isStatic":false,"isPublic":true},"getBalance":{"name":"getBalance","async":true,"parameters":[{"name":"asOfDate","type":"Date","optional":true}],"returnType":"Promise<number>","isStatic":false,"isPublic":true},"createChild":{"name":"createChild","async":true,"parameters":[{"name":"options","type":"Omit<AccountOptions, 'parentId' | 'type'>","optional":false}],"returnType":"Promise<Account>","isStatic":false,"isPublic":true}},"decoratorConfig":{"tableName":"ledger_accounts","api":{"include":["list","get","create","update","delete"]},"mcp":{"include":["list","get","create"]},"cli":{"skipApiCheck":true},"tenantScoped":{"mode":"optional"},"conflictColumns":["tenant_id","slug","context"]},"extends":"SmrtHierarchical","exportName":"Account","collectionExportName":"AccountCollection","displayLabelField":"name","schema":{"tableName":"ledger_accounts","ddl":"CREATE TABLE IF NOT EXISTS \\"ledger_accounts\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"parent_id\\" UUID,\\n \\"tenant_id\\" UUID,\\n \\"number\\" TEXT DEFAULT '',\\n \\"name\\" TEXT DEFAULT '',\\n \\"description\\" TEXT DEFAULT '',\\n \\"type\\" TEXT DEFAULT 'asset',\\n \\"active\\" BOOLEAN DEFAULT TRUE,\\n \\"metadata\\" JSON DEFAULT '{}'\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"parent_id":{"type":"UUID","referenceKind":"foreignKey","notNull":false,"unique":false,"foreignKey":{"table":"ledger_accounts","column":"id","onDelete":"NO ACTION","onUpdate":"CASCADE"}},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"number":{"type":"TEXT","notNull":false,"unique":false,"default":""},"name":{"type":"TEXT","notNull":false,"unique":false,"default":""},"description":{"type":"TEXT","notNull":false,"unique":false,"default":""},"type":{"type":"TEXT","notNull":false,"unique":false,"default":"asset"},"active":{"type":"BOOLEAN","notNull":false,"unique":false,"default":true},"metadata":{"type":"JSON","notNull":false,"unique":false,"default":{}}},"indexes":[{"name":"ledger_accounts_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true,"nullsNotDistinct":true},{"name":"ledger_accounts_tenant_id_created_at_idx","columns":["tenant_id","created_at"]},{"name":"ledger_accounts_parent_id_idx","columns":["parent_id"]}],"version":"49630dae"},"importPath":"@happyvertical/smrt-ledgers"},"@happyvertical/smrt-ledgers:Journal":{"name":"journal","className":"Journal","qualifiedName":"@happyvertical/smrt-ledgers:Journal","collection":"journals","filePath":"/home/runner/work/smrt/smrt/packages/ledgers/src/models/Journal.ts","packageName":"@happyvertical/smrt-ledgers","fields":{"tenantId":{"type":"text","required":false,"_meta":{"sqlType":"UUID","nullable":true,"__tenancy":{"isTenantIdField":true,"autoFilter":true,"required":false,"autoPopulate":true,"nullable":true,"mode":"optional","field":"tenantId","allowSuperAdminBypass":false}}},"number":{"type":"text","required":false,"default":"","description":"The journal's reference number.","_meta":{"description":"The journal's reference number."}},"date":{"type":"datetime","required":false,"description":"The date of the transaction.","_meta":{"description":"The date of the transaction."}},"description":{"type":"text","required":false,"default":"","description":"What the transaction was.","_meta":{"description":"What the transaction was."}},"sourceModule":{"type":"text","required":false,"default":""},"sourceRef":{"type":"text","required":false},"status":{"type":"text","required":false,"default":"draft","description":"draft until final, then posted, or voided.","_meta":{"description":"draft until final, then posted, or voided."},"enum":["draft","posted","voided"]},"postedAt":{"type":"datetime","required":false,"description":"When it was posted.","_meta":{"description":"When it was posted."}},"voidedAt":{"type":"datetime","required":false},"voidReason":{"type":"text","required":false},"metadata":{"type":"json","required":false,"default":{}}},"methods":{"isDraft":{"name":"isDraft","async":false,"parameters":[],"returnType":"boolean","isStatic":false,"isPublic":true},"isPosted":{"name":"isPosted","async":false,"parameters":[],"returnType":"boolean","isStatic":false,"isPublic":true},"isVoided":{"name":"isVoided","async":false,"parameters":[],"returnType":"boolean","isStatic":false,"isPublic":true},"isEditable":{"name":"isEditable","async":false,"parameters":[],"returnType":"boolean","isStatic":false,"isPublic":true},"getEntries":{"name":"getEntries","async":true,"parameters":[],"returnType":"any","isStatic":false,"isPublic":true},"getTotalDebits":{"name":"getTotalDebits","async":true,"parameters":[],"returnType":"Promise<number>","isStatic":false,"isPublic":true},"getTotalCredits":{"name":"getTotalCredits","async":true,"parameters":[],"returnType":"Promise<number>","isStatic":false,"isPublic":true},"isBalanced":{"name":"isBalanced","async":true,"parameters":[],"returnType":"Promise<boolean>","isStatic":false,"isPublic":true},"addEntry":{"name":"addEntry","async":true,"parameters":[{"name":"data","type":"JournalEntryData","optional":false}],"returnType":"Promise<void>","isStatic":false,"isPublic":true},"post":{"name":"post","async":true,"parameters":[],"returnType":"Promise<void>","isStatic":false,"isPublic":true},"void":{"name":"void","async":true,"parameters":[{"name":"reason","type":"string","optional":false}],"returnType":"Promise<void>","isStatic":false,"isPublic":true},"summarize":{"name":"summarize","async":true,"parameters":[],"returnType":"Promise<string>","isStatic":false,"isPublic":true}},"decoratorConfig":{"api":{"include":["list","get","create"]},"mcp":{"include":["list","get","create"]},"cli":{"skipApiCheck":true},"tenantScoped":{"mode":"optional"},"conflictColumns":["tenant_id","slug","context"]},"extends":"SmrtObject","exportName":"Journal","collectionExportName":"JournalCollection","schema":{"tableName":"journals","ddl":"CREATE TABLE IF NOT EXISTS \\"journals\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID,\\n \\"number\\" TEXT DEFAULT '',\\n \\"date\\" TIMESTAMP,\\n \\"description\\" TEXT DEFAULT '',\\n \\"source_module\\" TEXT DEFAULT '',\\n \\"source_ref\\" TEXT,\\n \\"status\\" TEXT DEFAULT 'draft',\\n \\"posted_at\\" TIMESTAMP,\\n \\"voided_at\\" TIMESTAMP,\\n \\"void_reason\\" TEXT,\\n \\"metadata\\" JSON DEFAULT '{}'\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"number":{"type":"TEXT","notNull":false,"unique":false,"default":""},"date":{"type":"TIMESTAMP","notNull":false,"unique":false},"description":{"type":"TEXT","notNull":false,"unique":false,"default":""},"source_module":{"type":"TEXT","notNull":false,"unique":false,"default":""},"source_ref":{"type":"TEXT","notNull":false,"unique":false},"status":{"type":"TEXT","notNull":false,"unique":false,"default":"draft"},"posted_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"voided_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"void_reason":{"type":"TEXT","notNull":false,"unique":false},"metadata":{"type":"JSON","notNull":false,"unique":false,"default":{}}},"indexes":[{"name":"journals_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true,"nullsNotDistinct":true},{"name":"journals_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"4b51d204"},"importPath":"@happyvertical/smrt-ledgers"},"@happyvertical/smrt-ledgers:JournalEntry":{"name":"journalentry","className":"JournalEntry","qualifiedName":"@happyvertical/smrt-ledgers:JournalEntry","collection":"journalentries","filePath":"/home/runner/work/smrt/smrt/packages/ledgers/src/models/JournalEntry.ts","packageName":"@happyvertical/smrt-ledgers","fields":{"tenantId":{"type":"text","required":false,"_meta":{"sqlType":"UUID","nullable":true,"__tenancy":{"isTenantIdField":true,"autoFilter":true,"required":false,"autoPopulate":true,"nullable":true,"mode":"optional","field":"tenantId","allowSuperAdminBypass":false}}},"journalId":{"type":"foreignKey","required":false,"related":"Journal","description":"The journal this entry belongs to.","_meta":{"description":"The journal this entry belongs to."}},"accountId":{"type":"foreignKey","required":false,"related":"Account","description":"The account this entry changes.","_meta":{"description":"The account this entry changes."}},"debit":{"type":"decimal","required":false,"default":0,"description":"The amount debited. Zero on a credit entry.","_meta":{"description":"The amount debited. Zero on a credit entry."}},"credit":{"type":"decimal","required":false,"default":0,"description":"The amount credited. Zero on a debit entry.","_meta":{"description":"The amount credited. Zero on a debit entry."}},"currency":{"type":"text","required":false,"default":"USD","description":"The currency of the amounts.","_meta":{"description":"The currency of the amounts."}},"exchangeRate":{"type":"decimal","required":false,"default":1},"memo":{"type":"text","required":false,"default":"","description":"A note on this entry.","_meta":{"description":"A note on this entry."}},"metadata":{"type":"json","required":false,"default":{}}},"methods":{"isDebit":{"name":"isDebit","async":false,"parameters":[],"returnType":"boolean","isStatic":false,"isPublic":true},"isCredit":{"name":"isCredit","async":false,"parameters":[],"returnType":"boolean","isStatic":false,"isPublic":true},"getAmount":{"name":"getAmount","async":false,"parameters":[],"returnType":"number","isStatic":false,"isPublic":true},"getBaseAmount":{"name":"getBaseAmount","async":false,"parameters":[],"returnType":"number","isStatic":false,"isPublic":true},"getJournal":{"name":"getJournal","async":true,"parameters":[],"returnType":"any","isStatic":false,"isPublic":true},"getAccount":{"name":"getAccount","async":true,"parameters":[],"returnType":"any","isStatic":false,"isPublic":true},"getDescription":{"name":"getDescription","async":true,"parameters":[],"returnType":"Promise<string>","isStatic":false,"isPublic":true}},"decoratorConfig":{"api":{"include":["list","get"]},"mcp":{"include":["list","get"]},"cli":{"skipApiCheck":true},"tenantScoped":{"mode":"optional"},"conflictColumns":["tenant_id","slug","context"]},"extends":"SmrtObject","exportName":"JournalEntry","collectionExportName":"JournalEntryCollection","schema":{"tableName":"journal_entries","ddl":"CREATE TABLE IF NOT EXISTS \\"journal_entries\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID,\\n \\"journal_id\\" UUID,\\n \\"account_id\\" UUID,\\n \\"debit\\" REAL DEFAULT 0,\\n \\"credit\\" REAL DEFAULT 0,\\n \\"currency\\" TEXT DEFAULT 'USD',\\n \\"exchange_rate\\" REAL DEFAULT 1,\\n \\"memo\\" TEXT DEFAULT '',\\n \\"metadata\\" JSON DEFAULT '{}'\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"journal_id":{"type":"UUID","referenceKind":"foreignKey","notNull":false,"unique":false,"foreignKey":{"table":"journals","column":"id","onDelete":"NO ACTION","onUpdate":"CASCADE"}},"account_id":{"type":"UUID","referenceKind":"foreignKey","notNull":false,"unique":false,"foreignKey":{"table":"ledger_accounts","column":"id","onDelete":"NO ACTION","onUpdate":"CASCADE"}},"debit":{"type":"REAL","notNull":false,"unique":false,"default":0},"credit":{"type":"REAL","notNull":false,"unique":false,"default":0},"currency":{"type":"TEXT","notNull":false,"unique":false,"default":"USD"},"exchange_rate":{"type":"REAL","notNull":false,"unique":false,"default":1},"memo":{"type":"TEXT","notNull":false,"unique":false,"default":""},"metadata":{"type":"JSON","notNull":false,"unique":false,"default":{}}},"indexes":[{"name":"journal_entries_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true,"nullsNotDistinct":true},{"name":"journal_entries_tenant_id_created_at_idx","columns":["tenant_id","created_at"]},{"name":"journal_entries_journal_id_idx","columns":["journal_id"]},{"name":"journal_entries_account_id_idx","columns":["account_id"]}],"version":"93cdc848"},"importPath":"@happyvertical/smrt-ledgers"}},"moduleType":"smrt","recipes":[{"id":"ledgers.bookkeeping","className":"BookkeepingRecipe","label":"Bookkeeping","summary":"Keep your books: a chart of accounts and double-entry journals.","synonyms":["accounting","ledger","general ledger","journals","chart of accounts"],"models":["@happyvertical/smrt-ledgers:Account","@happyvertical/smrt-ledgers:Journal","@happyvertical/smrt-ledgers:JournalEntry"],"nav":[{"label":"Accounts","model":"@happyvertical/smrt-ledgers:Account","icon":"bank","description":"The accounts your books are kept in, like sales, rent and bank."},{"label":"Journals","model":"@happyvertical/smrt-ledgers:Journal","icon":"book","description":"The entries behind your accounts, so every dollar has a trail."}],"requires":[],"section":{"id":"accounting","label":"Accounting","icon":"bank","description":"Your books: accounts, journals and balances."},"options":{"@happyvertical/smrt-ledgers:Account":{"fields":{"metadata":{"visibility":"hidden"},"parentId":{"visibility":"hidden"}}},"@happyvertical/smrt-ledgers:Journal":{"fields":{"sourceModule":{"visibility":"hidden"},"sourceRef":{"visibility":"hidden"},"voidedAt":{"visibility":"hidden"},"voidReason":{"visibility":"hidden"},"metadata":{"visibility":"hidden"}}},"@happyvertical/smrt-ledgers:JournalEntry":{"fields":{"exchangeRate":{"visibility":"hidden"},"metadata":{"visibility":"hidden"}}}},"help":{"markdown":"## Overview\\n\\nBookkeeping keeps your accounts. You list the accounts you use (your chart of\\naccounts) and record each transaction as a journal whose entries debit and\\ncredit those accounts.\\n\\n## Tasks\\n\\n### Set up your accounts\\n\\n1. Create a new account.\\n2. Give it a **{field:number}** and a **{field:name}**.\\n3. Choose its **{field:type}**: asset, liability, equity, revenue or expense.\\n\\n### Record a transaction\\n\\n1. Create a new journal and add a **{field:description}**.\\n2. Add entries: pick the account on each and enter a **{field:debit}** or a\\n **{field:credit}**. They must add up to the same total.\\n3. Set the journal's **{field:status}** to posted when it is final. A posted\\n journal is voided, not edited.\\n","fieldRefs":["credit","debit","description","name","number","status","type"]},"demo":{"mode":"server","reasons":["Needs a server because its package does not build for a browser: core migrations (node:os, node:crypto); and its package depends on @happyvertical/smrt-tenancy, which do not build for a browser (#3624, #3626)."]}}],"smrtDependencies":["@happyvertical/smrt-core","@happyvertical/smrt-prompts","@happyvertical/smrt-tenancy"],"browser":{"status":"server-only","issues":["#3624","#3626"],"reason":"core migrations (node:os, node:crypto)","via":["@happyvertical/smrt-tenancy"]},"stampsConstructors":true}`));
|
|
21
|
+
ObjectRegistry.registerPackageManifest(JSON.parse(`{"version":"1.0.0","timestamp":0,"packageName":"@happyvertical/smrt-ledgers","packageVersion":"0.57.4","objects":{"@happyvertical/smrt-ledgers:AccountCollection":{"name":"accountcollection","className":"AccountCollection","qualifiedName":"@happyvertical/smrt-ledgers:AccountCollection","collection":"accounts","filePath":"/home/runner/work/smrt/smrt/packages/ledgers/src/collections/Accounts.ts","packageName":"@happyvertical/smrt-ledgers","fields":{},"methods":{"findByNumber":{"name":"findByNumber","async":true,"parameters":[{"name":"number","type":"string","optional":false}],"returnType":"Promise<Account | null>","isStatic":false,"isPublic":true},"findByType":{"name":"findByType","async":true,"parameters":[{"name":"type","type":"AccountType","optional":false}],"returnType":"Promise<Account[]>","isStatic":false,"isPublic":true},"findActive":{"name":"findActive","async":true,"parameters":[],"returnType":"Promise<Account[]>","isStatic":false,"isPublic":true},"findTopLevel":{"name":"findTopLevel","async":true,"parameters":[],"returnType":"Promise<Account[]>","isStatic":false,"isPublic":true},"findChildren":{"name":"findChildren","async":true,"parameters":[{"name":"parentId","type":"string","optional":false}],"returnType":"Promise<Account[]>","isStatic":false,"isPublic":true},"getTree":{"name":"getTree","async":true,"parameters":[],"returnType":"Promise<AccountTree>","isStatic":false,"isPublic":true},"getOrCreateByNumber":{"name":"getOrCreateByNumber","async":true,"parameters":[{"name":"number","type":"string","optional":false},{"name":"defaults","type":"Partial<object>","optional":true,"memberTypes":["string","AccountType","string | null"]}],"returnType":"Promise<Account>","isStatic":false,"isPublic":true},"groupByType":{"name":"groupByType","async":true,"parameters":[],"returnType":"Promise<Record<AccountType, Account[]>>","isStatic":false,"isPublic":true},"getDescendants":{"name":"getDescendants","async":true,"parameters":[{"name":"accountId","type":"string","optional":false}],"returnType":"Promise<Account[]>","isStatic":false,"isPublic":true},"findByTenant":{"name":"findByTenant","async":true,"parameters":[{"name":"tenantId","type":"string","optional":false}],"returnType":"Promise<Account[]>","isStatic":false,"isPublic":true},"findGlobal":{"name":"findGlobal","async":true,"parameters":[],"returnType":"Promise<Account[]>","isStatic":false,"isPublic":true},"findWithGlobals":{"name":"findWithGlobals","async":true,"parameters":[{"name":"tenantId","type":"string","optional":false}],"returnType":"Promise<Account[]>","isStatic":false,"isPublic":true}},"decoratorConfig":{"tableName":"ledger_accounts","api":{"include":["list","get","create","update","delete"]},"mcp":{"include":["list","get","create"]}},"extends":"SmrtCollection","extendsTypeArg":"Account","exportName":"AccountCollection","collectionExportName":"AccountCollectionCollection","schema":{"tableName":"ledger_accounts","ddl":"CREATE TABLE IF NOT EXISTS \\"ledger_accounts\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"parent_id\\" UUID,\\n \\"tenant_id\\" UUID,\\n \\"number\\" TEXT DEFAULT '',\\n \\"name\\" TEXT DEFAULT '',\\n \\"description\\" TEXT DEFAULT '',\\n \\"type\\" TEXT DEFAULT 'asset',\\n \\"ledger_id\\" UUID,\\n \\"active\\" BOOLEAN DEFAULT TRUE,\\n \\"metadata\\" JSON DEFAULT '{}'\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"parent_id":{"type":"UUID","referenceKind":"foreignKey","notNull":false,"unique":false,"foreignKey":{"table":"ledger_accounts","column":"id","onDelete":"NO ACTION","onUpdate":"CASCADE"}},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"number":{"type":"TEXT","notNull":false,"unique":false,"default":""},"name":{"type":"TEXT","notNull":false,"unique":false,"default":""},"description":{"type":"TEXT","notNull":false,"unique":false,"default":""},"type":{"type":"TEXT","notNull":false,"unique":false,"default":"asset"},"ledger_id":{"type":"UUID","referenceKind":"foreignKey","notNull":false,"unique":false,"foreignKey":{"table":"ledgers","column":"id","onDelete":"NO ACTION","onUpdate":"CASCADE"}},"active":{"type":"BOOLEAN","notNull":false,"unique":false,"default":true},"metadata":{"type":"JSON","notNull":false,"unique":false,"default":{}}},"indexes":[{"name":"ledger_accounts_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true,"nullsNotDistinct":true},{"name":"ledger_accounts_tenant_id_created_at_idx","columns":["tenant_id","created_at"]},{"name":"ledger_accounts_parent_id_idx","columns":["parent_id"]},{"name":"ledger_accounts_ledger_id_idx","columns":["ledger_id"]}],"version":"caea63eb"},"importPath":"@happyvertical/smrt-ledgers"},"@happyvertical/smrt-ledgers:JournalEntryCollection":{"name":"journalentrycollection","className":"JournalEntryCollection","qualifiedName":"@happyvertical/smrt-ledgers:JournalEntryCollection","collection":"journalentries","filePath":"/home/runner/work/smrt/smrt/packages/ledgers/src/collections/JournalEntries.ts","packageName":"@happyvertical/smrt-ledgers","fields":{},"methods":{"findByJournal":{"name":"findByJournal","async":true,"parameters":[{"name":"journalId","type":"string","optional":false}],"returnType":"Promise<JournalEntry[]>","isStatic":false,"isPublic":true},"findByAccount":{"name":"findByAccount","async":true,"parameters":[{"name":"accountId","type":"string","optional":false}],"returnType":"Promise<JournalEntry[]>","isStatic":false,"isPublic":true},"getCounterpartyBalances":{"name":"getCounterpartyBalances","async":true,"parameters":[{"name":"options","type":"PostedJournalMovementOptions","optional":false}],"returnType":"Promise<CounterpartyBalance[]>","isStatic":false,"isPublic":true},"getCounterpartyAging":{"name":"getCounterpartyAging","async":true,"parameters":[{"name":"options","type":"PostedJournalMovementOptions","optional":false},{"name":"asOf","type":"Date","optional":false}],"returnType":"Promise<CounterpartyAgingRow[]>","isStatic":false,"isPublic":true},"getAccountBalance":{"name":"getAccountBalance","async":true,"parameters":[{"name":"accountId","type":"string","optional":false},{"name":"asOfDate","type":"Date","optional":true}],"returnType":"Promise<number>","isStatic":false,"isPublic":true},"getTrialBalance":{"name":"getTrialBalance","async":true,"parameters":[{"name":"asOfDate","type":"Date","optional":true}],"returnType":"Promise<TrialBalanceRow[]>","isStatic":false,"isPublic":true},"getTotalsForDateRange":{"name":"getTotalsForDateRange","async":true,"parameters":[{"name":"start","type":"Date","optional":false},{"name":"end","type":"Date","optional":false}],"returnType":"Promise<object>","isStatic":false,"isPublic":true},"findByAccounts":{"name":"findByAccounts","async":true,"parameters":[{"name":"accountIds","type":"string[]","optional":false}],"returnType":"Promise<JournalEntry[]>","isStatic":false,"isPublic":true},"listPostedMovements":{"name":"listPostedMovements","async":true,"parameters":[{"name":"options","type":"PostedJournalMovementOptions","optional":false}],"returnType":"Promise<PostedJournalMovement[]>","isStatic":false,"isPublic":true},"getAccountLedger":{"name":"getAccountLedger","async":true,"parameters":[{"name":"accountId","type":"string","optional":false}],"returnType":"Promise<Array<object>>","isStatic":false,"isPublic":true},"findByTenant":{"name":"findByTenant","async":true,"parameters":[{"name":"tenantId","type":"string","optional":false}],"returnType":"Promise<JournalEntry[]>","isStatic":false,"isPublic":true},"findGlobal":{"name":"findGlobal","async":true,"parameters":[],"returnType":"Promise<JournalEntry[]>","isStatic":false,"isPublic":true},"findWithGlobals":{"name":"findWithGlobals","async":true,"parameters":[{"name":"tenantId","type":"string","optional":false}],"returnType":"Promise<JournalEntry[]>","isStatic":false,"isPublic":true}},"decoratorConfig":{"api":{"include":["list","get"]},"mcp":{"include":["list","get"]}},"extends":"SmrtCollection","extendsTypeArg":"JournalEntry","exportName":"JournalEntryCollection","collectionExportName":"JournalEntryCollectionCollection","schema":{"tableName":"journal_entries","ddl":"CREATE TABLE IF NOT EXISTS \\"journal_entries\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID,\\n \\"journal_id\\" UUID,\\n \\"account_id\\" UUID,\\n \\"counterparty_kind\\" TEXT,\\n \\"counterparty_id\\" TEXT,\\n \\"due_date\\" TIMESTAMP,\\n \\"settles_source_ref\\" TEXT,\\n \\"debit\\" REAL DEFAULT 0,\\n \\"credit\\" REAL DEFAULT 0,\\n \\"currency\\" TEXT DEFAULT 'USD',\\n \\"exchange_rate\\" REAL DEFAULT 1,\\n \\"memo\\" TEXT DEFAULT '',\\n \\"metadata\\" JSON DEFAULT '{}'\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"journal_id":{"type":"UUID","referenceKind":"foreignKey","notNull":false,"unique":false,"foreignKey":{"table":"journals","column":"id","onDelete":"NO ACTION","onUpdate":"CASCADE"}},"account_id":{"type":"UUID","referenceKind":"foreignKey","notNull":false,"unique":false,"foreignKey":{"table":"ledger_accounts","column":"id","onDelete":"NO ACTION","onUpdate":"CASCADE"}},"counterparty_kind":{"type":"TEXT","notNull":false,"unique":false},"counterparty_id":{"type":"TEXT","notNull":false,"unique":false},"due_date":{"type":"TIMESTAMP","notNull":false,"unique":false},"settles_source_ref":{"type":"TEXT","notNull":false,"unique":false},"debit":{"type":"REAL","notNull":false,"unique":false,"default":0},"credit":{"type":"REAL","notNull":false,"unique":false,"default":0},"currency":{"type":"TEXT","notNull":false,"unique":false,"default":"USD"},"exchange_rate":{"type":"REAL","notNull":false,"unique":false,"default":1},"memo":{"type":"TEXT","notNull":false,"unique":false,"default":""},"metadata":{"type":"JSON","notNull":false,"unique":false,"default":{}}},"indexes":[{"name":"journal_entries_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true,"nullsNotDistinct":true},{"name":"journal_entries_tenant_id_created_at_idx","columns":["tenant_id","created_at"]},{"name":"journal_entries_journal_id_idx","columns":["journal_id"]},{"name":"journal_entries_account_id_idx","columns":["account_id"]}],"version":"e96b76a2"},"importPath":"@happyvertical/smrt-ledgers"},"@happyvertical/smrt-ledgers:JournalCollection":{"name":"journalcollection","className":"JournalCollection","qualifiedName":"@happyvertical/smrt-ledgers:JournalCollection","collection":"journals","filePath":"/home/runner/work/smrt/smrt/packages/ledgers/src/collections/Journals.ts","packageName":"@happyvertical/smrt-ledgers","fields":{},"methods":{"findByNumber":{"name":"findByNumber","async":true,"parameters":[{"name":"number","type":"string","optional":false}],"returnType":"Promise<Journal | null>","isStatic":false,"isPublic":true},"findByDateRange":{"name":"findByDateRange","async":true,"parameters":[{"name":"start","type":"Date","optional":false},{"name":"end","type":"Date","optional":false}],"returnType":"Promise<Journal[]>","isStatic":false,"isPublic":true},"findBySource":{"name":"findBySource","async":true,"parameters":[{"name":"sourceModule","type":"string","optional":false}],"returnType":"Promise<Journal[]>","isStatic":false,"isPublic":true},"findByStatus":{"name":"findByStatus","async":true,"parameters":[{"name":"status","type":"JournalStatus","optional":false}],"returnType":"Promise<Journal[]>","isStatic":false,"isPublic":true},"findDrafts":{"name":"findDrafts","async":true,"parameters":[],"returnType":"Promise<Journal[]>","isStatic":false,"isPublic":true},"findPosted":{"name":"findPosted","async":true,"parameters":[],"returnType":"Promise<Journal[]>","isStatic":false,"isPublic":true},"createWithEntries":{"name":"createWithEntries","async":true,"parameters":[{"name":"data","type":"CreateJournalData","optional":false}],"returnType":"Promise<Journal>","isStatic":false,"isPublic":true},"post":{"name":"post","async":true,"parameters":[{"name":"journalId","type":"string","optional":false}],"returnType":"Promise<Journal>","isStatic":false,"isPublic":true},"void":{"name":"void","async":true,"parameters":[{"name":"journalId","type":"string","optional":false},{"name":"reason","type":"string","optional":false}],"returnType":"Promise<Journal>","isStatic":false,"isPublic":true},"findBySourceRef":{"name":"findBySourceRef","async":true,"parameters":[{"name":"sourceRef","type":"string","optional":false}],"returnType":"Promise<Journal[]>","isStatic":false,"isPublic":true},"findByMonth":{"name":"findByMonth","async":true,"parameters":[{"name":"year","type":"number","optional":false},{"name":"month","type":"number","optional":false}],"returnType":"Promise<Journal[]>","isStatic":false,"isPublic":true},"findByTenant":{"name":"findByTenant","async":true,"parameters":[{"name":"tenantId","type":"string","optional":false}],"returnType":"Promise<Journal[]>","isStatic":false,"isPublic":true},"findGlobal":{"name":"findGlobal","async":true,"parameters":[],"returnType":"Promise<Journal[]>","isStatic":false,"isPublic":true},"findWithGlobals":{"name":"findWithGlobals","async":true,"parameters":[{"name":"tenantId","type":"string","optional":false}],"returnType":"Promise<Journal[]>","isStatic":false,"isPublic":true}},"decoratorConfig":{"api":{"include":["list","get","create"]},"mcp":{"include":["list","get","create"]}},"extends":"SmrtCollection","extendsTypeArg":"Journal","exportName":"JournalCollection","collectionExportName":"JournalCollectionCollection","schema":{"tableName":"journals","ddl":"CREATE TABLE IF NOT EXISTS \\"journals\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID,\\n \\"number\\" TEXT DEFAULT '',\\n \\"date\\" TIMESTAMP,\\n \\"description\\" TEXT DEFAULT '',\\n \\"source_module\\" TEXT DEFAULT '',\\n \\"source_ref\\" TEXT,\\n \\"ledger_id\\" UUID,\\n \\"idempotency_key\\" TEXT,\\n \\"request_digest\\" TEXT,\\n \\"status\\" TEXT DEFAULT 'draft',\\n \\"posted_at\\" TIMESTAMP,\\n \\"voided_at\\" TIMESTAMP,\\n \\"void_reason\\" TEXT,\\n \\"metadata\\" JSON DEFAULT '{}'\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"number":{"type":"TEXT","notNull":false,"unique":false,"default":""},"date":{"type":"TIMESTAMP","notNull":false,"unique":false},"description":{"type":"TEXT","notNull":false,"unique":false,"default":""},"source_module":{"type":"TEXT","notNull":false,"unique":false,"default":""},"source_ref":{"type":"TEXT","notNull":false,"unique":false},"ledger_id":{"type":"UUID","referenceKind":"foreignKey","notNull":false,"unique":false,"foreignKey":{"table":"ledgers","column":"id","onDelete":"NO ACTION","onUpdate":"CASCADE"}},"idempotency_key":{"type":"TEXT","notNull":false,"unique":false},"request_digest":{"type":"TEXT","notNull":false,"unique":false},"status":{"type":"TEXT","notNull":false,"unique":false,"default":"draft"},"posted_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"voided_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"void_reason":{"type":"TEXT","notNull":false,"unique":false},"metadata":{"type":"JSON","notNull":false,"unique":false,"default":{}}},"indexes":[{"name":"journals_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true,"nullsNotDistinct":true},{"name":"journals_ledger_idempotency_key","columns":["tenant_id","ledger_id","idempotency_key"],"unique":true},{"name":"journals_tenant_id_created_at_idx","columns":["tenant_id","created_at"]},{"name":"journals_ledger_id_idx","columns":["ledger_id"]}],"version":"1e73dd60"},"importPath":"@happyvertical/smrt-ledgers"},"@happyvertical/smrt-ledgers:LedgerCollection":{"name":"ledgercollection","className":"LedgerCollection","qualifiedName":"@happyvertical/smrt-ledgers:LedgerCollection","collection":"ledgers","filePath":"/home/runner/work/smrt/smrt/packages/ledgers/src/collections/Ledgers.ts","packageName":"@happyvertical/smrt-ledgers","fields":{},"methods":{},"decoratorConfig":{"api":{"include":["list","get","create","update"]},"mcp":{"include":["list","get","create"]}},"extends":"SmrtCollection","extendsTypeArg":"Ledger","exportName":"LedgerCollection","collectionExportName":"LedgerCollectionCollection","schema":{"tableName":"ledgers","ddl":"CREATE TABLE IF NOT EXISTS \\"ledgers\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID,\\n \\"name\\" TEXT,\\n \\"currency\\" TEXT,\\n \\"balance_mode\\" TEXT DEFAULT 'tolerant'\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"name":{"type":"TEXT","notNull":false,"unique":false},"currency":{"type":"TEXT","notNull":false,"unique":false},"balance_mode":{"type":"TEXT","notNull":false,"unique":false,"default":"tolerant"}},"indexes":[{"name":"ledgers_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true,"nullsNotDistinct":true},{"name":"ledgers_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"be316e4f"},"importPath":"@happyvertical/smrt-ledgers"},"@happyvertical/smrt-ledgers:Account":{"name":"account","className":"Account","qualifiedName":"@happyvertical/smrt-ledgers:Account","collection":"accounts","filePath":"/home/runner/work/smrt/smrt/packages/ledgers/src/models/Account.ts","packageName":"@happyvertical/smrt-ledgers","fields":{"parentId":{"type":"foreignKey","required":false,"related":"Account","_meta":{"nullable":true}},"tenantId":{"type":"text","required":false,"_meta":{"sqlType":"UUID","nullable":true,"__tenancy":{"isTenantIdField":true,"autoFilter":true,"required":false,"autoPopulate":true,"nullable":true,"mode":"optional","field":"tenantId","allowSuperAdminBypass":false}}},"number":{"type":"text","required":false,"default":"","description":"The account number in your chart of accounts.","_meta":{"description":"The account number in your chart of accounts."}},"name":{"type":"text","required":false,"default":"","description":"What the account is called.","_meta":{"description":"What the account is called."}},"description":{"type":"text","required":false,"default":"","description":"What the account is used for.","_meta":{"description":"What the account is used for."}},"type":{"type":"text","required":false,"default":"asset","description":"asset, liability, equity, revenue or expense.","_meta":{"description":"asset, liability, equity, revenue or expense."},"enum":["asset","liability","equity","revenue","expense"]},"ledgerId":{"type":"foreignKey","required":false,"related":"Ledger","description":"The ledger policy this account belongs to.","_meta":{"description":"The ledger policy this account belongs to.","nullable":true}},"active":{"type":"boolean","required":false,"default":true,"description":"Whether the account is in use; deactivate it instead of deleting it.","_meta":{"description":"Whether the account is in use; deactivate it instead of deleting it."}},"metadata":{"type":"json","required":false,"default":{}}},"methods":{"getParent":{"name":"getParent","async":true,"parameters":[],"returnType":"Promise<this | null>","isStatic":false,"isPublic":true},"getChildren":{"name":"getChildren","async":true,"parameters":[],"returnType":"Promise<this[]>","isStatic":false,"isPublic":true},"getAncestors":{"name":"getAncestors","async":true,"parameters":[],"returnType":"Promise<this[]>","isStatic":false,"isPublic":true},"getDescendants":{"name":"getDescendants","async":true,"parameters":[],"returnType":"Promise<this[]>","isStatic":false,"isPublic":true},"getHierarchy":{"name":"getHierarchy","async":true,"parameters":[],"returnType":"Promise<HierarchyView<this>>","isStatic":false,"isPublic":true},"moveTo":{"name":"moveTo","async":true,"parameters":[{"name":"newParent","type":"this | string | null","optional":false,"unionBranches":[{"type":"this"},{"type":"string"},{"type":"null"}]}],"returnType":"Promise<void>","isStatic":false,"isPublic":true},"delete":{"name":"delete","async":true,"parameters":[{"name":"options","type":"any","optional":true,"typeUnresolved":true}],"returnType":"Promise<void>","isStatic":false,"isPublic":true},"isTopLevel":{"name":"isTopLevel","async":false,"parameters":[],"returnType":"boolean","isStatic":false,"isPublic":true},"isDebitNormal":{"name":"isDebitNormal","async":false,"parameters":[],"returnType":"boolean","isStatic":false,"isPublic":true},"isCreditNormal":{"name":"isCreditNormal","async":false,"parameters":[],"returnType":"boolean","isStatic":false,"isPublic":true},"getFullPath":{"name":"getFullPath","async":true,"parameters":[],"returnType":"Promise<string>","isStatic":false,"isPublic":true},"toTreeNode":{"name":"toTreeNode","async":true,"parameters":[],"returnType":"Promise<AccountTreeNode>","isStatic":false,"isPublic":true},"getBalance":{"name":"getBalance","async":true,"parameters":[{"name":"asOfDate","type":"Date","optional":true}],"returnType":"Promise<number>","isStatic":false,"isPublic":true},"createChild":{"name":"createChild","async":true,"parameters":[{"name":"options","type":"Omit<AccountOptions, 'parentId' | 'type'>","optional":false}],"returnType":"Promise<Account>","isStatic":false,"isPublic":true}},"decoratorConfig":{"tableName":"ledger_accounts","api":{"include":["list","get","create","update","delete"]},"mcp":{"include":["list","get","create"]},"cli":{"skipApiCheck":true},"tenantScoped":{"mode":"optional"},"conflictColumns":["tenant_id","slug","context"]},"extends":"SmrtHierarchical","exportName":"Account","collectionExportName":"AccountCollection","displayLabelField":"name","schema":{"tableName":"ledger_accounts","ddl":"CREATE TABLE IF NOT EXISTS \\"ledger_accounts\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"parent_id\\" UUID,\\n \\"tenant_id\\" UUID,\\n \\"number\\" TEXT DEFAULT '',\\n \\"name\\" TEXT DEFAULT '',\\n \\"description\\" TEXT DEFAULT '',\\n \\"type\\" TEXT DEFAULT 'asset',\\n \\"ledger_id\\" UUID,\\n \\"active\\" BOOLEAN DEFAULT TRUE,\\n \\"metadata\\" JSON DEFAULT '{}'\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"parent_id":{"type":"UUID","referenceKind":"foreignKey","notNull":false,"unique":false,"foreignKey":{"table":"ledger_accounts","column":"id","onDelete":"NO ACTION","onUpdate":"CASCADE"}},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"number":{"type":"TEXT","notNull":false,"unique":false,"default":""},"name":{"type":"TEXT","notNull":false,"unique":false,"default":""},"description":{"type":"TEXT","notNull":false,"unique":false,"default":""},"type":{"type":"TEXT","notNull":false,"unique":false,"default":"asset"},"ledger_id":{"type":"UUID","referenceKind":"foreignKey","notNull":false,"unique":false,"foreignKey":{"table":"ledgers","column":"id","onDelete":"NO ACTION","onUpdate":"CASCADE"}},"active":{"type":"BOOLEAN","notNull":false,"unique":false,"default":true},"metadata":{"type":"JSON","notNull":false,"unique":false,"default":{}}},"indexes":[{"name":"ledger_accounts_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true,"nullsNotDistinct":true},{"name":"ledger_accounts_tenant_id_created_at_idx","columns":["tenant_id","created_at"]},{"name":"ledger_accounts_parent_id_idx","columns":["parent_id"]},{"name":"ledger_accounts_ledger_id_idx","columns":["ledger_id"]}],"version":"caea63eb"},"importPath":"@happyvertical/smrt-ledgers"},"@happyvertical/smrt-ledgers:Journal":{"name":"journal","className":"Journal","qualifiedName":"@happyvertical/smrt-ledgers:Journal","collection":"journals","filePath":"/home/runner/work/smrt/smrt/packages/ledgers/src/models/Journal.ts","packageName":"@happyvertical/smrt-ledgers","fields":{"tenantId":{"type":"text","required":false,"_meta":{"sqlType":"UUID","nullable":true,"__tenancy":{"isTenantIdField":true,"autoFilter":true,"required":false,"autoPopulate":true,"nullable":true,"mode":"optional","field":"tenantId","allowSuperAdminBypass":false}}},"number":{"type":"text","required":false,"default":"","description":"The journal's reference number.","_meta":{"description":"The journal's reference number."}},"date":{"type":"datetime","required":false,"description":"The date of the transaction.","_meta":{"description":"The date of the transaction."}},"description":{"type":"text","required":false,"default":"","description":"What the transaction was.","_meta":{"description":"What the transaction was."}},"sourceModule":{"type":"text","required":false,"default":""},"sourceRef":{"type":"text","required":false},"ledgerId":{"type":"foreignKey","required":false,"related":"Ledger","description":"The ledger policy that governs this journal.","_meta":{"description":"The ledger policy that governs this journal.","nullable":true}},"idempotencyKey":{"type":"text","required":false,"_meta":{"nullable":true}},"requestDigest":{"type":"text","required":false},"status":{"type":"text","required":false,"default":"draft","description":"draft until final, then posted, or voided.","_meta":{"description":"draft until final, then posted, or voided."},"enum":["draft","posted","voided"]},"postedAt":{"type":"datetime","required":false,"description":"When it was posted.","_meta":{"description":"When it was posted."}},"voidedAt":{"type":"datetime","required":false},"voidReason":{"type":"text","required":false},"metadata":{"type":"json","required":false,"default":{}}},"methods":{"isDraft":{"name":"isDraft","async":false,"parameters":[],"returnType":"boolean","isStatic":false,"isPublic":true},"isPosted":{"name":"isPosted","async":false,"parameters":[],"returnType":"boolean","isStatic":false,"isPublic":true},"isVoided":{"name":"isVoided","async":false,"parameters":[],"returnType":"boolean","isStatic":false,"isPublic":true},"isEditable":{"name":"isEditable","async":false,"parameters":[],"returnType":"boolean","isStatic":false,"isPublic":true},"getEntries":{"name":"getEntries","async":true,"parameters":[],"returnType":"any","isStatic":false,"isPublic":true},"getTotalDebits":{"name":"getTotalDebits","async":true,"parameters":[],"returnType":"Promise<number>","isStatic":false,"isPublic":true},"getTotalCredits":{"name":"getTotalCredits","async":true,"parameters":[],"returnType":"Promise<number>","isStatic":false,"isPublic":true},"isBalanced":{"name":"isBalanced","async":true,"parameters":[],"returnType":"Promise<boolean>","isStatic":false,"isPublic":true},"getLedger":{"name":"getLedger","async":true,"parameters":[],"returnType":"any","isStatic":false,"isPublic":true},"addEntry":{"name":"addEntry","async":true,"parameters":[{"name":"data","type":"JournalEntryData","optional":false}],"returnType":"Promise<void>","isStatic":false,"isPublic":true},"post":{"name":"post","async":true,"parameters":[],"returnType":"Promise<void>","isStatic":false,"isPublic":true},"void":{"name":"void","async":true,"parameters":[{"name":"reason","type":"string","optional":false}],"returnType":"Promise<void>","isStatic":false,"isPublic":true},"save":{"name":"save","async":true,"parameters":[{"name":"options","type":"any","optional":true,"typeUnresolved":true}],"returnType":"Promise<this>","isStatic":false,"isPublic":true},"delete":{"name":"delete","async":true,"parameters":[{"name":"options","type":"any","optional":true,"typeUnresolved":true}],"returnType":"Promise<void>","isStatic":false,"isPublic":true},"summarize":{"name":"summarize","async":true,"parameters":[],"returnType":"Promise<string>","isStatic":false,"isPublic":true}},"decoratorConfig":{"api":{"include":["list","get","create"]},"mcp":{"include":["list","get","create"]},"cli":{"skipApiCheck":true},"indexes":[{"name":"journals_ledger_idempotency_key","columns":["tenantId","ledgerId","idempotencyKey"],"unique":true}],"tenantScoped":{"mode":"optional"},"conflictColumns":["tenant_id","slug","context"]},"extends":"SmrtObject","exportName":"Journal","collectionExportName":"JournalCollection","schema":{"tableName":"journals","ddl":"CREATE TABLE IF NOT EXISTS \\"journals\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID,\\n \\"number\\" TEXT DEFAULT '',\\n \\"date\\" TIMESTAMP,\\n \\"description\\" TEXT DEFAULT '',\\n \\"source_module\\" TEXT DEFAULT '',\\n \\"source_ref\\" TEXT,\\n \\"ledger_id\\" UUID,\\n \\"idempotency_key\\" TEXT,\\n \\"request_digest\\" TEXT,\\n \\"status\\" TEXT DEFAULT 'draft',\\n \\"posted_at\\" TIMESTAMP,\\n \\"voided_at\\" TIMESTAMP,\\n \\"void_reason\\" TEXT,\\n \\"metadata\\" JSON DEFAULT '{}'\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"number":{"type":"TEXT","notNull":false,"unique":false,"default":""},"date":{"type":"TIMESTAMP","notNull":false,"unique":false},"description":{"type":"TEXT","notNull":false,"unique":false,"default":""},"source_module":{"type":"TEXT","notNull":false,"unique":false,"default":""},"source_ref":{"type":"TEXT","notNull":false,"unique":false},"ledger_id":{"type":"UUID","referenceKind":"foreignKey","notNull":false,"unique":false,"foreignKey":{"table":"ledgers","column":"id","onDelete":"NO ACTION","onUpdate":"CASCADE"}},"idempotency_key":{"type":"TEXT","notNull":false,"unique":false},"request_digest":{"type":"TEXT","notNull":false,"unique":false},"status":{"type":"TEXT","notNull":false,"unique":false,"default":"draft"},"posted_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"voided_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"void_reason":{"type":"TEXT","notNull":false,"unique":false},"metadata":{"type":"JSON","notNull":false,"unique":false,"default":{}}},"indexes":[{"name":"journals_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true,"nullsNotDistinct":true},{"name":"journals_ledger_idempotency_key","columns":["tenant_id","ledger_id","idempotency_key"],"unique":true},{"name":"journals_tenant_id_created_at_idx","columns":["tenant_id","created_at"]},{"name":"journals_ledger_id_idx","columns":["ledger_id"]}],"version":"1e73dd60"},"importPath":"@happyvertical/smrt-ledgers"},"@happyvertical/smrt-ledgers:JournalEntry":{"name":"journalentry","className":"JournalEntry","qualifiedName":"@happyvertical/smrt-ledgers:JournalEntry","collection":"journalentries","filePath":"/home/runner/work/smrt/smrt/packages/ledgers/src/models/JournalEntry.ts","packageName":"@happyvertical/smrt-ledgers","fields":{"tenantId":{"type":"text","required":false,"_meta":{"sqlType":"UUID","nullable":true,"__tenancy":{"isTenantIdField":true,"autoFilter":true,"required":false,"autoPopulate":true,"nullable":true,"mode":"optional","field":"tenantId","allowSuperAdminBypass":false}}},"journalId":{"type":"foreignKey","required":false,"related":"Journal","description":"The journal this entry belongs to.","_meta":{"description":"The journal this entry belongs to."}},"accountId":{"type":"foreignKey","required":false,"related":"Account","description":"The account this entry changes.","_meta":{"description":"The account this entry changes."}},"counterpartyKind":{"type":"text","required":false,"description":"Generic counterparty type.","_meta":{"description":"Generic counterparty type.","nullable":true}},"counterpartyId":{"type":"text","required":false,"description":"Generic counterparty identifier.","_meta":{"description":"Generic counterparty identifier.","nullable":true}},"dueDate":{"type":"datetime","required":false,"description":"When this open receivable or payable is due.","_meta":{"description":"When this open receivable or payable is due."}},"settlesSourceRef":{"type":"text","required":false},"debit":{"type":"decimal","required":false,"default":0,"description":"The amount debited. Zero on a credit entry.","_meta":{"description":"The amount debited. Zero on a credit entry."}},"credit":{"type":"decimal","required":false,"default":0,"description":"The amount credited. Zero on a debit entry.","_meta":{"description":"The amount credited. Zero on a debit entry."}},"currency":{"type":"text","required":false,"default":"USD","description":"The currency of the amounts.","_meta":{"description":"The currency of the amounts."}},"exchangeRate":{"type":"decimal","required":false,"default":1},"memo":{"type":"text","required":false,"default":"","description":"A note on this entry.","_meta":{"description":"A note on this entry."}},"metadata":{"type":"json","required":false,"default":{}}},"methods":{"save":{"name":"save","async":true,"parameters":[{"name":"options","type":"any","optional":true,"typeUnresolved":true}],"returnType":"Promise<this>","isStatic":false,"isPublic":true},"delete":{"name":"delete","async":true,"parameters":[{"name":"options","type":"any","optional":true,"typeUnresolved":true}],"returnType":"Promise<void>","isStatic":false,"isPublic":true},"isDebit":{"name":"isDebit","async":false,"parameters":[],"returnType":"boolean","isStatic":false,"isPublic":true},"isCredit":{"name":"isCredit","async":false,"parameters":[],"returnType":"boolean","isStatic":false,"isPublic":true},"getAmount":{"name":"getAmount","async":false,"parameters":[],"returnType":"number","isStatic":false,"isPublic":true},"getBaseAmount":{"name":"getBaseAmount","async":false,"parameters":[],"returnType":"number","isStatic":false,"isPublic":true},"getJournal":{"name":"getJournal","async":true,"parameters":[],"returnType":"any","isStatic":false,"isPublic":true},"getAccount":{"name":"getAccount","async":true,"parameters":[],"returnType":"any","isStatic":false,"isPublic":true},"getDescription":{"name":"getDescription","async":true,"parameters":[],"returnType":"Promise<string>","isStatic":false,"isPublic":true}},"decoratorConfig":{"api":{"include":["list","get"]},"mcp":{"include":["list","get"]},"cli":{"skipApiCheck":true},"tenantScoped":{"mode":"optional"},"conflictColumns":["tenant_id","slug","context"]},"extends":"SmrtObject","exportName":"JournalEntry","collectionExportName":"JournalEntryCollection","schema":{"tableName":"journal_entries","ddl":"CREATE TABLE IF NOT EXISTS \\"journal_entries\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID,\\n \\"journal_id\\" UUID,\\n \\"account_id\\" UUID,\\n \\"counterparty_kind\\" TEXT,\\n \\"counterparty_id\\" TEXT,\\n \\"due_date\\" TIMESTAMP,\\n \\"settles_source_ref\\" TEXT,\\n \\"debit\\" REAL DEFAULT 0,\\n \\"credit\\" REAL DEFAULT 0,\\n \\"currency\\" TEXT DEFAULT 'USD',\\n \\"exchange_rate\\" REAL DEFAULT 1,\\n \\"memo\\" TEXT DEFAULT '',\\n \\"metadata\\" JSON DEFAULT '{}'\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"journal_id":{"type":"UUID","referenceKind":"foreignKey","notNull":false,"unique":false,"foreignKey":{"table":"journals","column":"id","onDelete":"NO ACTION","onUpdate":"CASCADE"}},"account_id":{"type":"UUID","referenceKind":"foreignKey","notNull":false,"unique":false,"foreignKey":{"table":"ledger_accounts","column":"id","onDelete":"NO ACTION","onUpdate":"CASCADE"}},"counterparty_kind":{"type":"TEXT","notNull":false,"unique":false},"counterparty_id":{"type":"TEXT","notNull":false,"unique":false},"due_date":{"type":"TIMESTAMP","notNull":false,"unique":false},"settles_source_ref":{"type":"TEXT","notNull":false,"unique":false},"debit":{"type":"REAL","notNull":false,"unique":false,"default":0},"credit":{"type":"REAL","notNull":false,"unique":false,"default":0},"currency":{"type":"TEXT","notNull":false,"unique":false,"default":"USD"},"exchange_rate":{"type":"REAL","notNull":false,"unique":false,"default":1},"memo":{"type":"TEXT","notNull":false,"unique":false,"default":""},"metadata":{"type":"JSON","notNull":false,"unique":false,"default":{}}},"indexes":[{"name":"journal_entries_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true,"nullsNotDistinct":true},{"name":"journal_entries_tenant_id_created_at_idx","columns":["tenant_id","created_at"]},{"name":"journal_entries_journal_id_idx","columns":["journal_id"]},{"name":"journal_entries_account_id_idx","columns":["account_id"]}],"version":"e96b76a2"},"importPath":"@happyvertical/smrt-ledgers"},"@happyvertical/smrt-ledgers:Ledger":{"name":"ledger","className":"Ledger","qualifiedName":"@happyvertical/smrt-ledgers:Ledger","collection":"ledgers","description":"A named accounting scope. Exact ledgers store one currency's minor units and reject fractional entries; legacy journals without a ledger retain the tolerant balance rule for backwards compatibility.","filePath":"/home/runner/work/smrt/smrt/packages/ledgers/src/models/Ledger.ts","packageName":"@happyvertical/smrt-ledgers","fields":{"tenantId":{"type":"text","required":false,"_meta":{"sqlType":"UUID","nullable":true,"__tenancy":{"isTenantIdField":true,"autoFilter":true,"required":false,"autoPopulate":true,"nullable":true,"mode":"optional","field":"tenantId","allowSuperAdminBypass":false}}},"name":{"type":"text","required":false,"description":"The accounting scope name.","_meta":{"description":"The accounting scope name."}},"currency":{"type":"text","required":false,"description":"ISO 4217 currency used by this ledger.","_meta":{"description":"ISO 4217 currency used by this ledger."}},"balanceMode":{"type":"text","required":false,"default":"tolerant","description":"tolerant accepts decimal units; exact requires integer minor units.","_meta":{"description":"tolerant accepts decimal units; exact requires integer minor units."},"enum":["tolerant","exact-integer"]}},"methods":{"delete":{"name":"delete","async":true,"parameters":[],"returnType":"Promise<void>","isStatic":false,"isPublic":true}},"decoratorConfig":{"api":{"include":["list","get","create","update"]},"mcp":{"include":["list","get","create"]},"cli":{"skipApiCheck":true},"tenantScoped":{"mode":"optional"},"conflictColumns":["tenant_id","slug","context"]},"extends":"SmrtObject","exportName":"Ledger","collectionExportName":"LedgerCollection","displayLabelField":"name","schema":{"tableName":"ledgers","ddl":"CREATE TABLE IF NOT EXISTS \\"ledgers\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID,\\n \\"name\\" TEXT,\\n \\"currency\\" TEXT,\\n \\"balance_mode\\" TEXT DEFAULT 'tolerant'\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"name":{"type":"TEXT","notNull":false,"unique":false},"currency":{"type":"TEXT","notNull":false,"unique":false},"balance_mode":{"type":"TEXT","notNull":false,"unique":false,"default":"tolerant"}},"indexes":[{"name":"ledgers_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true,"nullsNotDistinct":true},{"name":"ledgers_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"be316e4f"},"importPath":"@happyvertical/smrt-ledgers"}},"moduleType":"smrt","recipes":[{"id":"ledgers.bookkeeping","className":"BookkeepingRecipe","label":"Bookkeeping","summary":"Keep your books: a chart of accounts and double-entry journals.","synonyms":["accounting","ledger","general ledger","journals","chart of accounts"],"models":["@happyvertical/smrt-ledgers:Account","@happyvertical/smrt-ledgers:Journal","@happyvertical/smrt-ledgers:JournalEntry"],"nav":[{"label":"Accounts","model":"@happyvertical/smrt-ledgers:Account","icon":"bank","description":"The accounts your books are kept in, like sales, rent and bank."},{"label":"Journals","model":"@happyvertical/smrt-ledgers:Journal","icon":"book","description":"The entries behind your accounts, so every dollar has a trail."}],"requires":[],"section":{"id":"accounting","label":"Accounting","icon":"bank","description":"Your books: accounts, journals and balances."},"options":{"@happyvertical/smrt-ledgers:Account":{"fields":{"metadata":{"visibility":"hidden"},"parentId":{"visibility":"hidden"}}},"@happyvertical/smrt-ledgers:Journal":{"fields":{"sourceModule":{"visibility":"hidden"},"sourceRef":{"visibility":"hidden"},"idempotencyKey":{"visibility":"hidden"},"requestDigest":{"visibility":"hidden"},"voidedAt":{"visibility":"hidden"},"voidReason":{"visibility":"hidden"},"metadata":{"visibility":"hidden"}}},"@happyvertical/smrt-ledgers:JournalEntry":{"fields":{"exchangeRate":{"visibility":"hidden"},"settlesSourceRef":{"visibility":"hidden"},"metadata":{"visibility":"hidden"}}}},"help":{"markdown":"## Overview\\n\\nBookkeeping keeps your accounts. You list the accounts you use (your chart of\\naccounts) and record each transaction as a journal whose entries debit and\\ncredit those accounts.\\n\\n## Tasks\\n\\n### Set up your accounts\\n\\n1. Create a new account.\\n2. Give it a **{field:number}** and a **{field:name}**.\\n3. Choose its **{field:type}**: asset, liability, equity, revenue or expense.\\n\\n### Record a transaction\\n\\n1. Create a new journal and add a **{field:description}**.\\n2. Add entries: pick the account on each and enter a **{field:debit}** or a\\n **{field:credit}**. They must add up to the same total.\\n3. Set the journal's **{field:status}** to posted when it is final. A posted\\n journal is voided, not edited.\\n","fieldRefs":["credit","debit","description","name","number","status","type"]},"demo":{"mode":"server","reasons":["Needs a server because its package does not build for a browser: core migrations (node:os, node:crypto); and its package depends on @happyvertical/smrt-tenancy, which do not build for a browser (#3624, #3626)."]}}],"smrtDependencies":["@happyvertical/smrt-core","@happyvertical/smrt-prompts","@happyvertical/smrt-tenancy"],"browser":{"status":"server-only","issues":["#3624","#3626"],"reason":"core migrations (node:os, node:crypto)","via":["@happyvertical/smrt-tenancy"]},"stampsConstructors":true}`));
|
|
21
22
|
//#endregion
|
|
22
23
|
//#region src/prompts.ts
|
|
23
24
|
var smrtLedgersJournalSummarizePrompt = definePrompt({
|
|
@@ -242,6 +243,11 @@ var JournalEntry = class extends SmrtObject {
|
|
|
242
243
|
tenantId = null;
|
|
243
244
|
journalId = "";
|
|
244
245
|
accountId = "";
|
|
246
|
+
counterpartyKind = null;
|
|
247
|
+
counterpartyId = null;
|
|
248
|
+
dueDate = null;
|
|
249
|
+
/** Source reference of the open item reduced by this settlement line. */
|
|
250
|
+
settlesSourceRef = null;
|
|
245
251
|
debit = 0;
|
|
246
252
|
credit = 0;
|
|
247
253
|
currency = "USD";
|
|
@@ -256,8 +262,13 @@ var JournalEntry = class extends SmrtObject {
|
|
|
256
262
|
metadata = {};
|
|
257
263
|
constructor(options = {}) {
|
|
258
264
|
super(options);
|
|
265
|
+
if (options.tenantId !== void 0) this.tenantId = options.tenantId;
|
|
259
266
|
if (options.journalId !== void 0) this.journalId = options.journalId;
|
|
260
267
|
if (options.accountId !== void 0) this.accountId = options.accountId;
|
|
268
|
+
if (options.counterpartyKind !== void 0) this.counterpartyKind = options.counterpartyKind;
|
|
269
|
+
if (options.counterpartyId !== void 0) this.counterpartyId = options.counterpartyId;
|
|
270
|
+
if (options.dueDate !== void 0) this.dueDate = options.dueDate;
|
|
271
|
+
if (options.settlesSourceRef !== void 0) this.settlesSourceRef = options.settlesSourceRef;
|
|
261
272
|
if (options.debit !== void 0) this.debit = options.debit;
|
|
262
273
|
if (options.credit !== void 0) this.credit = options.credit;
|
|
263
274
|
if (options.currency !== void 0) this.currency = options.currency;
|
|
@@ -265,16 +276,60 @@ var JournalEntry = class extends SmrtObject {
|
|
|
265
276
|
if (options.memo !== void 0) this.memo = options.memo;
|
|
266
277
|
if (options.metadata !== void 0) this.metadata = options.metadata;
|
|
267
278
|
}
|
|
279
|
+
async save(options = {}) {
|
|
280
|
+
return this.withTransaction(async () => {
|
|
281
|
+
const journal = await this.getJournal();
|
|
282
|
+
if (!journal) throw new Error("Journal entry requires an accessible parent journal");
|
|
283
|
+
if (journal.ledgerId) {
|
|
284
|
+
if (!journal.isDraft() || !journal.updated_at) throw new Error("Ledger entries are immutable after posting");
|
|
285
|
+
await journal.claimRevision(journal.updated_at);
|
|
286
|
+
}
|
|
287
|
+
return super.save(options);
|
|
288
|
+
});
|
|
289
|
+
}
|
|
268
290
|
/**
|
|
269
291
|
* Validate entry before save
|
|
270
292
|
*/
|
|
271
293
|
async validateBeforeSave() {
|
|
272
294
|
await super.validateBeforeSave();
|
|
295
|
+
this.requireInsertOnSave({ preserveDerivedSlug: true });
|
|
296
|
+
const journal = await this.getJournal();
|
|
297
|
+
const owner = this.tenantId ?? (isTenancyEnabled() && !isSuperAdminBypass() ? getTenantId() ?? null : null);
|
|
298
|
+
if (!journal || journal.tenantId !== owner) throw new Error("Journal entry and parent must belong to the same tenant");
|
|
299
|
+
const account = await this.getAccount();
|
|
300
|
+
if (!account || account.ledgerId !== journal.ledgerId || journal.ledgerId && account.tenantId !== journal.tenantId) throw new Error("Journal entry account must belong to its journal ledger");
|
|
301
|
+
if (journal.ledgerId && !journal.isDraft()) throw new Error("Ledger entries are immutable after posting");
|
|
302
|
+
if (this.id) {
|
|
303
|
+
const stored = await this.db.get(this.tableName, { id: this.id });
|
|
304
|
+
if (stored && stored.journal_id !== this.journalId) throw new Error("Journal entry cannot be moved to another journal");
|
|
305
|
+
if (stored && stored.account_id !== this.accountId) {
|
|
306
|
+
const oldAccount = await this.loadAccount(String(stored.account_id));
|
|
307
|
+
if (!oldAccount || oldAccount.ledgerId !== journal.ledgerId) throw new Error("Stored entry account must belong to its journal ledger");
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
if (!Number.isFinite(this.debit) || !Number.isFinite(this.credit)) throw new Error("Entry amounts must be finite");
|
|
273
311
|
if (this.debit < 0) throw new Error("Debit amount cannot be negative");
|
|
274
312
|
if (this.credit < 0) throw new Error("Credit amount cannot be negative");
|
|
275
313
|
if (this.debit > 0 && this.credit > 0) throw new Error("Entry cannot have both debit and credit amounts");
|
|
276
314
|
if (this.debit === 0 && this.credit === 0) throw new Error("Entry must have either a debit or credit amount");
|
|
277
315
|
if (this.exchangeRate <= 0) throw new Error("Exchange rate must be positive");
|
|
316
|
+
if (!!this.counterpartyKind !== !!this.counterpartyId) throw new Error("Counterparty kind and ID must be provided together");
|
|
317
|
+
if (this.dueDate && (!this.counterpartyKind || !this.counterpartyId)) throw new Error("Due date requires a counterparty");
|
|
318
|
+
}
|
|
319
|
+
async delete(options = {}) {
|
|
320
|
+
await this.withTransaction(async () => {
|
|
321
|
+
const stored = this.id ? await this.db.get(this.tableName, { id: this.id }) : null;
|
|
322
|
+
if (stored) {
|
|
323
|
+
const { JournalCollection } = await Promise.resolve().then(() => Journals_exports);
|
|
324
|
+
const journal = await (await JournalCollection.create({ db: this.db })).get({ id: String(stored.journal_id) });
|
|
325
|
+
if (!journal || journal.tenantId !== stored.tenant_id) throw new Error("Journal entry requires its accessible same-tenant parent");
|
|
326
|
+
if (journal.ledgerId) {
|
|
327
|
+
if (!journal.isDraft() || !journal.updated_at) throw new Error("Ledger entries are immutable after posting");
|
|
328
|
+
await journal.claimRevision(journal.updated_at);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
await super.delete(options);
|
|
332
|
+
});
|
|
278
333
|
}
|
|
279
334
|
/**
|
|
280
335
|
* Check if this is a debit entry
|
|
@@ -306,15 +361,32 @@ var JournalEntry = class extends SmrtObject {
|
|
|
306
361
|
async getJournal() {
|
|
307
362
|
if (!this.journalId) return null;
|
|
308
363
|
const { JournalCollection } = await Promise.resolve().then(() => Journals_exports);
|
|
309
|
-
return await (await JournalCollection.create(this.options)).get({ id: this.journalId });
|
|
364
|
+
return await (await JournalCollection.create(this.options)).get({ id: this.journalId }, { cache: false });
|
|
310
365
|
}
|
|
311
366
|
/**
|
|
312
367
|
* Get the account
|
|
313
368
|
*/
|
|
314
369
|
async getAccount() {
|
|
315
370
|
if (!this.accountId) return null;
|
|
371
|
+
return this.loadAccount(this.accountId);
|
|
372
|
+
}
|
|
373
|
+
async loadAccount(accountId) {
|
|
316
374
|
const { AccountCollection } = await Promise.resolve().then(() => Accounts_exports);
|
|
317
|
-
|
|
375
|
+
const collection = await AccountCollection.create(this.options);
|
|
376
|
+
const account = await collection.get({ id: accountId }, { cache: false });
|
|
377
|
+
if (account) return account;
|
|
378
|
+
const tenant = getTenantId();
|
|
379
|
+
if (!tenant) return null;
|
|
380
|
+
return withTenantGlobalRead(tenant, async () => {
|
|
381
|
+
return (await collection.list({
|
|
382
|
+
where: {
|
|
383
|
+
id: accountId,
|
|
384
|
+
tenantId: null,
|
|
385
|
+
ledgerId: null
|
|
386
|
+
},
|
|
387
|
+
limit: 1
|
|
388
|
+
}))[0] ?? null;
|
|
389
|
+
});
|
|
318
390
|
}
|
|
319
391
|
/**
|
|
320
392
|
* Get a formatted description of this entry
|
|
@@ -328,6 +400,15 @@ __publicField$1(JournalEntry, "__smrtPackage__", "@happyvertical/smrt-ledgers");
|
|
|
328
400
|
__decorateClass$1([tenantId({ nullable: true })], JournalEntry.prototype, "tenantId", 2);
|
|
329
401
|
__decorateClass$1([field({ description: "The journal this entry belongs to." }), foreignKey("Journal")], JournalEntry.prototype, "journalId", 2);
|
|
330
402
|
__decorateClass$1([field({ description: "The account this entry changes." }), foreignKey(Account)], JournalEntry.prototype, "accountId", 2);
|
|
403
|
+
__decorateClass$1([field({
|
|
404
|
+
description: "Generic counterparty type.",
|
|
405
|
+
nullable: true
|
|
406
|
+
})], JournalEntry.prototype, "counterpartyKind", 2);
|
|
407
|
+
__decorateClass$1([field({
|
|
408
|
+
description: "Generic counterparty identifier.",
|
|
409
|
+
nullable: true
|
|
410
|
+
})], JournalEntry.prototype, "counterpartyId", 2);
|
|
411
|
+
__decorateClass$1([field({ description: "When this open receivable or payable is due." })], JournalEntry.prototype, "dueDate", 2);
|
|
331
412
|
__decorateClass$1([field({ description: "The amount debited. Zero on a credit entry." })], JournalEntry.prototype, "debit", 2);
|
|
332
413
|
__decorateClass$1([field({ description: "The amount credited. Zero on a debit entry." })], JournalEntry.prototype, "credit", 2);
|
|
333
414
|
__decorateClass$1([field({ description: "The currency of the amounts." })], JournalEntry.prototype, "currency", 2);
|
|
@@ -366,6 +447,82 @@ var JournalEntryCollection = class extends SmrtCollection {
|
|
|
366
447
|
async findByAccount(accountId) {
|
|
367
448
|
return await this.list({ where: { accountId } });
|
|
368
449
|
}
|
|
450
|
+
/** Posted AR/AP net balances by opaque counterparty for selected accounts. */
|
|
451
|
+
async getCounterpartyBalances(options) {
|
|
452
|
+
const movements = await this.listPostedMovements(options);
|
|
453
|
+
const result = /* @__PURE__ */ new Map();
|
|
454
|
+
for (const movement of movements) {
|
|
455
|
+
const entry = await this.get({ id: movement.entryId });
|
|
456
|
+
if (!entry?.counterpartyKind || !entry.counterpartyId) continue;
|
|
457
|
+
const key = JSON.stringify([
|
|
458
|
+
entry.counterpartyKind,
|
|
459
|
+
entry.counterpartyId,
|
|
460
|
+
movement.currency
|
|
461
|
+
]);
|
|
462
|
+
const row = result.get(key) ?? {
|
|
463
|
+
counterpartyKind: entry.counterpartyKind,
|
|
464
|
+
counterpartyId: entry.counterpartyId,
|
|
465
|
+
currency: movement.currency,
|
|
466
|
+
balance: 0
|
|
467
|
+
};
|
|
468
|
+
row.balance = storedUnit(row.balance + (movement.debit - movement.credit) * (options.normalBalance === "credit" ? -1 : 1), "counterparty balance");
|
|
469
|
+
result.set(key, row);
|
|
470
|
+
}
|
|
471
|
+
return [...result.values()].filter((row) => row.balance !== 0);
|
|
472
|
+
}
|
|
473
|
+
/**
|
|
474
|
+
* Open-item aging. An invoice/allocation line needs a dueDate and sourceRef;
|
|
475
|
+
* a settlement line names that source in settlesSourceRef. This avoids
|
|
476
|
+
* pretending that net counterparty movements are aging.
|
|
477
|
+
*/
|
|
478
|
+
async getCounterpartyAging(options, asOf) {
|
|
479
|
+
const movements = await this.listPostedMovements({
|
|
480
|
+
...options,
|
|
481
|
+
to: asOf
|
|
482
|
+
});
|
|
483
|
+
const rows = /* @__PURE__ */ new Map();
|
|
484
|
+
const balances = /* @__PURE__ */ new Map();
|
|
485
|
+
for (const movement of movements) {
|
|
486
|
+
const entry = await this.get({ id: movement.entryId });
|
|
487
|
+
const source = entry?.settlesSourceRef ?? movement.sourceRef;
|
|
488
|
+
if (!entry?.counterpartyKind || !entry.counterpartyId || !source) continue;
|
|
489
|
+
const key = JSON.stringify([
|
|
490
|
+
entry.counterpartyKind,
|
|
491
|
+
entry.counterpartyId,
|
|
492
|
+
movement.currency,
|
|
493
|
+
source
|
|
494
|
+
]);
|
|
495
|
+
balances.set(key, storedUnit((balances.get(key) ?? 0) + (movement.debit - movement.credit) * (options.normalBalance === "credit" ? -1 : 1), "open item balance"));
|
|
496
|
+
if (!entry.settlesSourceRef && entry.dueDate) {
|
|
497
|
+
const prior = rows.get(key);
|
|
498
|
+
if (prior && prior.dueDate.getTime() !== entry.dueDate.getTime()) throw new Error("Open item source has conflicting due dates");
|
|
499
|
+
rows.set(key, {
|
|
500
|
+
counterpartyKind: entry.counterpartyKind,
|
|
501
|
+
counterpartyId: entry.counterpartyId,
|
|
502
|
+
currency: movement.currency,
|
|
503
|
+
sourceRef: source,
|
|
504
|
+
dueDate: entry.dueDate,
|
|
505
|
+
balance: 0,
|
|
506
|
+
current: 0,
|
|
507
|
+
days1To30: 0,
|
|
508
|
+
days31To60: 0,
|
|
509
|
+
days61To90: 0,
|
|
510
|
+
daysOver90: 0
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
for (const [key, row] of rows) row.balance = balances.get(key) ?? 0;
|
|
515
|
+
for (const row of rows.values()) {
|
|
516
|
+
if (row.balance <= 0) continue;
|
|
517
|
+
const days = Math.floor((asOf.getTime() - row.dueDate.getTime()) / 864e5);
|
|
518
|
+
if (days <= 0) row.current = row.balance;
|
|
519
|
+
else if (days <= 30) row.days1To30 = row.balance;
|
|
520
|
+
else if (days <= 60) row.days31To60 = row.balance;
|
|
521
|
+
else if (days <= 90) row.days61To90 = row.balance;
|
|
522
|
+
else row.daysOver90 = row.balance;
|
|
523
|
+
}
|
|
524
|
+
return [...rows.values()].filter((row) => row.balance > 0);
|
|
525
|
+
}
|
|
369
526
|
/**
|
|
370
527
|
* Get account balance
|
|
371
528
|
*
|
|
@@ -463,6 +620,7 @@ var JournalEntryCollection = class extends SmrtCollection {
|
|
|
463
620
|
* the reporting boundary.
|
|
464
621
|
*/
|
|
465
622
|
async listPostedMovements(options) {
|
|
623
|
+
if (getTenantId() && getTenantId() !== options.tenantId) throw new Error("Posted movements tenant differs from active context");
|
|
466
624
|
const accountIds = [...new Set(options.accountIds)];
|
|
467
625
|
if (!options.tenantId?.trim() || !options.currency?.trim() || !(options.from instanceof Date) || !(options.to instanceof Date) || !Number.isFinite(options.from.getTime()) || !Number.isFinite(options.to.getTime()) || options.from > options.to) throw new Error("Posted movements require tenant, currency and ordered dates.");
|
|
468
626
|
if (accountIds.length === 0) return [];
|
|
@@ -595,6 +753,9 @@ var Journal = class extends SmrtObject {
|
|
|
595
753
|
* External reference (e.g., order ID, invoice number)
|
|
596
754
|
*/
|
|
597
755
|
sourceRef = null;
|
|
756
|
+
ledgerId = null;
|
|
757
|
+
idempotencyKey = null;
|
|
758
|
+
requestDigest = null;
|
|
598
759
|
status = "draft";
|
|
599
760
|
postedAt = null;
|
|
600
761
|
/**
|
|
@@ -611,11 +772,15 @@ var Journal = class extends SmrtObject {
|
|
|
611
772
|
metadata = {};
|
|
612
773
|
constructor(options = {}) {
|
|
613
774
|
super(options);
|
|
775
|
+
if (options.tenantId !== void 0) this.tenantId = options.tenantId;
|
|
614
776
|
if (options.number !== void 0) this.number = options.number;
|
|
615
777
|
if (options.date !== void 0) this.date = options.date;
|
|
616
778
|
if (options.description !== void 0) this.description = options.description;
|
|
617
779
|
if (options.sourceModule !== void 0) this.sourceModule = options.sourceModule;
|
|
618
780
|
if (options.sourceRef !== void 0) this.sourceRef = options.sourceRef;
|
|
781
|
+
if (options.ledgerId !== void 0) this.ledgerId = options.ledgerId;
|
|
782
|
+
if (options.idempotencyKey !== void 0) this.idempotencyKey = options.idempotencyKey;
|
|
783
|
+
if (options.requestDigest !== void 0) this.requestDigest = options.requestDigest;
|
|
619
784
|
if (options.status !== void 0) this.status = options.status;
|
|
620
785
|
if (options.postedAt !== void 0) this.postedAt = options.postedAt;
|
|
621
786
|
if (options.voidedAt !== void 0) this.voidedAt = options.voidedAt;
|
|
@@ -672,7 +837,15 @@ var Journal = class extends SmrtObject {
|
|
|
672
837
|
async isBalanced() {
|
|
673
838
|
const debits = await this.getTotalDebits();
|
|
674
839
|
const credits = await this.getTotalCredits();
|
|
675
|
-
|
|
840
|
+
const ledger = await this.getLedger();
|
|
841
|
+
if (!ledger || ledger.balanceMode === "tolerant") return Math.abs(debits - credits) < BALANCE_EPSILON;
|
|
842
|
+
const entries = await this.getEntries();
|
|
843
|
+
return Number.isSafeInteger(debits) && Number.isSafeInteger(credits) && entries.every((entry) => Number.isSafeInteger(entry.debit) && Number.isSafeInteger(entry.credit)) && debits === credits;
|
|
844
|
+
}
|
|
845
|
+
async getLedger() {
|
|
846
|
+
if (!this.ledgerId) return null;
|
|
847
|
+
const { LedgerCollection } = await Promise.resolve().then(() => Ledgers_exports);
|
|
848
|
+
return (await LedgerCollection.create(this.options)).get({ id: this.ledgerId });
|
|
676
849
|
}
|
|
677
850
|
/**
|
|
678
851
|
* Add an entry to this journal (only if draft)
|
|
@@ -681,27 +854,32 @@ var Journal = class extends SmrtObject {
|
|
|
681
854
|
if (!this.id) throw new Error("Journal must be saved before adding entries");
|
|
682
855
|
if (!this.isEditable()) throw new Error("Cannot add entries to a posted or voided journal");
|
|
683
856
|
const { JournalEntryCollection } = await Promise.resolve().then(() => JournalEntries_exports);
|
|
684
|
-
|
|
857
|
+
const entry = await (await JournalEntryCollection.create(this.options)).create({
|
|
685
858
|
journalId: this.id,
|
|
859
|
+
tenantId: this.tenantId,
|
|
686
860
|
accountId: data.accountId,
|
|
861
|
+
counterpartyKind: data.counterpartyKind ?? null,
|
|
862
|
+
counterpartyId: data.counterpartyId ?? null,
|
|
863
|
+
dueDate: data.dueDate ?? null,
|
|
864
|
+
settlesSourceRef: data.settlesSourceRef ?? null,
|
|
687
865
|
debit: data.debit || 0,
|
|
688
866
|
credit: data.credit || 0,
|
|
689
867
|
currency: data.currency || "USD",
|
|
690
868
|
exchangeRate: data.exchangeRate || 1,
|
|
691
869
|
memo: data.memo || ""
|
|
692
|
-
})
|
|
870
|
+
});
|
|
871
|
+
await entry.save();
|
|
872
|
+
if (this.ledgerId) {
|
|
873
|
+
const parent = await entry.getJournal();
|
|
874
|
+
this.updated_at = parent?.updated_at ?? this.updated_at;
|
|
875
|
+
}
|
|
693
876
|
}
|
|
694
877
|
/**
|
|
695
878
|
* Post the journal (finalize and make immutable)
|
|
696
879
|
*/
|
|
697
880
|
async post() {
|
|
698
881
|
if (!this.isDraft()) throw new Error("Only draft journals can be posted");
|
|
699
|
-
|
|
700
|
-
const debits = await this.getTotalDebits();
|
|
701
|
-
const credits = await this.getTotalCredits();
|
|
702
|
-
throw new Error(`Journal is not balanced. Debits: ${debits}, Credits: ${credits}`);
|
|
703
|
-
}
|
|
704
|
-
if ((await this.getEntries()).length === 0) throw new Error("Journal must have at least one entry");
|
|
882
|
+
await this.validatePosting();
|
|
705
883
|
this.status = "posted";
|
|
706
884
|
this.postedAt = /* @__PURE__ */ new Date();
|
|
707
885
|
await this.save();
|
|
@@ -716,6 +894,66 @@ var Journal = class extends SmrtObject {
|
|
|
716
894
|
this.voidReason = reason;
|
|
717
895
|
await this.save();
|
|
718
896
|
}
|
|
897
|
+
async validatePosting() {
|
|
898
|
+
if (!await this.isBalanced()) {
|
|
899
|
+
const debits = await this.getTotalDebits();
|
|
900
|
+
const credits = await this.getTotalCredits();
|
|
901
|
+
throw new Error(`Journal is not balanced. Debits: ${debits}, Credits: ${credits}`);
|
|
902
|
+
}
|
|
903
|
+
const entries = await this.getEntries();
|
|
904
|
+
if (entries.length === 0) throw new Error("Journal must have at least one entry");
|
|
905
|
+
const ledger = await this.getLedger();
|
|
906
|
+
if (this.ledgerId && !ledger) throw new Error(`Ledger not found: ${this.ledgerId}`);
|
|
907
|
+
if (ledger) {
|
|
908
|
+
if (ledger.tenantId !== this.tenantId) throw new Error("Journal and ledger must belong to the same tenant");
|
|
909
|
+
if (entries.some((entry) => entry.currency !== ledger.currency)) throw new Error(`Journal entries must use ledger currency ${ledger.currency}`);
|
|
910
|
+
}
|
|
911
|
+
const { AccountCollection } = await Promise.resolve().then(() => Accounts_exports);
|
|
912
|
+
const accounts = await AccountCollection.create(this.options);
|
|
913
|
+
for (const entry of entries) {
|
|
914
|
+
const account = await accounts.get({ id: entry.accountId });
|
|
915
|
+
if ((this.ledgerId || account?.ledgerId) && (!account || !account.active || account.tenantId !== this.tenantId || entry.tenantId !== this.tenantId || account.ledgerId !== this.ledgerId)) throw new Error("Journal entries must use active accounts owned by the journal ledger");
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
async save(options = {}) {
|
|
919
|
+
return this.withTransaction(async () => {
|
|
920
|
+
if (this.isPersisted && this.updated_at) {
|
|
921
|
+
await this.claimRevision(options.expectedUpdatedAt ?? this.updated_at);
|
|
922
|
+
if (options.expectedUpdatedAt !== void 0) options = {
|
|
923
|
+
...options,
|
|
924
|
+
expectedUpdatedAt: this.updated_at
|
|
925
|
+
};
|
|
926
|
+
}
|
|
927
|
+
return super.save(options);
|
|
928
|
+
});
|
|
929
|
+
}
|
|
930
|
+
async validateBeforeSave() {
|
|
931
|
+
await super.validateBeforeSave();
|
|
932
|
+
this.requireInsertOnSave({ preserveDerivedSlug: true });
|
|
933
|
+
if (this.id) {
|
|
934
|
+
const stored = await this.db.get(this.tableName, { id: this.id });
|
|
935
|
+
if (stored && stored.ledger_id !== this.ledgerId) throw new Error("Journal ledger scope is immutable after creation");
|
|
936
|
+
if (stored?.ledger_id && stored.status !== "draft") throw new Error("Ledger journals are immutable after posting; use a compensating journal");
|
|
937
|
+
}
|
|
938
|
+
if (this.status === "posted") {
|
|
939
|
+
if (this.ledgerId) await this.validatePosting();
|
|
940
|
+
else for (const entry of await this.getEntries()) if ((await entry.getAccount())?.ledgerId) throw new Error("Scoped accounts require their journal ledger");
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
async delete(options = {}) {
|
|
944
|
+
await this.withTransaction(async () => {
|
|
945
|
+
if (this.isPersisted && this.updated_at) {
|
|
946
|
+
await this.claimRevision(options.expectedUpdatedAt ?? this.updated_at);
|
|
947
|
+
if (options.expectedUpdatedAt !== void 0) options = {
|
|
948
|
+
...options,
|
|
949
|
+
expectedUpdatedAt: this.updated_at
|
|
950
|
+
};
|
|
951
|
+
}
|
|
952
|
+
const stored = this.id ? await this.db.get(this.tableName, { id: this.id }) : null;
|
|
953
|
+
if (stored?.ledger_id && stored.status !== "draft") throw new Error("Ledger journals are immutable after posting");
|
|
954
|
+
await super.delete(options);
|
|
955
|
+
});
|
|
956
|
+
}
|
|
719
957
|
/**
|
|
720
958
|
* AI-powered: Generate a summary of this journal.
|
|
721
959
|
*
|
|
@@ -757,6 +995,11 @@ __decorateClass([tenantId({ nullable: true })], Journal.prototype, "tenantId", 2
|
|
|
757
995
|
__decorateClass([field({ description: "The journal's reference number." })], Journal.prototype, "number", 2);
|
|
758
996
|
__decorateClass([field({ description: "The date of the transaction." })], Journal.prototype, "date", 2);
|
|
759
997
|
__decorateClass([field({ description: "What the transaction was." })], Journal.prototype, "description", 2);
|
|
998
|
+
__decorateClass([field({
|
|
999
|
+
description: "The ledger policy that governs this journal.",
|
|
1000
|
+
nullable: true
|
|
1001
|
+
}), foreignKey(Ledger)], Journal.prototype, "ledgerId", 2);
|
|
1002
|
+
__decorateClass([field({ nullable: true })], Journal.prototype, "idempotencyKey", 2);
|
|
760
1003
|
__decorateClass([field({ description: "draft until final, then posted, or voided." })], Journal.prototype, "status", 2);
|
|
761
1004
|
__decorateClass([field({ description: "When it was posted." })], Journal.prototype, "postedAt", 2);
|
|
762
1005
|
Journal = __decorateClass([TenantScoped({ mode: "optional" }), smrt({
|
|
@@ -770,7 +1013,16 @@ Journal = __decorateClass([TenantScoped({ mode: "optional" }), smrt({
|
|
|
770
1013
|
"get",
|
|
771
1014
|
"create"
|
|
772
1015
|
] },
|
|
773
|
-
cli: { skipApiCheck: true }
|
|
1016
|
+
cli: { skipApiCheck: true },
|
|
1017
|
+
indexes: [{
|
|
1018
|
+
name: "journals_ledger_idempotency_key",
|
|
1019
|
+
columns: [
|
|
1020
|
+
"tenantId",
|
|
1021
|
+
"ledgerId",
|
|
1022
|
+
"idempotencyKey"
|
|
1023
|
+
],
|
|
1024
|
+
unique: true
|
|
1025
|
+
}]
|
|
774
1026
|
})], Journal);
|
|
775
1027
|
//#endregion
|
|
776
1028
|
//#region src/collections/Journals.ts
|
|
@@ -871,11 +1123,15 @@ var JournalCollection = class extends SmrtCollection {
|
|
|
871
1123
|
if (data.entries.length === 0) throw new Error("Journal must have at least one entry");
|
|
872
1124
|
const journalNumber = await this.generateJournalNumber();
|
|
873
1125
|
const journal = await this.create({
|
|
1126
|
+
tenantId: data.tenantId ?? null,
|
|
874
1127
|
number: journalNumber,
|
|
875
1128
|
date: data.date || /* @__PURE__ */ new Date(),
|
|
876
1129
|
description: data.description,
|
|
877
1130
|
sourceModule: data.sourceModule || "manual",
|
|
878
1131
|
sourceRef: data.sourceRef || null,
|
|
1132
|
+
ledgerId: data.ledgerId ?? null,
|
|
1133
|
+
idempotencyKey: data.idempotencyKey ?? null,
|
|
1134
|
+
requestDigest: data.requestDigest ?? null,
|
|
879
1135
|
metadata: data.metadata || {}
|
|
880
1136
|
});
|
|
881
1137
|
await journal.save();
|
|
@@ -965,6 +1221,12 @@ var JournalCollection = class extends SmrtCollection {
|
|
|
965
1221
|
}
|
|
966
1222
|
};
|
|
967
1223
|
//#endregion
|
|
1224
|
+
//#region src/collections/Ledgers.ts
|
|
1225
|
+
var Ledgers_exports = /* @__PURE__ */ __exportAll({ LedgerCollection: () => LedgerCollection });
|
|
1226
|
+
var LedgerCollection = class extends SmrtCollection {
|
|
1227
|
+
static _itemClass = Ledger;
|
|
1228
|
+
};
|
|
1229
|
+
//#endregion
|
|
968
1230
|
//#region src/migrations/ledger-accounts-table.ts
|
|
969
1231
|
var LEDGER_ACCOUNTS_TABLE = "ledger_accounts";
|
|
970
1232
|
var LEGACY_ACCOUNTS_TABLE = "accounts";
|
|
@@ -1171,6 +1433,104 @@ function targetType(declared) {
|
|
|
1171
1433
|
return type;
|
|
1172
1434
|
}
|
|
1173
1435
|
//#endregion
|
|
1436
|
+
//#region src/postings.ts
|
|
1437
|
+
function assertInput(input) {
|
|
1438
|
+
for (const value of [
|
|
1439
|
+
input.tenantId,
|
|
1440
|
+
input.ledgerId,
|
|
1441
|
+
input.idempotencyKey,
|
|
1442
|
+
input.sourceModule,
|
|
1443
|
+
input.sourceRef,
|
|
1444
|
+
input.currency,
|
|
1445
|
+
input.counterparty.kind,
|
|
1446
|
+
input.counterparty.id,
|
|
1447
|
+
input.debitAccountId,
|
|
1448
|
+
input.creditAccountId,
|
|
1449
|
+
...input.settlesSourceRef === void 0 ? [] : [input.settlesSourceRef]
|
|
1450
|
+
]) if (!value?.trim() || value !== value.trim()) throw new Error("Ledger posting identifiers must be nonempty trimmed strings");
|
|
1451
|
+
if (!Number.isSafeInteger(input.amountMinor) || input.amountMinor <= 0) throw new Error("Ledger posting amountMinor must be a positive safe integer");
|
|
1452
|
+
}
|
|
1453
|
+
async function postLedgerEntry(input) {
|
|
1454
|
+
input = {
|
|
1455
|
+
...input,
|
|
1456
|
+
counterparty: { ...input.counterparty },
|
|
1457
|
+
date: input.date ? new Date(input.date) : void 0,
|
|
1458
|
+
dueDate: input.dueDate ? new Date(input.dueDate) : void 0
|
|
1459
|
+
};
|
|
1460
|
+
assertInput(input);
|
|
1461
|
+
if (getTenantId() && getTenantId() !== input.tenantId) throw new Error("Ledger posting tenant differs from active context");
|
|
1462
|
+
const digest = digestRunOnceContent({
|
|
1463
|
+
ledgerId: input.ledgerId,
|
|
1464
|
+
sourceModule: input.sourceModule,
|
|
1465
|
+
sourceRef: input.sourceRef,
|
|
1466
|
+
description: input.description,
|
|
1467
|
+
date: input.date?.toISOString() ?? null,
|
|
1468
|
+
currency: input.currency,
|
|
1469
|
+
amountMinor: input.amountMinor,
|
|
1470
|
+
counterparty: input.counterparty,
|
|
1471
|
+
debitAccountId: input.debitAccountId,
|
|
1472
|
+
creditAccountId: input.creditAccountId,
|
|
1473
|
+
dueDate: input.dueDate?.toISOString() ?? null,
|
|
1474
|
+
settlesSourceRef: input.settlesSourceRef ?? null
|
|
1475
|
+
});
|
|
1476
|
+
const receipt = await withTenant({ tenantId: input.tenantId }, () => runOnce({
|
|
1477
|
+
db: input.db,
|
|
1478
|
+
tenantId: input.tenantId,
|
|
1479
|
+
actor: "smrt-ledgers.post:v1",
|
|
1480
|
+
token: input.idempotencyKey,
|
|
1481
|
+
content: { ledgerId: input.ledgerId }
|
|
1482
|
+
}, async (tx) => {
|
|
1483
|
+
const ledger = await (await LedgerCollection.create({ db: tx })).get({ id: input.ledgerId });
|
|
1484
|
+
if (!ledger || ledger.tenantId !== input.tenantId || ledger.balanceMode !== "exact-integer") throw new Error("Posting helpers require an owned exact-integer ledger");
|
|
1485
|
+
const journal2 = await (await JournalCollection.create({ db: tx })).createWithEntries({
|
|
1486
|
+
tenantId: input.tenantId,
|
|
1487
|
+
ledgerId: input.ledgerId,
|
|
1488
|
+
date: input.date ?? /* @__PURE__ */ new Date(),
|
|
1489
|
+
description: input.description,
|
|
1490
|
+
sourceModule: input.sourceModule,
|
|
1491
|
+
sourceRef: input.sourceRef,
|
|
1492
|
+
idempotencyKey: input.idempotencyKey,
|
|
1493
|
+
requestDigest: digest,
|
|
1494
|
+
metadata: {
|
|
1495
|
+
idempotencyKey: input.idempotencyKey,
|
|
1496
|
+
requestDigest: digest
|
|
1497
|
+
},
|
|
1498
|
+
entries: [{
|
|
1499
|
+
accountId: input.debitAccountId,
|
|
1500
|
+
debit: input.amountMinor,
|
|
1501
|
+
currency: input.currency,
|
|
1502
|
+
counterpartyKind: input.counterparty.kind,
|
|
1503
|
+
counterpartyId: input.counterparty.id,
|
|
1504
|
+
dueDate: input.dueDate,
|
|
1505
|
+
settlesSourceRef: input.settlesSourceRef
|
|
1506
|
+
}, {
|
|
1507
|
+
accountId: input.creditAccountId,
|
|
1508
|
+
credit: input.amountMinor,
|
|
1509
|
+
currency: input.currency,
|
|
1510
|
+
counterpartyKind: input.counterparty.kind,
|
|
1511
|
+
counterpartyId: input.counterparty.id,
|
|
1512
|
+
dueDate: input.dueDate,
|
|
1513
|
+
settlesSourceRef: input.settlesSourceRef
|
|
1514
|
+
}]
|
|
1515
|
+
});
|
|
1516
|
+
await journal2.post();
|
|
1517
|
+
return {
|
|
1518
|
+
journalId: journal2.id,
|
|
1519
|
+
requestDigest: digest
|
|
1520
|
+
};
|
|
1521
|
+
}));
|
|
1522
|
+
if (receipt.requestDigest !== digest) throw new Error("Ledger posting idempotency key was replayed with different content");
|
|
1523
|
+
const journal = await withTenant({ tenantId: input.tenantId }, async () => {
|
|
1524
|
+
return (await JournalCollection.create({ db: input.db })).get({ id: String(receipt.journalId) });
|
|
1525
|
+
});
|
|
1526
|
+
if (!journal?.isPosted()) throw new Error("Ledger posting receipt does not resolve to a posted journal");
|
|
1527
|
+
if (journal.requestDigest !== digest) throw new Error("Ledger posting idempotency key was replayed with different content");
|
|
1528
|
+
return journal;
|
|
1529
|
+
}
|
|
1530
|
+
var postReceivable = postLedgerEntry;
|
|
1531
|
+
var postPayable = postLedgerEntry;
|
|
1532
|
+
var postSettlement = postLedgerEntry;
|
|
1533
|
+
//#endregion
|
|
1174
1534
|
//#region src/recipes.ts
|
|
1175
1535
|
var BookkeepingRecipe = class extends SmrtRecipe {
|
|
1176
1536
|
static id = "ledgers.bookkeeping";
|
|
@@ -1214,17 +1574,20 @@ var BookkeepingRecipe = class extends SmrtRecipe {
|
|
|
1214
1574
|
Journal: { fields: {
|
|
1215
1575
|
sourceModule: { visibility: "hidden" },
|
|
1216
1576
|
sourceRef: { visibility: "hidden" },
|
|
1577
|
+
idempotencyKey: { visibility: "hidden" },
|
|
1578
|
+
requestDigest: { visibility: "hidden" },
|
|
1217
1579
|
voidedAt: { visibility: "hidden" },
|
|
1218
1580
|
voidReason: { visibility: "hidden" },
|
|
1219
1581
|
metadata: { visibility: "hidden" }
|
|
1220
1582
|
} },
|
|
1221
1583
|
JournalEntry: { fields: {
|
|
1222
1584
|
exchangeRate: { visibility: "hidden" },
|
|
1585
|
+
settlesSourceRef: { visibility: "hidden" },
|
|
1223
1586
|
metadata: { visibility: "hidden" }
|
|
1224
1587
|
} }
|
|
1225
1588
|
};
|
|
1226
1589
|
};
|
|
1227
1590
|
//#endregion
|
|
1228
|
-
export { Account, AccountCollection, BookkeepingRecipe, Journal, JournalCollection, JournalEntry, JournalEntryCollection, LEDGER_ACCOUNTS_TABLE, LEDGER_ACCOUNTS_TABLE_MOVE, LEGACY_ACCOUNTS_TABLE, LedgerAccountsTableMoveError, migrateLedgerAccountsTable,
|
|
1591
|
+
export { Account, AccountCollection, BookkeepingRecipe, Journal, JournalCollection, JournalEntry, JournalEntryCollection, LEDGER_ACCOUNTS_TABLE, LEDGER_ACCOUNTS_TABLE_MOVE, LEGACY_ACCOUNTS_TABLE, Ledger, LedgerAccountsTableMoveError, LedgerCollection, migrateLedgerAccountsTable, JournalEntries_exports as n, planLedgerAccountsTableMove, postLedgerEntry, postPayable, postReceivable, postSettlement, promptMessageOptions, Accounts_exports as r, smrtLedgersJournalSummarizePrompt, Ledgers_exports as t };
|
|
1229
1592
|
|
|
1230
1593
|
//# sourceMappingURL=index.js.map
|