@tailor-platform/erp-kit 0.1.2 → 0.2.1

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 (330) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +80 -12
  3. package/dist/cli.js +1070 -450
  4. package/package.json +11 -8
  5. package/schemas/app-compose/business-flow.yml +3 -0
  6. package/schemas/app-compose/story.yml +1 -1
  7. package/schemas/module/model.yml +5 -0
  8. package/skills/{app-compose-1-requirement-analysis → erp-kit-app-1-requirements}/SKILL.md +8 -14
  9. package/skills/{app-compose-2-requirements-breakdown → erp-kit-app-2-breakdown}/SKILL.md +6 -13
  10. package/skills/{app-compose-3-doc-review → erp-kit-app-3-doc-review}/SKILL.md +2 -6
  11. package/skills/{app-compose-6-implementation-spec → erp-kit-app-4-impl-spec}/SKILL.md +11 -22
  12. package/skills/erp-kit-app-5-implementation/SKILL.md +149 -0
  13. package/skills/erp-kit-app-5-implementation/references/backend.md +232 -0
  14. package/skills/erp-kit-app-5-implementation/references/frontend.md +242 -0
  15. package/skills/{mock-scenario → erp-kit-mock-scenario}/SKILL.md +1 -1
  16. package/skills/{1-module-docs → erp-kit-module-1-docs}/SKILL.md +2 -2
  17. package/skills/{2-module-feature-breakdown → erp-kit-module-2-feature-breakdown}/SKILL.md +13 -9
  18. package/skills/erp-kit-module-2-feature-breakdown/references/naming.md +59 -0
  19. package/skills/{3-module-doc-review → erp-kit-module-3-doc-review}/SKILL.md +83 -25
  20. package/skills/erp-kit-module-4-tdd/SKILL.md +94 -0
  21. package/skills/erp-kit-module-4-tdd/references/cross-module-dependency.md +133 -0
  22. package/skills/{4-module-tdd-implementation → erp-kit-module-4-tdd}/references/db-relations.md +5 -1
  23. package/skills/{4-module-tdd-implementation → erp-kit-module-4-tdd}/references/exports.md +1 -1
  24. package/skills/erp-kit-module-4-tdd/references/generated-code.md +32 -0
  25. package/skills/{5-module-implementation-review → erp-kit-module-5-impl-review}/SKILL.md +46 -44
  26. package/skills/erp-kit-module-5-impl-review/references/commands.md +62 -0
  27. package/skills/erp-kit-module-5-impl-review/references/errors.md +10 -0
  28. package/skills/{5-module-implementation-review → erp-kit-module-5-impl-review}/references/testing.md +1 -1
  29. package/skills/erp-kit-module-shared/SKILL.md +16 -0
  30. package/skills/erp-kit-module-shared/references/commands.md +203 -0
  31. package/skills/erp-kit-module-shared/references/errors.md +35 -0
  32. package/skills/erp-kit-module-shared/references/queries.md +168 -0
  33. package/skills/erp-kit-module-shared/references/structure.md +36 -0
  34. package/skills/{3-module-doc-review → erp-kit-module-shared}/references/testing.md +4 -3
  35. package/skills/erp-kit-update/SKILL.md +64 -0
  36. package/src/cli.doc.test.ts +65 -0
  37. package/src/cli.ts +3 -35
  38. package/src/commands/app/index.ts +3 -3
  39. package/src/commands/check.test.ts +1 -1
  40. package/src/commands/check.ts +2 -2
  41. package/src/commands/index.ts +73 -0
  42. package/src/commands/init.test.ts +22 -5
  43. package/src/commands/init.ts +25 -16
  44. package/src/commands/license.ts +193 -0
  45. package/src/commands/mock/index.ts +2 -2
  46. package/src/commands/mock/start.ts +1 -1
  47. package/src/commands/mock/validate.test.ts +1 -1
  48. package/src/commands/module/generate.ts +35 -0
  49. package/src/commands/module/index.ts +6 -4
  50. package/src/commands/module/list.test.ts +7 -12
  51. package/src/commands/module/list.ts +1 -1
  52. package/src/commands/scaffold-templates.ts +65 -0
  53. package/src/commands/scaffold.test.ts +92 -2
  54. package/src/commands/scaffold.ts +22 -2
  55. package/src/commands/sync-check.test.ts +60 -1
  56. package/src/commands/sync-check.ts +35 -2
  57. package/src/generator/generate-code.test.ts +200 -0
  58. package/src/generator/generate-code.ts +260 -0
  59. package/src/generator/parse-command-doc.test.ts +159 -0
  60. package/src/generator/parse-command-doc.ts +116 -0
  61. package/src/integration.test.ts +2 -2
  62. package/src/module.ts +44 -6
  63. package/src/modules/item-management/README.md +38 -0
  64. package/src/modules/item-management/command/activateItem.generated.ts +6 -0
  65. package/src/modules/item-management/command/activateItem.test.ts +76 -0
  66. package/src/modules/item-management/command/activateItem.ts +42 -0
  67. package/src/modules/item-management/command/assignItemToTaxonomy.generated.ts +6 -0
  68. package/src/modules/item-management/command/assignItemToTaxonomy.test.ts +88 -0
  69. package/src/modules/item-management/command/assignItemToTaxonomy.ts +63 -0
  70. package/src/modules/item-management/command/createItem.generated.ts +6 -0
  71. package/src/modules/item-management/command/createItem.test.ts +152 -0
  72. package/src/modules/item-management/command/createItem.ts +72 -0
  73. package/src/modules/item-management/command/createTaxonomyNode.generated.ts +6 -0
  74. package/src/modules/item-management/command/createTaxonomyNode.test.ts +126 -0
  75. package/src/modules/item-management/command/createTaxonomyNode.ts +70 -0
  76. package/src/modules/item-management/command/deactivateItem.generated.ts +6 -0
  77. package/src/modules/item-management/command/deactivateItem.test.ts +76 -0
  78. package/src/modules/item-management/command/deactivateItem.ts +42 -0
  79. package/src/modules/item-management/command/deleteItem.generated.ts +6 -0
  80. package/src/modules/item-management/command/deleteItem.test.ts +61 -0
  81. package/src/modules/item-management/command/deleteItem.ts +38 -0
  82. package/src/modules/item-management/command/deleteTaxonomyNode.generated.ts +6 -0
  83. package/src/modules/item-management/command/deleteTaxonomyNode.test.ts +73 -0
  84. package/src/modules/item-management/command/deleteTaxonomyNode.ts +50 -0
  85. package/src/modules/item-management/command/moveTaxonomyNode.generated.ts +6 -0
  86. package/src/modules/item-management/command/moveTaxonomyNode.test.ts +136 -0
  87. package/src/modules/item-management/command/moveTaxonomyNode.ts +85 -0
  88. package/src/modules/item-management/command/reactivateItem.generated.ts +6 -0
  89. package/src/modules/item-management/command/reactivateItem.test.ts +76 -0
  90. package/src/modules/item-management/command/reactivateItem.ts +42 -0
  91. package/src/modules/item-management/command/removeItemFromTaxonomy.generated.ts +6 -0
  92. package/src/modules/item-management/command/removeItemFromTaxonomy.test.ts +43 -0
  93. package/src/modules/item-management/command/removeItemFromTaxonomy.ts +30 -0
  94. package/src/modules/item-management/command/updateItem.generated.ts +6 -0
  95. package/src/modules/item-management/command/updateItem.test.ts +178 -0
  96. package/src/modules/item-management/command/updateItem.ts +103 -0
  97. package/src/modules/item-management/command/updateTaxonomyNode.generated.ts +6 -0
  98. package/src/modules/item-management/command/updateTaxonomyNode.test.ts +88 -0
  99. package/src/modules/item-management/command/updateTaxonomyNode.ts +62 -0
  100. package/src/modules/item-management/db/item.ts +47 -0
  101. package/src/modules/item-management/db/itemTaxonomyAssignment.ts +49 -0
  102. package/src/modules/item-management/db/taxonomyNode.ts +34 -0
  103. package/src/modules/item-management/docs/commands/ActivateItem.md +32 -0
  104. package/src/modules/item-management/docs/commands/AssignItemToTaxonomy.md +38 -0
  105. package/src/modules/item-management/docs/commands/CreateItem.md +44 -0
  106. package/src/modules/item-management/docs/commands/CreateTaxonomyNode.md +44 -0
  107. package/src/modules/item-management/docs/commands/DeactivateItem.md +34 -0
  108. package/src/modules/item-management/docs/commands/DeleteItem.md +35 -0
  109. package/src/modules/item-management/docs/commands/DeleteTaxonomyNode.md +39 -0
  110. package/src/modules/item-management/docs/commands/MoveTaxonomyNode.md +45 -0
  111. package/src/modules/item-management/docs/commands/ReactivateItem.md +34 -0
  112. package/src/modules/item-management/docs/commands/RemoveItemFromTaxonomy.md +30 -0
  113. package/src/modules/item-management/docs/commands/UpdateItem.md +55 -0
  114. package/src/modules/item-management/docs/commands/UpdateTaxonomyNode.md +36 -0
  115. package/src/modules/item-management/docs/features/item-lifecycle.md +60 -0
  116. package/src/modules/item-management/docs/features/item-taxonomy.md +65 -0
  117. package/src/modules/item-management/docs/models/ItemTaxonomyAssignment.md +36 -0
  118. package/src/modules/item-management/docs/models/TaxonomyNode.md +47 -0
  119. package/src/modules/item-management/docs/models/item.md +59 -0
  120. package/src/modules/item-management/docs/queries/CalculateNodeDepth.md +36 -0
  121. package/src/modules/item-management/docs/queries/CalculateSubtreeDepth.md +40 -0
  122. package/src/modules/item-management/docs/queries/DetectCircularReference.md +41 -0
  123. package/src/modules/item-management/docs/queries/GetItem.md +38 -0
  124. package/src/modules/item-management/docs/queries/GetItemTaxonomyAssignment.md +29 -0
  125. package/src/modules/item-management/docs/queries/GetTaxonomyNode.md +35 -0
  126. package/src/modules/item-management/docs/queries/GetTaxonomyNodeAssignments.md +29 -0
  127. package/src/modules/item-management/docs/queries/GetTaxonomyNodeChildren.md +29 -0
  128. package/src/modules/item-management/generated/enums.ts +9 -0
  129. package/src/modules/item-management/generated/kysely-tailordb.ts +62 -0
  130. package/src/modules/item-management/index.ts +53 -0
  131. package/src/modules/item-management/lib/_db_deps.ts +13 -0
  132. package/src/modules/item-management/lib/errors.generated.ts +117 -0
  133. package/src/modules/item-management/lib/permissions.generated.ts +17 -0
  134. package/src/modules/item-management/lib/types.ts +19 -0
  135. package/src/modules/item-management/module.ts +97 -0
  136. package/src/modules/item-management/query/calculateNodeDepth.generated.ts +5 -0
  137. package/src/modules/item-management/query/calculateNodeDepth.test.ts +56 -0
  138. package/src/modules/item-management/query/calculateNodeDepth.ts +28 -0
  139. package/src/modules/item-management/query/calculateSubtreeDepth.generated.ts +5 -0
  140. package/src/modules/item-management/query/calculateSubtreeDepth.test.ts +75 -0
  141. package/src/modules/item-management/query/calculateSubtreeDepth.ts +29 -0
  142. package/src/modules/item-management/query/detectCircularReference.generated.ts +5 -0
  143. package/src/modules/item-management/query/detectCircularReference.test.ts +61 -0
  144. package/src/modules/item-management/query/detectCircularReference.ts +32 -0
  145. package/src/modules/item-management/query/getItem.generated.ts +5 -0
  146. package/src/modules/item-management/query/getItem.test.ts +67 -0
  147. package/src/modules/item-management/query/getItem.ts +20 -0
  148. package/src/modules/item-management/query/getItemTaxonomyAssignment.generated.ts +5 -0
  149. package/src/modules/item-management/query/getItemTaxonomyAssignment.test.ts +25 -0
  150. package/src/modules/item-management/query/getItemTaxonomyAssignment.ts +18 -0
  151. package/src/modules/item-management/query/getTaxonomyNode.generated.ts +5 -0
  152. package/src/modules/item-management/query/getTaxonomyNode.test.ts +47 -0
  153. package/src/modules/item-management/query/getTaxonomyNode.ts +18 -0
  154. package/src/modules/item-management/query/getTaxonomyNodeAssignments.generated.ts +5 -0
  155. package/src/modules/item-management/query/getTaxonomyNodeAssignments.test.ts +25 -0
  156. package/src/modules/item-management/query/getTaxonomyNodeAssignments.ts +16 -0
  157. package/src/modules/item-management/query/getTaxonomyNodeChildren.generated.ts +5 -0
  158. package/src/modules/item-management/query/getTaxonomyNodeChildren.test.ts +34 -0
  159. package/src/modules/item-management/query/getTaxonomyNodeChildren.ts +16 -0
  160. package/src/modules/item-management/tailor.config.ts +11 -0
  161. package/src/modules/item-management/testing/fixtures.ts +81 -0
  162. package/src/modules/primitives/command/activateCategory.generated.ts +6 -0
  163. package/src/modules/primitives/command/activateCategory.test.ts +11 -29
  164. package/src/modules/primitives/command/activateCategory.ts +27 -34
  165. package/src/modules/primitives/command/activateCurrency.generated.ts +6 -0
  166. package/src/modules/primitives/command/activateCurrency.test.ts +11 -29
  167. package/src/modules/primitives/command/activateCurrency.ts +27 -34
  168. package/src/modules/primitives/command/activateUnit.generated.ts +6 -0
  169. package/src/modules/primitives/command/activateUnit.test.ts +11 -15
  170. package/src/modules/primitives/command/activateUnit.ts +27 -34
  171. package/src/modules/primitives/command/createCategory.generated.ts +6 -0
  172. package/src/modules/primitives/command/createCategory.test.ts +27 -39
  173. package/src/modules/primitives/command/createCategory.ts +53 -62
  174. package/src/modules/primitives/command/createCurrency.generated.ts +6 -0
  175. package/src/modules/primitives/command/createCurrency.test.ts +78 -71
  176. package/src/modules/primitives/command/createCurrency.ts +43 -48
  177. package/src/modules/primitives/command/createExchangeRate.generated.ts +6 -0
  178. package/src/modules/primitives/command/createExchangeRate.test.ts +101 -100
  179. package/src/modules/primitives/command/createExchangeRate.ts +50 -59
  180. package/src/modules/primitives/command/createUnit.generated.ts +6 -0
  181. package/src/modules/primitives/command/createUnit.test.ts +92 -95
  182. package/src/modules/primitives/command/createUnit.ts +54 -57
  183. package/src/modules/primitives/command/deactivateCategory.generated.ts +6 -0
  184. package/src/modules/primitives/command/deactivateCategory.test.ts +27 -28
  185. package/src/modules/primitives/command/deactivateCategory.ts +43 -50
  186. package/src/modules/primitives/command/deactivateCurrency.generated.ts +6 -0
  187. package/src/modules/primitives/command/deactivateCurrency.test.ts +23 -38
  188. package/src/modules/primitives/command/deactivateCurrency.ts +31 -38
  189. package/src/modules/primitives/command/deactivateUnit.generated.ts +6 -0
  190. package/src/modules/primitives/command/deactivateUnit.test.ts +27 -23
  191. package/src/modules/primitives/command/deactivateUnit.ts +39 -49
  192. package/src/modules/primitives/command/setBaseCurrency.generated.ts +6 -0
  193. package/src/modules/primitives/command/setBaseCurrency.test.ts +40 -33
  194. package/src/modules/primitives/command/setBaseCurrency.ts +43 -50
  195. package/src/modules/primitives/command/setReferenceUnit.generated.ts +6 -0
  196. package/src/modules/primitives/command/setReferenceUnit.test.ts +39 -35
  197. package/src/modules/primitives/command/setReferenceUnit.ts +46 -59
  198. package/src/modules/primitives/db/unit.ts +13 -3
  199. package/src/modules/primitives/docs/commands/ActivateCategory.md +1 -2
  200. package/src/modules/primitives/docs/commands/ActivateCurrency.md +1 -2
  201. package/src/modules/primitives/docs/commands/ActivateUnit.md +1 -2
  202. package/src/modules/primitives/docs/commands/CreateCategory.md +1 -4
  203. package/src/modules/primitives/docs/commands/CreateCurrency.md +3 -4
  204. package/src/modules/primitives/docs/commands/CreateExchangeRate.md +4 -5
  205. package/src/modules/primitives/docs/commands/CreateUnit.md +5 -5
  206. package/src/modules/primitives/docs/commands/DeactivateCategory.md +2 -3
  207. package/src/modules/primitives/docs/commands/DeactivateCurrency.md +2 -3
  208. package/src/modules/primitives/docs/commands/DeactivateUnit.md +2 -3
  209. package/src/modules/primitives/docs/commands/SetBaseCurrency.md +2 -3
  210. package/src/modules/primitives/docs/commands/SetReferenceUnit.md +2 -3
  211. package/src/modules/primitives/docs/queries/ConvertAmount.md +3 -5
  212. package/src/modules/primitives/docs/queries/ConvertQuantity.md +3 -5
  213. package/src/modules/primitives/docs/queries/GetBaseCurrency.md +32 -0
  214. package/src/modules/primitives/docs/queries/GetCurrency.md +36 -0
  215. package/src/modules/primitives/docs/queries/GetUnit.md +36 -0
  216. package/src/modules/primitives/docs/queries/GetUoMCategory.md +36 -0
  217. package/src/modules/primitives/docs/queries/ListUnitsByCategory.md +26 -0
  218. package/src/modules/primitives/generated/kysely-tailordb.ts +24 -45
  219. package/src/modules/primitives/index.ts +15 -4
  220. package/src/modules/primitives/lib/errors.generated.ts +112 -0
  221. package/src/modules/primitives/{permissions.ts → lib/permissions.generated.ts} +9 -8
  222. package/src/modules/primitives/module.ts +37 -27
  223. package/src/modules/primitives/query/convertAmount.generated.ts +5 -0
  224. package/src/modules/primitives/query/convertAmount.test.ts +2 -2
  225. package/src/modules/primitives/query/convertAmount.ts +27 -28
  226. package/src/modules/primitives/query/convertQuantity.generated.ts +5 -0
  227. package/src/modules/primitives/query/convertQuantity.test.ts +6 -2
  228. package/src/modules/primitives/query/convertQuantity.ts +49 -57
  229. package/src/modules/primitives/query/getBaseCurrency.generated.ts +5 -0
  230. package/src/modules/primitives/query/getBaseCurrency.test.ts +28 -0
  231. package/src/modules/primitives/query/getBaseCurrency.ts +16 -0
  232. package/src/modules/primitives/query/getCurrency.generated.ts +5 -0
  233. package/src/modules/primitives/query/getCurrency.test.ts +47 -0
  234. package/src/modules/primitives/query/getCurrency.ts +18 -0
  235. package/src/modules/primitives/query/getUnit.generated.ts +5 -0
  236. package/src/modules/primitives/query/getUnit.test.ts +47 -0
  237. package/src/modules/primitives/query/getUnit.ts +18 -0
  238. package/src/modules/primitives/query/getUoMCategory.generated.ts +5 -0
  239. package/src/modules/primitives/query/getUoMCategory.test.ts +47 -0
  240. package/src/modules/primitives/query/getUoMCategory.ts +18 -0
  241. package/src/modules/primitives/query/listUnitsByCategory.generated.ts +5 -0
  242. package/src/modules/primitives/query/listUnitsByCategory.ts +16 -0
  243. package/src/modules/primitives/tailor.config.ts +3 -3
  244. package/src/modules/shared/defineCommand.test.ts +23 -10
  245. package/src/modules/shared/defineCommand.ts +23 -10
  246. package/src/modules/shared/internal.ts +1 -0
  247. package/src/modules/shared/requirePermission.test.ts +22 -21
  248. package/src/modules/shared/requirePermission.ts +8 -2
  249. package/src/modules/shared/result.ts +12 -0
  250. package/src/modules/testing/index.ts +36 -11
  251. package/src/modules/user-management/command/activateUser.generated.ts +6 -0
  252. package/src/modules/user-management/command/activateUser.test.ts +27 -27
  253. package/src/modules/user-management/command/activateUser.ts +40 -48
  254. package/src/modules/user-management/command/assignPermissionToRole.generated.ts +6 -0
  255. package/src/modules/user-management/command/assignPermissionToRole.test.ts +42 -43
  256. package/src/modules/user-management/command/assignPermissionToRole.ts +59 -62
  257. package/src/modules/user-management/command/assignRoleToUser.generated.ts +6 -0
  258. package/src/modules/user-management/command/assignRoleToUser.test.ts +70 -63
  259. package/src/modules/user-management/command/assignRoleToUser.ts +63 -66
  260. package/src/modules/user-management/command/createPermission.generated.ts +6 -0
  261. package/src/modules/user-management/command/createPermission.test.ts +45 -38
  262. package/src/modules/user-management/command/createPermission.ts +42 -46
  263. package/src/modules/user-management/command/createRole.generated.ts +6 -0
  264. package/src/modules/user-management/command/createRole.test.ts +30 -29
  265. package/src/modules/user-management/command/createRole.ts +33 -33
  266. package/src/modules/user-management/command/createUser.generated.ts +6 -0
  267. package/src/modules/user-management/command/createUser.test.ts +64 -42
  268. package/src/modules/user-management/command/createUser.ts +54 -56
  269. package/src/modules/user-management/command/deactivateUser.generated.ts +6 -0
  270. package/src/modules/user-management/command/deactivateUser.test.ts +27 -27
  271. package/src/modules/user-management/command/deactivateUser.ts +40 -48
  272. package/src/modules/user-management/command/logAuditEvent.generated.ts +6 -0
  273. package/src/modules/user-management/command/logAuditEvent.test.ts +50 -42
  274. package/src/modules/user-management/command/logAuditEvent.ts +25 -28
  275. package/src/modules/user-management/command/reactivateUser.generated.ts +6 -0
  276. package/src/modules/user-management/command/reactivateUser.test.ts +31 -27
  277. package/src/modules/user-management/command/reactivateUser.ts +40 -48
  278. package/src/modules/user-management/command/revokePermissionFromRole.generated.ts +6 -0
  279. package/src/modules/user-management/command/revokePermissionFromRole.test.ts +52 -51
  280. package/src/modules/user-management/command/revokePermissionFromRole.ts +60 -57
  281. package/src/modules/user-management/command/revokeRoleFromUser.generated.ts +6 -0
  282. package/src/modules/user-management/command/revokeRoleFromUser.test.ts +53 -48
  283. package/src/modules/user-management/command/revokeRoleFromUser.ts +58 -57
  284. package/src/modules/user-management/docs/commands/CreatePermission.md +2 -2
  285. package/src/modules/user-management/docs/commands/CreateRole.md +1 -1
  286. package/src/modules/user-management/generated/enums.ts +11 -11
  287. package/src/modules/user-management/generated/kysely-tailordb.ts +27 -56
  288. package/src/modules/user-management/index.ts +2 -2
  289. package/src/modules/user-management/lib/errors.generated.ts +67 -0
  290. package/src/modules/user-management/{permissions.ts → lib/permissions.generated.ts} +8 -7
  291. package/src/modules/user-management/module.ts +22 -22
  292. package/src/modules/user-management/tailor.config.ts +3 -3
  293. package/src/schemas.ts +1 -1
  294. package/skills/1-module-docs/references/structure.md +0 -22
  295. package/skills/2-module-feature-breakdown/references/commands.md +0 -48
  296. package/skills/2-module-feature-breakdown/references/structure.md +0 -22
  297. package/skills/3-module-doc-review/references/commands.md +0 -54
  298. package/skills/3-module-doc-review/references/models.md +0 -29
  299. package/skills/4-module-tdd-implementation/SKILL.md +0 -74
  300. package/skills/4-module-tdd-implementation/references/commands.md +0 -45
  301. package/skills/4-module-tdd-implementation/references/errors.md +0 -7
  302. package/skills/4-module-tdd-implementation/references/models.md +0 -30
  303. package/skills/4-module-tdd-implementation/references/structure.md +0 -22
  304. package/skills/4-module-tdd-implementation/references/testing.md +0 -37
  305. package/skills/5-module-implementation-review/references/commands.md +0 -45
  306. package/skills/5-module-implementation-review/references/errors.md +0 -7
  307. package/skills/5-module-implementation-review/references/exports.md +0 -8
  308. package/skills/5-module-implementation-review/references/models.md +0 -30
  309. package/skills/app-compose-1-requirement-analysis/references/structure.md +0 -27
  310. package/skills/app-compose-2-requirements-breakdown/references/screen-detailview.md +0 -106
  311. package/skills/app-compose-2-requirements-breakdown/references/screen-form.md +0 -139
  312. package/skills/app-compose-2-requirements-breakdown/references/screen-listview.md +0 -153
  313. package/skills/app-compose-2-requirements-breakdown/references/structure.md +0 -27
  314. package/skills/app-compose-3-doc-review/references/structure.md +0 -27
  315. package/skills/app-compose-4-design-mock/SKILL.md +0 -256
  316. package/skills/app-compose-4-design-mock/references/component.md +0 -50
  317. package/skills/app-compose-4-design-mock/references/screen-detailview.md +0 -106
  318. package/skills/app-compose-4-design-mock/references/screen-form.md +0 -139
  319. package/skills/app-compose-4-design-mock/references/screen-listview.md +0 -153
  320. package/skills/app-compose-4-design-mock/references/structure.md +0 -27
  321. package/skills/app-compose-5-design-mock-review/SKILL.md +0 -290
  322. package/skills/app-compose-5-design-mock-review/references/component.md +0 -50
  323. package/skills/app-compose-5-design-mock-review/references/screen-detailview.md +0 -106
  324. package/skills/app-compose-5-design-mock-review/references/screen-form.md +0 -139
  325. package/skills/app-compose-5-design-mock-review/references/screen-listview.md +0 -153
  326. package/skills/app-compose-6-implementation-spec/references/auth.md +0 -72
  327. package/skills/app-compose-6-implementation-spec/references/structure.md +0 -27
  328. package/src/modules/primitives/lib/errors.ts +0 -138
  329. package/src/modules/user-management/lib/errors.ts +0 -81
  330. /package/skills/{2-module-feature-breakdown → erp-kit-module-4-tdd}/references/models.md +0 -0
