@mohasinac/appkit 4.59.0 → 4.60.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 (531) hide show
  1. package/dist/.build-stamp.json +3 -3
  2. package/dist/_internal/client/features/layout/DashboardLayoutClient.js +62 -5
  3. package/dist/_internal/client/features/maintenance/views/MaintenanceDashboardView.js +2 -2
  4. package/dist/_internal/server/features/brands/actions.js +78 -4
  5. package/dist/_internal/server/features/checkout/actions.d.ts +36 -13
  6. package/dist/_internal/server/features/checkout/actions.js +668 -183
  7. package/dist/_internal/server/features/checkout/supplier-identity.js +18 -1
  8. package/dist/_internal/server/features/gateway-events/index.d.ts +10 -0
  9. package/dist/_internal/server/features/gateway-events/index.js +10 -0
  10. package/dist/_internal/server/features/gateway-events/ingest.d.ts +127 -0
  11. package/dist/_internal/server/features/gateway-events/ingest.js +188 -0
  12. package/dist/_internal/server/features/gateway-events/redact.d.ts +66 -0
  13. package/dist/_internal/server/features/gateway-events/redact.js +151 -0
  14. package/dist/_internal/server/features/grievance/actions.d.ts +63 -0
  15. package/dist/_internal/server/features/grievance/actions.js +173 -0
  16. package/dist/_internal/server/features/grievance/index.d.ts +8 -0
  17. package/dist/_internal/server/features/grievance/index.js +8 -0
  18. package/dist/_internal/server/features/grouped/data.js +28 -3
  19. package/dist/_internal/server/features/lottery/actions.js +99 -4
  20. package/dist/_internal/server/features/order-completion/actions.d.ts +92 -0
  21. package/dist/_internal/server/features/order-completion/actions.js +336 -0
  22. package/dist/_internal/server/features/order-completion/index.d.ts +7 -0
  23. package/dist/_internal/server/features/order-completion/index.js +7 -0
  24. package/dist/_internal/server/features/orders/actions.d.ts +13 -0
  25. package/dist/_internal/server/features/orders/actions.js +56 -2
  26. package/dist/_internal/server/features/orders/adapters.js +26 -0
  27. package/dist/_internal/server/features/orders/cancellation-refund.d.ts +116 -0
  28. package/dist/_internal/server/features/orders/cancellation-refund.js +466 -0
  29. package/dist/_internal/server/features/orders/index.d.ts +2 -1
  30. package/dist/_internal/server/features/orders/index.js +1 -1
  31. package/dist/_internal/server/features/orders/service.d.ts +60 -0
  32. package/dist/_internal/server/features/orders/service.js +74 -0
  33. package/dist/_internal/server/features/payment-cases/disputes.d.ts +76 -0
  34. package/dist/_internal/server/features/payment-cases/disputes.js +241 -0
  35. package/dist/_internal/server/features/payment-cases/index.d.ts +9 -0
  36. package/dist/_internal/server/features/payment-cases/index.js +9 -0
  37. package/dist/_internal/server/features/payouts/actions.d.ts +28 -3
  38. package/dist/_internal/server/features/payouts/actions.js +84 -10
  39. package/dist/_internal/server/features/points/adjust.d.ts +61 -0
  40. package/dist/_internal/server/features/points/adjust.js +121 -0
  41. package/dist/_internal/server/features/points/award.d.ts +65 -0
  42. package/dist/_internal/server/features/points/award.js +145 -0
  43. package/dist/_internal/server/features/price-index/market.d.ts +33 -0
  44. package/dist/_internal/server/features/price-index/market.js +54 -1
  45. package/dist/_internal/server/features/products/data.js +40 -22
  46. package/dist/_internal/server/features/protection-claims/actions.d.ts +72 -0
  47. package/dist/_internal/server/features/protection-claims/actions.js +228 -0
  48. package/dist/_internal/server/features/protection-claims/index.d.ts +8 -0
  49. package/dist/_internal/server/features/protection-claims/index.js +8 -0
  50. package/dist/_internal/server/features/refunds/actions.d.ts +20 -0
  51. package/dist/_internal/server/features/refunds/actions.js +259 -17
  52. package/dist/_internal/server/features/refunds/capacity.d.ts +29 -0
  53. package/dist/_internal/server/features/refunds/capacity.js +37 -0
  54. package/dist/_internal/server/features/reviews/actions.js +3 -2
  55. package/dist/_internal/server/features/search/index-build/sources.js +20 -1
  56. package/dist/_internal/server/features/shipping/reconcile.d.ts +10 -1
  57. package/dist/_internal/server/features/shipping/reconcile.js +34 -3
  58. package/dist/_internal/server/features/shipping/reimbursement.d.ts +117 -0
  59. package/dist/_internal/server/features/shipping/reimbursement.js +223 -0
  60. package/dist/_internal/server/features/stores/tabs.d.ts +19 -4
  61. package/dist/_internal/server/features/stores/tabs.js +24 -4
  62. package/dist/_internal/server/functions/https.d.ts +31 -1
  63. package/dist/_internal/server/functions/https.js +52 -1
  64. package/dist/_internal/server/functions/scheduled.d.ts +72 -1
  65. package/dist/_internal/server/functions/scheduled.js +124 -1
  66. package/dist/_internal/server/jobs/core/autoPayoutEligibility.js +62 -16
  67. package/dist/_internal/server/jobs/core/boxRollupReconcile.d.ts +46 -0
  68. package/dist/_internal/server/jobs/core/boxRollupReconcile.js +142 -0
  69. package/dist/_internal/server/jobs/core/dailyDataCleanup.js +149 -1
  70. package/dist/_internal/server/jobs/core/dailyStatusDigest.d.ts +14 -0
  71. package/dist/_internal/server/jobs/core/dailyStatusDigest.js +79 -1
  72. package/dist/_internal/server/jobs/core/index.d.ts +2 -0
  73. package/dist/_internal/server/jobs/core/index.js +2 -0
  74. package/dist/_internal/server/jobs/core/marketPriceRollup.d.ts +64 -0
  75. package/dist/_internal/server/jobs/core/marketPriceRollup.js +153 -0
  76. package/dist/_internal/server/jobs/core/obligationSweep.d.ts +36 -0
  77. package/dist/_internal/server/jobs/core/obligationSweep.js +503 -0
  78. package/dist/_internal/server/jobs/core/paymentReconcile.d.ts +79 -0
  79. package/dist/_internal/server/jobs/core/paymentReconcile.js +614 -0
  80. package/dist/_internal/server/jobs/core/paymentWindowTimeout.js +34 -0
  81. package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.js +35 -4
  82. package/dist/_internal/server/jobs/handlers/boxRollupReconcile.d.ts +2 -0
  83. package/dist/_internal/server/jobs/handlers/boxRollupReconcile.js +15 -0
  84. package/dist/_internal/server/jobs/handlers/countersReconcileNow.d.ts +65 -0
  85. package/dist/_internal/server/jobs/handlers/countersReconcileNow.js +89 -0
  86. package/dist/_internal/server/jobs/handlers/index.d.ts +5 -0
  87. package/dist/_internal/server/jobs/handlers/index.js +5 -0
  88. package/dist/_internal/server/jobs/handlers/marketPriceRollup.d.ts +2 -0
  89. package/dist/_internal/server/jobs/handlers/marketPriceRollup.js +2 -0
  90. package/dist/_internal/server/jobs/handlers/obligationSweep.d.ts +2 -0
  91. package/dist/_internal/server/jobs/handlers/obligationSweep.js +15 -0
  92. package/dist/_internal/server/jobs/handlers/onShipmentAllocationSync.js +30 -1
  93. package/dist/_internal/server/jobs/handlers/paymentReconcile.d.ts +2 -0
  94. package/dist/_internal/server/jobs/handlers/paymentReconcile.js +6 -0
  95. package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
  96. package/dist/_internal/shared/actions/action-registry.js +71 -0
  97. package/dist/_internal/shared/checkout/coupon-discount.d.ts +73 -0
  98. package/dist/_internal/shared/checkout/coupon-discount.js +103 -0
  99. package/dist/_internal/shared/checkout/lanes.d.ts +42 -0
  100. package/dist/_internal/shared/checkout/lanes.js +46 -0
  101. package/dist/_internal/shared/checkout/order-math.d.ts +149 -1
  102. package/dist/_internal/shared/checkout/order-math.js +251 -3
  103. package/dist/_internal/shared/checkout/refundable-base.d.ts +116 -0
  104. package/dist/_internal/shared/checkout/refundable-base.js +122 -0
  105. package/dist/_internal/shared/features/auctions/config.d.ts +14 -1
  106. package/dist/_internal/shared/features/auctions/config.js +30 -1
  107. package/dist/_internal/shared/features/brands/schema.d.ts +42 -0
  108. package/dist/_internal/shared/features/brands/schema.js +18 -0
  109. package/dist/_internal/shared/features/orders/refund-copy.d.ts +22 -0
  110. package/dist/_internal/shared/features/orders/refund-copy.js +34 -0
  111. package/dist/_internal/shared/features/print/label-profiles.d.ts +198 -0
  112. package/dist/_internal/shared/features/print/label-profiles.js +350 -0
  113. package/dist/_internal/shared/features/products/to-product-item.js +33 -5
  114. package/dist/_internal/shared/fees/calculator.d.ts +31 -2
  115. package/dist/_internal/shared/fees/calculator.js +103 -5
  116. package/dist/_internal/shared/fees/india-states.d.ts +195 -0
  117. package/dist/_internal/shared/fees/india-states.js +190 -0
  118. package/dist/_internal/shared/fees/payout-hold.d.ts +80 -0
  119. package/dist/_internal/shared/fees/payout-hold.js +74 -0
  120. package/dist/_internal/shared/obligations/deadlines.d.ts +94 -0
  121. package/dist/_internal/shared/obligations/deadlines.js +155 -0
  122. package/dist/_internal/shared/shipping/quote.d.ts +96 -0
  123. package/dist/_internal/shared/shipping/quote.js +67 -0
  124. package/dist/_internal/shared/time/business-days.d.ts +91 -0
  125. package/dist/_internal/shared/time/business-days.js +185 -0
  126. package/dist/cli/index.js +0 -2
  127. package/dist/client.d.ts +9 -4
  128. package/dist/client.js +26 -3
  129. package/dist/configs/tailwind.d.ts +0 -12
  130. package/dist/configs/tailwind.js +28 -15
  131. package/dist/constants/api-endpoints.d.ts +51 -9
  132. package/dist/constants/api-endpoints.js +23 -7
  133. package/dist/constants/index.d.ts +1 -1
  134. package/dist/constants/index.js +1 -1
  135. package/dist/contracts/index.d.ts +1 -1
  136. package/dist/contracts/payment.d.ts +131 -0
  137. package/dist/features/about/components/AboutView.js +1 -1
  138. package/dist/features/about/components/DeveloperView.js +5 -2
  139. package/dist/features/about/components/FAQPageView.js +2 -1
  140. package/dist/features/about/components/FeesView.js +2 -1
  141. package/dist/features/about/components/HelpPageView.js +2 -1
  142. package/dist/features/about/components/HowAuctionsWorkView.js +2 -1
  143. package/dist/features/about/components/HowCheckoutWorksView.js +2 -1
  144. package/dist/features/about/components/HowEmiWorksView.js +2 -1
  145. package/dist/features/about/components/HowOffersWorkView.js +2 -1
  146. package/dist/features/about/components/HowOrdersWorkView.js +2 -1
  147. package/dist/features/about/components/HowPayoutsWorkView.js +2 -1
  148. package/dist/features/about/components/HowPreOrdersWorkView.js +2 -1
  149. package/dist/features/about/components/HowReviewsWorkView.js +2 -1
  150. package/dist/features/about/components/PolicyPageView.js +2 -1
  151. package/dist/features/about/components/ProseHero.d.ts +73 -0
  152. package/dist/features/about/components/ProseHero.js +18 -0
  153. package/dist/features/about/components/SecurityPrivacyView.js +2 -1
  154. package/dist/features/about/components/ShippingPolicyView.js +2 -1
  155. package/dist/features/about/components/TrackOrderView.js +2 -1
  156. package/dist/features/about/components/UnauthorizedView.js +1 -1
  157. package/dist/features/about/index.d.ts +2 -0
  158. package/dist/features/about/index.js +5 -0
  159. package/dist/features/account/actions/address-actions.d.ts +26 -2
  160. package/dist/features/account/actions/address-actions.js +25 -1
  161. package/dist/features/account/components/BuyerShoppingGuideView.js +1 -1
  162. package/dist/features/account/components/NotificationPreferencesPanel.js +1 -1
  163. package/dist/features/account/components/UserOrdersView.js +17 -0
  164. package/dist/features/account/components/UserSidebar.js +1 -1
  165. package/dist/features/account/hooks/useNotifications.js +29 -0
  166. package/dist/features/admin/actions/admin-coupon-actions.js +36 -0
  167. package/dist/features/admin/components/AdminBeysView.js +2 -2
  168. package/dist/features/admin/components/AdminBlogEditorView.js +2 -2
  169. package/dist/features/admin/components/AdminBrandEditorView.js +32 -2
  170. package/dist/features/admin/components/AdminBundleEditorView.js +1 -1
  171. package/dist/features/admin/components/AdminCarouselEditorView.js +1 -1
  172. package/dist/features/admin/components/AdminCategoriesView.js +1 -1
  173. package/dist/features/admin/components/AdminCategoryEditorView.js +73 -17
  174. package/dist/features/admin/components/AdminContactEditorView.js +1 -1
  175. package/dist/features/admin/components/AdminCouponEditorView.js +26 -1
  176. package/dist/features/admin/components/AdminFaqEditorView.js +1 -1
  177. package/dist/features/admin/components/AdminFaqsView.js +2 -2
  178. package/dist/features/admin/components/AdminGatewayEventsView.d.ts +54 -0
  179. package/dist/features/admin/components/AdminGatewayEventsView.js +209 -0
  180. package/dist/features/admin/components/AdminGuideHubView.js +1 -1
  181. package/dist/features/admin/components/AdminMoneyCasesView.d.ts +60 -0
  182. package/dist/features/admin/components/AdminMoneyCasesView.js +287 -0
  183. package/dist/features/admin/components/AdminPartsView.js +2 -2
  184. package/dist/features/admin/components/AdminProductsView.js +75 -4
  185. package/dist/features/admin/components/AdminSidebar.js +2 -2
  186. package/dist/features/admin/components/AdminSiteSettingsView.js +65 -7
  187. package/dist/features/admin/components/AdminSublistingCategoriesView.js +2 -0
  188. package/dist/features/admin/components/AdminSupportTicketDetailView.js +1 -1
  189. package/dist/features/admin/components/AdminSupportTicketsView.js +2 -2
  190. package/dist/features/admin/components/AdminTesterChecklistView.js +2 -2
  191. package/dist/features/admin/components/AdminUsersView.js +72 -1
  192. package/dist/features/admin/components/AdminViewCards.d.ts +3 -1
  193. package/dist/features/admin/components/AdminViewCards.js +4 -4
  194. package/dist/features/admin/components/DataListingView.d.ts +28 -0
  195. package/dist/features/admin/components/DataListingView.js +175 -14
  196. package/dist/features/admin/components/DataTable.d.ts +12 -1
  197. package/dist/features/admin/components/DataTable.js +3 -3
  198. package/dist/features/admin/components/OwnerQuickActions.d.ts +1 -1
  199. package/dist/features/admin/components/OwnerQuickActions.js +60 -2
  200. package/dist/features/admin/components/RecordOwnerQuickActions.d.ts +1 -1
  201. package/dist/features/admin/components/RecordOwnerQuickActions.js +61 -14
  202. package/dist/features/admin/components/analytics/AdminStatCard.d.ts +35 -1
  203. package/dist/features/admin/components/analytics/AdminStatCard.js +77 -2
  204. package/dist/features/admin/components/index.d.ts +4 -0
  205. package/dist/features/admin/components/index.js +6 -0
  206. package/dist/features/admin/constants/filter-tabs.d.ts +156 -0
  207. package/dist/features/admin/constants/filter-tabs.js +106 -0
  208. package/dist/features/admin/repository/site-settings.repository.d.ts +22 -0
  209. package/dist/features/admin/repository/site-settings.repository.js +82 -1
  210. package/dist/features/admin/schemas/admin-editor-forms.d.ts +21 -0
  211. package/dist/features/admin/schemas/admin-editor-forms.js +44 -0
  212. package/dist/features/admin/schemas/firestore.js +5 -1
  213. package/dist/features/admin/schemas/site-settings-form.js +30 -1
  214. package/dist/features/auctions/actions/bid-actions.js +13 -1
  215. package/dist/features/auctions/components/AuctionBottomActions.js +2 -2
  216. package/dist/features/auctions/components/AuctionDetailPageView.js +3 -1
  217. package/dist/features/auctions/components/MarketplaceAuctionCard.d.ts +11 -0
  218. package/dist/features/auctions/components/MarketplaceAuctionCard.js +5 -3
  219. package/dist/features/auctions/components/PlaceBidFormClient.d.ts +8 -1
  220. package/dist/features/auctions/components/PlaceBidFormClient.js +2 -2
  221. package/dist/features/audit-log/schemas/firestore.d.ts +28 -0
  222. package/dist/features/audit-log/schemas/firestore.js +14 -0
  223. package/dist/features/auth/permissions/constants.d.ts +17 -1
  224. package/dist/features/auth/permissions/constants.js +18 -0
  225. package/dist/features/blog/components/BlogPostView.js +1 -1
  226. package/dist/features/catalogue/components/AdminCatalogueApprovalsView.js +1 -1
  227. package/dist/features/categories/api/[id]/description-template/route.js +107 -1
  228. package/dist/features/categories/components/BrandDetailPageView.js +2 -2
  229. package/dist/features/categories/components/BreadcrumbTrail.js +7 -1
  230. package/dist/features/categories/components/BundleDetailView.js +1 -1
  231. package/dist/features/categories/components/CategoryDetailPageView.js +2 -2
  232. package/dist/features/categories/components/CategoryForm.js +12 -1
  233. package/dist/features/categories/components/CategoryTemplatePicker.js +38 -5
  234. package/dist/features/categories/repository/market-price-index.repository.d.ts +123 -0
  235. package/dist/features/categories/repository/market-price-index.repository.js +105 -0
  236. package/dist/features/categories/repository/price-observation.repository.d.ts +166 -0
  237. package/dist/features/categories/repository/price-observation.repository.js +132 -0
  238. package/dist/features/events/components/EventSaleBanner.js +1 -1
  239. package/dist/features/events/components/EventStatusBadge.js +1 -1
  240. package/dist/features/faq/components/FAQAccordion.js +2 -1
  241. package/dist/features/faq/components/FAQCategorySidebar.js +2 -2
  242. package/dist/features/faq/components/FAQHelpfulButtons.js +4 -4
  243. package/dist/features/faq/components/RelatedFAQs.js +1 -1
  244. package/dist/features/filters/FilterFacetSection.js +1 -1
  245. package/dist/features/filters/SwitchFilter.js +1 -1
  246. package/dist/features/gateway-events/repository/gateway-events.repository.d.ts +117 -0
  247. package/dist/features/gateway-events/repository/gateway-events.repository.js +274 -0
  248. package/dist/features/gateway-events/schemas/firestore.d.ts +217 -0
  249. package/dist/features/gateway-events/schemas/firestore.js +125 -0
  250. package/dist/features/gateway-events/schemas/index.d.ts +81 -0
  251. package/dist/features/gateway-events/schemas/index.js +79 -0
  252. package/dist/features/grouped/components/GroupedListingDetailView.js +1 -1
  253. package/dist/features/homepage/components/AnnouncementBar.js +37 -1
  254. package/dist/features/homepage/components/AnnouncementBar.style.css +30 -0
  255. package/dist/features/homepage/components/BrandsSection.js +1 -1
  256. package/dist/features/homepage/components/CTABannerSection.js +1 -1
  257. package/dist/features/homepage/components/FeaturedBundlesSection.js +14 -24
  258. package/dist/features/homepage/components/HeroCarousel.js +2 -2
  259. package/dist/features/homepage/components/SocialPostCard.js +1 -1
  260. package/dist/features/inventory/components/AdminMoveLedgerView.d.ts +7 -0
  261. package/dist/features/inventory/components/AdminMoveLedgerView.js +157 -0
  262. package/dist/features/inventory/components/AdminStorageBoxesView.d.ts +11 -0
  263. package/dist/features/inventory/components/AdminStorageBoxesView.js +168 -0
  264. package/dist/features/inventory/components/ReceiveStationView.d.ts +39 -0
  265. package/dist/features/inventory/components/ReceiveStationView.js +413 -0
  266. package/dist/features/inventory/components/operator-message.d.ts +29 -0
  267. package/dist/features/inventory/components/operator-message.js +41 -0
  268. package/dist/features/inventory/index.d.ts +13 -0
  269. package/dist/features/inventory/index.js +28 -0
  270. package/dist/features/inventory/repository/inventory-movements.repository.d.ts +97 -0
  271. package/dist/features/inventory/repository/inventory-movements.repository.js +186 -0
  272. package/dist/features/inventory/repository/inventory-placements.repository.d.ts +179 -0
  273. package/dist/features/inventory/repository/inventory-placements.repository.js +345 -0
  274. package/dist/features/inventory/repository/storage-boxes.repository.d.ts +83 -0
  275. package/dist/features/inventory/repository/storage-boxes.repository.js +127 -0
  276. package/dist/features/inventory/schemas/firestore.d.ts +197 -0
  277. package/dist/features/inventory/schemas/firestore.js +159 -0
  278. package/dist/features/layout/AppLayoutShell.d.ts +12 -1
  279. package/dist/features/layout/AppLayoutShell.js +25 -12
  280. package/dist/features/layout/AutoBreadcrumbs.js +162 -3
  281. package/dist/features/layout/AutoBreadcrumbs.style.css +45 -0
  282. package/dist/features/layout/BottomNavbar.d.ts +1 -1
  283. package/dist/features/layout/BottomNavbar.js +2 -2
  284. package/dist/features/media/MediaAvatar.js +1 -1
  285. package/dist/features/media/MediaImage.d.ts +24 -4
  286. package/dist/features/media/MediaImage.js +44 -4
  287. package/dist/features/media/MediaLightbox.js +1 -1
  288. package/dist/features/media/modals/ImageCropModal.js +1 -1
  289. package/dist/features/media/modals/ImageEditor.js +1 -1
  290. package/dist/features/media/upload/MediaUploadField.js +91 -3
  291. package/dist/features/obligations/constants/policies.d.ts +92 -0
  292. package/dist/features/obligations/constants/policies.js +378 -0
  293. package/dist/features/obligations/repository/obligations.repository.d.ts +68 -0
  294. package/dist/features/obligations/repository/obligations.repository.js +158 -0
  295. package/dist/features/obligations/schemas/firestore.d.ts +160 -0
  296. package/dist/features/obligations/schemas/firestore.js +87 -0
  297. package/dist/features/orders/actions/order-actions.d.ts +43 -4
  298. package/dist/features/orders/actions/order-actions.js +60 -3
  299. package/dist/features/orders/actions/refund-actions.js +70 -10
  300. package/dist/features/orders/components/OrderCompletionPanel.d.ts +27 -0
  301. package/dist/features/orders/components/OrderCompletionPanel.js +192 -0
  302. package/dist/features/orders/components/OrdersList.js +2 -2
  303. package/dist/features/orders/components/RefundHistoryTable.js +3 -1
  304. package/dist/features/orders/components/index.d.ts +2 -0
  305. package/dist/features/orders/components/index.js +6 -0
  306. package/dist/features/orders/constants/transitions.d.ts +59 -0
  307. package/dist/features/orders/constants/transitions.js +104 -0
  308. package/dist/features/orders/repository/orders.repository.d.ts +109 -6
  309. package/dist/features/orders/repository/orders.repository.js +464 -21
  310. package/dist/features/orders/schemas/firestore.d.ts +270 -0
  311. package/dist/features/orders/schemas/firestore.js +24 -0
  312. package/dist/features/orders/schemas/index.d.ts +61 -0
  313. package/dist/features/orders/schemas/index.js +22 -0
  314. package/dist/features/orders/types/index.d.ts +79 -0
  315. package/dist/features/parts/components/PartsIndexPageView.js +8 -1
  316. package/dist/features/payment-cases/repository/payment-cases.repository.d.ts +170 -0
  317. package/dist/features/payment-cases/repository/payment-cases.repository.js +342 -0
  318. package/dist/features/payment-cases/schemas/firestore.d.ts +229 -0
  319. package/dist/features/payment-cases/schemas/firestore.js +105 -0
  320. package/dist/features/payment-cases/schemas/resolve-form.d.ts +97 -0
  321. package/dist/features/payment-cases/schemas/resolve-form.js +114 -0
  322. package/dist/features/payments/repository/payout.repository.d.ts +0 -1
  323. package/dist/features/payments/repository/payout.repository.js +0 -1
  324. package/dist/features/points/repository/points.repository.d.ts +122 -0
  325. package/dist/features/points/repository/points.repository.js +304 -1
  326. package/dist/features/points/schemas/adjust-form.d.ts +58 -0
  327. package/dist/features/points/schemas/adjust-form.js +63 -0
  328. package/dist/features/points/schemas/firestore.d.ts +108 -1
  329. package/dist/features/points/schemas/firestore.js +84 -0
  330. package/dist/features/pre-orders/components/MarketplacePreorderCard.js +3 -3
  331. package/dist/features/pre-orders/components/PreOrderBadge.js +1 -1
  332. package/dist/features/pre-orders/components/PreOrderDetailPageView.js +1 -1
  333. package/dist/features/price-index/components/PriceIndexToolView.d.ts +23 -4
  334. package/dist/features/price-index/components/PriceIndexToolView.js +71 -6
  335. package/dist/features/price-index/market-stats.d.ts +82 -0
  336. package/dist/features/price-index/market-stats.js +230 -0
  337. package/dist/features/print/components/BoxLabelPrintView.d.ts +25 -0
  338. package/dist/features/print/components/BoxLabelPrintView.js +66 -0
  339. package/dist/features/print/components/LabelProfilePicker.d.ts +13 -0
  340. package/dist/features/print/components/LabelProfilePicker.js +38 -0
  341. package/dist/features/print/components/labels.d.ts +117 -0
  342. package/dist/features/print/components/labels.js +258 -0
  343. package/dist/features/print/components/labels.style.css +46 -0
  344. package/dist/features/print/index.d.ts +6 -0
  345. package/dist/features/print/index.js +16 -0
  346. package/dist/features/products/columns/productTableColumns.js +5 -4
  347. package/dist/features/products/components/MarketplaceBundleCard.js +2 -2
  348. package/dist/features/products/components/MarketplacePrizeDrawCard.js +6 -6
  349. package/dist/features/products/components/PrizeDrawCollage.js +1 -1
  350. package/dist/features/products/components/PrizeDrawItemsEditor.js +1 -1
  351. package/dist/features/products/components/PrizeRevealModal.js +2 -2
  352. package/dist/features/products/components/ProductDetailPageView.js +18 -4
  353. package/dist/features/products/components/ProductForm.js +34 -23
  354. package/dist/features/products/components/ProductGrid.js +86 -62
  355. package/dist/features/products/constants/card-badges.d.ts +97 -0
  356. package/dist/features/products/constants/card-badges.js +100 -0
  357. package/dist/features/products/repository/products.repository.js +34 -1
  358. package/dist/features/products/schemas/firestore.d.ts +46 -3
  359. package/dist/features/products/schemas/firestore.js +21 -0
  360. package/dist/features/promotions/components/PromotionsView.js +1 -1
  361. package/dist/features/promotions/repository/claimed-coupons.repository.d.ts +32 -0
  362. package/dist/features/promotions/repository/claimed-coupons.repository.js +58 -0
  363. package/dist/features/promotions/schemas/firestore.js +30 -3
  364. package/dist/features/promotions/schemas/index.d.ts +6 -6
  365. package/dist/features/protection-claims/repository/protection-claims.repository.d.ts +54 -0
  366. package/dist/features/protection-claims/repository/protection-claims.repository.js +174 -0
  367. package/dist/features/protection-claims/schemas/firestore.d.ts +168 -0
  368. package/dist/features/protection-claims/schemas/firestore.js +130 -0
  369. package/dist/features/reviews/actions/review-actions.js +3 -2
  370. package/dist/features/reviews/components/ReviewModal.js +1 -1
  371. package/dist/features/reviews/components/ReviewsList.js +1 -1
  372. package/dist/features/reviews/schemas/firestore.d.ts +20 -1
  373. package/dist/features/scams/constants/scam-types.d.ts +2 -0
  374. package/dist/features/scams/constants/scam-types.js +18 -0
  375. package/dist/features/scams/schemas/report-form.d.ts +3 -3
  376. package/dist/features/scams/schemas/report-form.js +26 -1
  377. package/dist/features/search/components/Search.js +9 -9
  378. package/dist/features/search/components/SearchResultsClient.js +18 -3
  379. package/dist/features/search/components/SearchResultsPageView.d.ts +1 -6
  380. package/dist/features/search/components/SearchResultsPageView.js +2 -2
  381. package/dist/features/seller/actions/offer-actions.js +16 -1
  382. package/dist/features/seller/actions/seller-actions.js +14 -3
  383. package/dist/features/seller/components/CategoryInlineSelect.js +75 -11
  384. package/dist/features/seller/components/PrintCenterView.d.ts +5 -0
  385. package/dist/features/seller/components/PrintCenterView.js +41 -30
  386. package/dist/features/seller/components/SellerOrdersView.js +1 -1
  387. package/dist/features/seller/components/SellerPayoutRequestView.js +16 -5
  388. package/dist/features/seller/components/SellerPayoutSettingsView.js +1 -1
  389. package/dist/features/seller/components/SellerProductShell.d.ts +16 -0
  390. package/dist/features/seller/components/SellerProductShell.js +123 -13
  391. package/dist/features/seller/components/SellerReviewsView.js +4 -2
  392. package/dist/features/seller/components/SellerSidebar.js +1 -1
  393. package/dist/features/seller/schemas/coupon-form.d.ts +26 -0
  394. package/dist/features/seller/schemas/coupon-form.js +27 -0
  395. package/dist/features/seller/schemas/product-form.d.ts +3 -0
  396. package/dist/features/seller/schemas/product-form.js +5 -0
  397. package/dist/features/shell/FormShell.js +2 -2
  398. package/dist/features/shell/QuickFormDrawer.js +14 -0
  399. package/dist/features/shell/SectionForm.d.ts +19 -0
  400. package/dist/features/shell/SectionForm.js +133 -9
  401. package/dist/features/shell/SectionForm.style.css +54 -0
  402. package/dist/features/shipments/components/AdminShipmentsView.js +16 -1
  403. package/dist/features/shipments/repository/shipment-items.repository.d.ts +9 -0
  404. package/dist/features/shipments/repository/shipment-items.repository.js +14 -0
  405. package/dist/features/site-settings/components/ActionPermissionsManager.js +1 -1
  406. package/dist/features/sticker-trace/components/StickerCommitPanel.js +1 -1
  407. package/dist/features/store-extensions/schemas/report-review-form.d.ts +8 -8
  408. package/dist/features/stores/components/StoreGuideHubView.js +1 -1
  409. package/dist/features/stores/components/StoreHeader.js +1 -1
  410. package/dist/features/support/schemas/firestore.d.ts +73 -2
  411. package/dist/features/support/schemas/firestore.js +59 -0
  412. package/dist/index.d.ts +16 -24
  413. package/dist/index.js +38 -47
  414. package/dist/next/ErrorBoundary.js +1 -1
  415. package/dist/next/routing/route-map.d.ts +24 -0
  416. package/dist/next/routing/route-map.js +40 -0
  417. package/dist/providers/payment-manual/index.d.ts +15 -1
  418. package/dist/providers/payment-manual/index.js +37 -0
  419. package/dist/providers/payment-phonepe/index.d.ts +14 -1
  420. package/dist/providers/payment-phonepe/index.js +36 -0
  421. package/dist/providers/payment-razorpay/index.d.ts +44 -1
  422. package/dist/providers/payment-razorpay/index.js +99 -0
  423. package/dist/providers/shipping-shiprocket/index.d.ts +18 -0
  424. package/dist/providers/shipping-shiprocket/index.js +18 -0
  425. package/dist/schemas/registry.d.ts +44 -11
  426. package/dist/server-entry.d.ts +2 -0
  427. package/dist/server-entry.js +27 -0
  428. package/dist/server.d.ts +42 -0
  429. package/dist/server.js +93 -0
  430. package/dist/styles.css +418 -149
  431. package/dist/tailwind-utilities.css +1 -1
  432. package/dist/tokens/themes/default-dark.js +15 -12
  433. package/dist/tokens/themes/default-light.js +14 -11
  434. package/dist/tokens/tokens.css +106 -23
  435. package/dist/ui/DataTable.style.css +4 -4
  436. package/dist/ui/columns/cell-renderers.d.ts +20 -0
  437. package/dist/ui/columns/cell-renderers.js +26 -1
  438. package/dist/ui/columns/index.d.ts +1 -1
  439. package/dist/ui/columns/index.js +4 -1
  440. package/dist/ui/components/Badge.style.css +1 -1
  441. package/dist/ui/components/Breadcrumb.js +19 -1
  442. package/dist/ui/components/BulkActionBar.style.css +4 -4
  443. package/dist/ui/components/Button.style.css +1 -1
  444. package/dist/ui/components/Checkbox.style.css +1 -1
  445. package/dist/ui/components/FallbackShell.js +1 -1
  446. package/dist/ui/components/Form.d.ts +14 -1
  447. package/dist/ui/components/Form.js +2 -2
  448. package/dist/ui/components/FormField.js +18 -4
  449. package/dist/ui/components/FormField.style.css +43 -3
  450. package/dist/ui/components/GatedPrice.style.css +1 -1
  451. package/dist/ui/components/IconButton.style.css +1 -1
  452. package/dist/ui/components/Input.js +22 -1
  453. package/dist/ui/components/Input.style.css +38 -22
  454. package/dist/ui/components/ListingFilterDrawer.js +1 -1
  455. package/dist/ui/components/ListingToolbar.js +1 -1
  456. package/dist/ui/components/PaginatedSelect.js +0 -0
  457. package/dist/ui/components/Radio.style.css +1 -1
  458. package/dist/ui/components/Repeater.d.ts +53 -0
  459. package/dist/ui/components/Repeater.js +7 -0
  460. package/dist/ui/components/RichTextEditor.d.ts +20 -1
  461. package/dist/ui/components/RichTextEditor.js +23 -2
  462. package/dist/ui/components/Select.style.css +7 -21
  463. package/dist/ui/components/Semantic.js +27 -3
  464. package/dist/ui/components/TagInput.style.css +4 -9
  465. package/dist/ui/components/Textarea.style.css +4 -18
  466. package/dist/ui/components/Toggle.style.css +1 -1
  467. package/dist/ui/components/Typography.d.ts +3 -3
  468. package/dist/ui/components/Typography.js +15 -15
  469. package/dist/ui/components/ViewToggle.style.css +4 -4
  470. package/dist/ui/forms/AddAnotherToggle.d.ts +16 -0
  471. package/dist/ui/forms/AddAnotherToggle.js +56 -0
  472. package/dist/ui/forms/ColorPickerField.js +15 -2
  473. package/dist/ui/forms/FieldCheckbox.js +15 -2
  474. package/dist/ui/forms/FieldInput.d.ts +22 -1
  475. package/dist/ui/forms/FieldInput.js +19 -5
  476. package/dist/ui/forms/FieldLabel.d.ts +35 -0
  477. package/dist/ui/forms/FieldLabel.js +70 -0
  478. package/dist/ui/forms/FieldSelect.d.ts +4 -1
  479. package/dist/ui/forms/FieldSelect.js +27 -5
  480. package/dist/ui/forms/FieldTextarea.d.ts +4 -1
  481. package/dist/ui/forms/FieldTextarea.js +22 -5
  482. package/dist/ui/forms/FormShell.d.ts +17 -1
  483. package/dist/ui/forms/FormShell.js +36 -2
  484. package/dist/ui/forms/FormShell.style.css +41 -33
  485. package/dist/ui/forms/index.d.ts +5 -1
  486. package/dist/ui/forms/index.js +2 -0
  487. package/dist/ui/icons/icon-registry.d.ts +1 -0
  488. package/dist/ui/icons/icon-registry.js +17 -1
  489. package/dist/utils/id-generators.d.ts +80 -0
  490. package/dist/utils/id-generators.js +93 -0
  491. package/dist/utils/search-txt-builders.d.ts +12 -0
  492. package/dist/utils/search-txt-builders.js +17 -0
  493. package/package.json +1 -1
  494. package/scripts/seed-cli.mjs +106 -5
  495. package/dist/features/loyalty/api/admin/loyalty/grant/route.d.ts +0 -12
  496. package/dist/features/loyalty/api/admin/loyalty/grant/route.js +0 -38
  497. package/dist/features/loyalty/api/balance/route.d.ts +0 -12
  498. package/dist/features/loyalty/api/balance/route.js +0 -41
  499. package/dist/features/loyalty/api/earn/route.d.ts +0 -12
  500. package/dist/features/loyalty/api/earn/route.js +0 -38
  501. package/dist/features/loyalty/api/history/route.d.ts +0 -12
  502. package/dist/features/loyalty/api/history/route.js +0 -58
  503. package/dist/features/loyalty/api/redeem/route.d.ts +0 -12
  504. package/dist/features/loyalty/api/redeem/route.js +0 -38
  505. package/dist/features/loyalty/columns/index.d.ts +0 -17
  506. package/dist/features/loyalty/columns/index.js +0 -40
  507. package/dist/features/loyalty/components/CoinsDisplay.d.ts +0 -12
  508. package/dist/features/loyalty/components/CoinsDisplay.js +0 -10
  509. package/dist/features/loyalty/components/index.d.ts +0 -1
  510. package/dist/features/loyalty/components/index.js +0 -1
  511. package/dist/features/loyalty/hooks/useLoyaltyBalance.d.ts +0 -4
  512. package/dist/features/loyalty/hooks/useLoyaltyBalance.js +0 -25
  513. package/dist/features/loyalty/index.d.ts +0 -6
  514. package/dist/features/loyalty/index.js +0 -6
  515. package/dist/features/loyalty/manifest.d.ts +0 -2
  516. package/dist/features/loyalty/manifest.js +0 -16
  517. package/dist/features/loyalty/messages/en.json +0 -19
  518. package/dist/features/loyalty/repository/loyalty.repository.d.ts +0 -8
  519. package/dist/features/loyalty/repository/loyalty.repository.js +0 -22
  520. package/dist/features/loyalty/schemas/index.d.ts +0 -85
  521. package/dist/features/loyalty/schemas/index.js +0 -40
  522. package/dist/features/loyalty/server.d.ts +0 -6
  523. package/dist/features/loyalty/server.js +0 -6
  524. package/dist/features/loyalty/types/index.d.ts +0 -31
  525. package/dist/features/loyalty/types/index.js +0 -1
  526. package/dist/features/loyalty/types/loyalty-config.d.ts +0 -7
  527. package/dist/features/loyalty/types/loyalty-config.js +0 -1
  528. package/dist/features/loyalty/types/loyalty-math.d.ts +0 -9
  529. package/dist/features/loyalty/types/loyalty-math.js +0 -27
  530. package/dist/features/products/components/ProductOwnerQuickActions.d.ts +0 -11
  531. package/dist/features/products/components/ProductOwnerQuickActions.js +0 -120
