@endora-commerce/mod-quote-requests 0.100.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 (151) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +59 -0
  3. package/dist/admin/index.d.ts +26 -0
  4. package/dist/admin/index.d.ts.map +1 -0
  5. package/dist/admin/index.js +56 -0
  6. package/dist/admin/index.js.map +1 -0
  7. package/dist/admin/pages/RfqCreatePage.d.ts +9 -0
  8. package/dist/admin/pages/RfqCreatePage.d.ts.map +1 -0
  9. package/dist/admin/pages/RfqCreatePage.js +163 -0
  10. package/dist/admin/pages/RfqCreatePage.js.map +1 -0
  11. package/dist/admin/pages/RfqDetail.d.ts +9 -0
  12. package/dist/admin/pages/RfqDetail.d.ts.map +1 -0
  13. package/dist/admin/pages/RfqDetail.js +399 -0
  14. package/dist/admin/pages/RfqDetail.js.map +1 -0
  15. package/dist/admin/pages/RfqList.d.ts +9 -0
  16. package/dist/admin/pages/RfqList.d.ts.map +1 -0
  17. package/dist/admin/pages/RfqList.js +214 -0
  18. package/dist/admin/pages/RfqList.js.map +1 -0
  19. package/dist/admin/validity.d.ts +52 -0
  20. package/dist/admin/validity.d.ts.map +1 -0
  21. package/dist/admin/validity.js +61 -0
  22. package/dist/admin/validity.js.map +1 -0
  23. package/dist/backend/entities/quote-request-event.entity.d.ts +24 -0
  24. package/dist/backend/entities/quote-request-event.entity.d.ts.map +1 -0
  25. package/dist/backend/entities/quote-request-event.entity.js +67 -0
  26. package/dist/backend/entities/quote-request-event.entity.js.map +1 -0
  27. package/dist/backend/entities/quote-request-item.entity.d.ts +34 -0
  28. package/dist/backend/entities/quote-request-item.entity.d.ts.map +1 -0
  29. package/dist/backend/entities/quote-request-item.entity.js +119 -0
  30. package/dist/backend/entities/quote-request-item.entity.js.map +1 -0
  31. package/dist/backend/entities/quote-request-notification-event.entity.d.ts +23 -0
  32. package/dist/backend/entities/quote-request-notification-event.entity.d.ts.map +1 -0
  33. package/dist/backend/entities/quote-request-notification-event.entity.js +72 -0
  34. package/dist/backend/entities/quote-request-notification-event.entity.js.map +1 -0
  35. package/dist/backend/entities/quote-request-revision.entity.d.ts +35 -0
  36. package/dist/backend/entities/quote-request-revision.entity.d.ts.map +1 -0
  37. package/dist/backend/entities/quote-request-revision.entity.js +67 -0
  38. package/dist/backend/entities/quote-request-revision.entity.js.map +1 -0
  39. package/dist/backend/entities/quote-request.entity.d.ts +90 -0
  40. package/dist/backend/entities/quote-request.entity.d.ts.map +1 -0
  41. package/dist/backend/entities/quote-request.entity.js +191 -0
  42. package/dist/backend/entities/quote-request.entity.js.map +1 -0
  43. package/dist/backend/index.d.ts +120 -0
  44. package/dist/backend/index.d.ts.map +1 -0
  45. package/dist/backend/index.js +361 -0
  46. package/dist/backend/index.js.map +1 -0
  47. package/dist/backend/plugin.d.ts +95 -0
  48. package/dist/backend/plugin.d.ts.map +1 -0
  49. package/dist/backend/plugin.js +152 -0
  50. package/dist/backend/plugin.js.map +1 -0
  51. package/dist/backend/routes.admin.d.ts +13 -0
  52. package/dist/backend/routes.admin.d.ts.map +1 -0
  53. package/dist/backend/routes.admin.js +82 -0
  54. package/dist/backend/routes.admin.js.map +1 -0
  55. package/dist/backend/routes.customer.d.ts +18 -0
  56. package/dist/backend/routes.customer.d.ts.map +1 -0
  57. package/dist/backend/routes.customer.js +98 -0
  58. package/dist/backend/routes.customer.js.map +1 -0
  59. package/dist/backend/routes.sales-reps.d.ts +12 -0
  60. package/dist/backend/routes.sales-reps.d.ts.map +1 -0
  61. package/dist/backend/routes.sales-reps.js +57 -0
  62. package/dist/backend/routes.sales-reps.js.map +1 -0
  63. package/dist/backend/services/order-completion-reactor.d.ts +32 -0
  64. package/dist/backend/services/order-completion-reactor.d.ts.map +1 -0
  65. package/dist/backend/services/order-completion-reactor.js +57 -0
  66. package/dist/backend/services/order-completion-reactor.js.map +1 -0
  67. package/dist/backend/services/quote-request-business-id-generator.d.ts +46 -0
  68. package/dist/backend/services/quote-request-business-id-generator.d.ts.map +1 -0
  69. package/dist/backend/services/quote-request-business-id-generator.js +69 -0
  70. package/dist/backend/services/quote-request-business-id-generator.js.map +1 -0
  71. package/dist/backend/services/quote-request-read-port.d.ts +36 -0
  72. package/dist/backend/services/quote-request-read-port.d.ts.map +1 -0
  73. package/dist/backend/services/quote-request-read-port.js +96 -0
  74. package/dist/backend/services/quote-request-read-port.js.map +1 -0
  75. package/dist/backend/services/raised-on-channel.d.ts +23 -0
  76. package/dist/backend/services/raised-on-channel.d.ts.map +1 -0
  77. package/dist/backend/services/raised-on-channel.js +26 -0
  78. package/dist/backend/services/raised-on-channel.js.map +1 -0
  79. package/dist/backend/services/rfq-admin-service.d.ts +75 -0
  80. package/dist/backend/services/rfq-admin-service.d.ts.map +1 -0
  81. package/dist/backend/services/rfq-admin-service.js +487 -0
  82. package/dist/backend/services/rfq-admin-service.js.map +1 -0
  83. package/dist/backend/services/rfq-event-service.d.ts +32 -0
  84. package/dist/backend/services/rfq-event-service.d.ts.map +1 -0
  85. package/dist/backend/services/rfq-event-service.js +28 -0
  86. package/dist/backend/services/rfq-event-service.js.map +1 -0
  87. package/dist/backend/services/rfq-expiry-worker.d.ts +50 -0
  88. package/dist/backend/services/rfq-expiry-worker.d.ts.map +1 -0
  89. package/dist/backend/services/rfq-expiry-worker.js +70 -0
  90. package/dist/backend/services/rfq-expiry-worker.js.map +1 -0
  91. package/dist/backend/services/rfq-notification-service.d.ts +36 -0
  92. package/dist/backend/services/rfq-notification-service.d.ts.map +1 -0
  93. package/dist/backend/services/rfq-notification-service.js +52 -0
  94. package/dist/backend/services/rfq-notification-service.js.map +1 -0
  95. package/dist/backend/services/rfq-revision-service.d.ts +70 -0
  96. package/dist/backend/services/rfq-revision-service.d.ts.map +1 -0
  97. package/dist/backend/services/rfq-revision-service.js +120 -0
  98. package/dist/backend/services/rfq-revision-service.js.map +1 -0
  99. package/dist/backend/services/rfq-service.d.ts +140 -0
  100. package/dist/backend/services/rfq-service.d.ts.map +1 -0
  101. package/dist/backend/services/rfq-service.js +786 -0
  102. package/dist/backend/services/rfq-service.js.map +1 -0
  103. package/dist/backend/services/sales-channel-attributions.d.ts +38 -0
  104. package/dist/backend/services/sales-channel-attributions.d.ts.map +1 -0
  105. package/dist/backend/services/sales-channel-attributions.js +48 -0
  106. package/dist/backend/services/sales-channel-attributions.js.map +1 -0
  107. package/dist/manifest.d.ts +203 -0
  108. package/dist/manifest.d.ts.map +1 -0
  109. package/dist/manifest.js +277 -0
  110. package/dist/manifest.js.map +1 -0
  111. package/dist/migrations/20260424T190112_quote_requests_init.d.ts +19 -0
  112. package/dist/migrations/20260424T190112_quote_requests_init.d.ts.map +1 -0
  113. package/dist/migrations/20260424T190112_quote_requests_init.js +65 -0
  114. package/dist/migrations/20260424T190112_quote_requests_init.js.map +1 -0
  115. package/dist/migrations/20260503T141344_quote_requests_workflow.d.ts +37 -0
  116. package/dist/migrations/20260503T141344_quote_requests_workflow.d.ts.map +1 -0
  117. package/dist/migrations/20260503T141344_quote_requests_workflow.js +251 -0
  118. package/dist/migrations/20260503T141344_quote_requests_workflow.js.map +1 -0
  119. package/dist/migrations/20260611T140415_quote_requests_qr_item_packaging.d.ts +10 -0
  120. package/dist/migrations/20260611T140415_quote_requests_qr_item_packaging.d.ts.map +1 -0
  121. package/dist/migrations/20260611T140415_quote_requests_qr_item_packaging.js +16 -0
  122. package/dist/migrations/20260611T140415_quote_requests_qr_item_packaging.js.map +1 -0
  123. package/dist/migrations/20260611T140417_quote_requests_business_id.d.ts +24 -0
  124. package/dist/migrations/20260611T140417_quote_requests_business_id.d.ts.map +1 -0
  125. package/dist/migrations/20260611T140417_quote_requests_business_id.js +34 -0
  126. package/dist/migrations/20260611T140417_quote_requests_business_id.js.map +1 -0
  127. package/dist/migrations/20260617T095510_quote_requests_backfill_admin_created_awaiting.d.ts +21 -0
  128. package/dist/migrations/20260617T095510_quote_requests_backfill_admin_created_awaiting.d.ts.map +1 -0
  129. package/dist/migrations/20260617T095510_quote_requests_backfill_admin_created_awaiting.js +29 -0
  130. package/dist/migrations/20260617T095510_quote_requests_backfill_admin_created_awaiting.js.map +1 -0
  131. package/dist/migrations/20260718T200342_quote_requests_quote_request_custom_field_values.d.ts +12 -0
  132. package/dist/migrations/20260718T200342_quote_requests_quote_request_custom_field_values.d.ts.map +1 -0
  133. package/dist/migrations/20260718T200342_quote_requests_quote_request_custom_field_values.js +16 -0
  134. package/dist/migrations/20260718T200342_quote_requests_quote_request_custom_field_values.js.map +1 -0
  135. package/dist/migrations/20260912T125614_quote_requests_quote_request_channel_attribution.d.ts +34 -0
  136. package/dist/migrations/20260912T125614_quote_requests_quote_request_channel_attribution.d.ts.map +1 -0
  137. package/dist/migrations/20260912T125614_quote_requests_quote_request_channel_attribution.js +57 -0
  138. package/dist/migrations/20260912T125614_quote_requests_quote_request_channel_attribution.js.map +1 -0
  139. package/dist/migrations/index.d.ts +53 -0
  140. package/dist/migrations/index.d.ts.map +1 -0
  141. package/dist/migrations/index.js +61 -0
  142. package/dist/migrations/index.js.map +1 -0
  143. package/dist/migrations/status-mapping.d.ts +18 -0
  144. package/dist/migrations/status-mapping.d.ts.map +1 -0
  145. package/dist/migrations/status-mapping.js +28 -0
  146. package/dist/migrations/status-mapping.js.map +1 -0
  147. package/docs/quote_requests.md +168 -0
  148. package/i18n/en.json +14 -0
  149. package/i18n/pl.json +14 -0
  150. package/package.json +99 -0
  151. package/tailwind.css +14 -0
