@endora-commerce/mod-carts 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 (155) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +62 -0
  3. package/dist/admin/components/CartApprovalPolicyPanel.d.ts +51 -0
  4. package/dist/admin/components/CartApprovalPolicyPanel.d.ts.map +1 -0
  5. package/dist/admin/components/CartApprovalPolicyPanel.js +59 -0
  6. package/dist/admin/components/CartApprovalPolicyPanel.js.map +1 -0
  7. package/dist/admin/index.d.ts +38 -0
  8. package/dist/admin/index.d.ts.map +1 -0
  9. package/dist/admin/index.js +73 -0
  10. package/dist/admin/index.js.map +1 -0
  11. package/dist/admin/pages/CartDetail.d.ts +3 -0
  12. package/dist/admin/pages/CartDetail.d.ts.map +1 -0
  13. package/dist/admin/pages/CartDetail.js +74 -0
  14. package/dist/admin/pages/CartDetail.js.map +1 -0
  15. package/dist/admin/pages/CartsList.d.ts +3 -0
  16. package/dist/admin/pages/CartsList.d.ts.map +1 -0
  17. package/dist/admin/pages/CartsList.js +90 -0
  18. package/dist/admin/pages/CartsList.js.map +1 -0
  19. package/dist/admin/zones/CartApprovalPolicy.d.ts +29 -0
  20. package/dist/admin/zones/CartApprovalPolicy.d.ts.map +1 -0
  21. package/dist/admin/zones/CartApprovalPolicy.js +11 -0
  22. package/dist/admin/zones/CartApprovalPolicy.js.map +1 -0
  23. package/dist/backend/cli/abandonment-sweep.d.ts +64 -0
  24. package/dist/backend/cli/abandonment-sweep.d.ts.map +1 -0
  25. package/dist/backend/cli/abandonment-sweep.js +17 -0
  26. package/dist/backend/cli/abandonment-sweep.js.map +1 -0
  27. package/dist/backend/entities/cart-audit-entry.entity.d.ts +29 -0
  28. package/dist/backend/entities/cart-audit-entry.entity.d.ts.map +1 -0
  29. package/dist/backend/entities/cart-audit-entry.entity.js +109 -0
  30. package/dist/backend/entities/cart-audit-entry.entity.js.map +1 -0
  31. package/dist/backend/entities/cart-item.entity.d.ts +42 -0
  32. package/dist/backend/entities/cart-item.entity.d.ts.map +1 -0
  33. package/dist/backend/entities/cart-item.entity.js +119 -0
  34. package/dist/backend/entities/cart-item.entity.js.map +1 -0
  35. package/dist/backend/entities/cart.entity.d.ts +96 -0
  36. package/dist/backend/entities/cart.entity.d.ts.map +1 -0
  37. package/dist/backend/entities/cart.entity.js +207 -0
  38. package/dist/backend/entities/cart.entity.js.map +1 -0
  39. package/dist/backend/index.d.ts +122 -0
  40. package/dist/backend/index.d.ts.map +1 -0
  41. package/dist/backend/index.js +184 -0
  42. package/dist/backend/index.js.map +1 -0
  43. package/dist/backend/routes.admin.d.ts +31 -0
  44. package/dist/backend/routes.admin.d.ts.map +1 -0
  45. package/dist/backend/routes.admin.js +95 -0
  46. package/dist/backend/routes.admin.js.map +1 -0
  47. package/dist/backend/routes.d.ts +101 -0
  48. package/dist/backend/routes.d.ts.map +1 -0
  49. package/dist/backend/routes.js +620 -0
  50. package/dist/backend/routes.js.map +1 -0
  51. package/dist/backend/routes.organization.d.ts +29 -0
  52. package/dist/backend/routes.organization.d.ts.map +1 -0
  53. package/dist/backend/routes.organization.js +150 -0
  54. package/dist/backend/routes.organization.js.map +1 -0
  55. package/dist/backend/services/cart-abandonment-settings.d.ts +34 -0
  56. package/dist/backend/services/cart-abandonment-settings.d.ts.map +1 -0
  57. package/dist/backend/services/cart-abandonment-settings.js +55 -0
  58. package/dist/backend/services/cart-abandonment-settings.js.map +1 -0
  59. package/dist/backend/services/cart-abandonment-worker.d.ts +110 -0
  60. package/dist/backend/services/cart-abandonment-worker.d.ts.map +1 -0
  61. package/dist/backend/services/cart-abandonment-worker.js +185 -0
  62. package/dist/backend/services/cart-abandonment-worker.js.map +1 -0
  63. package/dist/backend/services/cart-admin-service.d.ts +58 -0
  64. package/dist/backend/services/cart-admin-service.d.ts.map +1 -0
  65. package/dist/backend/services/cart-admin-service.js +397 -0
  66. package/dist/backend/services/cart-admin-service.js.map +1 -0
  67. package/dist/backend/services/cart-approval-service.d.ts +147 -0
  68. package/dist/backend/services/cart-approval-service.d.ts.map +1 -0
  69. package/dist/backend/services/cart-approval-service.js +242 -0
  70. package/dist/backend/services/cart-approval-service.js.map +1 -0
  71. package/dist/backend/services/cart-audit-service.d.ts +75 -0
  72. package/dist/backend/services/cart-audit-service.d.ts.map +1 -0
  73. package/dist/backend/services/cart-audit-service.js +70 -0
  74. package/dist/backend/services/cart-audit-service.js.map +1 -0
  75. package/dist/backend/services/cart-conversion-service.d.ts +104 -0
  76. package/dist/backend/services/cart-conversion-service.d.ts.map +1 -0
  77. package/dist/backend/services/cart-conversion-service.js +175 -0
  78. package/dist/backend/services/cart-conversion-service.js.map +1 -0
  79. package/dist/backend/services/cart-coupon-service.d.ts +129 -0
  80. package/dist/backend/services/cart-coupon-service.d.ts.map +1 -0
  81. package/dist/backend/services/cart-coupon-service.js +244 -0
  82. package/dist/backend/services/cart-coupon-service.js.map +1 -0
  83. package/dist/backend/services/cart-organization-visibility-service.d.ts +43 -0
  84. package/dist/backend/services/cart-organization-visibility-service.d.ts.map +1 -0
  85. package/dist/backend/services/cart-organization-visibility-service.js +98 -0
  86. package/dist/backend/services/cart-organization-visibility-service.js.map +1 -0
  87. package/dist/backend/services/cart-placement-apply-port.d.ts +38 -0
  88. package/dist/backend/services/cart-placement-apply-port.d.ts.map +1 -0
  89. package/dist/backend/services/cart-placement-apply-port.js +71 -0
  90. package/dist/backend/services/cart-placement-apply-port.js.map +1 -0
  91. package/dist/backend/services/cart-pricing-recompute.d.ts +62 -0
  92. package/dist/backend/services/cart-pricing-recompute.d.ts.map +1 -0
  93. package/dist/backend/services/cart-pricing-recompute.js +131 -0
  94. package/dist/backend/services/cart-pricing-recompute.js.map +1 -0
  95. package/dist/backend/services/cart-query-service.d.ts +29 -0
  96. package/dist/backend/services/cart-query-service.d.ts.map +1 -0
  97. package/dist/backend/services/cart-query-service.js +40 -0
  98. package/dist/backend/services/cart-query-service.js.map +1 -0
  99. package/dist/backend/services/cart-read-port.d.ts +40 -0
  100. package/dist/backend/services/cart-read-port.d.ts.map +1 -0
  101. package/dist/backend/services/cart-read-port.js +144 -0
  102. package/dist/backend/services/cart-read-port.js.map +1 -0
  103. package/dist/backend/services/cart-recompute-cache.d.ts +49 -0
  104. package/dist/backend/services/cart-recompute-cache.d.ts.map +1 -0
  105. package/dist/backend/services/cart-recompute-cache.js +56 -0
  106. package/dist/backend/services/cart-recompute-cache.js.map +1 -0
  107. package/dist/backend/services/cart-service.d.ts +165 -0
  108. package/dist/backend/services/cart-service.d.ts.map +1 -0
  109. package/dist/backend/services/cart-service.js +556 -0
  110. package/dist/backend/services/cart-service.js.map +1 -0
  111. package/dist/backend/services/cart-state-machine.d.ts +51 -0
  112. package/dist/backend/services/cart-state-machine.d.ts.map +1 -0
  113. package/dist/backend/services/cart-state-machine.js +74 -0
  114. package/dist/backend/services/cart-state-machine.js.map +1 -0
  115. package/dist/backend/services/cart-upsell-service.d.ts +57 -0
  116. package/dist/backend/services/cart-upsell-service.d.ts.map +1 -0
  117. package/dist/backend/services/cart-upsell-service.js +100 -0
  118. package/dist/backend/services/cart-upsell-service.js.map +1 -0
  119. package/dist/backend/services/customer-group-resolver.d.ts +27 -0
  120. package/dist/backend/services/customer-group-resolver.d.ts.map +1 -0
  121. package/dist/backend/services/customer-group-resolver.js +32 -0
  122. package/dist/backend/services/customer-group-resolver.js.map +1 -0
  123. package/dist/manifest.d.ts +221 -0
  124. package/dist/manifest.d.ts.map +1 -0
  125. package/dist/manifest.js +224 -0
  126. package/dist/manifest.js.map +1 -0
  127. package/dist/migrations/20260611T140352_carts_consolidation.d.ts +43 -0
  128. package/dist/migrations/20260611T140352_carts_consolidation.d.ts.map +1 -0
  129. package/dist/migrations/20260611T140352_carts_consolidation.js +237 -0
  130. package/dist/migrations/20260611T140352_carts_consolidation.js.map +1 -0
  131. package/dist/migrations/20260611T140413_carts_cart_item_packaging.d.ts +12 -0
  132. package/dist/migrations/20260611T140413_carts_cart_item_packaging.d.ts.map +1 -0
  133. package/dist/migrations/20260611T140413_carts_cart_item_packaging.js +20 -0
  134. package/dist/migrations/20260611T140413_carts_cart_item_packaging.js.map +1 -0
  135. package/dist/migrations/20260818T081253_carts_cart_completed_order_fk.d.ts +50 -0
  136. package/dist/migrations/20260818T081253_carts_cart_completed_order_fk.d.ts.map +1 -0
  137. package/dist/migrations/20260818T081253_carts_cart_completed_order_fk.js +62 -0
  138. package/dist/migrations/20260818T081253_carts_cart_completed_order_fk.js.map +1 -0
  139. package/dist/migrations/20260830T112911_carts_organization_attribution_check.d.ts +67 -0
  140. package/dist/migrations/20260830T112911_carts_organization_attribution_check.d.ts.map +1 -0
  141. package/dist/migrations/20260830T112911_carts_organization_attribution_check.js +121 -0
  142. package/dist/migrations/20260830T112911_carts_organization_attribution_check.js.map +1 -0
  143. package/dist/migrations/index.d.ts +30 -0
  144. package/dist/migrations/index.d.ts.map +1 -0
  145. package/dist/migrations/index.js +35 -0
  146. package/dist/migrations/index.js.map +1 -0
  147. package/dist/ports/index.d.ts +106 -0
  148. package/dist/ports/index.d.ts.map +1 -0
  149. package/dist/ports/index.js +2 -0
  150. package/dist/ports/index.js.map +1 -0
  151. package/docs/carts.md +232 -0
  152. package/i18n/en.json +96 -0
  153. package/i18n/pl.json +96 -0
  154. package/package.json +107 -0
  155. package/tailwind.css +14 -0
