@mohasinac/appkit 3.0.4 → 3.1.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 (320) hide show
  1. package/dist/_internal/client/features/lottery/LotteryAdminEditView.d.ts +42 -0
  2. package/dist/_internal/client/features/lottery/LotteryAdminEditView.js +86 -0
  3. package/dist/_internal/client/features/lottery/LotteryAdminSlotView.d.ts +14 -0
  4. package/dist/_internal/client/features/lottery/LotteryAdminSlotView.js +46 -0
  5. package/dist/_internal/client/features/lottery/LotteryDetailView.d.ts +28 -0
  6. package/dist/_internal/client/features/lottery/LotteryDetailView.js +17 -0
  7. package/dist/_internal/client/features/lottery/LotteryEntriesView.d.ts +23 -0
  8. package/dist/_internal/client/features/lottery/LotteryEntriesView.js +58 -0
  9. package/dist/_internal/client/features/lottery/LotteryListView.d.ts +21 -0
  10. package/dist/_internal/client/features/lottery/LotteryListView.js +25 -0
  11. package/dist/_internal/client/features/lottery/LotteryPullForm.d.ts +19 -0
  12. package/dist/_internal/client/features/lottery/LotteryPullForm.js +65 -0
  13. package/dist/_internal/client/features/lottery/LotterySlotGrid.d.ts +13 -0
  14. package/dist/_internal/client/features/lottery/LotterySlotGrid.js +21 -0
  15. package/dist/_internal/client/features/lottery/PrizeDrawLotteryDetailView.d.ts +28 -0
  16. package/dist/_internal/client/features/lottery/PrizeDrawLotteryDetailView.js +18 -0
  17. package/dist/_internal/server/features/auctions/__tests__/service.test.d.ts +1 -0
  18. package/dist/_internal/server/features/auctions/__tests__/service.test.js +140 -0
  19. package/dist/_internal/server/features/auctions/data.d.ts +2 -4
  20. package/dist/_internal/server/features/auctions/data.js +3 -9
  21. package/dist/_internal/server/features/checkout/__tests__/actions.test.d.ts +1 -0
  22. package/dist/_internal/server/features/checkout/__tests__/actions.test.js +600 -0
  23. package/dist/_internal/server/features/classified/adapters.d.ts +2 -15
  24. package/dist/_internal/server/features/classified/adapters.js +2 -17
  25. package/dist/_internal/server/features/classified/data.d.ts +1 -6
  26. package/dist/_internal/server/features/classified/data.js +2 -10
  27. package/dist/_internal/server/features/digital-code/adapters.d.ts +2 -15
  28. package/dist/_internal/server/features/digital-code/adapters.js +2 -17
  29. package/dist/_internal/server/features/digital-code/data.d.ts +1 -6
  30. package/dist/_internal/server/features/digital-code/data.js +2 -10
  31. package/dist/_internal/server/features/live/adapters.d.ts +2 -15
  32. package/dist/_internal/server/features/live/adapters.js +2 -17
  33. package/dist/_internal/server/features/live/data.d.ts +1 -6
  34. package/dist/_internal/server/features/live/data.js +2 -10
  35. package/dist/_internal/server/features/lottery/actions.d.ts +43 -0
  36. package/dist/_internal/server/features/lottery/actions.js +243 -0
  37. package/dist/_internal/server/features/lottery/adapters.d.ts +9 -0
  38. package/dist/_internal/server/features/lottery/adapters.js +21 -0
  39. package/dist/_internal/server/features/lottery/data.d.ts +20 -0
  40. package/dist/_internal/server/features/lottery/data.js +41 -0
  41. package/dist/_internal/server/features/lottery/metadata.d.ts +6 -0
  42. package/dist/_internal/server/features/lottery/metadata.js +31 -0
  43. package/dist/_internal/server/features/pre-orders/data.d.ts +2 -4
  44. package/dist/_internal/server/features/pre-orders/data.js +3 -9
  45. package/dist/_internal/server/features/prize-draws/actions.d.ts +2 -0
  46. package/dist/_internal/server/features/prize-draws/actions.js +22 -0
  47. package/dist/_internal/server/features/prize-draws/data.d.ts +1 -17
  48. package/dist/_internal/server/features/prize-draws/data.js +2 -20
  49. package/dist/_internal/server/features/prize-draws/index.d.ts +3 -1
  50. package/dist/_internal/server/features/prize-draws/index.js +2 -0
  51. package/dist/_internal/server/features/prize-draws/service.d.ts +3 -0
  52. package/dist/_internal/server/features/prize-draws/service.js +19 -0
  53. package/dist/_internal/server/features/refunds/__tests__/actions.test.d.ts +1 -0
  54. package/dist/_internal/server/features/refunds/__tests__/actions.test.js +263 -0
  55. package/dist/_internal/server/features/shared/listing-adapters.d.ts +19 -0
  56. package/dist/_internal/server/features/shared/listing-adapters.js +20 -0
  57. package/dist/_internal/server/features/shared/listing-data-factory.d.ts +9 -0
  58. package/dist/_internal/server/features/shared/listing-data-factory.js +33 -0
  59. package/dist/_internal/server/features/stores/data.d.ts +3 -14
  60. package/dist/_internal/server/features/stores/data.js +6 -44
  61. package/dist/_internal/server/jobs/core/__tests__/auctionSettlement.test.d.ts +1 -0
  62. package/dist/_internal/server/jobs/core/__tests__/auctionSettlement.test.js +249 -0
  63. package/dist/_internal/server/jobs/core/__tests__/onBidPlaced.test.d.ts +1 -0
  64. package/dist/_internal/server/jobs/core/__tests__/onBidPlaced.test.js +201 -0
  65. package/dist/_internal/server/jobs/core/__tests__/onOrderCreate.test.d.ts +1 -0
  66. package/dist/_internal/server/jobs/core/__tests__/onOrderCreate.test.js +169 -0
  67. package/dist/_internal/server/jobs/core/__tests__/onOrderStatusChange.test.d.ts +1 -0
  68. package/dist/_internal/server/jobs/core/__tests__/onOrderStatusChange.test.js +148 -0
  69. package/dist/_internal/server/jobs/core/__tests__/onProductStockChange.test.d.ts +1 -0
  70. package/dist/_internal/server/jobs/core/__tests__/onProductStockChange.test.js +210 -0
  71. package/dist/_internal/server/jobs/core/__tests__/onReviewWrite.test.d.ts +1 -0
  72. package/dist/_internal/server/jobs/core/__tests__/onReviewWrite.test.js +190 -0
  73. package/dist/_internal/server/jobs/core/__tests__/onUserBanChange.test.d.ts +1 -0
  74. package/dist/_internal/server/jobs/core/__tests__/onUserBanChange.test.js +161 -0
  75. package/dist/_internal/server/jobs/core/__tests__/payoutBatch.test.d.ts +1 -0
  76. package/dist/_internal/server/jobs/core/__tests__/payoutBatch.test.js +302 -0
  77. package/dist/_internal/server/jobs/core/__tests__/triggerEventRaffle.test.d.ts +1 -0
  78. package/dist/_internal/server/jobs/core/__tests__/triggerEventRaffle.test.js +252 -0
  79. package/dist/_internal/server/jobs/core/__tests__/wrapJobHandler.test.d.ts +1 -0
  80. package/dist/_internal/server/jobs/core/__tests__/wrapJobHandler.test.js +129 -0
  81. package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
  82. package/dist/_internal/shared/actions/action-registry.js +46 -0
  83. package/dist/_internal/shared/features/cart/schema.d.ts +8 -8
  84. package/dist/_internal/shared/features/cart/schema.js +3 -0
  85. package/dist/_internal/shared/features/products/schema.d.ts +8 -8
  86. package/dist/_internal/shared/listing-types/_registry.js +2 -0
  87. package/dist/_internal/shared/listing-types/auction/schema.d.ts +3 -1
  88. package/dist/_internal/shared/listing-types/auction/schema.js +7 -1
  89. package/dist/_internal/shared/listing-types/classified/schema.d.ts +2 -1
  90. package/dist/_internal/shared/listing-types/classified/schema.js +3 -1
  91. package/dist/_internal/shared/listing-types/digital-code/schema.d.ts +3 -1
  92. package/dist/_internal/shared/listing-types/digital-code/schema.js +7 -1
  93. package/dist/_internal/shared/listing-types/live/schema.d.ts +2 -1
  94. package/dist/_internal/shared/listing-types/live/schema.js +3 -1
  95. package/dist/_internal/shared/listing-types/pre-order/schema.d.ts +3 -1
  96. package/dist/_internal/shared/listing-types/pre-order/schema.js +7 -1
  97. package/dist/_internal/shared/listing-types/prize-draw/schema.d.ts +3 -1
  98. package/dist/_internal/shared/listing-types/prize-draw/schema.js +13 -1
  99. package/dist/_internal/shared/listing-types/standard/schema.d.ts +2 -1
  100. package/dist/_internal/shared/listing-types/standard/schema.js +4 -1
  101. package/dist/_internal/shared/types/base-document.d.ts +15 -0
  102. package/dist/_internal/shared/types/base-document.js +1 -0
  103. package/dist/_internal/shared/types/index.d.ts +2 -0
  104. package/dist/_internal/shared/types/index.js +1 -0
  105. package/dist/client.d.ts +13 -4
  106. package/dist/client.js +11 -2
  107. package/dist/constants/api-endpoints.d.ts +12 -0
  108. package/dist/constants/api-endpoints.js +4 -0
  109. package/dist/constants/field-names.d.ts +5 -1
  110. package/dist/constants/field-names.js +5 -1
  111. package/dist/features/addresses/repository/__tests__/addresses.repository.test.d.ts +1 -0
  112. package/dist/features/addresses/repository/__tests__/addresses.repository.test.js +386 -0
  113. package/dist/features/addresses/schemas/firestore.d.ts +2 -4
  114. package/dist/features/admin/api/bids/route.d.ts +2 -2
  115. package/dist/features/admin/api/coupons/route.d.ts +2 -2
  116. package/dist/features/admin/api/products/route.d.ts +2 -2
  117. package/dist/features/admin/api/reviews/route.d.ts +2 -2
  118. package/dist/features/admin/components/AdminFulfillmentView.d.ts +6 -0
  119. package/dist/features/admin/components/AdminFulfillmentView.js +107 -0
  120. package/dist/features/admin/components/AdminProductEditorView.js +21 -9
  121. package/dist/features/admin/components/AdminProductsView.js +3 -0
  122. package/dist/features/admin/components/DataListingView.d.ts +1 -0
  123. package/dist/features/admin/components/index.d.ts +2 -0
  124. package/dist/features/admin/components/index.js +1 -0
  125. package/dist/features/admin/repository/__tests__/notification.repository.test.d.ts +1 -0
  126. package/dist/features/admin/repository/__tests__/notification.repository.test.js +356 -0
  127. package/dist/features/admin/repository/__tests__/site-settings.repository.test.d.ts +1 -0
  128. package/dist/features/admin/repository/__tests__/site-settings.repository.test.js +298 -0
  129. package/dist/features/admin/schemas/firestore.d.ts +3 -8
  130. package/dist/features/auctions/repository/__tests__/bid.repository.test.d.ts +1 -0
  131. package/dist/features/auctions/repository/__tests__/bid.repository.test.js +290 -0
  132. package/dist/features/auctions/schemas/firestore.d.ts +2 -4
  133. package/dist/features/auctions/schemas/index.d.ts +2 -2
  134. package/dist/features/auth/api/route.d.ts +2 -2
  135. package/dist/features/auth/repository/__tests__/session.repository.test.d.ts +1 -0
  136. package/dist/features/auth/repository/__tests__/session.repository.test.js +310 -0
  137. package/dist/features/auth/repository/__tests__/session.test.d.ts +1 -0
  138. package/dist/features/auth/repository/__tests__/session.test.js +146 -0
  139. package/dist/features/auth/repository/__tests__/sms-counter.repository.test.d.ts +1 -0
  140. package/dist/features/auth/repository/__tests__/sms-counter.repository.test.js +171 -0
  141. package/dist/features/auth/repository/__tests__/sms-counter.test.d.ts +1 -0
  142. package/dist/features/auth/repository/__tests__/sms-counter.test.js +88 -0
  143. package/dist/features/auth/repository/__tests__/token.repository.test.d.ts +1 -0
  144. package/dist/features/auth/repository/__tests__/token.repository.test.js +260 -0
  145. package/dist/features/auth/repository/__tests__/token.test.d.ts +1 -0
  146. package/dist/features/auth/repository/__tests__/token.test.js +140 -0
  147. package/dist/features/auth/repository/__tests__/user.repository.test.d.ts +1 -0
  148. package/dist/features/auth/repository/__tests__/user.repository.test.js +352 -0
  149. package/dist/features/auth/repository/__tests__/user.test.d.ts +1 -0
  150. package/dist/features/auth/repository/__tests__/user.test.js +226 -0
  151. package/dist/features/auth/repository/session.repository.js +10 -1
  152. package/dist/features/before-after/schemas/index.d.ts +2 -2
  153. package/dist/features/blog/schemas/firestore.d.ts +2 -4
  154. package/dist/features/blog/schemas/index.d.ts +4 -4
  155. package/dist/features/cart/repository/__tests__/cart.repository.test.d.ts +1 -0
  156. package/dist/features/cart/repository/__tests__/cart.repository.test.js +371 -0
  157. package/dist/features/cart/repository/cart.repository.js +2 -2
  158. package/dist/features/cart/schemas/firestore.d.ts +2 -4
  159. package/dist/features/categories/api/[id]/route.d.ts +4 -4
  160. package/dist/features/categories/api/route.d.ts +2 -2
  161. package/dist/features/categories/repository/__tests__/categories.repository.test.d.ts +1 -0
  162. package/dist/features/categories/repository/__tests__/categories.repository.test.js +813 -0
  163. package/dist/features/categories/schemas/firestore.d.ts +2 -4
  164. package/dist/features/categories/schemas/index.d.ts +4 -4
  165. package/dist/features/events/components/EventCard.js +1 -0
  166. package/dist/features/events/repository/__tests__/event.repository.test.d.ts +1 -0
  167. package/dist/features/events/repository/__tests__/event.repository.test.js +299 -0
  168. package/dist/features/events/schemas/firestore.d.ts +5 -4
  169. package/dist/features/events/schemas/index.d.ts +836 -16
  170. package/dist/features/events/schemas/index.js +80 -1
  171. package/dist/features/events/types/index.d.ts +4 -1
  172. package/dist/features/faq/repository/__tests__/faqs.repository.test.d.ts +1 -0
  173. package/dist/features/faq/repository/__tests__/faqs.repository.test.js +311 -0
  174. package/dist/features/faq/schemas/firestore.d.ts +2 -4
  175. package/dist/features/faq/schemas/index.d.ts +2 -2
  176. package/dist/features/grouped/schemas/index.d.ts +2 -2
  177. package/dist/features/history/repository/__tests__/user-history.repository.test.d.ts +1 -0
  178. package/dist/features/history/repository/__tests__/user-history.repository.test.js +180 -0
  179. package/dist/features/homepage/api/[id]/route.d.ts +4 -4
  180. package/dist/features/homepage/api/carousel/[id]/route.d.ts +4 -4
  181. package/dist/features/homepage/api/carousel/route.d.ts +2 -2
  182. package/dist/features/homepage/api/route.d.ts +2 -2
  183. package/dist/features/homepage/repository/__tests__/carousel.repository.test.d.ts +1 -0
  184. package/dist/features/homepage/repository/__tests__/carousel.repository.test.js +182 -0
  185. package/dist/features/homepage/repository/__tests__/homepage-sections.repository.test.d.ts +1 -0
  186. package/dist/features/homepage/repository/__tests__/homepage-sections.repository.test.js +185 -0
  187. package/dist/features/homepage/schemas/firestore.d.ts +4 -12
  188. package/dist/features/homepage/schemas/index.d.ts +2 -2
  189. package/dist/features/lottery/repository/lottery-entry.repository.d.ts +33 -0
  190. package/dist/features/lottery/repository/lottery-entry.repository.js +130 -0
  191. package/dist/features/lottery/schemas/firestore.d.ts +49 -0
  192. package/dist/features/lottery/schemas/firestore.js +25 -0
  193. package/dist/features/lottery/schemas/zod.d.ts +113 -0
  194. package/dist/features/lottery/schemas/zod.js +39 -0
  195. package/dist/features/lottery/types/index.d.ts +67 -0
  196. package/dist/features/lottery/types/index.js +55 -0
  197. package/dist/features/messages/repository/__tests__/conversations.repository.test.d.ts +1 -0
  198. package/dist/features/messages/repository/__tests__/conversations.repository.test.js +257 -0
  199. package/dist/features/messages/schemas/firestore.d.ts +2 -4
  200. package/dist/features/messages/schemas/index.d.ts +2 -2
  201. package/dist/features/orders/repository/__tests__/orders.repository.test.d.ts +1 -0
  202. package/dist/features/orders/repository/__tests__/orders.repository.test.js +211 -0
  203. package/dist/features/orders/repository/orders.repository.d.ts +5 -0
  204. package/dist/features/orders/repository/orders.repository.js +26 -0
  205. package/dist/features/orders/schemas/firestore.d.ts +9 -5
  206. package/dist/features/orders/schemas/firestore.js +3 -0
  207. package/dist/features/payments/repository/__tests__/payout.repository.test.d.ts +1 -0
  208. package/dist/features/payments/repository/__tests__/payout.repository.test.js +292 -0
  209. package/dist/features/payments/schemas/firestore.d.ts +2 -4
  210. package/dist/features/pre-orders/schemas/index.d.ts +2 -2
  211. package/dist/features/products/api/[id]/route.d.ts +4 -4
  212. package/dist/features/products/api/route.d.ts +2 -2
  213. package/dist/features/products/constants/action-defs.d.ts +16 -0
  214. package/dist/features/products/constants/action-defs.js +16 -0
  215. package/dist/features/products/constants/listing-tabs.d.ts +48 -0
  216. package/dist/features/products/constants/listing-tabs.js +12 -0
  217. package/dist/features/products/repository/__tests__/product-features.repository.test.d.ts +1 -0
  218. package/dist/features/products/repository/__tests__/product-features.repository.test.js +329 -0
  219. package/dist/features/products/repository/__tests__/products.repository.test.d.ts +1 -0
  220. package/dist/features/products/repository/__tests__/products.repository.test.js +607 -0
  221. package/dist/features/products/repository/products.repository.d.ts +37 -0
  222. package/dist/features/products/repository/products.repository.js +28 -1
  223. package/dist/features/products/schemas/firestore.d.ts +23 -7
  224. package/dist/features/products/schemas/firestore.js +2 -0
  225. package/dist/features/products/schemas/index.d.ts +18 -18
  226. package/dist/features/products/schemas/index.js +4 -2
  227. package/dist/features/products/types/index.d.ts +3 -1
  228. package/dist/features/promotions/repository/__tests__/claimed-coupons.repository.test.d.ts +1 -0
  229. package/dist/features/promotions/repository/__tests__/claimed-coupons.repository.test.js +219 -0
  230. package/dist/features/promotions/repository/__tests__/coupons.repository.test.d.ts +1 -0
  231. package/dist/features/promotions/repository/__tests__/coupons.repository.test.js +480 -0
  232. package/dist/features/promotions/schemas/firestore.d.ts +2 -4
  233. package/dist/features/promotions/schemas/index.d.ts +4 -4
  234. package/dist/features/reviews/api/[id]/route.d.ts +4 -4
  235. package/dist/features/reviews/api/route.d.ts +2 -2
  236. package/dist/features/reviews/repository/__tests__/reviews.repository.test.d.ts +1 -0
  237. package/dist/features/reviews/repository/__tests__/reviews.repository.test.js +327 -0
  238. package/dist/features/reviews/schemas/firestore.d.ts +2 -4
  239. package/dist/features/reviews/schemas/index.d.ts +2 -2
  240. package/dist/features/scams/repository/__tests__/scammer.repository.test.d.ts +1 -0
  241. package/dist/features/scams/repository/__tests__/scammer.repository.test.js +385 -0
  242. package/dist/features/scams/schemas/firestore.d.ts +2 -4
  243. package/dist/features/scams/schemas/index.d.ts +4 -4
  244. package/dist/features/search/repository/__tests__/search.repository.test.d.ts +1 -0
  245. package/dist/features/search/repository/__tests__/search.repository.test.js +369 -0
  246. package/dist/features/search/schemas/index.d.ts +2 -2
  247. package/dist/features/seller/api/coupons/route.d.ts +2 -2
  248. package/dist/features/seller/api/offers/route.d.ts +2 -2
  249. package/dist/features/seller/api/products/route.d.ts +2 -2
  250. package/dist/features/seller/api/store/route.d.ts +2 -2
  251. package/dist/features/seller/components/BarcodeField.d.ts +17 -0
  252. package/dist/features/seller/components/BarcodeField.js +30 -0
  253. package/dist/features/seller/components/FulfillmentView.d.ts +5 -0
  254. package/dist/features/seller/components/FulfillmentView.js +120 -0
  255. package/dist/features/seller/components/PrintCenterView.d.ts +3 -1
  256. package/dist/features/seller/components/PrintCenterView.js +52 -4
  257. package/dist/features/seller/components/SellerProductShell.d.ts +2 -0
  258. package/dist/features/seller/components/SellerProductShell.js +2 -1
  259. package/dist/features/seller/components/index.d.ts +4 -0
  260. package/dist/features/seller/components/index.js +2 -0
  261. package/dist/features/seller/repository/__tests__/offer.repository.test.d.ts +1 -0
  262. package/dist/features/seller/repository/__tests__/offer.repository.test.js +458 -0
  263. package/dist/features/seller/schemas/index.d.ts +2 -2
  264. package/dist/features/store-extensions/schemas/firestore.d.ts +12 -44
  265. package/dist/features/stores/components/StoreClassifiedsListing.d.ts +5 -0
  266. package/dist/features/stores/components/StoreClassifiedsListing.js +48 -0
  267. package/dist/features/stores/components/StoreClassifiedsPageView.d.ts +4 -0
  268. package/dist/features/stores/components/StoreClassifiedsPageView.js +20 -0
  269. package/dist/features/stores/components/StoreDetailLayoutView.js +23 -2
  270. package/dist/features/stores/components/StoreDigitalCodesListing.d.ts +5 -0
  271. package/dist/features/stores/components/StoreDigitalCodesListing.js +48 -0
  272. package/dist/features/stores/components/StoreDigitalCodesPageView.d.ts +4 -0
  273. package/dist/features/stores/components/StoreDigitalCodesPageView.js +20 -0
  274. package/dist/features/stores/components/StoreLiveItemsListing.d.ts +5 -0
  275. package/dist/features/stores/components/StoreLiveItemsListing.js +48 -0
  276. package/dist/features/stores/components/StoreLiveItemsPageView.d.ts +4 -0
  277. package/dist/features/stores/components/StoreLiveItemsPageView.js +20 -0
  278. package/dist/features/stores/components/index.d.ts +9 -0
  279. package/dist/features/stores/components/index.js +3 -0
  280. package/dist/features/stores/repository/__tests__/store.repository.test.d.ts +1 -0
  281. package/dist/features/stores/repository/__tests__/store.repository.test.js +261 -0
  282. package/dist/features/stores/schemas/firestore.d.ts +2 -4
  283. package/dist/features/stores/schemas/index.d.ts +4 -4
  284. package/dist/features/support/repository/__tests__/support.repository.test.d.ts +1 -0
  285. package/dist/features/support/repository/__tests__/support.repository.test.js +312 -0
  286. package/dist/features/support/schemas/firestore.d.ts +2 -4
  287. package/dist/features/support/schemas/index.d.ts +2 -2
  288. package/dist/features/wishlist/repository/__tests__/user-wishlist.repository.test.d.ts +1 -0
  289. package/dist/features/wishlist/repository/__tests__/user-wishlist.repository.test.js +139 -0
  290. package/dist/index.d.ts +14 -0
  291. package/dist/index.js +17 -0
  292. package/dist/next/api/routeHandler.d.ts +1 -1
  293. package/dist/next/routing/route-map.d.ts +24 -0
  294. package/dist/next/routing/route-map.js +11 -0
  295. package/dist/repositories/index.d.ts +1 -0
  296. package/dist/repositories/index.js +2 -0
  297. package/dist/schemas/registry.d.ts +24 -24
  298. package/dist/security/index.d.ts +1 -1
  299. package/dist/security/index.js +1 -1
  300. package/dist/security/pii-schemas.d.ts +2 -0
  301. package/dist/security/pii-schemas.js +6 -0
  302. package/dist/seed/actions/demo-seed-actions.d.ts +1 -1
  303. package/dist/seed/events-seed-data.js +85 -2
  304. package/dist/seed/grouped-listings-seed-data.d.ts +5 -2
  305. package/dist/seed/index.d.ts +1 -0
  306. package/dist/seed/index.js +1 -0
  307. package/dist/seed/lottery-entries-seed-data.d.ts +2 -0
  308. package/dist/seed/lottery-entries-seed-data.js +108 -0
  309. package/dist/seed/manifest.js +1 -0
  310. package/dist/seed/products-preorders-seed-data.d.ts +5 -2
  311. package/dist/seed/products-standard-seed-data.js +8 -0
  312. package/dist/server-entry.d.ts +3 -0
  313. package/dist/server-entry.js +3 -0
  314. package/dist/server.d.ts +10 -4
  315. package/dist/server.js +6 -0
  316. package/dist/styles.css +1 -1
  317. package/dist/tailwind-utilities.css +1 -1
  318. package/dist/utils/id-generators.d.ts +8 -0
  319. package/dist/utils/id-generators.js +14 -0
  320. package/package.json +2 -1
