@tailor-platform/erp-kit 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (290) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +10 -10
  3. package/dist/cli.mjs +407 -69
  4. package/package.json +1 -1
  5. package/skills/erp-kit-app-1-requirements/SKILL.md +33 -17
  6. package/skills/erp-kit-app-2-requirements-review/SKILL.md +12 -0
  7. package/skills/erp-kit-app-3-plan/SKILL.md +18 -4
  8. package/skills/erp-kit-app-3-plan/references/resolver-extraction.md +1 -1
  9. package/skills/erp-kit-app-3-plan/references/screen-extraction.md +1 -1
  10. package/skills/erp-kit-app-4-plan-review/SKILL.md +12 -0
  11. package/skills/erp-kit-app-5-impl-backend/SKILL.md +12 -0
  12. package/skills/erp-kit-app-6-impl-frontend/SKILL.md +12 -0
  13. package/skills/erp-kit-app-7-impl-review/SKILL.md +13 -1
  14. package/skills/erp-kit-app-shared/references/progress-protocol.md +77 -0
  15. package/skills/erp-kit-mock-scenario/SKILL.md +1 -1
  16. package/skills/erp-kit-module-1-requirements/SKILL.md +1 -1
  17. package/skills/erp-kit-module-3-plan/SKILL.md +3 -3
  18. package/skills/erp-kit-module-3-update-plan/SKILL.md +3 -3
  19. package/skills/erp-kit-module-5-impl/SKILL.md +1 -1
  20. package/src/commands/app/index.ts +2 -0
  21. package/src/commands/app/progress/git-context.ts +16 -0
  22. package/src/commands/app/progress/index.ts +45 -0
  23. package/src/commands/app/progress/log.ts +49 -0
  24. package/src/commands/app/progress/progress.test.ts +128 -0
  25. package/src/commands/app/progress/schema-cmd.ts +10 -0
  26. package/src/commands/check.test.ts +4 -4
  27. package/src/commands/lib/discovery.test.ts +5 -7
  28. package/src/commands/lib/discovery.ts +8 -8
  29. package/src/commands/lib/sync-check-source.test.ts +1 -1
  30. package/src/commands/lib/sync-check-source.ts +6 -1
  31. package/src/commands/lib/sync-check-tests.test.ts +43 -0
  32. package/src/commands/lib/sync-check-tests.ts +20 -2
  33. package/src/commands/sync-check.ts +3 -0
  34. package/src/generator/generate-app-code.test.ts +0 -6
  35. package/src/generator/generate-app-code.ts +3 -13
  36. package/src/generator/generate-code.test.ts +10 -40
  37. package/src/generator/generate-code.ts +6 -12
  38. package/src/generator/stub-templates.test.ts +0 -7
  39. package/src/generator/stub-templates.ts +0 -14
  40. package/src/modules/finance-ledger/README.md +50 -0
  41. package/src/modules/finance-ledger/command/.gitkeep +0 -0
  42. package/src/modules/finance-ledger/command/addJournalLine.generated.ts +6 -0
  43. package/src/modules/finance-ledger/command/addJournalLine.test.ts +438 -0
  44. package/src/modules/finance-ledger/command/addJournalLine.ts +122 -0
  45. package/src/modules/finance-ledger/command/approveAndLockPeriod.generated.ts +6 -0
  46. package/src/modules/finance-ledger/command/approveAndLockPeriod.test.ts +107 -0
  47. package/src/modules/finance-ledger/command/approveAndLockPeriod.ts +72 -0
  48. package/src/modules/finance-ledger/command/beginClose.generated.ts +6 -0
  49. package/src/modules/finance-ledger/command/beginClose.test.ts +106 -0
  50. package/src/modules/finance-ledger/command/beginClose.ts +58 -0
  51. package/src/modules/finance-ledger/command/closePeriod.generated.ts +6 -0
  52. package/src/modules/finance-ledger/command/closePeriod.test.ts +87 -0
  53. package/src/modules/finance-ledger/command/closePeriod.ts +44 -0
  54. package/src/modules/finance-ledger/command/createAccountingPeriod.generated.ts +6 -0
  55. package/src/modules/finance-ledger/command/createAccountingPeriod.test.ts +425 -0
  56. package/src/modules/finance-ledger/command/createAccountingPeriod.ts +133 -0
  57. package/src/modules/finance-ledger/command/createFiscalYear.generated.ts +6 -0
  58. package/src/modules/finance-ledger/command/createFiscalYear.test.ts +197 -0
  59. package/src/modules/finance-ledger/command/createFiscalYear.ts +70 -0
  60. package/src/modules/finance-ledger/command/createJournalEntry.generated.ts +6 -0
  61. package/src/modules/finance-ledger/command/createJournalEntry.test.ts +261 -0
  62. package/src/modules/finance-ledger/command/createJournalEntry.ts +121 -0
  63. package/src/modules/finance-ledger/command/deleteAccountingPeriod.generated.ts +6 -0
  64. package/src/modules/finance-ledger/command/deleteAccountingPeriod.test.ts +71 -0
  65. package/src/modules/finance-ledger/command/deleteAccountingPeriod.ts +55 -0
  66. package/src/modules/finance-ledger/command/deleteFiscalYear.generated.ts +6 -0
  67. package/src/modules/finance-ledger/command/deleteFiscalYear.test.ts +38 -0
  68. package/src/modules/finance-ledger/command/deleteFiscalYear.ts +34 -0
  69. package/src/modules/finance-ledger/command/deleteJournalEntry.generated.ts +6 -0
  70. package/src/modules/finance-ledger/command/deleteJournalEntry.test.ts +58 -0
  71. package/src/modules/finance-ledger/command/deleteJournalEntry.ts +43 -0
  72. package/src/modules/finance-ledger/command/executeYearEndClose.generated.ts +6 -0
  73. package/src/modules/finance-ledger/command/executeYearEndClose.test.ts +239 -0
  74. package/src/modules/finance-ledger/command/executeYearEndClose.ts +415 -0
  75. package/src/modules/finance-ledger/command/finalCloseAndLockPeriod.generated.ts +6 -0
  76. package/src/modules/finance-ledger/command/finalCloseAndLockPeriod.test.ts +102 -0
  77. package/src/modules/finance-ledger/command/finalCloseAndLockPeriod.ts +76 -0
  78. package/src/modules/finance-ledger/command/finalizeFinancialStatement.generated.ts +6 -0
  79. package/src/modules/finance-ledger/command/finalizeFinancialStatement.test.ts +73 -0
  80. package/src/modules/finance-ledger/command/finalizeFinancialStatement.ts +73 -0
  81. package/src/modules/finance-ledger/command/generateFinancialStatement.generated.ts +6 -0
  82. package/src/modules/finance-ledger/command/generateFinancialStatement.test.ts +311 -0
  83. package/src/modules/finance-ledger/command/generateFinancialStatement.ts +275 -0
  84. package/src/modules/finance-ledger/command/generatePreliminaryStatements.generated.ts +6 -0
  85. package/src/modules/finance-ledger/command/generatePreliminaryStatements.test.ts +152 -0
  86. package/src/modules/finance-ledger/command/generatePreliminaryStatements.ts +140 -0
  87. package/src/modules/finance-ledger/command/generateTrialBalance.generated.ts +6 -0
  88. package/src/modules/finance-ledger/command/generateTrialBalance.test.ts +439 -0
  89. package/src/modules/finance-ledger/command/generateTrialBalance.ts +268 -0
  90. package/src/modules/finance-ledger/command/initiatePeriodClose.generated.ts +6 -0
  91. package/src/modules/finance-ledger/command/initiatePeriodClose.test.ts +153 -0
  92. package/src/modules/finance-ledger/command/initiatePeriodClose.ts +84 -0
  93. package/src/modules/finance-ledger/command/openForAdvanceEntry.generated.ts +6 -0
  94. package/src/modules/finance-ledger/command/openForAdvanceEntry.test.ts +87 -0
  95. package/src/modules/finance-ledger/command/openForAdvanceEntry.ts +44 -0
  96. package/src/modules/finance-ledger/command/openPeriod.generated.ts +6 -0
  97. package/src/modules/finance-ledger/command/openPeriod.test.ts +90 -0
  98. package/src/modules/finance-ledger/command/openPeriod.ts +44 -0
  99. package/src/modules/finance-ledger/command/permanentlyClosePeriod.generated.ts +6 -0
  100. package/src/modules/finance-ledger/command/permanentlyClosePeriod.test.ts +87 -0
  101. package/src/modules/finance-ledger/command/permanentlyClosePeriod.ts +48 -0
  102. package/src/modules/finance-ledger/command/postAdjustingEntries.generated.ts +6 -0
  103. package/src/modules/finance-ledger/command/postAdjustingEntries.test.ts +392 -0
  104. package/src/modules/finance-ledger/command/postAdjustingEntries.ts +156 -0
  105. package/src/modules/finance-ledger/command/postJournalEntry.generated.ts +6 -0
  106. package/src/modules/finance-ledger/command/postJournalEntry.test.ts +346 -0
  107. package/src/modules/finance-ledger/command/postJournalEntry.ts +160 -0
  108. package/src/modules/finance-ledger/command/processInventoryHandoff.generated.ts +6 -0
  109. package/src/modules/finance-ledger/command/processInventoryHandoff.test.ts +211 -0
  110. package/src/modules/finance-ledger/command/processInventoryHandoff.ts +133 -0
  111. package/src/modules/finance-ledger/command/processManufacturingHandoff.generated.ts +6 -0
  112. package/src/modules/finance-ledger/command/processManufacturingHandoff.test.ts +221 -0
  113. package/src/modules/finance-ledger/command/processManufacturingHandoff.ts +133 -0
  114. package/src/modules/finance-ledger/command/processPurchaseHandoff.generated.ts +6 -0
  115. package/src/modules/finance-ledger/command/processPurchaseHandoff.test.ts +222 -0
  116. package/src/modules/finance-ledger/command/processPurchaseHandoff.ts +133 -0
  117. package/src/modules/finance-ledger/command/processSalesHandoff.generated.ts +6 -0
  118. package/src/modules/finance-ledger/command/processSalesHandoff.test.ts +257 -0
  119. package/src/modules/finance-ledger/command/processSalesHandoff.ts +135 -0
  120. package/src/modules/finance-ledger/command/regenerateFinancialStatement.generated.ts +6 -0
  121. package/src/modules/finance-ledger/command/regenerateFinancialStatement.test.ts +129 -0
  122. package/src/modules/finance-ledger/command/regenerateFinancialStatement.ts +186 -0
  123. package/src/modules/finance-ledger/command/removeJournalLine.generated.ts +6 -0
  124. package/src/modules/finance-ledger/command/removeJournalLine.test.ts +65 -0
  125. package/src/modules/finance-ledger/command/removeJournalLine.ts +39 -0
  126. package/src/modules/finance-ledger/command/reopenPeriod.generated.ts +6 -0
  127. package/src/modules/finance-ledger/command/reopenPeriod.test.ts +87 -0
  128. package/src/modules/finance-ledger/command/reopenPeriod.ts +44 -0
  129. package/src/modules/finance-ledger/command/reverseJournalEntry.generated.ts +6 -0
  130. package/src/modules/finance-ledger/command/reverseJournalEntry.test.ts +337 -0
  131. package/src/modules/finance-ledger/command/reverseJournalEntry.ts +140 -0
  132. package/src/modules/finance-ledger/command/revertSoftLock.generated.ts +6 -0
  133. package/src/modules/finance-ledger/command/revertSoftLock.test.ts +96 -0
  134. package/src/modules/finance-ledger/command/revertSoftLock.ts +67 -0
  135. package/src/modules/finance-ledger/command/updateFiscalYear.generated.ts +6 -0
  136. package/src/modules/finance-ledger/command/updateFiscalYear.test.ts +138 -0
  137. package/src/modules/finance-ledger/command/updateFiscalYear.ts +85 -0
  138. package/src/modules/finance-ledger/command/updateJournalEntry.generated.ts +6 -0
  139. package/src/modules/finance-ledger/command/updateJournalEntry.test.ts +195 -0
  140. package/src/modules/finance-ledger/command/updateJournalEntry.ts +86 -0
  141. package/src/modules/finance-ledger/command/updateJournalLine.generated.ts +6 -0
  142. package/src/modules/finance-ledger/command/updateJournalLine.test.ts +385 -0
  143. package/src/modules/finance-ledger/command/updateJournalLine.ts +155 -0
  144. package/src/modules/finance-ledger/command/verifySubledgerTransfers.generated.ts +6 -0
  145. package/src/modules/finance-ledger/command/verifySubledgerTransfers.test.ts +201 -0
  146. package/src/modules/finance-ledger/command/verifySubledgerTransfers.ts +113 -0
  147. package/src/modules/finance-ledger/command/verifyTrialBalance.generated.ts +6 -0
  148. package/src/modules/finance-ledger/command/verifyTrialBalance.test.ts +136 -0
  149. package/src/modules/finance-ledger/command/verifyTrialBalance.ts +97 -0
  150. package/src/modules/finance-ledger/db/.gitkeep +0 -0
  151. package/src/modules/finance-ledger/db/accountingPeriod.ts +58 -0
  152. package/src/modules/finance-ledger/db/financialStatement.ts +92 -0
  153. package/src/modules/finance-ledger/db/financialStatementLineItem.ts +76 -0
  154. package/src/modules/finance-ledger/db/fiscalYear.ts +41 -0
  155. package/src/modules/finance-ledger/db/journalEntry.ts +101 -0
  156. package/src/modules/finance-ledger/db/journalLine.ts +64 -0
  157. package/src/modules/finance-ledger/db/periodClose.ts +97 -0
  158. package/src/modules/finance-ledger/db/trialBalance.ts +63 -0
  159. package/src/modules/finance-ledger/db/trialBalanceLine.ts +63 -0
  160. package/src/modules/finance-ledger/docs/commands/AddJournalLine.md +74 -0
  161. package/src/modules/finance-ledger/docs/commands/ApproveAndLockPeriod.md +53 -0
  162. package/src/modules/finance-ledger/docs/commands/BeginClose.md +47 -0
  163. package/src/modules/finance-ledger/docs/commands/ClosePeriod.md +45 -0
  164. package/src/modules/finance-ledger/docs/commands/CreateAccountingPeriod.md +69 -0
  165. package/src/modules/finance-ledger/docs/commands/CreateFiscalYear.md +56 -0
  166. package/src/modules/finance-ledger/docs/commands/CreateJournalEntry.md +63 -0
  167. package/src/modules/finance-ledger/docs/commands/DeleteAccountingPeriod.md +46 -0
  168. package/src/modules/finance-ledger/docs/commands/DeleteFiscalYear.md +40 -0
  169. package/src/modules/finance-ledger/docs/commands/DeleteJournalEntry.md +44 -0
  170. package/src/modules/finance-ledger/docs/commands/ExecuteYearEndClose.md +81 -0
  171. package/src/modules/finance-ledger/docs/commands/FinalCloseAndLockPeriod.md +49 -0
  172. package/src/modules/finance-ledger/docs/commands/FinalizeFinancialStatement.md +43 -0
  173. package/src/modules/finance-ledger/docs/commands/GenerateFinancialStatement.md +86 -0
  174. package/src/modules/finance-ledger/docs/commands/GeneratePreliminaryStatements.md +53 -0
  175. package/src/modules/finance-ledger/docs/commands/GenerateTrialBalance.md +75 -0
  176. package/src/modules/finance-ledger/docs/commands/InitiatePeriodClose.md +58 -0
  177. package/src/modules/finance-ledger/docs/commands/OpenForAdvanceEntry.md +44 -0
  178. package/src/modules/finance-ledger/docs/commands/OpenPeriod.md +45 -0
  179. package/src/modules/finance-ledger/docs/commands/PermanentlyClosePeriod.md +45 -0
  180. package/src/modules/finance-ledger/docs/commands/PostAdjustingEntries.md +61 -0
  181. package/src/modules/finance-ledger/docs/commands/PostJournalEntry.md +81 -0
  182. package/src/modules/finance-ledger/docs/commands/ProcessInventoryHandoff.md +72 -0
  183. package/src/modules/finance-ledger/docs/commands/ProcessManufacturingHandoff.md +68 -0
  184. package/src/modules/finance-ledger/docs/commands/ProcessPurchaseHandoff.md +68 -0
  185. package/src/modules/finance-ledger/docs/commands/ProcessSalesHandoff.md +71 -0
  186. package/src/modules/finance-ledger/docs/commands/RegenerateFinancialStatement.md +60 -0
  187. package/src/modules/finance-ledger/docs/commands/RemoveJournalLine.md +42 -0
  188. package/src/modules/finance-ledger/docs/commands/ReopenPeriod.md +45 -0
  189. package/src/modules/finance-ledger/docs/commands/ReverseJournalEntry.md +62 -0
  190. package/src/modules/finance-ledger/docs/commands/RevertSoftLock.md +49 -0
  191. package/src/modules/finance-ledger/docs/commands/UpdateFiscalYear.md +60 -0
  192. package/src/modules/finance-ledger/docs/commands/UpdateJournalEntry.md +50 -0
  193. package/src/modules/finance-ledger/docs/commands/UpdateJournalLine.md +61 -0
  194. package/src/modules/finance-ledger/docs/commands/VerifySubledgerTransfers.md +59 -0
  195. package/src/modules/finance-ledger/docs/commands/VerifyTrialBalance.md +53 -0
  196. package/src/modules/finance-ledger/docs/features/accounting-period-management.md +110 -0
  197. package/src/modules/finance-ledger/docs/features/financial-statement-generation.md +115 -0
  198. package/src/modules/finance-ledger/docs/features/journal-entry-management.md +138 -0
  199. package/src/modules/finance-ledger/docs/features/period-end-close.md +102 -0
  200. package/src/modules/finance-ledger/docs/features/subledger-integration.md +141 -0
  201. package/src/modules/finance-ledger/docs/features/trial-balance.md +99 -0
  202. package/src/modules/finance-ledger/docs/features/year-end-close.md +84 -0
  203. package/src/modules/finance-ledger/docs/models/AccountingPeriod.md +71 -0
  204. package/src/modules/finance-ledger/docs/models/FinancialStatement.md +76 -0
  205. package/src/modules/finance-ledger/docs/models/FinancialStatementLineItem.md +41 -0
  206. package/src/modules/finance-ledger/docs/models/FiscalYear.md +41 -0
  207. package/src/modules/finance-ledger/docs/models/JournalEntry.md +80 -0
  208. package/src/modules/finance-ledger/docs/models/JournalLine.md +47 -0
  209. package/src/modules/finance-ledger/docs/models/PeriodClose.md +83 -0
  210. package/src/modules/finance-ledger/docs/models/TrialBalance.md +56 -0
  211. package/src/modules/finance-ledger/docs/models/TrialBalanceLine.md +37 -0
  212. package/src/modules/finance-ledger/docs/queries/GetAccountingPeriod.md +35 -0
  213. package/src/modules/finance-ledger/docs/queries/GetFinancialStatement.md +38 -0
  214. package/src/modules/finance-ledger/docs/queries/GetFiscalYear.md +35 -0
  215. package/src/modules/finance-ledger/docs/queries/GetJournalEntry.md +37 -0
  216. package/src/modules/finance-ledger/docs/queries/GetPeriodByDate.md +38 -0
  217. package/src/modules/finance-ledger/docs/queries/GetPeriodClose.md +36 -0
  218. package/src/modules/finance-ledger/docs/queries/GetSubledgerTransferStatus.md +45 -0
  219. package/src/modules/finance-ledger/docs/queries/GetTrialBalance.md +38 -0
  220. package/src/modules/finance-ledger/docs/queries/ListAccountingPeriods.md +46 -0
  221. package/src/modules/finance-ledger/docs/queries/ListFinancialStatements.md +46 -0
  222. package/src/modules/finance-ledger/docs/queries/ListFiscalYears.md +42 -0
  223. package/src/modules/finance-ledger/docs/queries/ListJournalEntries.md +48 -0
  224. package/src/modules/finance-ledger/docs/queries/ListPeriodCloses.md +46 -0
  225. package/src/modules/finance-ledger/docs/queries/ListTrialBalances.md +51 -0
  226. package/src/modules/finance-ledger/executor/.gitkeep +0 -0
  227. package/src/modules/finance-ledger/generated/enums.ts +109 -0
  228. package/src/modules/finance-ledger/generated/kysely-tailordb.ts +202 -0
  229. package/src/modules/finance-ledger/index.ts +2 -0
  230. package/src/modules/finance-ledger/lib/_db_deps.ts +56 -0
  231. package/src/modules/finance-ledger/lib/errors.generated.ts +332 -0
  232. package/src/modules/finance-ledger/lib/permissions.generated.ts +41 -0
  233. package/src/modules/finance-ledger/lib/types.ts +66 -0
  234. package/src/modules/finance-ledger/module.ts +262 -0
  235. package/src/modules/finance-ledger/package.json +26 -0
  236. package/src/modules/finance-ledger/permissions.ts +3 -0
  237. package/src/modules/finance-ledger/query/.gitkeep +0 -0
  238. package/src/modules/finance-ledger/query/getAccountingPeriod.generated.ts +5 -0
  239. package/src/modules/finance-ledger/query/getAccountingPeriod.test.ts +31 -0
  240. package/src/modules/finance-ledger/query/getAccountingPeriod.ts +21 -0
  241. package/src/modules/finance-ledger/query/getFinancialStatement.generated.ts +5 -0
  242. package/src/modules/finance-ledger/query/getFinancialStatement.test.ts +35 -0
  243. package/src/modules/finance-ledger/query/getFinancialStatement.ts +29 -0
  244. package/src/modules/finance-ledger/query/getFiscalYear.generated.ts +5 -0
  245. package/src/modules/finance-ledger/query/getFiscalYear.test.ts +31 -0
  246. package/src/modules/finance-ledger/query/getFiscalYear.ts +21 -0
  247. package/src/modules/finance-ledger/query/getJournalEntry.generated.ts +5 -0
  248. package/src/modules/finance-ledger/query/getJournalEntry.test.ts +35 -0
  249. package/src/modules/finance-ledger/query/getJournalEntry.ts +29 -0
  250. package/src/modules/finance-ledger/query/getPeriodByDate.generated.ts +5 -0
  251. package/src/modules/finance-ledger/query/getPeriodByDate.test.ts +53 -0
  252. package/src/modules/finance-ledger/query/getPeriodByDate.ts +27 -0
  253. package/src/modules/finance-ledger/query/getPeriodClose.generated.ts +5 -0
  254. package/src/modules/finance-ledger/query/getPeriodClose.test.ts +31 -0
  255. package/src/modules/finance-ledger/query/getPeriodClose.ts +21 -0
  256. package/src/modules/finance-ledger/query/getSubledgerTransferStatus.generated.ts +5 -0
  257. package/src/modules/finance-ledger/query/getSubledgerTransferStatus.test.ts +101 -0
  258. package/src/modules/finance-ledger/query/getSubledgerTransferStatus.ts +68 -0
  259. package/src/modules/finance-ledger/query/getTrialBalance.generated.ts +5 -0
  260. package/src/modules/finance-ledger/query/getTrialBalance.test.ts +33 -0
  261. package/src/modules/finance-ledger/query/getTrialBalance.ts +30 -0
  262. package/src/modules/finance-ledger/query/listAccountingPeriods.generated.ts +5 -0
  263. package/src/modules/finance-ledger/query/listAccountingPeriods.test.ts +81 -0
  264. package/src/modules/finance-ledger/query/listAccountingPeriods.ts +61 -0
  265. package/src/modules/finance-ledger/query/listFinancialStatements.generated.ts +5 -0
  266. package/src/modules/finance-ledger/query/listFinancialStatements.test.ts +76 -0
  267. package/src/modules/finance-ledger/query/listFinancialStatements.ts +62 -0
  268. package/src/modules/finance-ledger/query/listFiscalYears.generated.ts +5 -0
  269. package/src/modules/finance-ledger/query/listFiscalYears.test.ts +63 -0
  270. package/src/modules/finance-ledger/query/listFiscalYears.ts +45 -0
  271. package/src/modules/finance-ledger/query/listJournalEntries.generated.ts +5 -0
  272. package/src/modules/finance-ledger/query/listJournalEntries.test.ts +91 -0
  273. package/src/modules/finance-ledger/query/listJournalEntries.ts +64 -0
  274. package/src/modules/finance-ledger/query/listPeriodCloses.generated.ts +5 -0
  275. package/src/modules/finance-ledger/query/listPeriodCloses.test.ts +63 -0
  276. package/src/modules/finance-ledger/query/listPeriodCloses.ts +64 -0
  277. package/src/modules/finance-ledger/query/listTrialBalances.generated.ts +5 -0
  278. package/src/modules/finance-ledger/query/listTrialBalances.test.ts +78 -0
  279. package/src/modules/finance-ledger/query/listTrialBalances.ts +56 -0
  280. package/src/modules/finance-ledger/seed/index.ts +19 -0
  281. package/src/modules/finance-ledger/tailor.config.ts +13 -0
  282. package/src/modules/finance-ledger/tailor.d.ts +13 -0
  283. package/src/modules/finance-ledger/testing/commandTestUtils.ts +35 -0
  284. package/src/modules/finance-ledger/testing/fixtures.ts +382 -0
  285. package/src/modules/finance-ledger/tsconfig.json +16 -0
  286. package/src/progress/schema.test.ts +161 -0
  287. package/src/progress/schema.ts +316 -0
  288. package/templates/scaffold/app/backend/package.json +1 -3
  289. package/templates/scaffold/app/backend/vitest.config.ts +4 -21
  290. package/src/generator/generate-stubs.ts +0 -35
