@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
@@ -1,5 +1,13 @@
1
1
  import { roundRupees } from "../../../utils/number.formatter.js";
2
2
  import { calculateGstInclusive, taxableFromInclusive } from "../fees/calculator.js";
3
+ /*
4
+ * Points: the CAP arithmetic only. `maxRedeemablePoints` lives beside
5
+ * `POINTS_MAX_REDEMPTION_PERCENT`, which is the constant that defines it, so
6
+ * importing it here keeps one owner for the rule rather than a second copy of
7
+ * the percentage (Root Cause #75). This file stays pure — the points SCHEMA is
8
+ * plain data with no Firestore import.
9
+ */
10
+ import { maxRedeemablePoints } from "../../../features/points/schemas/firestore.js";
3
11
  /**
4
12
  * The single source of truth for "what do we charge for ONE COPY of this line".
5
13
  *
@@ -593,14 +601,165 @@ export function orderPointsFunded(order) {
593
601
  ? roundRupees(Math.max(0, awarded))
594
602
  : 0;
595
603
  }
604
+ /**
605
+ * Points this order CONSUMED, which the accepting store also funds (D46/D47).
606
+ *
607
+ * Decision 3's other end. The earn above is borne by the originating store;
608
+ * the redemption is absorbed by the store that agreed to accept points
609
+ * (`StoreDocument.acceptsPoints`, defaulting to NOT accepted precisely so no
610
+ * seller is enrolled in funding discounts they never agreed to). The platform
611
+ * funds neither end.
612
+ *
613
+ * Reads `pointsApplied` off the order for the same reason the earn reads
614
+ * `pointsAwarded`: it must be what was actually spent. Recomputing the cap from
615
+ * today's total would deduct a figure the buyer never received the benefit of —
616
+ * and on a partially-cancelled order the total has moved.
617
+ */
618
+ export function orderPointsRedeemed(order) {
619
+ const applied = order.pointsApplied;
620
+ return typeof applied === "number" && Number.isFinite(applied)
621
+ ? roundRupees(Math.max(0, applied))
622
+ : 0;
623
+ }
596
624
  /** Sum of `orderPointsFunded` across a batch. */
597
625
  export function ordersPointsFunded(orders) {
598
626
  return roundRupees(orders.reduce((sum, o) => sum + orderPointsFunded(o), 0));
599
627
  }
628
+ /**
629
+ * Everything the store funds through the points programme, for one batch:
630
+ * points ISSUED on these orders plus points SPENT on them.
631
+ *
632
+ * ## 🛑 One figure, because they are one obligation
633
+ *
634
+ * Both ends are seller-funded (decisions 3 and 17) and both are deducted from
635
+ * the same payout at the same moment, so splitting them across two parameters
636
+ * of `computePayoutDeduction` would be two chances for a call site to pass one
637
+ * and forget the other — and a payout that deducts the earn but not the
638
+ * redemption is short by exactly the amount nobody noticed.
639
+ *
640
+ * 🛑 This helper exists because `ordersPointsFunded` had **ZERO consumers**
641
+ * from the day it was written — the earn deduction was built, documented at
642
+ * length, and never passed to the function it was built for, so every payout
643
+ * since has quietly been funded by the platform. That is the dead-field
644
+ * pattern (Rule: every declared field has both a writer and a reader) occurring
645
+ * inside the work that catalogues it. Wiring the combined figure at all four
646
+ * call sites is what closes it.
647
+ */
648
+ export function ordersPointsBorneByStore(orders) {
649
+ return roundRupees(orders.reduce((sum, o) => sum + orderPointsFunded(o) + orderPointsRedeemed(o), 0));
650
+ }
600
651
  /** Sum of `orderShippingReimbursement` across a batch. */
601
652
  export function ordersShippingReimbursement(orders) {
602
653
  return roundRupees(orders.reduce((sum, o) => sum + orderShippingReimbursement(o), 0));
603
654
  }
