@tailor-platform/erp-kit 0.1.2 → 0.2.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 (325) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +81 -12
  3. package/dist/cli.js +1070 -450
  4. package/package.json +11 -8
  5. package/schemas/module/model.yml +5 -0
  6. package/skills/{app-compose-1-requirement-analysis → erp-kit-app-1-requirements}/SKILL.md +2 -2
  7. package/skills/{app-compose-2-requirements-breakdown → erp-kit-app-2-breakdown}/SKILL.md +3 -3
  8. package/skills/{app-compose-3-doc-review → erp-kit-app-3-doc-review}/SKILL.md +2 -2
  9. package/skills/{app-compose-4-design-mock → erp-kit-app-4-design}/SKILL.md +3 -3
  10. package/skills/{app-compose-5-design-mock-review → erp-kit-app-5-design-review}/SKILL.md +4 -4
  11. package/skills/{app-compose-6-implementation-spec → erp-kit-app-6-impl-spec}/SKILL.md +3 -3
  12. package/skills/{mock-scenario → erp-kit-mock-scenario}/SKILL.md +1 -1
  13. package/skills/{1-module-docs → erp-kit-module-1-docs}/SKILL.md +2 -2
  14. package/skills/{2-module-feature-breakdown → erp-kit-module-2-feature-breakdown}/SKILL.md +13 -9
  15. package/skills/erp-kit-module-2-feature-breakdown/references/naming.md +59 -0
  16. package/skills/{3-module-doc-review → erp-kit-module-3-doc-review}/SKILL.md +83 -25
  17. package/skills/erp-kit-module-4-tdd/SKILL.md +94 -0
  18. package/skills/erp-kit-module-4-tdd/references/cross-module-dependency.md +133 -0
  19. package/skills/{4-module-tdd-implementation → erp-kit-module-4-tdd}/references/db-relations.md +5 -1
  20. package/skills/{4-module-tdd-implementation → erp-kit-module-4-tdd}/references/exports.md +1 -1
  21. package/skills/erp-kit-module-4-tdd/references/generated-code.md +32 -0
  22. package/skills/{5-module-implementation-review → erp-kit-module-5-impl-review}/SKILL.md +46 -44
  23. package/skills/erp-kit-module-5-impl-review/references/commands.md +62 -0
  24. package/skills/erp-kit-module-5-impl-review/references/errors.md +10 -0
  25. package/skills/{5-module-implementation-review → erp-kit-module-5-impl-review}/references/testing.md +1 -1
  26. package/skills/erp-kit-module-shared/SKILL.md +16 -0
  27. package/skills/erp-kit-module-shared/references/commands.md +203 -0
  28. package/skills/erp-kit-module-shared/references/errors.md +35 -0
  29. package/skills/erp-kit-module-shared/references/queries.md +168 -0
  30. package/skills/erp-kit-module-shared/references/structure.md +36 -0
  31. package/skills/{3-module-doc-review → erp-kit-module-shared}/references/testing.md +4 -3
  32. package/skills/erp-kit-update/SKILL.md +64 -0
  33. package/src/cli.doc.test.ts +65 -0
  34. package/src/cli.ts +3 -35
  35. package/src/commands/app/index.ts +3 -3
  36. package/src/commands/check.test.ts +1 -1
  37. package/src/commands/check.ts +2 -2
  38. package/src/commands/index.ts +73 -0
  39. package/src/commands/init.test.ts +22 -5
  40. package/src/commands/init.ts +25 -16
  41. package/src/commands/license.ts +193 -0
  42. package/src/commands/mock/index.ts +2 -2
  43. package/src/commands/mock/start.ts +1 -1
  44. package/src/commands/mock/validate.test.ts +1 -1
  45. package/src/commands/module/generate.ts +35 -0
  46. package/src/commands/module/index.ts +6 -4
  47. package/src/commands/module/list.test.ts +7 -12
  48. package/src/commands/module/list.ts +1 -1
  49. package/src/commands/scaffold-templates.ts +65 -0
  50. package/src/commands/scaffold.test.ts +92 -2
  51. package/src/commands/scaffold.ts +22 -2
  52. package/src/commands/sync-check.test.ts +60 -1
  53. package/src/commands/sync-check.ts +35 -2
  54. package/src/generator/generate-code.test.ts +200 -0
  55. package/src/generator/generate-code.ts +260 -0
  56. package/src/generator/parse-command-doc.test.ts +159 -0
  57. package/src/generator/parse-command-doc.ts +116 -0
  58. package/src/integration.test.ts +2 -2
  59. package/src/module.ts +6 -6
  60. package/src/modules/item-management/README.md +38 -0
  61. package/src/modules/item-management/command/activateItem.generated.ts +6 -0
  62. package/src/modules/item-management/command/activateItem.test.ts +76 -0
  63. package/src/modules/item-management/command/activateItem.ts +42 -0
  64. package/src/modules/item-management/command/assignItemToTaxonomy.generated.ts +6 -0
  65. package/src/modules/item-management/command/assignItemToTaxonomy.test.ts +88 -0
  66. package/src/modules/item-management/command/assignItemToTaxonomy.ts +63 -0
  67. package/src/modules/item-management/command/createItem.generated.ts +6 -0
  68. package/src/modules/item-management/command/createItem.test.ts +152 -0
  69. package/src/modules/item-management/command/createItem.ts +72 -0
  70. package/src/modules/item-management/command/createTaxonomyNode.generated.ts +6 -0
  71. package/src/modules/item-management/command/createTaxonomyNode.test.ts +126 -0
  72. package/src/modules/item-management/command/createTaxonomyNode.ts +70 -0
  73. package/src/modules/item-management/command/deactivateItem.generated.ts +6 -0
  74. package/src/modules/item-management/command/deactivateItem.test.ts +76 -0
  75. package/src/modules/item-management/command/deactivateItem.ts +42 -0
  76. package/src/modules/item-management/command/deleteItem.generated.ts +6 -0
  77. package/src/modules/item-management/command/deleteItem.test.ts +61 -0
  78. package/src/modules/item-management/command/deleteItem.ts +38 -0
  79. package/src/modules/item-management/command/deleteTaxonomyNode.generated.ts +6 -0
  80. package/src/modules/item-management/command/deleteTaxonomyNode.test.ts +73 -0
  81. package/src/modules/item-management/command/deleteTaxonomyNode.ts +50 -0
  82. package/src/modules/item-management/command/moveTaxonomyNode.generated.ts +6 -0
  83. package/src/modules/item-management/command/moveTaxonomyNode.test.ts +136 -0
  84. package/src/modules/item-management/command/moveTaxonomyNode.ts +85 -0
  85. package/src/modules/item-management/command/reactivateItem.generated.ts +6 -0
  86. package/src/modules/item-management/command/reactivateItem.test.ts +76 -0
  87. package/src/modules/item-management/command/reactivateItem.ts +42 -0
  88. package/src/modules/item-management/command/removeItemFromTaxonomy.generated.ts +6 -0
  89. package/src/modules/item-management/command/removeItemFromTaxonomy.test.ts +43 -0
  90. package/src/modules/item-management/command/removeItemFromTaxonomy.ts +30 -0
  91. package/src/modules/item-management/command/updateItem.generated.ts +6 -0
  92. package/src/modules/item-management/command/updateItem.test.ts +178 -0
  93. package/src/modules/item-management/command/updateItem.ts +103 -0
  94. package/src/modules/item-management/command/updateTaxonomyNode.generated.ts +6 -0
  95. package/src/modules/item-management/command/updateTaxonomyNode.test.ts +88 -0
  96. package/src/modules/item-management/command/updateTaxonomyNode.ts +62 -0
  97. package/src/modules/item-management/db/item.ts +47 -0
  98. package/src/modules/item-management/db/itemTaxonomyAssignment.ts +49 -0
  99. package/src/modules/item-management/db/taxonomyNode.ts +34 -0
  100. package/src/modules/item-management/docs/commands/ActivateItem.md +32 -0
  101. package/src/modules/item-management/docs/commands/AssignItemToTaxonomy.md +38 -0
  102. package/src/modules/item-management/docs/commands/CreateItem.md +44 -0
  103. package/src/modules/item-management/docs/commands/CreateTaxonomyNode.md +44 -0
  104. package/src/modules/item-management/docs/commands/DeactivateItem.md +34 -0
  105. package/src/modules/item-management/docs/commands/DeleteItem.md +35 -0
  106. package/src/modules/item-management/docs/commands/DeleteTaxonomyNode.md +39 -0
  107. package/src/modules/item-management/docs/commands/MoveTaxonomyNode.md +45 -0
  108. package/src/modules/item-management/docs/commands/ReactivateItem.md +34 -0
  109. package/src/modules/item-management/docs/commands/RemoveItemFromTaxonomy.md +30 -0
  110. package/src/modules/item-management/docs/commands/UpdateItem.md +55 -0
  111. package/src/modules/item-management/docs/commands/UpdateTaxonomyNode.md +36 -0
  112. package/src/modules/item-management/docs/features/item-lifecycle.md +60 -0
  113. package/src/modules/item-management/docs/features/item-taxonomy.md +65 -0
  114. package/src/modules/item-management/docs/models/ItemTaxonomyAssignment.md +36 -0
  115. package/src/modules/item-management/docs/models/TaxonomyNode.md +47 -0
  116. package/src/modules/item-management/docs/models/item.md +59 -0
  117. package/src/modules/item-management/docs/queries/CalculateNodeDepth.md +36 -0
  118. package/src/modules/item-management/docs/queries/CalculateSubtreeDepth.md +40 -0
  119. package/src/modules/item-management/docs/queries/DetectCircularReference.md +41 -0
  120. package/src/modules/item-management/docs/queries/GetItem.md +38 -0
  121. package/src/modules/item-management/docs/queries/GetItemTaxonomyAssignment.md +29 -0
  122. package/src/modules/item-management/docs/queries/GetTaxonomyNode.md +35 -0
  123. package/src/modules/item-management/docs/queries/GetTaxonomyNodeAssignments.md +29 -0
  124. package/src/modules/item-management/docs/queries/GetTaxonomyNodeChildren.md +29 -0
  125. package/src/modules/item-management/generated/enums.ts +9 -0
  126. package/src/modules/item-management/generated/kysely-tailordb.ts +62 -0
  127. package/src/modules/item-management/index.ts +53 -0
  128. package/src/modules/item-management/lib/_db_deps.ts +13 -0
  129. package/src/modules/item-management/lib/errors.generated.ts +117 -0
  130. package/src/modules/item-management/lib/permissions.generated.ts +17 -0
  131. package/src/modules/item-management/lib/types.ts +19 -0
  132. package/src/modules/item-management/module.ts +97 -0
  133. package/src/modules/item-management/query/calculateNodeDepth.generated.ts +5 -0
  134. package/src/modules/item-management/query/calculateNodeDepth.test.ts +56 -0
  135. package/src/modules/item-management/query/calculateNodeDepth.ts +28 -0
  136. package/src/modules/item-management/query/calculateSubtreeDepth.generated.ts +5 -0
  137. package/src/modules/item-management/query/calculateSubtreeDepth.test.ts +75 -0
  138. package/src/modules/item-management/query/calculateSubtreeDepth.ts +29 -0
  139. package/src/modules/item-management/query/detectCircularReference.generated.ts +5 -0
  140. package/src/modules/item-management/query/detectCircularReference.test.ts +61 -0
  141. package/src/modules/item-management/query/detectCircularReference.ts +32 -0
  142. package/src/modules/item-management/query/getItem.generated.ts +5 -0
  143. package/src/modules/item-management/query/getItem.test.ts +67 -0
  144. package/src/modules/item-management/query/getItem.ts +20 -0
  145. package/src/modules/item-management/query/getItemTaxonomyAssignment.generated.ts +5 -0
  146. package/src/modules/item-management/query/getItemTaxonomyAssignment.test.ts +25 -0
  147. package/src/modules/item-management/query/getItemTaxonomyAssignment.ts +18 -0
  148. package/src/modules/item-management/query/getTaxonomyNode.generated.ts +5 -0
  149. package/src/modules/item-management/query/getTaxonomyNode.test.ts +47 -0
  150. package/src/modules/item-management/query/getTaxonomyNode.ts +18 -0
  151. package/src/modules/item-management/query/getTaxonomyNodeAssignments.generated.ts +5 -0
  152. package/src/modules/item-management/query/getTaxonomyNodeAssignments.test.ts +25 -0
  153. package/src/modules/item-management/query/getTaxonomyNodeAssignments.ts +16 -0
  154. package/src/modules/item-management/query/getTaxonomyNodeChildren.generated.ts +5 -0
  155. package/src/modules/item-management/query/getTaxonomyNodeChildren.test.ts +34 -0
  156. package/src/modules/item-management/query/getTaxonomyNodeChildren.ts +16 -0
  157. package/src/modules/item-management/tailor.config.ts +11 -0
  158. package/src/modules/item-management/testing/fixtures.ts +81 -0
  159. package/src/modules/primitives/command/activateCategory.generated.ts +6 -0
  160. package/src/modules/primitives/command/activateCategory.test.ts +11 -29
  161. package/src/modules/primitives/command/activateCategory.ts +27 -34
  162. package/src/modules/primitives/command/activateCurrency.generated.ts +6 -0
  163. package/src/modules/primitives/command/activateCurrency.test.ts +11 -29
  164. package/src/modules/primitives/command/activateCurrency.ts +27 -34
  165. package/src/modules/primitives/command/activateUnit.generated.ts +6 -0
  166. package/src/modules/primitives/command/activateUnit.test.ts +11 -15
  167. package/src/modules/primitives/command/activateUnit.ts +27 -34
  168. package/src/modules/primitives/command/createCategory.generated.ts +6 -0
  169. package/src/modules/primitives/command/createCategory.test.ts +27 -39
  170. package/src/modules/primitives/command/createCategory.ts +53 -62
  171. package/src/modules/primitives/command/createCurrency.generated.ts +6 -0
  172. package/src/modules/primitives/command/createCurrency.test.ts +78 -71
  173. package/src/modules/primitives/command/createCurrency.ts +43 -48
  174. package/src/modules/primitives/command/createExchangeRate.generated.ts +6 -0
  175. package/src/modules/primitives/command/createExchangeRate.test.ts +101 -100
  176. package/src/modules/primitives/command/createExchangeRate.ts +50 -59
  177. package/src/modules/primitives/command/createUnit.generated.ts +6 -0
  178. package/src/modules/primitives/command/createUnit.test.ts +92 -95
  179. package/src/modules/primitives/command/createUnit.ts +54 -57
  180. package/src/modules/primitives/command/deactivateCategory.generated.ts +6 -0
  181. package/src/modules/primitives/command/deactivateCategory.test.ts +27 -28
  182. package/src/modules/primitives/command/deactivateCategory.ts +43 -50
  183. package/src/modules/primitives/command/deactivateCurrency.generated.ts +6 -0
  184. package/src/modules/primitives/command/deactivateCurrency.test.ts +23 -38
  185. package/src/modules/primitives/command/deactivateCurrency.ts +31 -38
  186. package/src/modules/primitives/command/deactivateUnit.generated.ts +6 -0
  187. package/src/modules/primitives/command/deactivateUnit.test.ts +27 -23
  188. package/src/modules/primitives/command/deactivateUnit.ts +39 -49
  189. package/src/modules/primitives/command/setBaseCurrency.generated.ts +6 -0
  190. package/src/modules/primitives/command/setBaseCurrency.test.ts +40 -33
  191. package/src/modules/primitives/command/setBaseCurrency.ts +43 -50
  192. package/src/modules/primitives/command/setReferenceUnit.generated.ts +6 -0
  193. package/src/modules/primitives/command/setReferenceUnit.test.ts +39 -35
  194. package/src/modules/primitives/command/setReferenceUnit.ts +46 -59
  195. package/src/modules/primitives/db/unit.ts +13 -3
  196. package/src/modules/primitives/docs/commands/ActivateCategory.md +1 -2
  197. package/src/modules/primitives/docs/commands/ActivateCurrency.md +1 -2
  198. package/src/modules/primitives/docs/commands/ActivateUnit.md +1 -2
  199. package/src/modules/primitives/docs/commands/CreateCategory.md +1 -4
  200. package/src/modules/primitives/docs/commands/CreateCurrency.md +3 -4
  201. package/src/modules/primitives/docs/commands/CreateExchangeRate.md +4 -5
  202. package/src/modules/primitives/docs/commands/CreateUnit.md +5 -5
  203. package/src/modules/primitives/docs/commands/DeactivateCategory.md +2 -3
  204. package/src/modules/primitives/docs/commands/DeactivateCurrency.md +2 -3
  205. package/src/modules/primitives/docs/commands/DeactivateUnit.md +2 -3
  206. package/src/modules/primitives/docs/commands/SetBaseCurrency.md +2 -3
  207. package/src/modules/primitives/docs/commands/SetReferenceUnit.md +2 -3
  208. package/src/modules/primitives/docs/queries/ConvertAmount.md +3 -5
  209. package/src/modules/primitives/docs/queries/ConvertQuantity.md +3 -5
  210. package/src/modules/primitives/docs/queries/GetBaseCurrency.md +32 -0
  211. package/src/modules/primitives/docs/queries/GetCurrency.md +36 -0
  212. package/src/modules/primitives/docs/queries/GetUnit.md +36 -0
  213. package/src/modules/primitives/docs/queries/GetUoMCategory.md +36 -0
  214. package/src/modules/primitives/docs/queries/ListUnitsByCategory.md +26 -0
  215. package/src/modules/primitives/generated/kysely-tailordb.ts +24 -45
  216. package/src/modules/primitives/index.ts +15 -4
  217. package/src/modules/primitives/lib/errors.generated.ts +112 -0
  218. package/src/modules/primitives/{permissions.ts → lib/permissions.generated.ts} +9 -8
  219. package/src/modules/primitives/module.ts +37 -27
  220. package/src/modules/primitives/query/convertAmount.generated.ts +5 -0
  221. package/src/modules/primitives/query/convertAmount.test.ts +2 -2
  222. package/src/modules/primitives/query/convertAmount.ts +27 -28
  223. package/src/modules/primitives/query/convertQuantity.generated.ts +5 -0
  224. package/src/modules/primitives/query/convertQuantity.test.ts +6 -2
  225. package/src/modules/primitives/query/convertQuantity.ts +49 -57
  226. package/src/modules/primitives/query/getBaseCurrency.generated.ts +5 -0
  227. package/src/modules/primitives/query/getBaseCurrency.test.ts +28 -0
  228. package/src/modules/primitives/query/getBaseCurrency.ts +16 -0
  229. package/src/modules/primitives/query/getCurrency.generated.ts +5 -0
  230. package/src/modules/primitives/query/getCurrency.test.ts +47 -0
  231. package/src/modules/primitives/query/getCurrency.ts +18 -0
  232. package/src/modules/primitives/query/getUnit.generated.ts +5 -0
  233. package/src/modules/primitives/query/getUnit.test.ts +47 -0
  234. package/src/modules/primitives/query/getUnit.ts +18 -0
  235. package/src/modules/primitives/query/getUoMCategory.generated.ts +5 -0
  236. package/src/modules/primitives/query/getUoMCategory.test.ts +47 -0
  237. package/src/modules/primitives/query/getUoMCategory.ts +18 -0
  238. package/src/modules/primitives/query/listUnitsByCategory.generated.ts +5 -0
  239. package/src/modules/primitives/query/listUnitsByCategory.ts +16 -0
  240. package/src/modules/primitives/tailor.config.ts +3 -3
  241. package/src/modules/shared/defineCommand.test.ts +23 -10
  242. package/src/modules/shared/defineCommand.ts +23 -10
  243. package/src/modules/shared/internal.ts +1 -0
  244. package/src/modules/shared/requirePermission.test.ts +22 -21
  245. package/src/modules/shared/requirePermission.ts +8 -2
  246. package/src/modules/shared/result.ts +12 -0
  247. package/src/modules/testing/index.ts +36 -11
  248. package/src/modules/user-management/command/activateUser.generated.ts +6 -0
  249. package/src/modules/user-management/command/activateUser.test.ts +27 -27
  250. package/src/modules/user-management/command/activateUser.ts +40 -48
  251. package/src/modules/user-management/command/assignPermissionToRole.generated.ts +6 -0
  252. package/src/modules/user-management/command/assignPermissionToRole.test.ts +42 -43
  253. package/src/modules/user-management/command/assignPermissionToRole.ts +59 -62
  254. package/src/modules/user-management/command/assignRoleToUser.generated.ts +6 -0
  255. package/src/modules/user-management/command/assignRoleToUser.test.ts +70 -63
  256. package/src/modules/user-management/command/assignRoleToUser.ts +63 -66
  257. package/src/modules/user-management/command/createPermission.generated.ts +6 -0
  258. package/src/modules/user-management/command/createPermission.test.ts +45 -38
  259. package/src/modules/user-management/command/createPermission.ts +42 -46
  260. package/src/modules/user-management/command/createRole.generated.ts +6 -0
  261. package/src/modules/user-management/command/createRole.test.ts +30 -29
  262. package/src/modules/user-management/command/createRole.ts +33 -33
  263. package/src/modules/user-management/command/createUser.generated.ts +6 -0
  264. package/src/modules/user-management/command/createUser.test.ts +64 -42
  265. package/src/modules/user-management/command/createUser.ts +54 -56
  266. package/src/modules/user-management/command/deactivateUser.generated.ts +6 -0
  267. package/src/modules/user-management/command/deactivateUser.test.ts +27 -27
  268. package/src/modules/user-management/command/deactivateUser.ts +40 -48
  269. package/src/modules/user-management/command/logAuditEvent.generated.ts +6 -0
  270. package/src/modules/user-management/command/logAuditEvent.test.ts +50 -42
  271. package/src/modules/user-management/command/logAuditEvent.ts +25 -28
  272. package/src/modules/user-management/command/reactivateUser.generated.ts +6 -0
  273. package/src/modules/user-management/command/reactivateUser.test.ts +31 -27
  274. package/src/modules/user-management/command/reactivateUser.ts +40 -48
  275. package/src/modules/user-management/command/revokePermissionFromRole.generated.ts +6 -0
  276. package/src/modules/user-management/command/revokePermissionFromRole.test.ts +52 -51
  277. package/src/modules/user-management/command/revokePermissionFromRole.ts +60 -57
  278. package/src/modules/user-management/command/revokeRoleFromUser.generated.ts +6 -0
  279. package/src/modules/user-management/command/revokeRoleFromUser.test.ts +53 -48
  280. package/src/modules/user-management/command/revokeRoleFromUser.ts +58 -57
  281. package/src/modules/user-management/docs/commands/CreatePermission.md +2 -2
  282. package/src/modules/user-management/docs/commands/CreateRole.md +1 -1
  283. package/src/modules/user-management/generated/enums.ts +11 -11
  284. package/src/modules/user-management/generated/kysely-tailordb.ts +27 -56
  285. package/src/modules/user-management/index.ts +2 -2
  286. package/src/modules/user-management/lib/errors.generated.ts +67 -0
  287. package/src/modules/user-management/{permissions.ts → lib/permissions.generated.ts} +8 -7
  288. package/src/modules/user-management/module.ts +22 -22
  289. package/src/modules/user-management/tailor.config.ts +3 -3
  290. package/src/schemas.ts +1 -1
  291. package/skills/1-module-docs/references/structure.md +0 -22
  292. package/skills/2-module-feature-breakdown/references/commands.md +0 -48
  293. package/skills/2-module-feature-breakdown/references/structure.md +0 -22
  294. package/skills/3-module-doc-review/references/commands.md +0 -54
  295. package/skills/3-module-doc-review/references/models.md +0 -29
  296. package/skills/4-module-tdd-implementation/SKILL.md +0 -74
  297. package/skills/4-module-tdd-implementation/references/commands.md +0 -45
  298. package/skills/4-module-tdd-implementation/references/errors.md +0 -7
  299. package/skills/4-module-tdd-implementation/references/models.md +0 -30
  300. package/skills/4-module-tdd-implementation/references/structure.md +0 -22
  301. package/skills/4-module-tdd-implementation/references/testing.md +0 -37
  302. package/skills/5-module-implementation-review/references/commands.md +0 -45
  303. package/skills/5-module-implementation-review/references/errors.md +0 -7
  304. package/skills/5-module-implementation-review/references/exports.md +0 -8
  305. package/skills/5-module-implementation-review/references/models.md +0 -30
  306. package/src/modules/primitives/lib/errors.ts +0 -138
  307. package/src/modules/user-management/lib/errors.ts +0 -81
  308. /package/skills/{app-compose-1-requirement-analysis → erp-kit-app-1-requirements}/references/structure.md +0 -0
  309. /package/skills/{app-compose-2-requirements-breakdown → erp-kit-app-2-breakdown}/references/screen-detailview.md +0 -0
  310. /package/skills/{app-compose-2-requirements-breakdown → erp-kit-app-2-breakdown}/references/screen-form.md +0 -0
  311. /package/skills/{app-compose-2-requirements-breakdown → erp-kit-app-2-breakdown}/references/screen-listview.md +0 -0
  312. /package/skills/{app-compose-2-requirements-breakdown → erp-kit-app-2-breakdown}/references/structure.md +0 -0
  313. /package/skills/{app-compose-3-doc-review → erp-kit-app-3-doc-review}/references/structure.md +0 -0
  314. /package/skills/{app-compose-4-design-mock → erp-kit-app-4-design}/references/component.md +0 -0
  315. /package/skills/{app-compose-4-design-mock → erp-kit-app-4-design}/references/screen-detailview.md +0 -0
  316. /package/skills/{app-compose-4-design-mock → erp-kit-app-4-design}/references/screen-form.md +0 -0
  317. /package/skills/{app-compose-4-design-mock → erp-kit-app-4-design}/references/screen-listview.md +0 -0
  318. /package/skills/{app-compose-4-design-mock → erp-kit-app-4-design}/references/structure.md +0 -0
  319. /package/skills/{app-compose-5-design-mock-review → erp-kit-app-5-design-review}/references/component.md +0 -0
  320. /package/skills/{app-compose-5-design-mock-review → erp-kit-app-5-design-review}/references/screen-detailview.md +0 -0
  321. /package/skills/{app-compose-5-design-mock-review → erp-kit-app-5-design-review}/references/screen-form.md +0 -0
  322. /package/skills/{app-compose-5-design-mock-review → erp-kit-app-5-design-review}/references/screen-listview.md +0 -0
  323. /package/skills/{app-compose-6-implementation-spec → erp-kit-app-6-impl-spec}/references/auth.md +0 -0
  324. /package/skills/{app-compose-6-implementation-spec → erp-kit-app-6-impl-spec}/references/structure.md +0 -0
  325. /package/skills/{2-module-feature-breakdown → erp-kit-module-4-tdd}/references/models.md +0 -0
