@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,620 @@
1
+ import { addCartItemRequestSchema, updateCartItemRequestSchema, saveCartItemToListSchema, cartUpsellsQuerySchema, applyCartCouponSchema, convertCartToQrSchema, ERROR_CODES, OrganizationCannotTransactError, } from '@endora-commerce/contracts';
2
+ import { derivePrimaryCta } from './services/cart-state-machine.js';
3
+ import { HttpError } from '@endora-commerce/platform/http';
4
+ import { productAudienceOf } from '@endora-commerce/platform/http';
5
+ import { rethrowIfModuleDisabled } from '@endora-commerce/platform/kernel';
6
+ const ANON_COOKIE = 'b2b_cart_anon';
7
+ /**
8
+ * Cart routes — open to anonymous users too. The resolver picks the right
9
+ * cart based on (authenticated session, anonymous cookie, neither).
10
+ *
11
+ * Anonymous callers receive a Set-Cookie for `b2b_cart_anon` on first add so
12
+ * later requests target the same cart.
13
+ */
14
+ export async function registerCartRoutes(app, deps) {
15
+ const { cartService, resolveCartActor, emFactory } = deps;
16
+ const { assertOrganizationCanTransact } = deps;
17
+ /**
18
+ * Refuses to mutate a cart when the signed-in Customer's Organization is
19
+ * not active. Anonymous carts are always permitted (no Organization is
20
+ * attached to them).
21
+ */
22
+ const guardOrganizationTransact = async (actor) => {
23
+ if (!assertOrganizationCanTransact)
24
+ return;
25
+ if (!actor.customer)
26
+ return;
27
+ // No-org Customer accounts (feature 026 US2) bypass the gate — they
28
+ // already use platform defaults and have no Organization status to fail
29
+ // against. Cart-add stays open.
30
+ if (!actor.customer.organizationId)
31
+ return;
32
+ try {
33
+ await assertOrganizationCanTransact(actor.customer.organizationId);
34
+ }
35
+ catch (err) {
36
+ if (err instanceof OrganizationCannotTransactError) {
37
+ throw new HttpError(423, ERROR_CODES.FORBIDDEN, 'Your Organization cannot transact in its current status.', { code: 'organization_cannot_transact', status: err.status });
38
+ }
39
+ throw err;
40
+ }
41
+ };
42
+ app.get('/api/v1/cart', async (request) => {
43
+ const actor = resolveCartActor(request);
44
+ const em = emFactory();
45
+ let cart = null;
46
+ if (actor.customer) {
47
+ cart = await cartService.getOrCreateForCustomer(actor.customer);
48
+ }
49
+ else if (actor.anonymousToken) {
50
+ cart = await cartService.getOrCreateForAnon(em, actor.anonymousToken);
51
+ }
52
+ else {
53
+ return request.query?.view === 'mini'
54
+ ? { data: emptyMiniCart() }
55
+ : { data: emptyCart() };
56
+ }
57
+ const items = await cartService.getItems(cart.id);
58
+ // Feature 027 FR-007 — mini-cart payload. Skips re-pricing-on-read,
59
+ // skips coupon re-evaluation, and emits the lightweight serializer
60
+ // (no per-line `unavailable*`, no `droppedLines`, no
61
+ // `couponDroppedThisRead`). The mini endpoint is on the storefront's
62
+ // hot path (every header render) so the heavy work is intentionally
63
+ // deferred to the full view.
64
+ if (request.query?.view === 'mini') {
65
+ return { data: serializeCartMini(cart, items) };
66
+ }
67
+ // Resolve per-line display name + slug so the storefront does not
68
+ // have to fan out one fetch per line. Bulk lookup keyed by
69
+ // productId; locale comes from Accept-Language (first tag wins),
70
+ // English/Polish are the documented fallback chain.
71
+ const preferredLanguage = parsePreferredLanguage(request.headers['accept-language']);
72
+ // Never block a cart read on a product-meta lookup hiccup (schema drift,
73
+ // a malformed product row, a since-deleted product): fall back to empty
74
+ // meta so lines still render with null names rather than 500ing the whole
75
+ // cart. Mirrors the recompute/coupon/promotion guards below.
76
+ let productMeta;
77
+ try {
78
+ productMeta = await loadProductMeta(deps.catalogProducts, items.map((it) => it.productId), preferredLanguage);
79
+ }
80
+ catch (err) {
81
+ request.log.warn({ err, cartId: cart.id }, 'cart product-meta lookup failed; rendering without names');
82
+ productMeta = new Map();
83
+ }
84
+ // Feature 027 §R5 — re-pricing on read (FR-008).
85
+ let recomputedPrices = null;
86
+ if (deps.cartPricingRecompute && items.length > 0) {
87
+ try {
88
+ const lines = items.map((it) => ({
89
+ cartItemId: it.id,
90
+ productId: it.productId,
91
+ variantId: it.variantId ?? null,
92
+ quantity: it.quantity,
93
+ }));
94
+ const resolved = await deps.cartPricingRecompute.recompute({
95
+ cartId: cart.id,
96
+ organizationId: cart.organizationId ?? null,
97
+ salesChannelId: cart.salesChannelId ?? null,
98
+ }, lines);
99
+ recomputedPrices = new Map(resolved
100
+ .filter((r) => r.amount !== null)
101
+ .map((r) => [r.cartItemId, { amount: r.amount, currency: r.currency }]));
102
+ }
103
+ catch (err) {
104
+ // The tolerance is narrow and stays: a resolver hiccup on one read must
105
+ // not take the whole cart down, and the snapshotted unit price is a
106
+ // figure the platform actually quoted.
107
+ //
108
+ // What it may not absorb is the presence answer (issue #124). `carts`
109
+ // declares `price_lists` a hard dependency, so an absent one fails
110
+ // closed — and this `catch` was quietly deciding the opposite: it
111
+ // rendered every line at its snapshot with `price_lists` switched off
112
+ // and said nothing, so the buyer read prices from a module the platform
113
+ // was refusing to serve and found out at checkout.
114
+ rethrowIfModuleDisabled(err);
115
+ request.log.warn({ err, cartId: cart.id }, 'cart repricing failed; rendering snapshots');
116
+ recomputedPrices = null;
117
+ }
118
+ }
119
+ // Feature 027 US2 / FR-014 — re-evaluate the applied coupon on every
120
+ // read. If a previously-valid code is no longer eligible (e.g. the
121
+ // cart fell below min spend after a line removal), drop it silently
122
+ // on the cart record and surface `couponDroppedThisRead` so the
123
+ // storefront banner can inform the buyer.
124
+ let couponDroppedThisRead = null;
125
+ if (deps.cartCouponService && cart.appliedPromotionCode && items.length > 0) {
126
+ try {
127
+ const result = await deps.cartCouponService.reevaluateOnRead(cart, items);
128
+ if (result.dropped) {
129
+ couponDroppedThisRead = result.dropped;
130
+ }
131
+ }
132
+ catch (err) {
133
+ // Never block a cart read on a coupon-engine hiccup — but an absent
134
+ // `promotions` is not a hiccup (issue #124). Swallowing it charged the
135
+ // buyer the undiscounted total while the cart went on showing the code.
136
+ rethrowIfModuleDisabled(err);
137
+ couponDroppedThisRead = null;
138
+ }
139
+ }
140
+ // Feature 045 — compute the real discount + per-promotion breakdown on
141
+ // read so the cart shows applied promotions (FR-031/FR-033). Never block
142
+ // a cart read on a promotion-engine hiccup.
143
+ let application = null;
144
+ if (deps.cartCouponService && items.length > 0) {
145
+ try {
146
+ application = await deps.cartCouponService.computeApplication(cart, items);
147
+ }
148
+ catch (err) {
149
+ // Same rule as the coupon re-evaluation above: a hiccup degrades to "no
150
+ // breakdown", an absent `promotions` does not degrade at all.
151
+ rethrowIfModuleDisabled(err);
152
+ application = null;
153
+ }
154
+ }
155
+ return {
156
+ data: serializeCart(cart, items, recomputedPrices, couponDroppedThisRead, productMeta, application),
157
+ };
158
+ });
159
+ app.post('/api/v1/cart/items', { schema: { body: addCartItemRequestSchema } }, async (request, reply) => {
160
+ let actor = resolveCartActor(request);
161
+ // If neither side identified, mint an anonymous token and echo it back.
162
+ if (!actor.customer && !actor.anonymousToken) {
163
+ const token = `anon-${crypto.randomUUID()}`;
164
+ reply.setCookie(ANON_COOKIE, token, { path: '/', sameSite: 'lax', httpOnly: true });
165
+ actor = { anonymousToken: token };
166
+ }
167
+ await guardOrganizationTransact(actor);
168
+ const body = addCartItemRequestSchema.parse(request.body);
169
+ const result = await cartService.addItem(actor, {
170
+ productId: body.productId,
171
+ ...(body.variantId ? { variantId: body.variantId } : {}),
172
+ quantity: body.quantity,
173
+ ...(body.packagingUnitId ? { packagingUnitId: body.packagingUnitId } : {}),
174
+ });
175
+ return { data: serializeCart(result.cart, result.items) };
176
+ });
177
+ app.patch('/api/v1/cart/items/:itemId', { schema: { body: updateCartItemRequestSchema } }, async (request) => {
178
+ const actor = resolveCartActor(request);
179
+ const body = updateCartItemRequestSchema.parse(request.body);
180
+ const result = await cartService.updateItem(actor, request.params.itemId, body.quantity);
181
+ return { data: serializeCart(result.cart, result.items) };
182
+ });
183
+ app.delete('/api/v1/cart/items/:itemId', async (request) => {
184
+ const actor = resolveCartActor(request);
185
+ const result = await cartService.removeItem(actor, request.params.itemId);
186
+ return { data: serializeCart(result.cart, result.items) };
187
+ });
188
+ // ── Feature 027 — new endpoints (touch / save-to-shopping-list / upsells)
189
+ /**
190
+ * Explicit "buyer opened the cart page" ping. Bumps last_activity_at;
191
+ * reactivates an abandoned cart back to active. No-op on missing cart
192
+ * (no error — the storefront calls this on every cart-page mount).
193
+ */
194
+ app.post('/api/v1/cart/touch', async (request, reply) => {
195
+ const actor = resolveCartActor(request);
196
+ if (!actor.customer && !actor.anonymousToken) {
197
+ reply.code(204);
198
+ return null;
199
+ }
200
+ await cartService.touch(actor);
201
+ reply.code(204);
202
+ return null;
203
+ });
204
+ /**
205
+ * Push one cart line into the named Purchase List. Cross-module call
206
+ * goes through the optional `pushLineToShoppingList` port; if not
207
+ * wired, the route returns HTTP 503 so the storefront surfaces the
208
+ * "feature unavailable" message instead of silently dropping.
209
+ */
210
+ app.post('/api/v1/cart/items/:itemId/save-to-shopping-list', { schema: { body: saveCartItemToListSchema } }, async (request, reply) => {
211
+ const actor = resolveCartActor(request);
212
+ if (!actor.customer) {
213
+ throw new HttpError(401, ERROR_CODES.UNAUTHORIZED, 'Sign-in required to save to a shopping list.');
214
+ }
215
+ if (!deps.pushLineToShoppingList) {
216
+ throw new HttpError(503, ERROR_CODES.NOT_FOUND, 'shopping_lists_unavailable');
217
+ }
218
+ const body = saveCartItemToListSchema.parse(request.body);
219
+ const item = await emFactory().findOne((await import('./entities/cart-item.entity.js')).CartItem, { id: request.params.itemId });
220
+ if (!item) {
221
+ throw new HttpError(404, ERROR_CODES.NOT_FOUND, 'Cart item not found.');
222
+ }
223
+ // Ownership: only the cart's owner may save its line.
224
+ const cart = await emFactory().findOne((await import('./entities/cart.entity.js')).Cart, { id: item.cartId });
225
+ if (!cart || cart.customerAccountId !== actor.customer.customerAccountId) {
226
+ throw new HttpError(404, ERROR_CODES.NOT_FOUND, 'Cart item not found.');
227
+ }
228
+ await deps.pushLineToShoppingList({
229
+ customerAccountId: actor.customer.customerAccountId,
230
+ organizationId: actor.customer.organizationId,
231
+ shoppingListId: body.shoppingListId,
232
+ productId: item.productId,
233
+ variantId: item.variantId ?? null,
234
+ quantity: item.quantity,
235
+ });
236
+ reply.code(204);
237
+ return null;
238
+ });
239
+ /**
240
+ * Apply (or replace, or clear) the active coupon code on the cart.
241
+ * Returns the recomputed full cart on success; HTTP 422 with a
242
+ * reason-specific body on rejection.
243
+ */
244
+ app.post('/api/v1/cart/coupon', { schema: { body: applyCartCouponSchema } }, async (request) => {
245
+ const actor = resolveCartActor(request);
246
+ const em = emFactory();
247
+ let cart = null;
248
+ if (actor.customer) {
249
+ cart = await cartService.getOrCreateForCustomer(actor.customer);
250
+ }
251
+ else if (actor.anonymousToken) {
252
+ cart = await cartService.getOrCreateForAnon(em, actor.anonymousToken);
253
+ }
254
+ else {
255
+ throw new HttpError(401, ERROR_CODES.UNAUTHORIZED, 'Cart not found.');
256
+ }
257
+ const items = await cartService.getItems(cart.id);
258
+ if (items.length === 0) {
259
+ throw new HttpError(422, ERROR_CODES.CART_EMPTY, 'cart_empty');
260
+ }
261
+ if (!deps.cartCouponService) {
262
+ throw new HttpError(503, ERROR_CODES.NOT_FOUND, 'promotions_unavailable');
263
+ }
264
+ const body = applyCartCouponSchema.parse(request.body);
265
+ const result = await deps.cartCouponService.apply(cart, body.code);
266
+ if (result.outcome === 'dropped') {
267
+ // Issue #231 — the discriminator goes in **both** fields, and the
268
+ // duplication is the point.
269
+ //
270
+ // `reason` is what the published contract carries
271
+ // (`couponFailureBodySchema` in `packages/contracts/src/carts.ts`) and
272
+ // what the storefront branches on. `code` is what the envelope's
273
+ // `refusalToken` reads (`src/http/error-envelope.ts`) to build
274
+ // `errors.CART_COUPON_REJECTED.<token>` — the keys this module's bundle
275
+ // files the seven written reason sentences under. Spelling the
276
+ // discriminator only `reason` is why every one of them was dead: a
277
+ // buyer under the minimum spend was shown the generic refusal while a
278
+ // translated sentence telling them what to do about it sat unread.
279
+ //
280
+ // Additive on purpose. Renaming `reason` to `code` would be one field
281
+ // instead of two and would break a shape two schemas already publish.
282
+ const detailsBody = {
283
+ code: result.reason,
284
+ reason: result.reason,
285
+ };
286
+ if ('shortfall' in result && result.shortfall) {
287
+ detailsBody['shortfall'] = result.shortfall;
288
+ }
289
+ throw new HttpError(422, ERROR_CODES.CART_COUPON_REJECTED, 'CART_COUPON_REJECTED', detailsBody);
290
+ }
291
+ const freshItems = await cartService.getItems(cart.id);
292
+ return { data: serializeCart(cart, freshItems) };
293
+ });
294
+ /**
295
+ * Convenience alias for `POST /api/v1/cart/coupon` with `code=null`.
296
+ */
297
+ app.delete('/api/v1/cart/coupon', async (request) => {
298
+ const actor = resolveCartActor(request);
299
+ const em = emFactory();
300
+ let cart = null;
301
+ if (actor.customer) {
302
+ cart = await cartService.getOrCreateForCustomer(actor.customer);
303
+ }
304
+ else if (actor.anonymousToken) {
305
+ cart = await cartService.getOrCreateForAnon(em, actor.anonymousToken);
306
+ }
307
+ else {
308
+ throw new HttpError(401, ERROR_CODES.UNAUTHORIZED, 'Cart not found.');
309
+ }
310
+ if (deps.cartCouponService) {
311
+ await deps.cartCouponService.clear(cart);
312
+ }
313
+ const items = await cartService.getItems(cart.id);
314
+ return { data: serializeCart(cart, items) };
315
+ });
316
+ // ── Feature 027 US3 — three conversions
317
+ /**
318
+ * Cart → Quote Request. Refuses on an empty cart or unauthenticated
319
+ * caller. Source cart flips to `completed` with
320
+ * `converted_to_quote_request_id` set.
321
+ */
322
+ app.post('/api/v1/cart/convert-to-quote-request', { schema: { body: convertCartToQrSchema } }, async (request) => {
323
+ const actor = resolveCartActor(request);
324
+ if (!actor.customer) {
325
+ throw new HttpError(401, ERROR_CODES.UNAUTHORIZED, 'Sign-in required.');
326
+ }
327
+ if (!deps.cartConversionService) {
328
+ throw new HttpError(503, ERROR_CODES.NOT_FOUND, 'quote_requests_unavailable');
329
+ }
330
+ // D-178 — an invariant, not a business state; see
331
+ // `routes.organization.ts`'s twin.
332
+ if (!actor.customer.organizationId) {
333
+ throw new HttpError(500, ERROR_CODES.INTERNAL, 'Invariant violated: a customer account has no Organization (Principle XI).');
334
+ }
335
+ const cart = await cartService.getOrCreateForCustomer(actor.customer);
336
+ const body = convertCartToQrSchema.parse(request.body ?? {});
337
+ const result = await deps.cartConversionService.convertToQuoteRequest(cart, {
338
+ customerAccountId: actor.customer.customerAccountId,
339
+ organizationId: actor.customer.organizationId,
340
+ isOrgAdmin: false,
341
+ }, body.note);
342
+ return {
343
+ data: {
344
+ quoteRequestId: result.quoteRequestId,
345
+ cartId: result.cartId,
346
+ quoteRequestSlug: result.quoteRequestId,
347
+ },
348
+ };
349
+ });
350
+ /**
351
+ * Quote Request → Cart. Re-prices from the customer's current list;
352
+ * unavailable / no-price lines are dropped and returned to the
353
+ * caller.
354
+ */
355
+ app.post('/api/v1/cart/from-quote-request/:quoteRequestId', async (request) => {
356
+ const actor = resolveCartActor(request);
357
+ if (!actor.customer) {
358
+ throw new HttpError(401, ERROR_CODES.UNAUTHORIZED, 'Sign-in required.');
359
+ }
360
+ if (!deps.cartConversionService) {
361
+ throw new HttpError(503, ERROR_CODES.NOT_FOUND, 'quote_requests_unavailable');
362
+ }
363
+ const result = await deps.cartConversionService.createCartFromQuoteRequest(request.params.quoteRequestId, actor.customer);
364
+ return { data: result };
365
+ });
366
+ /**
367
+ * Shopping List → Cart. Delegates to ShoppingListService.convertToCart
368
+ * through the `appendShoppingListToCart` port. Composition wires that
369
+ * port at boot time.
370
+ */
371
+ app.post('/api/v1/cart/from-shopping-list/:shoppingListId', async (request) => {
372
+ const actor = resolveCartActor(request);
373
+ if (!actor.customer) {
374
+ throw new HttpError(401, ERROR_CODES.UNAUTHORIZED, 'Sign-in required.');
375
+ }
376
+ if (!deps.appendShoppingListToCart) {
377
+ throw new HttpError(503, ERROR_CODES.NOT_FOUND, 'shopping_lists_unavailable');
378
+ }
379
+ const result = await deps.appendShoppingListToCart({
380
+ customerAccountId: actor.customer.customerAccountId,
381
+ organizationId: actor.customer.organizationId,
382
+ shoppingListId: request.params.shoppingListId,
383
+ });
384
+ return { data: result };
385
+ });
386
+ /**
387
+ * Up-sell strip for the full cart view. Aggregator over Catalog's
388
+ * `product_links` (kind = 'up_sell'); excludes products already in
389
+ * the cart; ranks by match-count desc, tie-break oldest-first.
390
+ */
391
+ app.get('/api/v1/cart/upsells', async (request) => {
392
+ if (!deps.cartUpsellService) {
393
+ return { data: [] };
394
+ }
395
+ const actor = resolveCartActor(request);
396
+ const em = emFactory();
397
+ let cart = null;
398
+ if (actor.customer) {
399
+ cart = await cartService.getOrCreateForCustomer(actor.customer);
400
+ }
401
+ else if (actor.anonymousToken) {
402
+ cart = await cartService.getOrCreateForAnon(em, actor.anonymousToken);
403
+ }
404
+ if (!cart)
405
+ return { data: [] };
406
+ const parsed = cartUpsellsQuerySchema.parse(request.query ?? {});
407
+ const limit = parsed.limit ?? 12;
408
+ const candidates = await deps.cartUpsellService.forCart(cart.id, limit, productAudienceOf(request));
409
+ return { data: candidates };
410
+ });
411
+ }
412
+ function emptyCart() {
413
+ return {
414
+ id: null,
415
+ customerAccountId: null,
416
+ organizationId: null,
417
+ salesChannelId: null,
418
+ anonymousCartToken: null,
419
+ status: 'active',
420
+ approvalStatus: 'not_required',
421
+ items: [],
422
+ itemCount: 0,
423
+ subtotal: { amount: 0, currency: 'PLN' },
424
+ discount: null,
425
+ appliedPromotions: [],
426
+ grandTotal: { amount: 0, currency: 'PLN' },
427
+ primaryCta: 'checkout',
428
+ droppedLines: [],
429
+ couponDroppedThisRead: null,
430
+ createdAt: null,
431
+ updatedAt: null,
432
+ lastActivityAt: null,
433
+ };
434
+ }
435
+ function emptyMiniCart() {
436
+ return {
437
+ id: null,
438
+ itemCount: 0,
439
+ items: [],
440
+ subtotal: { amount: 0, currency: 'PLN' },
441
+ };
442
+ }
443
+ /**
444
+ * Mini-cart payload (Feature 027 FR-007). Strips the heavy parts of the
445
+ * full view: no re-pricing-on-read, no coupon re-evaluation, no per-line
446
+ * `unavailable*`, no `droppedLines`, no `couponDroppedThisRead`, no
447
+ * `primaryCta`. The header renders this on every page navigation so the
448
+ * envelope is intentionally minimal.
449
+ */
450
+ function serializeCartMini(cart, items) {
451
+ let subtotal = 0;
452
+ const currency = items[0]?.currency ?? 'PLN';
453
+ const serializedItems = items.map((it) => {
454
+ const unitPriceAmount = Number(it.unitPrice);
455
+ subtotal += unitPriceAmount * it.quantity;
456
+ return {
457
+ id: it.id,
458
+ productId: it.productId,
459
+ variantId: it.variantId ?? null,
460
+ quantity: it.quantity,
461
+ unitPrice: { amount: unitPriceAmount, currency: it.currency },
462
+ lineTotal: { amount: unitPriceAmount * it.quantity, currency: it.currency },
463
+ };
464
+ });
465
+ return {
466
+ id: cart.id,
467
+ itemCount: items.length,
468
+ items: serializedItems,
469
+ subtotal: { amount: subtotal, currency },
470
+ };
471
+ }
472
+ function serializeCart(cart, items, recomputedPrices = null, couponDroppedThisRead = null, productMeta = new Map(), application = null) {
473
+ let subtotal = 0;
474
+ let currency = items[0]?.currency ?? 'PLN';
475
+ const serializedItems = items.map((it) => {
476
+ const recomputed = recomputedPrices?.get(it.id);
477
+ const unitPriceAmount = recomputed ? recomputed.amount : Number(it.unitPrice);
478
+ const lineCurrency = recomputed ? recomputed.currency : it.currency;
479
+ if (currency === 'PLN' && lineCurrency !== 'PLN')
480
+ currency = lineCurrency;
481
+ subtotal += unitPriceAmount * it.quantity;
482
+ const meta = productMeta.get(it.productId) ?? null;
483
+ // Feature 043 — append the packaging-unit name to the display name when the
484
+ // line was added as a packaging unit (e.g. "<name> (Paleta)").
485
+ const packagingUnitName = it.packagingUnitName ?? null;
486
+ const baseName = meta?.name ?? null;
487
+ const displayName = baseName !== null && packagingUnitName
488
+ ? `${baseName} (${packagingUnitName})`
489
+ : baseName;
490
+ return {
491
+ id: it.id,
492
+ productId: it.productId,
493
+ variantId: it.variantId ?? null,
494
+ quantity: it.quantity,
495
+ unitPrice: { amount: unitPriceAmount, currency: lineCurrency },
496
+ lineTotal: { amount: unitPriceAmount * it.quantity, currency: lineCurrency },
497
+ unavailable: false,
498
+ unavailableReason: null,
499
+ productName: baseName,
500
+ productSlug: meta?.slug ?? null,
501
+ productSku: meta?.sku ?? null,
502
+ packagingUnitName,
503
+ packagingUnitBaseQuantity: it.packagingUnitBaseQuantity ?? null,
504
+ displayName,
505
+ };
506
+ });
507
+ return {
508
+ id: cart.id,
509
+ customerAccountId: cart.customerAccountId ?? null,
510
+ organizationId: cart.organizationId ?? null,
511
+ salesChannelId: cart.salesChannelId ?? null,
512
+ anonymousCartToken: cart.anonymousCartToken ?? null,
513
+ status: cart.status,
514
+ approvalStatus: cart.approvalStatus,
515
+ items: serializedItems,
516
+ itemCount: items.length,
517
+ subtotal: { amount: subtotal, currency },
518
+ discount: application && application.discountTotal > 0
519
+ ? { code: cart.appliedPromotionCode ?? null, amount: application.discountTotal, currency }
520
+ : cart.appliedPromotionCode
521
+ ? { code: cart.appliedPromotionCode, amount: 0, currency }
522
+ : null,
523
+ appliedPromotions: application
524
+ ? application.appliedPromotions.map((ap) => ({
525
+ promotionId: ap.promotionId,
526
+ couponId: ap.couponId ?? null,
527
+ amount: ap.amount,
528
+ currency,
529
+ }))
530
+ : [],
531
+ grandTotal: {
532
+ amount: Math.max(0, round2Cart(subtotal - (application?.discountTotal ?? 0))),
533
+ currency,
534
+ },
535
+ primaryCta: resolvePrimaryCta(cart),
536
+ droppedLines: [],
537
+ couponDroppedThisRead,
538
+ createdAt: cart.createdAt.toISOString(),
539
+ updatedAt: cart.updatedAt.toISOString(),
540
+ lastActivityAt: cart.lastActivityAt.toISOString(),
541
+ };
542
+ }
543
+ function round2Cart(n) {
544
+ return Math.round(n * 100) / 100;
545
+ }
546
+ function resolvePrimaryCta(cart) {
547
+ // The `submit_for_approval` branch needs the Organization's policy
548
+ // flag, which the route handler does not have on hand here. The
549
+ // helper is callable from the org-admin route with the flag passed
550
+ // through explicitly; for the storefront read we default to
551
+ // `requiresApproval: false`, which makes `not_required` + cart-active
552
+ // collapse to `checkout`.
553
+ return derivePrimaryCta({
554
+ status: cart.status,
555
+ approvalStatus: cart.approvalStatus,
556
+ requiresApproval: false,
557
+ });
558
+ }
559
+ /**
560
+ * Resolves the storefront's preferred language from `Accept-Language`.
561
+ * Falls back to undefined when the header is missing — the caller
562
+ * then walks the product record's `name` locale chain in serializeCart's helper.
563
+ */
564
+ function parsePreferredLanguage(header) {
565
+ const raw = Array.isArray(header) ? header[0] : header;
566
+ if (!raw)
567
+ return undefined;
568
+ const first = raw.split(',')[0]?.trim();
569
+ return first || undefined;
570
+ }
571
+ /**
572
+ * Bulk-fetches product metadata for every productId on the cart and
573
+ * resolves a display name from the record's `name` (per-locale JSONB) using
574
+ * the `Accept-Language` tag with a `pl` → `pl-PL` → `en-US` → first
575
+ * available fallback chain. Empty list returns an empty map (the
576
+ * serializer treats `null` name as "unknown" and the storefront falls
577
+ * back to the productId).
578
+ */
579
+ async function loadProductMeta(catalogProducts, productIds, preferredLanguage) {
580
+ const meta = new Map();
581
+ if (productIds.length === 0)
582
+ return meta;
583
+ const unique = Array.from(new Set(productIds));
584
+ const products = await catalogProducts.findByIds(unique);
585
+ for (const p of products) {
586
+ meta.set(p.id, {
587
+ name: pickLocalized(p.name, preferredLanguage),
588
+ slug: p.slug,
589
+ sku: p.sku,
590
+ });
591
+ }
592
+ return meta;
593
+ }
594
+ /**
595
+ * Walks the locale-fallback chain for a per-locale JSONB field. Tries:
596
+ * 1. exact match on the preferred language (e.g. `pl-PL`)
597
+ * 2. language-only match (`pl` → first `pl-*` key)
598
+ * 3. `en-US`, then `en`
599
+ * 4. first available value
600
+ * 5. empty string
601
+ */
602
+ function pickLocalized(field, preferredLanguage) {
603
+ if (!field)
604
+ return '';
605
+ if (preferredLanguage && field[preferredLanguage])
606
+ return field[preferredLanguage];
607
+ const langOnly = preferredLanguage?.split('-')[0];
608
+ if (langOnly) {
609
+ const match = Object.keys(field).find((k) => k === langOnly || k.startsWith(`${langOnly}-`));
610
+ if (match)
611
+ return field[match] ?? '';
612
+ }
613
+ if (field['en-US'])
614
+ return field['en-US'];
615
+ if (field['en'])
616
+ return field['en'];
617
+ const first = Object.values(field)[0];
618
+ return first ?? '';
619
+ }
620
+ //# sourceMappingURL=routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/backend/routes.ts"],"names":[],"mappings":"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"}