@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
@@ -0,0 +1,170 @@
1
+ /**
2
+ * What each business event posts.
3
+ *
4
+ * ## 🛑 THIS FILE IS THE WHOLE SAFETY ARGUMENT
5
+ *
6
+ * "Every journal entry is machine-generated from a business event" is the
7
+ * one constraint that makes a ledger maintained by a web application
8
+ * trustworthy. If a human has to remember that a gateway fee is
9
+ * `Dr Bank Charges / Cr Bank`, it will eventually be posted backwards — and
10
+ * a backwards entry still balances, so nothing downstream objects. These
11
+ * functions are where that memory lives instead.
12
+ *
13
+ * Pure, and returning a `PostingInput` rather than writing: the caller hands
14
+ * the result to `journalRepository.post`, which is the only thing that
15
+ * touches Firestore and the only thing that checks the period lock. That
16
+ * separation is also what lets `verify-posting-rules` exercise the rules
17
+ * against real order shapes without a database.
18
+ *
19
+ * ## 🛑 Codes are referenced through ACCOUNT, never as bare strings
20
+ *
21
+ * A literal `"2200"` scattered across six rules is six chances to type
22
+ * `"2000"`, and a posting to an account that does not exist is silently
23
+ * dropped from the P&L by `profitAndLoss`'s unknown-account skip. One map,
24
+ * named, so a wrong code is a compile error.
25
+ */
26
+ import type { PostingInput } from "./posting";
27
+ import type { ExpenseCategory } from "../../../../features/ledger/schemas/expenses";
28
+ /** The accounts these rules post to. Codes match `chartOfAccountsSeedData`. */
29
+ export declare const ACCOUNT: {
30
+ readonly BANK: "1100";
31
+ readonly COURIER_FLOAT: "1150";
32
+ readonly GATEWAY_RECEIVABLE: "1200";
33
+ readonly INPUT_GST: "1300";
34
+ readonly SELLER_PAYABLE: "2100";
35
+ readonly ACCOUNTS_PAYABLE: "2300";
36
+ readonly OUTPUT_GST: "2200";
37
+ readonly BUYER_DEPOSITS: "2400";
38
+ readonly REFUNDS_PAYABLE: "2500";
39
+ readonly OPENING_EQUITY: "3900";
40
+ readonly COMMISSION_INCOME: "4100";
41
+ readonly SHIPPING_RECOVERED: "4200";
42
+ readonly ADDON_INCOME: "4300";
43
+ readonly GATEWAY_CHARGES: "5100";
44
+ readonly FREIGHT_PAID: "5200";
45
+ };
46
+ export interface OrderPostingInput {
47
+ orderId: string;
48
+ storeId: string;
49
+ placedAt: Date;
50
+ /** What the buyer paid in total, GST included. */
51
+ totalPrice: number;
52
+ /** Product GST inside `totalPrice`. */
53
+ gstAmount?: number;
54
+ /** Our commission, and the GST we charge on it. */
55
+ platformFee?: number;
56
+ platformFeeGst?: number;
57
+ /** What the buyer paid for delivery, inside `totalPrice`. */
58
+ shippingFee?: number;
59
+ /** Gift wrap, protection, WhatsApp — inside `totalPrice`. */
60
+ addonFees?: number;
61
+ }
62
+ /**
63
+ * A paid order.
64
+ *
65
+ * 🛑 **The seller payable is the RESIDUAL, not a computed share.** Everything
66
+ * the platform keeps is recognised explicitly — commission, its GST, the
67
+ * shipping the buyer paid, add-ons, and output GST — and what remains is what
68
+ * the seller is owed. Computing the seller's share independently and letting
69
+ * the two meet in the middle is how a rounding difference becomes an
70
+ * unbalanced entry that `assertBalanced` then refuses at checkout, turning a
71
+ * half-paisa into a failed order.
72
+ *
73
+ * 🛑 **Output GST is a LIABILITY, which is the entire point of the exercise.**
74
+ * `revenueRollup.totalRevenue` sums `order.totalPrice`, so today's "revenue"
75
+ * includes tax owed to the government and freight owed to a courier. Crediting
76
+ * 2200 here is what separates turnover from takings for the first time.
77
+ *
78
+ * 🛑 The debit is to GATEWAY RECEIVABLE, not Bank. Money captured is not
79
+ * money arrived — the settlement lands days later, net of MDR, and
80
+ * `settlementPosting` is what clears this account. Debiting Bank here would
81
+ * overstate cash by the whole float for the length of the settlement cycle.
82
+ */
83
+ export declare function orderPlacedPosting(o: OrderPostingInput): PostingInput;
84
+ export interface SettlementPostingInput {
85
+ settlementId: string;
86
+ settledAt: Date;
87
+ /** Gross captured in this settlement, matching what was debited to 1200. */
88
+ gross: number;
89
+ /** The gateway's real MDR for it. */
90
+ fee: number;
91
+ /** GST on that fee — an INPUT credit, not a cost. */
92
+ feeGst: number;
93
+ }
94
+ /**
95
+ * A gateway settlement arriving in the bank.
96
+ *
97
+ * 🛑 `fee` here is the gateway's REAL charge from the settlement report, and
98
+ * it is NOT `PayoutDocument.gatewayFee` — that field is our own withholding
99
+ * against a seller's gross, a different number with a different meaning.
100
+ * Posting one as the other overstates our costs and understates what we
101
+ * withheld, in opposite directions, so the error compounds.
102
+ *
103
+ * 🛑 The GST on the fee is an ASSET (input credit), not an expense. Nothing
104
+ * in this codebase could receive input tax before Part 4, so this was simply
105
+ * unrecoverable — which is money, every month, that was never claimable.
106
+ */
107
+ export declare function settlementPosting(s: SettlementPostingInput): PostingInput;
108
+ export interface PayoutPostingInput {
109
+ payoutId: string;
110
+ storeId: string;
111
+ paidAt: Date;
112
+ amount: number;
113
+ }
114
+ /**
115
+ * Paying a seller.
116
+ *
117
+ * Clears the payable raised at order time against real cash. Two legs and no
118
+ * income or expense — paying a debt is not a cost, and treating it as one
119
+ * double-counts every sale.
120
+ */
121
+ export declare function payoutPosting(p: PayoutPostingInput): PostingInput;
122
+ export interface ExpensePostingInput {
123
+ expenseId: string;
124
+ vendorId?: string;
125
+ vendorName: string;
126
+ category: ExpenseCategory;
127
+ billDate: Date;
128
+ amount: number;
129
+ inputGst?: number;
130
+ /** Paid outright, or on credit? Decides the funding leg. */
131
+ paid: boolean;
132
+ }
133
+ /**
134
+ * A bill.
135
+ *
136
+ * 🛑 The funding leg depends on whether it was PAID, and conflating the two
137
+ * is the commonest small-business bookkeeping error: crediting Bank for a
138
+ * bill not yet paid shows cash leaving that is still there, and crediting
139
+ * Accounts payable for one already settled leaves a debt that does not
140
+ * exist. Both balance; both are wrong; neither announces itself.
141
+ *
142
+ * 🛑 `inputGst` is DEBITED to an asset, never added to the cost. Expensing
143
+ * it is how input credit silently stops being claimable — the money is
144
+ * spent either way, but only one of the two gets it back.
145
+ */
146
+ export declare function expensePosting(e: ExpensePostingInput): PostingInput;
147
+ export interface RefundPostingInput {
148
+ orderId: string;
149
+ refundId: string;
150
+ refundedAt: Date;
151
+ amount: number;
152
+ /** The product GST inside the refunded amount, which is reclaimable. */
153
+ gstAmount?: number;
154
+ }
155
+ /**
156
+ * A refund.
157
+ *
158
+ * 🛑 **A refund is NOT a negative sale, and that distinction is why the top
159
+ * line is currently wrong.** `revenueRollup` removes a fully-refunded order
160
+ * from its sum entirely and does not reduce it at all for a partial — so
161
+ * revenue silently rewrites itself retroactively, and no two runs of the same
162
+ * report over the same period agree.
163
+ *
164
+ * Here it is its own event with its own date: the sale stays in the month it
165
+ * happened, the refund lands in the month it happened, and both are visible.
166
+ *
167
+ * 🛑 It DEBITS output GST, reclaiming tax already declared. Omitting that leg
168
+ * means paying GST on money that was given back.
169
+ */
170
+ export declare function refundPosting(r: RefundPostingInput): PostingInput;
@@ -0,0 +1,221 @@
1
+ /**
2
+ * What each business event posts.
3
+ *
4
+ * ## 🛑 THIS FILE IS THE WHOLE SAFETY ARGUMENT
5
+ *
6
+ * "Every journal entry is machine-generated from a business event" is the
7
+ * one constraint that makes a ledger maintained by a web application
8
+ * trustworthy. If a human has to remember that a gateway fee is
9
+ * `Dr Bank Charges / Cr Bank`, it will eventually be posted backwards — and
10
+ * a backwards entry still balances, so nothing downstream objects. These
11
+ * functions are where that memory lives instead.
12
+ *
13
+ * Pure, and returning a `PostingInput` rather than writing: the caller hands
14
+ * the result to `journalRepository.post`, which is the only thing that
15
+ * touches Firestore and the only thing that checks the period lock. That
16
+ * separation is also what lets `verify-posting-rules` exercise the rules
17
+ * against real order shapes without a database.
18
+ *
19
+ * ## 🛑 Codes are referenced through ACCOUNT, never as bare strings
20
+ *
21
+ * A literal `"2200"` scattered across six rules is six chances to type
22
+ * `"2000"`, and a posting to an account that does not exist is silently
23
+ * dropped from the P&L by `profitAndLoss`'s unknown-account skip. One map,
24
+ * named, so a wrong code is a compile error.
25
+ */
26
+ /** The accounts these rules post to. Codes match `chartOfAccountsSeedData`. */
27
+ export const ACCOUNT = {
28
+ BANK: "1100",
29
+ COURIER_FLOAT: "1150",
30
+ GATEWAY_RECEIVABLE: "1200",
31
+ INPUT_GST: "1300",
32
+ SELLER_PAYABLE: "2100",
33
+ ACCOUNTS_PAYABLE: "2300",
34
+ OUTPUT_GST: "2200",
35
+ BUYER_DEPOSITS: "2400",
36
+ REFUNDS_PAYABLE: "2500",
37
+ OPENING_EQUITY: "3900",
38
+ COMMISSION_INCOME: "4100",
39
+ SHIPPING_RECOVERED: "4200",
40
+ ADDON_INCOME: "4300",
41
+ GATEWAY_CHARGES: "5100",
42
+ FREIGHT_PAID: "5200",
43
+ };
44
+ /** Drop legs that rounded to nothing, so a zero fee does not fail `assertBalanced`. */
45
+ function compact(lines) {
46
+ return lines.filter((l) => (l.debit ?? 0) !== 0 || (l.credit ?? 0) !== 0);
47
+ }
48
+ const r2 = (n) => Math.round((n ?? 0) * 100) / 100;
49
+ /**
50
+ * A paid order.
51
+ *
52
+ * 🛑 **The seller payable is the RESIDUAL, not a computed share.** Everything
53
+ * the platform keeps is recognised explicitly — commission, its GST, the
54
+ * shipping the buyer paid, add-ons, and output GST — and what remains is what
55
+ * the seller is owed. Computing the seller's share independently and letting
56
+ * the two meet in the middle is how a rounding difference becomes an
57
+ * unbalanced entry that `assertBalanced` then refuses at checkout, turning a
58
+ * half-paisa into a failed order.
59
+ *
60
+ * 🛑 **Output GST is a LIABILITY, which is the entire point of the exercise.**
61
+ * `revenueRollup.totalRevenue` sums `order.totalPrice`, so today's "revenue"
62
+ * includes tax owed to the government and freight owed to a courier. Crediting
63
+ * 2200 here is what separates turnover from takings for the first time.
64
+ *
65
+ * 🛑 The debit is to GATEWAY RECEIVABLE, not Bank. Money captured is not
66
+ * money arrived — the settlement lands days later, net of MDR, and
67
+ * `settlementPosting` is what clears this account. Debiting Bank here would
68
+ * overstate cash by the whole float for the length of the settlement cycle.
69
+ */
70
+ export function orderPlacedPosting(o) {
71
+ const commission = r2(o.platformFee ?? 0);
72
+ const commissionGst = r2(o.platformFeeGst ?? 0);
73
+ const shipping = r2(o.shippingFee ?? 0);
74
+ const addons = r2(o.addonFees ?? 0);
75
+ const outputGst = r2((o.gstAmount ?? 0) + commissionGst);
76
+ const sellerPayable = r2(o.totalPrice - commission - commissionGst - shipping - addons - (o.gstAmount ?? 0));
77
+ return {
78
+ entryDate: o.placedAt,
79
+ sourceEvent: "order-placed",
80
+ sourceId: o.orderId,
81
+ narration: `Order ${o.orderId}`,
82
+ lines: compact([
83
+ { accountCode: ACCOUNT.GATEWAY_RECEIVABLE, debit: r2(o.totalPrice), credit: 0, memo: "Captured, awaiting settlement" },
84
+ { accountCode: ACCOUNT.SELLER_PAYABLE, debit: 0, credit: sellerPayable, counterpartyId: o.storeId, memo: "Owed to the seller" },
85
+ { accountCode: ACCOUNT.OUTPUT_GST, debit: 0, credit: outputGst, memo: "Tax collected, owed to the government" },
86
+ { accountCode: ACCOUNT.COMMISSION_INCOME, debit: 0, credit: commission },
87
+ { accountCode: ACCOUNT.SHIPPING_RECOVERED, debit: 0, credit: shipping },
88
+ { accountCode: ACCOUNT.ADDON_INCOME, debit: 0, credit: addons },
89
+ ]),
90
+ };
91
+ }
92
+ /**
93
+ * A gateway settlement arriving in the bank.
94
+ *
95
+ * 🛑 `fee` here is the gateway's REAL charge from the settlement report, and
96
+ * it is NOT `PayoutDocument.gatewayFee` — that field is our own withholding
97
+ * against a seller's gross, a different number with a different meaning.
98
+ * Posting one as the other overstates our costs and understates what we
99
+ * withheld, in opposite directions, so the error compounds.
100
+ *
101
+ * 🛑 The GST on the fee is an ASSET (input credit), not an expense. Nothing
102
+ * in this codebase could receive input tax before Part 4, so this was simply
103
+ * unrecoverable — which is money, every month, that was never claimable.
104
+ */
105
+ export function settlementPosting(s) {
106
+ const net = r2(s.gross - s.fee - s.feeGst);
107
+ return {
108
+ entryDate: s.settledAt,
109
+ sourceEvent: "settlement-ingest",
110
+ sourceId: s.settlementId,
111
+ narration: `Settlement ${s.settlementId}`,
112
+ lines: compact([
113
+ { accountCode: ACCOUNT.BANK, debit: net, credit: 0 },
114
+ { accountCode: ACCOUNT.GATEWAY_CHARGES, debit: r2(s.fee), credit: 0, memo: "MDR from the settlement report" },
115
+ { accountCode: ACCOUNT.INPUT_GST, debit: r2(s.feeGst), credit: 0, memo: "ITC on the gateway fee" },
116
+ { accountCode: ACCOUNT.GATEWAY_RECEIVABLE, debit: 0, credit: r2(s.gross) },
117
+ ]),
118
+ };
119
+ }
120
+ /**
121
+ * Paying a seller.
122
+ *
123
+ * Clears the payable raised at order time against real cash. Two legs and no
124
+ * income or expense — paying a debt is not a cost, and treating it as one
125
+ * double-counts every sale.
126
+ */
127
+ export function payoutPosting(p) {
128
+ return {
129
+ entryDate: p.paidAt,
130
+ sourceEvent: "payout-paid",
131
+ sourceId: p.payoutId,
132
+ narration: `Payout ${p.payoutId} to ${p.storeId}`,
133
+ lines: [
134
+ { accountCode: ACCOUNT.SELLER_PAYABLE, debit: r2(p.amount), credit: 0, counterpartyId: p.storeId },
135
+ { accountCode: ACCOUNT.BANK, debit: 0, credit: r2(p.amount) },
136
+ ],
137
+ };
138
+ }
139
+ /**
140
+ * Which expense account each category posts to.
141
+ *
142
+ * 🛑 A `Record<ExpenseCategory, …>`, so adding a category is a COMPILE
143
+ * ERROR until someone says where it lands. The alternative — a lookup with
144
+ * a default — silently files every new kind of spend into "other", and
145
+ * "other" growing is indistinguishable from nobody having noticed.
146
+ *
147
+ * 🛑 `asset` maps to a BALANCE-SHEET account, not an expense, and that is
148
+ * the one entry here that changes a P&L. A camera bought for ₹80,000 is not
149
+ * an ₹80,000 trading loss in the month it was bought; depreciation is the
150
+ * CA's and this system deliberately does not attempt it.
151
+ */
152
+ const EXPENSE_ACCOUNT = {
153
+ freight: ACCOUNT.FREIGHT_PAID,
154
+ "platform-software": "5500",
155
+ wages: "5400",
156
+ packaging: "5900",
157
+ asset: "1500",
158
+ other: "5900",
159
+ };
160
+ /**
161
+ * A bill.
162
+ *
163
+ * 🛑 The funding leg depends on whether it was PAID, and conflating the two
164
+ * is the commonest small-business bookkeeping error: crediting Bank for a
165
+ * bill not yet paid shows cash leaving that is still there, and crediting
166
+ * Accounts payable for one already settled leaves a debt that does not
167
+ * exist. Both balance; both are wrong; neither announces itself.
168
+ *
169
+ * 🛑 `inputGst` is DEBITED to an asset, never added to the cost. Expensing
170
+ * it is how input credit silently stops being claimable — the money is
171
+ * spent either way, but only one of the two gets it back.
172
+ */
173
+ export function expensePosting(e) {
174
+ const net = r2(e.amount);
175
+ const gst = r2(e.inputGst ?? 0);
176
+ return {
177
+ entryDate: e.billDate,
178
+ sourceEvent: "expense-recorded",
179
+ sourceId: e.expenseId,
180
+ narration: `${e.vendorName} — ${e.category}`,
181
+ lines: compact([
182
+ { accountCode: EXPENSE_ACCOUNT[e.category], debit: net, credit: 0, ...(e.vendorId ? { counterpartyId: e.vendorId } : {}) },
183
+ { accountCode: ACCOUNT.INPUT_GST, debit: gst, credit: 0, memo: "ITC on this bill" },
184
+ {
185
+ accountCode: e.paid ? ACCOUNT.BANK : ACCOUNT.ACCOUNTS_PAYABLE,
186
+ debit: 0,
187
+ credit: r2(net + gst),
188
+ ...(e.vendorId ? { counterpartyId: e.vendorId } : {}),
189
+ },
190
+ ]),
191
+ };
192
+ }
193
+ /**
194
+ * A refund.
195
+ *
196
+ * 🛑 **A refund is NOT a negative sale, and that distinction is why the top
197
+ * line is currently wrong.** `revenueRollup` removes a fully-refunded order
198
+ * from its sum entirely and does not reduce it at all for a partial — so
199
+ * revenue silently rewrites itself retroactively, and no two runs of the same
200
+ * report over the same period agree.
201
+ *
202
+ * Here it is its own event with its own date: the sale stays in the month it
203
+ * happened, the refund lands in the month it happened, and both are visible.
204
+ *
205
+ * 🛑 It DEBITS output GST, reclaiming tax already declared. Omitting that leg
206
+ * means paying GST on money that was given back.
207
+ */
208
+ export function refundPosting(r) {
209
+ const gst = r2(r.gstAmount ?? 0);
210
+ return {
211
+ entryDate: r.refundedAt,
212
+ sourceEvent: "order-refunded",
213
+ sourceId: r.refundId,
214
+ narration: `Refund ${r.refundId} on order ${r.orderId}`,
215
+ lines: compact([
216
+ { accountCode: ACCOUNT.COMMISSION_INCOME, debit: r2(r.amount - gst), credit: 0, memo: "Sale reversed" },
217
+ { accountCode: ACCOUNT.OUTPUT_GST, debit: gst, credit: 0, memo: "Tax reclaimed on the refunded amount" },
218
+ { accountCode: ACCOUNT.REFUNDS_PAYABLE, debit: 0, credit: r2(r.amount) },
219
+ ]),
220
+ };
221
+ }
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Coordinated purchase — several people chipping in on one listing.
3
+ *
4
+ * ## 🛑 It is a SPECIALISED OFFER. Almost nothing here is new.
5
+ *
6
+ * Owner, 2026-10-22: *"it is not a variant, it is similar to an offer, which
7
+ * the seller enables on the listing, then the customer can coordinate on it,
8
+ * it is a specialized offer."*
9
+ *
10
+ * What that framing DELETES is the valuable part, because every one of these
11
+ * is a thing somebody would otherwise build:
12
+ *
13
+ * | Looks required | Actually |
14
+ * |---|---|
15
+ * | a 7th `OrderSourceContext` variant | none — it is `offer-accepted`, and the provenance card renders that branch already |
16
+ * | an `orderType` tab | none — the Offer-wins tab covers it |
17
+ * | a commit / settlement path | the offer lifecycle: `made → countered → accepted → paid`, with its chain fields, `checkoutDeadline` and lapse sweep |
18
+ * | a new money term | none — `unitPriceFor` honours `lockedPrice`, so tax, payout base, refund ceiling and the invoice all follow |
19
+ * | a cart lane | none — the existing `offer` lane, not locked, lapsing at `checkoutDeadline` |
20
+ *
21
+ * So this module holds exactly two things the offer did not already have: WHO
22
+ * is chipping in and how much, and WHERE each of them wants their parcel.
23
+ *
24
+ * The arithmetic is Part 2's and is not re-derived here — `resolveSplit` and
25
+ * `lockedPriceWithSurplus` live in `checkout/split.ts`, already committed,
26
+ * already carrying the rounding-remainder discipline and the
27
+ * goods-not-landed-cost argument that makes the surplus a correct charge.
28
+ */
29
+ import type { SplitContribution } from "../../checkout/split";
30
+ /**
31
+ * 🛑 FIVE, and the ceiling is about carrier quotes rather than taste.
32
+ *
33
+ * Each distinct destination needs its own `Shipment` and its own real
34
+ * `checkServiceability` call, so members multiply outbound API calls on a
35
+ * path a buyer is waiting on — against Rule #6's ~3-round-trip budget and a
36
+ * 10s function ceiling. Five is what fits with room for the rest of checkout.
37
+ *
38
+ * It is NOT a statement that six people may not club together; it is the
39
+ * number of parcels one offer can quote for synchronously. Raising it means
40
+ * moving quoting off the request path first.
41
+ */
42
+ export declare const SHARED_PURCHASE_MAX_MEMBERS = 5;
43
+ /**
44
+ * One contributor.
45
+ *
46
+ * ## 🛑 There is deliberately NO member NAME field
47
+ *
48
+ * 🛑 **CORRECTED — the reason first given here was false.** It said
49
+ * `encryptPiiFields` *"is a FLAT top-level loop that never descends into
50
+ * arrays"*, taken from CLAUDE.md and wrong: the function handles dotted paths
51
+ * and `array[].key` via `encryptInArray`, and `CONVERSATION_PII_FIELDS` ships
52
+ * `"lastMessage.body"` in production.
53
+ *
54
+ * The real argument is narrower and still decisive. The encryptor does not
55
+ * INFER — a field is protected only where it is NAMED, in notation matching
56
+ * the object the list is applied to. So a `name` here would need
57
+ * `"coordination.members[].name"` in `OFFER_PII_FIELDS`, and the near-miss
58
+ * `"name"` would read as covered in review while storing plaintext: both are
59
+ * `string`, and `Encrypted<string>` is erased at runtime.
60
+ *
61
+ * A member is a uid; names resolve from it at render time. That costs one
62
+ * lookup the renderer was making anyway and removes the field from the
63
+ * document entirely, which is stronger than encrypting it — there is nothing
64
+ * to classify, nothing to retain, and nothing to get the notation wrong for.
65
+ */
66
+ export interface CoordinationMember extends SplitContribution {
67
+ /** Firebase Auth uid of the person chipping in. */
68
+ uid: string;
69
+ /**
70
+ * WHERE this member's parcel goes — an ID into `addresses`, never a copy.
71
+ *
72
+ * 🛑 **A reference, and this is not a style preference.** Copying the
73
+ * address inline would put a name, a phone number and a street into the
74
+ * offer document — a cart-adjacent record with no encryption story and no
75
+ * retention story, which is two new obligations to serve one picker.
76
+ *
77
+ * 🛑 **The id MUST be verified server-side to belong to the submitting
78
+ * buyer.** An id is guessable in a way an address is not: without the check,
79
+ * a member supplies any `addresses` document id and the parcel ships to a
80
+ * stranger's house at the coordinator's expense. See `assertOwnedAddresses`.
81
+ *
82
+ * Absent means "same as the coordinator's" — one parcel, which is the
83
+ * ordinary case and must not require every member to pick.
84
+ */
85
+ destinationAddressId?: string;
86
+ }
87
+ export interface OfferCoordination {
88
+ /**
89
+ * The coordinator is the offer's own `buyerUid` and is NOT repeated here.
90
+ *
91
+ * A second copy is a mirror, and a mirror drifts the first time a write
92
+ * path sets one and not the other (Root Cause #42). The coordinator is also
93
+ * a contributing member, so they appear in `members` like everyone else —
94
+ * what makes them the coordinator is owning the offer.
95
+ */
96
+ members: CoordinationMember[];
97
+ /**
98
+ * The landed cost the split was resolved against, snapshotted at the moment
99
+ * the coordinator committed.
100
+ *
101
+ * 🛑 Snapshotted, not recomputed. Shipping and fees move; a split agreed on
102
+ * Monday must still mean the same amounts on Friday, and recomputing would
103
+ * silently re-divide what people already agreed to pay.
104
+ */
105
+ landedCostAtSplit: number;
106
+ /** `contributed − landedCostAtSplit`, which rides on `lockedPrice`. */
107
+ surplus: number;
108
+ }
109
+ /**
110
+ * Is this set of members committable?
111
+ *
112
+ * Returns a MESSAGE rather than a boolean, for the same reason
113
+ * `rejectRateChange` does: "too many members" and "the split is short" need
114
+ * different corrections, and a bare `false` makes the form guess.
115
+ *
116
+ * 🛑 It does NOT check the split arithmetic — `resolveSplit` owns that, and
117
+ * duplicating the `Σ(contributions) ≥ landedCost` test here would be a second
118
+ * implementation of the one invariant Part 2 exists to hold.
119
+ */
120
+ export declare function rejectCoordination(members: readonly CoordinationMember[]): string | null;
121
+ /** The distinct destinations this offer will have to ship to. */
122
+ export declare function destinationIds(members: readonly CoordinationMember[]): string[];
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Coordinated purchase — several people chipping in on one listing.
3
+ *
4
+ * ## 🛑 It is a SPECIALISED OFFER. Almost nothing here is new.
5
+ *
6
+ * Owner, 2026-10-22: *"it is not a variant, it is similar to an offer, which
7
+ * the seller enables on the listing, then the customer can coordinate on it,
8
+ * it is a specialized offer."*
9
+ *
10
+ * What that framing DELETES is the valuable part, because every one of these
11
+ * is a thing somebody would otherwise build:
12
+ *
13
+ * | Looks required | Actually |
14
+ * |---|---|
15
+ * | a 7th `OrderSourceContext` variant | none — it is `offer-accepted`, and the provenance card renders that branch already |
16
+ * | an `orderType` tab | none — the Offer-wins tab covers it |
17
+ * | a commit / settlement path | the offer lifecycle: `made → countered → accepted → paid`, with its chain fields, `checkoutDeadline` and lapse sweep |
18
+ * | a new money term | none — `unitPriceFor` honours `lockedPrice`, so tax, payout base, refund ceiling and the invoice all follow |
19
+ * | a cart lane | none — the existing `offer` lane, not locked, lapsing at `checkoutDeadline` |
20
+ *
21
+ * So this module holds exactly two things the offer did not already have: WHO
22
+ * is chipping in and how much, and WHERE each of them wants their parcel.
23
+ *
24
+ * The arithmetic is Part 2's and is not re-derived here — `resolveSplit` and
25
+ * `lockedPriceWithSurplus` live in `checkout/split.ts`, already committed,
26
+ * already carrying the rounding-remainder discipline and the
27
+ * goods-not-landed-cost argument that makes the surplus a correct charge.
28
+ */
29
+ /**
30
+ * 🛑 FIVE, and the ceiling is about carrier quotes rather than taste.
31
+ *
32
+ * Each distinct destination needs its own `Shipment` and its own real
33
+ * `checkServiceability` call, so members multiply outbound API calls on a
34
+ * path a buyer is waiting on — against Rule #6's ~3-round-trip budget and a
35
+ * 10s function ceiling. Five is what fits with room for the rest of checkout.
36
+ *
37
+ * It is NOT a statement that six people may not club together; it is the
38
+ * number of parcels one offer can quote for synchronously. Raising it means
39
+ * moving quoting off the request path first.
40
+ */
41
+ export const SHARED_PURCHASE_MAX_MEMBERS = 5;
42
+ /**
43
+ * Is this set of members committable?
44
+ *
45
+ * Returns a MESSAGE rather than a boolean, for the same reason
46
+ * `rejectRateChange` does: "too many members" and "the split is short" need
47
+ * different corrections, and a bare `false` makes the form guess.
48
+ *
49
+ * 🛑 It does NOT check the split arithmetic — `resolveSplit` owns that, and
50
+ * duplicating the `Σ(contributions) ≥ landedCost` test here would be a second
51
+ * implementation of the one invariant Part 2 exists to hold.
52
+ */
53
+ export function rejectCoordination(members) {
54
+ if (members.length === 0)
55
+ return "A coordinated purchase needs at least one contributor.";
56
+ if (members.length > SHARED_PURCHASE_MAX_MEMBERS) {
57
+ return `A coordinated purchase is limited to ${SHARED_PURCHASE_MAX_MEMBERS} contributors.`;
58
+ }
59
+ const uids = new Set(members.map((m) => m.uid));
60
+ if (uids.size !== members.length) {
61
+ /*
62
+ * One person twice is almost always a UI slip, and letting it through
63
+ * means their two rows are summed into one charge they did not agree to.
64
+ */
65
+ return "The same person appears more than once.";
66
+ }
67
+ for (const m of members) {
68
+ if (m.splitMode === "percent" && (m.percent == null || m.percent <= 0 || m.percent > 100)) {
69
+ return "Every percentage share must be between 0 and 100.";
70
+ }
71
+ if (m.splitMode === "amount" && (m.amount == null || m.amount <= 0)) {
72
+ return "Every fixed share must be more than zero.";
73
+ }
74
+ }
75
+ return null;
76
+ }
77
+ /** The distinct destinations this offer will have to ship to. */
78
+ export function destinationIds(members) {
79
+ return [...new Set(members.map((m) => m.destinationAddressId).filter((id) => !!id))];
80
+ }