@@ -0,0 +1,257 @@
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ import { makeMockDb } from "../../../../../tests/helpers/mock-firestore";
3
+ const { db, mockDocRef, mockCollection, mockQuery, mockTxn } = makeMockDb();
4
+ vi.mock("../../../../providers/db-firebase", () => ({
5
+ getAdminDb: () => db,
6
+ }));
7
+ vi.mock("../../../../monitoring", () => ({
8
+ serverLogger: { info: vi.fn(), warn: vi.fn(), error: vi.fn() },
9
+ }));
10
+ vi.mock("../../../../errors/normalize", () => ({
11
+ normalizeError: vi.fn(),
12
+ }));
13
+ import { ConversationsRepository } from "../conversations.repository";
14
+ const repo = new ConversationsRepository();
15
+ function makeConvData(overrides = {}) {
16
+ return {
17
+ buyerId: "user-ravi",
18
+ buyerDisplayName: "Ravi Kumar",
19
+ storeId: "store-pokemon-palace",
20
+ storeName: "Pokemon Palace",
21
+ sellerDisplayName: "Misty Singh",
22
+ productId: "product-charizard",
23
+ productTitle: "Charizard PSA9",
24
+ messages: [],
25
+ lastMessage: "",
26
+ lastMessageAt: new Date(),
27
+ unreadBuyer: 0,
28
+ unreadSeller: 0,
29
+ status: "active",
30
+ createdAt: new Date(),
31
+ updatedAt: new Date(),
32
+ ...overrides,
33
+ };
34
+ }
35
+ beforeEach(() => {
36
+ vi.clearAllMocks();
37
+ db.collection.mockReturnValue(mockCollection);
38
+ mockCollection.doc.mockReturnValue(mockDocRef);
39
+ mockCollection.where.mockReturnValue(mockQuery);
40
+ mockQuery.where.mockReturnValue(mockQuery);
41
+ mockQuery.orderBy.mockReturnValue(mockQuery);
42
+ mockQuery.get.mockResolvedValue({ docs: [], empty: true, size: 0 });
43
+ mockDocRef.get.mockResolvedValue({ exists: false, id: "mock-id", data: () => ({}) });
44
+ mockDocRef.update.mockResolvedValue(undefined);
45
+ db.runTransaction.mockImplementation(async (fn) => fn(mockTxn));
46
+ mockTxn.get.mockResolvedValue({ exists: false, id: "mock-id", data: () => ({}) });
47
+ mockTxn.set.mockReturnValue(undefined);
48
+ mockTxn.update.mockReturnValue(undefined);
49
+ });
50
+ // ---------------------------------------------------------------------------
51
+ // findOrCreateByContext
52
+ // ---------------------------------------------------------------------------
53
+ describe("ConversationsRepository.findOrCreateByContext", () => {
54
+ it("generates stable ID: conv-{buyerId}-{storeId}-{productId}", async () => {
55
+ const convData = makeConvData();
56
+ mockTxn.get.mockResolvedValue({ exists: true, id: "conv-user-ravi-store-pokemon-palace-product-charizard", data: () => convData });
57
+ const result = await repo.findOrCreateByContext({
58
+ buyerId: "user-ravi",
59
+ buyerDisplayName: "Ravi Kumar",
60
+ storeId: "store-pokemon-palace",
61
+ storeName: "Pokemon Palace",
62
+ sellerDisplayName: "Misty Singh",
63
+ productId: "product-charizard",
64
+ });
65
+ expect(mockCollection.doc).toHaveBeenCalledWith("conv-user-ravi-store-pokemon-palace-product-charizard");
66
+ expect(result.buyerId).toBe("user-ravi");
67
+ });
68
+ it("uses 'general' productKey when productId is not provided", async () => {
69
+ const convData = makeConvData({ productId: undefined });
70
+ mockTxn.get.mockResolvedValue({ exists: true, id: "conv-user-ravi-store-1-general", data: () => convData });
71
+ await repo.findOrCreateByContext({
72
+ buyerId: "user-ravi",
73
+ buyerDisplayName: "Ravi",
74
+ storeId: "store-1",
75
+ storeName: "Store 1",
76
+ sellerDisplayName: "Seller 1",
77
+ });
78
+ expect(mockCollection.doc).toHaveBeenCalledWith("conv-user-ravi-store-1-general");
79
+ });
80
+ it("returns existing conversation without creating a new one (idempotent)", async () => {
81
+ const convData = makeConvData();
82
+ mockTxn.get.mockResolvedValue({ exists: true, id: "conv-abc", data: () => convData });
83
+ await repo.findOrCreateByContext({
84
+ buyerId: "user-ravi",
85
+ buyerDisplayName: "Ravi",
86
+ storeId: "store-1",
87
+ storeName: "Store 1",
88
+ sellerDisplayName: "Seller",
89
+ });
90
+ expect(mockTxn.set).not.toHaveBeenCalled();
91
+ });
92
+ it("creates a new conversation when one does not exist", async () => {
93
+ mockTxn.get.mockResolvedValue({ exists: false, id: "conv-new", data: () => ({}) });
94
+ await repo.findOrCreateByContext({
95
+ buyerId: "user-new",
96
+ buyerDisplayName: "New Buyer",
97
+ storeId: "store-new",
98
+ storeName: "New Store",
99
+ sellerDisplayName: "New Seller",
100
+ });
101
+ expect(mockTxn.set).toHaveBeenCalledOnce();
102
+ });
103
+ it("new conversation starts with messages=[], unreadBuyer=0, unreadSeller=0", async () => {
104
+ mockTxn.get.mockResolvedValue({ exists: false, id: "conv-new", data: () => ({}) });
105
+ const result = await repo.findOrCreateByContext({
106
+ buyerId: "user-new",
107
+ buyerDisplayName: "New",
108
+ storeId: "store-new",
109
+ storeName: "New Store",
110
+ sellerDisplayName: "Seller",
111
+ });
112
+ expect(result.messages).toHaveLength(0);
113
+ expect(result.unreadBuyer).toBe(0);
114
+ expect(result.unreadSeller).toBe(0);
115
+ });
116
+ it("uses Firestore transaction for atomicity", async () => {
117
+ mockTxn.get.mockResolvedValue({ exists: false, id: "conv-new", data: () => ({}) });
118
+ await repo.findOrCreateByContext({
119
+ buyerId: "user-a",
120
+ buyerDisplayName: "A",
121
+ storeId: "store-b",
122
+ storeName: "B",
123
+ sellerDisplayName: "Seller",
124
+ });
125
+ expect(db.runTransaction).toHaveBeenCalledOnce();
126
+ });
127
+ });
128
+ // ---------------------------------------------------------------------------
129
+ // appendMessage
130
+ // ---------------------------------------------------------------------------
131
+ describe("ConversationsRepository.appendMessage", () => {
132
+ it("increments unreadBuyer when seller sends a message", async () => {
133
+ const convData = makeConvData({ unreadBuyer: 0, unreadSeller: 0 });
134
+ mockTxn.get.mockResolvedValue({ exists: true, id: "conv-1", data: () => convData });
135
+ const result = await repo.appendMessage("conv-1", {
136
+ senderId: "seller-uid",
137
+ senderRole: "seller",
138
+ body: "Hello buyer!",
139
+ });
140
+ expect(result.unreadBuyer).toBe(1);
141
+ expect(result.unreadSeller).toBe(0);
142
+ });
143
+ it("increments unreadSeller when buyer sends a message", async () => {
144
+ const convData = makeConvData({ unreadBuyer: 0, unreadSeller: 2 });
145
+ mockTxn.get.mockResolvedValue({ exists: true, id: "conv-1", data: () => convData });
146
+ const result = await repo.appendMessage("conv-1", {
147
+ senderId: "buyer-uid",
148
+ senderRole: "buyer",
149
+ body: "Hello seller!",
150
+ });
151
+ expect(result.unreadSeller).toBe(3);
152
+ expect(result.unreadBuyer).toBe(0);
153
+ });
154
+ it("appends the new message to the existing messages array", async () => {
155
+ const existingMsg = {
156
+ id: "msg-old",
157
+ senderId: "seller-uid",
158
+ senderRole: "seller",
159
+ body: "Previous message",
160
+ isRead: false,
161
+ sentAt: new Date(),
162
+ };
163
+ const convData = makeConvData({ messages: [existingMsg] });
164
+ mockTxn.get.mockResolvedValue({ exists: true, id: "conv-1", data: () => convData });
165
+ const result = await repo.appendMessage("conv-1", {
166
+ senderId: "buyer-uid",
167
+ senderRole: "buyer",
168
+ body: "New message",
169
+ });
170
+ expect(result.messages).toHaveLength(2);
171
+ expect(result.messages[1].body).toBe("New message");
172
+ });
173
+ it("sets isRead: false on the new message", async () => {
174
+ const convData = makeConvData();
175
+ mockTxn.get.mockResolvedValue({ exists: true, id: "conv-1", data: () => convData });
176
+ const result = await repo.appendMessage("conv-1", {
177
+ senderId: "buyer-uid",
178
+ senderRole: "buyer",
179
+ body: "Test",
180
+ });
181
+ expect(result.messages[0].isRead).toBe(false);
182
+ });
183
+ it("updates lastMessage and lastMessageAt", async () => {
184
+ const convData = makeConvData();
185
+ mockTxn.get.mockResolvedValue({ exists: true, id: "conv-1", data: () => convData });
186
+ const result = await repo.appendMessage("conv-1", {
187
+ senderId: "buyer-uid",
188
+ senderRole: "buyer",
189
+ body: "Latest message",
190
+ });
191
+ expect(result.lastMessage).toBe("Latest message");
192
+ expect(result.lastMessageAt).toBeInstanceOf(Date);
193
+ });
194
+ it("uses Firestore transaction", async () => {
195
+ const convData = makeConvData();
196
+ mockTxn.get.mockResolvedValue({ exists: true, id: "conv-1", data: () => convData });
197
+ await repo.appendMessage("conv-1", { senderId: "uid", senderRole: "buyer", body: "msg" });
198
+ expect(db.runTransaction).toHaveBeenCalledOnce();
199
+ expect(mockTxn.update).toHaveBeenCalledOnce();
200
+ });
201
+ it("throws when conversation not found", async () => {
202
+ mockTxn.get.mockResolvedValue({ exists: false, id: "conv-ghost", data: () => ({}) });
203
+ await expect(repo.appendMessage("conv-ghost", { senderId: "uid", senderRole: "buyer", body: "msg" })).rejects.toThrow(/not found/i);
204
+ });
205
+ });
206
+ // ---------------------------------------------------------------------------
207
+ // markRead
208
+ // ---------------------------------------------------------------------------
209
+ describe("ConversationsRepository.markRead", () => {
210
+ it("zeroes unreadBuyer when role=buyer", async () => {
211
+ const sellerMsg = { id: "m1", senderId: "seller", senderRole: "seller", body: "Hi", isRead: false, sentAt: new Date() };
212
+ const convData = makeConvData({ unreadBuyer: 3, unreadSeller: 1, messages: [sellerMsg] });
213
+ mockTxn.get.mockResolvedValue({ exists: true, id: "conv-1", data: () => convData });
214
+ await repo.markRead("conv-1", "buyer");
215
+ const updateArg = mockTxn.update.mock.calls[0][1];
216
+ expect(updateArg.unreadBuyer).toBe(0);
217
+ });
218
+ it("does NOT touch unreadSeller when buyer reads", async () => {
219
+ const convData = makeConvData({ unreadBuyer: 2, unreadSeller: 5 });
220
+ mockTxn.get.mockResolvedValue({ exists: true, id: "conv-1", data: () => convData });
221
+ await repo.markRead("conv-1", "buyer");
222
+ const updateArg = mockTxn.update.mock.calls[0][1];
223
+ expect(updateArg).not.toHaveProperty("unreadSeller");
224
+ });
225
+ it("zeroes unreadSeller when role=seller", async () => {
226
+ const buyerMsg = { id: "m1", senderId: "buyer", senderRole: "buyer", body: "Hi", isRead: false, sentAt: new Date() };
227
+ const convData = makeConvData({ unreadBuyer: 2, unreadSeller: 4, messages: [buyerMsg] });
228
+ mockTxn.get.mockResolvedValue({ exists: true, id: "conv-1", data: () => convData });
229
+ await repo.markRead("conv-1", "seller");
230
+ const updateArg = mockTxn.update.mock.calls[0][1];
231
+ expect(updateArg.unreadSeller).toBe(0);
232
+ });
233
+ it("marks seller-sent messages as isRead=true when buyer reads", async () => {
234
+ const sellerMsg = { id: "m1", senderId: "seller", senderRole: "seller", body: "Hi", isRead: false, sentAt: new Date() };
235
+ const convData = makeConvData({ messages: [sellerMsg] });
236
+ mockTxn.get.mockResolvedValue({ exists: true, id: "conv-1", data: () => convData });
237
+ await repo.markRead("conv-1", "buyer");
238
+ const updateArg = mockTxn.update.mock.calls[0][1];
239
+ const msgs = updateArg.messages;
240
+ expect(msgs[0].isRead).toBe(true);
241
+ });
242
+ it("does NOT mark buyer-sent messages when buyer reads (only marks counterparty)", async () => {
243
+ const buyerMsg = { id: "m1", senderId: "buyer", senderRole: "buyer", body: "Hi", isRead: false, sentAt: new Date() };
244
+ const convData = makeConvData({ messages: [buyerMsg] });
245
+ mockTxn.get.mockResolvedValue({ exists: true, id: "conv-1", data: () => convData });
246
+ await repo.markRead("conv-1", "buyer");
247
+ const updateArg = mockTxn.update.mock.calls[0][1];
248
+ const msgs = updateArg.messages;
249
+ expect(msgs[0].isRead).toBe(false);
250
+ });
251
+ it("uses Firestore transaction", async () => {
252
+ const convData = makeConvData();
253
+ mockTxn.get.mockResolvedValue({ exists: true, id: "conv-1", data: () => convData });
254
+ await repo.markRead("conv-1", "buyer");
255
+ expect(db.runTransaction).toHaveBeenCalledOnce();
256
+ });
257
+ });
@@ -5,6 +5,7 @@
5
5
  * Messages are embedded as an array for seed purposes; production can migrate to