@@ -1,15 +1,10 @@
1
1
  import { describe, expect, it } from "vitest";
2
- import {
3
- createMockDb,
4
- testNotFound,
5
- testPermissionDenied,
6
- testIdempotent,
7
- } from "../../testing/index";
2
+ import { createMockDb, testNotFound, testIdempotent } from "../../testing/index";
8
3
  import { type CommandContext } from "../../shared/internal";
9
4
  import { DB } from "../generated/kysely-tailordb";
10
- import { CannotDeactivateBaseCurrencyError, CurrencyNotFoundError } from "../lib/errors";
5
+ import { CannotDeactivateBaseCurrencyError, CurrencyNotFoundError } from "../lib/errors.generated";
11
6
  import { baseCurrencyEUR, baseCurrencyUSD, inactiveCurrency } from "../testing/fixtures";
12
- import { deactivateCurrency } from "./deactivateCurrency";
7
+ import { run } from "./deactivateCurrency";
13
8
 
14
9
  describe("deactivateCurrency", () => {
15
10
  const ctx: CommandContext = {
@@ -19,38 +14,30 @@ describe("deactivateCurrency", () => {
19
14
 
20
15
  it(
21
16
  "throws when currency doesn't exist",
22
- testNotFound(
23
- deactivateCurrency,
24
- { currencyId: "nonexistent-currency" },
25
- ctx,
26
- CurrencyNotFoundError,
27
- ),
17
+ testNotFound(run, { currencyId: "nonexistent-currency" }, ctx, CurrencyNotFoundError),
28
18
  );
29
19
 
30
20
  it("throws when attempting to deactivate base currency", async () => {
31
21
  const { db, spies } = createMockDb<DB>();
32
22
  spies.select.mockReturnValue(baseCurrencyUSD); // USD is base currency
33
23
 
34
- await expect(
35
- deactivateCurrency(
36
- db,
37
- {
38
- currencyId: baseCurrencyUSD.id,
39
- },
40
- ctx,
41
- ),
42
- ).rejects.toBeInstanceOf(CannotDeactivateBaseCurrencyError);
24
+ const result = await run(
25
+ db,
26
+ {
27
+ currencyId: baseCurrencyUSD.id,
28
+ },
29
+ ctx,
30
+ );
31
+
32
+ expect(result.ok).toBe(false);
33
+ if (!result.ok) {
34
+ expect(result.error).toBeInstanceOf(CannotDeactivateBaseCurrencyError);
35
+ }
43
36
  });
44
37
 
45
38
  it(
46
39
  "returns currency unchanged when already inactive",
47
- testIdempotent(
48
- deactivateCurrency,
49
- { currencyId: inactiveCurrency.id },
50
- ctx,
51
- inactiveCurrency,
52
- "currency",
53
- ),
40
+ testIdempotent(run, { currencyId: inactiveCurrency.id }, ctx, inactiveCurrency, "currency"),
54
41
  );
55
42
 
56
43
  // Success cases
@@ -65,7 +52,7 @@ describe("deactivateCurrency", () => {
65
52
  spies.select.mockReturnValue(baseCurrencyEUR); // EUR is not base currency
66
53
  spies.update.mockReturnValue(deactivatedCurrency);
67
54
 
68
- const result = await deactivateCurrency(
55
+ const result = await run(
69
56
  db,
70
57
  {
71
58
  currencyId: baseCurrencyEUR.id,
@@ -73,13 +60,11 @@ describe("deactivateCurrency", () => {
73
60
  ctx,
74
61
  );
75
62
 
76
- expect(result.currency.isActive).toBe(false);
77
- expect(result.currency.updatedAt).not.toBeNull();
63
+ expect(result.ok).toBe(true);
64
+ if (result.ok) {
65
+ expect(result.value.currency.isActive).toBe(false);
66
+ expect(result.value.currency.updatedAt).not.toBeNull();
67
+ }
78
68
  expect(spies.update).toHaveBeenCalled();
79
69
  });
80
-
81
- it(
82
- "throws when permission is missing",
83
- testPermissionDenied(deactivateCurrency, { currencyId: "cur-1" }),
84
- );
85
70
  });
@@ -1,7 +1,7 @@
1
- import { defineCommand } from "../../shared/internal";
1
+ import { ok, err, type CommandContext } from "../../shared/internal";
2
2
  import { DB } from "../generated/kysely-tailordb";
3
- import { CannotDeactivateBaseCurrencyError, CurrencyNotFoundError } from "../lib/errors";
4
- import { permissions } from "../permissions";
3
+ import { CannotDeactivateBaseCurrencyError, CurrencyNotFoundError } from "../lib/errors.generated";
4
+ import { getCurrency } from "../query/getCurrency.generated";
5
5
 
6
6
  export interface DeactivateCurrencyInput {
7
7
  currencyId: string;
@@ -13,43 +13,36 @@ export interface DeactivateCurrencyInput {
13
13
  * Disables a currency from being used in new transactions while preserving
14
14
  * historical data. Base currency cannot be deactivated.
15
15
  */
16
- export const deactivateCurrency = defineCommand(
17
- permissions.deactivateCurrency,
18
- async (db: DB, input: DeactivateCurrencyInput) => {
19
- // 1. Find currency by ID
20
- const currency = await db
21
- .selectFrom("Currency")
22
- .selectAll()
23
- .where("id", "=", input.currencyId)
24
- .executeTakeFirst();
16
+ export async function run(db: DB, input: DeactivateCurrencyInput, ctx: CommandContext) {
17
+ // 1. Find currency by ID
18
+ const { currency } = await getCurrency(db, { id: input.currencyId }, ctx);
25
19
 
26
- // 2. If not found, throw error
27
- if (!currency) {
28
- throw new CurrencyNotFoundError(input.currencyId);
29
- }
20
+ // 2. If not found, throw error
21
+ if (!currency) {
22
+ return err(new CurrencyNotFoundError(input.currencyId));
23
+ }
30
24
 
31
- // 3. Check if base currency
32
- if (currency.isBaseCurrency) {
33
- throw new CannotDeactivateBaseCurrencyError(input.currencyId);
34
- }
25
+ // 3. Check if base currency
26
+ if (currency.isBaseCurrency) {
27
+ return err(new CannotDeactivateBaseCurrencyError(input.currencyId));
28
+ }
35
29
 
36
- // 4. If already inactive, return currency (idempotent)
37
- if (!currency.isActive) {
38
- return { currency };
39
- }
30
+ // 4. If already inactive, return currency (idempotent)
31
+ if (!currency.isActive) {
32
+ return ok({ currency });
33
+ }
40
34
 
41
- // 5. Update isActive = false
42
- const updatedCurrency = await db
43
- .updateTable("Currency")
44
- .set({
45
- isActive: false,
46
- updatedAt: new Date(),
47
- })
48
- .where("id", "=", input.currencyId)
49
- .returningAll()
50
- .executeTakeFirst();
35
+ // 5. Update isActive = false
36
+ const updatedCurrency = await db
37
+ .updateTable("Currency")
38
+ .set({
39
+ isActive: false,
40
+ updatedAt: new Date(),
41
+ })
42
+ .where("id", "=", input.currencyId)
43
+ .returningAll()
44
+ .executeTakeFirst();
51
45
 
52
- // 6. Return updated currency
53
- return { currency: updatedCurrency! };
54
- },
55
- );
46
+ // 6. Return updated currency
47
+ return ok({ currency: updatedCurrency! });
48
+ }
@@ -0,0 +1,6 @@
1
+ // @generated — do not edit
2
+ import { defineCommand } from "../../shared/internal";
3
+ import { permissions } from "../lib/permissions.generated";
4
+ import { run } from "./deactivateUnit";
5
+
6
+ export const deactivateUnit = defineCommand(permissions.deactivateUnit, run);
@@ -1,32 +1,35 @@
1
1
  import { describe, expect, it } from "vitest";
2
- import { createMockDb, testNotFound, testPermissionDenied } from "../../testing/index";
2
+ import { createMockDb, testNotFound } from "../../testing/index";
3
3
  import { type CommandContext } from "../../shared/internal";
4
4
  import { DB } from "../generated/kysely-tailordb";
5
- import { CannotDeactivateReferenceUnitError, UnitNotFoundError } from "../lib/errors";
5
+ import { CannotDeactivateReferenceUnitError, UnitNotFoundError } from "../lib/errors.generated";
6
6
  import { baseUnitKg, baseUnitGram, baseUoMCategory, inactiveUnit } from "../testing/fixtures";
7
- import { deactivateUnit } from "./deactivateUnit";
7
+ import { run } from "./deactivateUnit";
8
8
 
9
9
  describe("deactivateUnit", () => {
10
10
  const ctx: CommandContext = { actorId: "test-actor", permissions: ["primitives:deactivateUnit"] };
11
11
 
12
12
  it(
13
13
  "throws when unit doesn't exist",
14
- testNotFound(deactivateUnit, { unitId: "nonexistent-unit" }, ctx, UnitNotFoundError),
14
+ testNotFound(run, { unitId: "nonexistent-unit" }, ctx, UnitNotFoundError),
15
15
  );
16
16
 
17
17
  it("throws when attempting to deactivate reference unit", async () => {
18
18
  const { db, spies } = createMockDb<DB>();
19
19
  spies.select.mockReturnValueOnce(baseUnitKg).mockReturnValueOnce(baseUoMCategory);
20
20
 
21
- await expect(
22
- deactivateUnit(
23
- db,
24
- {
25
- unitId: baseUnitKg.id,
26
- },
27
- ctx,
28
- ),
29
- ).rejects.toBeInstanceOf(CannotDeactivateReferenceUnitError);
21
+ const result = await run(
22
+ db,
23
+ {
24
+ unitId: baseUnitKg.id,
25
+ },
26
+ ctx,
27
+ );
28
+
29
+ expect(result.ok).toBe(false);
30
+ if (!result.ok) {
31
+ expect(result.error).toBeInstanceOf(CannotDeactivateReferenceUnitError);
32
+ }
30
33
  });
31
34
 
32
35
  // Idempotent case needs multi-mock setup, kept inline
@@ -34,7 +37,7 @@ describe("deactivateUnit", () => {
34
37
  const { db, spies } = createMockDb<DB>();
35
38
  spies.select.mockReturnValueOnce(inactiveUnit).mockReturnValueOnce(baseUoMCategory);
36
39
 
37
- const result = await deactivateUnit(
40
+ const result = await run(
38
41
  db,
39
42
  {
40
43
  unitId: inactiveUnit.id,
@@ -42,7 +45,10 @@ describe("deactivateUnit", () => {
42
45
  ctx,
43
46
  );
44
47
 
45
- expect(result.unit).toEqual(inactiveUnit);
48
+ expect(result.ok).toBe(true);
49
+ if (result.ok) {
50
+ expect(result.value.unit).toEqual(inactiveUnit);
51
+ }
46
52
  expect(spies.update).not.toHaveBeenCalled();
47
53
  });
48
54
 
@@ -58,7 +64,7 @@ describe("deactivateUnit", () => {
58
64
  spies.select.mockReturnValueOnce(baseUnitGram).mockReturnValueOnce(baseUoMCategory);
59
65
  spies.update.mockReturnValue(deactivatedUnit);
60
66
 
61
- const result = await deactivateUnit(
67
+ const result = await run(
62
68
  db,
63
69
  {
64
70
  unitId: baseUnitGram.id,
@@ -66,13 +72,11 @@ describe("deactivateUnit", () => {
66
72
  ctx,
67
73
  );
68
74
 
69
- expect(result.unit.isActive).toBe(false);
70
- expect(result.unit.updatedAt).not.toBeNull();
75
+ expect(result.ok).toBe(true);
76
+ if (result.ok) {
77
+ expect(result.value.unit.isActive).toBe(false);
78
+ expect(result.value.unit.updatedAt).not.toBeNull();
79
+ }
71
80
  expect(spies.update).toHaveBeenCalled();
72
81
  });
73
-
74
- it(
75
- "throws when permission is missing",
76
- testPermissionDenied(deactivateUnit, { unitId: "unit-1" }),
77
- );
78
82
  });
@@ -1,7 +1,8 @@
1
- import { defineCommand } from "../../shared/internal";
1
+ import { ok, err, type CommandContext } from "../../shared/internal";
2
2
  import { DB } from "../generated/kysely-tailordb";
3
- import { CannotDeactivateReferenceUnitError, UnitNotFoundError } from "../lib/errors";
4
- import { permissions } from "../permissions";
3
+ import { CannotDeactivateReferenceUnitError, UnitNotFoundError } from "../lib/errors.generated";
4
+ import { getUnit } from "../query/getUnit.generated";
5
+ import { getUoMCategory } from "../query/getUoMCategory.generated";
5
6
 
6
7
  export interface DeactivateUnitInput {
7
8
  unitId: string;
@@ -14,49 +15,38 @@ export interface DeactivateUnitInput {
14
15
  * and quantity conversions while preserving all historical data.
15
16
  * Reference units cannot be deactivated.
16
17
  */
17
- export const deactivateUnit = defineCommand(
18
- permissions.deactivateUnit,
19
- async (db: DB, input: DeactivateUnitInput) => {
20
- // 1. Find unit by ID
21
- const unit = await db
22
- .selectFrom("Unit")
23
- .selectAll()
24
- .where("id", "=", input.unitId)
25
- .executeTakeFirst();
26
-
27
- // 2. If not found, throw error
28
- if (!unit) {
29
- throw new UnitNotFoundError(input.unitId);
30
- }
31
-
32
- // 3. Check if unit is reference unit for its category
33
- const category = await db
34
- .selectFrom("UoMCategory")
35
- .selectAll()
36
- .where("id", "=", unit.categoryId)
37
- .executeTakeFirst();
38
-
39
- if (category?.referenceUnitId === unit.id) {
40
- throw new CannotDeactivateReferenceUnitError(input.unitId);
41
- }
42
-
43
- // 4. If already inactive, return unit (idempotent)
44
- if (!unit.isActive) {
45
- return { unit };
46
- }
47
-
48
- // 5. Update isActive = false
49
- const updatedUnit = await db
50
- .updateTable("Unit")
51
- .set({
52
- isActive: false,
53
- updatedAt: new Date(),
54
- })
55
- .where("id", "=", input.unitId)
56
- .returningAll()
57
- .executeTakeFirst();
58
-
59
- // 6. Return updated unit
60
- return { unit: updatedUnit! };
61
- },
62
- );
18
+ export async function run(db: DB, input: DeactivateUnitInput, ctx: CommandContext) {
19
+ // 1. Find unit by ID
20
+ const { unit } = await getUnit(db, { id: input.unitId }, ctx);
21
+
22
+ // 2. If not found, throw error
23
+ if (!unit) {
24
+ return err(new UnitNotFoundError(input.unitId));
25
+ }
26
+
27
+ // 3. Check if unit is reference unit for its category
28
+ const { uoMCategory } = await getUoMCategory(db, { id: unit.categoryId }, ctx);
29
+
30
+ if (uoMCategory?.referenceUnitId === unit.id) {
31
+ return err(new CannotDeactivateReferenceUnitError(input.unitId));
32
+ }
33
+
34
+ // 4. If already inactive, return unit (idempotent)
35
+ if (!unit.isActive) {
36
+ return ok({ unit });
37
+ }
38
+
39
+ // 5. Update isActive = false
40
+ const updatedUnit = await db
41
+ .updateTable("Unit")
42
+ .set({
43
+ isActive: false,
44
+ updatedAt: new Date(),
45
+ })
46
+ .where("id", "=", input.unitId)
47
+ .returningAll()
48
+ .executeTakeFirst();
49
+
50
+ // 6. Return updated unit
51
+ return ok({ unit: updatedUnit! });
52
+ }
@@ -0,0 +1,6 @@
1
+ // @generated — do not edit
2
+ import { defineCommand } from "../../shared/internal";
3
+ import { permissions } from "../lib/permissions.generated";
4
+ import { run } from "./setBaseCurrency";
5
+
6
+ export const setBaseCurrency = defineCommand(permissions.setBaseCurrency, run);
@@ -1,10 +1,13 @@
1
1
  import { describe, expect, it } from "vitest";
2
- import { InsufficientPermissionError, type CommandContext } from "../../shared/internal";
2
+ import { type CommandContext } from "../../shared/internal";
3
3
  import { createMockDb } from "../../testing/index";
4
4
  import { DB } from "../generated/kysely-tailordb";
5
- import { CannotSetInactiveAsBaseCurrencyError, CurrencyNotFoundError } from "../lib/errors";
5
+ import {
6
+ CannotSetInactiveAsBaseCurrencyError,
7
+ CurrencyNotFoundError,
8
+ } from "../lib/errors.generated";
6
9
  import { baseCurrencyEUR, baseCurrencyUSD, inactiveCurrency } from "../testing/fixtures";
7
- import { setBaseCurrency } from "./setBaseCurrency";
10
+ import { run } from "./setBaseCurrency";
8
11
 
9
12
  describe("setBaseCurrency", () => {
10
13
  const ctx: CommandContext = {
@@ -17,30 +20,36 @@ describe("setBaseCurrency", () => {
17
20
  const { db, spies } = createMockDb<DB>();
18
21
  spies.select.mockReturnValue(undefined);
19
22
 
20
- await expect(
21
- setBaseCurrency(
22
- db,
23
- {
24
- currencyId: "nonexistent-currency",
25
- },
26
- ctx,
27
- ),
28
- ).rejects.toBeInstanceOf(CurrencyNotFoundError);
23
+ const result = await run(
24
+ db,
25
+ {
26
+ currencyId: "nonexistent-currency",
27
+ },
28
+ ctx,
29
+ );
30
+
31
+ expect(result.ok).toBe(false);
32
+ if (!result.ok) {
33
+ expect(result.error).toBeInstanceOf(CurrencyNotFoundError);
34
+ }
29
35
  });
30
36
 
31
37
  it("throws when currency is inactive", async () => {
32
38
  const { db, spies } = createMockDb<DB>();
33
39
  spies.select.mockReturnValue(inactiveCurrency);
34
40
 
35
- await expect(
36
- setBaseCurrency(
37
- db,
38
- {
39
- currencyId: inactiveCurrency.id,
40
- },
41
- ctx,
42
- ),
43
- ).rejects.toBeInstanceOf(CannotSetInactiveAsBaseCurrencyError);
41
+ const result = await run(
42
+ db,
43
+ {
44
+ currencyId: inactiveCurrency.id,
45
+ },
46
+ ctx,
47
+ );
48
+
49
+ expect(result.ok).toBe(false);
50
+ if (!result.ok) {
51
+ expect(result.error).toBeInstanceOf(CannotSetInactiveAsBaseCurrencyError);
52
+ }
44
53
  });
45
54
 
46
55
  // Idempotent cases
@@ -48,7 +57,7 @@ describe("setBaseCurrency", () => {
48
57
  const { db, spies } = createMockDb<DB>();
49
58
  spies.select.mockReturnValue(baseCurrencyUSD); // Already base currency
50
59
 
51
- const result = await setBaseCurrency(
60
+ const result = await run(
52
61
  db,
53
62
  {
54
63
  currencyId: baseCurrencyUSD.id,
@@ -56,7 +65,10 @@ describe("setBaseCurrency", () => {
56
65
  ctx,
57
66
  );
58
67
 
59
- expect(result.currency).toEqual(baseCurrencyUSD);
68
+ expect(result.ok).toBe(true);
69
+ if (result.ok) {
70
+ expect(result.value.currency).toEqual(baseCurrencyUSD);
71
+ }
60
72
  expect(spies.update).not.toHaveBeenCalled();
61
73
  });
62
74
 
@@ -76,7 +88,7 @@ describe("setBaseCurrency", () => {
76
88
  .mockReturnValueOnce({ ...baseCurrencyUSD, isBaseCurrency: false }) // Remove base from old
77
89
  .mockReturnValueOnce(newBaseCurrency); // Set base on new
78
90
 
79
- const result = await setBaseCurrency(
91
+ const result = await run(
80
92
  db,
81
93
  {
82
94
  currencyId: baseCurrencyEUR.id,
@@ -84,15 +96,10 @@ describe("setBaseCurrency", () => {
84
96
  ctx,
85
97
  );
86
98
 
87
- expect(result.currency.isBaseCurrency).toBe(true);
99
+ expect(result.ok).toBe(true);
100
+ if (result.ok) {
101
+ expect(result.value.currency.isBaseCurrency).toBe(true);
102
+ }
88
103
  expect(spies.update).toHaveBeenCalled();
89
104
  });
90
-
91
- it("throws when permission is missing", async () => {
92
- const { db } = createMockDb<DB>();
93
- const denied: CommandContext = { actorId: "test-actor", permissions: [] };
94
- await expect(setBaseCurrency(db, { currencyId: "cur-1" }, denied)).rejects.toBeInstanceOf(
95
- InsufficientPermissionError,
96
- );
97
- });
98
105
  });
@@ -1,7 +1,11 @@
1
- import { defineCommand } from "../../shared/internal";
1
+ import { ok, err, type CommandContext } from "../../shared/internal";
2
2
  import { DB } from "../generated/kysely-tailordb";
3
- import { CannotSetInactiveAsBaseCurrencyError, CurrencyNotFoundError } from "../lib/errors";
4
- import { permissions } from "../permissions";
3
+ import {
4
+ CannotSetInactiveAsBaseCurrencyError,
5
+ CurrencyNotFoundError,
6
+ } from "../lib/errors.generated";
7
+ import { getCurrency } from "../query/getCurrency.generated";
8
+ import { getBaseCurrency } from "../query/getBaseCurrency.generated";
5
9
 
6
10
  export interface SetBaseCurrencyInput {
7
11
  currencyId: string;
@@ -13,62 +17,51 @@ export interface SetBaseCurrencyInput {
13
17
  * Changes the organization's base currency to a different active currency.
14
18
  * The base currency serves as the default for financial reporting.
15
19
  */
16
- export const setBaseCurrency = defineCommand(
17
- permissions.setBaseCurrency,
18
- async (db: DB, input: SetBaseCurrencyInput) => {
19
- // 1. Find currency by ID
20
- const currency = await db
21
- .selectFrom("Currency")
22
- .selectAll()
23
- .where("id", "=", input.currencyId)
24
- .executeTakeFirst();
25
-
26
- // 2. If not found, throw error
27
- if (!currency) {
28
- throw new CurrencyNotFoundError(input.currencyId);
29
- }
20
+ export async function run(db: DB, input: SetBaseCurrencyInput, ctx: CommandContext) {
21
+ // 1. Find currency by ID
22
+ const { currency } = await getCurrency(db, { id: input.currencyId }, ctx);
30
23
 
31
- // 3. Check if currency is active
32
- if (!currency.isActive) {
33
- throw new CannotSetInactiveAsBaseCurrencyError(input.currencyId);
34
- }
24
+ // 2. If not found, throw error
25
+ if (!currency) {
26
+ return err(new CurrencyNotFoundError(input.currencyId));
27
+ }
35
28
 
36
- // 4. If already base currency, return (idempotent)
37
- if (currency.isBaseCurrency) {
38
- return { currency };
39
- }
29
+ // 3. Check if currency is active
30
+ if (!currency.isActive) {
31
+ return err(new CannotSetInactiveAsBaseCurrencyError(input.currencyId));
32
+ }
40
33
 
41
- // 5. Find current base currency
42
- const currentBase = await db
43
- .selectFrom("Currency")
44
- .selectAll()
45
- .where("isBaseCurrency", "=", true)
46
- .executeTakeFirst();
34
+ // 4. If already base currency, return (idempotent)
35
+ if (currency.isBaseCurrency) {
36
+ return ok({ currency });
37
+ }
47
38
 
48
- // 6. Remove base flag from current base
49
- if (currentBase) {
50
- await db
51
- .updateTable("Currency")
52
- .set({
53
- isBaseCurrency: false,
54
- updatedAt: new Date(),
55
- })
56
- .where("id", "=", currentBase.id)
57
- .returningAll()
58
- .executeTakeFirst();
59
- }
39
+ // 5. Find current base currency
40
+ const { currency: currentBase } = await getBaseCurrency(db, undefined, ctx);
60
41
 
61
- // 7. Set base flag on target currency
62
- const updatedCurrency = await db
42
+ // 6. Remove base flag from current base
43
+ if (currentBase) {
44
+ await db
63
45
  .updateTable("Currency")
64
46
  .set({
65
- isBaseCurrency: true,
47
+ isBaseCurrency: false,
66
48
  updatedAt: new Date(),
67
49
  })
68
- .where("id", "=", input.currencyId)
50
+ .where("id", "=", currentBase.id)
69
51
  .returningAll()
70
52
  .executeTakeFirst();
53
+ }
71
54
 
72
- return { currency: updatedCurrency! };
73
- },
74
- );
55
+ // 7. Set base flag on target currency
56
+ const updatedCurrency = await db
57
+ .updateTable("Currency")
58
+ .set({
59
+ isBaseCurrency: true,
60
+ updatedAt: new Date(),
61
+ })
62
+ .where("id", "=", input.currencyId)
63
+ .returningAll()
64
+ .executeTakeFirst();
65
+
66
+ return ok({ currency: updatedCurrency! });
67
+ }
@@ -0,0 +1,6 @@
1
+ // @generated — do not edit
2
+ import { defineCommand } from "../../shared/internal";
3
+ import { permissions } from "../lib/permissions.generated";
4
+ import { run } from "./setReferenceUnit";
5
+
6
+ export const setReferenceUnit = defineCommand(permissions.setReferenceUnit, run);