@mohasinac/appkit 4.62.0 → 4.63.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 (391) hide show
  1. package/dist/.build-stamp.json +3 -3
  2. package/dist/_internal/client/features/layout/DashboardLayoutClient.js +8 -29
  3. package/dist/_internal/client/features/layout/filterNavItems.d.ts +28 -0
  4. package/dist/_internal/client/features/layout/filterNavItems.js +35 -0
  5. package/dist/_internal/server/features/ads/booking.d.ts +118 -0
  6. package/dist/_internal/server/features/ads/booking.js +326 -0
  7. package/dist/_internal/server/features/checkout/actions.d.ts +129 -9
  8. package/dist/_internal/server/features/checkout/actions.js +850 -79
  9. package/dist/_internal/server/features/checkout/expand-order-items.d.ts +1 -2
  10. package/dist/_internal/server/features/checkout/expand-order-items.js +32 -0
  11. package/dist/_internal/server/features/checkout/freeze-parts.d.ts +50 -0
  12. package/dist/_internal/server/features/checkout/freeze-parts.js +94 -0
  13. package/dist/_internal/server/features/checkout/value-otp-gate.d.ts +55 -0
  14. package/dist/_internal/server/features/checkout/value-otp-gate.js +60 -0
  15. package/dist/_internal/server/features/dashboard/attention.d.ts +128 -0
  16. package/dist/_internal/server/features/dashboard/attention.js +183 -0
  17. package/dist/_internal/server/features/dashboard/data.d.ts +47 -0
  18. package/dist/_internal/server/features/dashboard/data.js +82 -0
  19. package/dist/_internal/server/features/inventory/reservations.d.ts +99 -0
  20. package/dist/_internal/server/features/inventory/reservations.js +273 -0
  21. package/dist/_internal/server/features/invoicing/allocate.d.ts +63 -0
  22. package/dist/_internal/server/features/invoicing/allocate.js +162 -0
  23. package/dist/_internal/server/features/invoicing/credit-note.d.ts +57 -0
  24. package/dist/_internal/server/features/invoicing/credit-note.js +126 -0
  25. package/dist/_internal/server/features/invoicing/gstr1.d.ts +74 -0
  26. package/dist/_internal/server/features/invoicing/gstr1.js +251 -0
  27. package/dist/_internal/server/features/invoicing/issue.d.ts +96 -0
  28. package/dist/_internal/server/features/invoicing/issue.js +202 -0
  29. package/dist/_internal/server/features/offers/destinations.d.ts +40 -0
  30. package/dist/_internal/server/features/offers/destinations.js +65 -0
  31. package/dist/_internal/server/features/orders/actions.d.ts +8 -1
  32. package/dist/_internal/server/features/orders/actions.js +81 -8
  33. package/dist/_internal/server/features/orders/adapters.js +54 -0
  34. package/dist/_internal/server/features/orders/amend-delivery.d.ts +56 -0
  35. package/dist/_internal/server/features/orders/amend-delivery.js +124 -0
  36. package/dist/_internal/server/features/orders/balance.d.ts +89 -0
  37. package/dist/_internal/server/features/orders/balance.js +256 -0
  38. package/dist/_internal/server/features/orders/cancellation-refund.d.ts +15 -9
  39. package/dist/_internal/server/features/orders/cancellation-refund.js +15 -9
  40. package/dist/_internal/server/features/points/award.js +46 -4
  41. package/dist/_internal/server/features/pricing/actions.d.ts +58 -0
  42. package/dist/_internal/server/features/pricing/actions.js +144 -0
  43. package/dist/_internal/server/features/refunds/actions.js +26 -0
  44. package/dist/_internal/server/features/shipping/book-split.d.ts +86 -0
  45. package/dist/_internal/server/features/shipping/book-split.js +130 -0
  46. package/dist/_internal/server/features/shipping/book.d.ts +61 -0
  47. package/dist/_internal/server/features/shipping/book.js +176 -0
  48. package/dist/_internal/server/features/shipping/courier-block.d.ts +69 -0
  49. package/dist/_internal/server/features/shipping/courier-block.js +264 -0
  50. package/dist/_internal/server/features/site-settings/adapters.d.ts +2 -2
  51. package/dist/_internal/server/features/site-settings/adapters.js +29 -0
  52. package/dist/_internal/server/features/stores/adapters.d.ts +2 -2
  53. package/dist/_internal/server/features/stores/adapters.js +65 -0
  54. package/dist/_internal/server/functions/scheduled.d.ts +2 -1
  55. package/dist/_internal/server/functions/scheduled.js +95 -2
  56. package/dist/_internal/server/jobs/core/autoPayoutEligibility.js +11 -2
  57. package/dist/_internal/server/jobs/core/dailyStatusDigest.d.ts +4 -0
  58. package/dist/_internal/server/jobs/core/dailyStatusDigest.js +19 -2
  59. package/dist/_internal/server/jobs/core/index.d.ts +2 -1
  60. package/dist/_internal/server/jobs/core/index.js +2 -1
  61. package/dist/_internal/server/jobs/core/jobRunners.js +45 -0
  62. package/dist/_internal/server/jobs/core/onJobCreated.d.ts +30 -7
  63. package/dist/_internal/server/jobs/core/onJobCreated.js +78 -45
  64. package/dist/_internal/server/jobs/core/onOrderStatusChange.d.ts +7 -0
  65. package/dist/_internal/server/jobs/core/onOrderStatusChange.js +65 -0
  66. package/dist/_internal/server/jobs/core/paymentWindowTimeout.js +33 -0
  67. package/dist/_internal/server/jobs/core/reservationExpiry.d.ts +17 -0
  68. package/dist/_internal/server/jobs/core/reservationExpiry.js +40 -0
  69. package/dist/_internal/server/jobs/core/runJobOnce.d.ts +48 -0
  70. package/dist/_internal/server/jobs/core/runJobOnce.js +195 -0
  71. package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.js +25 -2
  72. package/dist/_internal/server/jobs/handlers/index.d.ts +1 -0
  73. package/dist/_internal/server/jobs/handlers/index.js +1 -0
  74. package/dist/_internal/server/jobs/handlers/onOrderStatusChange.js +17 -0
  75. package/dist/_internal/server/jobs/handlers/reservationExpiry.d.ts +2 -0
  76. package/dist/_internal/server/jobs/handlers/reservationExpiry.js +2 -0
  77. package/dist/_internal/server/notifications/channel-health.d.ts +26 -3
  78. package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
  79. package/dist/_internal/shared/actions/action-registry.js +296 -0
  80. package/dist/_internal/shared/checkout/coupon-discount.d.ts +43 -1
  81. package/dist/_internal/shared/checkout/coupon-discount.js +26 -1
  82. package/dist/_internal/shared/checkout/order-math.d.ts +174 -0
  83. package/dist/_internal/shared/checkout/order-math.js +159 -0
  84. package/dist/_internal/shared/checkout/refundable-base.d.ts +25 -0
  85. package/dist/_internal/shared/checkout/refundable-base.js +13 -1
  86. package/dist/_internal/shared/checkout/rules/index.d.ts +1 -1
  87. package/dist/_internal/shared/checkout/rules/index.js +1 -1
  88. package/dist/_internal/shared/checkout/rules/payment-gate.d.ts +18 -0
  89. package/dist/_internal/shared/checkout/rules/payment-gate.js +25 -0
  90. package/dist/_internal/shared/checkout/split.d.ts +75 -0
  91. package/dist/_internal/shared/checkout/split.js +120 -0
  92. package/dist/_internal/shared/content/disclaimers.d.ts +88 -0
  93. package/dist/_internal/shared/content/disclaimers.js +217 -0
  94. package/dist/_internal/shared/content/published-values.d.ts +93 -0
  95. package/dist/_internal/shared/content/published-values.js +206 -0
  96. package/dist/_internal/shared/features/admin/integrations.d.ts +139 -0
  97. package/dist/_internal/shared/features/admin/integrations.js +263 -0
  98. package/dist/_internal/shared/features/dashboard/hub-sections.d.ts +72 -0
  99. package/dist/_internal/shared/features/dashboard/hub-sections.js +75 -0
  100. package/dist/_internal/shared/features/emi/choice.d.ts +98 -0
  101. package/dist/_internal/shared/features/emi/choice.js +69 -0
  102. package/dist/_internal/shared/features/emi/group.d.ts +84 -0
  103. package/dist/_internal/shared/features/emi/group.js +126 -0
  104. package/dist/_internal/shared/features/ledger/posting.d.ts +107 -0
  105. package/dist/_internal/shared/features/ledger/posting.js +165 -0
  106. package/dist/_internal/shared/features/ledger/reports.d.ts +76 -0
  107. package/dist/_internal/shared/features/ledger/reports.js +127 -0
  108. package/dist/_internal/shared/features/ledger/rules.d.ts +170 -0
  109. package/dist/_internal/shared/features/ledger/rules.js +221 -0
  110. package/dist/_internal/shared/features/offers/coordination.d.ts +122 -0
  111. package/dist/_internal/shared/features/offers/coordination.js +80 -0
  112. package/dist/_internal/shared/features/orders/delivery-snapshot.d.ts +114 -0
  113. package/dist/_internal/shared/features/orders/delivery-snapshot.js +116 -0
  114. package/dist/_internal/shared/features/orders/dispute-reasons.d.ts +113 -0
  115. package/dist/_internal/shared/features/orders/dispute-reasons.js +181 -0
  116. package/dist/_internal/shared/features/orders/refund-copy.d.ts +1 -1
  117. package/dist/_internal/shared/features/orders/refund-copy.js +18 -1
  118. package/dist/_internal/shared/features/payouts/pay-period.d.ts +91 -0
  119. package/dist/_internal/shared/features/payouts/pay-period.js +104 -0
  120. package/dist/_internal/shared/features/points/accepts.d.ts +29 -0
  121. package/dist/_internal/shared/features/points/accepts.js +49 -0
  122. package/dist/_internal/shared/features/pricing/rate-registry.d.ts +150 -0
  123. package/dist/_internal/shared/features/pricing/rate-registry.js +246 -0
  124. package/dist/_internal/shared/features/shipping/parcel.d.ts +123 -0
  125. package/dist/_internal/shared/features/shipping/parcel.js +139 -0
  126. package/dist/_internal/shared/features/shipping/shared-purchase.d.ts +91 -0
  127. package/dist/_internal/shared/features/shipping/shared-purchase.js +108 -0
  128. package/dist/_internal/shared/features/site-settings/fees.d.ts +16 -8
  129. package/dist/_internal/shared/features/site-settings/fees.js +12 -8
  130. package/dist/_internal/shared/features/site-settings/types.d.ts +11 -0
  131. package/dist/_internal/shared/fees/calculator.d.ts +33 -1
  132. package/dist/_internal/shared/fees/calculator.js +32 -2
  133. package/dist/_internal/shared/fees/explain.d.ts +81 -0
  134. package/dist/_internal/shared/fees/explain.js +101 -0
  135. package/dist/_internal/shared/history/index.d.ts +1 -1
  136. package/dist/_internal/shared/history/index.js +1 -1
  137. package/dist/_internal/shared/history/types.d.ts +7 -1
  138. package/dist/_internal/shared/history/types.js +25 -0
  139. package/dist/client.d.ts +21 -0
  140. package/dist/client.js +43 -0
  141. package/dist/constants/api-endpoints.d.ts +114 -0
  142. package/dist/constants/api-endpoints.js +55 -0
  143. package/dist/constants/field-names.d.ts +42 -0
  144. package/dist/constants/field-names.js +52 -0
  145. package/dist/contracts/index.d.ts +1 -1
  146. package/dist/contracts/shipping.d.ts +45 -0
  147. package/dist/contracts/shipping.js +15 -0
  148. package/dist/features/about/components/AboutView.js +1 -1
  149. package/dist/features/account/components/BuyerAuctionsGuideView.js +4 -1
  150. package/dist/features/account/components/UserOrdersView.js +47 -35
  151. package/dist/features/admin/components/AdminCouponEditorView.js +17 -0
  152. package/dist/features/admin/components/AdminIntegrationsView.d.ts +55 -0
  153. package/dist/features/admin/components/AdminIntegrationsView.js +74 -0
  154. package/dist/features/admin/components/AdminInvoicingView.d.ts +2 -0
  155. package/dist/features/admin/components/AdminInvoicingView.js +65 -0
  156. package/dist/features/admin/components/AdminOrderEditorView.d.ts +33 -1
  157. package/dist/features/admin/components/AdminOrderEditorView.js +81 -3
  158. package/dist/features/admin/components/AdminOrdersGuideView.js +23 -2
  159. package/dist/features/admin/components/AdminOrdersView.js +86 -5
  160. package/dist/features/admin/components/OwnerQuickActions.js +24 -2
  161. package/dist/features/admin/constants/filter-tabs.d.ts +6 -0
  162. package/dist/features/admin/constants/filter-tabs.js +6 -0
  163. package/dist/features/admin/constants/site-settings-tabs.d.ts +1 -1
  164. package/dist/features/admin/hooks/useAdminListingData.js +16 -0
  165. package/dist/features/admin/schemas/admin-user-form.d.ts +2 -2
  166. package/dist/features/admin/schemas/firestore.d.ts +62 -0
  167. package/dist/features/admin/schemas/firestore.js +5 -0
  168. package/dist/features/ads/schemas/booking-write.d.ts +120 -0
  169. package/dist/features/ads/schemas/booking-write.js +75 -0
  170. package/dist/features/ads/schemas/creative-form.d.ts +18 -0
  171. package/dist/features/ads/schemas/creative-form.js +51 -0
  172. package/dist/features/ads/schemas/firestore.d.ts +140 -0
  173. package/dist/features/ads/schemas/firestore.js +109 -0
  174. package/dist/features/auctions/repository/bid.repository.js +3 -1
  175. package/dist/features/audit-log/schemas/firestore.d.ts +140 -0
  176. package/dist/features/audit-log/schemas/firestore.js +89 -0
  177. package/dist/features/auth/actions/profile-actions.d.ts +69 -1
  178. package/dist/features/auth/actions/profile-actions.js +62 -1
  179. package/dist/features/auth/permissions/constants.js +13 -0
  180. package/dist/features/auth/schemas/firestore.d.ts +16 -2
  181. package/dist/features/auth/schemas/firestore.js +2 -1
  182. package/dist/features/blog/actions/blog-actions.d.ts +6 -0
  183. package/dist/features/blog/actions/blog-actions.js +17 -2
  184. package/dist/features/blog/api/route.js +4 -1
  185. package/dist/features/blog/columns/index.js +5 -0
  186. package/dist/features/blog/components/BlogIndexPageView.js +2 -1
  187. package/dist/features/blog/repository/blog.repository.d.ts +4 -0
  188. package/dist/features/blog/repository/blog.repository.js +5 -0
  189. package/dist/features/blog/schemas/blog-form.d.ts +3 -0
  190. package/dist/features/blog/schemas/blog-form.js +1 -0
  191. package/dist/features/blog/schemas/firestore.d.ts +38 -1
  192. package/dist/features/blog/schemas/firestore.js +23 -0
  193. package/dist/features/blog/schemas/index.d.ts +6 -0
  194. package/dist/features/blog/schemas/index.js +2 -0
  195. package/dist/features/blog/types/index.d.ts +2 -0
  196. package/dist/features/cart/components/CartPriceBreakdown.d.ts +25 -1
  197. package/dist/features/cart/components/CartPriceBreakdown.js +29 -6
  198. package/dist/features/cart/components/PointsTenderPicker.d.ts +61 -0
  199. package/dist/features/cart/components/PointsTenderPicker.js +15 -0
  200. package/dist/features/cart/components/StoreAddonsPicker.js +2 -1
  201. package/dist/features/cart/components/index.d.ts +2 -0
  202. package/dist/features/cart/components/index.js +1 -0
  203. package/dist/features/cart/repository/cart.repository.d.ts +33 -0
  204. package/dist/features/cart/repository/cart.repository.js +47 -0
  205. package/dist/features/cart/schemas/firestore.d.ts +116 -0
  206. package/dist/features/contact/email.d.ts +27 -10
  207. package/dist/features/contact/email.js +20 -3
  208. package/dist/features/dashboard/components/DashboardHubView.d.ts +83 -0
  209. package/dist/features/dashboard/components/DashboardHubView.js +56 -0
  210. package/dist/features/dashboard/components/DashboardSectionsClient.d.ts +23 -0
  211. package/dist/features/dashboard/components/DashboardSectionsClient.js +66 -0
  212. package/dist/features/dispute-reasons/components/AdminDisputeReasonsView.d.ts +55 -0
  213. package/dist/features/dispute-reasons/components/AdminDisputeReasonsView.js +175 -0
  214. package/dist/features/dispute-reasons/repository/dispute-reasons.repository.d.ts +62 -0
  215. package/dist/features/dispute-reasons/repository/dispute-reasons.repository.js +108 -0
  216. package/dist/features/dispute-reasons/schemas/firestore.d.ts +62 -0
  217. package/dist/features/dispute-reasons/schemas/firestore.js +40 -0
  218. package/dist/features/events/components/EventSaleBanner.js +1 -1
  219. package/dist/features/faq/components/FAQAccordion.d.ts +13 -1
  220. package/dist/features/faq/components/FAQAccordion.js +29 -4
  221. package/dist/features/faq/components/FAQPageContent.js +2 -2
  222. package/dist/features/gateway-events/schemas/index.d.ts +2 -2
  223. package/dist/features/homepage/schemas/index.d.ts +8 -8
  224. package/dist/features/inventory/schemas/stock-reservation.d.ts +114 -0
  225. package/dist/features/inventory/schemas/stock-reservation.js +103 -0
  226. package/dist/features/invoicing/schemas/firestore.d.ts +112 -0
  227. package/dist/features/invoicing/schemas/firestore.js +45 -0
  228. package/dist/features/invoicing/utils/financial-year.d.ts +43 -0
  229. package/dist/features/invoicing/utils/financial-year.js +53 -0
  230. package/dist/features/jobs/actions/enqueue-job.js +18 -1
  231. package/dist/features/jobs/repository/jobs.repository.d.ts +62 -1
  232. package/dist/features/jobs/repository/jobs.repository.js +84 -1
  233. package/dist/features/jobs/schemas/firestore.d.ts +80 -0
  234. package/dist/features/jobs/schemas/firestore.js +37 -0
  235. package/dist/features/layout/AppLayoutShell.d.ts +9 -1
  236. package/dist/features/layout/AppLayoutShell.js +12 -4
  237. package/dist/features/layout/BottomActions.js +2 -1
  238. package/dist/features/layout/BottomNavbar.d.ts +10 -2
  239. package/dist/features/layout/SideActionDock.js +52 -2
  240. package/dist/features/layout/TitleBarLayout.js +13 -4
  241. package/dist/features/layout/TitleBarLayout.style.css +59 -0
  242. package/dist/features/layout/useCtaReveal.d.ts +16 -1
  243. package/dist/features/layout/useCtaReveal.js +17 -26
  244. package/dist/features/ledger/repository/journal.repository.d.ts +110 -0
  245. package/dist/features/ledger/repository/journal.repository.js +312 -0
  246. package/dist/features/ledger/schemas/expenses.d.ts +87 -0
  247. package/dist/features/ledger/schemas/expenses.js +27 -0
  248. package/dist/features/ledger/schemas/firestore.d.ts +183 -0
  249. package/dist/features/ledger/schemas/firestore.js +69 -0
  250. package/dist/features/lottery/schemas/zod.d.ts +6 -6
  251. package/dist/features/media/MediaImage.js +22 -1
  252. package/dist/features/media/upload/ImageUpload.js +1 -1
  253. package/dist/features/obligations/constants/policies.js +24 -1
  254. package/dist/features/orders/components/BalancePaymentPanel.d.ts +12 -0
  255. package/dist/features/orders/components/BalancePaymentPanel.js +94 -0
  256. package/dist/features/orders/components/OrderPaymentSummary.js +10 -1
  257. package/dist/features/orders/components/OrderProvenanceCard.d.ts +8 -0
  258. package/dist/features/orders/components/OrderProvenanceCard.js +185 -0
  259. package/dist/features/orders/components/RaiseDisputeForm.d.ts +14 -0
  260. package/dist/features/orders/components/RaiseDisputeForm.js +119 -0
  261. package/dist/features/orders/components/RefundRequestView.js +19 -1
  262. package/dist/features/orders/components/index.d.ts +4 -0
  263. package/dist/features/orders/components/index.js +2 -0
  264. package/dist/features/orders/constants/order-lane-tabs.d.ts +69 -0
  265. package/dist/features/orders/constants/order-lane-tabs.js +88 -0
  266. package/dist/features/orders/repository/orders.repository.d.ts +85 -1
  267. package/dist/features/orders/repository/orders.repository.js +205 -6
  268. package/dist/features/orders/schemas/balance.d.ts +40 -0
  269. package/dist/features/orders/schemas/balance.js +47 -0
  270. package/dist/features/orders/schemas/firestore.d.ts +398 -1
  271. package/dist/features/orders/schemas/firestore.js +43 -0
  272. package/dist/features/orders/schemas/index.d.ts +56 -8
  273. package/dist/features/orders/schemas/index.js +12 -0
  274. package/dist/features/orders/types/index.d.ts +47 -0
  275. package/dist/features/orders/utils/courier-block.d.ts +25 -0
  276. package/dist/features/orders/utils/courier-block.js +23 -0
  277. package/dist/features/payment-cases/schemas/firestore.d.ts +26 -1
  278. package/dist/features/payment-cases/schemas/firestore.js +1 -0
  279. package/dist/features/payments/repository/payout.repository.js +3 -2
  280. package/dist/features/payments/schemas/firestore.d.ts +92 -1
  281. package/dist/features/payments/schemas/firestore.js +23 -0
  282. package/dist/features/pricing/components/AdminPricingView.d.ts +13 -0
  283. package/dist/features/pricing/components/AdminPricingView.js +157 -0
  284. package/dist/features/products/components/PrizeDrawDetailPageView.js +2 -2
  285. package/dist/features/products/components/ProductDetailPageView.d.ts +17 -1
  286. package/dist/features/products/components/ProductDetailPageView.js +2 -2
  287. package/dist/features/products/schemas/firestore.d.ts +26 -1
  288. package/dist/features/products/schemas/firestore.js +2 -0
  289. package/dist/features/products/schemas/index.d.ts +2 -2
  290. package/dist/features/products/schemas/product-features.validators.d.ts +10 -10
  291. package/dist/features/promotions/actions/coupon-stacking.d.ts +30 -3
  292. package/dist/features/promotions/actions/coupon-stacking.js +21 -2
  293. package/dist/features/promotions/components/CouponCard.js +13 -0
  294. package/dist/features/promotions/constants/coupon-help.d.ts +2 -2
  295. package/dist/features/promotions/constants/coupon-help.js +9 -1
  296. package/dist/features/promotions/schemas/firestore.d.ts +24 -0
  297. package/dist/features/promotions/schemas/firestore.js +4 -0
  298. package/dist/features/promotions/types/index.d.ts +19 -1
  299. package/dist/features/reviews/repository/reviews.repository.d.ts +14 -0
  300. package/dist/features/reviews/repository/reviews.repository.js +16 -0
  301. package/dist/features/scams/components/ScamProfileView.js +2 -2
  302. package/dist/features/scams/components/ScamRegistryView.js +2 -2
  303. package/dist/features/scams/repository/scammer.repository.js +2 -1
  304. package/dist/features/scams/schemas/firestore.d.ts +2 -1
  305. package/dist/features/scams/schemas/firestore.js +2 -1
  306. package/dist/features/search/action-index/tab-entries.js +1 -1
  307. package/dist/features/seller/actions/offer-actions.js +56 -0
  308. package/dist/features/seller/actions/seller-actions.d.ts +1 -1
  309. package/dist/features/seller/actions/seller-actions.js +37 -3
  310. package/dist/features/seller/components/DispatchForm.d.ts +11 -0
  311. package/dist/features/seller/components/DispatchForm.js +190 -0
  312. package/dist/features/seller/components/SellerOrdersView.js +221 -27
  313. package/dist/features/seller/components/index.d.ts +1 -0
  314. package/dist/features/seller/components/index.js +1 -0
  315. package/dist/features/seller/hooks/useSellerListingData.js +25 -0
  316. package/dist/features/seller/repository/offer.repository.js +4 -3
  317. package/dist/features/seller/schemas/firestore.d.ts +23 -2
  318. package/dist/features/seller/schemas/firestore.js +3 -2
  319. package/dist/features/seller/schemas/index.d.ts +4 -4
  320. package/dist/features/seller/schemas/order-forms.d.ts +61 -4
  321. package/dist/features/seller/schemas/order-forms.js +41 -8
  322. package/dist/features/shipments/schemas/firestore.d.ts +25 -0
  323. package/dist/features/shipments/schemas/validation.d.ts +4 -4
  324. package/dist/features/shipping-boxes/repository/shipping-boxes.repository.d.ts +82 -0
  325. package/dist/features/shipping-boxes/repository/shipping-boxes.repository.js +145 -0
  326. package/dist/features/shipping-boxes/schemas/firestore.d.ts +80 -0
  327. package/dist/features/shipping-boxes/schemas/firestore.js +53 -0
  328. package/dist/features/store-extensions/schemas/report-create-form.d.ts +2 -2
  329. package/dist/features/store-extensions/schemas/shipping-config-form.d.ts +2 -2
  330. package/dist/features/stores/components/StoreOrdersGuideView.js +6 -1
  331. package/dist/features/stores/repository/store.repository.d.ts +18 -0
  332. package/dist/features/stores/repository/store.repository.js +27 -1
  333. package/dist/features/stores/schemas/firestore.d.ts +112 -0
  334. package/dist/features/stores/schemas/firestore.js +20 -0
  335. package/dist/features/stores/schemas/index.d.ts +6 -6
  336. package/dist/features/stores/types/index.d.ts +19 -0
  337. package/dist/features/support/repository/support.repository.js +72 -6
  338. package/dist/features/support/schemas/firestore.d.ts +17 -0
  339. package/dist/features/support/schemas/index.d.ts +8 -8
  340. package/dist/features/wishlist/hooks/useWishlistWithGuest.d.ts +1 -1
  341. package/dist/index.d.ts +11 -1
  342. package/dist/index.js +33 -1
  343. package/dist/next/routing/route-map.d.ts +112 -0
  344. package/dist/next/routing/route-map.js +63 -0
  345. package/dist/providers/shipping-shiprocket/index.d.ts +27 -1
  346. package/dist/providers/shipping-shiprocket/index.js +84 -1
  347. package/dist/react/contexts/SessionContext.d.ts +17 -1
  348. package/dist/schemas/registry.d.ts +69 -34
  349. package/dist/schemas/sieve.d.ts +2 -2
  350. package/dist/security/pii-schemas.d.ts +1 -1
  351. package/dist/security/pii-schemas.js +45 -0
  352. package/dist/server-entry.d.ts +2 -2
  353. package/dist/server-entry.js +8 -1
  354. package/dist/server.d.ts +36 -1
  355. package/dist/server.js +183 -1
  356. package/dist/styles.css +412 -80
  357. package/dist/tailwind-utilities.css +1 -1
  358. package/dist/tokens/themes/default-dark.js +1 -0
  359. package/dist/tokens/themes/default-light.js +1 -0
  360. package/dist/tokens/themes/required.d.ts +1 -1
  361. package/dist/tokens/themes/required.js +1 -0
  362. package/dist/tokens/tokens.css +15 -0
  363. package/dist/ui/components/Button.d.ts +10 -1
  364. package/dist/ui/components/Button.js +25 -3
  365. package/dist/ui/components/Chart.d.ts +63 -0
  366. package/dist/ui/components/Chart.js +169 -0
  367. package/dist/ui/components/Chart.style.css +214 -0
  368. package/dist/ui/components/Disclaimer.d.ts +19 -0
  369. package/dist/ui/components/Disclaimer.js +83 -0
  370. package/dist/ui/components/OverflowRow.js +54 -2
  371. package/dist/ui/components/OverflowRow.style.css +38 -0
  372. package/dist/ui/components/RichTextEditor.js +99 -8
  373. package/dist/ui/components/chart-spec.d.ts +68 -0
  374. package/dist/ui/components/chart-spec.js +140 -0
  375. package/dist/ui/components/index.style.css +1 -0
  376. package/dist/ui/components/surface-tokens.d.ts +1 -1
  377. package/dist/ui/components/surface-tokens.js +9 -0
  378. package/dist/ui/components/tabs-overflow.js +64 -11
  379. package/dist/ui/components/toolbar-collapse.d.ts +13 -0
  380. package/dist/ui/components/toolbar-collapse.js +10 -1
  381. package/dist/ui/index.d.ts +8 -0
  382. package/dist/ui/index.js +9 -0
  383. package/dist/ui/rich-text/RichText.d.ts +10 -1
  384. package/dist/ui/rich-text/RichText.js +33 -2
  385. package/dist/ui/rich-text/RichText.style.css +83 -79
  386. package/dist/ui/rich-text/RichTextRenderer.d.ts +30 -1
  387. package/dist/ui/rich-text/RichTextRenderer.js +34 -2
  388. package/dist/ui/rich-text/chart-blocks.d.ts +62 -0
  389. package/dist/ui/rich-text/chart-blocks.js +87 -0
  390. package/package.json +1 -1
  391. package/scripts/seed-cli.mjs +1834 -1822
