@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,126 @@
1
+ /**
2
+ * Per-order-group EMI terms, and the one definition of what is COLLECTED NOW
3
+ * on an instalment order.
4
+ *
5
+ * ── Why this file exists ──────────────────────────────────────────────────
6
+ *
7
+ * Four money paths have to agree about an EMI order: the pricing preview (what
8
+ * the buyer is shown), `createOrderForGroup` (COD/manual), the gateway capture
9
+ * in `/api/payment/create-order`, and `createPhonePeGroupOrder` (the order
10
+ * written after that capture). Three of them had no EMI code at all, and the
11
+ * fourth computed its schedule inline — so adding the online tender by copying
12
+ * that block would have produced the exact shape Root Cause #75 is about: a
13
+ * rule reachable by copy-paste, copied, and the copy never learning about the
14
+ * branch added later. `lineTotalFor` was the last instance; this is the same
15
+ * fix applied before the divergence rather than after it.
16
+ *
17
+ * ── 🛑 THE DEFECT THIS CLOSES, which is larger than the refactor ──────────
18
+ *
19
+ * `emiTokenAmount` was written onto every EMI order and had **ZERO readers**,
20
+ * measured across `src` and `appkit/src`. The buyer's manual-payment page asks
21
+ * for `order.amountDue ?? order.total`, and `amountDue` was set only when
22
+ * points applied — so an EMI buyer was asked to transfer the **entire order
23
+ * total up front** *and* handed a schedule of monthly instalments. The token
24
+ * percentage was computed, stored, scheduled around, and never charged.
25
+ *
26
+ * `amountDueNow` below is that fix, and it is deliberately a SUBTRACTION
27
+ * rather than a re-derivation:
28
+ *
29
+ * orderTotal − remainingBalance
30
+ * = (subtotal + surcharge + fees) − (principalRemaining + surcharge)
31
+ * = (subtotal − principalRemaining) + fees
32
+ * = token + fees
33
+ *
34
+ * Provably the token plus every additive charge, with no second arithmetic to
35
+ * drift from `computeBuyerEmiQuote`'s own. A function that recomputed
36
+ * `tokenPercent × subtotal + …` would be a fifth place rounding money.
37
+ */
38
+ import { roundRupees } from "../../../../utils/number.formatter.js";
39
+ import { checkEmiEligibility, computeBuyerEmiQuote, computeEmiSchedule, } from "./schedule.js";
40
+ export function groupEmiGate(input, settings) {
41
+ if (!input.emiOptIn)
42
+ return { applies: false, reason: "not_opted_in" };
43
+ if (!input.emiTenureMonths)
44
+ return { applies: false, reason: "no_tenure" };
45
+ if (!settings)
46
+ return { applies: false, reason: "no_settings" };
47
+ const eligibility = checkEmiEligibility(input.groupSubtotal, input.sellerEmiEnabled, settings);
48
+ if (!eligibility.eligible)
49
+ return { applies: false, reason: eligibility.reason };
50
+ return { applies: true };
51
+ }
52
+ /**
53
+ * The buyer-visible quote for one group, or `null` when EMI does not apply.
54
+ *
55
+ * For the preview and for the gateway CAPTURE amount — neither needs the
56
+ * platform/seller surcharge split, and neither should be able to print it.
57
+ */
58
+ export function groupEmiQuote(input, settings, purchaseDate) {
59
+ if (!settings)
60
+ return null;
61
+ if (!groupEmiGate(input, settings).applies)
62
+ return null;
63
+ return computeBuyerEmiQuote(input.groupSubtotal, input.emiTenureMonths, settings, purchaseDate);
64
+ }
65
+ /**
66
+ * The server-side schedule for one group, including the surcharge split that
67
+ * is persisted onto the order. For the two order WRITERS only.
68
+ */
69
+ export function groupEmiSchedule(input, settings, purchaseDate) {
70
+ if (!settings)
71
+ return null;
72
+ if (!groupEmiGate(input, settings).applies)
73
+ return null;
74
+ return computeEmiSchedule(input.groupSubtotal, input.emiTenureMonths, settings, purchaseDate);
75
+ }
76
+ /**
77
+ * What is actually collected at checkout: the order total, less any points
78
+ * tendered, less whatever has been deferred into instalments.
79
+ *
80
+ * 🛑 Composes with the points tender rather than replacing it. Both reduce
81
+ * what is collected and they are independent, so an EMI order part-funded by
82
+ * points must subtract both — writing `total − remainingBalance` would hand
83
+ * back the points discount, and `total − pointsApplied` alone is the bug this
84
+ * function exists to fix. Floored at zero: points can cover at most half an
85
+ * order, so the sum cannot genuinely go negative, and clamping means a future
86
+ * change to that cap degrades to "collect nothing" rather than to a refund.
87
+ */
88
+ export function amountDueNow(args) {
89
+ return roundRupees(Math.max(0, args.orderTotal - args.pointsApplied - args.emiRemainingBalance));
90
+ }
91
+ /**
92
+ * The `emi*` fields written onto an order document.
93
+ *
94
+ * 🛑 One builder for both creation paths. These are eleven fields that have to
95
+ * be written identically by `createOrderForGroup` and
96
+ * `createPhonePeGroupOrder`, and the second one carried **none of them** —
97
+ * every order paid online lost its instalment plan entirely. Two hand-written
98
+ * copies is the create-vs-create axis of Root Cause #39, and these two
99
+ * functions have already drifted once before over add-on fees (#65).
100
+ */
101
+ export function emiOrderFields(schedule, emiTenureMonths) {
102
+ if (!schedule)
103
+ return {};
104
+ return {
105
+ emiEnabled: true,
106
+ emiTenureMonths,
107
+ emiTokenAmount: schedule.tokenAmount,
108
+ emiSurchargeAmount: schedule.surchargeAmount,
109
+ /*
110
+ * Persisted even though it moves no money at checkout: it is the
111
+ * platform/seller split of the surcharge, and the payout run needs it to
112
+ * credit the seller their share. It was discarded on every EMI order until
113
+ * it was added here. 🛑 It is `PRIVATE_*_FIELDS` — it belongs on the
114
+ * document and must never reach a buyer-facing projection.
115
+ */
116
+ emiSurchargeSellerShare: schedule.surchargeSellerShare,
117
+ emiInstallments: schedule.installments.map((i) => ({
118
+ index: i.index,
119
+ dueDate: i.dueDate,
120
+ amount: i.amount,
121
+ status: "pending",
122
+ })),
123
+ emiRemainingBalance: schedule.remainingBalance,
124
+ emiComplete: false,
125
+ };
126
+ }
@@ -0,0 +1,107 @@
1
+ /**
2
+ * The posting rules — pure, so they can be tested by an audit rather than by
3
+ * a `*.test.ts` the project forbids.
4
+ *
5
+ * Nothing here touches Firestore. `assertBalanced` and `buildReversal` are
6
+ * the two decisions that must never be wrong, and keeping them pure is what
7
+ * lets `verify-posting-rules.mjs` exercise them directly — the same shape as
8
+ * `verify-shipment-allocation-guard.mjs`, which reproduces a real failure
9
+ * against the real data shape and carries negative controls.
10
+ */
11
+ import type { JournalLine, JournalSourceEvent } from "../../../../features/ledger/schemas/firestore";
12
+ /**
13
+ * `YYYY-MM` for a date, in the ONE place that derives it.
14
+ *
15
+ * 🛑 **LOCAL, not UTC, and the difference is a GST return.** A sale at 02:00
16
+ * IST on 1 November is 20:30 UTC on 31 October, so `getUTCMonth()` files it
17
+ * under the wrong month — and the month is exactly what a GSTR-1 period is.
18
+ * Every evening sale in India would land in the previous return.
19
+ *
20
+ * Local is correct because `vercel.json` pins functions to `bom1` and the
21
+ * Firebase region is `asia-south1`, so "local" IS IST on every server that
22
+ * runs this. It also matches `financialYearLabel`, which uses `getMonth()`
23
+ * for the same reason and whose boundary error would be unrecoverable —
24
+ * these two must agree or a March entry could sit in one FY and one period
25
+ * that disagree about which year it belongs to.
26
+ *
27
+ * 🛑 It therefore DISAGREES with nothing by accident but with
28
+ * `payPeriodFor`'s UTC-free local midnight by design — both are local; if
29
+ * either is ever moved to UTC, move both, and expect the invoice series to
30
+ * need the same treatment.
31
+ */
32
+ export declare function periodOf(date: Date): string;
33
+ /**
34
+ * 🛑 Money comparison needs a TOLERANCE, and omitting one is the same bug
35
+ * Root Cause #92 cost a million invocations a day.
36
+ *
37
+ * Every leg here is a rupee amount with at most two decimals, and the
38
+ * arithmetic that produces them (a GST split, a pro-rata allocation) is
39
+ * floating point — `0.1 + 0.2 !== 0.3`. An exact `===` on the two totals
40
+ * would refuse a correct entry whose halves differ in the last bit, and the
41
+ * refusal would look like a posting-rule bug rather than a float.
42
+ *
43
+ * Half of the smallest representable unit (0.005): tight enough that a real
44
+ * 0.01 imbalance still fails, loose enough that no accumulation of
45
+ * two-decimal values can reach it.
46
+ */
47
+ export declare const BALANCE_TOLERANCE = 0.005;
48
+ export interface PostingInput {
49
+ entryDate: Date;
50
+ sourceEvent: JournalSourceEvent;
51
+ sourceId?: string;
52
+ narration: string;
53
+ lines: JournalLine[];
54
+ }
55
+ export interface BalancedPosting extends PostingInput {
56
+ period: string;
57
+ totalDebit: number;
58
+ totalCredit: number;
59
+ }
60
+ export declare class UnbalancedEntryError extends Error {
61
+ constructor(message: string);
62
+ }
63
+ /**
64
+ * Validate a posting and compute its totals, or refuse it.
65
+ *
66
+ * 🛑 **Refuses rather than correcting.** A plausible repair — dropping a
67
+ * zero line, inferring the missing side from the difference — is how a wrong
68
+ * posting rule gets a correct-looking entry written for it, and the books
69
+ * then balance while saying something false. An unbalanced entry is always a
70
+ * bug in the rule that built it, and the only safe response is to not write.
71
+ *
72
+ * The five checks, each of which has a distinct failure it prevents:
73
+ */
74
+ export declare function assertBalanced(input: PostingInput): BalancedPosting;
75
+ /**
76
+ * The reversing entry for a posting — every leg's sides swapped.
77
+ *
78
+ * 🛑 **Swapped, never negated.** `debit: -100` would balance arithmetically
79
+ * and is wrong in every other way: it breaks the non-negative rule above, it
80
+ * makes a trial balance sum to the right number through cancelling errors
81
+ * rather than through correct postings, and a ledger export to Tally would
82
+ * reject it. A credit of 100 against a debit of 100 is what a reversal IS.
83
+ *
84
+ * 🛑 **The reversal's `entryDate` is the CALLER's, not the original's.** A
85
+ * correction discovered in November for an October entry posts in November
86
+ * when October is locked — that is the whole point of the lock, and
87
+ * back-dating the reversal to the original would silently reopen a filed
88
+ * period. The link between them is `reversesEntryId`, not a shared date.
89
+ */
90
+ export declare function buildReversal(original: {
91
+ id: string;
92
+ lines: JournalLine[];
93
+ narration: string;
94
+ }, at: Date, reason: string): PostingInput;
95
+ /**
96
+ * Where a late correction must post.
97
+ *
98
+ * 🛑 Returns the entry's OWN period when it is open, and the caller's
99
+ * fallback when it is not — it never silently moves a posting. A rule that
100
+ * quietly re-dated anything landing in a closed period would make the lock
101
+ * invisible, and the first anyone knew of it would be a GST return that no
102
+ * longer reconciles to the books it was filed from.
103
+ */
104
+ export declare function resolvePostingPeriod(wanted: string, isLocked: (period: string) => boolean, openFallback: string): {
105
+ period: string;
106
+ deferred: boolean;
107
+ };
@@ -0,0 +1,165 @@
1
+ /**
2
+ * The posting rules — pure, so they can be tested by an audit rather than by
3
+ * a `*.test.ts` the project forbids.
4
+ *
5
+ * Nothing here touches Firestore. `assertBalanced` and `buildReversal` are
6
+ * the two decisions that must never be wrong, and keeping them pure is what
7
+ * lets `verify-posting-rules.mjs` exercise them directly — the same shape as
8
+ * `verify-shipment-allocation-guard.mjs`, which reproduces a real failure
9
+ * against the real data shape and carries negative controls.
10
+ */
11
+ /**
12
+ * `YYYY-MM` for a date, in the ONE place that derives it.
13
+ *
14
+ * 🛑 **LOCAL, not UTC, and the difference is a GST return.** A sale at 02:00
15
+ * IST on 1 November is 20:30 UTC on 31 October, so `getUTCMonth()` files it
16
+ * under the wrong month — and the month is exactly what a GSTR-1 period is.
17
+ * Every evening sale in India would land in the previous return.
18
+ *
19
+ * Local is correct because `vercel.json` pins functions to `bom1` and the
20
+ * Firebase region is `asia-south1`, so "local" IS IST on every server that
21
+ * runs this. It also matches `financialYearLabel`, which uses `getMonth()`
22
+ * for the same reason and whose boundary error would be unrecoverable —
23
+ * these two must agree or a March entry could sit in one FY and one period
24
+ * that disagree about which year it belongs to.
25
+ *
26
+ * 🛑 It therefore DISAGREES with nothing by accident but with
27
+ * `payPeriodFor`'s UTC-free local midnight by design — both are local; if
28
+ * either is ever moved to UTC, move both, and expect the invoice series to
29
+ * need the same treatment.
30
+ */
31
+ export function periodOf(date) {
32
+ const y = date.getFullYear();
33
+ const m = String(date.getMonth() + 1).padStart(2, "0");
34
+ return `${y}-${m}`;
35
+ }
36
+ /**
37
+ * 🛑 Money comparison needs a TOLERANCE, and omitting one is the same bug
38
+ * Root Cause #92 cost a million invocations a day.
39
+ *
40
+ * Every leg here is a rupee amount with at most two decimals, and the
41
+ * arithmetic that produces them (a GST split, a pro-rata allocation) is
42
+ * floating point — `0.1 + 0.2 !== 0.3`. An exact `===` on the two totals
43
+ * would refuse a correct entry whose halves differ in the last bit, and the
44
+ * refusal would look like a posting-rule bug rather than a float.
45
+ *
46
+ * Half of the smallest representable unit (0.005): tight enough that a real
47
+ * 0.01 imbalance still fails, loose enough that no accumulation of
48
+ * two-decimal values can reach it.
49
+ */
50
+ export const BALANCE_TOLERANCE = 0.005;
51
+ export class UnbalancedEntryError extends Error {
52
+ constructor(message) {
53
+ super(message);
54
+ this.name = "UnbalancedEntryError";
55
+ }
56
+ }
57
+ /**
58
+ * Validate a posting and compute its totals, or refuse it.
59
+ *
60
+ * 🛑 **Refuses rather than correcting.** A plausible repair — dropping a
61
+ * zero line, inferring the missing side from the difference — is how a wrong
62
+ * posting rule gets a correct-looking entry written for it, and the books
63
+ * then balance while saying something false. An unbalanced entry is always a
64
+ * bug in the rule that built it, and the only safe response is to not write.
65
+ *
66
+ * The five checks, each of which has a distinct failure it prevents:
67
+ */
68
+ export function assertBalanced(input) {
69
+ const { lines } = input;
70
+ // 1. A single-legged entry is not double entry. One line can never balance,
71
+ // and the commonest way to get one is a rule that forgot its credit.
72
+ if (lines.length < 2) {
73
+ throw new UnbalancedEntryError(`A journal entry needs at least two lines; got ${lines.length}.`);
74
+ }
75
+ let totalDebit = 0;
76
+ let totalCredit = 0;
77
+ for (const [i, line] of lines.entries()) {
78
+ const d = line.debit ?? 0;
79
+ const c = line.credit ?? 0;
80
+ // 2. NEGATIVE amounts are refused outright. A negative debit is a credit
81
+ // written the wrong way round, and allowing it means every report has
82
+ // to handle a sign it should never see — plus the two totals could
83
+ // then balance while both sides are nonsense.
84
+ if (d < 0 || c < 0) {
85
+ throw new UnbalancedEntryError(`Line ${i} (${line.accountCode}) has a negative amount. A reversal swaps the sides; it never negates them.`);
86
+ }
87
+ // 3. EXACTLY ONE SIDE per line. A line carrying both is ambiguous about
88
+ // what it asserts, and its net effect depends on a subtraction the
89
+ // reader has to perform — which is precisely what two separate fields
90
+ // exist to avoid.
91
+ if (d > 0 && c > 0) {
92
+ throw new UnbalancedEntryError(`Line ${i} (${line.accountCode}) carries both a debit and a credit. Split it into two lines.`);
93
+ }
94
+ // 4. A ZERO line asserts nothing and is almost always a rule that
95
+ // computed an amount it then failed to use.
96
+ if (d === 0 && c === 0) {
97
+ throw new UnbalancedEntryError(`Line ${i} (${line.accountCode}) is zero on both sides.`);
98
+ }
99
+ totalDebit += d;
100
+ totalCredit += c;
101
+ }
102
+ // 5. The accounting identity itself.
103
+ if (Math.abs(totalDebit - totalCredit) > BALANCE_TOLERANCE) {
104
+ throw new UnbalancedEntryError(`Entry does not balance: debits ${totalDebit.toFixed(2)} vs credits ${totalCredit.toFixed(2)}.`);
105
+ }
106
+ return {
107
+ ...input,
108
+ period: periodOf(input.entryDate),
109
+ /*
110
+ * Rounded to two decimals AFTER the comparison, not before. Rounding
111
+ * first would mask a genuine sub-unit imbalance by making both sides
112
+ * equal; rounding after records a figure a human can reconcile against
113
+ * a bank statement.
114
+ */
115
+ totalDebit: Math.round(totalDebit * 100) / 100,
116
+ totalCredit: Math.round(totalCredit * 100) / 100,
117
+ };
118
+ }
119
+ /**
120
+ * The reversing entry for a posting — every leg's sides swapped.
121
+ *
122
+ * 🛑 **Swapped, never negated.** `debit: -100` would balance arithmetically
123
+ * and is wrong in every other way: it breaks the non-negative rule above, it
124
+ * makes a trial balance sum to the right number through cancelling errors
125
+ * rather than through correct postings, and a ledger export to Tally would
126
+ * reject it. A credit of 100 against a debit of 100 is what a reversal IS.
127
+ *
128
+ * 🛑 **The reversal's `entryDate` is the CALLER's, not the original's.** A
129
+ * correction discovered in November for an October entry posts in November
130
+ * when October is locked — that is the whole point of the lock, and
131
+ * back-dating the reversal to the original would silently reopen a filed
132
+ * period. The link between them is `reversesEntryId`, not a shared date.
133
+ */
134
+ export function buildReversal(original, at, reason) {
135
+ return {
136
+ entryDate: at,
137
+ sourceEvent: "reversal",
138
+ sourceId: original.id,
139
+ narration: `Reversal of ${original.id}: ${reason}`,
140
+ lines: original.lines.map((l) => ({
141
+ accountCode: l.accountCode,
142
+ debit: l.credit,
143
+ credit: l.debit,
144
+ ...(l.memo ? { memo: l.memo } : {}),
145
+ ...(l.counterpartyId ? { counterpartyId: l.counterpartyId } : {}),
146
+ })),
147
+ };
148
+ }
149
+ /**
150
+ * Where a late correction must post.
151
+ *
152
+ * 🛑 Returns the entry's OWN period when it is open, and the caller's
153
+ * fallback when it is not — it never silently moves a posting. A rule that
154
+ * quietly re-dated anything landing in a closed period would make the lock
155
+ * invisible, and the first anyone knew of it would be a GST return that no
156
+ * longer reconciles to the books it was filed from.
157
+ */
158
+ export function resolvePostingPeriod(wanted, isLocked, openFallback) {
159
+ if (!isLocked(wanted))
160
+ return { period: wanted, deferred: false };
161
+ if (isLocked(openFallback)) {
162
+ throw new UnbalancedEntryError(`Both ${wanted} and the fallback period ${openFallback} are locked; there is nowhere to post.`);
163
+ }
164
+ return { period: openFallback, deferred: true };
165
+ }
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Trial balance and P&L — derived views, pure, so the audit can exercise them.
3
+ *
4
+ * ## 🛑 These are REPORTS, not truth, and they carry the disclaimer
5
+ *
6
+ * Phase 12's `accounting-output` label applies to every figure produced
7
+ * here. The ledger is already a projection of orders and payouts; a report
8
+ * is a projection of the ledger. Nobody files a return from this without a
9
+ * CA reading it, and the label is what stops the number being treated as
10
+ * though they had.
11
+ *
12
+ * ## 🛑 Signs are applied ONCE, at the boundary
13
+ *
14
+ * A trial balance lists raw debit and credit totals per account, which is
15
+ * what makes it a check: the two columns must agree, and that is only
16
+ * meaningful if nothing has been netted on the way. The P&L is where a
17
+ * normal-balance sign is applied, and it is applied in exactly one place
18
+ * (`signedBalance`) so an income account can never be summed as though it
19
+ * were an expense.
20
+ */
21
+ import type { AccountType, JournalEntryDocument, JournalLine } from "../../../../features/ledger/schemas/firestore";
22
+ /** Which side increases this type. Duplicated from the schema's own helper? No — see below. */
23
+ type Side = "debit" | "credit";
24
+ export interface AccountTotals {
25
+ accountCode: string;
26
+ debit: number;
27
+ credit: number;
28
+ }
29
+ export interface TrialBalance {
30
+ period: string;
31
+ rows: AccountTotals[];
32
+ totalDebit: number;
33
+ totalCredit: number;
34
+ /** The identity. False means an entry was written outside `post()`. */
35
+ balanced: boolean;
36
+ /**
37
+ * Propagated from the read that produced it.
38
+ *
39
+ * 🛑 A truncated trial balance BALANCES — both columns lose the same
40
+ * entries — so `balanced: true` with `truncated: true` says nothing at
41
+ * all. A caller that renders the first and ignores the second is showing
42
+ * a reconciliation that did not happen.
43
+ */
44
+ truncated: boolean;
45
+ }
46
+ /** Sum every line by account. Raw columns, nothing netted. */
47
+ export declare function trialBalance(period: string, entries: readonly JournalEntryDocument[], truncated?: boolean): TrialBalance;
48
+ /**
49
+ * The net movement on an account, signed by its normal balance.
50
+ *
51
+ * 🛑 The ONE place a sign is applied. An income account with ₹1,000 credited
52
+ * and ₹100 debited has earned ₹900; the same raw figures on an expense
53
+ * account are a ₹900 loss in the other direction. Applying this per call
54
+ * site is how one of the two gets inverted and a P&L reads profitable.
55
+ */
56
+ export declare function signedBalance(type: AccountType, totals: AccountTotals): number;
57
+ export interface ProfitAndLoss {
58
+ period: string;
59
+ income: number;
60
+ expenses: number;
61
+ net: number;
62
+ truncated: boolean;
63
+ }
64
+ /**
65
+ * Income less expenses for a period.
66
+ *
67
+ * 🛑 Needs the account TYPES, which it takes as a map rather than inferring
68
+ * from the code's leading digit. The range convention is for humans (see the
69
+ * chart's own header); inferring from it makes the first out-of-range
70
+ * account silently land in the wrong half of the P&L, and the total would
71
+ * still look plausible.
72
+ */
73
+ export declare function profitAndLoss(tb: TrialBalance, typeOf: (accountCode: string) => AccountType | undefined): ProfitAndLoss;
74
+ /** Re-exported for the audit, which checks the two mappings agree. */
75
+ export declare const NORMAL_SIDE_TABLE: Readonly<Record<AccountType, Side>>;
76
+ export type { JournalLine };
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Trial balance and P&L — derived views, pure, so the audit can exercise them.
3
+ *
4
+ * ## 🛑 These are REPORTS, not truth, and they carry the disclaimer
5
+ *
6
+ * Phase 12's `accounting-output` label applies to every figure produced
7
+ * here. The ledger is already a projection of orders and payouts; a report
8
+ * is a projection of the ledger. Nobody files a return from this without a
9
+ * CA reading it, and the label is what stops the number being treated as
10
+ * though they had.
11
+ *
12
+ * ## 🛑 Signs are applied ONCE, at the boundary
13
+ *
14
+ * A trial balance lists raw debit and credit totals per account, which is
15
+ * what makes it a check: the two columns must agree, and that is only
16
+ * meaningful if nothing has been netted on the way. The P&L is where a
17
+ * normal-balance sign is applied, and it is applied in exactly one place
18
+ * (`signedBalance`) so an income account can never be summed as though it
19
+ * were an expense.
20
+ */
21
+ /*
22
+ * 🛑 `normalBalanceFor` lives on the SCHEMA and is not imported here, for the
23
+ * same mechanical reason `periodOf` moved out of it: `verify-posting-rules`
24
+ * loads these modules through Node's type stripping, which erases
25
+ * `import type` but cannot resolve a runtime import against extensionless
26
+ * appkit source.
27
+ *
28
+ * So this is NOT a second definition — the table below is the same mapping,
29
+ * and the schema's function is what application code calls. Two copies of a
30
+ * rule is Root Cause #42, and the honest mitigation is that `R6` in the
31
+ * audit asserts they agree for all five types rather than trusting a
32
+ * comment to keep them in step.
33
+ */
34
+ const NORMAL_SIDE = {
35
+ asset: "debit",
36
+ expense: "debit",
37
+ liability: "credit",
38
+ equity: "credit",
39
+ income: "credit",
40
+ };
41
+ /** Sum every line by account. Raw columns, nothing netted. */
42
+ export function trialBalance(period, entries, truncated = false) {
43
+ const byAccount = new Map();
44
+ for (const entry of entries) {
45
+ for (const line of entry.lines) {
46
+ const row = byAccount.get(line.accountCode) ??
47
+ { accountCode: line.accountCode, debit: 0, credit: 0 };
48
+ row.debit += line.debit ?? 0;
49
+ row.credit += line.credit ?? 0;
50
+ byAccount.set(line.accountCode, row);
51
+ }
52
+ }
53
+ const rows = [...byAccount.values()]
54
+ .map((r) => ({
55
+ accountCode: r.accountCode,
56
+ debit: round2(r.debit),
57
+ credit: round2(r.credit),
58
+ }))
59
+ .sort((a, b) => a.accountCode.localeCompare(b.accountCode));
60
+ const totalDebit = round2(rows.reduce((s, r) => s + r.debit, 0));
61
+ const totalCredit = round2(rows.reduce((s, r) => s + r.credit, 0));
62
+ return {
63
+ period,
64
+ rows,
65
+ totalDebit,
66
+ totalCredit,
67
+ /*
68
+ * 🛑 Compared with the SAME tolerance the posting rules use. A trial
69
+ * balance stricter than the gate that wrote the entries would report an
70
+ * imbalance nobody can act on — every entry in it passed `assertBalanced`.
71
+ */
72
+ balanced: Math.abs(totalDebit - totalCredit) <= 0.005,
73
+ truncated,
74
+ };
75
+ }
76
+ /**
77
+ * The net movement on an account, signed by its normal balance.
78
+ *
79
+ * 🛑 The ONE place a sign is applied. An income account with ₹1,000 credited
80
+ * and ₹100 debited has earned ₹900; the same raw figures on an expense
81
+ * account are a ₹900 loss in the other direction. Applying this per call
82
+ * site is how one of the two gets inverted and a P&L reads profitable.
83
+ */
84
+ export function signedBalance(type, totals) {
85
+ return NORMAL_SIDE[type] === "debit"
86
+ ? round2(totals.debit - totals.credit)
87
+ : round2(totals.credit - totals.debit);
88
+ }
89
+ /**
90
+ * Income less expenses for a period.
91
+ *
92
+ * 🛑 Needs the account TYPES, which it takes as a map rather than inferring
93
+ * from the code's leading digit. The range convention is for humans (see the
94
+ * chart's own header); inferring from it makes the first out-of-range
95
+ * account silently land in the wrong half of the P&L, and the total would
96
+ * still look plausible.
97
+ */
98
+ export function profitAndLoss(tb, typeOf) {
99
+ let income = 0;
100
+ let expenses = 0;
101
+ for (const row of tb.rows) {
102
+ const type = typeOf(row.accountCode);
103
+ /*
104
+ * 🛑 An UNKNOWN account is skipped and that is why `truncated` is not
105
+ * the only honesty flag this needs — but it is the behaviour with the
106
+ * least bad failure: including it would need a guessed type, and a
107
+ * guessed type puts real money on the wrong side. An account code with
108
+ * no account is a `chartOfAccounts` wipe (the orphan case its
109
+ * `seedPurpose: "permanent"` exists to prevent), and the trial balance
110
+ * above still shows the row, so the discrepancy is visible there.
111
+ */
112
+ if (!type)
113
+ continue;
114
+ if (type === "income")
115
+ income += signedBalance(type, row);
116
+ else if (type === "expense")
117
+ expenses += signedBalance(type, row);
118
+ }
119
+ income = round2(income);
120
+ expenses = round2(expenses);
121
+ return { period: tb.period, income, expenses, net: round2(income - expenses), truncated: tb.truncated };
122
+ }
123
+ function round2(n) {
124
+ return Math.round(n * 100) / 100;
125
+ }
126
+ /** Re-exported for the audit, which checks the two mappings agree. */
127
+ export const NORMAL_SIDE_TABLE = NORMAL_SIDE;