6
6
  * a subcollection when the thread exceeds ~200 messages.
7
7
  */
8
+ import type { BaseDocument } from "../../../_internal/shared/types/base-document";
8
9
  export interface ConversationMessage {
9
10
  id: string;
10
11
  senderId: string;
@@ -14,8 +15,7 @@ export interface ConversationMessage {
14
15
  sentAt: Date;
15
16
  attachments?: string[];
16
17
  }
17
- export interface ConversationDocument {
18
- id: string;
18
+ export interface ConversationDocument extends BaseDocument {
19
19
  buyerId: string;
20
20
  buyerDisplayName: string;
21
21
  storeId: string;
@@ -29,8 +29,6 @@ export interface ConversationDocument {
29
29
  unreadBuyer: number;
30
30
  unreadSeller: number;
31
31
  status: "active" | "archived" | "blocked";
32
- createdAt: Date;
33
- updatedAt: Date;
34
32
  }
35
33
  export declare const CONVERSATIONS_COLLECTION: "conversations";
36
34
  export declare const CONVERSATIONS_INDEXED_FIELDS: readonly ["buyerId", "storeId", "productId", "status", "lastMessageAt", "createdAt"];
@@ -112,8 +112,8 @@ export declare const conversationFirestoreSchema: z.ZodObject<{
112
112
  createdAt: string | Date | z.objectOutputType<{
113
113
  toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
114
114
  }, z.ZodTypeAny, "passthrough">;
115
- id: string;
116
115
  storeName: string;
116
+ id: string;
117
117
  updatedAt: string | Date | z.objectOutputType<{
118
118
  toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
119
119
  }, z.ZodTypeAny, "passthrough">;
@@ -145,8 +145,8 @@ export declare const conversationFirestoreSchema: z.ZodObject<{
145
145
  createdAt: string | Date | z.objectInputType<{
146
146
  toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
147
147
  }, z.ZodTypeAny, "passthrough">;
148
- id: string;
149
148
  storeName: string;
149
+ id: string;
150
150
  updatedAt: string | Date | z.objectInputType<{
151
151
  toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
152
152
  }, z.ZodTypeAny, "passthrough">;
@@ -0,0 +1,211 @@
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ import { makeMockDb, makeSnap, makeQuerySnap } from "../../../../../tests/helpers/mock-firestore";
3
+ const { db, mockDocRef, mockCollection, mockQuery, mockBatch } = makeMockDb();
4
+ vi.mock("../../../../providers/db-firebase", () => ({
5
+ getAdminDb: () => db,
6
+ prepareForFirestore: (data) => data,
7
+ BaseRepository: class {
8
+ get db() { return db; }
9
+ constructor(col) { this.collection = col; }
10
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
11
+ getCollection() { return db.collection(this.collection); }
12
+ mapDoc(snap) {
13
+ return { id: snap.id, ...snap.data() };
14
+ }
15
+ async findById(id) {
16
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
17
+ const snap = await db.collection(this.collection).doc(id).get();
18
+ return snap.exists ? { id: snap.id, ...snap.data() } : null;
19
+ }
20
+ async findBy(field, value) {
21
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
22
+ const snap = await db.collection(this.collection).where(field, "==", value).get();
23
+ return snap.docs.map((d) => ({ id: d.id, ...d.data() }));
24
+ }
25
+ async update(id, data) {
26
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
27
+ await db.collection(this.collection).doc(id).update(data);
28
+ return { id, ...data };
29
+ }
30
+ },
31
+ }));
32
+ vi.mock("../../../../monitoring", () => ({
33
+ serverLogger: { info: vi.fn(), warn: vi.fn(), error: vi.fn() },
34
+ }));
35
+ vi.mock("../../../../errors/normalize", () => ({
36
+ normalizeError: vi.fn(),
37
+ }));
38
+ vi.mock("../../../../security", () => ({
39
+ ORDER_PII_FIELDS: ["shippingAddress.phone", "shippingAddress.fullName"],
40
+ encryptPiiFields: (data) => data,
41
+ decryptPiiFields: (data) => data,
42
+ }));
43
+ vi.mock("../../../../contracts/field-ops", () => ({
44
+ serverTimestamp: () => new Date(),
45
+ }));
46
+ vi.mock("../../schemas", async () => ({
47
+ ORDER_COLLECTION: "orders",
48
+ OrderStatusValues: {
49
+ PENDING: "pending",
50
+ CONFIRMED: "confirmed",
51
+ PROCESSING: "processing",
52
+ SHIPPED: "shipped",
53
+ DELIVERED: "delivered",
54
+ CANCELLED: "cancelled",
55
+ REFUNDED: "refunded",
56
+ },
57
+ createOrderId: () => "order-1-20260101-abc123",
58
+ }));
59
+ import { OrderRepository } from "../orders.repository";
60
+ const repo = new OrderRepository();
61
+ beforeEach(() => {
62
+ vi.clearAllMocks();
63
+ mockQuery.get.mockResolvedValue(makeQuerySnap([]));
64
+ mockDocRef.get.mockResolvedValue(makeSnap(null));
65
+ mockDocRef.update.mockResolvedValue(undefined);
66
+ mockDocRef.delete.mockResolvedValue(undefined);
67
+ mockCollection.doc.mockReturnValue(mockDocRef);
68
+ db.collection.mockReturnValue(mockCollection);
69
+ db.batch.mockReturnValue(mockBatch);
70
+ });
71
+ describe("OrderRepository.cancelOrder", () => {
72
+ it("sets status: cancelled", async () => {
73
+ mockDocRef.update.mockResolvedValue(undefined);
74
+ await repo.cancelOrder("order-1", "user changed mind");
75
+ expect(mockDocRef.update).toHaveBeenCalledWith(expect.objectContaining({ status: "cancelled" }));
76
+ });
77
+ it("stores cancellation reason", async () => {
78
+ await repo.cancelOrder("order-1", "payment failed");
79
+ expect(mockDocRef.update).toHaveBeenCalledWith(expect.objectContaining({ cancellationReason: "payment failed" }));
80
+ });
81
+ });
82
+ describe("OrderRepository.updateStatus", () => {
83
+ it("updates status and updatedAt", async () => {
84
+ await repo.updateStatus("order-1", "shipped");
85
+ expect(mockDocRef.update).toHaveBeenCalledWith(expect.objectContaining({ status: "shipped", updatedAt: expect.any(Date) }));
86
+ });
87
+ });
88
+ describe("OrderRepository.hasUserPurchased", () => {
89
+ it("returns true when confirmed order exists for user + product", async () => {
90
+ const docs = makeQuerySnap([
91
+ { id: "o1", data: { userId: "user-1", productId: "product-x", status: "confirmed" } },
92
+ ]);
93
+ mockQuery.get.mockResolvedValue(docs);
94
+ const result = await repo.hasUserPurchased("user-1", "product-x");
95
+ expect(result).toBe(true);
96
+ });
97
+ it("returns true for DELIVERED status", async () => {
98
+ const docs = makeQuerySnap([
99
+ { id: "o1", data: { userId: "user-1", productId: "product-x", status: "delivered" } },
100
+ ]);
101
+ mockQuery.get.mockResolvedValue(docs);
102
+ const result = await repo.hasUserPurchased("user-1", "product-x");
103
+ expect(result).toBe(true);
104
+ });
105
+ it("returns false for CANCELLED status", async () => {
106
+ const docs = makeQuerySnap([
107
+ { id: "o1", data: { userId: "user-1", productId: "product-x", status: "cancelled" } },
108
+ ]);
109
+ mockQuery.get.mockResolvedValue(docs);
110
+ const result = await repo.hasUserPurchased("user-1", "product-x");
111
+ expect(result).toBe(false);
112
+ });
113
+ it("returns false when no orders exist", async () => {
114
+ mockQuery.get.mockResolvedValue(makeQuerySnap([]));
115
+ const result = await repo.hasUserPurchased("user-1", "product-x");
116
+ expect(result).toBe(false);
117
+ });
118
+ });
119
+ describe("OrderRepository.countByUserAndProduct", () => {
120
+ it("returns query size (active statuses)", async () => {
121
+ mockQuery.get.mockResolvedValue({ ...makeQuerySnap([
122
+ { id: "o1", data: { status: "pending" } },
123
+ { id: "o2", data: { status: "delivered" } },
124
+ ]), size: 2 });
125
+ const count = await repo.countByUserAndProduct("user-1", "product-x");
126
+ expect(count).toBe(2);
127
+ });
128
+ });
129
+ describe("OrderRepository.getTimedOutPending", () => {
130
+ it("filters by status=pending, paymentStatus=pending, createdAt < cutoff", async () => {
131
+ mockQuery.get.mockResolvedValue(makeQuerySnap([]));
132
+ await repo.getTimedOutPending(24);
133
+ expect(mockQuery.where).toHaveBeenCalledWith("status", "==", "pending");
134
+ expect(mockQuery.where).toHaveBeenCalledWith("paymentStatus", "==", "pending");
135
+ expect(mockQuery.where).toHaveBeenCalledWith("createdAt", "<", expect.any(Date));
136
+ });
137
+ it("returns docs with id, ref, and data", async () => {
138
+ const docs = makeQuerySnap([
139
+ { id: "o-timeout", data: { status: "pending", paymentStatus: "pending" } },
140
+ ]);
141
+ // Attach .ref to each doc
142
+ docs.docs[0].ref = { id: "o-timeout" };
143
+ mockQuery.get.mockResolvedValue(docs);
144
+ const result = await repo.getTimedOutPending(24);
145
+ expect(result[0].id).toBe("o-timeout");
146
+ expect(result[0].data).toBeDefined();
147
+ });
148
+ });
149
+ describe("OrderRepository.cancelInBatch", () => {
150
+ it("stages status: cancelled in caller batch, does NOT commit", () => {
151
+ const ref = { id: "order-1" };
152
+ repo.cancelInBatch(mockBatch, ref);
153
+ expect(mockBatch.update).toHaveBeenCalledWith(ref, expect.objectContaining({ status: "cancelled", cancellationReason: "payment_timeout" }));
154
+ expect(mockBatch.commit).not.toHaveBeenCalled();
155
+ });
156
+ });
157
+ describe("OrderRepository.markPayoutRequested", () => {
158
+ it("stages payoutStatus: requested in caller batch, does NOT commit", () => {
159
+ const ref = { id: "order-1" };
160
+ repo.markPayoutRequested(mockBatch, ref, "payout-123");
161
+ expect(mockBatch.update).toHaveBeenCalledWith(ref, expect.objectContaining({ payoutStatus: "requested", payoutId: "payout-123" }));
162
+ expect(mockBatch.commit).not.toHaveBeenCalled();
163
+ });
164
+ });
165
+ describe("OrderRepository.postRefundEvent", () => {
166
+ it("appends refund event to refunds array, sets contestable: false", async () => {
167
+ mockDocRef.get.mockResolvedValue(makeSnap({
168
+ status: "delivered",
169
+ refunds: [],
170
+ totalPrice: 10000,
171
+ }));
172
+ const event = { type: "partial", amountInPaise: 5000, reason: "damaged", refundedBy: "admin-1", refundedAt: new Date() };
173
+ await repo.postRefundEvent("order-1", event);
174
+ expect(mockDocRef.update).toHaveBeenCalledWith(expect.objectContaining({ contestable: false, refunds: [event] }));
175
+ });
176
+ it("becomeRefunded=true → sets status: refunded", async () => {
177
+ mockDocRef.get.mockResolvedValue(makeSnap({ status: "delivered", refunds: [], totalPrice: 10000 }));
178
+ const event = { type: "full", amountInPaise: 10000, reason: "return", refundedBy: "admin-1", refundedAt: new Date() };
179
+ await repo.postRefundEvent("order-1", event, true);
180
+ expect(mockDocRef.update).toHaveBeenCalledWith(expect.objectContaining({ status: "refunded" }));
181
+ });
182
+ it("order not found → throws NotFoundError", async () => {
183
+ mockDocRef.get.mockResolvedValue(makeSnap(null));
184
+ const { NotFoundError } = await import("../../../../errors");
185
+ await expect(repo.postRefundEvent("nonexistent", {})).rejects.toBeInstanceOf(NotFoundError);
186
+ });
187
+ });
188
+ describe("OrderRepository.createFromAuction", () => {
189
+ it("stages order creation in caller batch with correct fields", () => {
190
+ mockCollection.doc.mockReturnValue({ ...mockDocRef, id: "new-order-id" });
191
+ repo.createFromAuction(mockBatch, {
192
+ productId: "auction-test",
193
+ productTitle: "Test Auction",
194
+ userId: "user-1",
195
+ userName: "Ravi Kumar",
196
+ userEmail: "ravi@example.com",
197
+ storeId: "store-1",
198
+ amount: 10000,
199
+ currency: "INR",
200
+ auctionProductId: "auction-test",
201
+ });
202
+ expect(mockBatch.create).toHaveBeenCalledWith(expect.anything(), expect.objectContaining({
203
+ productId: "auction-test",
204
+ userId: "user-1",
205
+ storeId: "store-1",
206
+ totalPrice: 10000,
207
+ status: "confirmed",
208
+ }));
209
+ expect(mockBatch.commit).not.toHaveBeenCalled();
210
+ });
211
+ });
@@ -15,6 +15,11 @@ declare class OrderRepository extends BaseRepository<OrderDocument> {
15
15
  findConfirmed(): Promise<OrderDocument[]>;
16
16
  findPending(): Promise<OrderDocument[]>;
17
17
  updateStatus(orderId: string, status: OrderStatus, additionalData?: Partial<OrderDocument>): Promise<OrderDocument>;
18
+ assignWorker(orderId: string, workerId: string): Promise<OrderDocument>;
19
+ unassignWorker(orderId: string): Promise<OrderDocument>;
20
+ markPicked(orderId: string): Promise<OrderDocument>;
21
+ markPacked(orderId: string): Promise<OrderDocument>;
22
+ findFulfillmentQueue(storeId: string): Promise<OrderDocument[]>;
18
23
  updatePaymentStatus(orderId: string, paymentStatus: PaymentStatus, paymentId?: string): Promise<OrderDocument>;
19
24
  cancelOrder(orderId: string, reason: string, refundAmount?: number): Promise<OrderDocument>;
20
25
  findRecentByUser(userId: string): Promise<OrderDocument[]>;
@@ -71,6 +71,32 @@ class OrderRepository extends BaseRepository {
71
71
  updatedAt: new Date(),
72
72
  });
73
73
  }
74
+ async assignWorker(orderId, workerId) {
75
+ return this.update(orderId, { assignedWorkerId: workerId, updatedAt: new Date() });
76
+ }
77
+ async unassignWorker(orderId) {
78
+ return this.update(orderId, { assignedWorkerId: undefined, updatedAt: new Date() });
79
+ }
80
+ async markPicked(orderId) {
81
+ const order = await this.findById(orderId);
82
+ if (!order)
83
+ throw new NotFoundError(`Order ${orderId} not found`);
84
+ const nextStatus = order.status === "confirmed" ? "processing" : order.status;
85
+ return this.update(orderId, { pickedAt: new Date(), status: nextStatus, updatedAt: new Date() });
86
+ }
87
+ async markPacked(orderId) {
88
+ return this.update(orderId, { packedAt: new Date(), updatedAt: new Date() });
89
+ }
90
+ async findFulfillmentQueue(storeId) {
91
+ const snap = await this.db
92
+ .collection(this.collection)
93
+ .where(ORDER_FIELDS.STORE_ID, "==", storeId)
94
+ .where(ORDER_FIELDS.STATUS, "in", ["confirmed", "processing"])
95
+ .orderBy(ORDER_FIELDS.CREATED_AT, "asc")
96
+ .limit(200)
97
+ .get();
98
+ return snap.docs.map((doc) => this.decryptOrder({ id: doc.id, ...doc.data() }));
99
+ }
74
100
  async updatePaymentStatus(orderId, paymentStatus, paymentId) {
75
101
  return this.update(orderId, {
76
102
  paymentStatus,
@@ -3,6 +3,7 @@
3
3
  */
4
4
  import type { OrderStatus, PaymentStatus } from "../types";
5
5
  import type { OrderType } from "../utils/order-splitter";
6
+ import type { BaseDocument } from "../../../_internal/shared/types/base-document";
6
7
  export type ShippingMethod = "custom" | "shiprocket";
7
8
  export type RefundType = "full" | "partial";
8
9
  export type OrderPayoutStatus = "eligible" | "requested" | "paid";
@@ -99,8 +100,7 @@ export interface AppliedOrderDiscount {
99
100
  scope?: "admin" | "seller";
100
101
  storeId?: string;
101
102
  }
102
- export interface OrderDocument {
103
- id: string;
103
+ export interface OrderDocument extends BaseDocument {
104
104
  productId: string;
105
105
  productTitle: string;
106
106
  userId: string;
@@ -203,11 +203,15 @@ export interface OrderDocument {
203
203
  shelf: string;
204
204
  bin: string;
205
205
  };
206
- createdAt: Date;
207
- updatedAt: Date;
206
+ /** UID of the employee or seller assigned to fulfil this order. */
207
+ assignedWorkerId?: string;
208
+ /** Timestamp when all items in this order were physically confirmed picked. */
209
+ pickedAt?: Date;
210
+ /** Timestamp when the order was packed and ready for courier handoff. */
211
+ packedAt?: Date;
208
212
  }
209
213
  export declare const ORDER_COLLECTION: "orders";
210
- export declare const ORDER_INDEXED_FIELDS: readonly ["userId", "productId", "storeId", "status", "paymentStatus", "payoutStatus", "shippingMethod", "orderDate", "createdAt"];
214
+ export declare const ORDER_INDEXED_FIELDS: readonly ["userId", "productId", "storeId", "status", "paymentStatus", "payoutStatus", "shippingMethod", "orderDate", "createdAt", "assignedWorkerId", "pickedAt", "packedAt"];
211
215
  export declare const DEFAULT_ORDER_DATA: Partial<OrderDocument>;
212
216
  export declare const ORDER_PUBLIC_FIELDS: readonly ["id", "productId", "productTitle", "quantity", "unitPrice", "totalPrice", "currency", "status", "paymentStatus", "shippingAddress", "trackingNumber", "notes", "orderDate", "shippingDate", "deliveryDate", "createdAt"];
213
217
  export declare const ORDER_UPDATABLE_FIELDS: readonly ["notes", "shippingAddress"];
@@ -54,6 +54,9 @@ export const ORDER_INDEXED_FIELDS = [
54
54
  "shippingMethod",
55
55
  "orderDate",
56
56
  "createdAt",
57
+ "assignedWorkerId",
58
+ "pickedAt",
59
+ "packedAt",
57
60
  ];
58
61
  export const DEFAULT_ORDER_DATA = {
59
62
  status: "pending",