@tailor-platform/erp-kit 0.5.0 → 0.6.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 (262) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/cli.mjs +139 -35
  3. package/package.json +1 -1
  4. package/skills/erp-kit-app-5-impl-backend/SKILL.md +10 -5
  5. package/skills/erp-kit-app-7-impl-review/SKILL.md +1 -1
  6. package/skills/erp-kit-module-6-impl-review/SKILL.md +39 -17
  7. package/src/commands/generate-doc.ts +1 -1
  8. package/src/commands/init-module.test.ts +17 -3
  9. package/src/commands/init-module.ts +0 -12
  10. package/src/commands/lib/discovery.test.ts +13 -3
  11. package/src/commands/lib/discovery.ts +10 -2
  12. package/src/commands/lib/paths.ts +4 -2
  13. package/src/commands/lib/sync-check-tests.test.ts +84 -6
  14. package/src/commands/lib/sync-check-tests.ts +63 -3
  15. package/src/commands/sync-check.ts +7 -3
  16. package/src/generator/generate-app-code.ts +51 -16
  17. package/src/generator/generate-code-boilerplate.test.ts +9 -1
  18. package/src/generator/generate-stubs.ts +4 -0
  19. package/src/generator/scaffold.ts +6 -2
  20. package/src/generator/stub-templates.test.ts +11 -0
  21. package/src/generator/stub-templates.ts +22 -1
  22. package/src/mdschema.ts +39 -3
  23. package/src/modules/inventory/docs/features/inventory-adjustment.md +2 -1
  24. package/src/modules/inventory/docs/features/scrap-management.md +39 -1
  25. package/src/modules/manufacturing/README.md +63 -0
  26. package/src/modules/manufacturing/command/activateBillOfMaterial.generated.ts +6 -0
  27. package/src/modules/manufacturing/command/activateBillOfMaterial.test.ts +166 -0
  28. package/src/modules/manufacturing/command/activateBillOfMaterial.ts +173 -0
  29. package/src/modules/manufacturing/command/activateRouting.generated.ts +6 -0
  30. package/src/modules/manufacturing/command/activateRouting.test.ts +152 -0
  31. package/src/modules/manufacturing/command/activateRouting.ts +92 -0
  32. package/src/modules/manufacturing/command/activateWorkCenter.generated.ts +6 -0
  33. package/src/modules/manufacturing/command/activateWorkCenter.test.ts +135 -0
  34. package/src/modules/manufacturing/command/activateWorkCenter.ts +91 -0
  35. package/src/modules/manufacturing/command/cancelProductionOrder.generated.ts +6 -0
  36. package/src/modules/manufacturing/command/cancelProductionOrder.test.ts +151 -0
  37. package/src/modules/manufacturing/command/cancelProductionOrder.ts +114 -0
  38. package/src/modules/manufacturing/command/closeProductionOrder.generated.ts +6 -0
  39. package/src/modules/manufacturing/command/closeProductionOrder.test.ts +126 -0
  40. package/src/modules/manufacturing/command/closeProductionOrder.ts +87 -0
  41. package/src/modules/manufacturing/command/completeProductionOrder.generated.ts +6 -0
  42. package/src/modules/manufacturing/command/completeProductionOrder.test.ts +132 -0
  43. package/src/modules/manufacturing/command/completeProductionOrder.ts +97 -0
  44. package/src/modules/manufacturing/command/completeWorkOrder.generated.ts +6 -0
  45. package/src/modules/manufacturing/command/completeWorkOrder.test.ts +369 -0
  46. package/src/modules/manufacturing/command/completeWorkOrder.ts +212 -0
  47. package/src/modules/manufacturing/command/createBillOfMaterial.generated.ts +6 -0
  48. package/src/modules/manufacturing/command/createBillOfMaterial.test.ts +210 -0
  49. package/src/modules/manufacturing/command/createBillOfMaterial.ts +176 -0
  50. package/src/modules/manufacturing/command/createProductionOrder.generated.ts +6 -0
  51. package/src/modules/manufacturing/command/createProductionOrder.test.ts +160 -0
  52. package/src/modules/manufacturing/command/createProductionOrder.ts +129 -0
  53. package/src/modules/manufacturing/command/createRouting.generated.ts +6 -0
  54. package/src/modules/manufacturing/command/createRouting.test.ts +168 -0
  55. package/src/modules/manufacturing/command/createRouting.ts +128 -0
  56. package/src/modules/manufacturing/command/createWorkCenter.generated.ts +6 -0
  57. package/src/modules/manufacturing/command/createWorkCenter.test.ts +148 -0
  58. package/src/modules/manufacturing/command/createWorkCenter.ts +131 -0
  59. package/src/modules/manufacturing/command/deactivateBillOfMaterial.generated.ts +6 -0
  60. package/src/modules/manufacturing/command/deactivateBillOfMaterial.test.ts +103 -0
  61. package/src/modules/manufacturing/command/deactivateBillOfMaterial.ts +78 -0
  62. package/src/modules/manufacturing/command/deactivateRouting.generated.ts +6 -0
  63. package/src/modules/manufacturing/command/deactivateRouting.test.ts +112 -0
  64. package/src/modules/manufacturing/command/deactivateRouting.ts +76 -0
  65. package/src/modules/manufacturing/command/deactivateWorkCenter.generated.ts +6 -0
  66. package/src/modules/manufacturing/command/deactivateWorkCenter.test.ts +113 -0
  67. package/src/modules/manufacturing/command/deactivateWorkCenter.ts +85 -0
  68. package/src/modules/manufacturing/command/pauseWorkOrder.generated.ts +6 -0
  69. package/src/modules/manufacturing/command/pauseWorkOrder.test.ts +118 -0
  70. package/src/modules/manufacturing/command/pauseWorkOrder.ts +82 -0
  71. package/src/modules/manufacturing/command/recordInventoryIssueOutcome.generated.ts +6 -0
  72. package/src/modules/manufacturing/command/recordInventoryIssueOutcome.test.ts +183 -0
  73. package/src/modules/manufacturing/command/recordInventoryIssueOutcome.ts +139 -0
  74. package/src/modules/manufacturing/command/recordManufacturingCostSettlementAcknowledgment.generated.ts +6 -0
  75. package/src/modules/manufacturing/command/recordManufacturingCostSettlementAcknowledgment.test.ts +120 -0
  76. package/src/modules/manufacturing/command/recordManufacturingCostSettlementAcknowledgment.ts +110 -0
  77. package/src/modules/manufacturing/command/releaseProductionOrder.generated.ts +6 -0
  78. package/src/modules/manufacturing/command/releaseProductionOrder.test.ts +220 -0
  79. package/src/modules/manufacturing/command/releaseProductionOrder.ts +450 -0
  80. package/src/modules/manufacturing/command/reopenProductionOrder.generated.ts +6 -0
  81. package/src/modules/manufacturing/command/reopenProductionOrder.test.ts +196 -0
  82. package/src/modules/manufacturing/command/reopenProductionOrder.ts +98 -0
  83. package/src/modules/manufacturing/command/reportWorkOrderProgress.generated.ts +6 -0
  84. package/src/modules/manufacturing/command/reportWorkOrderProgress.test.ts +204 -0
  85. package/src/modules/manufacturing/command/reportWorkOrderProgress.ts +129 -0
  86. package/src/modules/manufacturing/command/rescheduleProductionOrder.generated.ts +6 -0
  87. package/src/modules/manufacturing/command/rescheduleProductionOrder.test.ts +185 -0
  88. package/src/modules/manufacturing/command/rescheduleProductionOrder.ts +95 -0
  89. package/src/modules/manufacturing/command/resumeWorkOrder.generated.ts +6 -0
  90. package/src/modules/manufacturing/command/resumeWorkOrder.test.ts +122 -0
  91. package/src/modules/manufacturing/command/resumeWorkOrder.ts +94 -0
  92. package/src/modules/manufacturing/command/reviewManufacturingCostSummary.generated.ts +6 -0
  93. package/src/modules/manufacturing/command/reviewManufacturingCostSummary.test.ts +231 -0
  94. package/src/modules/manufacturing/command/reviewManufacturingCostSummary.ts +137 -0
  95. package/src/modules/manufacturing/command/startWorkOrder.generated.ts +6 -0
  96. package/src/modules/manufacturing/command/startWorkOrder.test.ts +118 -0
  97. package/src/modules/manufacturing/command/startWorkOrder.ts +126 -0
  98. package/src/modules/manufacturing/command/technicallyCompleteProductionOrder.generated.ts +6 -0
  99. package/src/modules/manufacturing/command/technicallyCompleteProductionOrder.test.ts +153 -0
  100. package/src/modules/manufacturing/command/technicallyCompleteProductionOrder.ts +106 -0
  101. package/src/modules/manufacturing/command/unreleaseProductionOrder.generated.ts +6 -0
  102. package/src/modules/manufacturing/command/unreleaseProductionOrder.test.ts +140 -0
  103. package/src/modules/manufacturing/command/unreleaseProductionOrder.ts +131 -0
  104. package/src/modules/manufacturing/command/updateBillOfMaterial.generated.ts +6 -0
  105. package/src/modules/manufacturing/command/updateBillOfMaterial.test.ts +149 -0
  106. package/src/modules/manufacturing/command/updateBillOfMaterial.ts +174 -0
  107. package/src/modules/manufacturing/command/updateProductionOrder.generated.ts +6 -0
  108. package/src/modules/manufacturing/command/updateProductionOrder.test.ts +112 -0
  109. package/src/modules/manufacturing/command/updateProductionOrder.ts +145 -0
  110. package/src/modules/manufacturing/command/updateRouting.generated.ts +6 -0
  111. package/src/modules/manufacturing/command/updateRouting.test.ts +211 -0
  112. package/src/modules/manufacturing/command/updateRouting.ts +124 -0
  113. package/src/modules/manufacturing/command/updateWorkCenter.generated.ts +6 -0
  114. package/src/modules/manufacturing/command/updateWorkCenter.test.ts +152 -0
  115. package/src/modules/manufacturing/command/updateWorkCenter.ts +137 -0
  116. package/src/modules/manufacturing/db/.gitkeep +0 -0
  117. package/src/modules/manufacturing/db/billOfMaterial.ts +70 -0
  118. package/src/modules/manufacturing/db/billOfMaterialLine.ts +49 -0
  119. package/src/modules/manufacturing/db/costVarianceLine.ts +53 -0
  120. package/src/modules/manufacturing/db/manufacturingCostLine.ts +35 -0
  121. package/src/modules/manufacturing/db/manufacturingCostSettlementRecord.ts +39 -0
  122. package/src/modules/manufacturing/db/manufacturingCostSummary.ts +59 -0
  123. package/src/modules/manufacturing/db/productionOrder.ts +83 -0
  124. package/src/modules/manufacturing/db/productionOrderBomSnapshot.ts +44 -0
  125. package/src/modules/manufacturing/db/productionOrderCostBaseline.ts +44 -0
  126. package/src/modules/manufacturing/db/productionOrderMaterialRequirement.ts +57 -0
  127. package/src/modules/manufacturing/db/productionOrderRoutingSnapshot.ts +43 -0
  128. package/src/modules/manufacturing/db/routing.ts +63 -0
  129. package/src/modules/manufacturing/db/routingOperation.ts +57 -0
  130. package/src/modules/manufacturing/db/workCenter.ts +87 -0
  131. package/src/modules/manufacturing/db/workOrder.ts +65 -0
  132. package/src/modules/manufacturing/db/workOrderExecutionEvent.ts +54 -0
  133. package/src/modules/manufacturing/docs/commands/ActivateBillOfMaterial.md +50 -0
  134. package/src/modules/manufacturing/docs/commands/ActivateRouting.md +48 -0
  135. package/src/modules/manufacturing/docs/commands/ActivateWorkCenter.md +49 -0
  136. package/src/modules/manufacturing/docs/commands/CancelProductionOrder.md +48 -0
  137. package/src/modules/manufacturing/docs/commands/CloseProductionOrder.md +46 -0
  138. package/src/modules/manufacturing/docs/commands/CompleteProductionOrder.md +48 -0
  139. package/src/modules/manufacturing/docs/commands/CompleteWorkOrder.md +66 -0
  140. package/src/modules/manufacturing/docs/commands/CreateBillOfMaterial.md +54 -0
  141. package/src/modules/manufacturing/docs/commands/CreateProductionOrder.md +49 -0
  142. package/src/modules/manufacturing/docs/commands/CreateRouting.md +50 -0
  143. package/src/modules/manufacturing/docs/commands/CreateWorkCenter.md +51 -0
  144. package/src/modules/manufacturing/docs/commands/DeactivateBillOfMaterial.md +45 -0
  145. package/src/modules/manufacturing/docs/commands/DeactivateRouting.md +45 -0
  146. package/src/modules/manufacturing/docs/commands/DeactivateWorkCenter.md +45 -0
  147. package/src/modules/manufacturing/docs/commands/PauseWorkOrder.md +44 -0
  148. package/src/modules/manufacturing/docs/commands/RecordInventoryIssueOutcome.md +59 -0
  149. package/src/modules/manufacturing/docs/commands/RecordManufacturingCostSettlementAcknowledgment.md +49 -0
  150. package/src/modules/manufacturing/docs/commands/ReleaseProductionOrder.md +57 -0
  151. package/src/modules/manufacturing/docs/commands/ReopenProductionOrder.md +54 -0
  152. package/src/modules/manufacturing/docs/commands/ReportWorkOrderProgress.md +53 -0
  153. package/src/modules/manufacturing/docs/commands/RescheduleProductionOrder.md +45 -0
  154. package/src/modules/manufacturing/docs/commands/ResumeWorkOrder.md +44 -0
  155. package/src/modules/manufacturing/docs/commands/ReviewManufacturingCostSummary.md +52 -0
  156. package/src/modules/manufacturing/docs/commands/StartWorkOrder.md +46 -0
  157. package/src/modules/manufacturing/docs/commands/TechnicallyCompleteProductionOrder.md +51 -0
  158. package/src/modules/manufacturing/docs/commands/UnreleaseProductionOrder.md +46 -0
  159. package/src/modules/manufacturing/docs/commands/UpdateBillOfMaterial.md +48 -0
  160. package/src/modules/manufacturing/docs/commands/UpdateProductionOrder.md +48 -0
  161. package/src/modules/manufacturing/docs/commands/UpdateRouting.md +52 -0
  162. package/src/modules/manufacturing/docs/commands/UpdateWorkCenter.md +48 -0
  163. package/src/modules/manufacturing/docs/features/bill-of-material-management.md +83 -0
  164. package/src/modules/manufacturing/docs/features/manufacturing-cost-and-variance.md +191 -0
  165. package/src/modules/manufacturing/docs/features/production-order-lifecycle.md +103 -0
  166. package/src/modules/manufacturing/docs/features/routing-and-work-center-definition.md +63 -0
  167. package/src/modules/manufacturing/docs/features/work-order-execution.md +115 -0
  168. package/src/modules/manufacturing/docs/models/BillOfMaterial.md +60 -0
  169. package/src/modules/manufacturing/docs/models/ManufacturingCostSummary.md +66 -0
  170. package/src/modules/manufacturing/docs/models/ProductionOrder.md +76 -0
  171. package/src/modules/manufacturing/docs/models/Routing.md +58 -0
  172. package/src/modules/manufacturing/docs/models/WorkCenter.md +56 -0
  173. package/src/modules/manufacturing/docs/models/WorkOrder.md +63 -0
  174. package/src/modules/manufacturing/docs/queries/DetectBillOfMaterialCircularReference.md +39 -0
  175. package/src/modules/manufacturing/docs/queries/ExplodeBillOfMaterial.md +56 -0
  176. package/src/modules/manufacturing/docs/queries/GetBillOfMaterial.md +37 -0
  177. package/src/modules/manufacturing/docs/queries/GetManufacturingCostSummary.md +39 -0
  178. package/src/modules/manufacturing/docs/queries/GetProductionOrder.md +37 -0
  179. package/src/modules/manufacturing/docs/queries/GetRouting.md +39 -0
  180. package/src/modules/manufacturing/docs/queries/GetWorkCenter.md +35 -0
  181. package/src/modules/manufacturing/docs/queries/GetWorkOrder.md +38 -0
  182. package/src/modules/manufacturing/docs/queries/ListBillOfMaterialsByItem.md +42 -0
  183. package/src/modules/manufacturing/docs/queries/ListManufacturingCostSummariesByStatus.md +41 -0
  184. package/src/modules/manufacturing/docs/queries/ListProductionOrdersByStatus.md +41 -0
  185. package/src/modules/manufacturing/docs/queries/ListRoutingsByItem.md +42 -0
  186. package/src/modules/manufacturing/docs/queries/ListWorkCentersBySite.md +38 -0
  187. package/src/modules/manufacturing/docs/queries/ListWorkOrdersByProductionOrder.md +39 -0
  188. package/src/modules/manufacturing/docs/queries/ListWorkOrdersByWorkCenter.md +43 -0
  189. package/src/modules/manufacturing/executor/.gitkeep +0 -0
  190. package/src/modules/manufacturing/generated/enums.ts +113 -0
  191. package/src/modules/manufacturing/generated/kysely-tailordb.ts +247 -0
  192. package/src/modules/manufacturing/index.ts +2 -0
  193. package/src/modules/manufacturing/lib/_db_deps.ts +22 -0
  194. package/src/modules/manufacturing/lib/errors.generated.ts +592 -0
  195. package/src/modules/manufacturing/lib/permissions.generated.ts +35 -0
  196. package/src/modules/manufacturing/lib/types.ts +111 -0
  197. package/src/modules/manufacturing/module.ts +226 -0
  198. package/src/modules/manufacturing/permissions.ts +3 -0
  199. package/src/modules/manufacturing/query/.gitkeep +0 -0
  200. package/src/modules/manufacturing/query/detectBillOfMaterialCircularReference.generated.ts +5 -0
  201. package/src/modules/manufacturing/query/detectBillOfMaterialCircularReference.test.ts +115 -0
  202. package/src/modules/manufacturing/query/detectBillOfMaterialCircularReference.ts +79 -0
  203. package/src/modules/manufacturing/query/explodeBillOfMaterial.generated.ts +5 -0
  204. package/src/modules/manufacturing/query/explodeBillOfMaterial.test.ts +445 -0
  205. package/src/modules/manufacturing/query/explodeBillOfMaterial.ts +306 -0
  206. package/src/modules/manufacturing/query/getBillOfMaterial.generated.ts +5 -0
  207. package/src/modules/manufacturing/query/getBillOfMaterial.test.ts +64 -0
  208. package/src/modules/manufacturing/query/getBillOfMaterial.ts +27 -0
  209. package/src/modules/manufacturing/query/getManufacturingCostSummary.generated.ts +5 -0
  210. package/src/modules/manufacturing/query/getManufacturingCostSummary.test.ts +147 -0
  211. package/src/modules/manufacturing/query/getManufacturingCostSummary.ts +46 -0
  212. package/src/modules/manufacturing/query/getProductionOrder.generated.ts +5 -0
  213. package/src/modules/manufacturing/query/getProductionOrder.test.ts +139 -0
  214. package/src/modules/manufacturing/query/getProductionOrder.ts +84 -0
  215. package/src/modules/manufacturing/query/getRouting.generated.ts +5 -0
  216. package/src/modules/manufacturing/query/getRouting.test.ts +71 -0
  217. package/src/modules/manufacturing/query/getRouting.ts +34 -0
  218. package/src/modules/manufacturing/query/getWorkCenter.generated.ts +5 -0
  219. package/src/modules/manufacturing/query/getWorkCenter.test.ts +37 -0
  220. package/src/modules/manufacturing/query/getWorkCenter.ts +21 -0
  221. package/src/modules/manufacturing/query/getWorkOrder.generated.ts +5 -0
  222. package/src/modules/manufacturing/query/getWorkOrder.test.ts +73 -0
  223. package/src/modules/manufacturing/query/getWorkOrder.ts +28 -0
  224. package/src/modules/manufacturing/query/listBillOfMaterialsByItem.generated.ts +5 -0
  225. package/src/modules/manufacturing/query/listBillOfMaterialsByItem.test.ts +107 -0
  226. package/src/modules/manufacturing/query/listBillOfMaterialsByItem.ts +58 -0
  227. package/src/modules/manufacturing/query/listManufacturingCostSummariesByStatus.generated.ts +5 -0
  228. package/src/modules/manufacturing/query/listManufacturingCostSummariesByStatus.test.ts +96 -0
  229. package/src/modules/manufacturing/query/listManufacturingCostSummariesByStatus.ts +77 -0
  230. package/src/modules/manufacturing/query/listProductionOrdersByStatus.generated.ts +5 -0
  231. package/src/modules/manufacturing/query/listProductionOrdersByStatus.test.ts +121 -0
  232. package/src/modules/manufacturing/query/listProductionOrdersByStatus.ts +83 -0
  233. package/src/modules/manufacturing/query/listRoutingsByItem.generated.ts +5 -0
  234. package/src/modules/manufacturing/query/listRoutingsByItem.test.ts +110 -0
  235. package/src/modules/manufacturing/query/listRoutingsByItem.ts +54 -0
  236. package/src/modules/manufacturing/query/listWorkCentersBySite.generated.ts +5 -0
  237. package/src/modules/manufacturing/query/listWorkCentersBySite.test.ts +81 -0
  238. package/src/modules/manufacturing/query/listWorkCentersBySite.ts +70 -0
  239. package/src/modules/manufacturing/query/listWorkOrdersByProductionOrder.generated.ts +5 -0
  240. package/src/modules/manufacturing/query/listWorkOrdersByProductionOrder.test.ts +102 -0
  241. package/src/modules/manufacturing/query/listWorkOrdersByProductionOrder.ts +53 -0
  242. package/src/modules/manufacturing/query/listWorkOrdersByWorkCenter.generated.ts +5 -0
  243. package/src/modules/manufacturing/query/listWorkOrdersByWorkCenter.test.ts +143 -0
  244. package/src/modules/manufacturing/query/listWorkOrdersByWorkCenter.ts +56 -0
  245. package/src/modules/manufacturing/seed/index.ts +19 -0
  246. package/src/modules/manufacturing/tailor.config.ts +13 -0
  247. package/src/modules/manufacturing/tailor.d.ts +13 -0
  248. package/src/modules/manufacturing/testing/commandTestUtils.ts +29 -0
  249. package/src/modules/manufacturing/testing/fixtures.ts +402 -0
  250. package/templates/scaffold/app/backend/package.json +9 -2
  251. package/templates/scaffold/app/backend/src/tests/utils/graphql-client.ts +66 -0
  252. package/templates/scaffold/app/backend/src/tests/utils/setup.ts +21 -0
  253. package/templates/scaffold/app/backend/tsconfig.json +9 -2
  254. package/templates/scaffold/app/backend/vitest.config.ts +35 -0
  255. package/templates/scaffold/app/frontend/package.json +2 -2
  256. package/templates/scaffold/module/__dot__gitignore +3 -0
  257. package/templates/scaffold/module/eslint.config.js +31 -0
  258. package/templates/scaffold/module/generated/kysely-tailordb.ts +3 -0
  259. package/templates/scaffold/module/lib/types.ts +1 -6
  260. package/templates/scaffold/module/package.json +26 -0
  261. package/templates/scaffold/module/tsconfig.json +16 -0
  262. /package/{templates/scaffold/module/generated → src/modules/manufacturing/command}/.gitkeep +0 -0
