@mohasinac/appkit 4.62.1 → 4.63.1

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 (263) hide show
  1. package/dist/.build-stamp.json +3 -3
  2. package/dist/_internal/client/features/layout/DashboardLayoutClient.js +8 -29
  3. package/dist/_internal/client/features/layout/filterNavItems.d.ts +28 -0
  4. package/dist/_internal/client/features/layout/filterNavItems.js +35 -0
  5. package/dist/_internal/server/features/ads/booking.d.ts +118 -0
  6. package/dist/_internal/server/features/ads/booking.js +326 -0
  7. package/dist/_internal/server/features/checkout/actions.d.ts +51 -11
  8. package/dist/_internal/server/features/checkout/actions.js +335 -80
  9. package/dist/_internal/server/features/checkout/expand-order-items.d.ts +1 -2
  10. package/dist/_internal/server/features/checkout/expand-order-items.js +32 -0
  11. package/dist/_internal/server/features/checkout/freeze-parts.d.ts +50 -0
  12. package/dist/_internal/server/features/checkout/freeze-parts.js +94 -0
  13. package/dist/_internal/server/features/checkout/value-otp-gate.d.ts +55 -0
  14. package/dist/_internal/server/features/checkout/value-otp-gate.js +60 -0
  15. package/dist/_internal/server/features/dashboard/attention.d.ts +128 -0
  16. package/dist/_internal/server/features/dashboard/attention.js +183 -0
  17. package/dist/_internal/server/features/dashboard/data.d.ts +47 -0
  18. package/dist/_internal/server/features/dashboard/data.js +82 -0
  19. package/dist/_internal/server/features/inventory/reservations.d.ts +99 -0
  20. package/dist/_internal/server/features/inventory/reservations.js +273 -0
  21. package/dist/_internal/server/features/offers/destinations.d.ts +40 -0
  22. package/dist/_internal/server/features/offers/destinations.js +65 -0
  23. package/dist/_internal/server/features/orders/adapters.js +21 -0
  24. package/dist/_internal/server/features/orders/amend-delivery.d.ts +56 -0
  25. package/dist/_internal/server/features/orders/amend-delivery.js +124 -0
  26. package/dist/_internal/server/features/orders/balance.d.ts +89 -0
  27. package/dist/_internal/server/features/orders/balance.js +256 -0
  28. package/dist/_internal/server/features/pricing/actions.d.ts +58 -0
  29. package/dist/_internal/server/features/pricing/actions.js +144 -0
  30. package/dist/_internal/server/features/shipping/book-split.d.ts +86 -0
  31. package/dist/_internal/server/features/shipping/book-split.js +130 -0
  32. package/dist/_internal/server/features/shipping/book.d.ts +61 -0
  33. package/dist/_internal/server/features/shipping/book.js +176 -0
  34. package/dist/_internal/server/features/shipping/courier-block.js +26 -1
  35. package/dist/_internal/server/features/site-settings/adapters.d.ts +1 -1
  36. package/dist/_internal/server/features/site-settings/adapters.js +14 -0
  37. package/dist/_internal/server/features/stores/adapters.d.ts +1 -1
  38. package/dist/_internal/server/features/stores/adapters.js +14 -0
  39. package/dist/_internal/server/functions/scheduled.d.ts +2 -1
  40. package/dist/_internal/server/functions/scheduled.js +57 -1
  41. package/dist/_internal/server/jobs/core/autoPayoutEligibility.js +2 -0
  42. package/dist/_internal/server/jobs/core/jobRunners.js +45 -0
  43. package/dist/_internal/server/jobs/core/onOrderStatusChange.js +4 -1
  44. package/dist/_internal/server/jobs/core/reservationExpiry.d.ts +17 -0
  45. package/dist/_internal/server/jobs/core/reservationExpiry.js +40 -0
  46. package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.js +15 -0
  47. package/dist/_internal/server/jobs/handlers/index.d.ts +1 -0
  48. package/dist/_internal/server/jobs/handlers/index.js +1 -0
  49. package/dist/_internal/server/jobs/handlers/reservationExpiry.d.ts +2 -0
  50. package/dist/_internal/server/jobs/handlers/reservationExpiry.js +2 -0
  51. package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
  52. package/dist/_internal/shared/actions/action-registry.js +268 -0
  53. package/dist/_internal/shared/checkout/order-math.d.ts +31 -2
  54. package/dist/_internal/shared/checkout/order-math.js +22 -36
  55. package/dist/_internal/shared/checkout/rules/index.d.ts +1 -1
  56. package/dist/_internal/shared/checkout/rules/index.js +1 -1
  57. package/dist/_internal/shared/checkout/rules/payment-gate.d.ts +18 -0
  58. package/dist/_internal/shared/checkout/rules/payment-gate.js +25 -0
  59. package/dist/_internal/shared/checkout/split.d.ts +0 -12
  60. package/dist/_internal/shared/checkout/split.js +22 -2
  61. package/dist/_internal/shared/content/disclaimers.js +7 -7
  62. package/dist/_internal/shared/content/published-values.d.ts +6 -1
  63. package/dist/_internal/shared/content/published-values.js +8 -0
  64. package/dist/_internal/shared/features/admin/integrations.d.ts +32 -2
  65. package/dist/_internal/shared/features/admin/integrations.js +19 -9
  66. package/dist/_internal/shared/features/dashboard/hub-sections.d.ts +72 -0
  67. package/dist/_internal/shared/features/dashboard/hub-sections.js +75 -0
  68. package/dist/_internal/shared/features/emi/choice.d.ts +98 -0
  69. package/dist/_internal/shared/features/emi/choice.js +69 -0
  70. package/dist/_internal/shared/features/emi/group.d.ts +84 -0
  71. package/dist/_internal/shared/features/emi/group.js +126 -0
  72. package/dist/_internal/shared/features/ledger/posting.d.ts +107 -0
  73. package/dist/_internal/shared/features/ledger/posting.js +165 -0
  74. package/dist/_internal/shared/features/ledger/reports.d.ts +76 -0
  75. package/dist/_internal/shared/features/ledger/reports.js +127 -0
  76. package/dist/_internal/shared/features/ledger/rules.d.ts +170 -0
  77. package/dist/_internal/shared/features/ledger/rules.js +221 -0
  78. package/dist/_internal/shared/features/offers/coordination.d.ts +122 -0
  79. package/dist/_internal/shared/features/offers/coordination.js +80 -0
  80. package/dist/_internal/shared/features/orders/delivery-snapshot.d.ts +114 -0
  81. package/dist/_internal/shared/features/orders/delivery-snapshot.js +116 -0
  82. package/dist/_internal/shared/features/payouts/pay-period.d.ts +91 -0
  83. package/dist/_internal/shared/features/payouts/pay-period.js +104 -0
  84. package/dist/_internal/shared/features/points/accepts.d.ts +1 -8
  85. package/dist/_internal/shared/features/points/accepts.js +12 -6
  86. package/dist/_internal/shared/features/pricing/rate-registry.d.ts +150 -0
  87. package/dist/_internal/shared/features/pricing/rate-registry.js +246 -0
  88. package/dist/_internal/shared/features/shipping/parcel.d.ts +123 -0
  89. package/dist/_internal/shared/features/shipping/parcel.js +139 -0
  90. package/dist/_internal/shared/features/site-settings/fees.d.ts +16 -8
  91. package/dist/_internal/shared/features/site-settings/fees.js +12 -8
  92. package/dist/_internal/shared/fees/explain.d.ts +81 -0
  93. package/dist/_internal/shared/fees/explain.js +101 -0
  94. package/dist/_internal/shared/history/index.d.ts +1 -1
  95. package/dist/_internal/shared/history/index.js +1 -1
  96. package/dist/_internal/shared/history/types.d.ts +7 -1
  97. package/dist/_internal/shared/history/types.js +25 -0
  98. package/dist/client.d.ts +11 -1
  99. package/dist/client.js +13 -0
  100. package/dist/constants/api-endpoints.d.ts +72 -0
  101. package/dist/constants/api-endpoints.js +41 -0
  102. package/dist/constants/field-names.d.ts +41 -0
  103. package/dist/constants/field-names.js +47 -0
  104. package/dist/features/account/components/UserOrdersView.js +28 -2
  105. package/dist/features/admin/components/AdminIntegrationsView.d.ts +55 -0
  106. package/dist/features/admin/components/AdminIntegrationsView.js +74 -0
  107. package/dist/features/admin/components/AdminOrderEditorView.d.ts +16 -1
  108. package/dist/features/admin/components/AdminOrderEditorView.js +72 -3
  109. package/dist/features/admin/components/AdminOrdersView.js +20 -1
  110. package/dist/features/admin/schemas/firestore.d.ts +32 -0
  111. package/dist/features/ads/schemas/booking-write.d.ts +157 -0
  112. package/dist/features/ads/schemas/booking-write.js +88 -0
  113. package/dist/features/ads/schemas/creative-form.d.ts +18 -0
  114. package/dist/features/ads/schemas/creative-form.js +51 -0
  115. package/dist/features/ads/schemas/firestore.d.ts +140 -0
  116. package/dist/features/ads/schemas/firestore.js +109 -0
  117. package/dist/features/auctions/repository/bid.repository.js +3 -1
  118. package/dist/features/audit-log/schemas/firestore.d.ts +110 -0
  119. package/dist/features/audit-log/schemas/firestore.js +74 -0
  120. package/dist/features/auth/actions/profile-actions.d.ts +69 -1
  121. package/dist/features/auth/actions/profile-actions.js +62 -1
  122. package/dist/features/auth/schemas/firestore.d.ts +16 -2
  123. package/dist/features/auth/schemas/firestore.js +2 -1
  124. package/dist/features/blog/actions/blog-actions.d.ts +6 -0
  125. package/dist/features/blog/actions/blog-actions.js +17 -2
  126. package/dist/features/blog/api/route.js +4 -1
  127. package/dist/features/blog/columns/index.js +5 -0
  128. package/dist/features/blog/components/BlogIndexPageView.js +2 -1
  129. package/dist/features/blog/repository/blog.repository.d.ts +4 -0
  130. package/dist/features/blog/repository/blog.repository.js +5 -0
  131. package/dist/features/blog/schemas/blog-form.d.ts +3 -0
  132. package/dist/features/blog/schemas/blog-form.js +1 -0
  133. package/dist/features/blog/schemas/firestore.d.ts +38 -1
  134. package/dist/features/blog/schemas/firestore.js +23 -0
  135. package/dist/features/blog/schemas/index.d.ts +6 -0
  136. package/dist/features/blog/schemas/index.js +2 -0
  137. package/dist/features/blog/types/index.d.ts +2 -0
  138. package/dist/features/cart/components/CartPriceBreakdown.d.ts +12 -1
  139. package/dist/features/cart/components/CartPriceBreakdown.js +24 -5
  140. package/dist/features/cart/repository/cart.repository.d.ts +14 -0
  141. package/dist/features/cart/repository/cart.repository.js +20 -0
  142. package/dist/features/cart/schemas/firestore.d.ts +24 -0
  143. package/dist/features/dashboard/components/DashboardHubView.d.ts +83 -0
  144. package/dist/features/dashboard/components/DashboardHubView.js +56 -0
  145. package/dist/features/dashboard/components/DashboardSectionsClient.d.ts +23 -0
  146. package/dist/features/dashboard/components/DashboardSectionsClient.js +66 -0
  147. package/dist/features/dispute-reasons/components/AdminDisputeReasonsView.d.ts +55 -0
  148. package/dist/features/dispute-reasons/components/AdminDisputeReasonsView.js +175 -0
  149. package/dist/features/dispute-reasons/repository/dispute-reasons.repository.d.ts +24 -0
  150. package/dist/features/dispute-reasons/repository/dispute-reasons.repository.js +28 -0
  151. package/dist/features/dispute-reasons/schemas/firestore.d.ts +3 -5
  152. package/dist/features/events/components/EventSaleBanner.js +1 -1
  153. package/dist/features/faq/components/FAQPageContent.js +2 -2
  154. package/dist/features/gateway-events/schemas/index.d.ts +2 -2
  155. package/dist/features/homepage/schemas/index.d.ts +8 -8
  156. package/dist/features/inventory/schemas/stock-reservation.d.ts +114 -0
  157. package/dist/features/inventory/schemas/stock-reservation.js +103 -0
  158. package/dist/features/layout/AppLayoutShell.d.ts +9 -1
  159. package/dist/features/layout/AppLayoutShell.js +12 -4
  160. package/dist/features/layout/BottomActions.js +2 -1
  161. package/dist/features/layout/BottomNavbar.d.ts +10 -2
  162. package/dist/features/layout/SideActionDock.js +52 -2
  163. package/dist/features/layout/TitleBarLayout.js +13 -4
  164. package/dist/features/layout/TitleBarLayout.style.css +59 -0
  165. package/dist/features/layout/useCtaReveal.d.ts +16 -1
  166. package/dist/features/layout/useCtaReveal.js +17 -26
  167. package/dist/features/ledger/repository/journal.repository.d.ts +110 -0
  168. package/dist/features/ledger/repository/journal.repository.js +312 -0
  169. package/dist/features/ledger/schemas/expenses.d.ts +87 -0
  170. package/dist/features/ledger/schemas/expenses.js +27 -0
  171. package/dist/features/ledger/schemas/firestore.d.ts +183 -0
  172. package/dist/features/ledger/schemas/firestore.js +69 -0
  173. package/dist/features/orders/components/BalancePaymentPanel.d.ts +12 -0
  174. package/dist/features/orders/components/BalancePaymentPanel.js +94 -0
  175. package/dist/features/orders/components/RaiseDisputeForm.js +19 -11
  176. package/dist/features/orders/repository/orders.repository.d.ts +28 -1
  177. package/dist/features/orders/repository/orders.repository.js +60 -6
  178. package/dist/features/orders/schemas/balance.d.ts +40 -0
  179. package/dist/features/orders/schemas/balance.js +47 -0
  180. package/dist/features/orders/schemas/firestore.d.ts +202 -0
  181. package/dist/features/orders/schemas/firestore.js +43 -0
  182. package/dist/features/orders/schemas/index.d.ts +2 -2
  183. package/dist/features/orders/types/index.d.ts +21 -0
  184. package/dist/features/payments/repository/payout.repository.js +3 -2
  185. package/dist/features/payments/schemas/firestore.d.ts +92 -1
  186. package/dist/features/payments/schemas/firestore.js +23 -0
  187. package/dist/features/pricing/components/AdminPricingView.d.ts +13 -0
  188. package/dist/features/pricing/components/AdminPricingView.js +157 -0
  189. package/dist/features/products/schemas/firestore.d.ts +26 -1
  190. package/dist/features/products/schemas/firestore.js +2 -0
  191. package/dist/features/products/schemas/index.d.ts +2 -2
  192. package/dist/features/reviews/repository/reviews.repository.d.ts +14 -0
  193. package/dist/features/reviews/repository/reviews.repository.js +16 -0
  194. package/dist/features/scams/repository/scammer.repository.js +2 -1
  195. package/dist/features/scams/schemas/firestore.d.ts +2 -1
  196. package/dist/features/scams/schemas/firestore.js +2 -1
  197. package/dist/features/seller/actions/offer-actions.js +56 -0
  198. package/dist/features/seller/actions/seller-actions.d.ts +1 -1
  199. package/dist/features/seller/actions/seller-actions.js +4 -0
  200. package/dist/features/seller/components/DispatchForm.d.ts +11 -0
  201. package/dist/features/seller/components/DispatchForm.js +190 -0
  202. package/dist/features/seller/components/SellerOrdersView.js +94 -2
  203. package/dist/features/seller/components/index.d.ts +1 -0
  204. package/dist/features/seller/components/index.js +1 -0
  205. package/dist/features/seller/repository/offer.repository.js +4 -3
  206. package/dist/features/seller/schemas/firestore.d.ts +23 -2
  207. package/dist/features/seller/schemas/firestore.js +3 -2
  208. package/dist/features/seller/schemas/index.d.ts +4 -4
  209. package/dist/features/seller/schemas/order-forms.d.ts +61 -4
  210. package/dist/features/seller/schemas/order-forms.js +41 -8
  211. package/dist/features/shipments/schemas/firestore.d.ts +25 -0
  212. package/dist/features/shipping-boxes/repository/shipping-boxes.repository.d.ts +39 -0
  213. package/dist/features/shipping-boxes/repository/shipping-boxes.repository.js +55 -0
  214. package/dist/features/shipping-boxes/schemas/firestore.d.ts +2 -4
  215. package/dist/features/stores/repository/store.repository.d.ts +18 -0
  216. package/dist/features/stores/repository/store.repository.js +27 -1
  217. package/dist/features/stores/schemas/firestore.d.ts +41 -0
  218. package/dist/features/stores/schemas/firestore.js +20 -0
  219. package/dist/features/stores/schemas/index.d.ts +6 -6
  220. package/dist/features/support/repository/support.repository.js +72 -6
  221. package/dist/features/support/schemas/firestore.d.ts +17 -0
  222. package/dist/features/support/schemas/index.d.ts +2 -2
  223. package/dist/index.d.ts +5 -0
  224. package/dist/index.js +19 -0
  225. package/dist/next/routing/route-map.d.ts +92 -0
  226. package/dist/next/routing/route-map.js +53 -0
  227. package/dist/react/contexts/SessionContext.d.ts +17 -1
  228. package/dist/schemas/registry.d.ts +22 -16
  229. package/dist/security/pii-schemas.d.ts +1 -1
  230. package/dist/security/pii-schemas.js +45 -0
  231. package/dist/server-entry.d.ts +1 -1
  232. package/dist/server-entry.js +10 -1
  233. package/dist/server.d.ts +29 -1
  234. package/dist/server.js +158 -0
  235. package/dist/styles.css +349 -1
  236. package/dist/tailwind-utilities.css +1 -1
  237. package/dist/ui/components/Button.d.ts +10 -1
  238. package/dist/ui/components/Button.js +25 -3
  239. package/dist/ui/components/Chart.d.ts +63 -0
  240. package/dist/ui/components/Chart.js +169 -0
  241. package/dist/ui/components/Chart.style.css +214 -0
  242. package/dist/ui/components/Disclaimer.js +10 -1
  243. package/dist/ui/components/OverflowRow.js +54 -2
  244. package/dist/ui/components/OverflowRow.style.css +38 -0
  245. package/dist/ui/components/RichTextEditor.js +99 -8
  246. package/dist/ui/components/chart-spec.d.ts +68 -0
  247. package/dist/ui/components/chart-spec.js +140 -0
  248. package/dist/ui/components/index.style.css +1 -0
  249. package/dist/ui/components/surface-tokens.d.ts +1 -1
  250. package/dist/ui/components/surface-tokens.js +9 -0
  251. package/dist/ui/components/toolbar-collapse.d.ts +13 -0
  252. package/dist/ui/components/toolbar-collapse.js +10 -1
  253. package/dist/ui/index.d.ts +6 -0
  254. package/dist/ui/index.js +3 -0
  255. package/dist/ui/rich-text/RichText.d.ts +10 -1
  256. package/dist/ui/rich-text/RichText.js +33 -2
  257. package/dist/ui/rich-text/RichText.style.css +35 -0
  258. package/dist/ui/rich-text/RichTextRenderer.d.ts +30 -1
  259. package/dist/ui/rich-text/RichTextRenderer.js +34 -2
  260. package/dist/ui/rich-text/chart-blocks.d.ts +62 -0
  261. package/dist/ui/rich-text/chart-blocks.js +87 -0
  262. package/package.json +1 -1
  263. package/scripts/seed-cli.mjs +3 -0