@@ -0,0 +1,64 @@
1
+ /**
2
+ * `carts abandonment-sweep` — one pass of `CartAbandonmentWorker.sweep()`
3
+ * against the live database (feature 027 US5).
4
+ *
5
+ * Intended for a cron job or a deploy hook, and safe to run manually:
6
+ *
7
+ * pnpm --filter backend run cart:abandonment-sweep
8
+ *
9
+ * Idempotent: subsequent invocations within the same threshold window are a
10
+ * no-op, because the eligibility filter excludes carts that already carry
11
+ * `abandonment_notified_at`.
12
+ *
13
+ * ## Why this file no longer asks the gate itself (feature 080, T042b)
14
+ *
15
+ * It used to, and the header it carried was the best statement in the tree of
16
+ * the question D-157 answered:
17
+ *
18
+ * > It used to run whatever the platform's opinion of `carts` was, because there
19
+ * > is nothing here for the gate to hang on: `ctx.routes` / `ctx.worker` /
20
+ * > `ctx.subscribe` gate at a registration seam and `providePort` gates at a
21
+ * > resolution, and a CLI has none of the three.
22
+ *
23
+ * There is a seam now, and it is the **declaration**: the host knows which
24
+ * module declared the command it is about to run and asks
25
+ * `requireModuleEnabled` about that module — first, before it builds a context
26
+ * and outside every `try` — in `src/cli/module-commands.ts`. That is the same
27
+ * call at the same point in the same order; what changed is that it is applied
28
+ * once, by the host, for every command, instead of being a line each command's
29
+ * author has to remember. Constitution XVII item 3 states the reason in the
30
+ * general case: *"A gate the registration applies cannot be forgotten in the one
31
+ * service somebody adds later, which a hand-placed call can and did."*
32
+ *
33
+ * ## What the conversion fixed
34
+ *
35
+ * The old file's *"What it still does not do"* section named it: *"It builds its
36
+ * services by hand, so a deployment **decoration** over `cartAuditService` or
37
+ * `cartAbandonmentWorker` does not reach it."* That is a client not getting an
38
+ * override they paid for, and it is fixed by resolving the module's own
39
+ * registration instead of running `new CartAbandonmentWorker(…)` here.
40
+ *
41
+ * The same section refused composition on the ground that `composeApp()`
42
+ * *"starts every queue consumer in the platform"*. That was false and
43
+ * `worker.ts` says so in its own comment — a composition without `buildServer`
44
+ * starts no BullMQ worker and arms no timer, because all three `ctx.worker(`
45
+ * call sites and both module timers sit inside `ctx.routes(…)` bodies that run
46
+ * at Fastify registration (D-157.2, measured three ways). The claim is retired
47
+ * here rather than left for the next author to re-derive.
48
+ *
49
+ * ## Notification dispatch
50
+ *
51
+ * The old file said no e-mail is dispatched in the CLI variant, and that *"the
52
+ * HTTP-bootstrap path in `composition.ts` injects the real
53
+ * `dispatchCartAbandonmentNotification`"*. The second half is stale: measured on
54
+ * this tree, `cartAbandonmentNotifier` is a contribution point that **nobody
55
+ * contributes** — neither composition root writes it — so it defaults to
56
+ * `undefined` and the composed worker dispatches nothing either. Behaviour is
57
+ * therefore unchanged by the conversion, and the day a deployment does
58
+ * contribute a notifier, this command and the platform will agree about it,
59
+ * which they could not before.
60
+ */
61
+ import type { ModuleCliCommandContext } from '@endora-commerce/contracts';
62
+ import type { ModuleContext } from '@endora-commerce/platform/kernel';
63
+ export declare function abandonmentSweep({ ctx, out, }: ModuleCliCommandContext<ModuleContext>): Promise<number>;
64
+ //# sourceMappingURL=abandonment-sweep.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abandonment-sweep.d.ts","sourceRoot":"","sources":["../../../src/backend/cli/abandonment-sweep.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2DG;AACH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAC1E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AAQtE,wBAAsB,gBAAgB,CAAC,EACrC,GAAG,EACH,GAAG,GACJ,EAAE,uBAAuB,CAAC,aAAa,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAiB1D"}
@@ -0,0 +1,17 @@
1
+ export async function abandonmentSweep({ ctx, out, }) {
2
+ // This module's own registration, so a deployment decoration over it reaches
3
+ // the command — and so the settings thresholds come from the one file
4
+ // `backend.ts` composes the worker from, which is what stopped the CLI and the
5
+ // server disagreeing about them (D-41/D-43).
6
+ //
7
+ // A cradle read rather than `lazyPort`, because `cartAbandonmentWorker` is a
8
+ // plain `ctx.di.register` and not a `providePort`: spelling it as a port here
9
+ // would suggest a presence gate that this name does not carry. Presence for
10
+ // this module is decided by the host before the command is invoked.
11
+ const worker = ctx.cradle().cartAbandonmentWorker;
12
+ const result = await worker.sweep();
13
+ out(`[cart abandonment-sweep] abandoned=${result.abandonedCount} ` +
14
+ `notified=${result.notifiedCount}`);
15
+ return 0;
16
+ }
17
+ //# sourceMappingURL=abandonment-sweep.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abandonment-sweep.js","sourceRoot":"","sources":["../../../src/backend/cli/abandonment-sweep.ts"],"names":[],"mappings":"AAqEA,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,EACrC,GAAG,EACH,GAAG,GACoC;IACvC,6EAA6E;IAC7E,sEAAsE;IACtE,+EAA+E;IAC/E,6CAA6C;IAC7C,EAAE;IACF,6EAA6E;IAC7E,8EAA8E;IAC9E,4EAA4E;IAC5E,oEAAoE;IACpE,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,EAA0B,CAAC,qBAAqB,CAAC;IAC1E,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACpC,GAAG,CACD,sCAAsC,MAAM,CAAC,cAAc,GAAG;QAC5D,YAAY,MAAM,CAAC,aAAa,EAAE,CACrC,CAAC;IACF,OAAO,CAAC,CAAC;AACX,CAAC"}
@@ -0,0 +1,29 @@
1
+ import { OptionalProps } from '@mikro-orm/core';
2
+ /**
3
+ * One audit row on a cart's typed feed (feature 027). Backs the cart-
4
+ * detail-page audit panel for both Org-Admin and platform-admin views.
5
+ *
6
+ * Companion to `audit_log_entries` — every cart-state transition also
7
+ * lands a row there via AuditPort.record(...), so the platform-wide
8
+ * audit timeline stays whole. Splitting the two tables keeps the cart UI
9
+ * tight (typed `from_state` / `to_state` / `metadata`) without bloating
10
+ * the generic audit feed.
11
+ */
12
+ export declare class CartAuditEntry {
13
+ [OptionalProps]?: 'id' | 'occurredAt' | 'actorId' | 'fromState' | 'toState' | 'reason' | 'metadata';
14
+ id: string;
15
+ cartId: string;
16
+ occurredAt: Date;
17
+ actorType: CartAuditActorType;
18
+ actorId?: string | null;
19
+ action: CartAuditAction;
20
+ fromState?: string | null;
21
+ toState?: string | null;
22
+ reason?: string | null;
23
+ metadata: Record<string, unknown>;
24
+ }
25
+ export type CartAuditActorType = 'customer' | 'org_admin' | 'platform_admin' | 'system' | 'sweep';
26
+ export declare const CART_AUDIT_ACTOR_TYPES: readonly CartAuditActorType[];
27
+ export type CartAuditAction = 'status_changed' | 'approval_submitted' | 'approval_approved' | 'approval_rejected' | 'approval_policy_reset' | 'approval_resubmission_required' | 'coupon_applied' | 'coupon_dropped' | 'converted_to_qr' | 'created_from_qr' | 'created_from_shopping_list' | 'admin_rejected' | 'abandonment_swept' | 'abandonment_reactivated' | 'line_added' | 'line_removed' | 'line_qty_changed' | 'cart_merged_from_anon';
28
+ export declare const CART_AUDIT_ACTIONS: readonly CartAuditAction[];
29
+ //# sourceMappingURL=cart-audit-entry.entity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cart-audit-entry.entity.d.ts","sourceRoot":"","sources":["../../../src/backend/entities/cart-audit-entry.entity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,aAAa,EAAwB,MAAM,iBAAiB,CAAC;AAIrF;;;;;;;;;GASG;AACH,qBAEa,cAAc;IACzB,CAAC,aAAa,CAAC,CAAC,EACZ,IAAI,GACJ,YAAY,GACZ,SAAS,GACT,WAAW,GACX,SAAS,GACT,QAAQ,GACR,UAAU,CAAC;IAGf,EAAE,EAAE,MAAM,CAAgB;IAI1B,MAAM,EAAG,MAAM,CAAC;IAGhB,UAAU,EAAE,IAAI,CAAc;IAG9B,SAAS,EAAG,kBAAkB,CAAC;IAG/B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAGxB,MAAM,EAAG,eAAe,CAAC;IAGzB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAG1B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAGxB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAGvB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAM;CACxC;AAED,MAAM,MAAM,kBAAkB,GAC1B,UAAU,GACV,WAAW,GACX,gBAAgB,GAChB,QAAQ,GACR,OAAO,CAAC;AAEZ,eAAO,MAAM,sBAAsB,EAAE,SAAS,kBAAkB,EAMtD,CAAC;AAEX,MAAM,MAAM,eAAe,GACvB,gBAAgB,GAChB,oBAAoB,GACpB,mBAAmB,GACnB,mBAAmB,GACnB,uBAAuB,GACvB,gCAAgC,GAChC,gBAAgB,GAChB,gBAAgB,GAChB,iBAAiB,GACjB,iBAAiB,GACjB,4BAA4B,GAC5B,gBAAgB,GAChB,mBAAmB,GACnB,yBAAyB,GACzB,YAAY,GACZ,cAAc,GACd,kBAAkB,GAClB,uBAAuB,CAAC;AAE5B,eAAO,MAAM,kBAAkB,EAAE,SAAS,eAAe,EAmB/C,CAAC"}
@@ -0,0 +1,109 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { Entity, Index, OptionalProps, PrimaryKey, Property } from '@mikro-orm/core';
11
+ import { GlobalEntity } from '@endora-commerce/platform/tenancy';
12
+ import { randomUUID } from 'crypto';
13
+ /**
14
+ * One audit row on a cart's typed feed (feature 027). Backs the cart-
15
+ * detail-page audit panel for both Org-Admin and platform-admin views.
16
+ *
17
+ * Companion to `audit_log_entries` — every cart-state transition also
18
+ * lands a row there via AuditPort.record(...), so the platform-wide
19
+ * audit timeline stays whole. Splitting the two tables keeps the cart UI
20
+ * tight (typed `from_state` / `to_state` / `metadata`) without bloating
21
+ * the generic audit feed.
22
+ */
23
+ let CartAuditEntry = class CartAuditEntry {
24
+ [OptionalProps];
25
+ id = randomUUID();
26
+ cartId;
27
+ occurredAt = new Date();
28
+ actorType;
29
+ actorId;
30
+ action;
31
+ fromState;
32
+ toState;
33
+ reason;
34
+ metadata = {};
35
+ };
36
+ __decorate([
37
+ PrimaryKey({ type: 'uuid' }),
38
+ __metadata("design:type", String)
39
+ ], CartAuditEntry.prototype, "id", void 0);
40
+ __decorate([
41
+ Property({ type: 'uuid' }),
42
+ Index(),
43
+ __metadata("design:type", String)
44
+ ], CartAuditEntry.prototype, "cartId", void 0);
45
+ __decorate([
46
+ Property({ type: 'datetime' }),
47
+ __metadata("design:type", Date)
48
+ ], CartAuditEntry.prototype, "occurredAt", void 0);
49
+ __decorate([
50
+ Property({ type: 'string', length: 32 }),
51
+ __metadata("design:type", String)
52
+ ], CartAuditEntry.prototype, "actorType", void 0);
53
+ __decorate([
54
+ Property({ type: 'uuid', nullable: true }),
55
+ __metadata("design:type", Object)
56
+ ], CartAuditEntry.prototype, "actorId", void 0);
57
+ __decorate([
58
+ Property({ type: 'string', length: 64 }),
59
+ __metadata("design:type", String)
60
+ ], CartAuditEntry.prototype, "action", void 0);
61
+ __decorate([
62
+ Property({ type: 'string', length: 32, nullable: true }),
63
+ __metadata("design:type", Object)
64
+ ], CartAuditEntry.prototype, "fromState", void 0);
65
+ __decorate([
66
+ Property({ type: 'string', length: 32, nullable: true }),
67
+ __metadata("design:type", Object)
68
+ ], CartAuditEntry.prototype, "toState", void 0);
69
+ __decorate([
70
+ Property({ type: 'text', nullable: true }),
71
+ __metadata("design:type", Object)
72
+ ], CartAuditEntry.prototype, "reason", void 0);
73
+ __decorate([
74
+ Property({ type: 'json' }),
75
+ __metadata("design:type", Object)
76
+ ], CartAuditEntry.prototype, "metadata", void 0);
77
+ CartAuditEntry = __decorate([
78
+ GlobalEntity(),
79
+ Entity({ tableName: 'cart_audit_entries' })
80
+ ], CartAuditEntry);
81
+ export { CartAuditEntry };
82
+ export const CART_AUDIT_ACTOR_TYPES = [
83
+ 'customer',
84
+ 'org_admin',
85
+ 'platform_admin',
86
+ 'system',
87
+ 'sweep',
88
+ ];
89
+ export const CART_AUDIT_ACTIONS = [
90
+ 'status_changed',
91
+ 'approval_submitted',
92
+ 'approval_approved',
93
+ 'approval_rejected',
94
+ 'approval_policy_reset',
95
+ 'approval_resubmission_required',
96
+ 'coupon_applied',
97
+ 'coupon_dropped',
98
+ 'converted_to_qr',
99
+ 'created_from_qr',
100
+ 'created_from_shopping_list',
101
+ 'admin_rejected',
102
+ 'abandonment_swept',
103
+ 'abandonment_reactivated',
104
+ 'line_added',
105
+ 'line_removed',
106
+ 'line_qty_changed',
107
+ 'cart_merged_from_anon',
108
+ ];
109
+ //# sourceMappingURL=cart-audit-entry.entity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cart-audit-entry.entity.js","sourceRoot":"","sources":["../../../src/backend/entities/cart-audit-entry.entity.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AACrF,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEpC;;;;;;;;;GASG;AAGI,IAAM,cAAc,GAApB,MAAM,cAAc;IACzB,CAAC,aAAa,CAAC,CAOA;IAGf,EAAE,GAAW,UAAU,EAAE,CAAC;IAI1B,MAAM,CAAU;IAGhB,UAAU,GAAS,IAAI,IAAI,EAAE,CAAC;IAG9B,SAAS,CAAsB;IAG/B,OAAO,CAAiB;IAGxB,MAAM,CAAmB;IAGzB,SAAS,CAAiB;IAG1B,OAAO,CAAiB;IAGxB,MAAM,CAAiB;IAGvB,QAAQ,GAA4B,EAAE,CAAC;CACxC,CAAA;AA7BC;IADC,UAAU,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;0CACH;AAI1B;IAFC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC1B,KAAK,EAAE;;8CACQ;AAGhB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;8BACnB,IAAI;kDAAc;AAG9B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;;iDACV;AAG/B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;+CACnB;AAGxB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;;8CAChB;AAGzB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;iDAC/B;AAG1B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;+CACjC;AAGxB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;8CACpB;AAGvB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;gDACY;AAvC5B,cAAc;IAF1B,YAAY,EAAE;IACd,MAAM,CAAC,EAAE,SAAS,EAAE,oBAAoB,EAAE,CAAC;GAC/B,cAAc,CAwC1B;;AASD,MAAM,CAAC,MAAM,sBAAsB,GAAkC;IACnE,UAAU;IACV,WAAW;IACX,gBAAgB;IAChB,QAAQ;IACR,OAAO;CACC,CAAC;AAsBX,MAAM,CAAC,MAAM,kBAAkB,GAA+B;IAC5D,gBAAgB;IAChB,oBAAoB;IACpB,mBAAmB;IACnB,mBAAmB;IACnB,uBAAuB;IACvB,gCAAgC;IAChC,gBAAgB;IAChB,gBAAgB;IAChB,iBAAiB;IACjB,iBAAiB;IACjB,4BAA4B;IAC5B,gBAAgB;IAChB,mBAAmB;IACnB,yBAAyB;IACzB,YAAY;IACZ,cAAc;IACd,kBAAkB;IAClB,uBAAuB;CACf,CAAC"}
@@ -0,0 +1,42 @@
1
+ import { OptionalProps } from '@mikro-orm/core';
2
+ /**
3
+ * A line in a Cart. Two-layer pricing snapshot (feature 027):
4
+ * - `unitPrice` / `currency`: the price the line was added at. Read-only
5
+ * after add; useful for audit / diff and for the "added at" column in
6
+ * cart_audit_entries metadata.
7
+ * - `recomputedUnitPrice` / `recomputedAt` / `recomputedCurrency`: the
8
+ * most recent re-resolved price. The Cart-Pricing-Recompute helper
9
+ * refreshes these on every full-cart-view read (with a 30 s Redis
10
+ * cache between mini-cart / full-cart / checkout-entry walks).
11
+ * Cleared on any cart-side write.
12
+ */
13
+ export declare class CartItem {
14
+ [OptionalProps]?: 'id' | 'createdAt' | 'updatedAt' | 'variantId' | 'recomputedUnitPrice' | 'recomputedAt' | 'recomputedCurrency' | 'packagingUnitId' | 'packagingUnitName' | 'packagingUnitBaseQuantity';
15
+ id: string;
16
+ cartId: string;
17
+ productId: string;
18
+ variantId?: string | null;
19
+ quantity: number;
20
+ /** Price snapshot at time of add — services recalculate on read. */
21
+ unitPrice: string;
22
+ currency: string;
23
+ /**
24
+ * Most-recent re-resolved unit price (per feature 011 PricingService).
25
+ * Stale beyond the cache TTL → re-resolve on next read. Cleared on every
26
+ * cart-side write so the next read forces a fresh resolution.
27
+ */
28
+ recomputedUnitPrice?: string | null;
29
+ recomputedAt?: Date | null;
30
+ recomputedCurrency?: string | null;
31
+ /**
32
+ * Feature 043 — when this line was added as a packaging unit (e.g. a
33
+ * pallet), these snapshot the unit it came from. `quantity` above already
34
+ * holds the resulting base-piece count. Null for plain single-piece lines.
35
+ */
36
+ packagingUnitId?: string | null;
37
+ packagingUnitName?: string | null;
38
+ packagingUnitBaseQuantity?: number | null;
39
+ createdAt: Date;
40
+ updatedAt: Date;
41
+ }
42
+ //# sourceMappingURL=cart-item.entity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cart-item.entity.d.ts","sourceRoot":"","sources":["../../../src/backend/entities/cart-item.entity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,aAAa,EAAwB,MAAM,iBAAiB,CAAC;AAIrF;;;;;;;;;;GAUG;AACH,qBAEa,QAAQ;IACnB,CAAC,aAAa,CAAC,CAAC,EACZ,IAAI,GACJ,WAAW,GACX,WAAW,GACX,WAAW,GACX,qBAAqB,GACrB,cAAc,GACd,oBAAoB,GACpB,iBAAiB,GACjB,mBAAmB,GACnB,2BAA2B,CAAC;IAGhC,EAAE,EAAE,MAAM,CAAgB;IAI1B,MAAM,EAAG,MAAM,CAAC;IAGhB,SAAS,EAAG,MAAM,CAAC;IAGnB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAG1B,QAAQ,EAAG,MAAM,CAAC;IAElB,oEAAoE;IAEpE,SAAS,EAAG,MAAM,CAAC;IAGnB,QAAQ,EAAG,MAAM,CAAC;IAElB;;;;OAIG;IAEH,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAGpC,YAAY,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IAG3B,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEnC;;;;OAIG;IAEH,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAGhC,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAGlC,yBAAyB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAG1C,SAAS,EAAE,IAAI,CAAc;IAG7B,SAAS,EAAE,IAAI,CAAc;CAC9B"}
@@ -0,0 +1,119 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { Entity, Index, OptionalProps, PrimaryKey, Property } from '@mikro-orm/core';
11
+ import { GlobalEntity } from '@endora-commerce/platform/tenancy';
12
+ import { randomUUID } from 'crypto';
13
+ /**
14
+ * A line in a Cart. Two-layer pricing snapshot (feature 027):
15
+ * - `unitPrice` / `currency`: the price the line was added at. Read-only
16
+ * after add; useful for audit / diff and for the "added at" column in
17
+ * cart_audit_entries metadata.
18
+ * - `recomputedUnitPrice` / `recomputedAt` / `recomputedCurrency`: the
19
+ * most recent re-resolved price. The Cart-Pricing-Recompute helper
20
+ * refreshes these on every full-cart-view read (with a 30 s Redis
21
+ * cache between mini-cart / full-cart / checkout-entry walks).
22
+ * Cleared on any cart-side write.
23
+ */
24
+ let CartItem = class CartItem {
25
+ [OptionalProps];
26
+ id = randomUUID();
27
+ cartId;
28
+ productId;
29
+ variantId;
30
+ quantity;
31
+ /** Price snapshot at time of add — services recalculate on read. */
32
+ unitPrice;
33
+ currency;
34
+ /**
35
+ * Most-recent re-resolved unit price (per feature 011 PricingService).
36
+ * Stale beyond the cache TTL → re-resolve on next read. Cleared on every
37
+ * cart-side write so the next read forces a fresh resolution.
38
+ */
39
+ recomputedUnitPrice;
40
+ recomputedAt;
41
+ recomputedCurrency;
42
+ /**
43
+ * Feature 043 — when this line was added as a packaging unit (e.g. a
44
+ * pallet), these snapshot the unit it came from. `quantity` above already
45
+ * holds the resulting base-piece count. Null for plain single-piece lines.
46
+ */
47
+ packagingUnitId;
48
+ packagingUnitName;
49
+ packagingUnitBaseQuantity;
50
+ createdAt = new Date();
51
+ updatedAt = new Date();
52
+ };
53
+ __decorate([
54
+ PrimaryKey({ type: 'uuid' }),
55
+ __metadata("design:type", String)
56
+ ], CartItem.prototype, "id", void 0);
57
+ __decorate([
58
+ Property({ type: 'uuid' }),
59
+ Index(),
60
+ __metadata("design:type", String)
61
+ ], CartItem.prototype, "cartId", void 0);
62
+ __decorate([
63
+ Property({ type: 'uuid' }),
64
+ __metadata("design:type", String)
65
+ ], CartItem.prototype, "productId", void 0);
66
+ __decorate([
67
+ Property({ type: 'uuid', nullable: true }),
68
+ __metadata("design:type", Object)
69
+ ], CartItem.prototype, "variantId", void 0);
70
+ __decorate([
71
+ Property({ type: 'integer' }),
72
+ __metadata("design:type", Number)
73
+ ], CartItem.prototype, "quantity", void 0);
74
+ __decorate([
75
+ Property({ type: 'decimal', precision: 12, scale: 2 }),
76
+ __metadata("design:type", String)
77
+ ], CartItem.prototype, "unitPrice", void 0);
78
+ __decorate([
79
+ Property({ type: 'string', length: 3 }),
80
+ __metadata("design:type", String)
81
+ ], CartItem.prototype, "currency", void 0);
82
+ __decorate([
83
+ Property({ type: 'decimal', precision: 12, scale: 2, nullable: true }),
84
+ __metadata("design:type", Object)
85
+ ], CartItem.prototype, "recomputedUnitPrice", void 0);
86
+ __decorate([
87
+ Property({ type: 'datetime', nullable: true }),
88
+ __metadata("design:type", Object)
89
+ ], CartItem.prototype, "recomputedAt", void 0);
90
+ __decorate([
91
+ Property({ type: 'string', length: 3, nullable: true }),
92
+ __metadata("design:type", Object)
93
+ ], CartItem.prototype, "recomputedCurrency", void 0);
94
+ __decorate([
95
+ Property({ type: 'uuid', nullable: true }),
96
+ __metadata("design:type", Object)
97
+ ], CartItem.prototype, "packagingUnitId", void 0);
98
+ __decorate([
99
+ Property({ type: 'string', length: 160, nullable: true }),
100
+ __metadata("design:type", Object)
101
+ ], CartItem.prototype, "packagingUnitName", void 0);
102
+ __decorate([
103
+ Property({ type: 'integer', nullable: true }),
104
+ __metadata("design:type", Object)
105
+ ], CartItem.prototype, "packagingUnitBaseQuantity", void 0);
106
+ __decorate([
107
+ Property({ type: 'datetime', onCreate: () => new Date() }),
108
+ __metadata("design:type", Date)
109
+ ], CartItem.prototype, "createdAt", void 0);
110
+ __decorate([
111
+ Property({ type: 'datetime', onUpdate: () => new Date() }),
112
+ __metadata("design:type", Date)
113
+ ], CartItem.prototype, "updatedAt", void 0);
114
+ CartItem = __decorate([
115
+ GlobalEntity(),
116
+ Entity({ tableName: 'cart_items' })
117
+ ], CartItem);
118
+ export { CartItem };
119
+ //# sourceMappingURL=cart-item.entity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cart-item.entity.js","sourceRoot":"","sources":["../../../src/backend/entities/cart-item.entity.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AACrF,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEpC;;;;;;;;;;GAUG;AAGI,IAAM,QAAQ,GAAd,MAAM,QAAQ;IACnB,CAAC,aAAa,CAAC,CAUiB;IAGhC,EAAE,GAAW,UAAU,EAAE,CAAC;IAI1B,MAAM,CAAU;IAGhB,SAAS,CAAU;IAGnB,SAAS,CAAiB;IAG1B,QAAQ,CAAU;IAElB,oEAAoE;IAEpE,SAAS,CAAU;IAGnB,QAAQ,CAAU;IAElB;;;;OAIG;IAEH,mBAAmB,CAAiB;IAGpC,YAAY,CAAe;IAG3B,kBAAkB,CAAiB;IAEnC;;;;OAIG;IAEH,eAAe,CAAiB;IAGhC,iBAAiB,CAAiB;IAGlC,yBAAyB,CAAiB;IAG1C,SAAS,GAAS,IAAI,IAAI,EAAE,CAAC;IAG7B,SAAS,GAAS,IAAI,IAAI,EAAE,CAAC;CAC9B,CAAA;AAvDC;IADC,UAAU,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;oCACH;AAI1B;IAFC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC1B,KAAK,EAAE;;wCACQ;AAGhB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;2CACR;AAGnB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;2CACjB;AAG1B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;;0CACZ;AAIlB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;;2CACpC;AAGnB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;;0CACtB;AAQlB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;qDACnC;AAGpC;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;8CACpB;AAG3B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;oDACrB;AAQnC;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;iDACX;AAGhC;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;mDACxB;AAGlC;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;2DACJ;AAG1C;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;8BAChD,IAAI;2CAAc;AAG7B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;8BAChD,IAAI;2CAAc;AApElB,QAAQ;IAFpB,YAAY,EAAE;IACd,MAAM,CAAC,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC;GACvB,QAAQ,CAqEpB"}
@@ -0,0 +1,96 @@
1
+ import { OptionalProps } from '@mikro-orm/core';
2
+ /**
3
+ * Cart — a buyer's in-progress basket. Owned by a Customer (authenticated)
4
+ * or an anonymous session (cookie-token addressable). Scoped to a Sales
5
+ * Channel (feature 027) so the spec's "one active cart per
6
+ * (Customer, Sales Channel)" rule holds.
7
+ *
8
+ * Status lifecycle (feature 027):
9
+ * active → abandoned (sweep: last_activity_at past threshold)
10
+ * abandoned → active (owner activity)
11
+ * active → completed (checkout success OR cart→QR conversion)
12
+ * active → rejected (org-admin reject OR platform-admin reject)
13
+ *
14
+ * Legacy `converted` was migrated to `completed` by migration 050. Mass
15
+ * code in the repo that previously wrote `'converted'` now writes
16
+ * `'completed'` (CartService.clearForCustomer).
17
+ *
18
+ * `approval_status` is the orthogonal sub-state that gates checkout when
19
+ * the Organization's `requires_cart_approval` policy is `true`. Self-
20
+ * approval exemption: a cart created by an Org Admin is born with
21
+ * `approval_status='not_required'` regardless of the policy. Post-approval
22
+ * mutation re-arms `approved → pending` (see CartApprovalService).
23
+ *
24
+ * `version` is the optimistic-lock token used by the approval / mutation
25
+ * race (buyer-vs-Org-Admin) — aligned with the convention shared by
26
+ * features 003 / 026.
27
+ */
28
+ export declare class Cart {
29
+ [OptionalProps]?: 'id' | 'createdAt' | 'updatedAt' | 'customerAccountId' | 'organizationId' | 'anonymousCartToken' | 'salesChannelId' | 'status' | 'approvalStatus' | 'submittedForApprovalAt' | 'approvedAt' | 'approvedByCustomerAccountId' | 'rejectedAt' | 'rejectedByActor' | 'rejectedReason' | 'appliedPromotionCode' | 'completedOrderId' | 'convertedToQuoteRequestId' | 'abandonmentNotifiedAt' | 'lastActivityAt' | 'version';
30
+ id: string;
31
+ customerAccountId?: string | null;
32
+ organizationId?: string | null;
33
+ anonymousCartToken?: string | null;
34
+ /**
35
+ * Sales channel the cart is scoped to. Backfilled to the system-default
36
+ * channel by migration 050; NULL is read as "system default" until the
37
+ * next consolidation tightens it (see research.md §R3).
38
+ */
39
+ salesChannelId?: string | null;
40
+ status: CartStatus;
41
+ approvalStatus: CartApprovalStatus;
42
+ submittedForApprovalAt?: Date | null;
43
+ approvedAt?: Date | null;
44
+ approvedByCustomerAccountId?: string | null;
45
+ rejectedAt?: Date | null;
46
+ /** Free-form `customer:<uuid>` / `admin:<uuid>` / `org_admin:<uuid>`. */
47
+ rejectedByActor?: string | null;
48
+ rejectedReason?: string | null;
49
+ /**
50
+ * The Promotion.code the buyer most recently applied to this cart. The
51
+ * resolver in PromotionService.applyToCart consumes this on every read.
52
+ * Persisted even on terminal carts for audit / analytics.
53
+ */
54
+ appliedPromotionCode?: string | null;
55
+ /**
56
+ * The order this cart produced, set by `placeOrder` beside
57
+ * `status = 'completed'` and inside the placement transaction (D-94.1).
58
+ *
59
+ * The twin of {@link convertedToQuoteRequestId}: the two terminal artefacts
60
+ * a cart can leave behind, and until D-94 only one of them was recorded —
61
+ * asked which order emptied a completed cart, the platform answered by
62
+ * correlating timestamps. `carts_completed_order_fk` holds it
63
+ * (`on delete set null`), for the reason the QR pointer's migration wrote
64
+ * down for its own: deleting the order does not invalidate the fact that
65
+ * the cart was once completed.
66
+ *
67
+ * Nullable, and it stays nullable. It cannot be backfilled — no surviving
68
+ * record says which order emptied which historical cart — and
69
+ * `status = 'completed'` does not imply it: `CartService.clearForCustomer`,
70
+ * the anonymous-merge source and the quote-request conversion all reach
71
+ * `completed` without an order.
72
+ */
73
+ completedOrderId?: string | null;
74
+ /** Set on Cart → Quote Request conversion (feature 027 US3). */
75
+ convertedToQuoteRequestId?: string | null;
76
+ /**
77
+ * Idempotency stamp for the abandonment-sweep notification. Cleared on
78
+ * reactivation so the next abandonment cycle can notify again.
79
+ */
80
+ abandonmentNotifiedAt?: Date | null;
81
+ /**
82
+ * Bumped by every buyer-driven add / remove / qty / coupon / explicit
83
+ * page-open. Drives the abandonment sweep. NOT bumped by mini-cart
84
+ * hovers or non-owner inspections (Org-Admin / platform-admin reads).
85
+ */
86
+ lastActivityAt: Date;
87
+ /** Optimistic-lock token (auto-incremented by MikroORM on every update). */
88
+ version: number;
89
+ createdAt: Date;
90
+ updatedAt: Date;
91
+ }
92
+ export type CartStatus = 'active' | 'abandoned' | 'completed' | 'rejected';
93
+ export declare const CART_STATUSES: readonly CartStatus[];
94
+ export type CartApprovalStatus = 'not_required' | 'pending' | 'approved' | 'rejected_by_org_admin';
95
+ export declare const CART_APPROVAL_STATUSES: readonly CartApprovalStatus[];
96
+ //# sourceMappingURL=cart.entity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cart.entity.d.ts","sourceRoot":"","sources":["../../../src/backend/entities/cart.entity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,aAAa,EAAgC,MAAM,iBAAiB,CAAC;AAI7F;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBAEa,IAAI;IACf,CAAC,aAAa,CAAC,CAAC,EACZ,IAAI,GACJ,WAAW,GACX,WAAW,GACX,mBAAmB,GACnB,gBAAgB,GAChB,oBAAoB,GACpB,gBAAgB,GAChB,QAAQ,GACR,gBAAgB,GAChB,wBAAwB,GACxB,YAAY,GACZ,6BAA6B,GAC7B,YAAY,GACZ,iBAAiB,GACjB,gBAAgB,GAChB,sBAAsB,GACtB,kBAAkB,GAClB,2BAA2B,GAC3B,uBAAuB,GACvB,gBAAgB,GAChB,SAAS,CAAC;IAGd,EAAE,EAAE,MAAM,CAAgB;IAI1B,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAIlC,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAI/B,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEnC;;;;OAIG;IAEH,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAG/B,MAAM,EAAE,UAAU,CAAY;IAG9B,cAAc,EAAE,kBAAkB,CAAkB;IAGpD,sBAAsB,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IAGrC,UAAU,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IAGzB,2BAA2B,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAG5C,UAAU,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IAEzB,yEAAyE;IAEzE,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAGhC,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE/B;;;;OAIG;IAEH,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAErC;;;;;;;;;;;;;;;;;OAiBG;IAEH,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEjC,gEAAgE;IAEhE,yBAAyB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE1C;;;OAGG;IAEH,qBAAqB,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IAEpC;;;;OAIG;IAEH,cAAc,EAAE,IAAI,CAAc;IAElC,4EAA4E;IAE5E,OAAO,EAAG,MAAM,CAAC;IAGjB,SAAS,EAAE,IAAI,CAAc;IAG7B,SAAS,EAAE,IAAI,CAAc;CAC9B;AAED,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,GAAG,UAAU,CAAC;AAE3E,eAAO,MAAM,aAAa,EAAE,SAAS,UAAU,EAKrC,CAAC;AAEX,MAAM,MAAM,kBAAkB,GAC1B,cAAc,GACd,SAAS,GACT,UAAU,GACV,uBAAuB,CAAC;AAE5B,eAAO,MAAM,sBAAsB,EAAE,SAAS,kBAAkB,EAKtD,CAAC"}