@@ -2,7 +2,13 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { formatPhysicalLocation } from "../../../utils/physical-location.js";
4
4
  import { OrderAddonBadges } from "../../orders/components/OrderAddonBadges.js";
5
+ import { OrderProvenanceCard } from "../../orders/components/OrderProvenanceCard.js";
6
+ import { groupOrderItemsByLine } from "../../orders/utils/bundle-grouping.js";
5
7
  import { normalizeError } from "../../../errors/normalize.js";
8
+ import { formatCurrency } from "../../../utils/number.formatter.js";
9
+ // The defining module, not a barrel (Root Cause #18). Maps a server error CODE
10
+ // to user-facing copy; it can never return server text, which is the point.
11
+ import { toUserMessage } from "../../../errors/error-display-map.js";
6
12
  import { Row, SIEVE_OP, sieveFilter } from "@mohasinac/appkit/client";
7
13
  import { sortBy } from "@mohasinac/appkit/client";
8
14
  import React, { useState, useCallback } from "react";
@@ -12,6 +18,7 @@ import { SELLER_ENDPOINTS } from "../../../constants/api-endpoints.js";
12
18
  import { Badge, Button, Div, FilterChipGroup, SideDrawer, Span, Stack, Text, useToast } from "../../../ui/index.js";
13
19
  import { SELLER_ORDER_STATUS_TABS } from "../../admin/constants/filter-tabs.js";
