@naisys/erp 3.0.0-beta.6

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 (150) hide show
  1. package/bin/naisys-erp +2 -0
  2. package/client-dist/android-chrome-192x192.png +0 -0
  3. package/client-dist/android-chrome-512x512.png +0 -0
  4. package/client-dist/apple-touch-icon.png +0 -0
  5. package/client-dist/assets/index-45dVo30p.css +1 -0
  6. package/client-dist/assets/index-Dffms7F_.js +168 -0
  7. package/client-dist/assets/naisys-logo-CzoPnn5I.webp +0 -0
  8. package/client-dist/favicon.ico +0 -0
  9. package/client-dist/index.html +42 -0
  10. package/client-dist/site.webmanifest +22 -0
  11. package/dist/api-reference.js +101 -0
  12. package/dist/audit.js +14 -0
  13. package/dist/auth-middleware.js +203 -0
  14. package/dist/dbConfig.js +10 -0
  15. package/dist/erpDb.js +34 -0
  16. package/dist/erpServer.js +321 -0
  17. package/dist/error-handler.js +17 -0
  18. package/dist/generated/prisma/client.js +35 -0
  19. package/dist/generated/prisma/commonInputTypes.js +11 -0
  20. package/dist/generated/prisma/enums.js +60 -0
  21. package/dist/generated/prisma/internal/class.js +50 -0
  22. package/dist/generated/prisma/internal/prismaNamespace.js +366 -0
  23. package/dist/generated/prisma/models/Attachment.js +2 -0
  24. package/dist/generated/prisma/models/AuditLog.js +2 -0
  25. package/dist/generated/prisma/models/Field.js +2 -0
  26. package/dist/generated/prisma/models/FieldAttachment.js +2 -0
  27. package/dist/generated/prisma/models/FieldRecord.js +2 -0
  28. package/dist/generated/prisma/models/FieldSet.js +2 -0
  29. package/dist/generated/prisma/models/FieldValue.js +2 -0
  30. package/dist/generated/prisma/models/Item.js +2 -0
  31. package/dist/generated/prisma/models/ItemInstance.js +2 -0
  32. package/dist/generated/prisma/models/LaborTicket.js +2 -0
  33. package/dist/generated/prisma/models/Operation.js +2 -0
  34. package/dist/generated/prisma/models/OperationDependency.js +2 -0
  35. package/dist/generated/prisma/models/OperationFieldRef.js +2 -0
  36. package/dist/generated/prisma/models/OperationRun.js +2 -0
  37. package/dist/generated/prisma/models/OperationRunComment.js +2 -0
  38. package/dist/generated/prisma/models/Order.js +2 -0
  39. package/dist/generated/prisma/models/OrderRevision.js +2 -0
  40. package/dist/generated/prisma/models/OrderRun.js +2 -0
  41. package/dist/generated/prisma/models/SchemaVersion.js +2 -0
  42. package/dist/generated/prisma/models/Session.js +2 -0
  43. package/dist/generated/prisma/models/Step.js +2 -0
  44. package/dist/generated/prisma/models/StepRun.js +2 -0
  45. package/dist/generated/prisma/models/User.js +2 -0
  46. package/dist/generated/prisma/models/UserPermission.js +2 -0
  47. package/dist/generated/prisma/models/WorkCenter.js +2 -0
  48. package/dist/generated/prisma/models/WorkCenterUser.js +2 -0
  49. package/dist/generated/prisma/models.js +2 -0
  50. package/dist/hateoas.js +61 -0
  51. package/dist/route-helpers.js +220 -0
  52. package/dist/routes/admin.js +147 -0
  53. package/dist/routes/audit.js +36 -0
  54. package/dist/routes/auth.js +112 -0
  55. package/dist/routes/dispatch.js +174 -0
  56. package/dist/routes/inventory.js +70 -0
  57. package/dist/routes/item-fields.js +220 -0
  58. package/dist/routes/item-instances.js +426 -0
  59. package/dist/routes/items.js +252 -0
  60. package/dist/routes/labor-tickets.js +268 -0
  61. package/dist/routes/operation-dependencies.js +170 -0
  62. package/dist/routes/operation-field-refs.js +263 -0
  63. package/dist/routes/operation-run-comments.js +108 -0
  64. package/dist/routes/operation-run-transitions.js +249 -0
  65. package/dist/routes/operation-runs.js +299 -0
  66. package/dist/routes/operations.js +283 -0
  67. package/dist/routes/order-revision-transitions.js +86 -0
  68. package/dist/routes/order-revisions.js +327 -0
  69. package/dist/routes/order-run-transitions.js +215 -0
  70. package/dist/routes/order-runs.js +335 -0
  71. package/dist/routes/orders.js +262 -0
  72. package/dist/routes/root.js +123 -0
  73. package/dist/routes/schemas.js +31 -0
  74. package/dist/routes/step-field-attachments.js +231 -0
  75. package/dist/routes/step-fields.js +315 -0
  76. package/dist/routes/step-run-fields.js +438 -0
  77. package/dist/routes/step-run-transitions.js +113 -0
  78. package/dist/routes/step-runs.js +324 -0
  79. package/dist/routes/steps.js +283 -0
  80. package/dist/routes/user-permissions.js +100 -0
  81. package/dist/routes/users.js +381 -0
  82. package/dist/routes/work-centers.js +280 -0
  83. package/dist/schema-registry.js +45 -0
  84. package/dist/services/attachment-service.js +118 -0
  85. package/dist/services/field-ref-service.js +74 -0
  86. package/dist/services/field-service.js +114 -0
  87. package/dist/services/field-value-service.js +256 -0
  88. package/dist/services/item-instance-service.js +155 -0
  89. package/dist/services/item-service.js +56 -0
  90. package/dist/services/labor-ticket-service.js +148 -0
  91. package/dist/services/log-file-service.js +11 -0
  92. package/dist/services/operation-dependency-service.js +30 -0
  93. package/dist/services/operation-run-comment-service.js +26 -0
  94. package/dist/services/operation-run-service.js +347 -0
  95. package/dist/services/operation-service.js +132 -0
  96. package/dist/services/order-revision-service.js +264 -0
  97. package/dist/services/order-run-service.js +356 -0
  98. package/dist/services/order-service.js +68 -0
  99. package/dist/services/revision-diff-service.js +194 -0
  100. package/dist/services/step-run-service.js +106 -0
  101. package/dist/services/step-service.js +89 -0
  102. package/dist/services/user-service.js +132 -0
  103. package/dist/services/work-center-service.js +106 -0
  104. package/dist/supervisorAuth.js +16 -0
  105. package/dist/userService.js +118 -0
  106. package/package.json +75 -0
  107. package/prisma/migrations/20260212170352_init/migration.sql +125 -0
  108. package/prisma/migrations/20260308000000_multi_session/migration.sql +23 -0
  109. package/prisma/migrations/20260309000000_add_user_api_key/migration.sql +5 -0
  110. package/prisma/migrations/20260309010000_add_plan_operations/migration.sql +21 -0
  111. package/prisma/migrations/20260309020000_rename_exec_orders_to_order_runs/migration.sql +13 -0
  112. package/prisma/migrations/20260310000000_rename_plan_order_revs_to_order_revisions/migration.sql +22 -0
  113. package/prisma/migrations/20260310100000_rename_plan_orders_to_orders/migration.sql +23 -0
  114. package/prisma/migrations/20260310200000_rename_order_no_to_run_no/migration.sql +3 -0
  115. package/prisma/migrations/20260312000000_add_user_permissions/migration.sql +16 -0
  116. package/prisma/migrations/20260313000000_rename_plan_operations_to_operations/migration.sql +2 -0
  117. package/prisma/migrations/20260313100000_add_steps/migration.sql +20 -0
  118. package/prisma/migrations/20260314000000_add_step_fields/migration.sql +22 -0
  119. package/prisma/migrations/20260315000000_add_operation_runs/migration.sql +24 -0
  120. package/prisma/migrations/20260315100000_add_step_runs/migration.sql +40 -0
  121. package/prisma/migrations/20260316000000_drop_order_name/migration.sql +12 -0
  122. package/prisma/migrations/20260317000000_add_attachments/migration.sql +28 -0
  123. package/prisma/migrations/20260317000000_add_items/migration.sql +21 -0
  124. package/prisma/migrations/20260317100000_add_order_item_id/migration.sql +8 -0
  125. package/prisma/migrations/20260318000000_add_labor_tickets/migration.sql +27 -0
  126. package/prisma/migrations/20260319000000_add_operation_dependencies/migration.sql +17 -0
  127. package/prisma/migrations/20260320000000_step_field_is_array/migration.sql +5 -0
  128. package/prisma/migrations/20260320100000_rename_is_array_to_multi_value/migration.sql +2 -0
  129. package/prisma/migrations/20260320200000_add_field_types/migration.sql +2 -0
  130. package/prisma/migrations/20260321000000_add_multi_set/migration.sql +13 -0
  131. package/prisma/migrations/20260322000000_add_field_sets/migration.sql +90 -0
  132. package/prisma/migrations/20260323000000_add_item_instances/migration.sql +18 -0
  133. package/prisma/migrations/20260324000000_add_field_records/migration.sql +77 -0
  134. package/prisma/migrations/20260325000000_add_run_costs/migration.sql +3 -0
  135. package/prisma/migrations/20260326000000_add_comments/migration.sql +16 -0
  136. package/prisma/migrations/20260327000000_move_assigned_to_op_run/migration.sql +3 -0
  137. package/prisma/migrations/20260328000000_add_step_completion_note/migration.sql +2 -0
  138. package/prisma/migrations/20260328000000_add_step_title/migration.sql +2 -0
  139. package/prisma/migrations/20260329000000_rename_notes_to_release_note/migration.sql +2 -0
  140. package/prisma/migrations/20260329000000_simplify_order_run_dates/migration.sql +5 -0
  141. package/prisma/migrations/20260330000000_add_operation_run_completion_note/migration.sql +2 -0
  142. package/prisma/migrations/20260331000000_add_work_centers/migration.sql +30 -0
  143. package/prisma/migrations/20260401000000_fix_field_values_column_shift/migration.sql +26 -0
  144. package/prisma/migrations/20260402000000_rename_completion_note_to_status_note/migration.sql +5 -0
  145. package/prisma/migrations/20260403000000_add_operation_field_refs/migration.sql +16 -0
  146. package/prisma/migrations/20260404000000_rename_multi_value_to_is_array/migration.sql +2 -0
  147. package/prisma/migrations/20260404100000_add_attachment_public_id/migration.sql +8 -0
  148. package/prisma/migrations/migration_lock.toml +3 -0
  149. package/prisma/schema.prisma +595 -0
  150. package/prisma.config.ts +18 -0