655
+ /**
656
+ * How many points may be spent on ONE order group, and what is left to charge.
657
+ *
658
+ * ## 🛑 A PIPELINE STAGE, after the final rounding — never a post-order debit
659
+ *
660
+ * This is the whole lesson of D46. The deleted code redeemed points AFTER the
661
+ * orders existed and the gateway had captured `orderTotal`, so a successful
662
+ * redemption took points from a buyer who had just paid full price: nothing in
663
+ * the pipeline knew about the spend, so nothing reduced the charge.
664
+ *
665
+ * So the tender is a STAGE. `amountDue = orderTotal − pointsApplied` is
666
+ * computed here, and `amountDue` is what the gateway captures and what the
667
+ * post-capture guard compares. A sixth way for the captured amount to diverge
668
+ * from the recorded total is the D37/D38/D40 family; this is how it is avoided.
669
+ *
670
+ * ## 🛑 Applied AFTER rounding, deliberately
671
+ *
672
+ * `orderTotal` is rounded ONCE at the end of its own nine-term sum (D42).
673
+ * Folding points in before that rounding would put a discount inside the sum
674
+ * being rounded, so the figure shown to the buyer and the figure captured could
675
+ * differ by a paisa. They must be provably equal, which is why `amountDue` is
676
+ * derived here and never recomputed at the gateway.
677
+ *
678
+ * ## Per order group, because the ACCEPTING STORE absorbs it
679
+ *
680
+ * Decision 3: a redeemed point reduces THAT store's payout for THAT order. A
681
+ * cart spanning an accepting and a non-accepting store must not pool the
682
+ * discount — each group gets its own cap and its own figure. That is the same
683
+ * granularity `splitCartIntoOrderGroups` and `allocateCheckoutFees` already
684
+ * use, and its absence is what caused Root Cause #65's per-store
685
+ * multiplication bug.
686
+ *
687
+ * ## All-or-nothing, and the remainder STAYS
688
+ *
689
+ * Owner's rule: *"if use point it is all and then the balance is returned if
690
+ * excess"*. There is no requested amount — the balance is spent down as far as
691
+ * the cap allows, and whatever will not fit is simply not spent. It stays in
692
+ * the ledger for a later order; nothing is forfeited, and no caller can ask for
693
+ * a partial spend.
694
+ *
695
+ * 🛑 The 50% cap is not optional, and removing it was explicitly declined.
696
+ * `POINTS_MAX_REDEMPTION_PERCENT` exists because a ₹0 order breaks the gateway
697
+ * (a ₹0 Razorpay order is not a thing) and because a balance that can settle a
698
+ * whole purchase behaves like the stored value the points schema is written to
699
+ * avoid.
700
+ */
701
+ export function resolvePointsTender(input) {
702
+ const total = roundRupees(Math.max(0, input.orderTotal));
703
+ if (!input.optedIn || !input.accepted)
704
+ return { pointsApplied: 0, amountDue: total };
705
+ const balance = Math.floor(Math.max(0, input.balance));
706
+ if (!Number.isFinite(balance) || balance <= 0)
707
+ return { pointsApplied: 0, amountDue: total };
708
+ /*
709
+ * `maxRedeemablePoints` owns the cap arithmetic — it floors to whole points
710
+ * and applies `POINTS_MAX_REDEMPTION_PERCENT`. Re-deriving the percentage
711
+ * here would be a second copy of a money rule (Root Cause #75), and the one
712
+ * place it already lives sits beside the constant that defines it.
713
+ */
714
+ const pointsApplied = maxRedeemablePoints(total, balance);
715
+ return { pointsApplied, amountDue: roundRupees(total - pointsApplied) };
716
+ }
717
+ /**
718
+ * The payable total a points allocation is measured against.
719
+ *
720
+ * 🛑 ONE implementation, because it was two. `POST /api/payment/create-order`
721
+ * and `verifyAndPlaceRazorpayOrderAction`'s amount guard each built this sum
722
+ * by hand, in the same shape, from the same six parts — and they are the
723
+ * *shown* figure and the *charged* figure for the same cart. Two hand-written
724
+ * copies of one money rule is Root Cause #75 exactly, and the failure mode is
725
+ * the worst kind: they only disagree on carts where the arithmetic differs, so
726
+ * nothing errors and the buyer is quoted one number and charged another.
727
+ *
728
+ * The coupon is floored at zero before the fees are added, never after — a
729
+ * discount larger than the goods must not eat the shipping and platform fee.
730
+ */
731
+ export function pointsBaseForGroup(parts) {
732
+ return {
733
+ total: roundRupees(Math.max(0, parts.goods - parts.couponDiscount) +
734
+ parts.shippingFee +
735
+ parts.addonFee +
736
+ parts.platformFee +
737
+ parts.gstOnFee),
738
+ accepted: parts.acceptsPoints,
739
+ };
740
+ }
741
+ export function allocatePointsAcrossGroups(groups, balance, optedIn) {
742
+ const perGroup = groups.map(() => 0);
743
+ if (!optedIn)
744
+ return { perGroup, pointsApplied: 0 };
745
+ let remaining = Math.floor(Math.max(0, balance));
746
+ if (!Number.isFinite(remaining) || remaining <= 0)
747
+ return { perGroup, pointsApplied: 0 };
748
+ let applied = 0;
749
+ for (let i = 0; i < groups.length; i += 1) {
750
+ const g = groups[i];
751
+ const { pointsApplied } = resolvePointsTender({
752
+ orderTotal: g.total,
753
+ balance: g.accepted ? remaining : 0,
754
+ accepted: g.accepted,
755
+ optedIn: true,
756
+ });
757
+ perGroup[i] = pointsApplied;
758
+ remaining -= pointsApplied;
759
+ applied += pointsApplied;
760
+ }
761
+ return { perGroup, pointsApplied: applied };
762
+ }
604
763
  /**
605
764
  * P-6 — pre-order groups charge each product's own `preOrderDepositPercent`
606
765
  * (falling back to the generic COD deposit % when a product doesn't have one
@@ -36,6 +36,21 @@ export interface RefundableOrderLike {
36
36
  amount: number;
37
37
  status?: string;
38
38
  }>;
39
+ /**
40
+ * D46/D47 — points applied at checkout, in points (1 point = ₹1).
41
+ *
42
+ * 🛑 Subtracted from the refundable base, because **a refund can only return
43
+ * money that was collected.** On a ₹1,000 order settled with 250 points the
44
+ * card was charged ₹750; refunding the full base would hand the buyer ₹1,000
45
+ * and then `reverseRedemptionForOrder` would hand back 250 points on top —
46
+ * ₹250 of real money created out of a discount.
47
+ *
48
+ * The points themselves come back as POINTS, never as cash. That is not a
49
+ * stylistic choice: `pointsLedger`'s header states it as a legal boundary,
50
+ * because paying a balance out in rupees is what makes it stored value, which
51
+ * in India is PPI territory with RBI authorisation attached.
52
+ */
53
+ pointsApplied?: number;
39
54
  }