@@ -174,6 +174,68 @@ export declare const RefundStatusValues: {
174
174
  readonly REJECTED: "rejected";
175
175
  };
176
176
  /** Firestore storage shape for an order line item â€" distinct from the API display model OrderItem */
177
+ /**
178
+ * The PII inside one amendment.
179
+ *
180
+ * 🛑 BARE keys, and `ORDER_PII_FIELDS` uses the `deliveryAmendments[].…`
181
+ * form for the same five fields. Two notations, two scopes, both correct:
182
+ * the `[]` form is for the whole ORDER document, where the hook has to walk
183
+ * into the array; these bare names are for ONE amendment object, where they
184
+ * are genuinely top-level.
185
+ *
186
+ * 🛑 This list was first justified as "`encryptPiiFields` CANNOT cover an
187
+ * array" — CLAUDE.md's wording, and FALSE. `encryptInArray` has always
188
+ * handled `a[].b`, in both directions. The real rule is that the encryptor
189
+ * does not infer: a field is covered only where it is NAMED, in the notation
190
+ * matching the object the list is applied to.
191
+ */
192
+ export declare const AMENDMENT_PII_FIELDS: readonly ["fullName", "phone", "addressLine1", "addressLine2", "landmark"];
193
+ /**
194
+ * A correction to the delivery address after the order was placed.
195
+ *
196
+ * 🛑 Carries the FULL new address, not a diff. A diff would make the current
197
+ * address reconstructable only by replaying every entry in order, so one
198
+ * malformed entry in the middle makes everything after it unreadable — and
199
+ * the parcel label is produced from the current address.
200
+ *
201
+ * PII in here is the same problem as everywhere else: `encryptPiiFields` does
202
+ * not descend into arrays, so these values are NOT encrypted by that
203
+ * mechanism. `scrubAmendmentPii` is what handles them; see its header.
204
+ */
205
+ export interface DeliveryAmendment {
206
+ at: Date;
207
+ /** Who asked. `actorRole` distinguishes a buyer correction from a support fix. */
208
+ actorUid?: string;
209
+ actorRole: "buyer" | "seller" | "admin" | "system";
210
+ reason?: string;
211
+ fullName: string;
212
+ phone: string;
213
+ addressLine1: string;
214
+ addressLine2?: string;
215
+ landmark?: string;
216
+ city: string;
217
+ state: string;
218
+ pincode: string;
219
+ country: string;
220
+ }
221
+ /**
222
+ * How much seller prose a single order line carries.
223
+ *
224
+ * 🛑 A Firestore document caps at 1 MiB and `items[]` is inline on the order.
225
+ * 2,000 characters × 20 lines is ~40 KB of description — comfortable. The
226
+ * same field unbounded is a rejected write at checkout, and the checkout is
227
+ * the one operation in the system that must never fail for a reason the buyer
228
+ * cannot act on.
229
+ */
230
+ export declare const ORDER_ITEM_DESCRIPTION_MAX = 2000;
231
+ /**
232
+ * How many spec rows one order line keeps.
233
+ *
234
+ * Capped by COUNT rather than characters: a spec table is rows, and half a
235
+ * row is worse than a missing one — "Weight: 4" with the unit cut off reads
236
+ * as a fact rather than as truncation.
237
+ */
238
+ export declare const ORDER_ITEM_SPECIFICATIONS_MAX = 30;
177
239
  export interface OrderDocumentItem {
178
240
  productId: string;
179
241
  productTitle: string;
@@ -261,6 +323,37 @@ export interface OrderDocumentItem {
261
323
  /** Which kind of multi-member line produced these rows. */
262
324
  groupSource?: "bundle" | "product-group" | "grouped-listing";
263
325
  /** P-8 GST — snapshotted from the product at order time so the invoice stays accurate even if the product's HSN/rate later changes. */
326
+ /**
327
+ * The listing description as it read at purchase.
328
+ *
329
+ * 🛑 BOUNDED at `ORDER_ITEM_DESCRIPTION_MAX`, with `descriptionTruncated`
330
+ * recording that it was cut. A Firestore document caps at 1 MiB and this is
331
+ * free-form seller prose on every line of every order — an unbounded copy
332
+ * on a 20-line order is a rejected write AT CHECKOUT, which fails the one
333
+ * operation that must not fail. Truncation is recorded rather than silent
334
+ * for the same reason `statusHistoryTruncated` exists: a short description
335
+ * and a cut one must not read alike.
336
+ */
337
+ description?: string;
338
+ descriptionTruncated?: boolean;
339
+ /** The spec table as it read at purchase. */
340
+ specifications?: Array<{
341
+ name: string;
342
+ value: string;
343
+ unit?: string;
344
+ }>;
345
+ /**
346
+ * For a composed listing, the parts it was sold as containing.
347
+ *
348
+ * Ids and names only — the part CATALOGUE is a live reference work and
349
+ * copying its entries onto every order line would duplicate a research
350
+ * corpus per purchase. What matters for a dispute is which parts were
351
+ * claimed, not their current catalogue entry.
352
+ */
353
+ parts?: Array<{
354
+ code: string;
355
+ name: string;
356
+ }>;
264
357
  hsnCode?: string;
265
358
  gstRate?: 0 | 5 | 12 | 18 | 28;
266
359
  /**
@@ -425,7 +518,64 @@ export interface OrderDocument extends BaseDocument {
425
518
  paymentStatus: PaymentStatus;
426
519
  paymentId?: string;
427
520
  paymentMethod?: string;
521
+ /**
522
+ * 🛑 LEGACY. Never written for an order created after Part 14.
523
+ *
524
+ * Flat free text with no pincode, no phone and no address id — which is why
525
+ * `placeOfSupply` had to be written separately rather than derived, and why
526
+ * parcel booking could not be built at all (`CreateShipmentInput` needs a
527
+ * structured `{name, phone, addressLine1, city, state, pincode, country}`).
528
+ *
529
+ * It is ALSO in `ORDER_UPDATABLE_FIELDS`, so it is editable after the order
530
+ * — meaning it never recorded what the buyer actually chose. And it was
531
+ * never encrypted: `ORDER_PII_FIELDS` is `userName` / `userEmail` /
532
+ * `sellerEmail`, so every delivery address on every order up to now sits in
533
+ * Firestore in plaintext, despite the docs saying otherwise.
534
+ *
535
+ * Read it only as a fallback for orders that predate `deliveryAddress*`,
536
+ * and render it labelled as legacy. Forward-only; no backfill — parsing a
537
+ * state out of free text to file a tax return is the thing the
538
+ * `placeOfSupply` comment below already refuses.
539
+ */
428
540
  shippingAddress?: string;
541
+ /** PII — encrypted. See `ORDER_PII_FIELDS`. */
542
+ deliveryFullName?: Encrypted<string>;
543
+ /** PII — encrypted. */
544
+ deliveryPhone?: Encrypted<string>;
545
+ /** PII — encrypted. */
546
+ deliveryAddressLine1?: Encrypted<string>;
547
+ /** PII — encrypted. Optional second line / apartment. */
548
+ deliveryAddressLine2?: Encrypted<string>;
549
+ /** PII — encrypted. */
550
+ deliveryLandmark?: Encrypted<string>;
551
+ deliveryCity?: string;
552
+ deliveryState?: string;
553
+ deliveryPincode?: string;
554
+ deliveryCountry?: string;
555
+ /**
556
+ * The `addresses` row this was taken from, for provenance only.
557
+ *
558
+ * 🛑 Never resolved at read time. The row can be edited or deleted after the
559
+ * order, and following it would make the invoice disagree with what the
560
+ * buyer chose — which is the entire failure a snapshot exists to prevent.
561
+ */
562
+ deliveryAddressId?: string;
563
+ /**
564
+ * Corrections after the fact, newest LAST. Append-only.
565
+ *
566
+ * 🛑 Its OWN array, not a passenger on `statusHistory`.
567
+ *
568
+ * `statusHistory` caps at 50 with FIFO eviction. Address edits riding that
569
+ * log would compete with status transitions for the same slots and evict
570
+ * the thing the timeline exists to show — and on a chatty order the
571
+ * creation entry goes first, which is precisely the value reconstruction
572
+ * depends on. The creation snapshot is a FIELD above for the same reason: a
573
+ * field cannot be truncated.
574
+ *
575
+ * Dispatch reads the latest amendment (or the snapshot when there is none).
576
+ * The invoice always reads the snapshot.
577
+ */
578
+ deliveryAmendments?: DeliveryAmendment[];
429
579
  trackingNumber?: string;
430
580
  notes?: string;
431
581
  orderDate: Date;
@@ -1130,6 +1280,58 @@ export interface OrderDocument extends BaseDocument {
1130
1280
  /** Buyer's required "this payment is genuine, no fraudulent tricks/chargebacks" agreement — server-validated, not just a client-side disable. */
1131
1281
  buyerFraudAgreementAccepted?: boolean;
1132
1282
  buyerFraudAgreementAcceptedAt?: Date;
1283
+ /**
1284
+ * ── D55: the pre-order BALANCE, which is a second payment ──────────────
1285
+ *
1286
+ * 🛑 Its own block rather than reusing the fields above, and that is the
1287
+ * decision this whole feature turns on. Every field above describes ONE
1288
+ * payment; a pre-order has two, months apart. Reusing `paymentProofUrl`
1289
+ * for the balance overwrites the deposit's proof — the evidence for the
1290
+ * payment that created the order — and `paymentReviewOutcome` then means
1291
+ * two different things depending on when you read it.
1292
+ *
1293
+ * Worse, `paymentWindowTimeout` sweeps orders that are `pending`/`pending`
1294
+ * with no `paymentProofUrl`, so clearing that field to collect a balance
1295
+ * would make the sweep cancel and restock a PAID order.
1296
+ *
1297
+ * The balance is therefore its own small state machine beside the
1298
+ * deposit's, sharing the review vocabulary but none of the storage.
1299
+ */
1300
+ balance?: {
1301
+ /**
1302
+ * 🛑 SNAPSHOTTED, not recomputed — D61, and the worst case in the
1303
+ * codebase for it: a deposit-to-balance gap is months. It is copied from
1304
+ * `sourceContext.balanceDue` at the moment the collection is opened, so
1305
+ * a price change, a tax-rate change or a re-quote in between cannot move
1306
+ * what the buyer was told they owe. Recomputing at payment time is how a
1307
+ * buyer who agreed to ₹4,000 is charged ₹4,400.
1308
+ */
1309
+ amount: number;
1310
+ /**
1311
+ * `manual` only, today, and the field exists so the absence is explicit.
1312
+ *
1313
+ * 🛑 The AUTO path is not merely unbuilt — it is blocked on things
1314
+ * outside this repo. A months-long gap cannot use authorise-then-capture
1315
+ * (capture windows are days), so it needs a real RBI-compliant mandate:
1316
+ * AFA at creation, a pre-debit notice at least 24 HOURS before every
1317
+ * debit, and a max amount fixed at registration. Razorpay must also have
1318
+ * recurring enabled, and production runs TEST keys with
1319
+ * `razorpayEnabled` defaulting false. Declaring the union now means
1320
+ * adding `auto` later is a compile-checked change rather than a new
1321
+ * field nobody wires.
1322
+ */
1323
+ method: "manual";
1324
+ status: "awaiting" | "submitted" | "paid" | "rejected";
1325
+ /** Set when the collection is opened, so the buyer has a stated window. */
1326
+ dueBy?: Date;
1327
+ proofUrl?: string;
1328
+ transactionId?: string;
1329
+ submittedAt?: Date;
1330
+ reviewedBy?: string;
1331
+ reviewedAt?: Date;
1332
+ /** Required on `rejected`, for the same reason a refund reason is. */
1333
+ reviewNote?: string;
1334
+ };
1133
1335
  /** Which of the three admin review actions was taken on this order's payment proof. */
1134
1336
  paymentReviewOutcome?: "approved" | "reupload_requested" | "rejected_fraud";
1135
1337
  /** Admin's reason text — required for both `reupload_requested` and `rejected_fraud`. */
@@ -48,6 +48,49 @@ export const RefundStatusValues = {
48
48
  COMPLETED: "completed",
49
49
  REJECTED: "rejected",
50
50
  };
51
+ /** Firestore storage shape for an order line item â€" distinct from the API display model OrderItem */
52
+ /**
53
+ * The PII inside one amendment.
54
+ *
55
+ * 🛑 BARE keys, and `ORDER_PII_FIELDS` uses the `deliveryAmendments[].…`
56
+ * form for the same five fields. Two notations, two scopes, both correct:
57
+ * the `[]` form is for the whole ORDER document, where the hook has to walk
58
+ * into the array; these bare names are for ONE amendment object, where they
59
+ * are genuinely top-level.
60
+ *
61
+ * 🛑 This list was first justified as "`encryptPiiFields` CANNOT cover an
62
+ * array" — CLAUDE.md's wording, and FALSE. `encryptInArray` has always
63
+ * handled `a[].b`, in both directions. The real rule is that the encryptor
64
+ * does not infer: a field is covered only where it is NAMED, in the notation
65
+ * matching the object the list is applied to.
66
+ */
67
+ export const AMENDMENT_PII_FIELDS = [
68
+ "fullName",
69
+ "phone",
70
+ "addressLine1",
71
+ "addressLine2",
72
+ /* Encrypted on the snapshot as `deliveryLandmark`; the two must agree or the
73
+ * same datum is protected before a correction and exposed after it. */
74
+ "landmark",
75
+ ];
76
+ /**
77
+ * How much seller prose a single order line carries.
78
+ *
79
+ * 🛑 A Firestore document caps at 1 MiB and `items[]` is inline on the order.
80
+ * 2,000 characters × 20 lines is ~40 KB of description — comfortable. The
81
+ * same field unbounded is a rejected write at checkout, and the checkout is
82
+ * the one operation in the system that must never fail for a reason the buyer
83
+ * cannot act on.
84
+ */
85
+ export const ORDER_ITEM_DESCRIPTION_MAX = 2000;
86
+ /**
87
+ * How many spec rows one order line keeps.
88
+ *
89
+ * Capped by COUNT rather than characters: a spec table is rows, and half a
90
+ * row is worse than a missing one — "Weight: 4" with the unit cut off reads
91
+ * as a fact rather than as truncation.
92
+ */
93
+ export const ORDER_ITEM_SPECIFICATIONS_MAX = 30;
51
94
  export const ORDER_COLLECTION = "orders";
52
95
  /**
53
96
  * At-most-once gate for refunds. Document id = `sha256(idempotencyKey)`,
@@ -684,6 +684,7 @@ export declare const orderFirestoreSchema: z.ZodObject<{
684
684
  prizeRevealStatus?: "closed" | "open" | "pending" | "revealed" | undefined;
685
685
  }[] | undefined;
686
686
  bundleId?: string | undefined;
687
+ orderType?: string | undefined;
687
688
  prizeWon?: {
688
689
  title: string;
689
690
  images: string[];
@@ -700,7 +701,6 @@ export declare const orderFirestoreSchema: z.ZodObject<{
700
701
  bin: string;
701
702
  } | undefined;
702
703
  offerId?: string | undefined;
703
- orderType?: string | undefined;
704
704
  isNonRefundable?: boolean | undefined;
705
705
  imageUrls?: string[] | undefined;
706
706
  refundFeeDeducted?: number | undefined;
@@ -843,6 +843,7 @@ export declare const orderFirestoreSchema: z.ZodObject<{
843
843
  prizeRevealStatus?: "closed" | "open" | "pending" | "revealed" | undefined;
844
844
  }[] | undefined;
845
845
  bundleId?: string | undefined;
846
+ orderType?: string | undefined;
846
847
  prizeWon?: {
847
848
  title: string;
848
849
  images: string[];
@@ -859,7 +860,6 @@ export declare const orderFirestoreSchema: z.ZodObject<{
859
860
  bin: string;
860
861
  } | undefined;
861
862
  offerId?: string | undefined;
862
- orderType?: string | undefined;
863
863
  isNonRefundable?: boolean | undefined;
864
864
  imageUrls?: string[] | undefined;
865
865
  refundFeeDeducted?: number | undefined;
@@ -287,6 +287,27 @@ export interface Order {
287
287
  timelineTruncated?: number;
288
288
  /** How the buyer acquired the right to buy. Written once, at creation. */
289
289
  sourceContext?: OrderSourceContext;
290
+ /**
291
+ * D55 — the pre-order balance, once the seller has OPENED it for collection.
292
+ *
293
+ * 🛑 Absent until then, and that is the difference between "a balance
294
+ * exists" (`sourceContext.balanceDue > 0`, true from the moment the order
295
+ * was placed) and "a balance is payable". The buyer's panel gates on this
296
+ * field, so forgetting it in `orderDocumentToOrder` would render the
297
+ * "nothing to pay" branch on every order forever — Root Cause #57, which
298
+ * is what made the whole manual-payment flow dead for weeks.
299
+ */
300
+ balance?: {
301
+ amount: number;
302
+ method: "manual";
303
+ status: "awaiting" | "submitted" | "paid" | "rejected";
304
+ dueBy?: string;
305
+ proofUrl?: string;
306
+ transactionId?: string;
307
+ submittedAt?: string;
308
+ reviewedAt?: string;
309
+ reviewNote?: string;
310
+ };
290
311
  physicalLocation?: {
291
312
  zone: string;
292
313
  shelf: string;
@@ -220,8 +220,9 @@ export class PayoutRepository extends BaseRepository {
220
220
  trigger: ctx?.trigger ?? defaultTrigger,
221
221
  reason: ctx?.reason,
222
222
  note: ctx?.note,
223
- // `sellerEmail` / `upiId` — `encryptPiiFields` never descends into
224
- // arrays, so either reaching `changes` would persist in PLAINTEXT.
223
+ // `sellerEmail` / `upiId` — `encryptPiiFields` covers only NAMED paths,
224
+ // and nothing declares them under `statusHistory[].changes`, so either
225
+ // one reaching `changes` would persist in PLAINTEXT.
225
226
  piiFields: PAYOUT_PII_FIELDS,
226
227
  });
227
228
  return withEntry ?? patch;
@@ -5,6 +5,7 @@ import { type GeneratePayoutIdInput } from "../../../utils/id-generators";
5
5
  import type { BaseDocument } from "../../../_internal/shared/types/base-document";
6
6
  import type { StatusChangeEntry } from "../../../_internal/shared/history/types";
7
7
  import type { Encrypted, Plaintext } from "../../../security/encrypted";
8
+ import type { PayCadence } from "../../../_internal/shared/features/payouts/pay-period";
8
9
  export interface PayoutBankAccount {
9
10
  accountHolderName: string;
10
11
  accountNumberMasked: string;
@@ -45,7 +46,29 @@ export type PayoutPaymentMethod = "bank_transfer" | "upi";
45
46
  * asterisks". The distinction is which named method you called.
46
47
  */
47
48
  export type PayoutPlain = Plaintext<PayoutDocument>;
48
- export interface PayoutDocument extends BaseDocument {
49
+ /**
50
+ * 🛑 **A seller payout settles a LIABILITY. An employee payout is an EXPENSE.**
51
+ *
52
+ * One undiscriminated shape misstates both statements at once — wages vanish
53
+ * from the P&L and reappear as settled seller liabilities — so `payeeType` is
54
+ * a discriminated union rather than an optional field.
55
+ *
56
+ * ## Why `PayoutDocument` still names the STORE variant
57
+ *
58
+ * Every one of the ~30 existing readers means a seller payout, and every one
59
+ * of them is correct. Renaming the type they import would turn a safety change
60
+ * into a mechanical sweep, and the sweep is where the real mistakes go in.
61
+ * `PayoutDocument = StorePayoutDocument` keeps them compiling and correct;
62
+ * anything that must handle BOTH takes `AnyPayoutDocument` and is forced by
63
+ * `tsc` to narrow.
64
+ *
65
+ * 🛑 `payeeType` is REQUIRED here, not optional-with-a-default. That breaks
66
+ * the five sites that CONSTRUCT a payout, which is the entire point — a row
67
+ * written without it is a row the books cannot classify, and an optional
68
+ * discriminant defers that discovery to a reader rather than a writer.
69
+ */
70
+ export interface StorePayoutDocument extends BaseDocument {
71
+ payeeType: "store";
49
72
  storeId: string;
50
73
  sellerName: string;
51
74
  sellerEmail: Encrypted<string>;
@@ -92,6 +115,74 @@ export interface PayoutDocument extends BaseDocument {
92
115
  statusHistory?: StatusChangeEntry[];
93
116
  statusHistoryTruncated?: number;
94
117
  }
118
+ /**
119
+ * Wages for a period, earned by resolving support tickets.
120
+ *
121
+ * ## 🛑 `platformFee` is ABSENT, not zero
122
+ *
123
+ * A `0` would read as "we took no commission on these wages", which is a
124
+ * statement about a transaction that did not happen. Commission is not a
125
+ * concept between a platform and its own staff, and the books must be able to
126
+ * tell "not applicable" from "nil" — a nil commission is a seller payout where
127
+ * the rate happened to resolve to zero, and those post differently.
128
+ *
129
+ * The same argument removes `storeId`, `sellerName`, `sellerEmail`,
130
+ * `grossAmount`, `platformFeeRate`, `gatewayFee*`, `orderIds` and
131
+ * `refundDeductions`. A field that cannot apply is omitted so `tsc` refuses
132
+ * the read, rather than present-and-empty so a reader quietly gets a falsy
133
+ * value.
134
+ */
135
+ export interface EmployeePayoutDocument extends BaseDocument {
136
+ payeeType: "employee";
137
+ employeeUid: string;
138
+ employeeName: string;
139
+ /** PII, same treatment as a seller's. */
140
+ employeeEmail: Encrypted<string>;
141
+ amount: number;
142
+ currency: string;
143
+ status: PayoutStatus;
144
+ paymentMethod: PayoutPaymentMethod;
145
+ bankAccount?: PayoutBankAccount;
146
+ upiId?: Encrypted<string>;
147
+ /**
148
+ * The tickets this payslip is for.
149
+ *
150
+ * 🛑 Tickets **still resolved at period end**, not tickets closed during it.
151
+ * Paying per ticket closed rewards closing rather than resolving, so a
152
+ * reopened ticket does not count — see `resolvedTicketsForPeriod`.
153
+ */
154
+ ticketIds: string[];
155
+ /** Resolved by `payPeriodFor`, never computed at a call site. */
156
+ periodStart: Date;
157
+ periodEnd: Date;
158
+ payCadence: PayCadence;
159
+ notes?: string;
160
+ adminNote?: string;
161
+ requestedAt: Date;
162
+ processedAt?: Date;
163
+ transactionId?: string;
164
+ statusHistory?: StatusChangeEntry[];
165
+ statusHistoryTruncated?: number;
166
+ }
167
+ /**
168
+ * What ~30 existing readers mean, and what they should keep meaning.
169
+ *
170
+ * Deliberately an alias rather than a rename: see the header on
171
+ * `StorePayoutDocument`.
172
+ */
173
+ export type PayoutDocument = StorePayoutDocument;
174
+ /** Use this ONLY where both kinds genuinely arrive together. */
175
+ export type AnyPayoutDocument = StorePayoutDocument | EmployeePayoutDocument;
176
+ /**
177
+ * 🛑 Narrow on the DISCRIMINANT, never on the presence of `storeId`.
178
+ *
179
+ * A `"storeId" in payout` test reads as equivalent and is not: it answers a
180
+ * question about the object in hand rather than about what the row IS, so a
181
+ * partially-populated or hand-built object answers it wrongly, silently, and
182
+ * in the direction that posts wages as a settled seller liability.
183
+ */
184
+ export declare function isStorePayout(p: AnyPayoutDocument): p is StorePayoutDocument;
185
+ export declare function isEmployeePayout(p: AnyPayoutDocument): p is EmployeePayoutDocument;
95
186
  /**
96
187
  * The fields whose changes earn a timeline entry.
97
188
  *
@@ -8,6 +8,20 @@ export const PayoutStatusValues = {
8
8
  PAID: "paid",
9
9
  FAILED: "failed",
10
10
  };
11
+ /**
12
+ * 🛑 Narrow on the DISCRIMINANT, never on the presence of `storeId`.
13
+ *
14
+ * A `"storeId" in payout` test reads as equivalent and is not: it answers a
15
+ * question about the object in hand rather than about what the row IS, so a
16
+ * partially-populated or hand-built object answers it wrongly, silently, and
17
+ * in the direction that posts wages as a settled seller liability.
18
+ */
19
+ export function isStorePayout(p) {
20
+ return p.payeeType === "store";
21
+ }
22
+ export function isEmployeePayout(p) {
23
+ return p.payeeType === "employee";
24
+ }
11
25
  /**
12
26
  * The fields whose changes earn a timeline entry.
13
27
  *
@@ -36,6 +50,15 @@ export const PAYOUT_INDEXED_FIELDS = [
36
50
  ];
37
51
  export const DEFAULT_PLATFORM_FEE_RATE = 0.05;
38
52
  export const DEFAULT_PAYOUT_DATA = {
53
+ /*
54
+ * 🛑 Here as a BACKSTOP, not as the reason the field is set. Every caller
55
+ * passes `payeeType` explicitly and must keep doing so — a default that is
56
+ * the only writer makes the discriminant optional in practice, which is the
57
+ * exact failure the required field exists to prevent. This catches a row
58
+ * built by some path nobody enumerated and lands it on the correct side of
59
+ * the books rather than on neither.
60
+ */
61
+ payeeType: "store",
39
62
  status: "pending",
40
63
  platformFeeRate: DEFAULT_PLATFORM_FEE_RATE,
41
64
  orderIds: [],
@@ -0,0 +1,13 @@
1
+ import React from "react";
2
+ export interface AdminPricingViewProps {
3
+ /**
4
+ * The rate endpoint, supplied by the consumer.
5
+ *
6
+ * 🛑 REQUIRED, with no default. appkit cannot import `API_ROUTES` (that is
7
+ * consumer-side), so a default would be a path literal living in the
8
+ * library — a second place the route is written, and the one nobody updates
9
+ * when it moves. `audit-hardcoded-api-routes` blocks it, correctly.
10
+ */
11
+ endpoint: string;
12
+ }
13
+ export declare function AdminPricingView({ endpoint }: AdminPricingViewProps): React.JSX.Element;