@@ -0,0 +1,27 @@
1
+ -- CreateTable
2
+ CREATE TABLE "labor_tickets" (
3
+ "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
4
+ "operation_run_id" INTEGER NOT NULL,
5
+ "user_id" INTEGER NOT NULL,
6
+ "run_id" INTEGER,
7
+ "clock_in" DATETIME NOT NULL,
8
+ "clock_out" DATETIME,
9
+ "cost" REAL,
10
+ "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
11
+ "created_by" INTEGER NOT NULL,
12
+ "updated_at" DATETIME NOT NULL,
13
+ "updated_by" INTEGER NOT NULL,
14
+ CONSTRAINT "labor_tickets_operation_run_id_fkey" FOREIGN KEY ("operation_run_id") REFERENCES "operation_runs" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
15
+ CONSTRAINT "labor_tickets_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
16
+ CONSTRAINT "labor_tickets_created_by_fkey" FOREIGN KEY ("created_by") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
17
+ CONSTRAINT "labor_tickets_updated_by_fkey" FOREIGN KEY ("updated_by") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
18
+ );
19
+
20
+ -- CreateIndex
21
+ CREATE INDEX "labor_tickets_operation_run_id_idx" ON "labor_tickets"("operation_run_id");
22
+
23
+ -- CreateIndex
24
+ CREATE INDEX "labor_tickets_user_id_clock_out_idx" ON "labor_tickets"("user_id", "clock_out");
25
+
26
+ -- UpdateSchemaVersion
27
+ UPDATE "schema_version" SET "version" = 19, "updated" = datetime('now');
@@ -0,0 +1,17 @@
1
+ -- CreateTable
2
+ CREATE TABLE "operation_dependencies" (
3
+ "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
4
+ "successor_id" INTEGER NOT NULL,
5
+ "predecessor_id" INTEGER NOT NULL,
6
+ "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
7
+ "created_by" INTEGER NOT NULL,
8
+ CONSTRAINT "operation_dependencies_successor_id_fkey" FOREIGN KEY ("successor_id") REFERENCES "operations" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
9
+ CONSTRAINT "operation_dependencies_predecessor_id_fkey" FOREIGN KEY ("predecessor_id") REFERENCES "operations" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
10
+ CONSTRAINT "operation_dependencies_created_by_fkey" FOREIGN KEY ("created_by") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
11
+ );
12
+
13
+ -- CreateIndex
14
+ CREATE UNIQUE INDEX "operation_dependencies_successor_id_predecessor_id_key" ON "operation_dependencies"("successor_id", "predecessor_id");
15
+
16
+ -- UpdateSchemaVersion
17
+ UPDATE "schema_version" SET "version" = 20, "updated" = datetime('now');
@@ -0,0 +1,5 @@
1
+ -- AlterTable: add is_array column
2
+ ALTER TABLE "step_fields" ADD COLUMN "is_array" BOOLEAN NOT NULL DEFAULT 0;
3
+
4
+ -- Migrate existing StringArray fields to string + is_array
5
+ UPDATE "step_fields" SET "type" = 'string', "is_array" = 1 WHERE "type" = 'StringArray';
@@ -0,0 +1,2 @@
1
+ -- RenameColumn: is_array -> multi_value
2
+ ALTER TABLE "step_fields" RENAME COLUMN "is_array" TO "multi_value";
@@ -0,0 +1,2 @@
1
+ -- No DDL needed: SQLite stores enums as TEXT.
2
+ -- New StepFieldType values: date, datetime, yesNo, checkbox
@@ -0,0 +1,13 @@
1
+ -- Add multi_set flag to steps
2
+ ALTER TABLE "steps" ADD COLUMN "multi_set" BOOLEAN NOT NULL DEFAULT 0;
3
+
4
+ -- Add set_index to step_field_values
5
+ ALTER TABLE "step_field_values" ADD COLUMN "set_index" INTEGER NOT NULL DEFAULT 0;
6
+
7
+ -- Replace unique constraint to include set_index
8
+ DROP INDEX "step_field_values_step_run_id_step_field_id_key";
9
+ CREATE UNIQUE INDEX "step_field_values_step_run_id_step_field_id_set_index_key"
10
+ ON "step_field_values" ("step_run_id", "step_field_id", "set_index");
11
+
12
+ -- Bump schema version
13
+ UPDATE "schema_version" SET "version" = 24, "updated" = datetime('now');
@@ -0,0 +1,90 @@
1
+ PRAGMA foreign_keys=OFF;
2
+
3
+ -- 1. Create field_sets table
4
+ CREATE TABLE "field_sets" (
5
+ "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
6
+ "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
7
+ "created_by" INTEGER NOT NULL,
8
+ CONSTRAINT "field_sets_created_by_fkey" FOREIGN KEY ("created_by") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
9
+ );
10
+
11
+ -- 2. Add field_set_id to steps and items
12
+ ALTER TABLE "steps" ADD COLUMN "field_set_id" INTEGER REFERENCES "field_sets"("id");
13
+ ALTER TABLE "items" ADD COLUMN "field_set_id" INTEGER REFERENCES "field_sets"("id");
14
+
15
+ -- 3. Create a field_set for each step that has fields (using step.id as field_set.id)
16
+ INSERT INTO "field_sets" ("id", "created_at", "created_by")
17
+ SELECT DISTINCT s."id", s."created_at", s."created_by"
18
+ FROM "steps" s
19
+ WHERE EXISTS (SELECT 1 FROM "step_fields" sf WHERE sf."step_id" = s."id");
20
+
21
+ -- 4. Link steps to their field_sets
22
+ UPDATE "steps" SET "field_set_id" = "id"
23
+ WHERE "id" IN (SELECT "id" FROM "field_sets");
24
+
25
+ -- 5. Create new fields table
26
+ CREATE TABLE "fields" (
27
+ "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
28
+ "field_set_id" INTEGER NOT NULL,
29
+ "seq_no" INTEGER NOT NULL,
30
+ "label" TEXT NOT NULL,
31
+ "type" TEXT NOT NULL DEFAULT 'string',
32
+ "multi_value" BOOLEAN NOT NULL DEFAULT 0,
33
+ "required" BOOLEAN NOT NULL DEFAULT 0,
34
+ "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
35
+ "created_by" INTEGER NOT NULL,
36
+ "updated_at" DATETIME NOT NULL,
37
+ "updated_by" INTEGER NOT NULL,
38
+ CONSTRAINT "fields_field_set_id_fkey" FOREIGN KEY ("field_set_id") REFERENCES "field_sets" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
39
+ CONSTRAINT "fields_created_by_fkey" FOREIGN KEY ("created_by") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
40
+ CONSTRAINT "fields_updated_by_fkey" FOREIGN KEY ("updated_by") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
41
+ );
42
+ CREATE UNIQUE INDEX "fields_field_set_id_seq_no_key" ON "fields"("field_set_id", "seq_no");
43
+
44
+ -- 6. Copy data from step_fields to fields (step_id = field_set_id since IDs match)
45
+ INSERT INTO "fields" ("id", "field_set_id", "seq_no", "label", "type", "multi_value", "required", "created_at", "created_by", "updated_at", "updated_by")
46
+ SELECT "id", "step_id", "seq_no", "label", "type", "multi_value", "required", "created_at", "created_by", "updated_at", "updated_by"
47
+ FROM "step_fields";
48
+
49
+ -- 7. Recreate step_field_values with FK to fields instead of step_fields
50
+ CREATE TABLE "step_field_values_new" (
51
+ "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
52
+ "step_run_id" INTEGER NOT NULL,
53
+ "step_field_id" INTEGER NOT NULL,
54
+ "set_index" INTEGER NOT NULL DEFAULT 0,
55
+ "value" TEXT NOT NULL DEFAULT '',
56
+ "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
57
+ "created_by" INTEGER NOT NULL,
58
+ "updated_at" DATETIME NOT NULL,
59
+ "updated_by" INTEGER NOT NULL,
60
+ CONSTRAINT "step_field_values_step_run_id_fkey" FOREIGN KEY ("step_run_id") REFERENCES "step_runs" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
61
+ CONSTRAINT "step_field_values_step_field_id_fkey" FOREIGN KEY ("step_field_id") REFERENCES "fields" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
62
+ CONSTRAINT "step_field_values_created_by_fkey" FOREIGN KEY ("created_by") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
63
+ CONSTRAINT "step_field_values_updated_by_fkey" FOREIGN KEY ("updated_by") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
64
+ UNIQUE ("step_run_id", "step_field_id", "set_index")
65
+ );
66
+ INSERT OR IGNORE INTO "step_field_values_new" SELECT * FROM "step_field_values";
67
+
68
+ -- 8. Recreate step_field_attachments (references step_field_values by final name)
69
+ CREATE TABLE "step_field_attachments_new" (
70
+ "step_field_value_id" INTEGER NOT NULL,
71
+ "attachment_id" INTEGER NOT NULL,
72
+ "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
73
+ CONSTRAINT "step_field_attachments_sfv_fkey" FOREIGN KEY ("step_field_value_id") REFERENCES "step_field_values" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
74
+ CONSTRAINT "step_field_attachments_att_fkey" FOREIGN KEY ("attachment_id") REFERENCES "attachments" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
75
+ PRIMARY KEY ("step_field_value_id", "attachment_id")
76
+ );
77
+ INSERT INTO "step_field_attachments_new" SELECT * FROM "step_field_attachments";
78
+
79
+ -- 9. Drop old tables and rename new ones
80
+ DROP TABLE "step_field_attachments";
81
+ DROP TABLE "step_field_values";
82
+ DROP TABLE "step_fields";
83
+
84
+ ALTER TABLE "step_field_values_new" RENAME TO "step_field_values";
85
+ ALTER TABLE "step_field_attachments_new" RENAME TO "step_field_attachments";
86
+
87
+ PRAGMA foreign_keys=ON;
88
+
89
+ -- 11. Update schema version
90
+ INSERT OR REPLACE INTO "schema_version" ("id", "version", "updated") VALUES (1, 27, datetime('now'));
@@ -0,0 +1,18 @@
1
+ CREATE TABLE "item_instances" (
2
+ "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
3
+ "item_id" INTEGER NOT NULL,
4
+ "order_run_id" INTEGER,
5
+ "key" TEXT NOT NULL,
6
+ "quantity" REAL,
7
+ "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
8
+ "created_by" INTEGER NOT NULL,
9
+ "updated_at" DATETIME NOT NULL,
10
+ "updated_by" INTEGER NOT NULL,
11
+ CONSTRAINT "item_instances_item_id_fkey" FOREIGN KEY ("item_id") REFERENCES "items" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
12
+ CONSTRAINT "item_instances_order_run_id_fkey" FOREIGN KEY ("order_run_id") REFERENCES "order_runs" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
13
+ CONSTRAINT "item_instances_created_by_fkey" FOREIGN KEY ("created_by") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
14
+ CONSTRAINT "item_instances_updated_by_fkey" FOREIGN KEY ("updated_by") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
15
+ );
16
+
17
+ CREATE UNIQUE INDEX "item_instances_item_id_key_key" ON "item_instances"("item_id", "key");
18
+ CREATE INDEX "item_instances_order_run_id_idx" ON "item_instances"("order_run_id");
@@ -0,0 +1,77 @@
1
+ PRAGMA foreign_keys=OFF;
2
+
3
+ -- 1. Create field_records table
4
+ CREATE TABLE "field_records" (
5
+ "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
6
+ "field_set_id" INTEGER NOT NULL,
7
+ "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
8
+ "created_by" INTEGER NOT NULL,
9
+ CONSTRAINT "field_records_field_set_id_fkey" FOREIGN KEY ("field_set_id") REFERENCES "field_sets" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
10
+ CONSTRAINT "field_records_created_by_fkey" FOREIGN KEY ("created_by") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
11
+ );
12
+
13
+ -- 2. Create field_values table
14
+ CREATE TABLE "field_values" (
15
+ "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
16
+ "field_record_id" INTEGER NOT NULL,
17
+ "field_id" INTEGER NOT NULL,
18
+ "set_index" INTEGER NOT NULL DEFAULT 0,
19
+ "value" TEXT NOT NULL DEFAULT '',
20
+ "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
21
+ "created_by" INTEGER NOT NULL,
22
+ "updated_at" DATETIME NOT NULL,
23
+ "updated_by" INTEGER NOT NULL,
24
+ CONSTRAINT "field_values_field_record_id_fkey" FOREIGN KEY ("field_record_id") REFERENCES "field_records" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
25
+ CONSTRAINT "field_values_field_id_fkey" FOREIGN KEY ("field_id") REFERENCES "fields" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
26
+ CONSTRAINT "field_values_created_by_fkey" FOREIGN KEY ("created_by") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
27
+ CONSTRAINT "field_values_updated_by_fkey" FOREIGN KEY ("updated_by") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
28
+ UNIQUE ("field_record_id", "field_id", "set_index")
29
+ );
30
+
31
+ -- 3. Create field_attachments table
32
+ CREATE TABLE "field_attachments" (
33
+ "field_value_id" INTEGER NOT NULL,
34
+ "attachment_id" INTEGER NOT NULL,
35
+ "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
36
+ CONSTRAINT "field_attachments_fv_fkey" FOREIGN KEY ("field_value_id") REFERENCES "field_values" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
37
+ CONSTRAINT "field_attachments_att_fkey" FOREIGN KEY ("attachment_id") REFERENCES "attachments" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
38
+ PRIMARY KEY ("field_value_id", "attachment_id")
39
+ );
40
+
41
+ -- 4. Add field_record_id to step_runs and item_instances
42
+ ALTER TABLE "step_runs" ADD COLUMN "field_record_id" INTEGER REFERENCES "field_records"("id");
43
+ ALTER TABLE "item_instances" ADD COLUMN "field_record_id" INTEGER REFERENCES "field_records"("id");
44
+
45
+ -- 5. Create field_records for step_runs that have field values (use step_run.id as field_record.id)
46
+ INSERT INTO "field_records" ("id", "field_set_id", "created_at", "created_by")
47
+ SELECT sr."id", s."field_set_id", sr."created_at", sr."created_by"
48
+ FROM "step_runs" sr
49
+ JOIN "steps" s ON sr."step_id" = s."id"
50
+ WHERE s."field_set_id" IS NOT NULL
51
+ AND EXISTS (SELECT 1 FROM "step_field_values" sfv WHERE sfv."step_run_id" = sr."id");
52
+
53
+ -- 6. Link step_runs to their field_records
54
+ UPDATE "step_runs" SET "field_record_id" = "id"
55
+ WHERE "id" IN (SELECT "id" FROM "field_records");
56
+
57
+ -- 7. Migrate field values (field_record_id = step_run_id, field_id = step_field_id)
58
+ INSERT OR IGNORE INTO "field_values" ("id", "field_record_id", "field_id", "set_index", "value", "created_at", "created_by", "updated_at", "updated_by")
59
+ SELECT sfv."id", sfv."step_run_id", sfv."step_field_id", sfv."set_index", sfv."value",
60
+ sfv."created_at", sfv."created_by", sfv."updated_at", sfv."updated_by"
61
+ FROM "step_field_values" sfv
62
+ WHERE sfv."step_run_id" IN (SELECT "id" FROM "field_records");
63
+
64
+ -- 8. Migrate attachments
65
+ INSERT INTO "field_attachments" ("field_value_id", "attachment_id", "created_at")
66
+ SELECT sfa."step_field_value_id", sfa."attachment_id", sfa."created_at"
67
+ FROM "step_field_attachments" sfa
68
+ WHERE sfa."step_field_value_id" IN (SELECT "id" FROM "field_values");
69
+
70
+ -- 9. Drop old tables
71
+ DROP TABLE "step_field_attachments";
72
+ DROP TABLE "step_field_values";
73
+
74
+ PRAGMA foreign_keys=ON;
75
+
76
+ -- 10. Update schema version
77
+ INSERT OR REPLACE INTO "schema_version" ("id", "version", "updated") VALUES (1, 29, datetime('now'));
@@ -0,0 +1,3 @@
1
+ -- Add cost column to operation_runs and order_runs
2
+ ALTER TABLE "operation_runs" ADD COLUMN "cost" REAL;
3
+ ALTER TABLE "order_runs" ADD COLUMN "cost" REAL;
@@ -0,0 +1,16 @@
1
+ -- Add operation_run_comments table and remove unused feedback column from operation_runs
2
+ CREATE TABLE "operation_run_comments" (
3
+ "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
4
+ "operation_run_id" INTEGER NOT NULL,
5
+ "type" TEXT NOT NULL DEFAULT 'note',
6
+ "body" TEXT NOT NULL,
7
+ "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
8
+ "created_by" INTEGER NOT NULL,
9
+ CONSTRAINT "operation_run_comments_operation_run_id_fkey" FOREIGN KEY ("operation_run_id") REFERENCES "operation_runs" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
10
+ CONSTRAINT "operation_run_comments_created_by_fkey" FOREIGN KEY ("created_by") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
11
+ );
12
+
13
+ CREATE INDEX "operation_run_comments_operation_run_id_idx" ON "operation_run_comments"("operation_run_id");
14
+
15
+ -- Remove unused feedback column
16
+ ALTER TABLE "operation_runs" DROP COLUMN "feedback";
@@ -0,0 +1,3 @@
1
+ -- Move assigned_to from order_runs to operation_runs (as FK to users)
2
+ ALTER TABLE "operation_runs" ADD COLUMN "assigned_to_id" INTEGER REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
3
+ ALTER TABLE "order_runs" DROP COLUMN "assigned_to";
@@ -0,0 +1,2 @@
1
+ -- AlterTable
2
+ ALTER TABLE "step_runs" ADD COLUMN "completion_note" TEXT;
@@ -0,0 +1,2 @@
1
+ -- Add title column to steps
2
+ ALTER TABLE "steps" ADD COLUMN "title" TEXT NOT NULL DEFAULT '';
@@ -0,0 +1,2 @@
1
+ -- AlterTable
2
+ ALTER TABLE "order_runs" RENAME COLUMN "notes" TO "release_note";
@@ -0,0 +1,5 @@
1
+ -- Remove scheduled_start_at, convert due_at from datetime to date string
2
+ ALTER TABLE "order_runs" DROP COLUMN "scheduled_start_at";
3
+
4
+ -- SQLite doesn't support ALTER COLUMN, so we keep due_at as-is (TEXT is already the storage type).
5
+ -- Existing datetime values will still work as date strings since date comparisons sort lexicographically.
@@ -0,0 +1,2 @@
1
+ -- AlterTable
2
+ ALTER TABLE "operation_runs" ADD COLUMN "completion_note" TEXT;
@@ -0,0 +1,30 @@
1
+ -- CreateTable: work_centers
2
+ CREATE TABLE "work_centers" (
3
+ "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
4
+ "key" TEXT NOT NULL,
5
+ "description" TEXT NOT NULL DEFAULT '',
6
+ "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
7
+ "created_by" INTEGER NOT NULL,
8
+ "updated_at" DATETIME NOT NULL,
9
+ "updated_by" INTEGER NOT NULL,
10
+ CONSTRAINT "work_centers_created_by_fkey" FOREIGN KEY ("created_by") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
11
+ CONSTRAINT "work_centers_updated_by_fkey" FOREIGN KEY ("updated_by") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
12
+ );
13
+
14
+ CREATE UNIQUE INDEX "work_centers_key_key" ON "work_centers"("key");
15
+ CREATE INDEX "work_centers_created_at_idx" ON "work_centers"("created_at");
16
+
17
+ -- CreateTable: work_center_users
18
+ CREATE TABLE "work_center_users" (
19
+ "work_center_id" INTEGER NOT NULL,
20
+ "user_id" INTEGER NOT NULL,
21
+ "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
22
+ "created_by" INTEGER NOT NULL,
23
+ CONSTRAINT "work_center_users_work_center_id_fkey" FOREIGN KEY ("work_center_id") REFERENCES "work_centers" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
24
+ CONSTRAINT "work_center_users_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
25
+ CONSTRAINT "work_center_users_created_by_fkey" FOREIGN KEY ("created_by") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
26
+ PRIMARY KEY ("work_center_id", "user_id")
27
+ );
28
+
29
+ -- AlterTable: add work_center_id to operations
30
+ ALTER TABLE "operations" ADD COLUMN "work_center_id" INTEGER REFERENCES "work_centers"("id") ON DELETE SET NULL;
@@ -0,0 +1,26 @@
1
+ -- Fix data corruption from migration 20260322000000_add_field_sets.
2
+ -- That migration used `INSERT INTO ... SELECT * FROM` when recreating
3
+ -- step_field_values with set_index in a new column position. Since
4
+ -- ALTER TABLE ADD COLUMN appends at the end, SELECT * returned columns
5
+ -- in physical order (set_index last), causing all data after field_id
6
+ -- to shift by one column.
7
+ --
8
+ -- In corrupted rows the columns are mapped as:
9
+ -- set_index <- original value
10
+ -- value <- original created_at
11
+ -- created_at <- original created_by (integer)
12
+ -- created_by <- original updated_at (timestamp text)
13
+ -- updated_at <- original updated_by (integer)
14
+ -- updated_by <- original set_index (integer, usually 0)
15
+ --
16
+ -- Detect corrupted rows by checking if created_by holds a timestamp
17
+ -- string instead of an integer user ID.
18
+
19
+ UPDATE "field_values" SET
20
+ "set_index" = "updated_by",
21
+ "value" = "set_index",
22
+ "created_at" = "value",
23
+ "created_by" = "created_at",
24
+ "updated_at" = "created_by",
25
+ "updated_by" = "updated_at"
26
+ WHERE typeof("created_by") = 'text';
@@ -0,0 +1,5 @@
1
+ -- Rename completion_note → status_note on operation_runs
2
+ ALTER TABLE "operation_runs" RENAME COLUMN "completion_note" TO "status_note";
3
+
4
+ -- Rename completion_note → status_note on step_runs
5
+ ALTER TABLE "step_runs" RENAME COLUMN "completion_note" TO "status_note";
@@ -0,0 +1,16 @@
1
+ -- CreateTable: operation_field_refs
2
+ CREATE TABLE "operation_field_refs" (
3
+ "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
4
+ "operation_id" INTEGER NOT NULL,
5
+ "seq_no" INTEGER NOT NULL,
6
+ "title" TEXT NOT NULL,
7
+ "source_step_id" INTEGER NOT NULL,
8
+ "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
9
+ "created_by" INTEGER NOT NULL,
10
+ CONSTRAINT "operation_field_refs_operation_id_fkey" FOREIGN KEY ("operation_id") REFERENCES "operations" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
11
+ CONSTRAINT "operation_field_refs_source_step_id_fkey" FOREIGN KEY ("source_step_id") REFERENCES "steps" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
12
+ CONSTRAINT "operation_field_refs_created_by_fkey" FOREIGN KEY ("created_by") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
13
+ );
14
+
15
+ CREATE UNIQUE INDEX "operation_field_refs_operation_id_seq_no_key" ON "operation_field_refs"("operation_id", "seq_no");
16
+ CREATE UNIQUE INDEX "operation_field_refs_operation_id_source_step_id_key" ON "operation_field_refs"("operation_id", "source_step_id");
@@ -0,0 +1,2 @@
1
+ -- Rename multi_value column back to is_array
2
+ ALTER TABLE "fields" RENAME COLUMN "multi_value" TO "is_array";
@@ -0,0 +1,8 @@
1
+ -- Add public_id column to attachments (nullable initially for migration)
2
+ ALTER TABLE "attachments" ADD COLUMN "public_id" TEXT;
3
+
4
+ -- Populate existing rows with 12-char random hex
5
+ UPDATE "attachments" SET "public_id" = lower(hex(randomblob(6)));
6
+
7
+ -- Make non-nullable and add unique index
8
+ CREATE UNIQUE INDEX "attachments_public_id_key" ON "attachments"("public_id");
@@ -0,0 +1,3 @@
1
+ # Please do not edit this file manually
2
+ # It should be added in your version-control system (e.g., Git)
3
+ provider = "sqlite"