40
55
  /**
41
56
  * The platform fee actually withheld on a refund: the amount CHARGED, never a
@@ -77,6 +92,16 @@ legacyGstPercent?: number): number;
77
92
  * has to compare against THIS, or the largest possible refund is strictly less
78
93
  * than `totalPrice` and **an order can never reach `status: "refunded"`** —
79
94
  * which is what the old `amount >= totalPrice` test guaranteed.
95
+ *
96
+ * 🛑 And `pointsApplied` comes off too (D46/D47). A refund returns MONEY, and
97
+ * the money collected was `totalPrice − pointsApplied`; the points go back
98
+ * through `reverseRedemptionForOrder` as points. Leaving them in the base would
99
+ * refund them twice — once in rupees here and once in points there — which is
100
+ * the one way this feature could manufacture real money from a discount.
101
+ *
102
+ * Absent means zero, so every order written before the tender existed is
103
+ * unaffected, and `isFull` still reaches the exhausted state on them exactly as
104
+ * before.
80
105
  */
81
106
  export declare function refundableBase(order: RefundableOrderLike, legacyGstPercent?: number): number;
82
107
  /**
@@ -75,9 +75,21 @@ legacyGstPercent) {
75
75
  * has to compare against THIS, or the largest possible refund is strictly less
76
76
  * than `totalPrice` and **an order can never reach `status: "refunded"`** —
77
77
  * which is what the old `amount >= totalPrice` test guaranteed.
78
+ *
79
+ * 🛑 And `pointsApplied` comes off too (D46/D47). A refund returns MONEY, and
80
+ * the money collected was `totalPrice − pointsApplied`; the points go back
81
+ * through `reverseRedemptionForOrder` as points. Leaving them in the base would
82
+ * refund them twice — once in rupees here and once in points there — which is
83
+ * the one way this feature could manufacture real money from a discount.
84
+ *
85
+ * Absent means zero, so every order written before the tender existed is
86
+ * unaffected, and `isFull` still reaches the exhausted state on them exactly as
87
+ * before.
78
88
  */