@@ -0,0 +1,81 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { createMockDb } from "../../../testing/index";
3
+ import type { DB } from "../generated/kysely-tailordb";
4
+ import { SiteScopeRequiredError } from "../lib/errors.generated";
5
+ import { baseActiveWorkCenter, baseDraftWorkCenter } from "../testing/fixtures";
6
+ import { expectOk, expectErr } from "../testing/commandTestUtils";
7
+ import { run } from "./listWorkCentersBySite";
8
+
9
+ describe("listWorkCentersBySite", () => {
10
+ it("lists work centers for a site", async () => {
11
+ const { db, spies } = createMockDb<DB>();
12
+ spies.select.mockReturnValueOnce([baseActiveWorkCenter, baseDraftWorkCenter]);
13
+
14
+ const result = await run(db, {
15
+ companyId: "company-1",
16
+ siteId: "site-1",
17
+ });
18
+ const { items } = expectOk<{ items: unknown[]; hasNextPage: boolean }>(result as never);
19
+
20
+ expect(items).toHaveLength(2);
21
+ });
22
+
23
+ it("filters work centers by status when provided", async () => {
24
+ const { db, spies } = createMockDb<DB>();
25
+ spies.select.mockReturnValueOnce([baseActiveWorkCenter]);
26
+
27
+ const result = await run(db, {
28
+ companyId: "company-1",
29
+ siteId: "site-1",
30
+ status: "ACTIVE",
31
+ });
32
+ const { items } = expectOk<{ items: unknown[]; hasNextPage: boolean }>(result as never);
33
+
34
+ expect(items).toHaveLength(1);
35
+ });
36
+
37
+ it("filters work centers by work-center type and accepts name ordering", async () => {
38
+ const { db, spies } = createMockDb<DB>();
39
+ spies.select.mockReturnValueOnce([{ ...baseActiveWorkCenter, name: "Assembly Cell A" }]);
40
+
41
+ const result = await run(db, {
42
+ companyId: "company-1",
43
+ siteId: "site-1",
44
+ workCenterType: "ASSEMBLY",
45
+ orderBy: "name",
46
+ });
47
+ const { items } = expectOk<{ items: { code: string }[]; hasNextPage: boolean }>(
48
+ result as never,
49
+ );
50
+
51
+ expect(items).toHaveLength(1);
52
+ expect(items[0].code).toBe(baseActiveWorkCenter.code);
53
+ });
54
+
55
+ it("returns an empty list when the site has no work centers", async () => {
56
+ const { db, spies } = createMockDb<DB>();
57
+ spies.select.mockReturnValueOnce([]);
58
+
59
+ const result = await run(db, {
60
+ companyId: "company-1",
61
+ siteId: "site-1",
62
+ });
63
+ const { items } = expectOk<{ items: unknown[]; hasNextPage: boolean }>(result as never);
64
+
65
+ expect(items).toHaveLength(0);
66
+ });
67
+
68
+ it("returns error when company scope is missing", async () => {
69
+ const { db } = createMockDb<DB>();
70
+
71
+ const result = await run(db, { companyId: "", siteId: "site-1" });
72
+ expectErr(result as never, SiteScopeRequiredError);
73
+ });
74
+
75
+ it("returns error when site scope is missing", async () => {
76
+ const { db } = createMockDb<DB>();
77
+
78
+ const result = await run(db, { companyId: "company-1", siteId: "" });
79
+ expectErr(result as never, SiteScopeRequiredError);
80
+ });
81
+ });
@@ -0,0 +1,70 @@
1
+ import type { DB } from "../generated/kysely-tailordb";
2
+ import { SiteScopeRequiredError } from "../lib/errors.generated";
3
+ import {
4
+ ok,
5
+ err,
6
+ type ReadonlyDB,
7
+ type PaginationInput,
8
+ buildPaginatedResult,
9
+ DEFAULT_PAGE_SIZE,
10
+ } from "@tailor-platform/erp-kit/module";
11
+
12
+ type OrderByField = "code" | "name";
13
+
14
+ export interface ListWorkCentersBySiteInput extends PaginationInput<OrderByField> {
15
+ companyId: string;
16
+ siteId: string;
17
+ status?: string;
18
+ workCenterType?: string;
19
+ }
20
+
21
+ /**
22
+ * Function: listWorkCentersBySite
23
+ *
24
+ * Lists work centers for one company and site with optional status or
25
+ * work-center-type filters and code/name ordering.
26
+ */
27
+ export async function run(db: ReadonlyDB<DB>, input: ListWorkCentersBySiteInput) {
28
+ if (!input.companyId || !input.siteId) {
29
+ return err(new SiteScopeRequiredError(input.companyId ?? input.siteId ?? "missing"));
30
+ }
31
+
32
+ const limit = input.limit ?? DEFAULT_PAGE_SIZE;
33
+ const offset = input.offset ?? 0;
34
+ const orderBy = (input.orderBy ?? "code") as "code" | "name";
35
+ const orderDirection = input.orderDirection ?? "asc";
36
+
37
+ let query = db
38
+ .selectFrom("WorkCenter")
39
+ .selectAll()
40
+ .where("companyId", "=", input.companyId)
41
+ .where("siteId", "=", input.siteId);
42
+
43
+ if (input.status) {
44
+ query = query.where("status", "=", input.status as "DRAFT" | "ACTIVE" | "INACTIVE");
45
+ }
46
+
47
+ if (input.workCenterType) {
48
+ query = (query as never as { where: (...args: unknown[]) => typeof query }).where(
49
+ "workCenterType",
50
+ "=",
51
+ input.workCenterType,
52
+ );
53
+ }
54
+
55
+ const items = await (
56
+ query as never as {
57
+ orderBy: (...args: unknown[]) => {
58
+ limit: (...args: unknown[]) => {
59
+ offset: (...args: unknown[]) => { execute: () => Promise<unknown[]> };
60
+ };
61
+ };
62
+ }
63
+ )
64
+ .orderBy(orderBy, orderDirection)
65
+ .limit(limit + 1)
66
+ .offset(offset)
67
+ .execute();
68
+
69
+ return ok(buildPaginatedResult(items, limit));
70
+ }
@@ -0,0 +1,5 @@
1
+ // @generated — do not edit
2
+ import { run } from "./listWorkOrdersByProductionOrder";
3
+ import { defineQuery } from "@tailor-platform/erp-kit/module";
4
+
5
+ export const listWorkOrdersByProductionOrder = defineQuery(run);
@@ -0,0 +1,102 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { createMockDb } from "../../../testing/index";
3
+ import type { DB } from "../generated/kysely-tailordb";
4
+ import { expectOk, expectErr } from "../testing/commandTestUtils";
5
+ import { basePendingWorkOrder, baseInProgressWorkOrder } from "../testing/fixtures";
6
+ import { ProductionOrderReferenceRequiredError } from "../lib/errors.generated";
7
+ import { run } from "./listWorkOrdersByProductionOrder";
8
+
9
+ describe("listWorkOrdersByProductionOrder", () => {
10
+ it("lists work orders for a production order in sequence order", async () => {
11
+ const { db, spies } = createMockDb<DB>();
12
+ const workOrder20 = {
13
+ ...basePendingWorkOrder,
14
+ id: "work-order-20",
15
+ routingOperationSequenceNumber: 20,
16
+ };
17
+ spies.select.mockReturnValueOnce([basePendingWorkOrder, workOrder20]);
18
+
19
+ const result = await run(db, {
20
+ productionOrderId: "production-order-2",
21
+ });
22
+ const { items } = expectOk<{ items: unknown[]; hasNextPage: boolean }>(result as never);
23
+
24
+ expect(items).toHaveLength(2);
25
+ expect(items[0]).toEqual(basePendingWorkOrder);
26
+ expect(items[1]).toEqual(workOrder20);
27
+ });
28
+
29
+ it("filters work orders by status when provided", async () => {
30
+ const { db, spies } = createMockDb<DB>();
31
+ spies.select.mockReturnValueOnce([baseInProgressWorkOrder]);
32
+
33
+ const result = await run(db, {
34
+ productionOrderId: "production-order-2",
35
+ status: "IN_PROGRESS",
36
+ });
37
+ const { items } = expectOk<{ items: unknown[]; hasNextPage: boolean }>(result as never);
38
+
39
+ expect(items).toHaveLength(1);
40
+ expect(items[0]).toEqual(baseInProgressWorkOrder);
41
+ });
42
+
43
+ it("filters work orders by work center when provided", async () => {
44
+ const { db, spies } = createMockDb<DB>();
45
+ spies.select.mockReturnValueOnce([basePendingWorkOrder]);
46
+
47
+ const result = await run(db, {
48
+ productionOrderId: "production-order-2",
49
+ workCenterId: "work-center-2",
50
+ });
51
+ const { items } = expectOk<{ items: unknown[]; hasNextPage: boolean }>(result as never);
52
+
53
+ expect(items).toHaveLength(1);
54
+ expect(items[0]).toEqual(basePendingWorkOrder);
55
+ });
56
+
57
+ it("returns summary fields with sequence and progress data", async () => {
58
+ const { db, spies } = createMockDb<DB>();
59
+ spies.select.mockReturnValueOnce([baseInProgressWorkOrder]);
60
+
61
+ const result = await run(db, {
62
+ productionOrderId: "production-order-2",
63
+ });
64
+ const { items } = expectOk<{
65
+ items: {
66
+ routingOperationSequenceNumber: number;
67
+ completedQuantity: number;
68
+ plannedQuantity: number;
69
+ }[];
70
+ hasNextPage: boolean;
71
+ }>(result as never);
72
+
73
+ expect(items[0].routingOperationSequenceNumber).toBe(10);
74
+ expect(items[0].completedQuantity).toBe(50);
75
+ expect(items[0].plannedQuantity).toBe(100);
76
+ });
77
+
78
+ it("returns an empty list when no work orders exist", async () => {
79
+ const { db, spies } = createMockDb<DB>();
80
+ spies.select.mockReturnValueOnce([]);
81
+
82
+ const result = await run(db, {
83
+ productionOrderId: "production-order-2",
84
+ });
85
+ const { items, hasNextPage } = expectOk<{
86
+ items: unknown[];
87
+ hasNextPage: boolean;
88
+ }>(result as never);
89
+
90
+ expect(items).toHaveLength(0);
91
+ expect(hasNextPage).toBe(false);
92
+ });
93
+
94
+ it("returns error when the production-order reference is missing", async () => {
95
+ const { db } = createMockDb<DB>();
96
+
97
+ const result = await run(db, {
98
+ productionOrderId: "",
99
+ });
100
+ expectErr(result as never, ProductionOrderReferenceRequiredError);
101
+ });
102
+ });
@@ -0,0 +1,53 @@
1
+ import type { DB } from "../generated/kysely-tailordb";
2
+ import { ProductionOrderReferenceRequiredError } from "../lib/errors.generated";
3
+ import {
4
+ ok,
5
+ err,
6
+ type ReadonlyDB,
7
+ type PaginationInput,
8
+ buildPaginatedResult,
9
+ DEFAULT_PAGE_SIZE,
10
+ } from "@tailor-platform/erp-kit/module";
11
+
12
+ type OrderByField = "routingOperationSequenceNumber";
13
+
14
+ export interface ListWorkOrdersByProductionOrderInput extends PaginationInput<OrderByField> {
15
+ productionOrderId: string;
16
+ status?: string;
17
+ workCenterId?: string;
18
+ }
19
+
20
+ export async function run(db: ReadonlyDB<DB>, input: ListWorkOrdersByProductionOrderInput) {
21
+ if (!input.productionOrderId) {
22
+ return err(new ProductionOrderReferenceRequiredError("missing"));
23
+ }
24
+
25
+ const limit = input.limit ?? DEFAULT_PAGE_SIZE;
26
+ const offset = input.offset ?? 0;
27
+ const orderBy = input.orderBy ?? "routingOperationSequenceNumber";
28
+ const orderDirection = input.orderDirection ?? "asc";
29
+
30
+ let query = db
31
+ .selectFrom("WorkOrder")
32
+ .selectAll()
33
+ .where("productionOrderId", "=", input.productionOrderId);
34
+
35
+ if (input.status) {
36
+ query = query.where(
37
+ "status",
38
+ "=",
39
+ input.status as "PENDING" | "IN_PROGRESS" | "PAUSED" | "COMPLETE" | "CANCELLED",
40
+ );
41
+ }
42
+ if (input.workCenterId) {
43
+ query = query.where("workCenterId", "=", input.workCenterId);
44
+ }
45
+
46
+ const items = await query
47
+ .orderBy(orderBy, orderDirection)
48
+ .limit(limit + 1)
49
+ .offset(offset)
50
+ .execute();
51
+
52
+ return ok(buildPaginatedResult(items, limit));
53
+ }
@@ -0,0 +1,5 @@
1
+ // @generated — do not edit
2
+ import { run } from "./listWorkOrdersByWorkCenter";
3
+ import { defineQuery } from "@tailor-platform/erp-kit/module";
4
+
5
+ export const listWorkOrdersByWorkCenter = defineQuery(run);
@@ -0,0 +1,143 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { createMockDb } from "../../../testing/index";
3
+ import type { DB } from "../generated/kysely-tailordb";
4
+ import { expectOk, expectErr } from "../testing/commandTestUtils";
5
+ import {
6
+ basePendingWorkOrder,
7
+ baseInProgressWorkOrder,
8
+ baseActiveWorkCenter,
9
+ } from "../testing/fixtures";
10
+ import { WorkCenterReferenceRequiredError, WorkCenterNotFoundError } from "../lib/errors.generated";
11
+ import { run } from "./listWorkOrdersByWorkCenter";
12
+
13
+ describe("listWorkOrdersByWorkCenter", () => {
14
+ it("lists pending and in-progress work orders for one work center across multiple production orders", async () => {
15
+ const { db, spies } = createMockDb<DB>();
16
+ const workOrderFromAnotherPO = {
17
+ ...basePendingWorkOrder,
18
+ id: "work-order-10",
19
+ productionOrderId: "production-order-3",
20
+ };
21
+ // 1st select: WorkCenter lookup
22
+ spies.select.mockReturnValueOnce(baseActiveWorkCenter);
23
+ // 2nd select: WorkOrder list
24
+ spies.select.mockReturnValueOnce([
25
+ basePendingWorkOrder,
26
+ baseInProgressWorkOrder,
27
+ workOrderFromAnotherPO,
28
+ ]);
29
+
30
+ const result = await run(db, {
31
+ workCenterId: "work-center-2",
32
+ });
33
+ const { items } = expectOk<{ items: unknown[]; hasNextPage: boolean }>(result as never);
34
+
35
+ expect(items).toHaveLength(3);
36
+ });
37
+
38
+ it("filters work orders by status when provided", async () => {
39
+ const { db, spies } = createMockDb<DB>();
40
+ // 1st select: WorkCenter lookup
41
+ spies.select.mockReturnValueOnce(baseActiveWorkCenter);
42
+ // 2nd select: WorkOrder list filtered by status
43
+ spies.select.mockReturnValueOnce([baseInProgressWorkOrder]);
44
+
45
+ const result = await run(db, {
46
+ workCenterId: "work-center-2",
47
+ status: "IN_PROGRESS",
48
+ });
49
+ const { items } = expectOk<{ items: unknown[]; hasNextPage: boolean }>(result as never);
50
+
51
+ expect(items).toHaveLength(1);
52
+ expect(items[0]).toEqual(baseInProgressWorkOrder);
53
+ });
54
+
55
+ it("orders the result for bottleneck review by execution priority and planned timing", async () => {
56
+ const { db, spies } = createMockDb<DB>();
57
+ const workOrderSeq20 = {
58
+ ...basePendingWorkOrder,
59
+ id: "work-order-20",
60
+ routingOperationSequenceNumber: 20,
61
+ };
62
+ // 1st select: WorkCenter lookup
63
+ spies.select.mockReturnValueOnce(baseActiveWorkCenter);
64
+ // 2nd select: WorkOrder list ordered by routingOperationSequenceNumber asc
65
+ spies.select.mockReturnValueOnce([basePendingWorkOrder, workOrderSeq20]);
66
+
67
+ const result = await run(db, {
68
+ workCenterId: "work-center-2",
69
+ });
70
+ const { items } = expectOk<{
71
+ items: { routingOperationSequenceNumber: number }[];
72
+ hasNextPage: boolean;
73
+ }>(result as never);
74
+
75
+ expect(items[0].routingOperationSequenceNumber).toBe(10);
76
+ expect(items[1].routingOperationSequenceNumber).toBe(20);
77
+ });
78
+
79
+ it("returns summary fields with production-order reference operation sequence and progress totals", async () => {
80
+ const { db, spies } = createMockDb<DB>();
81
+ // 1st select: WorkCenter lookup
82
+ spies.select.mockReturnValueOnce(baseActiveWorkCenter);
83
+ // 2nd select: WorkOrder list
84
+ spies.select.mockReturnValueOnce([baseInProgressWorkOrder]);
85
+
86
+ const result = await run(db, {
87
+ workCenterId: "work-center-2",
88
+ });
89
+ const { items } = expectOk<{
90
+ items: {
91
+ productionOrderId: string;
92
+ routingOperationSequenceNumber: number;
93
+ completedQuantity: number;
94
+ plannedQuantity: number;
95
+ }[];
96
+ hasNextPage: boolean;
97
+ }>(result as never);
98
+
99
+ expect(items[0].productionOrderId).toBe("production-order-2");
100
+ expect(items[0].routingOperationSequenceNumber).toBe(10);
101
+ expect(items[0].completedQuantity).toBe(50);
102
+ expect(items[0].plannedQuantity).toBe(100);
103
+ });
104
+
105
+ it("returns an empty list when the work center has no assigned work orders", async () => {
106
+ const { db, spies } = createMockDb<DB>();
107
+ // 1st select: WorkCenter lookup
108
+ spies.select.mockReturnValueOnce(baseActiveWorkCenter);
109
+ // 2nd select: empty WorkOrder list
110
+ spies.select.mockReturnValueOnce([]);
111
+
112
+ const result = await run(db, {
113
+ workCenterId: "work-center-2",
114
+ });
115
+ const { items, hasNextPage } = expectOk<{
116
+ items: unknown[];
117
+ hasNextPage: boolean;
118
+ }>(result as never);
119
+
120
+ expect(items).toHaveLength(0);
121
+ expect(hasNextPage).toBe(false);
122
+ });
123
+
124
+ it("returns error when the work-center reference is missing", async () => {
125
+ const { db } = createMockDb<DB>();
126
+
127
+ const result = await run(db, {
128
+ workCenterId: "",
129
+ });
130
+ expectErr(result as never, WorkCenterReferenceRequiredError);
131
+ });
132
+
133
+ it("returns error when the work center does not exist", async () => {
134
+ const { db, spies } = createMockDb<DB>();
135
+ // 1st select: WorkCenter lookup returns undefined
136
+ spies.select.mockReturnValueOnce(undefined);
137
+
138
+ const result = await run(db, {
139
+ workCenterId: "nonexistent-wc",
140
+ });
141
+ expectErr(result as never, WorkCenterNotFoundError);
142
+ });
143
+ });
@@ -0,0 +1,56 @@
1
+ import type { DB } from "../generated/kysely-tailordb";
2
+ import { WorkCenterReferenceRequiredError, WorkCenterNotFoundError } from "../lib/errors.generated";
3
+ import {
4
+ ok,
5
+ err,
6
+ type ReadonlyDB,
7
+ type PaginationInput,
8
+ buildPaginatedResult,
9
+ DEFAULT_PAGE_SIZE,
10
+ } from "@tailor-platform/erp-kit/module";
11
+
12
+ type OrderByField = "routingOperationSequenceNumber";
13
+
14
+ export interface ListWorkOrdersByWorkCenterInput extends PaginationInput<OrderByField> {
15
+ workCenterId: string;
16
+ status?: string;
17
+ }
18
+
19
+ export async function run(db: ReadonlyDB<DB>, input: ListWorkOrdersByWorkCenterInput) {
20
+ if (!input.workCenterId) {
21
+ return err(new WorkCenterReferenceRequiredError("missing"));
22
+ }
23
+
24
+ const workCenter = await db
25
+ .selectFrom("WorkCenter")
26
+ .selectAll()
27
+ .where("id", "=", input.workCenterId)
28
+ .executeTakeFirst();
29
+
30
+ if (!workCenter) {
31
+ return err(new WorkCenterNotFoundError(input.workCenterId));
32
+ }
33
+
34
+ const limit = input.limit ?? DEFAULT_PAGE_SIZE;
35
+ const offset = input.offset ?? 0;
36
+ const orderBy = input.orderBy ?? "routingOperationSequenceNumber";
37
+ const orderDirection = input.orderDirection ?? "asc";
38
+
39
+ let query = db.selectFrom("WorkOrder").selectAll().where("workCenterId", "=", input.workCenterId);
40
+
41
+ if (input.status) {
42
+ query = query.where(
43
+ "status",
44
+ "=",
45
+ input.status as "PENDING" | "IN_PROGRESS" | "PAUSED" | "COMPLETE" | "CANCELLED",
46
+ );
47
+ }
48
+
49
+ const items = await query
50
+ .orderBy(orderBy, orderDirection)
51
+ .limit(limit + 1)
52
+ .offset(offset)
53
+ .execute();
54
+
55
+ return ok(buildPaginatedResult(items, limit));
56
+ }
@@ -0,0 +1,19 @@
1
+ // Export seed data maps here.
2
+ // Use PascalCase names matching entity types — `erp-kit app generate seed`
3
+ // discovers exports automatically and writes <ExportName>.jsonl files.
4
+ //
5
+ // Example:
6
+ //
7
+ // import { uuidv5 } from "../../../shared/uuidv5";
8
+ // const NS = "erp-kit:<module-name>";
9
+ //
10
+ // export const entityIds = {
11
+ // foo: uuidv5(NS, "entity:foo"),
12
+ // } as const;
13
+ //
14
+ // const entities: Record<string, SeedRow> = {
15
+ // [entityIds.foo]: { name: "Foo", ... },
16
+ // };
17
+ //
18
+ // // Re-export with PascalCase entity name
19
+ // export { entities as Entity };
@@ -0,0 +1,13 @@
1
+ import { defineConfig, definePlugins } from "@tailor-platform/sdk";
2
+ import { kyselyTypePlugin } from "@tailor-platform/sdk/plugin/kysely-type";
3
+ import { enumConstantsPlugin } from "@tailor-platform/sdk/plugin/enum-constants";
4
+
5
+ export default defineConfig({
6
+ name: "manufacturing",
7
+ db: { "main-db": { files: [`./db/*.ts`, `./lib/_db_deps.ts`] } },
8
+ });
9
+
10
+ export const plugins = definePlugins(
11
+ kyselyTypePlugin({ distPath: `./generated/kysely-tailordb.ts` }),
12
+ enumConstantsPlugin({ distPath: "./generated/enums.ts" }),
13
+ );
@@ -0,0 +1,13 @@
1
+ // This file is auto-generated by @tailor-platform/sdk
2
+ // Do not edit this file manually
3
+ // Regenerated automatically when running 'tailor-sdk apply' or 'tailor-sdk generate'
4
+
5
+ declare module "@tailor-platform/sdk" {
6
+ interface AttributeMap {}
7
+ interface AttributeList {
8
+ __tuple?: [];
9
+ }
10
+ interface Env {}
11
+ }
12
+
13
+ export {};
@@ -0,0 +1,29 @@
1
+ import { expect } from "vitest";
2
+
3
+ interface OkResult<T> {
4
+ ok: true;
5
+ value: T;
6
+ }
7
+
8
+ interface ErrResult {
9
+ ok: false;
10
+ error: unknown;
11
+ }
12
+
13
+ export function expectErr(
14
+ result: OkResult<unknown> | ErrResult,
15
+ errorClass: abstract new (...args: never[]) => Error,
16
+ ) {
17
+ expect(result.ok).toBe(false);
18
+ if (!result.ok) {
19
+ expect(result.error).toBeInstanceOf(errorClass);
20
+ }
21
+ }
22
+
23
+ export function expectOk<T>(result: OkResult<T> | ErrResult) {
24
+ expect(result.ok).toBe(true);
25
+ if (!result.ok) {
26
+ throw result.error;
27
+ }
28
+ return result.value;
29
+ }