@@ -0,0 +1,173 @@
1
+ "use server";
2
+ /**
3
+ * Grievance intake — a record, a clock, and a place in the queue.
4
+ *
5
+ * ## What was wrong (D18)
6
+ *
7
+ * There was **no intake at all**: no form, no route, no API endpoint. The
8
+ * public `/grievance` page's only instruction was a `mailto:` to the generic
9
+ * support address, so nothing recorded a grievance, timestamped it, or tracked
10
+ * any statutory clock. `/report` is for scam and entity reports, not money.
11
+ *
12
+ * ## What this builds, and what it deliberately does NOT
13
+ *
14
+ * Built: the record, the acknowledgement timestamp, the resolution deadline,
15
+ * the structured disputed amount, and a `paymentCases` row so the deadline sits
16
+ * in the one queue an operator already reads.
17
+ *
18
+ * 🛑 **NOT built: anything published.** The Consumer Protection (E-Commerce)
19
+ * Rules 2020 require a NAMED individual as grievance officer, and this project
20
+ * publishes the business name with designation "Support" and the same generic
21
+ * support email — so there is no escalation tier (D17). It also publishes no
22
+ * timeline anywhere.
23
+ *
24
+ * I am not asserting the statutory periods from memory, and the reason is
25
+ * asymmetric: **a published timeline we then miss is worse than the present
26
+ * silence.** So the clock runs against `GRIEVANCE_PERIODS`, whose defaults are
27
+ * deliberately shorter than any plausible statutory period — firing early is
28
+ * harmless, firing late is the thing the regime punishes — and the public page
29
+ * stays untouched until the owner supplies the officer and the real numbers.
30
+ */
31
+ import { wrapAction } from "../../../shared/types/action-result.js";
32
+ import { requireRoleUser } from "../../../../providers/auth-firebase/helpers.js";
33
+ import { normalizeError } from "../../../../errors/normalize.js";
34
+ import { serverLogger } from "../../../../monitoring/index.js";
35
+ import { ValidationError } from "../../../../errors/index.js";
36
+ import { supportRepository } from "../../../../features/support/repository/support.repository.js";
37
+ import { GRIEVANCE_PERIODS, TicketCategoryValues, } from "../../../../features/support/schemas/firestore.js";
38
+ import { paymentCasesRepository } from "../../../../features/payment-cases/repository/payment-cases.repository.js";
39
+ const DETAIL_MIN = 30;
40
+ const DETAIL_MAX = 5000;
41
+ /**
42
+ * File a grievance.
43
+ *
44
+ * 🛑 The acknowledgement is stamped at intake, SYNCHRONOUSLY, and that is the
45
+ * one thing here that must not be best-effort. An acknowledgement timestamp is
46
+ * the evidence that we received the complaint on the day we say we did; writing
47
+ * it fire-and-forget would mean the clock's start could silently fail to
48
+ * record, and a clock whose start is unknown cannot be shown to have been met.
49
+ *
50
+ * The `paymentCases` row IS best-effort, because it is a convenience surface —
51
+ * losing it costs visibility, not evidence.
52
+ */
53
+ export async function fileGrievanceAction(input) {
54
+ return wrapAction(async () => {
55
+ const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
56
+ const subject = input.subject?.trim() ?? "";
57
+ const detail = input.detail?.trim() ?? "";
58
+ if (subject.length < 5) {
59
+ throw new ValidationError("Please give your grievance a short subject line.");
60
+ }
61
+ if (detail.length < DETAIL_MIN) {
62
+ throw new ValidationError(`Please describe the grievance in at least ${DETAIL_MIN} characters — a complaint with no account of the problem cannot be investigated or evidenced.`);
63
+ }
64
+ if (detail.length > DETAIL_MAX) {
65
+ throw new ValidationError(`Please keep the description under ${DETAIL_MAX} characters.`);
66
+ }
67
+ if (input.disputedAmount !== undefined &&
68
+ (!Number.isFinite(input.disputedAmount) || input.disputedAmount < 0)) {
69
+ throw new ValidationError("The disputed amount must be a positive number of rupees.");
70
+ }
71
+ const now = new Date();
72
+ const dueAt = new Date(now.getTime() + GRIEVANCE_PERIODS.resolveHours * 3600000);
73
+ /*
74
+ * `description`, not `message` — the create input is a `Pick` of the plain
75
+ * document and that is the field's real name. I wrote `message` first; an
76
+ * excess property would have been a compile error, which is the signal
77
+ * working as intended rather than a cast hiding it.
78
+ */
79
+ const ticket = await supportRepository.createTicket({
80
+ userId: user.uid,
81
+ /*
82
+ * Both REQUIRED by `SupportTicketCreateInput`, which is a `Pick` of the
83
+ * PLAIN document — so plaintext here is correct, and the repository
84
+ * encrypts on write. Omitting them was a compile error rather than a
85
+ * silent gap, which is the Pick working as intended.
86
+ */
87
+ userEmail: user.email ?? "",
88
+ userDisplayName: user.name ?? user.email ?? "Buyer",
89
+ category: TicketCategoryValues.GRIEVANCE,
90
+ subject,
91
+ description: detail,
92
+ ...(input.orderId ? { orderId: input.orderId } : {}),
93
+ /*
94
+ * Both stamped at creation. `acknowledgedAt` is "we have it" and is
95
+ * automatic; `firstResponseAt` is deliberately NOT set — that is a
96
+ * human replying, and letting an automatic receipt satisfy it would make
97
+ * the response metric meaningless.
98
+ */
99
+ acknowledgedAt: now,
100
+ dueAt,
101
+ ...(input.disputedAmount !== undefined ? { disputedAmount: input.disputedAmount } : {}),
102
+ });
103
+ /*
104
+ * Into the operator queue with the SAME `dueAt`, because a grievance with a
105
+ * deadline is structurally a chargeback with a deadline: an external clock
106
+ * we did not set and cannot extend. Phase 3's queue already sorts by
107
+ * nearest `dueAt` and the daily digest already prints it, so this needs no
108
+ * new surface — which is the whole reason that queue was built as one
109
+ * collection rather than three.
110
+ */
111
+ void paymentCasesRepository()
112
+ .openOrObserve({
113
+ kind: "grievance",
114
+ subjectId: ticket.id,
115
+ severity: "error",
116
+ title: `Grievance — ${subject}`,
117
+ detail: [
118
+ `A formal grievance has been filed and a statutory clock is running.`,
119
+ "",
120
+ `Ticket: ${ticket.id}`,
121
+ input.orderId ? `Order: ${input.orderId}` : "Order: (not order-specific)",
122
+ input.disputedAmount !== undefined
123
+ ? `Disputed amount: ${input.disputedAmount}`
124
+ : "Disputed amount: not stated",
125
+ `Acknowledged: ${now.toISOString()}`,
126
+ `Due: ${dueAt.toISOString()}`,
127
+ "",
128
+ detail,
129
+ "",
130
+ `🛑 The periods are internal DEFAULTS (${GRIEVANCE_PERIODS.acknowledgeHours}h ack /`,
131
+ `${GRIEVANCE_PERIODS.resolveHours / 24}d resolve), chosen shorter than any plausible`,
132
+ `statutory period so the clock fires early. Nothing is published yet.`,
133
+ ].join("\n"),
134
+ entityType: "user",
135
+ entityId: user.uid,
136
+ dueAt,
137
+ ...(input.disputedAmount !== undefined ? { amountAtRisk: input.disputedAmount } : {}),
138
+ ...(input.orderId ? { orderIds: [input.orderId] } : {}),
139
+ now,
140
+ })
141
+ .catch((err) => {
142
+ void normalizeError(err);
143
+ });
144
+ serverLogger.warn("grievance filed", {
145
+ ticketId: ticket.id,
146
+ orderId: input.orderId,
147
+ dueAt: dueAt.toISOString(),
148
+ });
149
+ return { ticketId: ticket.id, dueAt: dueAt.toISOString() };
150
+ });
151
+ }
152
+ /**
153
+ * Stamp the first human response.
154
+ *
155
+ * 🛑 Separate from the ticket's ordinary reply path on purpose: it is
156
+ * write-once (`!existing.firstResponseAt`), so a second reply cannot move the
157
+ * metric forward and make a slow first response look fast. The same
158
+ * write-once discipline `resolvedAt` already uses.
159
+ */
160
+ export async function recordGrievanceFirstResponseAction(ticketId) {
161
+ return wrapAction(async () => {
162
+ const user = await requireRoleUser(["admin", "moderator", "employee"]);
163
+ const existing = (await supportRepository.findById(ticketId));
164
+ if (!existing)
165
+ throw new ValidationError(`Ticket ${ticketId} not found`);
166
+ if (existing.firstResponseAt)
167
+ return; // write-once, idempotent
168
+ await supportRepository.update(ticketId, {
169
+ firstResponseAt: new Date(),
170
+ });
171
+ serverLogger.info("grievance first response recorded", { ticketId, by: user.uid });
172
+ });
173
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * grievance — server surface.
3
+ *
4
+ * Two actions. Narrow on purpose (Root Cause #18): the intake and the
5
+ * write-once first-response stamp. Everything else about a grievance is an
6
+ * ordinary support ticket and uses the support repository directly.
7
+ */
8
+ export { fileGrievanceAction, recordGrievanceFirstResponseAction, type FileGrievanceInput, } from "./actions";
@@ -0,0 +1,8 @@
1
+ /**
2
+ * grievance — server surface.
3
+ *
4
+ * Two actions. Narrow on purpose (Root Cause #18): the intake and the
5
+ * write-once first-response stamp. Everything else about a grievance is an
6
+ * ordinary support ticket and uses the support repository directly.
7
+ */
8
+ export { fileGrievanceAction, recordGrievanceFirstResponseAction, } from "./actions.js";
@@ -7,6 +7,28 @@ import { GROUPED_LISTINGS_COLLECTION, } from "../../../../features/grouped/schem
7
7
  import { productRepository, groupedListingsRepository } from "../../../../repositories/index.js";
8
8
  import { PRODUCT_FIELDS, CATEGORY_FIELDS } from "../../../../constants/field-names.js";
9
9
  import { GROUPED_LISTINGS_FEATURED_LIMIT, GROUPED_LISTINGS_PAGE_SIZE, GROUPED_LISTINGS_SITEMAP_LIMIT, } from "../../../shared/features/grouped/config.js";
10
+ import { isListingTypeEnabled } from "../../../shared/listing-types/feature-flags.js";
11
+ import { normalizeListingType } from "../../../../features/products/utils/listing-type.js";
12
+ import { getSiteSettingsSafe } from "../site-settings/safe-settings.js";
13
+ /**
14
+ * Drop members whose listing type the admin has switched off.
15
+ *
16
+ * 🛑 One helper for all three hydrators rather than the same `.filter()`
17
+ * repeated three times — three copies of one rule is how the next person
18
+ * updates two of them (Root Cause #75).
19
+ *
20
+ * `isListingTypeEnabled` reads a missing flag as ENABLED and
21
+ * `getSiteSettingsSafe` returns null on failure, so a settings read that fails
22
+ * shows every member rather than emptying the carousel — the right failure
23
+ * direction for a discovery surface.
24
+ */
25
+ async function withEnabledMembers(groups) {
26
+ const settings = await getSiteSettingsSafe();
27
+ return groups.map((group) => ({
28
+ ...group,
29
+ items: group.items.filter((p) => isListingTypeEnabled(normalizeListingType(p), settings)),
30
+ }));
31
+ }
10
32
  function mapDoc(doc) {
11
33
  const data = doc.data();
12
34
  const ts = (v) => {
@@ -127,7 +149,7 @@ export const getGroupsForProduct = cache(async (productId) => {
127
149
  */
128
150
  export const getGroupsWithItemsForProduct = cache(async (productId) => {
129
151
  const groups = await getGroupsForProduct(productId);
130
- return Promise.all(groups.map(async (group) => {
152
+ const hydrated = await Promise.all(groups.map(async (group) => {
131
153
  const otherIds = group.productIds.filter((id) => id !== productId);
132
154
  const items = await Promise.all(otherIds.map((id) => safeRead(() => productRepository.findByIdOrSlug(id), {
133
155
  route: "/products",
@@ -136,6 +158,7 @@ export const getGroupsWithItemsForProduct = cache(async (productId) => {
136
158
  })));
137
159
  return { ...group, items: items.filter((p) => p !== null) };
138
160
  }));
161
+ return withEnabledMembers(hydrated);
139
162
  });
140
163
  /** Groups tagged to a category, hydrated with all member products — for the category detail page's GroupedListingsCarousel. */
141
164
  export const getGroupsForCategory = cache(async (categorySlug) => {
@@ -144,10 +167,11 @@ export const getGroupsForCategory = cache(async (categorySlug) => {
144
167
  serverLogger.warn("grouped-data: getGroupsForCategory failed — returning empty", { categorySlug, error: err instanceof Error ? err.message : String(err) });
145
168
  return [];
146
169
  });
147
- return Promise.all(groups.map(async (group) => {
170
+ const hydrated = await Promise.all(groups.map(async (group) => {
148
171
  const items = await Promise.all(group.productIds.map((id) => productRepository.findByIdOrSlug(id).catch(() => null)));
149
172
  return { ...group, items: items.filter((p) => p !== null) };
150
173
  }));
174
+ return withEnabledMembers(hydrated);
151
175
  });
152
176
  /** Groups tagged to a brand, hydrated with all member products — for the brand detail page's GroupedListingsCarousel. */
153
177
  export const getGroupsForBrand = cache(async (brandSlug) => {
@@ -156,10 +180,11 @@ export const getGroupsForBrand = cache(async (brandSlug) => {
156
180
  serverLogger.warn("grouped-data: getGroupsForBrand failed — returning empty", { brandSlug, error: err instanceof Error ? err.message : String(err) });
157
181
  return [];
158
182
  });
159
- return Promise.all(groups.map(async (group) => {
183
+ const hydrated = await Promise.all(groups.map(async (group) => {
160
184
  const items = await Promise.all(group.productIds.map((id) => productRepository.findByIdOrSlug(id).catch(() => null)));
161
185
  return { ...group, items: items.filter((p) => p !== null) };
162
186
  }));
187
+ return withEnabledMembers(hydrated);
163
188
  });
164
189
  export async function listSitemapGroupedListings() {
165
190
  try {
@@ -1,7 +1,8 @@
1
1
  "use server";
2
2
  import { wrapAction } from "@mohasinac/appkit/server";
3
3
  import { getAdminDb } from "../../../../providers/db-firebase/index.js";
4
- import { eventRepository, productRepository } from "../../../../repositories/index.js";
4
+ import { eventRepository, productRepository, orderRepository } from "../../../../repositories/index.js";
5
+ import { serverLogger } from "../../../../monitoring/index.js";
5
6
  import { lotteryEntryRepository } from "../../../../features/lottery/repository/lottery-entry.repository.js";
6
7
  import { requireRoleUser } from "../../../../providers/auth-firebase/helpers.js";
7
8
  import { ValidationError } from "../../../shared/errors/index.js";
@@ -73,10 +74,89 @@ export async function submitLotteryPullAction(input) {
73
74
  if (existingUserPulls >= lotteryConfig.maxPullsPerUser) {
74
75
  throw new LotteryError("USER_LIMIT_REACHED", "You have reached the maximum number of pulls for this lottery.");
75
76
  }
76
- // Enforce maxPullsPerTransaction
77
+ /*
78
+ * ── D52: THE TRANSACTION MUST BE A REAL, PAID, CALLER-OWNED ORDER ──────
79
+ *
80
+ * 🛑 Before this, `data.transactionId` was a user-supplied STRING
81
+ * (`z.string().min(4)`) and the only thing checked was a COUNT of prior
82
+ * entries carrying the same string. Nothing verified that the transaction
83
+ * existed, that it was paid, or that it belonged to the caller — and
84
+ * `paymentTime` was user-supplied too.
85
+ *
86
+ * So **anyone could claim a lottery slot for free** by typing any
87
+ * four-character string, up to `maxPullsPerUser`, and then another
88
+ * `maxPullsPerUser` under the next string. On a lottery whose slots carry
89
+ * real prices and real prizes.
90
+ *
91
+ * The code knew: `// FUTURE_FINANCIAL_DB: external_tx_id →
92
+ * lottery_transactions.external_tx_id`, pointing at a collection that does
93
+ * not exist. The gap was marked and left open.
94
+ *
95
+ * It does not need that collection: a prize-draw entry is bought through
96
+ * the ordinary cart, so a paid ORDER is the payment record we already
97
+ * have. `maxPullsPerTransaction` then does what its name says — it bounds
98
+ * pulls per PAYMENT rather than per guessed string.
99
+ *
100
+ * 🛑 THE TWO SOURCES HAVE DIFFERENT PAYMENT REALITIES, and pretending
101
+ * otherwise would either leave the hole open or break a working feature.
102
+ *
103
+ * · A PRODUCT-sourced lottery is a `prize-draw` listing bought through the
104
+ * ordinary cart, so a paid ORDER exists and is verifiable. Required.
105
+ *
106
+ * · An EVENT-sourced lottery carries real slot prices (the seed has both
107
+ * `uniform` and `variable` events) and has **no cart or checkout path at
108
+ * all** — an event is not a product and cannot be added to a cart. So
109
+ * the typed `transactionId` was the ENTIRE payment record: an
110
+ * honour-system reference with nothing behind it.
111
+ *
112
+ * Requiring an order here would break every event lottery. Accepting the
113
+ * string silently is the hole. So the entry is accepted and marked
114
+ * `isFlagged` for admin review BEFORE the draw — `flagLotteryEntry`
115
+ * already exists for exactly this, and an admin can clear or void it.
116
+ * That makes the unverified state VISIBLE instead of indistinguishable
117
+ * from a paid one.
118
+ *
119
+ * 🛑 This is a stopgap, not a fix, and it is the honest one available
120
+ * without building a checkout path for events. The real fix is to make an
121
+ * event lottery purchasable (or free), which is a product decision.
122
+ */
123
+ let paymentUnverified = false;
124
+ if (data.sourceType === "product") {
125
+ const payingOrder = await orderRepository.findById(data.transactionId);
126
+ /*
127
+ * "Not found" and "not yours" share one message DELIBERATELY.
128
+ * Distinguishing them confirms that an order id exists and belongs to
129
+ * someone else, which is an enumeration oracle over order ids.
130
+ */
131
+ if (!payingOrder || payingOrder.userId !== user.uid) {
132
+ throw new LotteryError("TX_ALREADY_USED", "That order could not be found. Enter the order ID from your confirmation email.");
133
+ }
134
+ if (payingOrder.paymentStatus !== "paid") {
135
+ throw new LotteryError("TX_ALREADY_USED", "That order has not been paid yet. Once the payment is confirmed you can claim your slot.");
136
+ }
137
+ /*
138
+ * The order must contain THIS prize draw, or one paid order could be
139
+ * spent across every open lottery on the site.
140
+ *
141
+ * Both shapes are checked: `items[]` is the fan-out form, and the flat
142
+ * `productId` is the PRIMARY field on an order — CLAUDE.md's own
143
+ * correction records that `items` is OPTIONAL and the flat fields are
144
+ * not legacy residue, so checking only one misses real orders.
145
+ */
146
+ const orderCoversSource = payingOrder.productId === sourceId ||
147
+ (payingOrder.items ?? []).some((i) => i.productId === sourceId);
148
+ if (!orderCoversSource) {
149
+ throw new LotteryError("TX_ALREADY_USED", "That order does not include this prize draw. Check the order ID.");
150
+ }
151
+ }
152
+ else {
153
+ paymentUnverified = true;
154
+ serverLogger.warn("[lottery] event pull accepted with an UNVERIFIED payment reference — flagged for admin review", { eventId: sourceId, uid: user.uid, transactionId: data.transactionId });
155
+ }
156
+ // Enforce maxPullsPerTransaction — now per PAYMENT, not per guessed string.
77
157
  const existingTxPulls = await lotteryEntryRepository.countByTransactionId(sourceId, sourceField, data.transactionId);
78
158
  if (existingTxPulls >= lotteryConfig.maxPullsPerTransaction) {
79
- throw new LotteryError("TX_ALREADY_USED", "This transaction ID has already been used the maximum number of times.");
159
+ throw new LotteryError("TX_ALREADY_USED", "This order has already been used for the maximum number of pulls.");
80
160
  }
81
161
  // Atomically: pick slot + create entry + mark slot booked
82
162
  const db = getAdminDb();
@@ -139,7 +219,22 @@ export async function submitLotteryPullAction(input) {
139
219
  userLotteryNumber,
140
220
  assignedPrizeSlotNumber: assignedSlot.slotNumber,
141
221
  status: "drawn",
142
- isFlagged: false,
222
+ /*
223
+ * D52 — an EVENT pull carries no verifiable payment (events have no
224
+ * cart path), so it is flagged on creation rather than recorded as if it
225
+ * were paid. A product pull reached here only after its order was
226
+ * verified paid, caller-owned and covering this draw, so it is not
227
+ * flagged.
228
+ *
229
+ * This is what makes the unverified state visible to an admin before the
230
+ * draw instead of indistinguishable from a paid one.
231
+ */
232
+ isFlagged: paymentUnverified,
233
+ ...(paymentUnverified
234
+ ? {
235
+ flagNote: "Payment reference not verified — event lotteries have no checkout path, so this reference was typed by the entrant. Confirm the payment before the draw.",
236
+ }
237
+ : {}),
143
238
  submittedAt: new Date(),
144
239
  drawnAt: new Date(),
145
240
  };
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Order completion — per-item ratings, and the two ways an order completes.
3
+ *
4
+ * ## The owner's rule, 2026-10-21
5
+ *
6
+ * > *"Points only get issued on successful purchases after buyer put reviews…
7
+ * > they are also assigned if the user [raises] no issues or updates after 7
8
+ * > days of delivery — no further disputes should be entertained as well."*
9
+ *
10
+ * > *"Auto assigned after 7 days of delivery, when order is marked complete; if
11
+ * > review is given and order marked complete by the buyer before — immediate
12
+ * > disburse."*
13
+ *
14
+ * > *"Like in Zomato, each item of the order can be individually rated and a
15
+ * > comment can be given — use that."*
16
+ *
17
+ * So completion has exactly two writers, and they are not equivalent:
18
+ *
19
+ * | writer | when | effect |
20
+ * |---|---|---|
21
+ * | `obligationSweep` (`order-complete`) | 7 days after delivery, nothing contested | completes; points award |
22
+ * | `markOrderCompleteAction` | the buyer, having rated at least one item | completes NOW; **immediate disburse** |
23
+ *
24
+ * 🛑 **The "immediate disburse" half needs no extra mechanism, and that is the
25
+ * nicest property of the design.** `payout-release` is already
26
+ * `blockedBy: ["order-complete", …]`, so a buyer completing early opens the
27
+ * seller's payout gate early as a CONSEQUENCE rather than as a second
28
+ * decision. The buyer confirming satisfaction is precisely the signal a quiet
29
+ * period exists to wait for — so when it arrives, waiting out the rest of the
30
+ * period is pure dead time for the seller.
31
+ */
32
+ import { type ActionResult } from "../../../shared/types/action-result";
33
+ /** The lines of an order a buyer can rate — one entry per order line. */
34
+ export interface RateableOrderItem {
35
+ orderItemId: string;
36
+ productId: string;
37
+ productTitle: string;
38
+ /** The buyer's existing rating for this line, when they have left one. */
39
+ existingRating?: number;
40
+ }
41
+ /**
42
+ * Which lines of this order the buyer may rate, and which they already have.
43
+ *
44
+ * 🛑 Reads the buyer's OWN reviews (`findByUser`) rather than each product's
45
+ * reviews (`findByProduct`). A product can carry thousands of reviews and a
46
+ * buyer carries a handful, so this is bounded by the right dimension —
47
+ * `findByProduct` on a popular bey would be an unbounded read to answer a
48
+ * question about one person (Rule #6).
49
+ */
50
+ export declare function getRateableItemsAction(orderId: string): Promise<ActionResult<RateableOrderItem[]>>;
51
+ export interface RateOrderItemInput {
52
+ orderId: string;
53
+ orderItemId: string;
54
+ rating: number;
55
+ comment: string;
56
+ title?: string;
57
+ images?: string[];
58
+ }
59
+ /**
60
+ * Rate ONE line of an order — the Zomato-style per-item review.
61
+ *
62
+ * 🛑 Gated on DELIVERY, not on completion. A buyer must be able to rate before
63
+ * marking the order complete, because rating is the precondition for the fast
64
+ * completion path — gating it on completion would make the fast path
65
+ * unreachable, which is a circular dependency that would look like a bug in
66
+ * the button.
67
+ */
68
+ export declare function rateOrderItemAction(input: RateOrderItemInput): Promise<ActionResult<{
69
+ reviewId: string;
70
+ }>>;
71
+ /**
72
+ * The buyer marks the order complete — the FAST path.
73
+ *
74
+ * Requires at least one rated line, per the owner's rule (*"if review is given
75
+ * and order marked complete by the buyer"*).
76
+ *
77
+ * 🛑 **At least one, not all.** Requiring every line would make a six-item
78
+ * order's completion hostage to the one item the buyer has no opinion about —
79
+ * and the buyer's alternative is simply to wait 7 days and be completed
80
+ * automatically with no review at all, which is strictly worse for everyone.
81
+ * One rating is the signal; demanding six is a toll.
82
+ *
83
+ * 🛑 It REFUSES while anything is contested, and the check is the obligation
84
+ * policy's own `precondition` rather than a second hand-written copy — so the
85
+ * buyer-initiated path and the 7-day sweep cannot disagree about what "nothing
86
+ * contested" means.
87
+ */
88
+ export declare function markOrderCompleteAction(orderId: string): Promise<ActionResult<{
89
+ completedAt: string;
90
+ payoutUnblocked: boolean;
91
+ pointsAwarded: number;
92
+ }>>;