79
89
  export function refundableBase(order, legacyGstPercent) {
80
- return roundRupees(Math.max(0, order.totalPrice - platformFeeWithheld(order, legacyGstPercent)));
90
+ return roundRupees(Math.max(0, order.totalPrice -
91
+ platformFeeWithheld(order, legacyGstPercent) -
92
+ Math.max(0, order.pointsApplied ?? 0)));
81
93
  }
82
94
  /**
83
95
  * Sum of refunds that have COMMITTED money, i.e. everything not `failed`.
@@ -1,6 +1,6 @@
1
1
  export type { ListingCheckoutRule, CategoryCheckoutRule, CartItemProductPair, OrderItemInput, RefundPolicy, } from "./types";
2
2
  export { CHECKOUT_RULES, CATEGORY_CHECKOUT_RULES, getListingRule, getCategoryRule, pickOrderType, getSplitKey, runSyncPreflight, } from "./_registry";
3
- export { assertPaymentMethodAllowed, blockedMethodsForCart, type BlockedMethod, } from "./payment-gate";
3
+ export { assertPaymentMethodAllowed, assertEmiOptInAllowed, blockedMethodsForCart, type BlockedMethod, } from "./payment-gate";
4
4
  export { CART_MAX_ITEMS, CHECKOUT_MAX_ORDERS_PER_TX, PRIZE_DRAW_MAX_REVEALS_PER_ORDER, PRIZE_DRAW_DURATION_DAYS_MIN, PRIZE_DRAW_DURATION_DAYS_MAX, BUNDLE_MAX_QTY_PER_TX, STANDARD_MAX_QTY_PER_LINE, } from "./_limits";
5
5
  export { standardRule } from "./standard.rule";
6
6
  export { auctionRule } from "./auction.rule";
@@ -6,7 +6,7 @@ export { CHECKOUT_RULES, CATEGORY_CHECKOUT_RULES, getListingRule, getCategoryRul
6
6
  * apart is what stops someone folding it back into preflight, where it would
7
7
  * silently stop covering bundles and grouped lines.
8
8
  */
9
- export { assertPaymentMethodAllowed, blockedMethodsForCart, } from "./payment-gate.js";
9
+ export { assertPaymentMethodAllowed, assertEmiOptInAllowed, blockedMethodsForCart, } from "./payment-gate.js";
10
10
  export { CART_MAX_ITEMS, CHECKOUT_MAX_ORDERS_PER_TX, PRIZE_DRAW_MAX_REVEALS_PER_ORDER, PRIZE_DRAW_DURATION_DAYS_MIN, PRIZE_DRAW_DURATION_DAYS_MAX, BUNDLE_MAX_QTY_PER_TX, STANDARD_MAX_QTY_PER_LINE, } from "./_limits.js";
11
11
  // Individual rules — exported for tests and direct access.
12
12
  export { standardRule } from "./standard.rule.js";