14
20
  import { useOrderScope } from "../../orders/components/OrderScopeTabs.js";
21
+ import { ORDER_LANE_TABS } from "../../orders/constants/order-lane-tabs.js";
15
22
  import { OrderStatusValues } from "../../orders/schemas/firestore.js";
16
23
  import { isManualPaymentMethod } from "../../orders/constants/payment-window.js";
17
24
  import { ACTIONS } from "../../../_internal/shared/actions/action-registry.js";
@@ -21,6 +28,7 @@ import { SectionForm, useSectionFormNav, buildSectionsFromSchema, visibleValues,
21
28
  import { useFormShellState, FormShellContext } from "../../../ui/forms/index.js";
22
29
  import { applyZodIssues } from "../../../ui/forms/apply-zod-issues.js";
23
30
  import { FormErrorSummary } from "../../../ui/forms/FormErrorSummary.js";
31
+ import { DispatchForm } from "./DispatchForm.js";
24
32
  import { PhysicalLocationModal } from "./PhysicalLocationModal.js";
25
33
  import { ROUTES } from "../../../constants/index.js";
26
34
  import { toRecordArray, toCurrency, toStringValue } from "../hooks/useSellerListingData.js";
@@ -31,6 +39,13 @@ import { MediaImage } from "../../media/MediaImage.js";
31
39
  const __O = {
32
40
  yAuto: "overflow-y-auto",
33
41
  };
42
+ /*
43
+ * The hairline that separates each panel section inside the order drawer.
44
+ * Named because the drawer gained its fourth section with D55's balance
45
+ * collector, and four copies of one border declaration is four places a
46
+ * future token rename has to find.
47
+ */
48
+ const SECTION_DIVIDER = "border-t border-[var(--appkit-color-border)]";
34
49
  const DEFAULT_SORT = "-createdAt";
35
50
  const SORT_OPTIONS = [
36
51
  { value: sortBy("createdAt", "DESC"), label: "Newest" },
@@ -60,6 +75,14 @@ const UPDATE_STATUS_OPTIONS = [
60
75
  { value: "delivered", label: "Delivered" },
61
76
  { value: "cancelled", label: "Cancelled" },
62
77
  ];
78
+ /**
79
+ * One item row. Extracted verbatim when grouping landed so the single and
80
+ * grouped paths cannot render differently — two copies of this markup is how
81
+ * the field-name bug below would come back on one path only.
82
+ */
83
+ function sellerOrderItemRow(item, key) {
84
+ return (_jsxs(Row, { paddingY: "y-xs-tall", padding: "x-sm", align: "center", justify: "between", gap: "3", children: [_jsxs(Row, { align: "center", gap: "sm", className: "min-w-0", children: [_jsx(Div, { className: "h-10 w-10 shrink-0", rounded: "md", overflow: "hidden", children: _jsx(MediaImage, { src: item.image, alt: item.title ?? "Order item", size: "thumbnail" }) }), _jsxs(Div, { className: "min-w-0", children: [_jsx(Text, { size: "sm", className: "truncate", weight: "medium", children: item.productTitle ?? item.title ?? item.productId ?? "Item" }), _jsxs(Text, { size: "xs", className: "text-[var(--appkit-color-text-muted)]", children: ["Qty: ", item.quantity ?? 1] })] })] }), _jsx(Text, { size: "sm", className: "shrink-0", weight: "medium", children: toCurrency(item.totalPrice ?? item.unitPrice ?? item.price ?? 0) })] }, key));
85
+ }
63
86
  /**
64
87
  * Manual-payment state for the seller's read-only badge. Derived from the same
65
88
  * two fields the admin queue uses (`paymentProofUrl` + `paymentReviewOutcome`)
@@ -82,6 +105,69 @@ const EMI_INSTALLMENT_BADGE_VARIANT = {
82
105
  pending: "warning",
83
106
  overdue: "danger",
84
107
  };
108
+ /**
109
+ * D55 — the seller's half of the pre-order balance.
110
+ *
111
+ * ## 🛑 Opening is an EVENT, and the control has to say so
112
+ *
113
+ * The balance has existed on the order since checkout. What the seller is
114
+ * declaring here is that the GOODS HAVE ARRIVED — a pre-order's premise is
115
+ * that the item does not exist yet, so asking for the balance before then is
116
+ * asking a buyer to fund inventory. The button's label and its blurb both
117
+ * name that, rather than saying "request payment", which would read as a
118
+ * nudge the seller could send at any time.
119
+ *
120
+ * ## Why no Cancel and no confirm dialog
121
+ *
122
+ * Opening takes money NOWHERE and reverses by simply not chasing it — the
123
+ * worst case is a buyer told a week early. A confirmation step on a
124
+ * non-destructive, idempotent action is the dialog people learn to click
125
+ * through, which is what makes the ones on real deletions worthless.
126
+ *
127
+ * ## The states are the seller's, not the buyer's
128
+ *
129
+ * Once opened the seller cannot act again, so every later state is read-only
130
+ * here: "with the buyer", "proof submitted, we are checking it", "paid". The
131
+ * verification is staff-only and deliberately NOT offered — a seller
132
+ * approving payment to themselves is not a review.
133
+ */
134
+ function SellerBalanceBlock({ orderId, apiBase, balance, balanceDue, currency, onOpened, }) {
135
+ const [opening, setOpening] = React.useState(false);
136
+ const [error, setError] = React.useState(null);
137
+ if (balance) {
138
+ const label = balance.status === "paid"
139
+ ? "Balance paid"
140
+ : balance.status === "submitted"
141
+ ? "Balance proof under review"
142
+ : balance.status === "rejected"
143
+ ? "Balance proof rejected — the buyer has been asked to resend"
144
+ : "Balance open — awaiting the buyer";
145
+ return (_jsxs(Div, { children: [_jsx(Text, { size: "sm", weight: "semibold", color: "primary", children: "Pre-order balance" }), _jsxs(Text, { className: "mt-1", color: "muted", size: "xs", children: [formatCurrency(balance.amount, currency), " \u2014 ", label, balance.transactionId ? ` · Ref ${balance.transactionId}` : ""] })] }));
146
+ }
147
+ const handleOpen = async () => {
148
+ setOpening(true);
149
+ setError(null);
150
+ try {
151
+ const res = await fetch(`${apiBase}/${orderId}/open-balance`, {
152
+ method: "POST",
153
+ credentials: "include",
154
+ });
155
+ if (!res.ok) {
156
+ setError("Could not open the balance. Try again, or contact support if it persists.");
157
+ return;
158
+ }
159
+ onOpened();
160
+ }
161
+ catch (err) {
162
+ void normalizeError(err);
163
+ setError("Could not reach the server. Check your connection and try again.");
164
+ }
165
+ finally {
166
+ setOpening(false);
167
+ }
168
+ };
169
+ return (_jsxs(Div, { children: [_jsx(Text, { size: "sm", weight: "semibold", color: "primary", children: "Pre-order balance" }), _jsxs(Text, { className: "mt-1", color: "muted", size: "xs", children: [formatCurrency(balanceDue, currency), " is still owed on this order. Open it once the stock is physically with you \u2014 the buyer is notified and gets a week to pay, and the parcel ships when it clears."] }), _jsx(Row, { className: "mt-2", gap: "3", children: _jsx(Button, { variant: "primary", size: "sm", disabled: opening, onClick: handleOpen, children: opening ? "Opening…" : "Stock has arrived — open balance" }) }), error && (_jsx(Div, { textSize: "xs", className: "mt-2 border border-error/20", color: "error", surface: "danger-surface", padding: "inlineSm", rounded: "lg", children: error }))] }));
170
+ }
85
171
  /**
86
172
  * Fetches + renders one order's full detail content (items, address,
87
173
  * payment, EMI, status/tracking update form). Shared by the seller orders
@@ -198,8 +284,33 @@ export function SellerOrderDetailPanel({ orderId, apiBase, onClose, }) {
198
284
  body: JSON.stringify(payload),
199
285
  });
200
286
  if (!res.ok) {
201
- const d = await res.json().catch(() => ({}));
202
- throw new Error(d?.error ?? "Failed to update order");
287
+ const d = (await res.json().catch(() => ({})));
288
+ /*
289
+ * 🛑 FIELD ERRORS GO ON THE FIELD. The server already sends them.
290
+ *
291
+ * `mapToHttpError` answers a rejected body with
292
+ * `{ status: 400, code: VALIDATION_FAILED, message: "Validation
293
+ * failed", issues }` — the per-field detail is ON THE WIRE. This
294
+ * handler used to throw `d.error` and render it in the banner below,
295
+ * so the seller saw a bare "Validation failed" with nothing marked and
296
+ * no way to tell WHICH field was wrong. Rule #9 §6.
297
+ *
298
+ * `applyZodIssues` keys by the full dotted path, so a nested field
299
+ * lands on itself rather than collapsing onto `issue.path[0]`.
300
+ */
301
+ if (Array.isArray(d.issues) && d.issues.length > 0) {
302
+ applyZodIssues(d.issues, form.setFieldError);
303
+ return;
304
+ }
305
+ /*
306
+ * 🛑 NEVER the server's own message, and this is not hypothetical.
307
+ * `d.error` is server text; rendering it is how a Node
308
+ * `MODULE_NOT_FOUND` with a `/var/task/.next/...` require stack was
309
+ * once shown inside a buyer's "Place your bid" modal (Root Cause #86).
310
+ * `toUserMessage` resolves through `errors.codes.*`, terminates at
311
+ * UNKNOWN, and cannot return server internals.
312
+ */
313
+ throw new Error(toUserMessage(d.code));
203
314
  }
204
315
  const updated = await res.json();
205
316
  const next = (updated?.data ?? updated);
@@ -217,8 +328,19 @@ export function SellerOrderDetailPanel({ orderId, apiBase, onClose, }) {
217
328
  });
