@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
@@ -79,6 +79,129 @@ export declare function normaliseDimensions(d: ParcelSource["dimensionsCm"]): Pa
79
79
  * whichever tier won on weight would discard information that exists.
80
80
  */
81
81
  export declare function resolveParcel(shipment: ParcelSource | null | undefined, product: ParcelSource | null | undefined, category: ParcelSource | null | undefined): Parcel | null;
82
+ /**
83
+ * Divisors, by service class.
84
+ *
85
+ * A carrier sells space, not mass, so it bills the greater of actual weight and
86
+ * `l × w × h ÷ divisor`. The divisor is the whole ballgame on this catalogue:
87
+ * collectible packaging is mostly air, so for a stadium box the volumetric
88
+ * figure is ~5× the actual and no per-kilo negotiation touches it.
89
+ *
90
+ * 🛑 `surfaceTight` is not a typo. Some Indian surface B2C plans quote ÷4000,
91
+ * which is a silent 25% increase over ÷5000 on every bulky parcel and is
92
+ * never the number on the front of the rate card. Read the contract, then set
93
+ * this per carrier — do not assume 5000 because it is the common default.
94
+ *
95
+ * Air uses a LARGER divisor, which means a very light bulky box can genuinely
96
+ * cost less by air than by surface. That is counter-intuitive and real.
97
+ */
98
+ export declare const VOLUMETRIC_DIVISORS: {
99
+ readonly surfaceTight: 4000;
100
+ readonly standard: 5000;
101
+ readonly air: 6000;
102
+ };
103
+ export declare const DEFAULT_VOLUMETRIC_DIVISOR: 5000;
104
+ /**
105
+ * Where a parcel sits against the two thresholds, and therefore which carrier
106
+ * class is cheaper. See `carrierClassFor` for why these numbers.
107
+ */
108
+ export declare const VOLUMETRIC_RATIO_THRESHOLDS: {
109
+ /** Below this the two weights are close enough that the rate card decides. */
110
+ readonly private: 1.5;
111
+ /** At or above this the box is mostly air and a postal service wins. */
112
+ readonly postal: 2;
113
+ };
114
+ /**
115
+ * The first billing slab, in grams — the region where R means nothing.
116
+ *
117
+ * 🛑 This guard exists because the ratio rule is WRONG below it, and the error
118
+ * was caught by checking the rule against real tariffs instead of trusting it.
119
+ *
120
+ * A single boxed bey is 250 g actual / 448 g volumetric — R 1.79, which the
121
+ * thresholds above call `"either"`. The real bill at >2000 km is ₹106 by Speed
122
+ * Post against ₹50 by private courier: private wins by 2×, not "either".
123
+ *
124
+ * The reason is that both figures land inside each carrier's MINIMUM charge, so
125
+ * the comparison is floor against floor and the ratio describes nothing. India
126
+ * Post's 201–500 g floor is ₹90; a private first slab is around ₹42. Whenever
127
+ * both weights sit in that first slab, the lower floor wins and that is private.
128
+ */
129
+ export declare const FIRST_SLAB_G = 500;
130
+ export interface ChargeableWeight {
131
+ actualG: number;
132
+ /**
133
+ * `null` when the dimension triple is unknown — NEVER 0.
134
+ *
135
+ * A carrier with no dimensions bills actual weight, so `chargeableG` is still
136
+ * correct in that case. But a `0` here would read as "this box has no volume",
137
+ * and `ratio` would compute to 0, which routes a stadium to the private
138
+ * carrier that bills it at 7.3 kg. Unknown has to stay distinguishable from
139
+ * dense — same discipline as `resolveParcel` refusing to return weight 0.
140
+ */
141
+ volumetricG: number | null;
142
+ /** `max(actual, volumetric)` — what you are billed for. */
143
+ chargeableG: number;
144
+ divisor: number;
145
+ billedOn: "actual" | "volumetric";
146
+ /**
147
+ * **The R value**: volumetric ÷ actual, 2dp. `null` without dimensions.
148
+ *
149
+ * 1 means the box is exactly at the divisor's break-even density. Above 1 you
150
+ * are paying for air; below 1 the volume is free and actual weight bills.
151
+ */
152
+ ratio: number | null;
153
+ /** Packed density in kg/m³. `null` without dimensions. */
154
+ densityKgM3: number | null;
155
+ /**
156
+ * The density at which volumetric starts to bite, derived from the divisor
157
+ * rather than hardcoded: `1e6 / divisor`. 200 kg/m³ at ÷5000, 250 at ÷4000,
158
+ * ~167 at ÷6000. A parcel below this is billed on volume.
159
+ */
160
+ breakEvenKgM3: number;
161
+ }
162
+ /** Volumetric weight in grams. `l × w × h ÷ divisor` is kilos, hence ×1000. */
163
+ export declare function volumetricWeightG(d: ParcelDimensionsCm, divisor?: number): number;
164
+ /**
165
+ * What this parcel is billed at, and by how much volume beats mass.
166
+ *
167
+ * Pure arithmetic — it reports, it does not decide. `carrierClassFor` turns the
168
+ * result into a routing opinion, deliberately as a separate step so a surface
169
+ * can show the numbers without adopting the recommendation.
170
+ */
171
+ export declare function chargeableWeight(parcel: Pick<Parcel, "weightG" | "dimensionsCm">, divisor?: number): ChargeableWeight;
172
+ /**
173
+ * Which carrier class is cheaper for this parcel, on freight alone.
174
+ *
175
+ * India Post Speed Post bills ACTUAL weight and applies no volumetric
176
+ * calculation; every private carrier bills the greater of the two. So the
177
+ * freight comparison reduces to the R value:
178
+ *
179
+ * R < 1.5 the two weights are close; the rate card decides, and a private
180
+ * card is usually cheaper at low weight → `"private"`
181
+ * 1.5 ≤ R < 2 genuinely close; decide on pincode serviceability and
182
+ * whether the item needs insurance → `"either"`
183
+ * R ≥ 2 the box is mostly air and postal is materially cheaper → `"postal"`
184
+ *
185
+ * 🛑 `"unknown"` when dimensions are missing, and callers must not collapse it
186
+ * into a default. Defaulting to `"private"` is precisely the wrong way round:
187
+ * the parcels whose dimensions nobody recorded are disproportionately the big
188
+ * awkward ones, which are the parcels this function exists to divert.
189
+ *
190
+ * 🛑 This is a FREIGHT opinion and nothing more. Above roughly ₹8,000 of order
191
+ * value the decision stops being about freight — the delta is a few hundred
192
+ * rupees against an uninsured loss of the whole item — so an order-value test
193
+ * and serviceability both outrank this. It answers "which is cheaper", never
194
+ * "which should we book".
195
+ *
196
+ * ## Where it is weakest, stated rather than hidden
197
+ *
198
+ * At HIGH weight the per-additional-slab rates start to matter more than the
199
+ * ratio, and those are negotiated. A 8 kg / 14 kg parcel is R 1.75 → `"either"`,
200
+ * while one representative card puts it at ₹991 postal against ₹1,197 private —
201
+ * a real 21% gap the ratio does not see. `"either"` is the honest answer there:
202
+ * it means your own card decides, not that the two are equal.
203
+ */
204
+ export declare function carrierClassFor(c: Pick<ChargeableWeight, "ratio" | "actualG" | "volumetricG">): "private" | "either" | "postal" | "unknown";
82
205
  /**
83
206
  * The weight of a whole order group — what a single shipment actually carries.
84
207
  *
@@ -88,6 +88,145 @@ export function resolveParcel(shipment, product, category) {
88
88
  }
89
89
  return { weightG, source, ...(dimensionsCm ? { dimensionsCm } : {}) };
90
90
  }
91
+ /* ── Volumetric weight — what the carrier actually bills ──────────────────── */
92
+ /**
93
+ * Divisors, by service class.
94
+ *
95
+ * A carrier sells space, not mass, so it bills the greater of actual weight and
96
+ * `l × w × h ÷ divisor`. The divisor is the whole ballgame on this catalogue:
97
+ * collectible packaging is mostly air, so for a stadium box the volumetric
98
+ * figure is ~5× the actual and no per-kilo negotiation touches it.
99
+ *
100
+ * 🛑 `surfaceTight` is not a typo. Some Indian surface B2C plans quote ÷4000,
101
+ * which is a silent 25% increase over ÷5000 on every bulky parcel and is
102
+ * never the number on the front of the rate card. Read the contract, then set
103
+ * this per carrier — do not assume 5000 because it is the common default.
104
+ *
105
+ * Air uses a LARGER divisor, which means a very light bulky box can genuinely
106
+ * cost less by air than by surface. That is counter-intuitive and real.
107
+ */
108
+ export const VOLUMETRIC_DIVISORS = {
109
+ surfaceTight: 4000,
110
+ standard: 5000,
111
+ air: 6000,
112
+ };
113
+ export const DEFAULT_VOLUMETRIC_DIVISOR = VOLUMETRIC_DIVISORS.standard;
114
+ /**
115
+ * Where a parcel sits against the two thresholds, and therefore which carrier
116
+ * class is cheaper. See `carrierClassFor` for why these numbers.
117
+ */
118
+ export const VOLUMETRIC_RATIO_THRESHOLDS = {
119
+ /** Below this the two weights are close enough that the rate card decides. */
120
+ private: 1.5,
121
+ /** At or above this the box is mostly air and a postal service wins. */
122
+ postal: 2,
123
+ };
124
+ /**
125
+ * The first billing slab, in grams — the region where R means nothing.
126
+ *
127
+ * 🛑 This guard exists because the ratio rule is WRONG below it, and the error
128
+ * was caught by checking the rule against real tariffs instead of trusting it.
129
+ *
130
+ * A single boxed bey is 250 g actual / 448 g volumetric — R 1.79, which the
131
+ * thresholds above call `"either"`. The real bill at >2000 km is ₹106 by Speed
132
+ * Post against ₹50 by private courier: private wins by 2×, not "either".
133
+ *
134
+ * The reason is that both figures land inside each carrier's MINIMUM charge, so
135
+ * the comparison is floor against floor and the ratio describes nothing. India
136
+ * Post's 201–500 g floor is ₹90; a private first slab is around ₹42. Whenever
137
+ * both weights sit in that first slab, the lower floor wins and that is private.
138
+ */
139
+ export const FIRST_SLAB_G = 500;
140
+ /** Volumetric weight in grams. `l × w × h ÷ divisor` is kilos, hence ×1000. */
141
+ export function volumetricWeightG(d, divisor = DEFAULT_VOLUMETRIC_DIVISOR) {
142
+ if (!(divisor > 0)) {
143
+ throw new RangeError(`volumetricWeightG: divisor must be > 0, got ${divisor}`);
144
+ }
145
+ return Math.round(((d.l * d.w * d.h) / divisor) * 1000);
146
+ }
147
+ /**
148
+ * What this parcel is billed at, and by how much volume beats mass.
149
+ *
150
+ * Pure arithmetic — it reports, it does not decide. `carrierClassFor` turns the
151
+ * result into a routing opinion, deliberately as a separate step so a surface
152
+ * can show the numbers without adopting the recommendation.
153
+ */
154
+ export function chargeableWeight(parcel, divisor = DEFAULT_VOLUMETRIC_DIVISOR) {
155
+ const actualG = parcel.weightG;
156
+ const breakEvenKgM3 = Math.round((1000000 / divisor) * 10) / 10;
157
+ const d = parcel.dimensionsCm;
158
+ if (!d) {
159
+ return {
160
+ actualG,
161
+ volumetricG: null,
162
+ chargeableG: actualG,
163
+ divisor,
164
+ billedOn: "actual",
165
+ ratio: null,
166
+ densityKgM3: null,
167
+ breakEvenKgM3,
168
+ };
169
+ }
170
+ const volumetricG = volumetricWeightG(d, divisor);
171
+ const cm3 = d.l * d.w * d.h;
172
+ return {
173
+ actualG,
174
+ volumetricG,
175
+ chargeableG: Math.max(actualG, volumetricG),
176
+ divisor,
177
+ billedOn: volumetricG > actualG ? "volumetric" : "actual",
178
+ ratio: actualG > 0 ? Math.round((volumetricG / actualG) * 100) / 100 : null,
179
+ densityKgM3: cm3 > 0 ? Math.round(((actualG * 1000) / cm3) * 10) / 10 : null,
180
+ breakEvenKgM3,
181
+ };
182
+ }
183
+ /**
184
+ * Which carrier class is cheaper for this parcel, on freight alone.
185
+ *
186
+ * India Post Speed Post bills ACTUAL weight and applies no volumetric
187
+ * calculation; every private carrier bills the greater of the two. So the
188
+ * freight comparison reduces to the R value:
189
+ *
190
+ * R < 1.5 the two weights are close; the rate card decides, and a private
191
+ * card is usually cheaper at low weight → `"private"`
192
+ * 1.5 ≤ R < 2 genuinely close; decide on pincode serviceability and
193
+ * whether the item needs insurance → `"either"`
194
+ * R ≥ 2 the box is mostly air and postal is materially cheaper → `"postal"`
195
+ *
196
+ * 🛑 `"unknown"` when dimensions are missing, and callers must not collapse it
197
+ * into a default. Defaulting to `"private"` is precisely the wrong way round:
198
+ * the parcels whose dimensions nobody recorded are disproportionately the big
199
+ * awkward ones, which are the parcels this function exists to divert.
200
+ *
201
+ * 🛑 This is a FREIGHT opinion and nothing more. Above roughly ₹8,000 of order
202
+ * value the decision stops being about freight — the delta is a few hundred
203
+ * rupees against an uninsured loss of the whole item — so an order-value test
204
+ * and serviceability both outrank this. It answers "which is cheaper", never
205
+ * "which should we book".
206
+ *
207
+ * ## Where it is weakest, stated rather than hidden
208
+ *
209
+ * At HIGH weight the per-additional-slab rates start to matter more than the
210
+ * ratio, and those are negotiated. A 8 kg / 14 kg parcel is R 1.75 → `"either"`,
211
+ * while one representative card puts it at ₹991 postal against ₹1,197 private —
212
+ * a real 21% gap the ratio does not see. `"either"` is the honest answer there:
213
+ * it means your own card decides, not that the two are equal.
214
+ */
215
+ export function carrierClassFor(c) {
216
+ if (c.ratio == null)
217
+ return "unknown";
218
+ // Both weights inside the first slab → floor vs floor; see FIRST_SLAB_G.
219
+ if (c.actualG <= FIRST_SLAB_G &&
220
+ c.volumetricG != null &&
221
+ c.volumetricG <= FIRST_SLAB_G) {
222
+ return "private";
223
+ }
224
+ if (c.ratio >= VOLUMETRIC_RATIO_THRESHOLDS.postal)
225
+ return "postal";
226
+ if (c.ratio >= VOLUMETRIC_RATIO_THRESHOLDS.private)
227
+ return "either";
228
+ return "private";
229
+ }
91
230
  /**
92
231
  * The weight of a whole order group — what a single shipment actually carries.
93
232
  *
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Shared purchase, S5a — one payer, N destinations.
3
+ *
4
+ * ## What this is, and what it deliberately is not
5
+ *
6
+ * The coordinator buys everything and assigns a destination per item, so one
7
+ * paid order becomes N parcels. That is **~20% of the shared-purchase work for
8
+ * most of its value** (the plan's own assessment), because it needs none of
9
+ * the hard parts: no multi-party payment, no coordinator deposit, no approval
10
+ * cascade, no per-buyer invoicing, no per-buyer GST, and no stock-reservation
11
+ * primitive.
12
+ *
13
+ * 🛑 It is NOT S5b. There is exactly ONE payer and ONE place of supply, which
14
+ * is what keeps the tax, the invoice and the refund path unchanged. The moment
15
+ * a second person pays, every one of those becomes per-buyer and the design is
16
+ * a different design.
17
+ *
18
+ * ## 🛑 Why the fees are SNAPSHOTTED, and the precedent that proves it
19
+ *
20
+ * A coordinator commits to a quoted total. If the handling fee or the
21
+ * per-destination shipping is re-read at settle, a seller can raise it after
22
+ * the quote and the coordinator absorbs the difference.
23
+ *
24
+ * The codebase already has this exact hole and this exact fix: the refund path
25
+ * reads `finalSale` from the ORDER snapshot rather than the live product,
26
+ * because — in its own words — "re-reading the live product would let a seller
27
+ * flip the switch afterwards". D61 generalises it: *any agreement with a gap
28
+ * between "terms agreed" and "money taken" must snapshot its terms at
29
+ * agreement.*
30
+ *
31
+ * So `quoteSharedPurchase` takes the rates as ARGUMENTS and the caller
32
+ * snapshots the result onto the order. There is no settings read in here.
33
+ */
34
+ /** The two rates, read from the store document at quote time. */
35
+ export interface SharedPurchaseRates {
36
+ allowSharedPurchase?: boolean;
37
+ sharedPurchaseHandlingFee?: number;
38
+ sharedPurchaseExtraShippingPerDestination?: number;
39
+ }
40
+ export interface SharedPurchaseQuoteInput {
41
+ /**
42
+ * Distinct destinations in this order group, INCLUDING the first.
43
+ *
44
+ * 🛑 A count of DISTINCT addresses, not of items. Three items to one address
45
+ * is one parcel and no extra leg; two items to two addresses is two. Passing
46
+ * an item count would charge a coordinator for splitting an order they did
47
+ * not split.
48
+ */
49
+ destinationCount: number;
50
+ /** The store's snapshotted rates. */
51
+ rates: SharedPurchaseRates;
52
+ }
53
+ export interface SharedPurchaseQuote {
54
+ /** True when this is actually a multi-destination order. */
55
+ isShared: boolean;
56
+ /** Flat handling fee, or 0. */
57
+ handlingFee: number;
58
+ /** Extra shipping for destinations beyond the first, or 0. */
59
+ extraShippingFee: number;
60
+ /** `handlingFee + extraShippingFee`, the figure added to the order total. */
61
+ total: number;
62
+ /**
63
+ * Set when the arrangement cannot be priced — the seller allows it but has
64
+ * not configured a rate.
65
+ *
66
+ * 🛑 The caller MUST act on this rather than treating the fee as ₹0. That is
67
+ * D44 exactly: `shippingUnavailable` existed with its own docstring saying
68
+ * "the caller MUST act on this rather than trusting `shippingFee: 0`", had
69
+ * ZERO consumers, and an `estimate`-mode store shipped free on every path as
70
+ * a result. An unpriced arrangement must be refused, not given away.
71
+ */
72
+ unpriced?: "handling" | "extra-shipping";
73
+ }
74
+ /**
75
+ * Price a shared-purchase arrangement for ONE order group.
76
+ *
77
+ * Pure: no settings read, no Firestore, no clock. The rates come in, the
78
+ * figure comes out, and the caller snapshots it.
79
+ */
80
+ export declare function quoteSharedPurchase(input: SharedPurchaseQuoteInput): SharedPurchaseQuote;
81
+ /**
82
+ * Distinct destinations across a set of lines.
83
+ *
84
+ * 🛑 Lines with NO `destinationAddressId` collapse into one bucket — the
85
+ * order's own address — rather than counting as a destination each. Otherwise
86
+ * an ordinary three-item order would look like three destinations and be
87
+ * charged two extra legs.
88
+ */
89
+ export declare function countDestinations(lines: readonly {
90
+ destinationAddressId?: string;
91
+ }[]): number;
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Shared purchase, S5a — one payer, N destinations.
3
+ *
4
+ * ## What this is, and what it deliberately is not
5
+ *
6
+ * The coordinator buys everything and assigns a destination per item, so one
7
+ * paid order becomes N parcels. That is **~20% of the shared-purchase work for
8
+ * most of its value** (the plan's own assessment), because it needs none of
9
+ * the hard parts: no multi-party payment, no coordinator deposit, no approval
10
+ * cascade, no per-buyer invoicing, no per-buyer GST, and no stock-reservation
11
+ * primitive.
12
+ *
13
+ * 🛑 It is NOT S5b. There is exactly ONE payer and ONE place of supply, which
14
+ * is what keeps the tax, the invoice and the refund path unchanged. The moment
15
+ * a second person pays, every one of those becomes per-buyer and the design is
16
+ * a different design.
17
+ *
18
+ * ## 🛑 Why the fees are SNAPSHOTTED, and the precedent that proves it
19
+ *
20
+ * A coordinator commits to a quoted total. If the handling fee or the
21
+ * per-destination shipping is re-read at settle, a seller can raise it after
22
+ * the quote and the coordinator absorbs the difference.
23
+ *
24
+ * The codebase already has this exact hole and this exact fix: the refund path
25
+ * reads `finalSale` from the ORDER snapshot rather than the live product,
26
+ * because — in its own words — "re-reading the live product would let a seller
27
+ * flip the switch afterwards". D61 generalises it: *any agreement with a gap
28
+ * between "terms agreed" and "money taken" must snapshot its terms at
29
+ * agreement.*
30
+ *
31
+ * So `quoteSharedPurchase` takes the rates as ARGUMENTS and the caller
32
+ * snapshots the result onto the order. There is no settings read in here.
33
+ */
34
+ import { roundRupees } from "../../../../utils/number.formatter.js";
35
+ /**
36
+ * Price a shared-purchase arrangement for ONE order group.
37
+ *
38
+ * Pure: no settings read, no Firestore, no clock. The rates come in, the
39
+ * figure comes out, and the caller snapshots it.
40
+ */
41
+ export function quoteSharedPurchase(input) {
42
+ const none = {
43
+ isShared: false,
44
+ handlingFee: 0,
45
+ extraShippingFee: 0,
46
+ total: 0,
47
+ };
48
+ /*
49
+ * One destination is an ordinary order. Checked BEFORE the allow flag, so a
50
+ * seller who has not opted in is unaffected by this code path entirely —
51
+ * rather than being refused an order they were always able to take.
52
+ */
53
+ const destinations = Math.max(1, Math.floor(input.destinationCount));
54
+ if (destinations <= 1)
55
+ return none;
56
+ if (input.rates.allowSharedPurchase !== true) {
57
+ /*
58
+ * 🛑 Returns `isShared: false` rather than throwing, and the CALLER
59
+ * refuses. This function prices; it does not authorise. A thrown error
60
+ * here would be caught by a preview path and rendered as a broken page,
61
+ * where the correct behaviour is to tell the buyer this seller does not
62
+ * split orders.
63
+ */
64
+ return none;
65
+ }
66
+ const handling = input.rates.sharedPurchaseHandlingFee;
67
+ const perExtra = input.rates.sharedPurchaseExtraShippingPerDestination;
68
+ /*
69
+ * 🛑 `undefined` is UNPRICED, not zero — see the `unpriced` field. A seller
70
+ * who opted in without setting a rate has not agreed to do it for free, and
71
+ * charging ₹0 would hand them the extra labour at their own cost silently.
72
+ */
73
+ if (typeof handling !== "number" || !Number.isFinite(handling)) {
74
+ return { ...none, isShared: true, unpriced: "handling" };
75
+ }
76
+ if (typeof perExtra !== "number" || !Number.isFinite(perExtra)) {
77
+ return { ...none, isShared: true, unpriced: "extra-shipping" };
78
+ }
79
+ const handlingFee = roundRupees(Math.max(0, handling));
80
+ // BEYOND THE FIRST: the first destination's shipping is what the order would
81
+ // have paid anyway, so only the marginal legs are charged here.
82
+ const extraShippingFee = roundRupees(Math.max(0, perExtra) * (destinations - 1));
83
+ return {
84
+ isShared: true,
85
+ handlingFee,
86
+ extraShippingFee,
87
+ total: roundRupees(handlingFee + extraShippingFee),
88
+ };
89
+ }
90
+ /**
91
+ * Distinct destinations across a set of lines.
92
+ *
93
+ * 🛑 Lines with NO `destinationAddressId` collapse into one bucket — the
94
+ * order's own address — rather than counting as a destination each. Otherwise
95
+ * an ordinary three-item order would look like three destinations and be
96
+ * charged two extra legs.
97
+ */
98
+ export function countDestinations(lines) {
99
+ const ids = new Set();
100
+ let usesOrderAddress = false;
101
+ for (const line of lines) {
102
+ if (line.destinationAddressId)
103
+ ids.add(line.destinationAddressId);
104
+ else
105
+ usesOrderAddress = true;
106
+ }
107
+ return ids.size + (usesOrderAddress ? 1 : 0);
108
+ }
@@ -38,17 +38,25 @@ export interface BuyerFacingFees {
38
38
  codHandlingFeeCap?: number;
39
39
  codHandlingFeePercent?: number;
40
40
  codDepositPercent?: number;
41
+ /** Commission rate applied to the cart subtotal, before the cap. */
42
+ platformFeePercent?: number;
43
+ /** Rupee ceiling on the commission — the reason a ₹39,500 order pays ₹10. */
44
+ platformFeeMax?: number;
45
+ /** GST rate levied on the commission actually charged (never on the uncapped figure). */
46
+ gstPercent?: number;
47
+ /** Rupee floor on `platformFee + gstOnFee` combined. */
48
+ minimumTransactionFee?: number;
41
49
  }
42
50
  /**
43
- * Withheld on purpose (15 of 25): platformFeePercent, gstPercent,
44
- * minimumTransactionFee, platformFeeMax, gatewayFeePercent,
45
- * sellerShippingFixed, platformShippingPercent, platformShippingFixedMin,
46
- * autoPayoutWindowDays, payoutHoldDays, minPayoutAmount, auctionListingFee,
47
- * preOrderListingFee, featuredSlotFee, promotedSlotFee.
51
+ * Withheld on purpose (11 of 25): gatewayFeePercent, sellerShippingFixed,
52
+ * platformShippingPercent, platformShippingFixedMin, autoPayoutWindowDays,
53
+ * payoutHoldDays, minPayoutAmount, auctionListingFee, preOrderListingFee,
54
+ * featuredSlotFee, promotedSlotFee — plus `surchargeSellerSharePercent`, which
55
+ * lives on the EMI block and is excluded by `BuyerEmiSettings` below.
48
56
  *
49
- * The buyer still SEES the platform fee and GST — as computed amounts in the
50
- * server pricing preview (`CartPriceBreakdownData`), never as the rates that
51
- * produced them.
57
+ * Every one of those prices something between us and a seller or a gateway.
58
+ * None of them changes what the buyer is asked to pay, so none of them has a
59
+ * reader in a browser.
52
60
  */
53
61
  export declare function toBuyerFacingFees(commissions: SiteSettingsDocument["commissions"] | null | undefined): BuyerFacingFees | null;
54
62
  /**
@@ -1,13 +1,13 @@
1
1
  /**
2
- * Withheld on purpose (15 of 25): platformFeePercent, gstPercent,
3
- * minimumTransactionFee, platformFeeMax, gatewayFeePercent,
4
- * sellerShippingFixed, platformShippingPercent, platformShippingFixedMin,
5
- * autoPayoutWindowDays, payoutHoldDays, minPayoutAmount, auctionListingFee,
6
- * preOrderListingFee, featuredSlotFee, promotedSlotFee.
2
+ * Withheld on purpose (11 of 25): gatewayFeePercent, sellerShippingFixed,
3
+ * platformShippingPercent, platformShippingFixedMin, autoPayoutWindowDays,
4
+ * payoutHoldDays, minPayoutAmount, auctionListingFee, preOrderListingFee,
5
+ * featuredSlotFee, promotedSlotFee — plus `surchargeSellerSharePercent`, which
6
+ * lives on the EMI block and is excluded by `BuyerEmiSettings` below.
7
7
  *
8
- * The buyer still SEES the platform fee and GST — as computed amounts in the
9
- * server pricing preview (`CartPriceBreakdownData`), never as the rates that
10
- * produced them.
8
+ * Every one of those prices something between us and a seller or a gateway.
9
+ * None of them changes what the buyer is asked to pay, so none of them has a
10
+ * reader in a browser.
11
11
  */
12
12
  export function toBuyerFacingFees(commissions) {
13
13
  if (!commissions)
@@ -24,6 +24,10 @@ export function toBuyerFacingFees(commissions) {
24
24
  codHandlingFeeCap: commissions.codHandlingFeeCap,
25
25
  codHandlingFeePercent: commissions.codHandlingFeePercent,
26
26
  codDepositPercent: commissions.codDepositPercent,
27
+ platformFeePercent: commissions.platformFeePercent,
28
+ platformFeeMax: commissions.platformFeeMax,
29
+ gstPercent: commissions.gstPercent,
30
+ minimumTransactionFee: commissions.minimumTransactionFee,
27
31
  };
28
32
  }
29
33
  export function toBuyerEmiSettings(emi) {
@@ -42,6 +42,17 @@ export interface PublicSiteSettings {
42
42
  chat?: {
43
43
  enabled: boolean;
44
44
  };
45
+ /**
46
+ * Is the support desk reachable — read by `UserLayoutClient`, a client
47
+ * component. Narrowed to the one boolean rather than passed by reference,
48
+ * so a field added to the document's `support` group later is not published
49
+ * by accident; `PUBLIC_SITE_SETTINGS_FIELDS` carries the same caveat beside
50
+ * its entry. Optional here because the group is absent on a settings
51
+ * document written before it existed.
52
+ */
53
+ support?: {
54
+ enabled: boolean;
55
+ };
45
56
  /**
46
57
  * The browser-side search index kill switch. **ON by default** — the
47
58
  * projection emits `indexEnabled: doc.search?.indexEnabled !== false`, so
@@ -79,6 +79,17 @@ export interface PayoutDeduction {
79
79
  * plus ₹80 postage" is a sentence; one net figure is not.
80
80
  */
81
81
  shippingReimbursement: number;
82
+ /**
83
+ * Rupee value of buyer points this order was settled with, deducted from
84
+ * `netAmount` (D46/D47, decisions 3 and 17 — the accepting store funds the
85
+ * redemption).
86
+ *
87
+ * Returned as its own figure rather than folded into `totalDeduction` for the
88
+ * same reason `shippingReimbursement` is: *"'₹900 less ₹30 commission plus
89
+ * ₹80 postage' is a sentence; one net figure is not."* A seller looking at a
90
+ * short payout needs to see which of the four terms shortened it.
91
+ */
92
+ pointsFunded: number;
82
93
  }
83
94
  /**
84
95
  * What a seller is actually paid.
@@ -101,8 +112,29 @@ export interface PayoutDeduction {
101
112
  *
102
113
  * Defaulted to 0, so the three call sites that do not yet pass it keep their
103
114
  * current behaviour exactly rather than silently gaining a term.
115
+ *
116
+ * ## 🛑 `pointsFunded` is the mirror of that, and it is a DEDUCTION
117
+ *
118
+ * Decisions 3 and 17: the programme is seller-funded at both ends — the
119
+ * accepting store absorbs the redemption, the originating store bears the
120
+ * earn — and the platform funds neither. So points spent on an order reduce
121
+ * that order's payout by the rupee value spent.
122
+ *
123
+ * It sits in the SAME position as postage and for the inverse reason: outside
124
+ * the commission and gateway bases. The seller agreed to fund a discount, not
125
+ * to pay us a commission on the discount they funded, and a gateway percentage
126
+ * on money no gateway touched is not a card fee at all.
127
+ *
128
+ * 🛑 So `grossAmount` is untouched and the fee figures are IDENTICAL whether
129
+ * points were used or not. That is what keeps the commission the seller is
130
+ * charged a function of the sale rather than of how the buyer chose to settle
131
+ * it — and it is why this cannot be implemented by passing a smaller
132
+ * `grossAmount`, which is the obvious shortcut and silently reduces our own
133
+ * commission by 2% of every redemption.
134
+ *
135
+ * Also defaulted to 0, for the same reason.
104
136
  */
105
- export declare function computePayoutDeduction(grossAmount: number, commissions: FeeCommissionRates, shippingReimbursement?: number): PayoutDeduction;
137
+ export declare function computePayoutDeduction(grossAmount: number, commissions: FeeCommissionRates, shippingReimbursement?: number, pointsFunded?: number): PayoutDeduction;
106
138
  export interface CodHandlingFeeRates {
107
139
  /**
108
140
  * Rupee CEILING on the COD handling fee. Optional so a `siteSettings`
@@ -114,8 +114,29 @@ export function allocateCheckoutFees(groupSubtotals, fees) {
114
114
  *
115
115
  * Defaulted to 0, so the three call sites that do not yet pass it keep their
116
116
  * current behaviour exactly rather than silently gaining a term.
117
+ *
118
+ * ## 🛑 `pointsFunded` is the mirror of that, and it is a DEDUCTION
119
+ *
120
+ * Decisions 3 and 17: the programme is seller-funded at both ends — the
121
+ * accepting store absorbs the redemption, the originating store bears the
122
+ * earn — and the platform funds neither. So points spent on an order reduce
123
+ * that order's payout by the rupee value spent.
124
+ *
125
+ * It sits in the SAME position as postage and for the inverse reason: outside
126
+ * the commission and gateway bases. The seller agreed to fund a discount, not
127
+ * to pay us a commission on the discount they funded, and a gateway percentage
128
+ * on money no gateway touched is not a card fee at all.
129
+ *
130
+ * 🛑 So `grossAmount` is untouched and the fee figures are IDENTICAL whether
131
+ * points were used or not. That is what keeps the commission the seller is
132
+ * charged a function of the sale rather than of how the buyer chose to settle
133
+ * it — and it is why this cannot be implemented by passing a smaller
134
+ * `grossAmount`, which is the obvious shortcut and silently reduces our own
135
+ * commission by 2% of every redemption.
136
+ *
137
+ * Also defaulted to 0, for the same reason.
117
138
  */
118
- export function computePayoutDeduction(grossAmount, commissions, shippingReimbursement = 0) {
139
+ export function computePayoutDeduction(grossAmount, commissions, shippingReimbursement = 0, pointsFunded = 0) {
119
140
  const platformFee = roundRupees(grossAmount * (commissions.platformFeePercent / 100));
120
141
  const gatewayFee = roundRupees(grossAmount * ((commissions.gatewayFeePercent ?? 0) / 100));
121
142
  const gstOnFee = roundRupees(platformFee * (commissions.gstPercent / 100));
@@ -123,7 +144,15 @@ export function computePayoutDeduction(grossAmount, commissions, shippingReimbur
123
144
  const postage = Number.isFinite(shippingReimbursement)
124
145
  ? Math.max(0, shippingReimbursement)
125
146
  : 0;
126
- const netAmount = Math.max(0, roundRupees(grossAmount - totalDeduction + postage));
147
+ const points = Number.isFinite(pointsFunded) ? Math.max(0, pointsFunded) : 0;
148
+ /*
149
+ * Clamped at zero, as it already was. A redemption cannot exceed 50% of the
150
+ * order total, so it cannot plausibly exceed the net — but a floor here means
151
+ * no caller can ever hand a seller a negative payout, which would be written
152
+ * to a `PayoutDocument.amount` that every downstream sum then treats as a
153
+ * credit against the platform.
154
+ */
155
+ const netAmount = Math.max(0, roundRupees(grossAmount - totalDeduction + postage - points));
127
156
  return {
128
157
  platformFee,
129
158
  gatewayFee,
@@ -131,6 +160,7 @@ export function computePayoutDeduction(grossAmount, commissions, shippingReimbur
131
160
  totalDeduction,
132
161
  netAmount,
133
162
  shippingReimbursement: roundRupees(postage),
163
+ pointsFunded: roundRupees(points),
134
164
  };
135
165
  }
136
166
  /** Buyer-facing COD handling ceiling, in decimal rupees. */