@@ -24,3 +24,21 @@ export declare function blockedMethodsForCart(items: readonly CartItemDocument[]
24
24
  * decision.
25
25
  */
26
26
  export declare function assertPaymentMethodAllowed(items: readonly CartItemDocument[], productById: ReadonlyMap<string, ProductDocument>, paymentMethod: CheckoutPaymentMethod | undefined): void;
27
+ /**
28
+ * Throw when anything in the cart forbids an instalment plan.
29
+ *
30
+ * 🛑 Reads the SAME `blockedPaymentMethods` declaration, under the key
31
+ * `"emi"`, rather than introducing a parallel `blocksEmi` field. The listing
32
+ * rules already say "this listing type cannot be paid in instalments" — they
33
+ * said it by naming a payment method, because that is what EMI was. Once EMI
34
+ * became an order-level opt-in, that declaration needed a second reader, not
35
+ * a second declaration: a rule stated twice is a rule that drifts (Root Cause
36
+ * #61), and `prizeDrawRule`'s entry would otherwise have gone inert the day
37
+ * the tender disappeared.
38
+ *
39
+ * `blockedPaymentMessage` is reused verbatim for the same reason the gate
40
+ * above prefers it to a generated sentence: it names the REASON (winner
41
+ * assignment waits on confirmed payment), which is what lets a buyer choose
42
+ * differently instead of abandoning.
43
+ */
44
+ export declare function assertEmiOptInAllowed(items: readonly CartItemDocument[], productById: ReadonlyMap<string, ProductDocument>, emiOptIn: boolean): void;
@@ -131,3 +131,28 @@ export function assertPaymentMethodAllowed(items, productById, paymentMethod) {
131
131
  ? `${offender.message} Available instead: ${allowed.join(", ")}.`
132
132
  : `${offender.message} Nothing in this cart's combination can be paid for — remove the item and buy it on its own.`), { code: "PAYMENT_METHOD_BLOCKED" });
133
133
  }