218
329
  }
219
330
  catch (err) {
220
- void normalizeError(err);
221
- setSaveError(err.message);
331
+ /*
332
+ * `normalizeError`'s RESULT, not an `as Error` cast. The cast asserted a
333
+ * shape nothing checked, and the only reason it happened to work is that
334
+ * every throw above is one we construct — a rejected promise from `fetch`
335
+ * or a JSON parse failure is not an `Error` by that assertion's logic,
336
+ * it just happens to be one at runtime.
337
+ *
338
+ * What reaches the banner is now bounded: either `toUserMessage(code)`
339
+ * from the throw above (mapped copy, never server text) or a browser-level
340
+ * network message. Field-level problems never get here at all — they were
341
+ * routed to the fields by `applyZodIssues`.
342
+ */
343
+ setSaveError(normalizeError(err).message);
222
344
  }
223
345
  finally {
224
346
  setSaving(false);
@@ -249,21 +371,41 @@ export function SellerOrderDetailPanel({ orderId, apiBase, onClose, }) {
249
371
  const addrLine = typeof rawAddr === "string" && rawAddr.trim()
250
372
  ? rawAddr.trim()
251
373
  : [addr.addressLine1, addr.city, addr.state, addr.pincode].filter(Boolean).join(", ");
252
- return (_jsxs(_Fragment, { children: [loading && (_jsx(Row, { align: "center", justify: "center", padding: "y-4xl", children: _jsx(Div, { className: "h-6 w-6 animate-spin border-2 border-[var(--appkit-color-primary)] border-t-transparent", rounded: "full" }) })), fetchError && (_jsx(Div, { textSize: "sm", className: "mx-4 mt-4 border border-error/20", color: "error", surface: "danger-surface", padding: "inline", rounded: "lg", children: fetchError })), order && !loading && (_jsxs(Stack, { gap: "none", children: [_jsxs(Stack, { className: `flex-1 ${__O.yAuto}`, gap: "5", padding: "md", children: [_jsxs(Row, { align: "center", justify: "between", children: [_jsx(Badge, { variant: STATUS_BADGE_VARIANT[order.status ?? ""] ?? "default", children: order.status ?? "Unknown" }), _jsx(Text, { size: "sm", className: "text-[var(--appkit-color-text-muted)]", children: toRelativeDate(order.createdAt) })] }), (order.items ?? []).length > 0 && (_jsxs(Div, { children: [_jsx(Text, { size: "sm", className: "text-[var(--appkit-color-text)] mb-2", weight: "semibold", children: "Items" }), _jsx(Div, { className: "divide-y divide-[var(--appkit-color-border)] divide-[var(--appkit-color-border)] border border-[var(--appkit-color-border)]", rounded: "lg", children: (order.items ?? []).map((item, i) => (_jsxs(Row, { paddingY: "y-xs-tall", padding: "x-sm", align: "center", justify: "between", gap: "3", children: [_jsxs(Row, { align: "center", gap: "sm", className: "min-w-0", children: [_jsx(Div, { className: "h-10 w-10 shrink-0", rounded: "md", overflow: "hidden", children: _jsx(MediaImage, { src: item.image, alt: item.title ?? "Order item", size: "thumbnail" }) }), _jsxs(Div, { className: "min-w-0", children: [_jsx(Text, { size: "sm", className: "truncate", weight: "medium", children: item.productTitle ?? item.title ?? item.productId ?? "Item" }), _jsxs(Text, { size: "xs", className: "text-[var(--appkit-color-text-muted)]", children: ["Qty: ", item.quantity ?? 1] })] })] }), _jsx(Text, { size: "sm", className: "shrink-0", weight: "medium", children: toCurrency(item.totalPrice ?? item.unitPrice ?? item.price ?? 0) })] }, i))) })] })), _jsx(OrderAddonBadges, { order: order, variant: "detail" }), order.giftWrapAddon && (_jsxs(Div, { className: "border border-[var(--appkit-color-primary-200)] dark:border-[var(--appkit-color-primary-800)]", surface: "subtle", padding: "inline", rounded: "lg", children: [_jsx(Text, { size: "sm", weight: "semibold", children: "\uD83C\uDF81 Gift wrap requested" }), order.giftWrapMessage && (_jsxs(Text, { size: "sm", className: "mt-1 text-[var(--appkit-color-text-muted)]", children: ["\u201C", order.giftWrapMessage, "\u201D"] }))] })), _jsxs(Row, { surface: "muted", padding: "inline", align: "center", justify: "between", rounded: "lg", children: [_jsx(Text, { size: "sm", weight: "semibold", children: "Total" }), _jsx(Text, { size: "sm", className: "text-[var(--appkit-color-primary)]", weight: "bold", children: toCurrency(order.totalAmount ?? order.totalPrice ?? 0) })] }), addrLine && (_jsxs(Div, { children: [_jsx(Text, { size: "sm", className: "mb-1", weight: "semibold", children: "Shipping address" }), _jsx(Text, { size: "sm", className: "text-[var(--appkit-color-text-muted)]", children: [String(addr.fullName ?? ""), addrLine].filter(Boolean).join(" · ") })] })), order.paymentMethod && (_jsxs(Div, { children: [_jsxs(Row, { align: "center", justify: "between", className: "mb-1", gap: "3", children: [_jsx(Text, { size: "sm", weight: "semibold", children: "Payment" }), isManualPaymentMethod(order.paymentMethod) && (_jsx(Badge, { variant: sellerPaymentBadge(order).variant, children: sellerPaymentBadge(order).label }))] }), _jsx(Text, { size: "sm", className: "text-[var(--appkit-color-text-muted)]", transform: "capitalize", children: order.paymentMethod }), isManualPaymentMethod(order.paymentMethod) && order.paymentTransactionId && (_jsxs(Text, { size: "xs", color: "muted", className: "mt-1", children: ["UTR: ", order.paymentTransactionId] }))] })), order.emiEnabled && (_jsxs(Div, { className: "border-t border-[var(--appkit-color-border)]", padding: "t-md", children: [_jsxs(Row, { align: "center", justify: "between", className: "mb-2", children: [_jsxs(Text, { size: "sm", weight: "semibold", children: ["EMI plan ", order.emiTenureMonths ? `· ${order.emiTenureMonths} months` : ""] }), _jsx(Badge, { variant: order.emiComplete ? "success" : "warning", children: order.emiComplete ? "Fully paid" : "In progress" })] }), _jsxs(Row, { align: "center", justify: "between", className: "mb-2", children: [_jsx(Text, { size: "xs", color: "muted", children: "Token collected" }), _jsx(Text, { size: "xs", weight: "medium", children: toCurrency(order.emiTokenAmount ?? 0) })] }), _jsxs(Row, { align: "center", justify: "between", className: "mb-3", children: [_jsx(Text, { size: "xs", color: "muted", children: "Remaining balance" }), _jsx(Text, { size: "xs", weight: "medium", children: toCurrency(order.emiRemainingBalance ?? 0) })] }), _jsx(Div, { className: "divide-y divide-[var(--appkit-color-border)] border border-[var(--appkit-color-border)]", rounded: "lg", children: (order.emiInstallments ?? []).map((inst) => (_jsxs(Row, { paddingY: "y-xs-tall", padding: "x-sm", align: "center", justify: "between", gap: "3", children: [_jsxs(Div, { className: "min-w-0", children: [_jsxs(Text, { size: "sm", weight: "medium", children: ["Installment ", inst.index, " \u00B7 ", toCurrency(inst.amount)] }), _jsx(Text, { size: "xs", color: "muted", children: inst.status === "paid" && inst.paidAt
253
- ? `Paid ${toRelativeDate(inst.paidAt)}`
254
- : inst.dueDate
255
- ? `Due ${toRelativeDate(inst.dueDate)}`
256
- : "" })] }), _jsxs(Row, { align: "center", gap: "sm", className: "shrink-0", children: [_jsx(Badge, { variant: EMI_INSTALLMENT_BADGE_VARIANT[inst.status] ?? "default", children: inst.status }), inst.status !== "paid" && (_jsx(Button, { action: ACTIONS.STORE["mark-installment-paid"], size: "sm", variant: "outline", isLoading: markingPaidIndex === inst.index, disabled: markingPaidIndex !== null, onClick: () => handleMarkInstallmentPaid(inst.index), children: "Mark paid" }))] })] }, inst.index))) }), emiError && (_jsx(Div, { textSize: "xs", className: "mt-2 border border-error/20", color: "error", surface: "danger-surface", padding: "inlineSm", rounded: "lg", children: emiError }))] })), _jsxs(Stack, { className: "border-t border-[var(--appkit-color-border)]", padding: "t-md", gap: "3", children: [_jsxs(FormShellContext.Provider, { value: form.shellCtx, children: [_jsx(FormErrorSummary, {}), _jsx(SectionForm, { sections: sections, values: draft, onChange: (partial) => setDraft((d) => ({ ...d, ...partial })), onSubmit: () => {
257
- // SectionForm scrolls to the first erroring section and then
258
- // submits regardless, so the guard lives here.
259
- form.clearErrors();
260
- const parsed = sellerOrderUpdateSchema.safeParse(visibleValues(sellerOrderUpdateSchema, draft));
261
- if (!parsed.success) {
262
- applyZodIssues(parsed.error.issues, form.setFieldError);
263
- return;
264
- }
265
- void handleSave();
266
- }, onValidationChange: () => form.validate(draft), schema: sellerOrderUpdateSchema, openIds: nav.openIds, onOpenChange: nav.setOpenIds, submitLabel: "Save", cancelLabel: "Close", onCancel: onClose, isLoading: saving })] }), saveError && (_jsx(Div, { textSize: "xs", className: "border border-error/20", color: "error", surface: "danger-surface", padding: "inlineSm", rounded: "lg", children: saveError }))] })] }), _jsxs(Row, { border: "top", paddingY: "y-sm-tall", padding: "x-md", align: "center", justify: "end", gap: "3", children: [_jsx(Button, { variant: "outline", onClick: onClose, disabled: saving, children: "Close" }), _jsx(Button, { onClick: handleSave, isLoading: saving, disabled: saving, children: "Save" })] })] }))] }));
374
+ return (_jsxs(_Fragment, { children: [loading && (_jsx(Row, { align: "center", justify: "center", padding: "y-4xl", children: _jsx(Div, { className: "h-6 w-6 animate-spin border-2 border-[var(--appkit-color-primary)] border-t-transparent", rounded: "full" }) })), fetchError && (_jsx(Div, { textSize: "sm", className: "mx-4 mt-4 border border-error/20", color: "error", surface: "danger-surface", padding: "inline", rounded: "lg", children: fetchError })), order && !loading && (_jsx(Stack, { gap: "none", children: _jsxs(Stack, { className: `flex-1 ${__O.yAuto}`, gap: "5", padding: "md", children: [_jsxs(Row, { align: "center", justify: "between", children: [_jsx(Badge, { variant: STATUS_BADGE_VARIANT[order.status ?? ""] ?? "default", children: order.status ?? "Unknown" }), _jsx(Text, { size: "sm", className: "text-[var(--appkit-color-text-muted)]", children: toRelativeDate(order.createdAt) })] }), _jsx(OrderProvenanceCard, { sourceContext: order.sourceContext, currency: order.currency }), (order.items ?? []).length > 0 && (_jsxs(Div, { children: [_jsx(Text, { size: "sm", className: "text-[var(--appkit-color-text)] mb-2", weight: "semibold", children: "Items" }), _jsx(Div, { className: "divide-y divide-[var(--appkit-color-border)] divide-[var(--appkit-color-border)] border border-[var(--appkit-color-border)]", rounded: "lg", children: groupOrderItemsByLine(order.items ?? []).map((group, gi) => group.kind === "single" ? (sellerOrderItemRow(group.item, `s-${group.index}`)) : (_jsxs(Div, { children: [_jsxs(Row, { paddingY: "y-xs", padding: "x-sm", align: "center", gap: "sm", surface: "muted", children: [_jsx(Text, { size: "xs", weight: "semibold", children: group.groupTitle ?? "Grouped purchase" }), _jsx(Text, { size: "xs", className: "text-[var(--appkit-color-text-muted)]", children: `${group.memberCount} ${group.memberCount === 1 ? "item" : "items"} · one line` })] }), _jsx(Div, { paddingX: "l-md", children: group.items.map(({ item, index }) => sellerOrderItemRow(item, `m-${index}`)) })] }, `g-${gi}`))) })] })), _jsx(OrderAddonBadges, { order: order, variant: "detail" }), order.giftWrapAddon && (_jsxs(Div, { className: "border border-[var(--appkit-color-primary-200)] dark:border-[var(--appkit-color-primary-800)]", surface: "subtle", padding: "inline", rounded: "lg", children: [_jsx(Text, { size: "sm", weight: "semibold", children: "\uD83C\uDF81 Gift wrap requested" }), order.giftWrapMessage && (_jsxs(Text, { size: "sm", className: "mt-1 text-[var(--appkit-color-text-muted)]", children: ["\u201C", order.giftWrapMessage, "\u201D"] }))] })), _jsxs(Row, { surface: "muted", padding: "inline", align: "center", justify: "between", rounded: "lg", children: [_jsx(Text, { size: "sm", weight: "semibold", children: "Total" }), _jsx(Text, { size: "sm", className: "text-[var(--appkit-color-primary)]", weight: "bold", children: toCurrency(order.totalAmount ?? order.totalPrice ?? 0) })] }), addrLine && (_jsxs(Div, { children: [_jsx(Text, { size: "sm", className: "mb-1", weight: "semibold", children: "Shipping address" }), _jsx(Text, { size: "sm", className: "text-[var(--appkit-color-text-muted)]", children: [String(addr.fullName ?? ""), addrLine].filter(Boolean).join(" · ") })] })), order.paymentMethod && (_jsxs(Div, { children: [_jsxs(Row, { align: "center", justify: "between", className: "mb-1", gap: "3", children: [_jsx(Text, { size: "sm", weight: "semibold", children: "Payment" }), isManualPaymentMethod(order.paymentMethod) && (_jsx(Badge, { variant: sellerPaymentBadge(order).variant, children: sellerPaymentBadge(order).label }))] }), _jsx(Text, { size: "sm", className: "text-[var(--appkit-color-text-muted)]", transform: "capitalize", children: order.paymentMethod }), isManualPaymentMethod(order.paymentMethod) && order.paymentTransactionId && (_jsxs(Text, { size: "xs", color: "muted", className: "mt-1", children: ["UTR: ", order.paymentTransactionId] }))] })), order.emiEnabled && (_jsxs(Div, { className: SECTION_DIVIDER, padding: "t-md", children: [_jsxs(Row, { align: "center", justify: "between", className: "mb-2", children: [_jsxs(Text, { size: "sm", weight: "semibold", children: ["EMI plan ", order.emiTenureMonths ? `· ${order.emiTenureMonths} months` : ""] }), _jsx(Badge, { variant: order.emiComplete ? "success" : "warning", children: order.emiComplete ? "Fully paid" : "In progress" })] }), _jsxs(Row, { align: "center", justify: "between", className: "mb-2", children: [_jsx(Text, { size: "xs", color: "muted", children: "Token collected" }), _jsx(Text, { size: "xs", weight: "medium", children: toCurrency(order.emiTokenAmount ?? 0) })] }), _jsxs(Row, { align: "center", justify: "between", className: "mb-3", children: [_jsx(Text, { size: "xs", color: "muted", children: "Remaining balance" }), _jsx(Text, { size: "xs", weight: "medium", children: toCurrency(order.emiRemainingBalance ?? 0) })] }), _jsx(Div, { className: "divide-y divide-[var(--appkit-color-border)] border border-[var(--appkit-color-border)]", rounded: "lg", children: (order.emiInstallments ?? []).map((inst) => (_jsxs(Row, { paddingY: "y-xs-tall", padding: "x-sm", align: "center", justify: "between", gap: "3", children: [_jsxs(Div, { className: "min-w-0", children: [_jsxs(Text, { size: "sm", weight: "medium", children: ["Installment ", inst.index, " \u00B7 ", toCurrency(inst.amount)] }), _jsx(Text, { size: "xs", color: "muted", children: inst.status === "paid" && inst.paidAt
375
+ ? `Paid ${toRelativeDate(inst.paidAt)}`
376
+ : inst.dueDate
377
+ ? `Due ${toRelativeDate(inst.dueDate)}`
378
+ : "" })] }), _jsxs(Row, { align: "center", gap: "sm", className: "shrink-0", children: [_jsx(Badge, { variant: EMI_INSTALLMENT_BADGE_VARIANT[inst.status] ?? "default", children: inst.status }), inst.status !== "paid" && (_jsx(Button, { action: ACTIONS.STORE["mark-installment-paid"], size: "sm", variant: "outline", isLoading: markingPaidIndex === inst.index, disabled: markingPaidIndex !== null, onClick: () => handleMarkInstallmentPaid(inst.index), children: "Mark paid" }))] })] }, inst.index))) }), emiError && (_jsx(Div, { textSize: "xs", className: "mt-2 border border-error/20", color: "error", surface: "danger-surface", padding: "inlineSm", rounded: "lg", children: emiError }))] })), order.sourceContext?.path === "pre-order" &&
379
+ order.sourceContext.balanceDue > 0 && (_jsx(Stack, { className: SECTION_DIVIDER, padding: "t-md", gap: "3", children: _jsx(SellerBalanceBlock, { orderId: orderId, apiBase: apiBase, balance: order.balance, balanceDue: order.sourceContext.balanceDue, currency: order.currency, onOpened: () => {
380
+ showToast("Balance opened — the buyer has been notified", "success");
381
+ void fetch(`${apiBase}/${orderId}`)
382
+ .then((r) => r.json())
383
+ .then((json) => setOrder((json?.data ?? json)))
384
+ .catch((err) => void normalizeError(err));
385
+ } }) })), _jsx(Stack, { className: SECTION_DIVIDER, padding: "t-md", gap: "3", children: _jsx(DispatchForm, { orderId: orderId, trackingNumber: order.trackingNumber, platformBooked: order.platformBookedShipment, onDispatched: () => {
386
+ showToast("Dispatch recorded", "success");
387
+ /*
388
+ * Re-read rather than patching local state: the platform
389
+ * branch's tracking id is produced by the CARRIER, so there
390
+ * is no value here to optimistically write. On that branch
391
+ * the job is still running, so this first re-read correctly
392
+ * shows no tracking number yet.
393
+ */
394
+ void fetch(`${apiBase}/${orderId}`)
395
+ .then((r) => r.json())
396
+ .then((json) => setOrder((json?.data ?? json)))
397
+ .catch((err) => void normalizeError(err));
398
+ } }) }), _jsxs(Stack, { className: SECTION_DIVIDER, padding: "t-md", gap: "3", children: [_jsxs(FormShellContext.Provider, { value: form.shellCtx, children: [_jsx(FormErrorSummary, {}), _jsx(SectionForm, { sections: sections, values: draft, onChange: (partial) => setDraft((d) => ({ ...d, ...partial })), onSubmit: () => {
399
+ // SectionForm scrolls to the first erroring section and then
400
+ // submits regardless, so the guard lives here.
401
+ form.clearErrors();
402
+ const parsed = sellerOrderUpdateSchema.safeParse(visibleValues(sellerOrderUpdateSchema, draft));
403
+ if (!parsed.success) {
404
+ applyZodIssues(parsed.error.issues, form.setFieldError);
405
+ return;
406
+ }
407
+ void handleSave();
408
+ }, onValidationChange: () => form.validate(draft), schema: sellerOrderUpdateSchema, openIds: nav.openIds, onOpenChange: nav.setOpenIds, submitLabel: "Save", cancelLabel: "Close", onCancel: onClose, isLoading: saving })] }), saveError && (_jsx(Div, { textSize: "xs", className: "border border-error/20", color: "error", surface: "danger-surface", padding: "inlineSm", rounded: "lg", children: saveError }))] })] }) }))] }));
267
409
  }
268
410
  function OrderDetailDrawer({ orderId, apiBase, onClose, }) {
269
411
  return (_jsx(SideDrawer, { isOpen: true, title: `Order ${orderId}`, onClose: onClose, children: _jsx(SellerOrderDetailPanel, { orderId: orderId, apiBase: apiBase, onClose: onClose }) }));
@@ -343,9 +485,7 @@ export function SellerOrdersView({ orderDetailApiBase = SELLER_ENDPOINTS.ORDERS,
343
485
  {
344
486
  key: "primary",
345
487
  header: "Order",
346
- render: (row) => (_jsxs(Row, { gap: "sm", align: "center", className: "min-w-0", children: [_jsx(Div, { className: "h-10 w-10 shrink-0", rounded: "md", overflow: "hidden", children: _jsx(MediaImage, { src: row.itemImage, alt: row.itemTitle ?? "Order item", size: "thumbnail" }) }), _jsxs(Stack, { gap: "none", className: "min-w-0", children: [_jsx(Text, { className: "truncate", size: "sm", weight: "semibold", children: row.itemTitle
347
- ? `${row.itemTitle}${row.itemCount > 1 ? ` +${row.itemCount - 1} more` : ""}`
348
- : row.primary }), _jsxs(Text, { size: "xs", color: "muted", children: [row.buyerName, " \u00B7 ", row.itemCount, " item", row.itemCount !== 1 ? "s" : ""] })] })] })),
488
+ render: (row) => (_jsxs(Row, { gap: "sm", align: "center", className: "min-w-0", children: [_jsx(Div, { className: "h-10 w-10 shrink-0", rounded: "md", overflow: "hidden", children: _jsx(MediaImage, { src: row.itemImage, alt: row.itemTitle ?? "Order item", size: "thumbnail" }) }), _jsxs(Stack, { gap: "none", className: "min-w-0", children: [_jsx(Text, { className: "truncate", size: "sm", weight: "semibold", children: row.primary }), _jsxs(Text, { size: "xs", color: "muted", children: [row.buyerName, " \u00B7 ", row.itemCount, " item", row.itemCount !== 1 ? "s" : ""] })] })] })),
349
489
  },
350
490
  {
351
491
  key: "totalAmount",
@@ -392,7 +532,7 @@ export function SellerOrdersView({ orderDetailApiBase = SELLER_ENDPOINTS.ORDERS,
392
532
  commit: "debounce",
393
533
  },
394
534
  emptyLabel: "No orders yet",
395
- filterKeys: ["status"],
535
+ filterKeys: ["status", "orderType"],
396
536
  defaultSort: DEFAULT_SORT,
397
537
  queryKey: ["seller", "orders", "listing"],
398
538
  endpoint: SELLER_ENDPOINTS.ORDERS,
@@ -425,10 +565,45 @@ export function SellerOrdersView({ orderDetailApiBase = SELLER_ENDPOINTS.ORDERS,
425
565
  * below as `itemTitle`.
426
566
  */
427
567
  primary: (() => {
428
- const title = typeof firstItem.productTitle === "string" ? firstItem.productTitle : "";
568
+ /*
569
+ * Counted in LINES, not item rows, and a grouped line is named by
570
+ * its own title.
571
+ *
572
+ * This was `items[0].productTitle` + `itemsArr.length - 1`, so a
573
+ * four-member bundle read "Dranzer S +3 more" — an arbitrary
574
+ * member, implying four separate purchases. Grouping through the
575
+ * same helper the drawer now uses makes it "Starter Bundle", and a
576
+ * bundle beside one standalone item "+1 more".
577
+ */
578
+ const groups = groupOrderItemsByLine(itemsArr
579
+ .filter((entry) => Boolean(entry) && typeof entry === "object")
580
+ /*
581
+ * Narrowed, not cast: `Record<string, unknown>` does NOT
582
+ * satisfy `OrderItemForLineGrouping` — its `groupSlug` is
583
+ * `unknown`, which is not assignable to `string | undefined`.
584
+ * A cast would compile and then group on whatever junk a bad
585
+ * document carried.
586
+ */
587
+ .map((e) => ({
588
+ productTitle: typeof e.productTitle === "string" ? e.productTitle : undefined,
589
+ groupSlug: typeof e.groupSlug === "string" ? e.groupSlug : undefined,
590
+ groupTitle: typeof e.groupTitle === "string" ? e.groupTitle : undefined,
591
+ bundleCategorySlug: typeof e.bundleCategorySlug === "string" ? e.bundleCategorySlug : undefined,
592
+ bundleProductIds: Array.isArray(e.bundleProductIds)
593
+ ? e.bundleProductIds.filter((v) => typeof v === "string")
594
+ : undefined,
595
+ })));
596
+ const head = groups[0];
597
+ const extra = Math.max(0, groups.length - 1);
598
+ const title = head === undefined
599
+ ? typeof firstItem.productTitle === "string"
600
+ ? firstItem.productTitle
601
+ : ""
602
+ : head.kind === "bundle"
603
+ ? (head.groupTitle ?? "Grouped purchase")
604
+ : (head.item.productTitle ?? "");
429
605
  if (!title)
430
606
  return `Order ${toStringValue(item.id, "-")}`;
431
- const extra = itemsArr.length - 1;
432
607
  return extra > 0 ? `${title} +${extra} more` : title;
433
608
  })(),
434
609
  /*
@@ -456,10 +631,29 @@ export function SellerOrdersView({ orderDetailApiBase = SELLER_ENDPOINTS.ORDERS,
456
631
  // The scope narrows; the status chip drills down inside it. Both are
457
632
  // emitted — an explicit status always wins, since picking "Delivered"
458
633
  // while sitting on Active should show delivered orders, not nothing.
459
- buildFilters: (state) => (state.status && state.status !== "All" ? sieveFilter("status", SIEVE_OP.EQ, state.status) : undefined),
634
+ /*
635
+ * Two independent axes, joined. The lane answers "how was this won", the
636
+ * status answers "where is it now" — a seller asking "which of my auction
637
+ * wins are still unshipped" should not have to choose between them.
638
+ *
639
+ * 🛑 `orderType` is a registered SELLER_SIEVE_FIELD as of this change. It
640
+ * was not, and the failure would have been invisible: `throwExceptions` is
641
+ * false, so an unallowlisted field drops its clause and the chip would have
642
+ * returned the seller's whole order list while looking like it filtered
643
+ * (Root Cause #62). `standard` is stripped from the query server-side and
644
+ * refined in memory — see `/api/store/orders`.
645
+ */
646
+ buildFilters: (state) => [
647
+ state.status && state.status !== "All"
648
+ ? sieveFilter("status", SIEVE_OP.EQ, state.status)
649
+ : null,
650
+ state.orderType ? sieveFilter("orderType", SIEVE_OP.EQ, state.orderType) : null,
651
+ ]
652
+ .filter(Boolean)
653
+ .join(",") || undefined,
460
654
  buildExtraParams: () => orderScope.extraParams,
461
655
  renderAboveContent: orderScope.renderAboveContent,
462
- renderFilterPanel: ({ pendingFilters, setPendingFilters }) => (_jsx(FilterChipGroup, { label: "Status", tabs: STATUS_OPTIONS, value: pendingFilters.status ?? "", onChange: (id) => setPendingFilters((p) => ({ ...p, status: id })) })),
656
+ renderFilterPanel: ({ pendingFilters, setPendingFilters }) => (_jsxs(_Fragment, { children: [_jsx(FilterChipGroup, { label: "Status", tabs: STATUS_OPTIONS, value: pendingFilters.status ?? "", onChange: (id) => setPendingFilters((p) => ({ ...p, status: id })) }), _jsx(FilterChipGroup, { label: "Type", tabs: ORDER_LANE_TABS, value: pendingFilters.orderType ?? "", onChange: (id) => setPendingFilters((p) => ({ ...p, orderType: id })) })] })),
463
657
  buildBulkActions: (selection) => {
464
658
  const handlePrintPackingSlips = () => {
465
659
  const ids = selection.selectedIds.join(",");
@@ -5,6 +5,7 @@ export { SellerListingTypeView, SELLER_LISTING_TYPE_SPECS } from "./SellerListin
5
5
  export type { SellerListingTypeViewProps, SellerListingTypeSpec, SellerListingTypeKey, SellerListingRow } from "./SellerListingTypeView";
6
6
  export type { SellerProductsViewProps } from "./SellerProductsView";
7
7
  export { PrintCenterView } from "./PrintCenterView";
8
+ export { DispatchForm } from "./DispatchForm";
8
9
  export { SellerOrdersView, SellerOrderDetailPanel } from "./SellerOrdersView";
9
10
  export type { SellerOrdersViewProps } from "./SellerOrdersView";
10
11
  export { SellerOffersView } from "./SellerOffersView";
@@ -2,6 +2,7 @@ export { SellerDashboardView } from "./SellerDashboardView.js";
2
2
  export { SellerProductsView } from "./SellerProductsView.js";
3
3
  export { SellerListingTypeView, SELLER_LISTING_TYPE_SPECS } from "./SellerListingTypeView.js";
4
4
  export { PrintCenterView } from "./PrintCenterView.js";
5
+ export { DispatchForm } from "./DispatchForm.js";
5
6
  export { SellerOrdersView, SellerOrderDetailPanel } from "./SellerOrdersView.js";
6
7
  export { SellerOffersView } from "./SellerOffersView.js";
7
8
  export { SellerCouponsView } from "./SellerCouponsView.js";
@@ -1,10 +1,35 @@
1
1
  "use client";
2
2
  import { formatCurrency } from "../../../utils/number.formatter.js";
3
+ // The defining module, not a barrel (Root Cause #18). `hasEncPrefix` is a pure
4
+ // string test with no crypto in its import chain, so it is client-safe.
5
+ import { hasEncPrefix } from "../../../security/pii-mask.js";
3
6
  export function toRecordArray(value) {
4
7
  return Array.isArray(value) ? value.filter(Boolean) : [];
5
8
  }
6
9
  export function toStringValue(value, fallback = "-") {
7
10
  if (typeof value === "string") {
11
+ /*
12
+ * 🛑 Ciphertext is not a display value, and this is the last line of
13
+ * defence rather than the fix.
14
+ *
15
+ * `OrderRepository.mapDoc` deliberately does not decrypt, so any route
16
+ * that forgets `revealOrders`/`maskedOrders` hands this function a stored
17
+ * `enc:v1:…` blob — and it is a `string`, so it rendered verbatim.
18
+ * Measured live in the seller's order list, where the row subtitle read
19
+ * `enc:v1:8plr3ZzKBqejPPti:MCZsrfOidLkSL6EogbxlCzU=:…` where the buyer's
20
+ * name belongs.
21
+ *
22
+ * This is a RECURRING class, not one slip: eight separate files in appkit
23
+ * carry a comment recording the same leak, and one of them had already
24
+ * baked `enc:v1:…` into 383 notification bodies. The route fix is the real
25
+ * repair; this makes the NEXT one degrade to "-" instead of garbage.
26
+ *
27
+ * `hasEncPrefix` rather than `isPiiEncrypted`: its own docstring says this
28
+ * is the check the display masks want, because a settings-encrypted or
29
+ * malformed envelope is exactly as unshowable as a PII one.
30
+ */
31
+ if (hasEncPrefix(value))
32
+ return fallback;
8
33
  return value.trim() || fallback;
9
34
  }
10
35
  if (typeof value === "number" || typeof value === "boolean") {
@@ -247,9 +247,10 @@ class OfferRepository extends BaseRepository {
247
247
  trigger: ctx?.trigger ?? "offerRepository.updateStatus",
248
248
  reason: ctx?.reason,
249
249
  note: ctx?.note,
250
- // buyerName/buyerEmail live on this document. `encryptPiiFields` is a
251
- // flat top-level loop and never descends into arrays, so without this
252
- // they would persist in PLAINTEXT inside statusHistory.
250
+ // buyerName/buyerEmail live on this document. `encryptPiiFields` covers
251
+ // only NAMED paths, and nothing declares them under
252
+ // `statusHistory[].changes` — so without this scrub they persist in
253
+ // PLAINTEXT inside the history.
253
254
  piiFields: OFFER_PII_FIELDS,
254
255
  historyField: OFFER_FIELDS.STATUS_HISTORY,
255
256
  truncatedField: OFFER_FIELDS.STATUS_HISTORY_TRUNCATED,
@@ -5,6 +5,7 @@ import { type GenerateOfferIdInput } from "../../../utils/id-generators";
5
5
  import type { BaseDocument } from "../../../_internal/shared/types/base-document";
6
6
  import type { StatusChangeEntry } from "../../../_internal/shared/history/index";
7
7
  import type { Encrypted, Plaintext } from "../../../security/encrypted";
8
+ import type { OfferCoordination } from "../../../_internal/shared/features/offers/coordination";
8
9
  export type OfferStatus = "pending" | "accepted" | "declined" | "countered" | "expired" | "withdrawn" | "paid";
9
10
  /** Runtime-accessible offer status values — use instead of bare string literals. */
10
11
  export declare const OfferStatusValues: {
@@ -50,6 +51,25 @@ export interface OfferDocument extends BaseDocument {
50
51
  acceptedAt?: Date;
51
52
  checkoutDeadline?: Date;
52
53
  respondedAt?: Date;
54
+ /**
55
+ * Present when this offer is a COORDINATED purchase — several people
56
+ * chipping in on one listing.
57
+ *
58
+ * 🛑 A field on the offer, not a new document and not a new lifecycle.
59
+ * Acceptance produces an ordinary `offer-accepted` order; `unitPriceFor`
60
+ * already honours `lockedPrice`, so tax, payout base, refund ceiling and
61
+ * the invoice all follow with no new money term. See
62
+ * `_internal/shared/features/offers/coordination.ts` for the full list of
63
+ * things this deliberately does NOT add.
64
+ *
65
+ * 🛑 No member NAME is stored in here. `encryptPiiFields` CAN reach into an
66
+ * array (`coordination.members[].name`) — the claim that it cannot was
67
+ * wrong — but it covers only what is NAMED, and the near-miss `"name"`
68
+ * reads as covering it while storing plaintext. Members are uids; names
69
+ * resolve at render time, which removes the field rather than classifying
70
+ * it. See `coordination.ts`.
71
+ */
72
+ coordination?: OfferCoordination;
53
73
  /** Set by `markPaid` once the buyer's order exists — makes "paid" auditable. */
54
74
  paidOrderId?: string;
55
75
  paidAt?: Date;
@@ -93,8 +113,9 @@ export interface OfferDocument extends BaseDocument {
93
113
  /**
94
114
  * Fields whose changes are recorded in an offer's `statusHistory`.
95
115
  *
96
- * Excludes `buyerName`/`buyerEmail` (PII — `encryptPiiFields` never descends
97
- * into arrays, so they would persist in plaintext inside the history),
116
+ * Excludes `buyerName`/`buyerEmail` (PII — nothing declares them under
117
+ * `statusHistory[].changes`, and `encryptPiiFields` covers only NAMED paths,
118
+ * so they would persist in plaintext inside the history),
98
119
  * `buyerNote`/`sellerNote` (they ride in the entry's `note`), and
99
120
  * `updatedAt`/`respondedAt` (noise that would burn the FIFO cap).
100
121
  */
@@ -15,8 +15,9 @@ export const OfferStatusValues = {
15
15
  /**
16
16
  * Fields whose changes are recorded in an offer's `statusHistory`.
17
17
  *
18
- * Excludes `buyerName`/`buyerEmail` (PII — `encryptPiiFields` never descends
19
- * into arrays, so they would persist in plaintext inside the history),
18
+ * Excludes `buyerName`/`buyerEmail` (PII — nothing declares them under
19
+ * `statusHistory[].changes`, and `encryptPiiFields` covers only NAMED paths,
20
+ * so they would persist in plaintext inside the history),
20
21
  * `buyerNote`/`sellerNote` (they ride in the entry's `note`), and
21
22
  * `updatedAt`/`respondedAt` (noise that would burn the FIFO cap).
22
23
  */
@@ -72,13 +72,13 @@ export declare const sellerStoreSchema: z.ZodObject<{
72
72
  totalReviews: z.ZodNumber;
73
73
  averageRating: z.ZodOptional<z.ZodNumber>;
74
74
  }, "strip", z.ZodTypeAny, {
75
- itemsSold: number;
76
75
  totalProducts: number;
76
+ itemsSold: number;
77
77
  totalReviews: number;
78
78
  averageRating?: number | undefined;
79
79
  }, {
80
- itemsSold: number;
81
80
  totalProducts: number;
81
+ itemsSold: number;
82
82
  totalReviews: number;
83
83
  averageRating?: number | undefined;
84
84
  }>>;
@@ -96,8 +96,8 @@ export declare const sellerStoreSchema: z.ZodObject<{
96
96
  location?: string | undefined;
97
97
  returnPolicy?: string | undefined;
98
98
  stats?: {
99
- itemsSold: number;
100
99
  totalProducts: number;
100
+ itemsSold: number;
101
101
  totalReviews: number;
102
102
  averageRating?: number | undefined;
103
103
  } | undefined;
@@ -128,8 +128,8 @@ export declare const sellerStoreSchema: z.ZodObject<{
128
128
  location?: string | undefined;
129
129
  returnPolicy?: string | undefined;
130
130
  stats?: {
131
- itemsSold: number;
132
131
  totalProducts: number;
132
+ itemsSold: number;
133
133
  totalReviews: number;
134
134
  averageRating?: number | undefined;
135
135
  } | undefined;
@@ -32,10 +32,30 @@ export declare const sellerOrderUpdateSchema: z.ZodEffects<z.ZodObject<{
32
32
  }>;
33
33
  export type SellerOrderUpdateValues = z.infer<typeof sellerOrderUpdateSchema>;
34
34
  /**
35
- * Manual shipment entry. `method` is a literal rather than an enum because
36
- * `ManualShippingProvider` is the only provider — see § "Provider Resolution".
35
+ * Shipment entry — manual, or booked through the platform.
36
+ *
37
+ * 🛑 **`method` was `z.literal("custom")`, and that literal WAS bug 0e.**
38
+ *
39
+ * Its comment said *"a literal rather than an enum because
40
+ * `ManualShippingProvider` is the only provider"* — no longer true:
41
+ * `providers/shipping-shiprocket/` is 570 lines with all six methods, and
42
+ * `providers.config.ts` already resolves it from
43
+ * `siteSettings.shipping.provider`. The seller simply could not EXPRESS
44
+ * "book this through us", so there was no option to offer, and
45
+ * `platformBookedShipment` — which `order-math.ts` gates reimbursement on —
46
+ * had zero writers.
47
+ *
48
+ * A DISCRIMINATED UNION rather than an enum plus optional fields, because
49
+ * the two branches need different things and an optional-everything shape
50
+ * cannot say so:
51
+ *
52
+ * · `custom` — the seller posted it and types the carrier and tracking id.
53
+ * Those are REQUIRED, which is the rule enforced in three places today.
54
+ * · `platform` — we book it, so there is no tracking id to type; it comes
55
+ * back from the carrier. Requiring one here would be asking the seller to
56
+ * invent the thing the booking produces.
37
57
  */
38
- export declare const shipOrderSchema: z.ZodObject<{
58
+ export declare const shipOrderSchema: z.ZodDiscriminatedUnion<"method", [z.ZodObject<{
39
59
  method: z.ZodLiteral<"custom">;
40
60
  shippingCarrier: z.ZodString;
41
61
  trackingNumber: z.ZodString;
@@ -50,7 +70,44 @@ export declare const shipOrderSchema: z.ZodObject<{
50
70
  shippingCarrier: string;
51
71
  trackingUrl: string;
52
72
  method: "custom";
53
- }>;
73
+ }>, z.ZodObject<{
74
+ method: z.ZodLiteral<"platform">;
75
+ pickupAddressId: z.ZodString;
76
+ dimensions: z.ZodObject<{
77
+ weight: z.ZodNumber;
78
+ length: z.ZodNumber;
79
+ width: z.ZodNumber;
80
+ height: z.ZodNumber;
81
+ }, "strip", z.ZodTypeAny, {
82
+ length: number;
83
+ weight: number;
84
+ height: number;
85
+ width: number;
86
+ }, {
87
+ length: number;
88
+ weight: number;
89
+ height: number;
90
+ width: number;
91
+ }>;
92
+ }, "strip", z.ZodTypeAny, {
93
+ pickupAddressId: string;
94
+ method: "platform";
95
+ dimensions: {
96
+ length: number;
97
+ weight: number;
98
+ height: number;
99
+ width: number;
100
+ };
101
+ }, {
102
+ pickupAddressId: string;
103
+ method: "platform";
104
+ dimensions: {
105
+ length: number;
106
+ weight: number;
107
+ height: number;
108
+ width: number;
109
+ };
110
+ }>]>;
54
111
  export type ShipOrderValues = z.infer<typeof shipOrderSchema>;
55
112
  /**
56
113
  * Marking one EMI installment paid. `installmentIndex` is 1-based, matching