@@ -0,0 +1,346 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { createMockDb } from "../../../testing/index";
3
+ import type { Transaction } from "../generated/kysely-tailordb";
4
+ import {
5
+ JournalEntryNotFoundError,
6
+ InvalidStatusForPostingError,
7
+ MinimumLinesNotMetError,
8
+ UnbalancedEntryError,
9
+ InvalidPeriodStatusError,
10
+ InactiveAccountError,
11
+ SuccessorAccountInvalidError,
12
+ } from "../lib/errors.generated";
13
+ import {
14
+ baseJournalEntry,
15
+ postedJournalEntry,
16
+ reversedJournalEntry,
17
+ baseJournalLine,
18
+ baseJournalLine2,
19
+ baseAccountingPeriod,
20
+ futureEnterablePeriod,
21
+ neverOpenedPeriod,
22
+ closedPeriod,
23
+ permanentlyClosedPeriod,
24
+ baseAccount,
25
+ baseAccount2,
26
+ inactiveAccount,
27
+ deprecatedAccount,
28
+ } from "../testing/fixtures";
29
+ import { commandCtx, expectErr, expectOk } from "../testing/commandTestUtils";
30
+ import { run } from "./postJournalEntry";
31
+
32
+ describe("postJournalEntry", () => {
33
+ it("returns error when journal entry does not exist", async () => {
34
+ const { db, spies } = createMockDb<Transaction>();
35
+ spies.select.mockReturnValueOnce(undefined); // journal entry lookup
36
+
37
+ const result = await run(db, { id: "nonexistent" }, commandCtx);
38
+
39
+ expectErr(result, JournalEntryNotFoundError);
40
+ });
41
+
42
+ it("returns error when journal entry is already POSTED", async () => {
43
+ const { db, spies } = createMockDb<Transaction>();
44
+ spies.select.mockReturnValueOnce(postedJournalEntry);
45
+
46
+ const result = await run(db, { id: postedJournalEntry.id }, commandCtx);
47
+
48
+ expectErr(result, InvalidStatusForPostingError);
49
+ });
50
+
51
+ it("returns error when journal entry is REVERSED", async () => {
52
+ const { db, spies } = createMockDb<Transaction>();
53
+ spies.select.mockReturnValueOnce(reversedJournalEntry);
54
+
55
+ const result = await run(db, { id: reversedJournalEntry.id }, commandCtx);
56
+
57
+ expectErr(result, InvalidStatusForPostingError);
58
+ });
59
+
60
+ it("returns error when entry has fewer than two journal lines", async () => {
61
+ const { db, spies } = createMockDb<Transaction>();
62
+ spies.select
63
+ .mockReturnValueOnce(baseJournalEntry) // journal entry lookup
64
+ .mockReturnValueOnce(undefined); // lines query returns via execute()
65
+ // execute() for lines returns an array with only one line
66
+ spies.select.mockReset();
67
+ spies.select
68
+ .mockReturnValueOnce(baseJournalEntry)
69
+ .mockImplementationOnce(() => [baseJournalLine]); // journal lines
70
+
71
+ const result = await run(db, { id: baseJournalEntry.id }, commandCtx);
72
+
73
+ expectErr(result, MinimumLinesNotMetError);
74
+ });
75
+
76
+ it("returns error when entry has only one line (debit only or credit only)", async () => {
77
+ const { db, spies } = createMockDb<Transaction>();
78
+ const singleLine = { ...baseJournalLine };
79
+ spies.select
80
+ .mockReturnValueOnce(baseJournalEntry) // journal entry lookup
81
+ .mockImplementationOnce(() => [singleLine]); // only one journal line
82
+
83
+ const result = await run(db, { id: baseJournalEntry.id }, commandCtx);
84
+
85
+ expectErr(result, MinimumLinesNotMetError);
86
+ });
87
+
88
+ it("returns error when total debits do not equal total credits in functional currency", async () => {
89
+ const { db, spies } = createMockDb<Transaction>();
90
+ const unbalancedCreditLine = {
91
+ ...baseJournalLine2,
92
+ functionalCreditAmount: 500, // doesn't match debit of 1000
93
+ };
94
+ spies.select
95
+ .mockReturnValueOnce(baseJournalEntry) // journal entry lookup
96
+ .mockImplementationOnce(() => [baseJournalLine, unbalancedCreditLine]) // journal lines
97
+ .mockReturnValueOnce(baseAccountingPeriod); // period lookup
98
+
99
+ const result = await run(db, { id: baseJournalEntry.id }, commandCtx);
100
+
101
+ expectErr(result, UnbalancedEntryError);
102
+ });
103
+
104
+ it("returns error when target period is in NEVER_OPENED status", async () => {
105
+ const { db, spies } = createMockDb<Transaction>();
106
+ const entryInNeverOpened = {
107
+ ...baseJournalEntry,
108
+ accountingPeriodId: neverOpenedPeriod.id,
109
+ };
110
+ spies.select
111
+ .mockReturnValueOnce(entryInNeverOpened) // journal entry lookup
112
+ .mockImplementationOnce(() => [baseJournalLine, baseJournalLine2]) // journal lines
113
+ .mockReturnValueOnce(neverOpenedPeriod); // period lookup
114
+
115
+ const result = await run(db, { id: entryInNeverOpened.id }, commandCtx);
116
+
117
+ expectErr(result, InvalidPeriodStatusError);
118
+ });
119
+
120
+ it("returns error when target period is in CLOSED status", async () => {
121
+ const { db, spies } = createMockDb<Transaction>();
122
+ const entryInClosed = {
123
+ ...baseJournalEntry,
124
+ accountingPeriodId: closedPeriod.id,
125
+ };
126
+ spies.select
127
+ .mockReturnValueOnce(entryInClosed) // journal entry lookup
128
+ .mockImplementationOnce(() => [baseJournalLine, baseJournalLine2]) // journal lines
129
+ .mockReturnValueOnce(closedPeriod); // period lookup
130
+
131
+ const result = await run(db, { id: entryInClosed.id }, commandCtx);
132
+
133
+ expectErr(result, InvalidPeriodStatusError);
134
+ });
135
+
136
+ it("returns error when target period is in PERMANENTLY_CLOSED status", async () => {
137
+ const { db, spies } = createMockDb<Transaction>();
138
+ const entryInPermClosed = {
139
+ ...baseJournalEntry,
140
+ accountingPeriodId: permanentlyClosedPeriod.id,
141
+ };
142
+ spies.select
143
+ .mockReturnValueOnce(entryInPermClosed) // journal entry lookup
144
+ .mockImplementationOnce(() => [baseJournalLine, baseJournalLine2]) // journal lines
145
+ .mockReturnValueOnce(permanentlyClosedPeriod); // period lookup
146
+
147
+ const result = await run(db, { id: entryInPermClosed.id }, commandCtx);
148
+
149
+ expectErr(result, InvalidPeriodStatusError);
150
+ });
151
+
152
+ it("returns error when a GL account is inactive", async () => {
153
+ const { db, spies } = createMockDb<Transaction>();
154
+ const lineWithInactiveAccount = {
155
+ ...baseJournalLine,
156
+ accountId: inactiveAccount.id,
157
+ };
158
+ spies.select
159
+ .mockReturnValueOnce(baseJournalEntry) // journal entry lookup
160
+ .mockImplementationOnce(() => [lineWithInactiveAccount, baseJournalLine2]) // journal lines
161
+ .mockReturnValueOnce(baseAccountingPeriod) // period lookup
162
+ .mockReturnValueOnce(inactiveAccount) // account lookup for inactive account
163
+ .mockReturnValueOnce(baseAccount2); // account lookup for active account
164
+
165
+ const result = await run(db, { id: baseJournalEntry.id }, commandCtx);
166
+
167
+ expectErr(result, InactiveAccountError);
168
+ });
169
+
170
+ it("returns error when a GL account is in draft status", async () => {
171
+ const { db, spies } = createMockDb<Transaction>();
172
+ const draftAccount = { ...baseAccount, id: "account-draft", status: "DRAFT" };
173
+ const lineWithDraftAccount = {
174
+ ...baseJournalLine,
175
+ accountId: draftAccount.id,
176
+ };
177
+ spies.select
178
+ .mockReturnValueOnce(baseJournalEntry) // journal entry lookup
179
+ .mockImplementationOnce(() => [lineWithDraftAccount, baseJournalLine2]) // journal lines
180
+ .mockReturnValueOnce(baseAccountingPeriod) // period lookup
181
+ .mockReturnValueOnce(draftAccount) // account lookup for draft account
182
+ .mockReturnValueOnce(baseAccount2); // account lookup for active account
183
+
184
+ const result = await run(db, { id: baseJournalEntry.id }, commandCtx);
185
+
186
+ expectErr(result, InactiveAccountError);
187
+ });
188
+
189
+ it("returns error when successor account is itself inactive without further successor", async () => {
190
+ const { db, spies } = createMockDb<Transaction>();
191
+ const deprecatedWithInactiveSuccessor = {
192
+ ...deprecatedAccount,
193
+ successorAccountId: inactiveAccount.id,
194
+ };
195
+ const inactiveSuccessor = { ...inactiveAccount, successorAccountId: null };
196
+ const lineWithDeprecatedAccount = {
197
+ ...baseJournalLine,
198
+ accountId: deprecatedWithInactiveSuccessor.id,
199
+ };
200
+ spies.select
201
+ .mockReturnValueOnce(baseJournalEntry) // journal entry lookup
202
+ .mockImplementationOnce(() => [lineWithDeprecatedAccount, baseJournalLine2]) // journal lines
203
+ .mockReturnValueOnce(baseAccountingPeriod) // period lookup
204
+ .mockReturnValueOnce(deprecatedWithInactiveSuccessor) // deprecated account lookup
205
+ .mockReturnValueOnce(inactiveSuccessor) // successor account lookup (inactive)
206
+ .mockReturnValueOnce(baseAccount2); // second line account lookup
207
+
208
+ const result = await run(db, { id: baseJournalEntry.id }, commandCtx);
209
+
210
+ expectErr(result, SuccessorAccountInvalidError);
211
+ });
212
+
213
+ it("posts balanced DRAFT entry to OPEN period", async () => {
214
+ const { db, spies } = createMockDb<Transaction>();
215
+ const postedEntry = { ...baseJournalEntry, status: "POSTED", postedAt: new Date() };
216
+ spies.select
217
+ .mockReturnValueOnce(baseJournalEntry) // journal entry lookup
218
+ .mockImplementationOnce(() => [baseJournalLine, baseJournalLine2]) // journal lines
219
+ .mockReturnValueOnce(baseAccountingPeriod) // period lookup (OPEN)
220
+ .mockReturnValueOnce(baseAccount) // account lookup for line 1
221
+ .mockReturnValueOnce(baseAccount2); // account lookup for line 2
222
+ spies.update.mockReturnValueOnce(postedEntry);
223
+
224
+ const result = await run(db, { id: baseJournalEntry.id }, commandCtx);
225
+
226
+ const value = expectOk(result);
227
+ expect(value.journalEntry.status).toBe("POSTED");
228
+ });
229
+
230
+ it("posts balanced DRAFT entry to FUTURE_ENTERABLE period", async () => {
231
+ const { db, spies } = createMockDb<Transaction>();
232
+ const entryInFuture = {
233
+ ...baseJournalEntry,
234
+ accountingPeriodId: futureEnterablePeriod.id,
235
+ };
236
+ const postedEntry = { ...entryInFuture, status: "POSTED", postedAt: new Date() };
237
+ spies.select
238
+ .mockReturnValueOnce(entryInFuture) // journal entry lookup
239
+ .mockImplementationOnce(() => [baseJournalLine, baseJournalLine2]) // journal lines
240
+ .mockReturnValueOnce(futureEnterablePeriod) // period lookup (FUTURE_ENTERABLE)
241
+ .mockReturnValueOnce(baseAccount) // account lookup for line 1
242
+ .mockReturnValueOnce(baseAccount2); // account lookup for line 2
243
+ spies.update.mockReturnValueOnce(postedEntry);
244
+
245
+ const result = await run(db, { id: entryInFuture.id }, commandCtx);
246
+
247
+ const value = expectOk(result);
248
+ expect(value.journalEntry.status).toBe("POSTED");
249
+ });
250
+
251
+ it("redirects deprecated GL account to successor account at posting time", async () => {
252
+ const { db, spies } = createMockDb<Transaction>();
253
+ const lineWithDeprecatedAccount = {
254
+ ...baseJournalLine,
255
+ accountId: deprecatedAccount.id,
256
+ };
257
+ const postedEntry = { ...baseJournalEntry, status: "POSTED", postedAt: new Date() };
258
+ const updatedLine = { ...lineWithDeprecatedAccount, accountId: baseAccount.id };
259
+ spies.select
260
+ .mockReturnValueOnce(baseJournalEntry) // journal entry lookup
261
+ .mockImplementationOnce(() => [lineWithDeprecatedAccount, baseJournalLine2]) // journal lines
262
+ .mockReturnValueOnce(baseAccountingPeriod) // period lookup
263
+ .mockReturnValueOnce(deprecatedAccount) // deprecated account lookup
264
+ .mockReturnValueOnce(baseAccount) // successor account lookup (ACTIVE)
265
+ .mockReturnValueOnce(baseAccount2); // second line account lookup
266
+ spies.update
267
+ .mockReturnValueOnce(updatedLine) // journal line update (redirect)
268
+ .mockReturnValueOnce(postedEntry); // journal entry update
269
+
270
+ const result = await run(db, { id: baseJournalEntry.id }, commandCtx);
271
+
272
+ const value = expectOk(result);
273
+ expect(value.journalEntry.status).toBe("POSTED");
274
+ expect(value.auditTrail).toBeDefined();
275
+ expect(value.auditTrail.length).toBeGreaterThan(0);
276
+ expect(value.auditTrail[0].type).toBe("SUCCESSOR_REDIRECT");
277
+ });
278
+
279
+ it("records successor account redirect in audit trail", async () => {
280
+ const { db, spies } = createMockDb<Transaction>();
281
+ const lineWithDeprecatedAccount = {
282
+ ...baseJournalLine,
283
+ accountId: deprecatedAccount.id,
284
+ };
285
+ const postedEntry = { ...baseJournalEntry, status: "POSTED", postedAt: new Date() };
286
+ const updatedLine = { ...lineWithDeprecatedAccount, accountId: baseAccount.id };
287
+ spies.select
288
+ .mockReturnValueOnce(baseJournalEntry) // journal entry lookup
289
+ .mockImplementationOnce(() => [lineWithDeprecatedAccount, baseJournalLine2]) // journal lines
290
+ .mockReturnValueOnce(baseAccountingPeriod) // period lookup
291
+ .mockReturnValueOnce(deprecatedAccount) // deprecated account lookup
292
+ .mockReturnValueOnce(baseAccount) // successor account lookup (ACTIVE)
293
+ .mockReturnValueOnce(baseAccount2); // second line account lookup
294
+ spies.update
295
+ .mockReturnValueOnce(updatedLine) // journal line update (redirect)
296
+ .mockReturnValueOnce(postedEntry); // journal entry update
297
+
298
+ const result = await run(db, { id: baseJournalEntry.id }, commandCtx);
299
+
300
+ const value = expectOk(result);
301
+ expect(value.auditTrail).toContainEqual(
302
+ expect.objectContaining({
303
+ type: "SUCCESSOR_REDIRECT",
304
+ originalAccountId: deprecatedAccount.id,
305
+ successorAccountId: baseAccount.id,
306
+ }),
307
+ );
308
+ });
309
+
310
+ it("entry becomes immutable after posting", async () => {
311
+ const { db, spies } = createMockDb<Transaction>();
312
+ const postedEntry = { ...baseJournalEntry, status: "POSTED", postedAt: new Date() };
313
+ spies.select
314
+ .mockReturnValueOnce(baseJournalEntry) // journal entry lookup
315
+ .mockImplementationOnce(() => [baseJournalLine, baseJournalLine2]) // journal lines
316
+ .mockReturnValueOnce(baseAccountingPeriod) // period lookup
317
+ .mockReturnValueOnce(baseAccount) // account lookup for line 1
318
+ .mockReturnValueOnce(baseAccount2); // account lookup for line 2
319
+ spies.update.mockReturnValueOnce(postedEntry);
320
+
321
+ const result = await run(db, { id: baseJournalEntry.id }, commandCtx);
322
+
323
+ const value = expectOk(result);
324
+ expect(value.journalEntry.status).toBe("POSTED");
325
+ expect(value.journalEntry.postedAt).toBeDefined();
326
+ });
327
+
328
+ it("emits audit event recording status transition from DRAFT to POSTED and posting user", async () => {
329
+ const { db, spies } = createMockDb<Transaction>();
330
+ const postedEntry = { ...baseJournalEntry, status: "POSTED", postedAt: new Date() };
331
+ spies.select
332
+ .mockReturnValueOnce(baseJournalEntry) // journal entry lookup
333
+ .mockImplementationOnce(() => [baseJournalLine, baseJournalLine2]) // journal lines
334
+ .mockReturnValueOnce(baseAccountingPeriod) // period lookup
335
+ .mockReturnValueOnce(baseAccount) // account lookup for line 1
336
+ .mockReturnValueOnce(baseAccount2); // account lookup for line 2
337
+ spies.update.mockReturnValueOnce(postedEntry);
338
+
339
+ const result = await run(db, { id: baseJournalEntry.id }, commandCtx);
340
+
341
+ const value = expectOk(result);
342
+ expect(value.journalEntry.status).toBe("POSTED");
343
+ // Audit event is emitted as part of successful posting
344
+ expect(value.auditTrail).toBeDefined();
345
+ });
346
+ });
@@ -0,0 +1,160 @@
1
+ import { ok, err, type CommandContext } from "@tailor-platform/erp-kit/module";
2
+ import type { Transaction } from "../generated/kysely-tailordb";
3
+ import {
4
+ JournalEntryNotFoundError,
5
+ InvalidStatusForPostingError,
6
+ MinimumLinesNotMetError,
7
+ UnbalancedEntryError,
8
+ InvalidPeriodStatusError,
9
+ InactiveAccountError,
10
+ SuccessorAccountInvalidError,
11
+ } from "../lib/errors.generated";
12
+
13
+ export interface PostJournalEntryInput {
14
+ id: string;
15
+ }
16
+
17
+ interface AuditEntry {
18
+ type: string;
19
+ originalAccountId?: string;
20
+ successorAccountId?: string;
21
+ journalLineId?: string;
22
+ from?: string;
23
+ to?: string;
24
+ actorId?: string;
25
+ }
26
+
27
+ const VALID_PERIOD_STATUSES = ["OPEN", "FUTURE_ENTERABLE"];
28
+
29
+ /**
30
+ * Function: postJournalEntry
31
+ *
32
+ * Transitions a journal entry from DRAFT to POSTED status, making it an
33
+ * immutable part of the general ledger. Validates accounting constraints
34
+ * including balance, period status, and account status.
35
+ */
36
+ export async function run(db: Transaction, input: PostJournalEntryInput, ctx: CommandContext) {
37
+ const { id } = input;
38
+ const auditTrail: AuditEntry[] = [];
39
+
40
+ // 1. Find journal entry
41
+ const journalEntry = await db
42
+ .selectFrom("JournalEntry")
43
+ .selectAll()
44
+ .where("id", "=", id)
45
+ .forUpdate()
46
+ .executeTakeFirst();
47
+
48
+ if (!journalEntry) {
49
+ return err(new JournalEntryNotFoundError(id));
50
+ }
51
+
52
+ // 2. Validate status is DRAFT
53
+ if (journalEntry.status !== "DRAFT") {
54
+ return err(new InvalidStatusForPostingError(id));
55
+ }
56
+
57
+ // 3. Fetch journal lines
58
+ const journalLines = await db
59
+ .selectFrom("JournalLine")
60
+ .selectAll()
61
+ .where("journalEntryId", "=", id)
62
+ .execute();
63
+
64
+ // 4. Validate minimum two lines
65
+ if (journalLines.length < 2) {
66
+ return err(new MinimumLinesNotMetError(id));
67
+ }
68
+
69
+ // 5. Fetch the accounting period
70
+ const period = await db
71
+ .selectFrom("AccountingPeriod")
72
+ .selectAll()
73
+ .where("id", "=", journalEntry.accountingPeriodId)
74
+ .executeTakeFirst();
75
+
76
+ // 6. Validate period status
77
+ if (!period || !VALID_PERIOD_STATUSES.includes(period.status)) {
78
+ return err(new InvalidPeriodStatusError(journalEntry.accountingPeriodId));
79
+ }
80
+
81
+ // 7. Validate balance: total functional debits must equal total functional credits
82
+ const totalDebits = journalLines.reduce(
83
+ (sum, line) => sum + (line.functionalDebitAmount ?? 0),
84
+ 0,
85
+ );
86
+ const totalCredits = journalLines.reduce(
87
+ (sum, line) => sum + (line.functionalCreditAmount ?? 0),
88
+ 0,
89
+ );
90
+
91
+ if (totalDebits !== totalCredits) {
92
+ return err(new UnbalancedEntryError(id));
93
+ }
94
+
95
+ // 8. Validate all GL accounts and handle successor redirects
96
+ for (const line of journalLines) {
97
+ const account = await db
98
+ .selectFrom("Account")
99
+ .selectAll()
100
+ .where("id", "=", line.accountId)
101
+ .executeTakeFirst();
102
+
103
+ if (!account) {
104
+ return err(new InactiveAccountError(line.accountId));
105
+ }
106
+
107
+ if (account.status === "DEPRECATED" && account.successorAccountId) {
108
+ // Resolve successor
109
+ const successor = await db
110
+ .selectFrom("Account")
111
+ .selectAll()
112
+ .where("id", "=", account.successorAccountId)
113
+ .executeTakeFirst();
114
+
115
+ if (successor?.status !== "ACTIVE") {
116
+ return err(new SuccessorAccountInvalidError(account.successorAccountId ?? line.accountId));
117
+ }
118
+
119
+ // Redirect journal line to successor account
120
+ await db
121
+ .updateTable("JournalLine")
122
+ .set({ accountId: successor.id, updatedAt: new Date() })
123
+ .where("id", "=", line.id)
124
+ .returningAll()
125
+ .executeTakeFirst();
126
+
127
+ auditTrail.push({
128
+ type: "SUCCESSOR_REDIRECT",
129
+ originalAccountId: account.id,
130
+ successorAccountId: successor.id,
131
+ journalLineId: line.id,
132
+ });
133
+ } else if (account.status !== "ACTIVE") {
134
+ return err(new InactiveAccountError(line.accountId));
135
+ }
136
+ }
137
+
138
+ // 9. Transition entry to POSTED
139
+ const now = new Date();
140
+ const updatedEntry = await db
141
+ .updateTable("JournalEntry")
142
+ .set({
143
+ status: "POSTED",
144
+ postedAt: now,
145
+ updatedAt: now,
146
+ })
147
+ .where("id", "=", id)
148
+ .returningAll()
149
+ .executeTakeFirst();
150
+
151
+ // 10. Record audit event
152
+ auditTrail.push({
153
+ type: "STATUS_TRANSITION",
154
+ from: "DRAFT",
155
+ to: "POSTED",
156
+ actorId: ctx.actorId,
157
+ });
158
+
159
+ return ok({ journalEntry: updatedEntry!, auditTrail });
160
+ }
@@ -0,0 +1,6 @@
1
+ // @generated — do not edit
2
+ import { defineCommand } from "@tailor-platform/erp-kit/module";
3
+ import { permissions } from "../lib/permissions.generated";
4
+ import { run } from "./processInventoryHandoff";
5
+
6
+ export const processInventoryHandoff = defineCommand(permissions.processInventoryHandoff, run);