@@ -1,10 +1,10 @@
1
1
  import { describe, expect, it } from "vitest";
2
2
  import { createMockDb } from "../../testing/index";
3
- import { InsufficientPermissionError, type CommandContext } from "../../shared/internal";
3
+ import { type CommandContext } from "../../shared/internal";
4
4
  import { DB } from "../generated/kysely-tailordb";
5
- import { UnitNotFoundError, UnitNotInCategoryError } from "../lib/errors";
5
+ import { UnitNotFoundError, UnitNotInCategoryError } from "../lib/errors.generated";
6
6
  import { baseUoMCategory, baseUnitGram, baseUnitKg, baseUnitLiter } from "../testing/fixtures";
7
- import { setReferenceUnit } from "./setReferenceUnit";
7
+ import { run } from "./setReferenceUnit";
8
8
 
9
9
  describe("setReferenceUnit", () => {
10
10
  const ctx: CommandContext = {
@@ -17,32 +17,38 @@ describe("setReferenceUnit", () => {
17
17
  const { db, spies } = createMockDb<DB>();
18
18
  spies.select.mockReturnValue(undefined);
19
19
 
20
- await expect(
21
- setReferenceUnit(
22
- db,
23
- {
24
- unitId: "nonexistent-unit",
25
- categoryId: baseUoMCategory.id,
26
- },
27
- ctx,
28
- ),
29
- ).rejects.toBeInstanceOf(UnitNotFoundError);
20
+ const result = await run(
21
+ db,
22
+ {
23
+ unitId: "nonexistent-unit",
24
+ categoryId: baseUoMCategory.id,
25
+ },
26
+ ctx,
27
+ );
28
+
29
+ expect(result.ok).toBe(false);
30
+ if (!result.ok) {
31
+ expect(result.error).toBeInstanceOf(UnitNotFoundError);
32
+ }
30
33
  });
31
34
 
32
35
  it("throws when unit is not in specified category", async () => {
33
36
  const { db, spies } = createMockDb<DB>();
34
37
  spies.select.mockReturnValue(baseUnitLiter); // Unit is in category-2, not category-1
35
38
 
36
- await expect(
37
- setReferenceUnit(
38
- db,
39
- {
40
- unitId: baseUnitLiter.id,
41
- categoryId: baseUoMCategory.id, // category-1
42
- },
43
- ctx,
44
- ),
45
- ).rejects.toBeInstanceOf(UnitNotInCategoryError);
39
+ const result = await run(
40
+ db,
41
+ {
42
+ unitId: baseUnitLiter.id,
43
+ categoryId: baseUoMCategory.id, // category-1
44
+ },
45
+ ctx,
46
+ );
47
+
48
+ expect(result.ok).toBe(false);
49
+ if (!result.ok) {
50
+ expect(result.error).toBeInstanceOf(UnitNotInCategoryError);
51
+ }
46
52
  });
47
53
 
48
54
  // Idempotent cases
@@ -52,7 +58,7 @@ describe("setReferenceUnit", () => {
52
58
  .mockReturnValueOnce(baseUnitKg) // Unit lookup
53
59
  .mockReturnValueOnce(baseUoMCategory); // Category lookup
54
60
 
55
- const result = await setReferenceUnit(
61
+ const result = await run(
56
62
  db,
57
63
  {
58
64
  unitId: baseUnitKg.id,
@@ -61,7 +67,10 @@ describe("setReferenceUnit", () => {
61
67
  ctx,
62
68
  );
63
69
 
64
- expect(result.category.referenceUnitId).toBe(baseUnitKg.id);
70
+ expect(result.ok).toBe(true);
71
+ if (result.ok) {
72
+ expect(result.value.uoMCategory.referenceUnitId).toBe(baseUnitKg.id);
73
+ }
65
74
  expect(spies.update).not.toHaveBeenCalled();
66
75
  });
67
76
 
@@ -85,7 +94,7 @@ describe("setReferenceUnit", () => {
85
94
  .mockReturnValueOnce({ ...baseUnitGram, conversionFactor: 1.0 }) // Update gram factor
86
95
  .mockReturnValueOnce(updatedCategory); // Update category
87
96
 
88
- const result = await setReferenceUnit(
97
+ const result = await run(
89
98
  db,
90
99
  {
91
100
  unitId: baseUnitGram.id,
@@ -94,15 +103,10 @@ describe("setReferenceUnit", () => {
94
103
  ctx,
95
104
  );
96
105
 
97
- expect(result.category.referenceUnitId).toBe(baseUnitGram.id);
106
+ expect(result.ok).toBe(true);
107
+ if (result.ok) {
108
+ expect(result.value.uoMCategory.referenceUnitId).toBe(baseUnitGram.id);
109
+ }
98
110
  expect(spies.update).toHaveBeenCalled();
99
111
  });
100
-
101
- it("throws when permission is missing", async () => {
102
- const { db } = createMockDb<DB>();
103
- const denied: CommandContext = { actorId: "test-actor", permissions: [] };
104
- await expect(
105
- setReferenceUnit(db, { unitId: "unit-1", categoryId: "cat-1" }, denied),
106
- ).rejects.toBeInstanceOf(InsufficientPermissionError);
107
- });
108
112
  });
@@ -1,7 +1,9 @@
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 { UnitNotFoundError, UnitNotInCategoryError } from "../lib/errors";
4
- import { permissions } from "../permissions";
3
+ import { UnitNotFoundError, UnitNotInCategoryError } from "../lib/errors.generated";
4
+ import { getUnit } from "../query/getUnit.generated";
5
+ import { getUoMCategory } from "../query/getUoMCategory.generated";
6
+ import { listUnitsByCategory } from "../query/listUnitsByCategory.generated";
5
7
 
6
8
  export interface SetReferenceUnitInput {
7
9
  unitId: string;
@@ -14,71 +16,56 @@ export interface SetReferenceUnitInput {
14
16
  * Changes the reference unit for a UoM category. All conversion factors
15
17
  * are recalculated relative to the new reference unit.
16
18
  */
17
- export const setReferenceUnit = defineCommand(
18
- permissions.setReferenceUnit,
19
- async (db: DB, input: SetReferenceUnitInput) => {
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
- if (!unit) {
28
- throw new UnitNotFoundError(input.unitId);
29
- }
19
+ export async function run(db: DB, input: SetReferenceUnitInput, ctx: CommandContext) {
20
+ // 1. Find unit by ID
21
+ const { unit } = await getUnit(db, { id: input.unitId }, ctx);
30
22
 
31
- // 2. Check unit belongs to specified category
32
- if (unit.categoryId !== input.categoryId) {
33
- throw new UnitNotInCategoryError(input.unitId, input.categoryId);
34
- }
23
+ if (!unit) {
24
+ return err(new UnitNotFoundError(input.unitId));
25
+ }
35
26
 
36
- // 3. Get category
37
- const category = await db
38
- .selectFrom("UoMCategory")
39
- .selectAll()
40
- .where("id", "=", input.categoryId)
41
- .executeTakeFirst();
27
+ // 2. Check unit belongs to specified category
28
+ if (unit.categoryId !== input.categoryId) {
29
+ return err(new UnitNotInCategoryError(`${input.unitId} in ${input.categoryId}`));
30
+ }
42
31
 
43
- // 4. If already reference unit, return (idempotent)
44
- if (category?.referenceUnitId === input.unitId && category) {
45
- return { category };
46
- }
32
+ // 3. Get category
33
+ const { uoMCategory } = await getUoMCategory(db, { id: input.categoryId }, ctx);
47
34
 
48
- // 5. Get all units in category for recalculation
49
- const units = await db
50
- .selectFrom("Unit")
51
- .selectAll()
52
- .where("categoryId", "=", input.categoryId)
53
- .execute();
35
+ // 4. If already reference unit, return (idempotent)
36
+ if (uoMCategory?.referenceUnitId === input.unitId && uoMCategory) {
37
+ return ok({ uoMCategory });
38
+ }
54
39
 
55
- // 6. Recalculate all conversion factors
56
- // new_factor = old_factor / new_reference_old_factor
57
- const newReferenceFactor = unit.conversionFactor;
58
- for (const u of units) {
59
- const newFactor = u.conversionFactor / newReferenceFactor;
60
- await db
61
- .updateTable("Unit")
62
- .set({
63
- conversionFactor: newFactor,
64
- updatedAt: new Date(),
65
- })
66
- .where("id", "=", u.id)
67
- .returningAll()
68
- .executeTakeFirst();
69
- }
40
+ // 5. Get all units in category for recalculation
41
+ const { units } = await listUnitsByCategory(db, { categoryId: input.categoryId }, ctx);
70
42
 
71
- // 7. Update category reference unit
72
- const updatedCategory = await db
73
- .updateTable("UoMCategory")
43
+ // 6. Recalculate all conversion factors
44
+ // new_factor = old_factor / new_reference_old_factor
45
+ const newReferenceFactor = unit.conversionFactor;
46
+ for (const u of units) {
47
+ const newFactor = u.conversionFactor / newReferenceFactor;
48
+ await db
49
+ .updateTable("Unit")
74
50
  .set({
75
- referenceUnitId: input.unitId,
51
+ conversionFactor: newFactor,
76
52
  updatedAt: new Date(),
77
53
  })
78
- .where("id", "=", input.categoryId)
54
+ .where("id", "=", u.id)
79
55
  .returningAll()
80
56
  .executeTakeFirst();
57
+ }
81
58
 
82
- return { category: updatedCategory! };
83
- },
84
- );
59
+ // 7. Update category reference unit
60
+ const updatedCategory = await db
61
+ .updateTable("UoMCategory")
62
+ .set({
63
+ referenceUnitId: input.unitId,
64
+ updatedAt: new Date(),
65
+ })
66
+ .where("id", "=", input.categoryId)
67
+ .returningAll()
68
+ .executeTakeFirst();
69
+
70
+ return ok({ uoMCategory: updatedCategory! });
71
+ }
@@ -1,12 +1,15 @@
1
1
  import {
2
2
  db,
3
3
  type TailorAnyDBField,
4
+ type TailorAnyDBType,
4
5
  unsafeAllowAllGqlPermission,
5
6
  unsafeAllowAllTypePermission,
6
7
  } from "@tailor-platform/sdk";
8
+ import { uomCategory } from "./uomCategory";
7
9
 
8
10
  export interface CreateUnitTypeParams<F extends Record<string, TailorAnyDBField>> {
9
11
  fields?: F;
12
+ uomCategoryType: TailorAnyDBType;
10
13
  }
11
14
 
12
15
  export function createUnitType<const F extends Record<string, TailorAnyDBField>>(
@@ -15,8 +18,15 @@ export function createUnitType<const F extends Record<string, TailorAnyDBField>>
15
18
  return db
16
19
  .type("Unit", {
17
20
  name: db.string().description("Unit display name (e.g., Kilogram)"),
18
- symbol: db.string().description("Short symbol (e.g., kg)"),
19
- categoryId: db.uuid().description("Foreign key to UoMCategory"),
21
+ symbol: db.string().unique().description("Short symbol (e.g., kg)"),
22
+ categoryId: db
23
+ .uuid()
24
+ .relation({
25
+ type: "n-1",
26
+ toward: { type: params.uomCategoryType },
27
+ backward: "units",
28
+ })
29
+ .description("Foreign key to UoMCategory"),
20
30
  conversionFactor: db
21
31
  .float()
22
32
  .description("Multiplier relative to reference unit (reference unit = 1.0)"),
@@ -29,4 +39,4 @@ export function createUnitType<const F extends Record<string, TailorAnyDBField>>
29
39
  .gqlPermission(unsafeAllowAllGqlPermission);
30
40
  }
31
41
 
32
- export const unit = createUnitType({});
42
+ export const unit = createUnitType({ uomCategoryType: uomCategory });
@@ -30,5 +30,4 @@ flowchart TD
30
30
 
31
31
  ## Error Scenarios
32
32
 
33
- - **Category not found**: Specified category ID does not exist - return not found error
34
- - **Invalid category ID**: Malformed or empty ID provided - return validation error
33
+ - **UOM_CATEGORY_NOT_FOUND**: Specified category ID does not exist
@@ -29,5 +29,4 @@ flowchart TD
29
29
 
30
30
  ## Error Scenarios
31
31
 
32
- - **Currency not found**: Specified currency ID does not exist - return not found error
33
- - **Invalid currency ID**: Malformed or empty ID provided - return validation error
32
+ - **CURRENCY_NOT_FOUND**: Specified currency ID does not exist
@@ -30,5 +30,4 @@ flowchart TD
30
30
 
31
31
  ## Error Scenarios
32
32
 
33
- - **Unit not found**: Specified unit ID does not exist - return not found error
34
- - **Invalid unit ID**: Malformed or empty ID provided - return validation error
33
+ - **UNIT_NOT_FOUND**: Specified unit ID does not exist
@@ -38,7 +38,4 @@ flowchart TD
38
38
 
39
39
  ## Error Scenarios
40
40
 
41
- - **Missing category name**: Name not provided - return validation error
42
- - **Duplicate category name**: Category with same name already exists - return conflict error
43
- - **Missing reference unit**: No reference unit details provided - return validation error indicating reference unit is required
44
- - **Invalid reference unit**: Reference unit details are incomplete or invalid - return validation error with specific issues
41
+ - **DUPLICATE_CATEGORY_NAME**: Category with same name already exists
@@ -41,7 +41,6 @@ flowchart TD
41
41
 
42
42
  ## Error Scenarios
43
43
 
44
- - **Invalid ISO code format**: Code is not exactly 3 uppercase letters - return validation error with format requirements
45
- - **Duplicate ISO code**: Currency with same code already exists - return conflict error with existing currency reference
46
- - **Invalid decimal places**: Value is negative or exceeds maximum (typically 4) - return validation error with valid range
47
- - **Missing required fields**: Symbol or name not provided - return validation error listing missing fields
44
+ - **INVALID_ISO_CODE**: Code is not exactly 3 uppercase letters
45
+ - **DUPLICATE_CURRENCY_CODE**: Currency with same code already exists
46
+ - **INVALID_DECIMAL_PLACES**: Value is negative or exceeds maximum (typically 4)
@@ -41,8 +41,7 @@ flowchart TD
41
41
 
42
42
  ## Error Scenarios
43
43
 
44
- - **Invalid source currency**: Source currency does not exist or is inactive - return error identifying the currency
45
- - **Invalid target currency**: Target currency does not exist or is inactive - return error identifying the currency
46
- - **Same currency pair**: Source and target currencies are the same - return error indicating self-conversion is not allowed
47
- - **Invalid rate value**: Rate is zero, negative, or not a valid number - return validation error with acceptable range
48
- - **Missing effective date**: No effective date provided - return validation error indicating date is required
44
+ - **CURRENCY_NOT_FOUND**: Source or target currency does not exist
45
+ - **INACTIVE_CURRENCY**: Source or target currency is inactive
46
+ - **SAME_CURRENCY_PAIR**: Source and target currencies are the same
47
+ - **INVALID_EXCHANGE_RATE**: Rate is zero, negative, or not a valid number
@@ -41,8 +41,8 @@ flowchart TD
41
41
 
42
42
  ## Error Scenarios
43
43
 
44
- - **Invalid category**: Category does not exist or is inactive - return error identifying the category
45
- - **Missing symbol**: Unit symbol not provided - return validation error
46
- - **Duplicate symbol**: Unit with same symbol already exists in category - return conflict error
47
- - **Invalid conversion factor**: Factor is zero, negative, or not a valid number - return validation error
48
- - **Invalid rounding precision**: Precision is negative - return validation error with acceptable range
44
+ - **UOM_CATEGORY_NOT_FOUND**: Category does not exist
45
+ - **CATEGORY_NOT_ACTIVE**: Category is inactive
46
+ - **DUPLICATE_UNIT_SYMBOL**: Unit with same symbol already exists in category
47
+ - **INVALID_CONVERSION_FACTOR**: Factor is zero, negative, or not a valid number
48
+ - **INVALID_ROUNDING_PRECISION**: Precision is negative
@@ -33,6 +33,5 @@ flowchart TD
33
33
 
34
34
  ## Error Scenarios
35
35
 
36
- - **Category not found**: Specified category ID does not exist - return not found error
37
- - **Has active units**: Category still contains active units - return error listing active units that must be deactivated first
38
- - **Invalid category ID**: Malformed or empty ID provided - return validation error
36
+ - **UOM_CATEGORY_NOT_FOUND**: Specified category ID does not exist
37
+ - **CATEGORY_HAS_ACTIVE_UNITS**: Category still contains active units that must be deactivated first
@@ -33,6 +33,5 @@ flowchart TD
33
33
 
34
34
  ## Error Scenarios
35
35
 
36
- - **Currency not found**: Specified currency ID does not exist - return not found error
37
- - **Base currency protection**: Attempting to deactivate the base currency - return error indicating base currency must be changed first
38
- - **Invalid currency ID**: Malformed or empty ID provided - return validation error
36
+ - **CURRENCY_NOT_FOUND**: Specified currency ID does not exist
37
+ - **CANNOT_DEACTIVATE_BASE_CURRENCY**: Attempting to deactivate the base currency, must change base currency first
@@ -33,6 +33,5 @@ flowchart TD
33
33
 
34
34
  ## Error Scenarios
35
35
 
36
- - **Unit not found**: Specified unit ID does not exist - return not found error
37
- - **Reference unit protection**: Attempting to deactivate the category's reference unit - return error indicating reference unit must be changed first
38
- - **Invalid unit ID**: Malformed or empty ID provided - return validation error
36
+ - **UNIT_NOT_FOUND**: Specified unit ID does not exist
37
+ - **CANNOT_DEACTIVATE_REFERENCE_UNIT**: Attempting to deactivate the category's reference unit, must change reference unit first
@@ -34,6 +34,5 @@ flowchart TD
34
34
 
35
35
  ## Error Scenarios
36
36
 
37
- - **Currency not found**: Specified currency ID does not exist - return not found error
38
- - **Inactive currency**: Target currency is not in Active status - return error indicating currency must be activated first
39
- - **Invalid currency ID**: Malformed or empty ID provided - return validation error
37
+ - **CURRENCY_NOT_FOUND**: Specified currency ID does not exist
38
+ - **CANNOT_SET_INACTIVE_AS_BASE_CURRENCY**: Target currency is not in Active status, must be activated first
@@ -38,6 +38,5 @@ flowchart TD
38
38
 
39
39
  ## Error Scenarios
40
40
 
41
- - **Unit not found**: Specified unit ID does not exist - return not found error
42
- - **Unit not in category**: Unit belongs to a different category than specified - return error with category mismatch details
43
- - **Invalid unit ID**: Malformed or empty ID provided - return validation error
41
+ - **UNIT_NOT_FOUND**: Specified unit ID does not exist
42
+ - **UNIT_NOT_IN_CATEGORY**: Unit belongs to a different category than specified
@@ -43,8 +43,6 @@ flowchart TD
43
43
 
44
44
  ## Error Scenarios
45
45
 
46
- - **Inactive currency**: Either source or target currency is inactive - return error identifying the inactive currency
47
- - **No exchange rate**: No rate found for the currency pair on or before the specified date - return error with date and currency pair
48
- - **Invalid amount**: Negative amount provided - return validation error
49
- - **Currency not found**: Specified currency code/ID does not exist - return not found error
50
- - **Date in future**: Conversion date is in the future and no forward rate exists - return error or use most recent rate based on configuration
46
+ - **INACTIVE_CURRENCY**: Either source or target currency is inactive
47
+ - **EXCHANGE_RATE_NOT_FOUND**: No rate found for the currency pair on or before the specified date
48
+ - **CURRENCY_NOT_FOUND**: Specified currency code/ID does not exist
@@ -36,8 +36,6 @@ flowchart TD
36
36
 
37
37
  ## Error Scenarios
38
38
 
39
- - **Incompatible units**: Source and target units belong to different categories - return error with message indicating the mismatch
40
- - **Inactive unit**: Either source or target unit is inactive - return error identifying the inactive unit
41
- - **Invalid quantity**: Negative quantity provided - return validation error (or allow based on configuration)
42
- - **Unit not found**: Specified unit ID does not exist - return not found error
43
- - **Overflow**: Calculation produces a number exceeding system limits - return overflow error
39
+ - **INCOMPATIBLE_UNITS**: Source and target units belong to different categories
40
+ - **INACTIVE_UNIT**: Either source or target unit is inactive
41
+ - **UNIT_NOT_FOUND**: Specified unit ID does not exist
@@ -0,0 +1,32 @@
1
+ # GetBaseCurrency
2
+
3
+ ## Overview
4
+
5
+ GetBaseCurrency retrieves the currency designated as the organization's base currency. Returns the currency record if a base currency has been set, or null if no base currency exists.
6
+
7
+ This function supports financial reporting and default currency selection workflows.
8
+
9
+ ## Business Rules
10
+
11
+ - Returns the single currency where `isBaseCurrency` is true
12
+ - At most one currency can be the base currency at any time
13
+ - Returns null if no base currency has been configured (e.g., before any currencies are created)
14
+ - Does not require any input parameters
15
+
16
+ ## Process Flow
17
+
18
+ ```mermaid
19
+ flowchart TD
20
+ A[Receive request] --> B[Query Currency where isBaseCurrency = true]
21
+ B --> C{Found?}
22
+ C -->|Yes| D[Return base currency]
23
+ C -->|No| E[Return null]
24
+ ```
25
+
26
+ ## External Dependencies
27
+
28
+ - None
29
+
30
+ ## Error Scenarios
31
+
32
+ - None (returns null when no base currency is set instead of throwing)
@@ -0,0 +1,36 @@
1
+ # GetCurrency
2
+
3
+ ## Overview
4
+
5
+ GetCurrency retrieves a single currency by its unique identifier or ISO 4217 code. Returns the currency record if found, or null if no matching currency exists.
6
+
7
+ This function supports currency validation and lookup operations across all modules that reference currencies.
8
+
9
+ ## Business Rules
10
+
11
+ - Lookup by `id` performs an exact UUID match
12
+ - Lookup by `code` performs an exact string match against ISO 4217 codes (e.g., "USD", "EUR", "JPY")
13
+ - Returns the full currency record including status, decimal places, and base currency flag
14
+ - Does not filter by active status - returns both active and inactive currencies
15
+ - Exactly one lookup key must be provided (id or code)
16
+
17
+ ## Process Flow
18
+
19
+ ```mermaid
20
+ flowchart TD
21
+ A[Receive lookup request] --> B{Lookup by id or code?}
22
+ B -->|id| C[Query Currency by id]
23
+ B -->|code| D[Query Currency by code]
24
+ C --> E{Found?}
25
+ D --> E
26
+ E -->|Yes| F[Return currency]
27
+ E -->|No| G[Return null]
28
+ ```
29
+
30
+ ## External Dependencies
31
+
32
+ - None
33
+
34
+ ## Error Scenarios
35
+
36
+ - None (returns null when not found instead of throwing)
@@ -0,0 +1,36 @@
1
+ # GetUnit
2
+
3
+ ## Overview
4
+
5
+ GetUnit retrieves a single unit of measure by its unique identifier or symbol. Returns the unit record if found, or null if no matching unit exists.
6
+
7
+ This function supports unit validation and lookup operations across all modules that reference units of measure.
8
+
9
+ ## Business Rules
10
+
11
+ - Lookup by `id` performs an exact UUID match
12
+ - Lookup by `symbol` performs an exact string match (e.g., "kg", "lb", "g")
13
+ - Returns the full unit record including status, conversion factor, and rounding precision
14
+ - Does not filter by active status - returns both active and inactive units
15
+ - Exactly one lookup key must be provided (id or symbol)
16
+
17
+ ## Process Flow
18
+
19
+ ```mermaid
20
+ flowchart TD
21
+ A[Receive lookup request] --> B{Lookup by id or symbol?}
22
+ B -->|id| C[Query Unit by id]
23
+ B -->|symbol| D[Query Unit by symbol]
24
+ C --> E{Found?}
25
+ D --> E
26
+ E -->|Yes| F[Return unit]
27
+ E -->|No| G[Return null]
28
+ ```
29
+
30
+ ## External Dependencies
31
+
32
+ - None
33
+
34
+ ## Error Scenarios
35
+
36
+ - None (returns null when not found instead of throwing)
@@ -0,0 +1,36 @@
1
+ # GetUoMCategory
2
+
3
+ ## Overview
4
+
5
+ GetUoMCategory retrieves a single UoM category by its unique identifier or name. Returns the category record if found, or null if no matching category exists.
6
+
7
+ This function supports category validation and lookup operations for unit management workflows.
8
+
9
+ ## Business Rules
10
+
11
+ - Lookup by `id` performs an exact UUID match
12
+ - Lookup by `name` performs an exact string match (e.g., "Weight", "Volume", "Length")
13
+ - Returns the full category record including status, description, and reference unit ID
14
+ - Does not filter by active status - returns both active and inactive categories
15
+ - Exactly one lookup key must be provided (id or name)
16
+
17
+ ## Process Flow
18
+
19
+ ```mermaid
20
+ flowchart TD
21
+ A[Receive lookup request] --> B{Lookup by id or name?}
22
+ B -->|id| C[Query UoMCategory by id]
23
+ B -->|name| D[Query UoMCategory by name]
24
+ C --> E{Found?}
25
+ D --> E
26
+ E -->|Yes| F[Return category]
27
+ E -->|No| G[Return null]
28
+ ```
29
+
30
+ ## External Dependencies
31
+
32
+ - None
33
+
34
+ ## Error Scenarios
35
+
36
+ - None (returns null when not found instead of throwing)
@@ -0,0 +1,26 @@
1
+ # ListUnitsByCategory
2
+
3
+ ## Overview
4
+
5
+ ListUnitsByCategory retrieves all units belonging to a specific UoM category. Used to find related units within a category and to validate category constraints such as ensuring a category has units before deactivation.
6
+
7
+ ## Business Rules
8
+
9
+ - Returns all units with the matching categoryId
10
+ - Returns empty array if no units match
11
+
12
+ ## Process Flow
13
+
14
+ ```mermaid
15
+ flowchart TD
16
+ A[Receive categoryId] --> B[SELECT from Unit where categoryId = input]
17
+ B --> C[Return units array]
18
+ ```
19
+
20
+ ## External Dependencies
21
+
22
+ - None
23
+
24
+ ## Error Scenarios
25
+
26
+ - None