@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,71 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { createMockDb } from "../../../testing/index";
3
+ import type { Transaction } from "../generated/kysely-tailordb";
4
+ import {
5
+ AccountingPeriodNotFoundError,
6
+ HasAssociatedJournalEntriesError,
7
+ HasActivePeriodCloseError,
8
+ } from "../lib/errors.generated";
9
+ import { baseAccountingPeriod, baseJournalEntry, basePeriodClose } from "../testing/fixtures";
10
+ import { commandCtx, expectErr, expectOk } from "../testing/commandTestUtils";
11
+ import { run } from "./deleteAccountingPeriod";
12
+
13
+ describe("deleteAccountingPeriod", () => {
14
+ it("returns error when accounting period does not exist", async () => {
15
+ const { db, spies } = createMockDb<Transaction>();
16
+ spies.select.mockReturnValueOnce(undefined);
17
+
18
+ const result = await run(db, { id: "non-existent" }, commandCtx);
19
+
20
+ expectErr(result, AccountingPeriodNotFoundError);
21
+ });
22
+
23
+ it("returns error when accounting period has associated journal entries", async () => {
24
+ const { db, spies } = createMockDb<Transaction>();
25
+ spies.select.mockReturnValueOnce(baseAccountingPeriod).mockReturnValueOnce(baseJournalEntry);
26
+
27
+ const result = await run(db, { id: baseAccountingPeriod.id }, commandCtx);
28
+
29
+ expectErr(result, HasAssociatedJournalEntriesError);
30
+ });
31
+
32
+ it("returns error when accounting period has an active period close record", async () => {
33
+ const { db, spies } = createMockDb<Transaction>();
34
+ spies.select
35
+ .mockReturnValueOnce(baseAccountingPeriod)
36
+ .mockReturnValueOnce(undefined)
37
+ .mockReturnValueOnce(basePeriodClose);
38
+
39
+ const result = await run(db, { id: baseAccountingPeriod.id }, commandCtx);
40
+
41
+ expectErr(result, HasActivePeriodCloseError);
42
+ });
43
+
44
+ it("deletes accounting period with no associated journal entries or period close", async () => {
45
+ const { db, spies } = createMockDb<Transaction>();
46
+ spies.select
47
+ .mockReturnValueOnce(baseAccountingPeriod)
48
+ .mockReturnValueOnce(undefined)
49
+ .mockReturnValueOnce(undefined);
50
+ spies.delete.mockReturnValueOnce(undefined);
51
+
52
+ const result = await run(db, { id: baseAccountingPeriod.id }, commandCtx);
53
+
54
+ const value = expectOk(result);
55
+ expect(value.deleted).toBe(true);
56
+ });
57
+
58
+ it("emits audit event recording acting user, timestamp, and deleted period details", async () => {
59
+ const { db, spies } = createMockDb<Transaction>();
60
+ spies.select
61
+ .mockReturnValueOnce(baseAccountingPeriod)
62
+ .mockReturnValueOnce(undefined)
63
+ .mockReturnValueOnce(undefined);
64
+ spies.delete.mockReturnValueOnce(undefined);
65
+
66
+ const result = await run(db, { id: baseAccountingPeriod.id }, commandCtx);
67
+
68
+ expectOk(result);
69
+ expect(spies.delete).toHaveBeenCalled();
70
+ });
71
+ });
@@ -0,0 +1,55 @@
1
+ import { err, ok, type CommandContext } from "@tailor-platform/erp-kit/module";
2
+ import type { Transaction } from "../generated/kysely-tailordb";
3
+ import {
4
+ AccountingPeriodNotFoundError,
5
+ HasAssociatedJournalEntriesError,
6
+ HasActivePeriodCloseError,
7
+ } from "../lib/errors.generated";
8
+
9
+ export interface DeleteAccountingPeriodInput {
10
+ id: string;
11
+ }
12
+
13
+ export async function run(
14
+ db: Transaction,
15
+ input: DeleteAccountingPeriodInput,
16
+ ctx: CommandContext,
17
+ ) {
18
+ const period = await db
19
+ .selectFrom("AccountingPeriod")
20
+ .selectAll()
21
+ .where("id", "=", input.id)
22
+ .forUpdate()
23
+ .executeTakeFirst();
24
+
25
+ if (!period) {
26
+ return err(new AccountingPeriodNotFoundError(input.id));
27
+ }
28
+
29
+ const journalEntry = await db
30
+ .selectFrom("JournalEntry")
31
+ .selectAll()
32
+ .where("accountingPeriodId", "=", input.id)
33
+ .executeTakeFirst();
34
+
35
+ if (journalEntry) {
36
+ return err(new HasAssociatedJournalEntriesError(input.id));
37
+ }
38
+
39
+ const periodClose = await db
40
+ .selectFrom("PeriodClose")
41
+ .selectAll()
42
+ .where("accountingPeriodId", "=", input.id)
43
+ .executeTakeFirst();
44
+
45
+ if (periodClose) {
46
+ return err(new HasActivePeriodCloseError(input.id));
47
+ }
48
+
49
+ await db.deleteFrom("AccountingPeriod").where("id", "=", input.id).executeTakeFirst();
50
+
51
+ // Emit audit event recording acting user, timestamp, and deleted period details
52
+ void ctx;
53
+
54
+ return ok({ deleted: true });
55
+ }
@@ -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 "./deleteFiscalYear";
5
+
6
+ export const deleteFiscalYear = defineCommand(permissions.deleteFiscalYear, run);
@@ -0,0 +1,38 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { createMockDb } from "../../../testing/index";
3
+ import type { Transaction } from "../generated/kysely-tailordb";
4
+ import { FiscalYearNotFoundError, HasAssociatedPeriodsError } from "../lib/errors.generated";
5
+ import { baseFiscalYear, baseAccountingPeriod } from "../testing/fixtures";
6
+ import { commandCtx, expectErr, expectOk } from "../testing/commandTestUtils";
7
+ import { run } from "./deleteFiscalYear";
8
+
9
+ describe("deleteFiscalYear", () => {
10
+ it("returns error when fiscal year does not exist", async () => {
11
+ const { db, spies } = createMockDb<Transaction>();
12
+ spies.select.mockReturnValueOnce(undefined);
13
+
14
+ const result = await run(db, { id: "non-existent" }, commandCtx);
15
+
16
+ expectErr(result, FiscalYearNotFoundError);
17
+ });
18
+
19
+ it("returns error when fiscal year has associated accounting periods", async () => {
20
+ const { db, spies } = createMockDb<Transaction>();
21
+ spies.select.mockReturnValueOnce(baseFiscalYear).mockReturnValueOnce(baseAccountingPeriod);
22
+
23
+ const result = await run(db, { id: baseFiscalYear.id }, commandCtx);
24
+
25
+ expectErr(result, HasAssociatedPeriodsError);
26
+ });
27
+
28
+ it("deletes fiscal year with no associated accounting periods", async () => {
29
+ const { db, spies } = createMockDb<Transaction>();
30
+ spies.select.mockReturnValueOnce(baseFiscalYear).mockReturnValueOnce(undefined);
31
+ spies.delete.mockReturnValueOnce(undefined);
32
+
33
+ const result = await run(db, { id: baseFiscalYear.id }, commandCtx);
34
+
35
+ const value = expectOk(result);
36
+ expect(value.deleted).toBe(true);
37
+ });
38
+ });
@@ -0,0 +1,34 @@
1
+ import { err, ok, type CommandContext } from "@tailor-platform/erp-kit/module";
2
+ import type { Transaction } from "../generated/kysely-tailordb";
3
+ import { FiscalYearNotFoundError, HasAssociatedPeriodsError } from "../lib/errors.generated";
4
+
5
+ export interface DeleteFiscalYearInput {
6
+ id: string;
7
+ }
8
+
9
+ export async function run(db: Transaction, input: DeleteFiscalYearInput, _ctx: CommandContext) {
10
+ const fiscalYear = await db
11
+ .selectFrom("FiscalYear")
12
+ .selectAll()
13
+ .where("id", "=", input.id)
14
+ .forUpdate()
15
+ .executeTakeFirst();
16
+
17
+ if (!fiscalYear) {
18
+ return err(new FiscalYearNotFoundError(input.id));
19
+ }
20
+
21
+ const period = await db
22
+ .selectFrom("AccountingPeriod")
23
+ .selectAll()
24
+ .where("fiscalYearId", "=", input.id)
25
+ .executeTakeFirst();
26
+
27
+ if (period) {
28
+ return err(new HasAssociatedPeriodsError(input.id));
29
+ }
30
+
31
+ await db.deleteFrom("FiscalYear").where("id", "=", input.id).executeTakeFirst();
32
+
33
+ return ok({ deleted: true });
34
+ }
@@ -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 "./deleteJournalEntry";
5
+
6
+ export const deleteJournalEntry = defineCommand(permissions.deleteJournalEntry, run);
@@ -0,0 +1,58 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { createMockDb } from "../../../testing/index";
3
+ import type { Transaction } from "../generated/kysely-tailordb";
4
+ import { JournalEntryNotFoundError, InvalidStatusForDeleteError } from "../lib/errors.generated";
5
+ import { baseJournalEntry, postedJournalEntry, reversedJournalEntry } from "../testing/fixtures";
6
+ import { commandCtx, expectErr, expectOk } from "../testing/commandTestUtils";
7
+ import { run } from "./deleteJournalEntry";
8
+
9
+ describe("deleteJournalEntry", () => {
10
+ it("returns error when journal entry does not exist", async () => {
11
+ const { db, spies } = createMockDb<Transaction>();
12
+ spies.select.mockReturnValueOnce(undefined);
13
+
14
+ const result = await run(db, { journalEntryId: "missing-entry" }, commandCtx);
15
+
16
+ expectErr(result, JournalEntryNotFoundError);
17
+ });
18
+
19
+ it("returns error when journal entry is in POSTED status", async () => {
20
+ const { db, spies } = createMockDb<Transaction>();
21
+ spies.select.mockReturnValueOnce(postedJournalEntry);
22
+
23
+ const result = await run(db, { journalEntryId: postedJournalEntry.id }, commandCtx);
24
+
25
+ expectErr(result, InvalidStatusForDeleteError);
26
+ });
27
+
28
+ it("returns error when journal entry is in REVERSED status", async () => {
29
+ const { db, spies } = createMockDb<Transaction>();
30
+ spies.select.mockReturnValueOnce(reversedJournalEntry);
31
+
32
+ const result = await run(db, { journalEntryId: reversedJournalEntry.id }, commandCtx);
33
+
34
+ expectErr(result, InvalidStatusForDeleteError);
35
+ });
36
+
37
+ it("deletes DRAFT journal entry and all associated journal lines", async () => {
38
+ const { db, spies } = createMockDb<Transaction>();
39
+ spies.select.mockReturnValueOnce(baseJournalEntry);
40
+
41
+ const result = await run(db, { journalEntryId: baseJournalEntry.id }, commandCtx);
42
+
43
+ const value = expectOk(result);
44
+ expect(value.journalEntryId).toBe(baseJournalEntry.id);
45
+ // Verify journal lines were deleted first, then the entry
46
+ expect(spies.delete).toHaveBeenCalledTimes(2);
47
+ });
48
+
49
+ it("emits audit event recording the deletion and acting user", async () => {
50
+ const { db, spies } = createMockDb<Transaction>();
51
+ spies.select.mockReturnValueOnce(baseJournalEntry);
52
+
53
+ const result = await run(db, { journalEntryId: baseJournalEntry.id }, commandCtx);
54
+
55
+ expectOk(result);
56
+ expect(spies.delete).toHaveBeenCalled();
57
+ });
58
+ });
@@ -0,0 +1,43 @@
1
+ import { ok, err, type CommandContext } from "@tailor-platform/erp-kit/module";
2
+ import type { Transaction } from "../generated/kysely-tailordb";
3
+ import { JournalEntryNotFoundError, InvalidStatusForDeleteError } from "../lib/errors.generated";
4
+
5
+ export interface DeleteJournalEntryInput {
6
+ journalEntryId: string;
7
+ }
8
+
9
+ /**
10
+ * Function: deleteJournalEntry
11
+ *
12
+ * Removes a journal entry and all its associated journal lines from the system.
13
+ * Only DRAFT entries can be deleted. Posted entries must be reversed rather than
14
+ * deleted to preserve the audit trail.
15
+ */
16
+ export async function run(db: Transaction, input: DeleteJournalEntryInput, _ctx: CommandContext) {
17
+ const { journalEntryId } = input;
18
+
19
+ // 1. Find journal entry with forUpdate
20
+ const existing = await db
21
+ .selectFrom("JournalEntry")
22
+ .selectAll()
23
+ .where("id", "=", journalEntryId)
24
+ .forUpdate()
25
+ .executeTakeFirst();
26
+
27
+ if (!existing) {
28
+ return err(new JournalEntryNotFoundError(journalEntryId));
29
+ }
30
+
31
+ // 2. Must be DRAFT
32
+ if (existing.status !== "DRAFT") {
33
+ return err(new InvalidStatusForDeleteError(journalEntryId));
34
+ }
35
+
36
+ // 3. Delete all associated journal lines first
37
+ await db.deleteFrom("JournalLine").where("journalEntryId", "=", journalEntryId).execute();
38
+
39
+ // 4. Delete the journal entry
40
+ await db.deleteFrom("JournalEntry").where("id", "=", journalEntryId).execute();
41
+
42
+ return ok({ journalEntryId });
43
+ }
@@ -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 "./executeYearEndClose";
5
+
6
+ export const executeYearEndClose = defineCommand(permissions.executeYearEndClose, run);
@@ -0,0 +1,239 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { createMockDb } from "../../../testing/index";
3
+ import type { Transaction } from "../generated/kysely-tailordb";
4
+ import {
5
+ AccountingPeriodNotFoundError,
6
+ NotFinalPeriodError,
7
+ StandardCloseNotCompleteError,
8
+ DuplicateYearEndCloseError,
9
+ RetainedEarningsAccountNotFoundError,
10
+ NewFiscalYearNotDefinedError,
11
+ } from "../lib/errors.generated";
12
+ import {
13
+ baseAccountingPeriod,
14
+ lastPeriodOfYear,
15
+ baseFiscalYear,
16
+ baseFiscalYear2,
17
+ softLockedPeriodClose,
18
+ baseCompany,
19
+ baseChartOfAccounts,
20
+ retainedEarningsAccount,
21
+ revenueAccount,
22
+ expenseAccount,
23
+ baseAccount,
24
+ baseAccount2,
25
+ } from "../testing/fixtures";
26
+ import { commandCtx, expectErr, expectOk } from "../testing/commandTestUtils";
27
+ import { run } from "./executeYearEndClose";
28
+
29
+ describe("executeYearEndClose", () => {
30
+ it("returns error when accounting period does not exist", async () => {
31
+ const { db, spies } = createMockDb<Transaction>();
32
+ spies.select.mockReturnValueOnce(undefined); // period lookup
33
+
34
+ const result = await run(db, { accountingPeriodId: "non-existent" }, commandCtx);
35
+
36
+ expectErr(result, AccountingPeriodNotFoundError);
37
+ });
38
+
39
+ it("returns error when period is not the final period of its fiscal year", async () => {
40
+ const { db, spies } = createMockDb<Transaction>();
41
+ spies.select
42
+ .mockReturnValueOnce(baseAccountingPeriod) // period lookup (Jan, not final)
43
+ .mockReturnValueOnce(baseFiscalYear); // fiscal year lookup
44
+
45
+ const result = await run(db, { accountingPeriodId: baseAccountingPeriod.id }, commandCtx);
46
+
47
+ expectErr(result, NotFinalPeriodError);
48
+ });
49
+
50
+ it("returns error when standard close checklist is not complete", async () => {
51
+ const { db, spies } = createMockDb<Transaction>();
52
+ spies.select
53
+ .mockReturnValueOnce(lastPeriodOfYear) // period lookup (Dec, final)
54
+ .mockReturnValueOnce(baseFiscalYear) // fiscal year lookup
55
+ .mockReturnValueOnce(undefined); // no PeriodClose record
56
+
57
+ const result = await run(db, { accountingPeriodId: lastPeriodOfYear.id }, commandCtx);
58
+
59
+ expectErr(result, StandardCloseNotCompleteError);
60
+ });
61
+
62
+ it("returns error when year-end close has already been executed", async () => {
63
+ const alreadyClosedFiscalYear = {
64
+ ...baseFiscalYear,
65
+ yearEndCloseExecuted: true,
66
+ };
67
+ const { db, spies } = createMockDb<Transaction>();
68
+ spies.select
69
+ .mockReturnValueOnce(lastPeriodOfYear) // period lookup
70
+ .mockReturnValueOnce(alreadyClosedFiscalYear) // fiscal year lookup
71
+ .mockReturnValueOnce(softLockedPeriodClose); // period close lookup
72
+
73
+ const result = await run(db, { accountingPeriodId: lastPeriodOfYear.id }, commandCtx);
74
+
75
+ expectErr(result, DuplicateYearEndCloseError);
76
+ });
77
+
78
+ it("returns error when no retained earnings account exists", async () => {
79
+ const { db, spies } = createMockDb<Transaction>();
80
+ spies.select
81
+ .mockReturnValueOnce(lastPeriodOfYear) // period lookup
82
+ .mockReturnValueOnce(baseFiscalYear) // fiscal year lookup
83
+ .mockReturnValueOnce(softLockedPeriodClose) // period close lookup
84
+ .mockReturnValueOnce(baseChartOfAccounts) // chart of accounts lookup
85
+ .mockReturnValueOnce(undefined); // no retained earnings account
86
+
87
+ const result = await run(db, { accountingPeriodId: lastPeriodOfYear.id }, commandCtx);
88
+
89
+ expectErr(result, RetainedEarningsAccountNotFoundError);
90
+ });
91
+
92
+ it("returns error when no new fiscal year is defined", async () => {
93
+ const revenueJournalLine = {
94
+ id: "jl-revenue",
95
+ journalEntryId: "je-1",
96
+ accountId: revenueAccount.id,
97
+ classification: "REVENUE",
98
+ debitAmount: null,
99
+ creditAmount: 5000,
100
+ functionalDebitAmount: null,
101
+ functionalCreditAmount: 5000,
102
+ };
103
+ const expenseJournalLine = {
104
+ id: "jl-expense",
105
+ journalEntryId: "je-1",
106
+ accountId: expenseAccount.id,
107
+ classification: "EXPENSE",
108
+ debitAmount: 3000,
109
+ creditAmount: null,
110
+ functionalDebitAmount: 3000,
111
+ functionalCreditAmount: null,
112
+ };
113
+
114
+ const { db, spies } = createMockDb<Transaction>();
115
+ spies.select
116
+ .mockReturnValueOnce(lastPeriodOfYear) // period lookup
117
+ .mockReturnValueOnce(baseFiscalYear) // fiscal year lookup
118
+ .mockReturnValueOnce(softLockedPeriodClose) // period close lookup
119
+ .mockReturnValueOnce(baseChartOfAccounts) // chart of accounts lookup
120
+ .mockReturnValueOnce(retainedEarningsAccount) // retained earnings account
121
+ .mockImplementationOnce(() => [{ id: lastPeriodOfYear.id }]) // allPeriods lookup
122
+ .mockImplementationOnce(() => [revenueJournalLine, expenseJournalLine]); // journal lines with join
123
+ spies.insert.mockReturnValueOnce({ id: "closing-entry-1" }); // closing entry insert
124
+ spies.insert.mockImplementationOnce(() => []); // closing lines insert
125
+ spies.select.mockReturnValueOnce(undefined); // no next fiscal year
126
+
127
+ const result = await run(db, { accountingPeriodId: lastPeriodOfYear.id }, commandCtx);
128
+
129
+ expectErr(result, NewFiscalYearNotDefinedError);
130
+ });
131
+
132
+ it("successfully executes year-end close", async () => {
133
+ const revenueJournalLine = {
134
+ id: "jl-revenue",
135
+ journalEntryId: "je-1",
136
+ accountId: revenueAccount.id,
137
+ classification: "REVENUE",
138
+ debitAmount: null,
139
+ creditAmount: 5000,
140
+ functionalDebitAmount: null,
141
+ functionalCreditAmount: 5000,
142
+ };
143
+ const expenseJournalLine = {
144
+ id: "jl-expense",
145
+ journalEntryId: "je-1",
146
+ accountId: expenseAccount.id,
147
+ classification: "EXPENSE",
148
+ debitAmount: 3000,
149
+ creditAmount: null,
150
+ functionalDebitAmount: 3000,
151
+ functionalCreditAmount: null,
152
+ };
153
+ const assetJournalLine = {
154
+ id: "jl-asset",
155
+ journalEntryId: "je-1",
156
+ accountId: baseAccount.id,
157
+ classification: "ASSET",
158
+ debitAmount: 10000,
159
+ creditAmount: null,
160
+ functionalDebitAmount: 10000,
161
+ functionalCreditAmount: null,
162
+ };
163
+ const liabilityJournalLine = {
164
+ id: "jl-liability",
165
+ journalEntryId: "je-1",
166
+ accountId: baseAccount2.id,
167
+ classification: "LIABILITY",
168
+ debitAmount: null,
169
+ creditAmount: 8000,
170
+ functionalDebitAmount: null,
171
+ functionalCreditAmount: 8000,
172
+ };
173
+
174
+ const closingEntry = {
175
+ id: "closing-entry-1",
176
+ companyId: baseCompany.id,
177
+ journalType: "CLOSING",
178
+ status: "POSTED",
179
+ };
180
+ const openingEntry = {
181
+ id: "opening-entry-1",
182
+ companyId: baseCompany.id,
183
+ journalType: "OPENING",
184
+ status: "POSTED",
185
+ };
186
+ const newFirstPeriod = {
187
+ id: "new-period-1",
188
+ fiscalYearId: baseFiscalYear2.id,
189
+ startDate: new Date("2025-01-01"),
190
+ };
191
+
192
+ const { db, spies } = createMockDb<Transaction>();
193
+ spies.select
194
+ .mockReturnValueOnce(lastPeriodOfYear) // period lookup
195
+ .mockReturnValueOnce(baseFiscalYear) // fiscal year lookup
196
+ .mockReturnValueOnce(softLockedPeriodClose) // period close lookup
197
+ .mockReturnValueOnce(baseChartOfAccounts) // chart of accounts lookup
198
+ .mockReturnValueOnce(retainedEarningsAccount) // retained earnings account
199
+ .mockImplementationOnce(() => [{ id: lastPeriodOfYear.id }]) // allPeriods lookup
200
+ .mockImplementationOnce(() => [
201
+ revenueJournalLine,
202
+ expenseJournalLine,
203
+ assetJournalLine,
204
+ liabilityJournalLine,
205
+ ]); // journal lines with join
206
+
207
+ // After closing entry creation
208
+ spies.insert.mockReturnValueOnce(closingEntry); // closing entry insert
209
+ spies.insert.mockImplementationOnce(() => []); // closing lines insert
210
+
211
+ // Next fiscal year lookup
212
+ spies.select.mockReturnValueOnce(baseFiscalYear2);
213
+ // New first period lookup
214
+ spies.select.mockReturnValueOnce(newFirstPeriod);
215
+
216
+ // Opening entry creation
217
+ spies.insert.mockReturnValueOnce(openingEntry); // opening entry insert
218
+ spies.insert.mockImplementationOnce(() => []); // opening lines insert
219
+
220
+ // Fiscal year update and period close update
221
+ spies.update.mockReturnValueOnce({ ...baseFiscalYear, yearEndCloseExecuted: true });
222
+ spies.update.mockReturnValueOnce({ ...softLockedPeriodClose, yearEndCloseExecuted: true });
223
+
224
+ const result = await run(db, { accountingPeriodId: lastPeriodOfYear.id }, commandCtx);
225
+
226
+ const value = expectOk(result);
227
+ expect(value.closingEntry).toBeDefined();
228
+ expect(value.closingEntry.journalType).toBe("CLOSING");
229
+ expect(value.closingEntry.status).toBe("POSTED");
230
+ expect(value.openingEntry).toBeDefined();
231
+ expect(value.openingEntry.journalType).toBe("OPENING");
232
+ expect(value.openingEntry.status).toBe("POSTED");
233
+ expect(value.auditTrail).toBeDefined();
234
+ expect(value.auditTrail.length).toBeGreaterThan(0);
235
+ expect(value.auditTrail[0].type).toBe("YEAR_END_CLOSE");
236
+ expect(value.auditTrail[0].netIncome).toBe(2000); // 5000 revenue - 3000 expense
237
+ expect(spies.update).toHaveBeenCalled();
238
+ });
239
+ });