134
+ /**
135
+ * Throw when anything in the cart forbids an instalment plan.
136
+ *
137
+ * 🛑 Reads the SAME `blockedPaymentMethods` declaration, under the key
138
+ * `"emi"`, rather than introducing a parallel `blocksEmi` field. The listing
139
+ * rules already say "this listing type cannot be paid in instalments" — they
140
+ * said it by naming a payment method, because that is what EMI was. Once EMI
141
+ * became an order-level opt-in, that declaration needed a second reader, not
142
+ * a second declaration: a rule stated twice is a rule that drifts (Root Cause
143
+ * #61), and `prizeDrawRule`'s entry would otherwise have gone inert the day
144
+ * the tender disappeared.
145
+ *
146
+ * `blockedPaymentMessage` is reused verbatim for the same reason the gate
147
+ * above prefers it to a generated sentence: it names the REASON (winner
148
+ * assignment waits on confirmed payment), which is what lets a buyer choose
149
+ * differently instead of abandoning.
150
+ */
151
+ export function assertEmiOptInAllowed(items, productById, emiOptIn) {
152
+ if (!emiOptIn)
153
+ return;
154
+ const offender = blockedMethodsForCart(items, productById).get("emi");
155
+ if (!offender)
156
+ return;
157
+ throw Object.assign(new ValidationError(`${offender.message} Pay for this order in full instead, or remove the item and buy it on its own.`), { code: "EMI_NOT_ALLOWED" });
158
+ }
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Group-purchase contribution splits — the ONE owner of the invariant.
3
+ *
4
+ * A coordinator divides what a grouped line costs among its members. They may
5
+ * type absolute amounts or percentages, and the total may come out at or ABOVE
6
+ * the landed cost; the excess belongs to the seller.
7
+ *
8
+ * ## The invariant
9
+ *
10
+ * ```
11
+ * landedCost = goods + shipping + fees + add-ons (per order group)
12
+ *
13
+ * contribution(member) = percent × landedCost OR a typed amount
14
+ * require: Σ(contributions) ≥ landedCost
15
+ * surplus: Σ(contributions) − landedCost
16
+ * ```
17
+ *
18
+ * Percentages summing above 100% and typed amounts summing above the landed
19
+ * cost are **the same case**, so one rule covers both and there is no
20
+ * mode-specific branch to get wrong.
21
+ *
22
+ * ## Why the surplus becomes `lockedPrice`
23
+ *
24
+ * `unitPriceFor` already honours `lockedPrice` ahead of everything else — that
25
+ * is how an accepted offer BELOW list is charged correctly. An agreed total
26
+ * ABOVE list is the same mechanism in the other direction, so GST is charged on
27
+ * what was actually paid, the payout base rises by the surplus,
28
+ * `refundableBase` ceilings at the agreed amount, and the invoice needs no new
29
+ * line. No new money term anywhere.
30
+ */
31
+ /** A member's share, as the coordinator expressed it. */
32
+ export interface SplitContribution {
33
+ productId: string;
34
+ /** `"percent"` reads `percent`; `"amount"` reads `amount`. */
35
+ splitMode: "amount" | "percent";
36
+ /** 0–100. Required when `splitMode === "percent"`. */
37
+ percent?: number;
38
+ /** Decimal rupees. Required when `splitMode === "amount"`. */
39
+ amount?: number;
40
+ }
41
+ export interface SplitResolution {
42
+ /** Per member, in input order, after rounding. */
43
+ resolved: Array<{
44
+ productId: string;
45
+ amount: number;
46
+ }>;
47
+ /** What the members together put in. */
48
+ contributed: number;
49
+ /** `contributed − landedCost`, never negative (see `shortfall`). */
50
+ surplus: number;
51
+ /** `landedCost − contributed` when the split is short, else 0. */
52
+ shortfall: number;
53
+ /** The invariant holds. A caller must refuse to commit when false. */
54
+ valid: boolean;
55
+ }
56
+ export declare function resolveSplit(contributions: readonly SplitContribution[], landedCost: number): SplitResolution;
57
+ /**
58
+ * The price to lock on the line, given the goods subtotal and a surplus.
59
+ *
60
+ * ## 🛑 THE TRAP THIS FUNCTION EXISTS TO PREVENT
61
+ *
62
+ * The percentage BASE is the landed cost — goods **plus shipping plus fees** —
63
+ * because that is what the coordinator is really dividing. But `lockedPrice` is
64
+ * the GOODS price of the line: the checkout adds shipping, the platform fee,
65
+ * GST and the add-ons on top of it, independently.
66
+ *
67
+ * So locking the landed cost would charge shipping and every fee **TWICE** —
68
+ * once inside `lockedPrice` and once again as the checkout's own terms. The
69
+ * surplus rides on the goods price alone.
70
+ *
71
+ * That is the whole reason this is a named function rather than an expression
72
+ * at a call site: `goods + surplus` and `landedCost + surplus` are both
73
+ * plausible-looking one-liners and only one of them is a correct charge.
74
+ */
75
+ export declare function lockedPriceWithSurplus(goodsSubtotal: number, surplus: number): number;
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Group-purchase contribution splits — the ONE owner of the invariant.
3
+ *
4
+ * A coordinator divides what a grouped line costs among its members. They may
5
+ * type absolute amounts or percentages, and the total may come out at or ABOVE
6
+ * the landed cost; the excess belongs to the seller.
7
+ *
8
+ * ## The invariant
9
+ *
10
+ * ```
11
+ * landedCost = goods + shipping + fees + add-ons (per order group)
12
+ *
13
+ * contribution(member) = percent × landedCost OR a typed amount
14
+ * require: Σ(contributions) ≥ landedCost
15
+ * surplus: Σ(contributions) − landedCost
16
+ * ```
17
+ *
18
+ * Percentages summing above 100% and typed amounts summing above the landed
19
+ * cost are **the same case**, so one rule covers both and there is no
20
+ * mode-specific branch to get wrong.
21
+ *
22
+ * ## Why the surplus becomes `lockedPrice`
23
+ *
24
+ * `unitPriceFor` already honours `lockedPrice` ahead of everything else — that
25
+ * is how an accepted offer BELOW list is charged correctly. An agreed total
26
+ * ABOVE list is the same mechanism in the other direction, so GST is charged on
27
+ * what was actually paid, the payout base rises by the surplus,
28
+ * `refundableBase` ceilings at the agreed amount, and the invoice needs no new
29
+ * line. No new money term anywhere.
30
+ */
31
+ import { roundRupees } from "../../../utils/number.formatter.js";
32
+ /**
33
+ * Resolve contributions against a landed cost.
34
+ *
35
+ * Pure. No I/O, no clock — the landed cost is computed by the caller from the
36
+ * order group it already has.
37
+ *
38
+ * 🛑 ROUNDS ONCE, at the end of each member's amount, and then puts the
39
+ * ROUNDING REMAINDER on the last member. Rounding each percentage
40
+ * independently and summing is how a 3-way 33.33% split charges a rupee less
41
+ * than the agreed total and the surplus silently goes negative — the same
42
+ * remainder discipline `allocateAcrossMembers` uses for bundle tax.
43
+ */
44
+ /**
45
+ * `percent` of `amount`, where `percent` is 0–100.
46
+ *
47
+ * 🛑 A NAMED HELPER rather than the division written inline, for legibility
48
+ * to a reader AND to `audit-money-units`. That audit flags a scale division
49
+ * beside a money identifier because it is the exact shape of the 2026-05
50
+ * minor-unit bug — a conversion left behind by a migration — and a
51
+ * percentage conversion is visually identical to it. Two such lines are two
52
+ * judgement calls; one helper is a single place to establish that this
53
+ * divisor is about PERCENTAGES and never about currency scale.
54
+ *
55
+ * 🛑 That audit reads COMMENTS as well as code, so this one cannot quote the
56
+ * expression it is about: a worked example of the shape is indistinguishable
57
+ * from the shape. Reading comments is correct of it — a stale "stored in
58
+ * minor units" remark in prose is one of the things it hunts, and Root Cause
59
+ * #87 is the opposite mistake, an audit that stripped comments and so
60
+ * counted a commented-out registration as live.
61
+ */
62
+ // audit-money-units-ok: a percent-to-fraction conversion, not a minor-unit conversion
63
+ const applyPercent = (percent, amount) => (percent / 100) * amount;
64
+ export function resolveSplit(contributions, landedCost) {
65
+ const resolved = [];
66
+ for (const c of contributions) {
67
+ const raw = c.splitMode === "percent" ? applyPercent(c.percent ?? 0, landedCost) : (c.amount ?? 0);
68
+ resolved.push({ productId: c.productId, amount: roundRupees(raw) });
69
+ }
70
+ /*
71
+ * The remainder goes on the LAST member rather than being spread, so the
72
+ * parts reconcile to the total exactly and the discrepancy is one member's
73
+ * single rupee rather than a fraction on everybody.
74
+ *
75
+ * Only for a pure PERCENT split: typed amounts are what the coordinator
76
+ * actually said, and silently adjusting one of them would charge somebody a
77
+ * figure they did not enter.
78
+ */
79
+ const allPercent = contributions.every((c) => c.splitMode === "percent");
80
+ if (allPercent && resolved.length > 0) {
81
+ const pctTotal = contributions.reduce((s, c) => s + (c.percent ?? 0), 0);
82
+ const target = roundRupees(applyPercent(pctTotal, landedCost));
83
+ const sum = resolved.reduce((s, r) => s + r.amount, 0);
84
+ const drift = roundRupees(target - sum);
85
+ if (drift !== 0) {
86
+ const last = resolved[resolved.length - 1];
87
+ resolved[resolved.length - 1] = { ...last, amount: roundRupees(last.amount + drift) };
88
+ }
89
+ }
90
+ const contributed = roundRupees(resolved.reduce((s, r) => s + r.amount, 0));
91
+ const diff = roundRupees(contributed - landedCost);
92
+ return {
93
+ resolved,
94
+ contributed,
95
+ surplus: diff > 0 ? diff : 0,
96
+ shortfall: diff < 0 ? -diff : 0,
97
+ valid: diff >= 0,
98
+ };
99
+ }
100
+ /**
101
+ * The price to lock on the line, given the goods subtotal and a surplus.
102
+ *
103
+ * ## 🛑 THE TRAP THIS FUNCTION EXISTS TO PREVENT
104
+ *
105
+ * The percentage BASE is the landed cost — goods **plus shipping plus fees** —
106
+ * because that is what the coordinator is really dividing. But `lockedPrice` is
107
+ * the GOODS price of the line: the checkout adds shipping, the platform fee,
108
+ * GST and the add-ons on top of it, independently.
109
+ *
110
+ * So locking the landed cost would charge shipping and every fee **TWICE** —
111
+ * once inside `lockedPrice` and once again as the checkout's own terms. The
112
+ * surplus rides on the goods price alone.
113
+ *
114
+ * That is the whole reason this is a named function rather than an expression
115
+ * at a call site: `goods + surplus` and `landedCost + surplus` are both
116
+ * plausible-looking one-liners and only one of them is a correct charge.
117
+ */
118
+ export function lockedPriceWithSurplus(goodsSubtotal, surplus) {
119
+ return roundRupees(goodsSubtotal + surplus);
120
+ }
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Disclaimers — one registry, rendered by `<Disclaimer id>` (Phase 12).
3
+ *
4
+ * ## 🛑 Why a registry and not a sentence per surface
5
+ *
6
+ * Same failure mode as the published numbers in Phase 9: if each surface
7
+ * writes its own, they drift, and **the legally material ones end up
8
+ * weakest** — because the surface that most needs a careful disclaimer is
9
+ * usually the one whose author was busiest. The scam registry is the example:
10
+ * naming a person a scammer is defamation exposure, and it had no disclaimer
11
+ * at all.
12
+ *
13
+ * ## The three rules every entry obeys
14
+ *
15
+ * 1. **Visible BEFORE the decision it qualifies**, not only on a policy page
16
+ * reachable from the footer. The protection disclaimer belongs beside the
17
+ * checkbox, not in `/refund-policy`.
18
+ * 2. **It names a LIMIT or an EXCLUSION.** A disclaimer that only says "we
19
+ * try our best" qualifies nothing and is worse than none — it reads as
20
+ * cover while providing none.
21
+ * 3. **It AGREES with the code.** Limits render from the constants that
22
+ * enforce them (`SALE_PROTECTION_MAX_VALUE`, the claim windows), through
23
+ * the same `{{token}}` mechanism as Phase 9, so a constant change updates
24
+ * the published terms rather than contradicting them.
25
+ *
26
+ * ## 🛑 NOT a cookie-banner blanket
27
+ *
28
+ * A disclaimer that appears everywhere is read nowhere. Each entry names the
29
+ * specific surfaces that need it, and `audit-disclaimer-coverage` checks those
30
+ * surfaces render one — not that every page does.
31
+ */
32
+ export type DisclaimerId =
33
+ /** Naming a person a scammer. The highest-exposure entry in this file. */
34
+ "scam-registry"
35
+ /** Prize draws and the lottery — state-specific gaming law. */
36
+ | "prize-draw"
37
+ /** Collectibles shown with historical prices. */
38
+ | "not-investment-advice"
39
+ /** The realised-price index. */
40
+ | "price-index"
41
+ /** Authenticity and grading. */
42
+ | "authenticity"
43
+ /** Buyer protection cover — OUR cover, not insurance. */
44
+ | "protection-cover"
45
+ /** P&L, trial balance, GSTR-1 draft. */
46
+ | "accounting-output"
47
+ /** Live animals and plants. */
48
+ | "live-items"
49
+ /** Pre-orders. */
50
+ | "pre-order"
51
+ /** Auctions. */
52
+ | "auction-binding"
53
+ /** EMI. */
54
+ | "emi"
55
+ /** Delivery estimates. */
56
+ | "delivery-estimate"
57
+ /** Reviews, catalogue entries, blog comments. */
58
+ | "user-content"
59
+ /** GST shown on an invoice. */
60
+ | "tax-computation"
61
+ /** An automated decision — a timer cancelled, approved or completed something. */
62
+ | "automated-decision";
63
+ export interface DisclaimerEntry {
64
+ /** Short heading, when the surface renders one. Omit for inline notes. */
65
+ heading?: string;
66
+ /**
67
+ * The text. May contain `{{token}}`s resolved by `resolvePublishedCopy`.
68
+ *
69
+ * 🛑 Must name a limit or an exclusion — see rule 2 in the header. An entry
70
+ * that does not is not a disclaimer, and `audit-disclaimer-coverage` checks
71
+ * for it rather than trusting the author.
72
+ */
73
+ body: string;
74
+ /**
75
+ * Tone, which decides the rendered variant.
76
+ *
77
+ * `legal` is the quiet grey note; `warning` is the one a user must not scroll
78
+ * past. 🛑 Reserved for the entries where ignoring it has a consequence the
79
+ * user cannot undo — not used to make a disclaimer feel important.
80
+ */
81
+ tone: "legal" | "warning";
82
+ /**
83
+ * Where this must appear, as a free-text note for the reviewer and the
84
+ * audit's own registry.
85
+ */
86
+ surfaces: readonly string[];
87
+ }
88
+ export declare const DISCLAIMERS: Record<DisclaimerId, DisclaimerEntry>;