@@ -0,0 +1,19 @@
1
+ import { Migration } from '@mikro-orm/migrations';
2
+ /**
3
+ * quote_requests module — Phase 3.5 (T075).
4
+ *
5
+ * Schema notes:
6
+ * - Foreign keys to customer_accounts / organizations / admin_users stay as
7
+ * plain uuid columns without FK constraints: those target tables ship in
8
+ * US2/US3/US4. FKs get added by their respective migrations.
9
+ * - Partial unique index on (organization_id, customer_account_id) WHERE
10
+ * status='draft' enforces "one open draft per customer per organization"
11
+ * (tasks.md T075).
12
+ * - `version` column drives optimistic concurrency — the `If-Match` header
13
+ * path uses a CAS `UPDATE ... WHERE version = $expected`.
14
+ */
15
+ export declare class Migration20260424T190112QuoteRequestsInit extends Migration {
16
+ up(): Promise<void>;
17
+ down(): Promise<void>;
18
+ }
19
+ //# sourceMappingURL=20260424T190112_quote_requests_init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"20260424T190112_quote_requests_init.d.ts","sourceRoot":"","sources":["../../src/migrations/20260424T190112_quote_requests_init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD;;;;;;;;;;;;GAYG;AACH,qBAAa,yCAA0C,SAAQ,SAAS;IACvD,EAAE,IAAI,OAAO,CAAC,IAAI,CAAC;IAgDnB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAIrC"}
@@ -0,0 +1,65 @@
1
+ import { Migration } from '@mikro-orm/migrations';
2
+ /**
3
+ * quote_requests module — Phase 3.5 (T075).
4
+ *
5
+ * Schema notes:
6
+ * - Foreign keys to customer_accounts / organizations / admin_users stay as
7
+ * plain uuid columns without FK constraints: those target tables ship in
8
+ * US2/US3/US4. FKs get added by their respective migrations.
9
+ * - Partial unique index on (organization_id, customer_account_id) WHERE
10
+ * status='draft' enforces "one open draft per customer per organization"
11
+ * (tasks.md T075).
12
+ * - `version` column drives optimistic concurrency — the `If-Match` header
13
+ * path uses a CAS `UPDATE ... WHERE version = $expected`.
14
+ */
15
+ export class Migration20260424T190112QuoteRequestsInit extends Migration {
16
+ async up() {
17
+ this.addSql(`
18
+ create table "quote_requests" (
19
+ "id" uuid not null,
20
+ "organization_id" uuid not null,
21
+ "customer_account_id" uuid not null,
22
+ "status" varchar(32) not null default 'draft',
23
+ "requester_note" text null,
24
+ "assigned_admin_user_id" uuid null,
25
+ "submitted_at" timestamptz null,
26
+ "quoted_at" timestamptz null,
27
+ "responded_at" timestamptz null,
28
+ "expires_at" timestamptz null,
29
+ "quote_terms" jsonb null,
30
+ "version" int not null default 0,
31
+ "created_at" timestamptz not null,
32
+ "updated_at" timestamptz not null,
33
+ constraint "quote_requests_pkey" primary key ("id")
34
+ );
35
+ `);
36
+ this.addSql('create index "quote_requests_organization_id_index" on "quote_requests" ("organization_id");');
37
+ this.addSql('create index "quote_requests_customer_account_id_index" on "quote_requests" ("customer_account_id");');
38
+ this.addSql('create index "quote_requests_status_index" on "quote_requests" ("status");');
39
+ this.addSql(`create unique index "quote_requests_one_draft_per_customer" on "quote_requests" ("organization_id", "customer_account_id") where "status" = 'draft';`);
40
+ this.addSql(`
41
+ create table "quote_request_items" (
42
+ "id" uuid not null,
43
+ "quote_request_id" uuid not null,
44
+ "product_id" uuid not null,
45
+ "product_name" varchar(255) not null,
46
+ "variant_id" uuid null,
47
+ "variant_label" varchar(255) null,
48
+ "quantity" int not null,
49
+ "requester_note" text null,
50
+ "quoted_unit_price" numeric(12,2) null,
51
+ "quoted_discount_percent" numeric(5,2) null,
52
+ "created_at" timestamptz not null,
53
+ "updated_at" timestamptz not null,
54
+ constraint "quote_request_items_pkey" primary key ("id"),
55
+ constraint "quote_request_items_rfq_fk" foreign key ("quote_request_id") references "quote_requests" ("id") on delete cascade
56
+ );
57
+ `);
58
+ this.addSql('create index "quote_request_items_quote_request_id_index" on "quote_request_items" ("quote_request_id");');
59
+ }
60
+ async down() {
61
+ this.addSql('drop table if exists "quote_request_items" cascade;');
62
+ this.addSql('drop table if exists "quote_requests" cascade;');
63
+ }
64
+ }
65
+ //# sourceMappingURL=20260424T190112_quote_requests_init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"20260424T190112_quote_requests_init.js","sourceRoot":"","sources":["../../src/migrations/20260424T190112_quote_requests_init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,yCAA0C,SAAQ,SAAS;IAC7D,KAAK,CAAC,EAAE;QACf,IAAI,CAAC,MAAM,CAAC;;;;;;;;;;;;;;;;;;KAkBX,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,8FAA8F,CAAC,CAAC;QAC5G,IAAI,CAAC,MAAM,CAAC,sGAAsG,CAAC,CAAC;QACpH,IAAI,CAAC,MAAM,CAAC,4EAA4E,CAAC,CAAC;QAC1F,IAAI,CAAC,MAAM,CACT,sJAAsJ,CACvJ,CAAC;QAEF,IAAI,CAAC,MAAM,CAAC;;;;;;;;;;;;;;;;;KAiBX,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,0GAA0G,CAAC,CAAC;IAC1H,CAAC;IAEQ,KAAK,CAAC,IAAI;QACjB,IAAI,CAAC,MAAM,CAAC,qDAAqD,CAAC,CAAC;QACnE,IAAI,CAAC,MAAM,CAAC,gDAAgD,CAAC,CAAC;IAChE,CAAC;CACF"}
@@ -0,0 +1,37 @@
1
+ import { Migration } from '@mikro-orm/migrations';
2
+ /**
3
+ * Quote Requests workflow rewrite (feature 008).
4
+ *
5
+ * What this migration does, in order:
6
+ * 1. Renames quote_requests.requester_note → header_note (the "header note"
7
+ * attached to the whole RFQ, not a per-line note).
8
+ * 2. Adds new lifecycle columns: created_by_admin_user_id,
9
+ * cancellation_reason, awaiting_customer_revision_acceptance,
10
+ * last_customer_seen_revision_number, current_revision_number,
11
+ * approved_at, canceled_at, completed_at, expired_at, converted_order_id.
12
+ * 3. Maps legacy quote_requests.status values to the new six-status enum
13
+ * using mapLegacyStatus() — drops legacy `draft` rows, keeps the rest.
14
+ * 4. Drops the now-redundant legacy columns (quoted_at, responded_at,
15
+ * quote_terms) — the lifecycle data they encoded moves into
16
+ * quote_request_events / quote_request_revisions.
17
+ * 5. Renames quote_request_items.requester_note → line_note,
18
+ * quoted_unit_price → agreed_unit_price,
19
+ * quoted_discount_percent → discount_percent. Adds
20
+ * desired_unit_price, line_currency, product_slug.
21
+ * 6. Creates quote_request_revisions, quote_request_events,
22
+ * quote_request_notification_events.
23
+ * 7. Creates organization_sales_rep_assignments (lives in the organizations
24
+ * module logically — research.md §R9 — but the migration itself is
25
+ * colocated here for atomicity).
26
+ *
27
+ * The down() path is best-effort: it restores the legacy schema enough that
28
+ * a clean rebuild does not crash, but does NOT round-trip data written under
29
+ * the new schema. Spec accepts this trade-off (data-model.md §8).
30
+ *
31
+ * Spec references: data-model.md §1–§6, research.md §R1, §R9.
32
+ */
33
+ export declare class Migration20260503T141344QuoteRequestsWorkflow extends Migration {
34
+ up(): Promise<void>;
35
+ down(): Promise<void>;
36
+ }
37
+ //# sourceMappingURL=20260503T141344_quote_requests_workflow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"20260503T141344_quote_requests_workflow.d.ts","sourceRoot":"","sources":["../../src/migrations/20260503T141344_quote_requests_workflow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAAa,6CAA8C,SAAQ,SAAS;IAC3D,EAAE,IAAI,OAAO,CAAC,IAAI,CAAC;IAqMnB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAoCrC"}
@@ -0,0 +1,251 @@
1
+ import { Migration } from '@mikro-orm/migrations';
2
+ /**
3
+ * Quote Requests workflow rewrite (feature 008).
4
+ *
5
+ * What this migration does, in order:
6
+ * 1. Renames quote_requests.requester_note → header_note (the "header note"
7
+ * attached to the whole RFQ, not a per-line note).
8
+ * 2. Adds new lifecycle columns: created_by_admin_user_id,
9
+ * cancellation_reason, awaiting_customer_revision_acceptance,
10
+ * last_customer_seen_revision_number, current_revision_number,
11
+ * approved_at, canceled_at, completed_at, expired_at, converted_order_id.
12
+ * 3. Maps legacy quote_requests.status values to the new six-status enum
13
+ * using mapLegacyStatus() — drops legacy `draft` rows, keeps the rest.
14
+ * 4. Drops the now-redundant legacy columns (quoted_at, responded_at,
15
+ * quote_terms) — the lifecycle data they encoded moves into
16
+ * quote_request_events / quote_request_revisions.
17
+ * 5. Renames quote_request_items.requester_note → line_note,
18
+ * quoted_unit_price → agreed_unit_price,
19
+ * quoted_discount_percent → discount_percent. Adds
20
+ * desired_unit_price, line_currency, product_slug.
21
+ * 6. Creates quote_request_revisions, quote_request_events,
22
+ * quote_request_notification_events.
23
+ * 7. Creates organization_sales_rep_assignments (lives in the organizations
24
+ * module logically — research.md §R9 — but the migration itself is
25
+ * colocated here for atomicity).
26
+ *
27
+ * The down() path is best-effort: it restores the legacy schema enough that
28
+ * a clean rebuild does not crash, but does NOT round-trip data written under
29
+ * the new schema. Spec accepts this trade-off (data-model.md §8).
30
+ *
31
+ * Spec references: data-model.md §1–§6, research.md §R1, §R9.
32
+ */
33
+ export class Migration20260503T141344QuoteRequestsWorkflow extends Migration {
34
+ async up() {
35
+ // -- 1. Rename header note column -------------------------------
36
+ this.addSql(`alter table "quote_requests" rename column "requester_note" to "header_note";`);
37
+ // -- 2. Add new lifecycle columns -------------------------------
38
+ this.addSql(`
39
+ alter table "quote_requests"
40
+ add column "created_by_admin_user_id" uuid null,
41
+ add column "cancellation_reason" text null,
42
+ add column "awaiting_customer_revision_acceptance" boolean not null default false,
43
+ add column "last_customer_seen_revision_number" int not null default 0,
44
+ add column "current_revision_number" int not null default 0,
45
+ add column "approved_at" timestamptz null,
46
+ add column "canceled_at" timestamptz null,
47
+ add column "completed_at" timestamptz null,
48
+ add column "expired_at" timestamptz null,
49
+ add column "converted_order_id" uuid null;
50
+ `);
51
+ // -- 3. Drop legacy partial unique index that referenced 'draft'.
52
+ // Has to be dropped BEFORE we remap statuses or the unique
53
+ // constraint can fire spuriously.
54
+ this.addSql(`drop index if exists "quote_requests_one_draft_per_customer";`);
55
+ // -- 4. Status mapping. Postgres lets us update the column
56
+ // in-place because it's stored as varchar(32), not a true
57
+ // enum type. The legacy CHECK is implicit (no constraint
58
+ // defined in 002).
59
+ // legacy 'draft' → DELETE row
60
+ // legacy 'new' → 'Pending'
61
+ // legacy 'under_review' → 'Pending'
62
+ // legacy 'quoted' → 'Pending' + awaiting_customer_revision_acceptance=true
63
+ // legacy 'accepted' → 'Approved' (+ approved_at = updated_at)
64
+ // legacy 'rejected' → 'Canceled' (+ canceled_at = updated_at)
65
+ // legacy 'expired' → 'Expired' (+ expired_at = updated_at)
66
+ this.addSql(`delete from "quote_requests" where "status" = 'draft';`);
67
+ this.addSql(`
68
+ update "quote_requests"
69
+ set "status" = 'Pending'
70
+ where "status" in ('new', 'under_review');
71
+ `);
72
+ this.addSql(`
73
+ update "quote_requests"
74
+ set "status" = 'Pending',
75
+ "awaiting_customer_revision_acceptance" = true,
76
+ "current_revision_number" = 1
77
+ where "status" = 'quoted';
78
+ `);
79
+ this.addSql(`
80
+ update "quote_requests"
81
+ set "status" = 'Approved',
82
+ "approved_at" = coalesce("responded_at", "updated_at")
83
+ where "status" = 'accepted';
84
+ `);
85
+ this.addSql(`
86
+ update "quote_requests"
87
+ set "status" = 'Canceled',
88
+ "canceled_at" = coalesce("responded_at", "updated_at")
89
+ where "status" = 'rejected';
90
+ `);
91
+ this.addSql(`
92
+ update "quote_requests"
93
+ set "status" = 'Expired',
94
+ "expired_at" = "updated_at"
95
+ where "status" = 'expired';
96
+ `);
97
+ // -- 5. Add the new CHECK constraint accepting only the six new values.
98
+ this.addSql(`
99
+ alter table "quote_requests"
100
+ add constraint "quote_requests_status_check"
101
+ check ("status" in ('Created from admin','Pending','Canceled','Approved','Completed','Expired'));
102
+ `);
103
+ // -- 6. Drop legacy columns now that all data has been migrated.
104
+ this.addSql(`alter table "quote_requests" drop column "quoted_at";`);
105
+ this.addSql(`alter table "quote_requests" drop column "responded_at";`);
106
+ this.addSql(`alter table "quote_requests" drop column "quote_terms";`);
107
+ // -- 7. Indexes for the expiry worker scan and the assignment-scoped lists.
108
+ this.addSql(`create index "idx_quote_requests_status_updated" on "quote_requests" ("status", "updated_at");`);
109
+ this.addSql(`create index "idx_quote_requests_org_status" on "quote_requests" ("organization_id", "status");`);
110
+ this.addSql(`create index "idx_quote_requests_customer_status" on "quote_requests" ("customer_account_id", "status");`);
111
+ // ============================================================
112
+ // quote_request_items
113
+ // ============================================================
114
+ this.addSql(`alter table "quote_request_items" rename column "requester_note" to "line_note";`);
115
+ this.addSql(`alter table "quote_request_items" rename column "quoted_unit_price" to "agreed_unit_price";`);
116
+ this.addSql(`alter table "quote_request_items" rename column "quoted_discount_percent" to "discount_percent";`);
117
+ this.addSql(`
118
+ alter table "quote_request_items"
119
+ add column "desired_unit_price" numeric(12,2) null,
120
+ add column "line_currency" varchar(3) null,
121
+ add column "product_slug" varchar(255) null;
122
+ `);
123
+ this.addSql(`update "quote_request_items" set "line_currency" = 'PLN' where "line_currency" is null;`);
124
+ this.addSql(`alter table "quote_request_items" alter column "line_currency" set not null;`);
125
+ // ============================================================
126
+ // quote_request_revisions
127
+ // ============================================================
128
+ this.addSql(`
129
+ create table "quote_request_revisions" (
130
+ "id" uuid not null,
131
+ "quote_request_id" uuid not null,
132
+ "revision_number" int not null,
133
+ "created_by_admin_user_id" uuid null,
134
+ "created_by_customer_account_id" uuid null,
135
+ "header_note_snapshot" text null,
136
+ "items_snapshot" jsonb not null,
137
+ "previous_revision_id" uuid null,
138
+ "created_at" timestamptz not null,
139
+ constraint "quote_request_revisions_pkey" primary key ("id"),
140
+ constraint "qrr_rfq_fk" foreign key ("quote_request_id") references "quote_requests" ("id") on delete cascade,
141
+ constraint "qrr_unique_per_rfq" unique ("quote_request_id", "revision_number")
142
+ );
143
+ `);
144
+ this.addSql(`create index "qrr_rfq_idx" on "quote_request_revisions" ("quote_request_id");`);
145
+ // ============================================================
146
+ // quote_request_events
147
+ // ============================================================
148
+ this.addSql(`
149
+ create table "quote_request_events" (
150
+ "id" uuid not null,
151
+ "quote_request_id" uuid not null,
152
+ "event_type" varchar(64) not null,
153
+ "actor_admin_user_id" uuid null,
154
+ "actor_customer_account_id" uuid null,
155
+ "actor_role_label" varchar(64) null,
156
+ "payload" jsonb not null,
157
+ "revision_id" uuid null,
158
+ "created_at" timestamptz not null,
159
+ constraint "quote_request_events_pkey" primary key ("id"),
160
+ constraint "qre_rfq_fk" foreign key ("quote_request_id") references "quote_requests" ("id") on delete cascade,
161
+ constraint "qre_event_type_check" check ("event_type" in (
162
+ 'created','submitted','modified','approved','canceled','expired',
163
+ 'completed','customer-accepted-revision','customer-rejected-revision',
164
+ 're-submitted','note-added'
165
+ )),
166
+ constraint "qre_actor_xor" check (
167
+ ("actor_admin_user_id" is null) <> ("actor_customer_account_id" is null)
168
+ or ("actor_admin_user_id" is null and "actor_customer_account_id" is null)
169
+ )
170
+ );
171
+ `);
172
+ this.addSql(`create index "qre_rfq_created_idx" on "quote_request_events" ("quote_request_id", "created_at");`);
173
+ // ============================================================
174
+ // quote_request_notification_events
175
+ // ============================================================
176
+ this.addSql(`
177
+ create table "quote_request_notification_events" (
178
+ "id" uuid not null,
179
+ "quote_request_id" uuid not null,
180
+ "source_event_id" uuid not null,
181
+ "recipient_admin_user_id" uuid null,
182
+ "recipient_customer_account_id" uuid null,
183
+ "channel" varchar(16) not null,
184
+ "status" varchar(16) not null,
185
+ "error" text null,
186
+ "enqueued_at" timestamptz not null,
187
+ "sent_at" timestamptz null,
188
+ constraint "quote_request_notification_events_pkey" primary key ("id"),
189
+ constraint "qrne_rfq_fk" foreign key ("quote_request_id") references "quote_requests" ("id") on delete cascade,
190
+ constraint "qrne_event_fk" foreign key ("source_event_id") references "quote_request_events" ("id") on delete cascade,
191
+ constraint "qrne_channel_check" check ("channel" in ('email','in_app')),
192
+ constraint "qrne_status_check" check ("status" in ('queued','sent','failed'))
193
+ );
194
+ `);
195
+ this.addSql(`
196
+ create unique index "qrne_dedupe_idx" on "quote_request_notification_events"
197
+ ("quote_request_id", "source_event_id",
198
+ coalesce("recipient_admin_user_id", '00000000-0000-0000-0000-000000000000'::uuid),
199
+ coalesce("recipient_customer_account_id", '00000000-0000-0000-0000-000000000000'::uuid),
200
+ "channel");
201
+ `);
202
+ // ============================================================
203
+ // organization_sales_rep_assignments (organizations module — research §R9)
204
+ // ============================================================
205
+ this.addSql(`
206
+ create table "organization_sales_rep_assignments" (
207
+ "id" uuid not null,
208
+ "organization_id" uuid not null,
209
+ "admin_user_id" uuid not null,
210
+ "assigned_by_admin_user_id" uuid null,
211
+ "created_at" timestamptz not null,
212
+ constraint "organization_sales_rep_assignments_pkey" primary key ("id"),
213
+ constraint "orgsa_unique" unique ("organization_id", "admin_user_id")
214
+ );
215
+ `);
216
+ this.addSql(`create index "orgsa_admin_user_idx" on "organization_sales_rep_assignments" ("admin_user_id");`);
217
+ this.addSql(`create index "orgsa_organization_idx" on "organization_sales_rep_assignments" ("organization_id");`);
218
+ }
219
+ async down() {
220
+ // Best-effort rollback. Loses all data written under the new schema.
221
+ this.addSql(`drop table if exists "organization_sales_rep_assignments" cascade;`);
222
+ this.addSql(`drop table if exists "quote_request_notification_events" cascade;`);
223
+ this.addSql(`drop table if exists "quote_request_events" cascade;`);
224
+ this.addSql(`drop table if exists "quote_request_revisions" cascade;`);
225
+ this.addSql(`alter table "quote_request_items" drop column if exists "product_slug";`);
226
+ this.addSql(`alter table "quote_request_items" drop column if exists "line_currency";`);
227
+ this.addSql(`alter table "quote_request_items" drop column if exists "desired_unit_price";`);
228
+ this.addSql(`alter table "quote_request_items" rename column "discount_percent" to "quoted_discount_percent";`);
229
+ this.addSql(`alter table "quote_request_items" rename column "agreed_unit_price" to "quoted_unit_price";`);
230
+ this.addSql(`alter table "quote_request_items" rename column "line_note" to "requester_note";`);
231
+ this.addSql(`drop index if exists "idx_quote_requests_status_updated";`);
232
+ this.addSql(`drop index if exists "idx_quote_requests_org_status";`);
233
+ this.addSql(`drop index if exists "idx_quote_requests_customer_status";`);
234
+ this.addSql(`alter table "quote_requests" drop constraint if exists "quote_requests_status_check";`);
235
+ this.addSql(`alter table "quote_requests" add column "quoted_at" timestamptz null;`);
236
+ this.addSql(`alter table "quote_requests" add column "responded_at" timestamptz null;`);
237
+ this.addSql(`alter table "quote_requests" add column "quote_terms" jsonb null;`);
238
+ this.addSql(`alter table "quote_requests" drop column if exists "converted_order_id";`);
239
+ this.addSql(`alter table "quote_requests" drop column if exists "expired_at";`);
240
+ this.addSql(`alter table "quote_requests" drop column if exists "completed_at";`);
241
+ this.addSql(`alter table "quote_requests" drop column if exists "canceled_at";`);
242
+ this.addSql(`alter table "quote_requests" drop column if exists "approved_at";`);
243
+ this.addSql(`alter table "quote_requests" drop column if exists "current_revision_number";`);
244
+ this.addSql(`alter table "quote_requests" drop column if exists "last_customer_seen_revision_number";`);
245
+ this.addSql(`alter table "quote_requests" drop column if exists "awaiting_customer_revision_acceptance";`);
246
+ this.addSql(`alter table "quote_requests" drop column if exists "cancellation_reason";`);
247
+ this.addSql(`alter table "quote_requests" drop column if exists "created_by_admin_user_id";`);
248
+ this.addSql(`alter table "quote_requests" rename column "header_note" to "requester_note";`);
249
+ }
250
+ }
251
+ //# sourceMappingURL=20260503T141344_quote_requests_workflow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"20260503T141344_quote_requests_workflow.js","sourceRoot":"","sources":["../../src/migrations/20260503T141344_quote_requests_workflow.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { Migration } from '@mikro-orm/migrations';
2
+ /**
3
+ * Feature 043 — packaging-unit snapshot on quote-request lines. The unit name
4
+ * is also appended to `product_name`. Nullable — plain lines have none.
5
+ */
6
+ export declare class Migration20260611T140415QuoteRequestsQrItemPackaging extends Migration {
7
+ up(): Promise<void>;
8
+ down(): Promise<void>;
9
+ }
10
+ //# sourceMappingURL=20260611T140415_quote_requests_qr_item_packaging.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"20260611T140415_quote_requests_qr_item_packaging.d.ts","sourceRoot":"","sources":["../../src/migrations/20260611T140415_quote_requests_qr_item_packaging.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD;;;GAGG;AACH,qBAAa,oDAAqD,SAAQ,SAAS;IAClE,EAAE,IAAI,OAAO,CAAC,IAAI,CAAC;IAKnB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAIrC"}
@@ -0,0 +1,16 @@
1
+ import { Migration } from '@mikro-orm/migrations';
2
+ /**
3
+ * Feature 043 — packaging-unit snapshot on quote-request lines. The unit name
4
+ * is also appended to `product_name`. Nullable — plain lines have none.
5
+ */
6
+ export class Migration20260611T140415QuoteRequestsQrItemPackaging extends Migration {
7
+ async up() {
8
+ this.addSql('alter table "quote_request_items" add column "packaging_unit_name" varchar(160) null;');
9
+ this.addSql('alter table "quote_request_items" add column "packaging_unit_base_quantity" integer null;');
10
+ }
11
+ async down() {
12
+ this.addSql('alter table "quote_request_items" drop column "packaging_unit_base_quantity";');
13
+ this.addSql('alter table "quote_request_items" drop column "packaging_unit_name";');
14
+ }
15
+ }
16
+ //# sourceMappingURL=20260611T140415_quote_requests_qr_item_packaging.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"20260611T140415_quote_requests_qr_item_packaging.js","sourceRoot":"","sources":["../../src/migrations/20260611T140415_quote_requests_qr_item_packaging.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD;;;GAGG;AACH,MAAM,OAAO,oDAAqD,SAAQ,SAAS;IACxE,KAAK,CAAC,EAAE;QACf,IAAI,CAAC,MAAM,CAAC,uFAAuF,CAAC,CAAC;QACrG,IAAI,CAAC,MAAM,CAAC,2FAA2F,CAAC,CAAC;IAC3G,CAAC;IAEQ,KAAK,CAAC,IAAI;QACjB,IAAI,CAAC,MAAM,CAAC,+EAA+E,CAAC,CAAC;QAC7F,IAAI,CAAC,MAAM,CAAC,sEAAsE,CAAC,CAAC;IACtF,CAAC;CACF"}
@@ -0,0 +1,24 @@
1
+ import { Migration } from '@mikro-orm/migrations';
2
+ /**
3
+ * Customer-facing business Quote Request ID.
4
+ *
5
+ * Adds `quote_requests.business_id`: a human, business-facing identifier shown
6
+ * to the Customer instead of the internal UUID `id`, mirroring
7
+ * `orders.business_id` (feature 036). Its numeric core comes from a dedicated
8
+ * monotonic sequence (`quote_requests_business_id_seq`); the optional
9
+ * prefix/suffix are admin-configurable via the `quote_requests.business_id.*`
10
+ * settings and applied at creation time by RfqService / RfqAdminService — not
11
+ * here.
12
+ *
13
+ * Strategy:
14
+ * 1. create the sequence,
15
+ * 2. add a nullable `business_id` column,
16
+ * 3. backfill every existing RFQ with the bare sequence value (empty
17
+ * default prefix/suffix),
18
+ * 4. tighten to NOT NULL + UNIQUE.
19
+ */
20
+ export declare class Migration20260611T140417QuoteRequestsBusinessId extends Migration {
21
+ up(): Promise<void>;
22
+ down(): Promise<void>;
23
+ }
24
+ //# sourceMappingURL=20260611T140417_quote_requests_business_id.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"20260611T140417_quote_requests_business_id.d.ts","sourceRoot":"","sources":["../../src/migrations/20260611T140417_quote_requests_business_id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,+CAAgD,SAAQ,SAAS;IAC7D,EAAE,IAAI,OAAO,CAAC,IAAI,CAAC;IAYnB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAOrC"}
@@ -0,0 +1,34 @@
1
+ import { Migration } from '@mikro-orm/migrations';
2
+ /**
3
+ * Customer-facing business Quote Request ID.
4
+ *
5
+ * Adds `quote_requests.business_id`: a human, business-facing identifier shown
6
+ * to the Customer instead of the internal UUID `id`, mirroring
7
+ * `orders.business_id` (feature 036). Its numeric core comes from a dedicated
8
+ * monotonic sequence (`quote_requests_business_id_seq`); the optional
9
+ * prefix/suffix are admin-configurable via the `quote_requests.business_id.*`
10
+ * settings and applied at creation time by RfqService / RfqAdminService — not
11
+ * here.
12
+ *
13
+ * Strategy:
14
+ * 1. create the sequence,
15
+ * 2. add a nullable `business_id` column,
16
+ * 3. backfill every existing RFQ with the bare sequence value (empty
17
+ * default prefix/suffix),
18
+ * 4. tighten to NOT NULL + UNIQUE.
19
+ */
20
+ export class Migration20260611T140417QuoteRequestsBusinessId extends Migration {
21
+ async up() {
22
+ this.addSql(`create sequence if not exists "quote_requests_business_id_seq";`);
23
+ this.addSql(`alter table "quote_requests" add column "business_id" varchar(128) null;`);
24
+ this.addSql(`update "quote_requests" set "business_id" = nextval('quote_requests_business_id_seq')::text where "business_id" is null;`);
25
+ this.addSql(`alter table "quote_requests" alter column "business_id" set not null;`);
26
+ this.addSql(`alter table "quote_requests" add constraint "quote_requests_business_id_unique" unique ("business_id");`);
27
+ }
28
+ async down() {
29
+ this.addSql(`alter table "quote_requests" drop constraint "quote_requests_business_id_unique";`);
30
+ this.addSql(`alter table "quote_requests" drop column "business_id";`);
31
+ this.addSql(`drop sequence if exists "quote_requests_business_id_seq";`);
32
+ }
33
+ }
34
+ //# sourceMappingURL=20260611T140417_quote_requests_business_id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"20260611T140417_quote_requests_business_id.js","sourceRoot":"","sources":["../../src/migrations/20260611T140417_quote_requests_business_id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,OAAO,+CAAgD,SAAQ,SAAS;IACnE,KAAK,CAAC,EAAE;QACf,IAAI,CAAC,MAAM,CAAC,iEAAiE,CAAC,CAAC;QAC/E,IAAI,CAAC,MAAM,CAAC,0EAA0E,CAAC,CAAC;QACxF,IAAI,CAAC,MAAM,CACT,0HAA0H,CAC3H,CAAC;QACF,IAAI,CAAC,MAAM,CAAC,uEAAuE,CAAC,CAAC;QACrF,IAAI,CAAC,MAAM,CACT,yGAAyG,CAC1G,CAAC;IACJ,CAAC;IAEQ,KAAK,CAAC,IAAI;QACjB,IAAI,CAAC,MAAM,CACT,mFAAmF,CACpF,CAAC;QACF,IAAI,CAAC,MAAM,CAAC,yDAAyD,CAAC,CAAC;QACvE,IAAI,CAAC,MAAM,CAAC,2DAA2D,CAAC,CAAC;IAC3E,CAAC;CACF"}
@@ -0,0 +1,21 @@
1
+ import { Migration } from '@mikro-orm/migrations';
2
+ /**
3
+ * Backfill the awaiting-acceptance flag for legacy admin-created quotes.
4
+ *
5
+ * Quote Requests created on the customer's behalf (status `Created from admin`)
6
+ * must surface the Accept/Reject controls on the storefront, which gate on
7
+ * `awaiting_customer_revision_acceptance`. The service now sets that flag at
8
+ * creation time (see RfqAdminService.createOnBehalf), but rows created before
9
+ * that fix landed still have the flag at its `false` default, so the customer
10
+ * has no way to act on them.
11
+ *
12
+ * Any RFQ still in `Created from admin` status is genuinely awaiting the
13
+ * customer's decision (acceptance moves it to `Approved`, rejection to
14
+ * `Canceled`), so flipping the flag for exactly those rows is safe and
15
+ * idempotent.
16
+ */
17
+ export declare class Migration20260617T095510QuoteRequestsBackfillAdminCreatedAwaiting extends Migration {
18
+ up(): Promise<void>;
19
+ down(): Promise<void>;
20
+ }
21
+ //# sourceMappingURL=20260617T095510_quote_requests_backfill_admin_created_awaiting.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"20260617T095510_quote_requests_backfill_admin_created_awaiting.d.ts","sourceRoot":"","sources":["../../src/migrations/20260617T095510_quote_requests_backfill_admin_created_awaiting.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD;;;;;;;;;;;;;;GAcG;AACH,qBAAa,iEAAkE,SAAQ,SAAS;IAC/E,EAAE,IAAI,OAAO,CAAC,IAAI,CAAC;IASnB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAIrC"}
@@ -0,0 +1,29 @@
1
+ import { Migration } from '@mikro-orm/migrations';
2
+ /**
3
+ * Backfill the awaiting-acceptance flag for legacy admin-created quotes.
4
+ *
5
+ * Quote Requests created on the customer's behalf (status `Created from admin`)
6
+ * must surface the Accept/Reject controls on the storefront, which gate on
7
+ * `awaiting_customer_revision_acceptance`. The service now sets that flag at
8
+ * creation time (see RfqAdminService.createOnBehalf), but rows created before
9
+ * that fix landed still have the flag at its `false` default, so the customer
10
+ * has no way to act on them.
11
+ *
12
+ * Any RFQ still in `Created from admin` status is genuinely awaiting the
13
+ * customer's decision (acceptance moves it to `Approved`, rejection to
14
+ * `Canceled`), so flipping the flag for exactly those rows is safe and
15
+ * idempotent.
16
+ */
17
+ export class Migration20260617T095510QuoteRequestsBackfillAdminCreatedAwaiting extends Migration {
18
+ async up() {
19
+ this.addSql(`update "quote_requests"
20
+ set "awaiting_customer_revision_acceptance" = true
21
+ where "status" = 'Created from admin'
22
+ and "awaiting_customer_revision_acceptance" = false;`);
23
+ }
24
+ async down() {
25
+ // Non-reversible data backfill: the original per-row flag value is not
26
+ // recoverable. Leaving the rows as-is on rollback is the safe choice.
27
+ }
28
+ }
29
+ //# sourceMappingURL=20260617T095510_quote_requests_backfill_admin_created_awaiting.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"20260617T095510_quote_requests_backfill_admin_created_awaiting.js","sourceRoot":"","sources":["../../src/migrations/20260617T095510_quote_requests_backfill_admin_created_awaiting.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAO,iEAAkE,SAAQ,SAAS;IACrF,KAAK,CAAC,EAAE;QACf,IAAI,CAAC,MAAM,CACT;;;8DAGwD,CACzD,CAAC;IACJ,CAAC;IAEQ,KAAK,CAAC,IAAI;QACjB,uEAAuE;QACvE,sEAAsE;IACxE,CAAC;CACF"}
@@ -0,0 +1,12 @@
1
+ import { Migration } from '@mikro-orm/migrations';
2
+ /**
3
+ * Feature 055 — Custom Fields Layer. Additive: adds the `custom_field_values`
4
+ * JSONB bag to `quote_requests` so operator-defined fields persist on the host row.
5
+ * The column inherits the host entity's tenant classification (Principle XI);
6
+ * no scoping column is added.
7
+ */
8
+ export declare class Migration20260718T200342QuoteRequestsQuoteRequestCustomFieldValues extends Migration {
9
+ up(): Promise<void>;
10
+ down(): Promise<void>;
11
+ }
12
+ //# sourceMappingURL=20260718T200342_quote_requests_quote_request_custom_field_values.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"20260718T200342_quote_requests_quote_request_custom_field_values.d.ts","sourceRoot":"","sources":["../../src/migrations/20260718T200342_quote_requests_quote_request_custom_field_values.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD;;;;;GAKG;AACH,qBAAa,kEAAmE,SAAQ,SAAS;IAChF,EAAE,IAAI,OAAO,CAAC,IAAI,CAAC;IAMnB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAGrC"}
@@ -0,0 +1,16 @@
1
+ import { Migration } from '@mikro-orm/migrations';
2
+ /**
3
+ * Feature 055 — Custom Fields Layer. Additive: adds the `custom_field_values`
4
+ * JSONB bag to `quote_requests` so operator-defined fields persist on the host row.
5
+ * The column inherits the host entity's tenant classification (Principle XI);
6
+ * no scoping column is added.
7
+ */
8
+ export class Migration20260718T200342QuoteRequestsQuoteRequestCustomFieldValues extends Migration {
9
+ async up() {
10
+ this.addSql(`alter table "quote_requests" add column "custom_field_values" jsonb not null default '{}';`);
11
+ }
12
+ async down() {
13
+ this.addSql(`alter table "quote_requests" drop column "custom_field_values";`);
14
+ }
15
+ }
16
+ //# sourceMappingURL=20260718T200342_quote_requests_quote_request_custom_field_values.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"20260718T200342_quote_requests_quote_request_custom_field_values.js","sourceRoot":"","sources":["../../src/migrations/20260718T200342_quote_requests_quote_request_custom_field_values.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD;;;;;GAKG;AACH,MAAM,OAAO,kEAAmE,SAAQ,SAAS;IACtF,KAAK,CAAC,EAAE;QACf,IAAI,CAAC,MAAM,CACT,4FAA4F,CAC7F,CAAC;IACJ,CAAC;IAEQ,KAAK,CAAC,IAAI;QACjB,IAAI,CAAC,MAAM,CAAC,iEAAiE,CAAC,CAAC;IACjF,CAAC;CACF"}