@mohasinac/appkit 3.2.20 → 3.3.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 (190) hide show
  1. package/dist/_internal/server/features/checkout/actions.d.ts +2 -0
  2. package/dist/_internal/server/features/checkout/actions.js +239 -190
  3. package/dist/_internal/server/functions/scheduled.d.ts +2 -1
  4. package/dist/_internal/server/functions/scheduled.js +9 -1
  5. package/dist/_internal/server/jobs/core/autoPayoutEligibility.js +8 -11
  6. package/dist/_internal/server/jobs/core/emiInstallmentReminder.d.ts +8 -0
  7. package/dist/_internal/server/jobs/core/emiInstallmentReminder.js +78 -0
  8. package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.d.ts +2 -2
  9. package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.js +15 -10
  10. package/dist/_internal/server/jobs/handlers/emiInstallmentReminder.d.ts +2 -0
  11. package/dist/_internal/server/jobs/handlers/emiInstallmentReminder.js +2 -0
  12. package/dist/_internal/server/jobs/handlers/index.d.ts +1 -0
  13. package/dist/_internal/server/jobs/handlers/index.js +2 -0
  14. package/dist/_internal/server/providers/index.d.ts +4 -4
  15. package/dist/_internal/server/providers/index.js +4 -4
  16. package/dist/_internal/server/providers/payment/razorpay-mock.d.ts +3 -2
  17. package/dist/_internal/server/providers/payment/razorpay-mock.js +3 -1
  18. package/dist/_internal/server/providers/resolve.d.ts +10 -13
  19. package/dist/_internal/server/providers/resolve.js +9 -15
  20. package/dist/_internal/shared/actions/action-registry.js +28 -0
  21. package/dist/_internal/shared/checkout/rules/_defaults.js +1 -0
  22. package/dist/_internal/shared/checkout/rules/_registry.js +4 -0
  23. package/dist/_internal/shared/checkout/rules/art.rule.d.ts +9 -0
  24. package/dist/_internal/shared/checkout/rules/art.rule.js +5 -0
  25. package/dist/_internal/shared/checkout/rules/auction.rule.js +1 -0
  26. package/dist/_internal/shared/checkout/rules/classified.rule.js +1 -0
  27. package/dist/_internal/shared/checkout/rules/index.d.ts +2 -0
  28. package/dist/_internal/shared/checkout/rules/index.js +2 -0
  29. package/dist/_internal/shared/checkout/rules/stickers.rule.d.ts +9 -0
  30. package/dist/_internal/shared/checkout/rules/stickers.rule.js +5 -0
  31. package/dist/_internal/shared/checkout/rules/types.d.ts +6 -0
  32. package/dist/_internal/shared/features/checkout/config.d.ts +16 -1
  33. package/dist/_internal/shared/features/checkout/config.js +16 -1
  34. package/dist/_internal/shared/features/emi/schedule.d.ts +63 -0
  35. package/dist/_internal/shared/features/emi/schedule.js +62 -0
  36. package/dist/_internal/shared/fees/calculator.d.ts +53 -0
  37. package/dist/_internal/shared/fees/calculator.js +40 -0
  38. package/dist/_internal/shared/listing-types/_registry.d.ts +22 -66
  39. package/dist/_internal/shared/listing-types/_registry.js +19 -2
  40. package/dist/_internal/shared/listing-types/art/config.d.ts +15 -0
  41. package/dist/_internal/shared/listing-types/art/config.js +14 -0
  42. package/dist/_internal/shared/listing-types/art/ctas.d.ts +1 -0
  43. package/dist/_internal/shared/listing-types/art/ctas.js +3 -0
  44. package/dist/_internal/shared/listing-types/art/og.d.ts +1 -0
  45. package/dist/_internal/shared/listing-types/art/og.js +1 -0
  46. package/dist/_internal/shared/listing-types/art/schema.d.ts +2 -0
  47. package/dist/_internal/shared/listing-types/art/schema.js +3 -0
  48. package/dist/_internal/shared/listing-types/art/seed-factory.d.ts +1 -0
  49. package/dist/_internal/shared/listing-types/art/seed-factory.js +1 -0
  50. package/dist/_internal/shared/listing-types/auction/config.d.ts +8 -0
  51. package/dist/_internal/shared/listing-types/auction/config.js +6 -0
  52. package/dist/_internal/shared/listing-types/capabilities.js +17 -0
  53. package/dist/_internal/shared/listing-types/classified/config.d.ts +8 -0
  54. package/dist/_internal/shared/listing-types/classified/config.js +6 -0
  55. package/dist/_internal/shared/listing-types/digital-code/config.d.ts +8 -0
  56. package/dist/_internal/shared/listing-types/digital-code/config.js +6 -0
  57. package/dist/_internal/shared/listing-types/live/config.d.ts +8 -0
  58. package/dist/_internal/shared/listing-types/live/config.js +6 -0
  59. package/dist/_internal/shared/listing-types/pre-order/config.d.ts +8 -0
  60. package/dist/_internal/shared/listing-types/pre-order/config.js +6 -0
  61. package/dist/_internal/shared/listing-types/prize-draw/config.d.ts +8 -0
  62. package/dist/_internal/shared/listing-types/prize-draw/config.js +6 -0
  63. package/dist/_internal/shared/listing-types/standard/config.d.ts +8 -0
  64. package/dist/_internal/shared/listing-types/standard/config.js +6 -0
  65. package/dist/_internal/shared/listing-types/stickers/config.d.ts +15 -0
  66. package/dist/_internal/shared/listing-types/stickers/config.js +14 -0
  67. package/dist/_internal/shared/listing-types/stickers/ctas.d.ts +1 -0
  68. package/dist/_internal/shared/listing-types/stickers/ctas.js +3 -0
  69. package/dist/_internal/shared/listing-types/stickers/og.d.ts +1 -0
  70. package/dist/_internal/shared/listing-types/stickers/og.js +1 -0
  71. package/dist/_internal/shared/listing-types/stickers/schema.d.ts +2 -0
  72. package/dist/_internal/shared/listing-types/stickers/schema.js +3 -0
  73. package/dist/_internal/shared/listing-types/stickers/seed-factory.d.ts +1 -0
  74. package/dist/_internal/shared/listing-types/stickers/seed-factory.js +1 -0
  75. package/dist/client.d.ts +7 -2
  76. package/dist/client.js +4 -2
  77. package/dist/constants/field-names.d.ts +2 -6
  78. package/dist/constants/field-names.js +2 -6
  79. package/dist/contracts/index.d.ts +4 -2
  80. package/dist/contracts/index.js +6 -0
  81. package/dist/contracts/payment.d.ts +14 -9
  82. package/dist/contracts/payment.js +11 -1
  83. package/dist/contracts/shipping.d.ts +14 -9
  84. package/dist/contracts/shipping.js +11 -1
  85. package/dist/features/about/components/PublicProfileView.js +3 -6
  86. package/dist/features/admin/components/AdminAddressBookView.d.ts +11 -0
  87. package/dist/features/admin/components/AdminAddressBookView.js +30 -0
  88. package/dist/features/admin/components/AdminArtView.d.ts +3 -0
  89. package/dist/features/admin/components/AdminArtView.js +45 -0
  90. package/dist/features/admin/components/AdminSiteConfigGuideView.js +1 -1
  91. package/dist/features/admin/components/AdminSiteSettingsView.js +14 -9
  92. package/dist/features/admin/components/AdminStickersView.d.ts +3 -0
  93. package/dist/features/admin/components/AdminStickersView.js +45 -0
  94. package/dist/features/admin/components/index.d.ts +6 -0
  95. package/dist/features/admin/components/index.js +4 -0
  96. package/dist/features/admin/schemas/firestore.d.ts +19 -11
  97. package/dist/features/admin/schemas/firestore.js +12 -2
  98. package/dist/features/auctions/components/MarketplaceAuctionCard.d.ts +3 -2
  99. package/dist/features/auth/hooks/useAuth.js +35 -9
  100. package/dist/features/auth/schemas/firestore.d.ts +2 -6
  101. package/dist/features/cart/schemas/firestore.d.ts +3 -2
  102. package/dist/features/consultation/schemas/index.d.ts +2 -2
  103. package/dist/features/loyalty/schemas/index.d.ts +6 -6
  104. package/dist/features/orders/repository/orders.repository.d.ts +20 -2
  105. package/dist/features/orders/repository/orders.repository.js +34 -5
  106. package/dist/features/orders/schemas/firestore.d.ts +33 -7
  107. package/dist/features/orders/schemas/firestore.js +1 -1
  108. package/dist/features/orders/schemas/index.d.ts +176 -31
  109. package/dist/features/orders/schemas/index.js +20 -6
  110. package/dist/features/orders/types/index.d.ts +3 -3
  111. package/dist/features/payments/repository/payout.repository.js +2 -2
  112. package/dist/features/payments/schemas/firestore.d.ts +3 -3
  113. package/dist/features/payments/schemas/firestore.js +2 -2
  114. package/dist/features/payments/schemas/index.d.ts +5 -5
  115. package/dist/features/payments/schemas/index.js +2 -2
  116. package/dist/features/products/api/[id]/route.js +4 -1
  117. package/dist/features/products/api/route.js +4 -1
  118. package/dist/features/products/components/CompareOverlay.js +7 -9
  119. package/dist/features/products/components/ProductDetailPageView.d.ts +3 -1
  120. package/dist/features/products/components/ProductDetailPageView.js +2 -2
  121. package/dist/features/products/components/ProductForm.js +18 -7
  122. package/dist/features/products/components/ProductGrid.js +7 -12
  123. package/dist/features/products/components/ShowGroupSection.js +3 -5
  124. package/dist/features/products/components/SublistingCarouselSection.js +3 -6
  125. package/dist/features/products/constants/listing-tabs.d.ts +32 -0
  126. package/dist/features/products/constants/listing-tabs.js +8 -0
  127. package/dist/features/products/index.d.ts +1 -1
  128. package/dist/features/products/index.js +3 -1
  129. package/dist/features/products/schemas/firestore.d.ts +20 -1
  130. package/dist/features/products/schemas/firestore.js +2 -0
  131. package/dist/features/products/schemas/index.d.ts +48 -0
  132. package/dist/features/products/schemas/index.js +9 -0
  133. package/dist/features/products/schemas/product-features.d.ts +1 -1
  134. package/dist/features/products/types/index.d.ts +5 -3
  135. package/dist/features/products/utils/listing-type.d.ts +6 -0
  136. package/dist/features/products/utils/listing-type.js +3 -0
  137. package/dist/features/reviews/api/[id]/route.js +5 -4
  138. package/dist/features/seller/actions/seller-actions.d.ts +29 -14
  139. package/dist/features/seller/actions/seller-actions.js +101 -27
  140. package/dist/features/seller/components/SellerArtView.d.ts +7 -0
  141. package/dist/features/seller/components/SellerArtView.js +114 -0
  142. package/dist/features/seller/components/SellerOrdersView.js +38 -1
  143. package/dist/features/seller/components/SellerProductShell.d.ts +5 -1
  144. package/dist/features/seller/components/SellerProductShell.js +69 -59
  145. package/dist/features/seller/components/SellerShippingView.js +6 -25
  146. package/dist/features/seller/components/SellerStickersView.d.ts +7 -0
  147. package/dist/features/seller/components/SellerStickersView.js +114 -0
  148. package/dist/features/seller/components/index.d.ts +4 -0
  149. package/dist/features/seller/components/index.js +2 -0
  150. package/dist/features/seller/messages/en.json +1 -1
  151. package/dist/features/seller/schemas/index.d.ts +7 -7
  152. package/dist/features/seller/schemas/index.js +1 -1
  153. package/dist/features/seller/types/index.d.ts +1 -1
  154. package/dist/features/stores/components/StoreDetailLayoutView.js +18 -2
  155. package/dist/features/stores/schemas/firestore.d.ts +7 -1
  156. package/dist/features/stores/schemas/index.d.ts +19 -16
  157. package/dist/features/stores/schemas/index.js +1 -1
  158. package/dist/index.d.ts +21 -36
  159. package/dist/index.js +27 -39
  160. package/dist/next/routing/route-map.d.ts +22 -0
  161. package/dist/next/routing/route-map.js +10 -0
  162. package/dist/providers/payment-manual/index.d.ts +40 -0
  163. package/dist/providers/payment-manual/index.js +91 -0
  164. package/dist/providers/payment-razorpay/index.d.ts +4 -2
  165. package/dist/providers/payment-razorpay/index.js +4 -1
  166. package/dist/providers/shipping-manual/index.d.ts +22 -0
  167. package/dist/providers/shipping-manual/index.js +47 -0
  168. package/dist/providers.d.ts +2 -2
  169. package/dist/providers.js +5 -3
  170. package/dist/schemas/registry.d.ts +129 -70
  171. package/dist/schemas/registry.js +0 -4
  172. package/dist/security/pii-encrypt.js +0 -7
  173. package/dist/security/pii-redact.js +0 -1
  174. package/dist/seed/conversations-seed-data.js +2 -2
  175. package/dist/seed/faq-seed-data.js +7 -7
  176. package/dist/seed/grouped-listings-seed-data.d.ts +2 -0
  177. package/dist/seed/index.d.ts +2 -0
  178. package/dist/seed/index.js +2 -0
  179. package/dist/seed/manifest.js +20 -16
  180. package/dist/seed/payouts-seed-data.js +5 -5
  181. package/dist/seed/products-art-seed-data.d.ts +11 -0
  182. package/dist/seed/products-art-seed-data.js +125 -0
  183. package/dist/seed/products-preorders-seed-data.d.ts +2 -0
  184. package/dist/seed/products-stickers-seed-data.d.ts +11 -0
  185. package/dist/seed/products-stickers-seed-data.js +125 -0
  186. package/dist/seed/site-settings-seed-data.js +13 -4
  187. package/dist/seed/stores-seed-data.js +11 -11
  188. package/dist/server.d.ts +7 -15
  189. package/dist/server.js +17 -42
  190. package/package.json +1 -1
@@ -0,0 +1,45 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ /**
4
+ * AdminStickersView — admin browse of sticker listings (EMI/art-stickers session).
5
+ * Mirrors AdminClassifiedView's thin config-driven pattern.
6
+ */
7
+ import { sortBy } from "@mohasinac/appkit";
8
+ import React from "react";
9
+ import { ListingLayout } from "../../../ui";
10
+ import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
11
+ import { toRecordArray, toRelativeDate, toRupees, toStringValue, } from "../hooks/useAdminListingData";
12
+ import { DataListingView } from "./DataListingView";
13
+ const ADMIN_STICKERS_CONFIG = {
14
+ portal: "admin",
15
+ title: "Stickers",
16
+ searchPlaceholder: "Search stickers by name or seller",
17
+ emptyLabel: "No sticker listings",
18
+ filterKeys: [],
19
+ defaultSort: sortBy("createdAt", "DESC"),
20
+ queryKey: ["admin", "stickers", "listing"],
21
+ endpoint: ADMIN_ENDPOINTS.PRODUCTS,
22
+ sortOptions: [
23
+ { value: sortBy("createdAt", "DESC"), label: "Newest" },
24
+ { value: sortBy("createdAt", "ASC"), label: "Oldest" },
25
+ { value: "title", label: "Title A–Z" },
26
+ ],
27
+ mapRows: (response) => toRecordArray(response.items).map((item, index) => ({
28
+ id: toStringValue(item.id, `stickers-${index}`),
29
+ primary: toStringValue(item.title ?? item.productTitle, "Untitled sticker listing"),
30
+ secondary: [
31
+ toStringValue(item.sellerName, "Unknown seller"),
32
+ toRupees(item.price),
33
+ ].join(" · "),
34
+ status: toStringValue(item.status, "draft"),
35
+ updatedAt: toRelativeDate(item.updatedAt ?? item.createdAt),
36
+ })),
37
+ getTotal: (response, mappedRows) => typeof response.total === "number" ? response.total : mappedRows.length,
38
+ buildFilters: () => "listingType==stickers",
39
+ };
40
+ export function AdminStickersView({ children, ...props }) {
41
+ if (React.Children.count(children) > 0) {
42
+ return (_jsx(ListingLayout, { portal: "admin", ...props, children: children }));
43
+ }
44
+ return _jsx(DataListingView, { config: ADMIN_STICKERS_CONFIG });
45
+ }
@@ -40,6 +40,10 @@ export { AdminDigitalCodesView } from "./AdminDigitalCodesView";
40
40
  export type { AdminDigitalCodesViewProps } from "./AdminDigitalCodesView";
41
41
  export { AdminLiveView } from "./AdminLiveView";
42
42
  export type { AdminLiveViewProps } from "./AdminLiveView";
43
+ export { AdminArtView } from "./AdminArtView";
44
+ export type { AdminArtViewProps } from "./AdminArtView";
45
+ export { AdminStickersView } from "./AdminStickersView";
46
+ export type { AdminStickersViewProps } from "./AdminStickersView";
43
47
  export { AdminGroupedListingsView } from "./AdminGroupedListingsView";
44
48
  export type { AdminGroupedListingsViewProps } from "./AdminGroupedListingsView";
45
49
  export { AdminBundlesView } from "./AdminBundlesView";
@@ -157,6 +161,8 @@ export { AdminFulfillmentView } from "./AdminFulfillmentView";
157
161
  export type { AdminFulfillmentViewProps } from "./AdminFulfillmentView";
158
162
  export { AdminAddressesView } from "./AdminAddressesView";
159
163
  export type { AdminAddressesViewProps } from "./AdminAddressesView";
164
+ export { AdminAddressBookView } from "./AdminAddressBookView";
165
+ export type { AdminAddressBookViewProps } from "./AdminAddressBookView";
160
166
  export { AdminAddressClustersView } from "./AdminAddressClustersView";
161
167
  export type { AdminAddressClustersViewProps } from "./AdminAddressClustersView";
162
168
  export { AdminPaymentMethodsView } from "./AdminPaymentMethodsView";
@@ -22,6 +22,9 @@ export { AdminPrizeDrawsView } from "./AdminPrizeDrawsView";
22
22
  export { AdminClassifiedView } from "./AdminClassifiedView";
23
23
  export { AdminDigitalCodesView } from "./AdminDigitalCodesView";
24
24
  export { AdminLiveView } from "./AdminLiveView";
25
+ // EMI/art-stickers session — admin listing views for art / stickers.
26
+ export { AdminArtView } from "./AdminArtView";
27
+ export { AdminStickersView } from "./AdminStickersView";
25
28
  export { AdminGroupedListingsView } from "./AdminGroupedListingsView";
26
29
  // S-SBUNI-4 2026-05-13 — admin bundle CRUD views.
27
30
  export { AdminBundlesView } from "./AdminBundlesView";
@@ -82,6 +85,7 @@ export { AdminScammersView } from "./AdminScammersView";
82
85
  export { AdminScammerEditorView } from "./AdminScammerEditorView";
83
86
  export { AdminFulfillmentView } from "./AdminFulfillmentView";
84
87
  export { AdminAddressesView } from "./AdminAddressesView";
88
+ export { AdminAddressBookView } from "./AdminAddressBookView";
85
89
  export { AdminAddressClustersView } from "./AdminAddressClustersView";
86
90
  export { AdminPaymentMethodsView } from "./AdminPaymentMethodsView";
87
91
  export { AdminPaymentClustersView } from "./AdminPaymentClustersView";
@@ -3,7 +3,7 @@
3
3
  * Covers: notifications, chat rooms, site settings
4
4
  */
5
5
  export declare const ADMIN_CHECKOUT_BYPASS_FLAG_KEY: "adminCheckoutBypass";
6
- export type NotificationType = "order_placed" | "order_confirmed" | "order_shipped" | "order_delivered" | "order_cancelled" | "bid_placed" | "bid_outbid" | "bid_won" | "bid_lost" | "review_approved" | "review_replied" | "product_available" | "promotion" | "system" | "welcome" | "account_action" | "offer_received" | "offer_responded" | "offer_expired" | "offer_counter_accepted" | "refund_initiated" | "prize_reveal_ready" | "prize_reveal_expired" | "prize_reveal_reminder";
6
+ export type NotificationType = "order_placed" | "order_confirmed" | "order_shipped" | "order_delivered" | "order_cancelled" | "bid_placed" | "bid_outbid" | "bid_won" | "bid_lost" | "review_approved" | "review_replied" | "product_available" | "promotion" | "system" | "welcome" | "account_action" | "offer_received" | "offer_responded" | "offer_expired" | "offer_counter_accepted" | "refund_initiated" | "prize_reveal_ready" | "prize_reveal_expired" | "prize_reveal_reminder" | "emi_installment_due_soon" | "emi_installment_overdue";
7
7
  import type { BaseDocument } from "../../../_internal/shared/types/base-document";
8
8
  export type NotificationPriority = "low" | "normal" | "high";
9
9
  export interface NotificationDocument extends BaseDocument {
@@ -143,8 +143,6 @@ export interface SiteSettingsCredentials {
143
143
  razorpayWebhookSecret?: string;
144
144
  resendApiKey?: string;
145
145
  whatsappApiKey?: string;
146
- shiprocketEmail?: string;
147
- shiprocketPassword?: string;
148
146
  metaAppId?: string;
149
147
  metaAppSecret?: string;
150
148
  metaPageAccessToken?: string;
@@ -171,8 +169,6 @@ export interface SiteSettingsCredentialsMasked {
171
169
  razorpayWebhookSecret?: string;
172
170
  resendApiKey?: string;
173
171
  whatsappApiKey?: string;
174
- shiprocketEmail?: string;
175
- shiprocketPassword?: string;
176
172
  metaAppId?: string;
177
173
  metaAppSecret?: string;
178
174
  metaPageAccessToken?: string;
@@ -293,6 +289,21 @@ export interface SiteSettingsDocument extends BaseDocument {
293
289
  upiManualEnabled: boolean;
294
290
  codEnabled: boolean;
295
291
  };
292
+ /** Site-wide EMI (installment) settings. A seller must ALSO have `StoreDocument.emiEnabled` on for EMI to appear at checkout for their items. */
293
+ emi: {
294
+ enabled: boolean;
295
+ /** Paise — a seller's cart subtotal must exceed this for EMI to appear as an option. */
296
+ minOrderValueInPaise: number;
297
+ tenureOptions: number[];
298
+ /** Down payment % collected at checkout. */
299
+ tokenPercent: number;
300
+ /** Day of month (1–10) each installment is due. */
301
+ billingDay: number;
302
+ /** Extra % of principal per month of tenure — the "excess EMI fee" the buyer pays for spreading payment. */
303
+ surchargePercentPerMonth: number;
304
+ /** Share of the surcharge that goes to the seller (0–100); the rest is the platform's cut. */
305
+ surchargeSellerSharePercent: number;
306
+ };
296
307
  commissions: {
297
308
  /** Our platform cut charged to the buyer as a % of order value (e.g. 5 = 5%). */
298
309
  platformFeePercent: number;
@@ -303,6 +314,9 @@ export interface SiteSettingsDocument extends BaseDocument {
303
314
  /** Razorpay gateway cost % (absorbed by platform, not passed through separately). */
304
315
  gatewayFeePercent: number;
305
316
  codDepositPercent: number;
317
+ /** COD handling fee charged to the buyer: max(codHandlingFeeMinInPaise, subtotal × codHandlingFeePercent / 100). */
318
+ codHandlingFeeMinInPaise: number;
319
+ codHandlingFeePercent: number;
306
320
  sellerShippingFixed: number;
307
321
  platformShippingPercent: number;
308
322
  platformShippingFixedMin: number;
@@ -362,12 +376,6 @@ export interface SiteSettingsDocument extends BaseDocument {
362
376
  * if this is ever true. Default false.
363
377
  */
364
378
  useMockPayment?: boolean;
365
- /**
366
- * Track H — when true and NODE_ENV !== "production", the shipping provider
367
- * resolver returns MockShiprocketProvider. In production the resolver throws
368
- * if this is ever true. Default false.
369
- */
370
- useMockShipping?: boolean;
371
379
  listingTypes?: {
372
380
  standard?: boolean;
373
381
  auction?: boolean;
@@ -167,16 +167,27 @@ export const DEFAULT_SITE_SETTINGS_DATA = {
167
167
  motto: "Your Marketplace, Your Rules",
168
168
  theme: DEFAULT_SITE_SETTINGS_THEME,
169
169
  payment: {
170
- razorpayEnabled: true,
170
+ razorpayEnabled: false,
171
171
  upiManualEnabled: true,
172
172
  codEnabled: true,
173
173
  },
174
+ emi: {
175
+ enabled: false,
176
+ minOrderValueInPaise: 1000000,
177
+ tenureOptions: [2, 3, 4, 5, 6],
178
+ tokenPercent: 10,
179
+ billingDay: 5,
180
+ surchargePercentPerMonth: 1,
181
+ surchargeSellerSharePercent: 50,
182
+ },
174
183
  commissions: {
175
184
  platformFeePercent: 5,
176
185
  gstPercent: 18,
177
186
  minimumTransactionFee: 0,
178
187
  gatewayFeePercent: 2,
179
188
  codDepositPercent: 10,
189
+ codHandlingFeeMinInPaise: 20000,
190
+ codHandlingFeePercent: 10,
180
191
  sellerShippingFixed: 0,
181
192
  platformShippingPercent: 10,
182
193
  platformShippingFixedMin: 0,
@@ -205,7 +216,6 @@ export const DEFAULT_SITE_SETTINGS_DATA = {
205
216
  // Track H — both mock-provider flags default to false. Production
206
217
  // deployments must never flip these on (the resolver throws if they are).
207
218
  useMockPayment: false,
208
- useMockShipping: false,
209
219
  // W1-37 2026-05-23 — Phase 2 listing types enabled by default; all per-type
210
220
  // surfaces (seller + admin via W1-29 + public) are now shipped.
211
221
  listingTypes: {
@@ -1,4 +1,5 @@
1
1
  import { type WishlistToggleActions } from "../../wishlist";
2
+ import type { ListingType } from "../../products/types/index";
2
3
  export interface MarketplaceAuctionCardData {
3
4
  id: string;
4
5
  title: string;
@@ -11,8 +12,8 @@ export interface MarketplaceAuctionCardData {
11
12
  url?: string;
12
13
  thumbnailUrl?: string;
13
14
  };
14
- /** Canonical discriminator (SB1-G Phase 4 · SB-UNI-F 2026-05-13 union extension). */
15
- listingType?: "standard" | "auction" | "pre-order" | "prize-draw" | "classified" | "digital-code" | "live";
15
+ /** Canonical discriminator (SB1-G Phase 4). */
16
+ listingType?: ListingType;
16
17
  auctionEndDate?: string | Date;
17
18
  startingBid?: number;
18
19
  currentBid?: number;
@@ -57,6 +57,17 @@ export function useGoogleLogin(options) {
57
57
  const [popupPending, setPopupPending] = useState(false);
58
58
  // calledRef prevents both RTDB and postMessage from firing the callbacks
59
59
  const calledRef = useRef(false);
60
+ // Polls for the popup being closed manually (without completing sign-in).
61
+ // Without this, a user who closes the popup before RTDB/postMessage
62
+ // resolves leaves popupPending stuck true forever — the button never
63
+ // recovers from its loading state.
64
+ const closePollRef = useRef(null);
65
+ const clearClosePoll = useCallback(() => {
66
+ if (closePollRef.current !== null) {
67
+ clearInterval(closePollRef.current);
68
+ closePollRef.current = null;
69
+ }
70
+ }, []);
60
71
  const onSuccessRef = useRef(options?.onSuccess);
61
72
  const onErrorRef = useRef(options?.onError);
62
73
  const onSessionSyncedRef = useRef(options?.onSessionSynced);
@@ -65,6 +76,8 @@ export function useGoogleLogin(options) {
65
76
  useEffect(() => { onErrorRef.current = options?.onError; }, [options?.onError]);
66
77
  useEffect(() => { onSessionSyncedRef.current = options?.onSessionSynced; }, [options?.onSessionSynced]);
67
78
  useEffect(() => { authEventResetRef.current = authEvent.reset; }, [authEvent.reset]);
79
+ // Stop polling for popup-closed if the component unmounts mid-flow.
80
+ useEffect(() => clearClosePoll, [clearClosePoll]);
68
81
  // RTDB status watcher — fast path when RTDB is available.
69
82
  // FAILED is intentionally not forwarded to onError here: RTDB connection
70
83
  // failures (e.g. missing database URL) should fall through to the postMessage
@@ -75,6 +88,7 @@ export function useGoogleLogin(options) {
75
88
  if (calledRef.current)
76
89
  return;
77
90
  calledRef.current = true;
91
+ clearClosePoll();
78
92
  Promise.resolve(onSessionSyncedRef.current?.()).then(() => {
79
93
  onSuccessRef.current?.(authEvent.data);
80
94
  });
@@ -85,10 +99,11 @@ export function useGoogleLogin(options) {
85
99
  if (calledRef.current)
86
100
  return;
87
101
  calledRef.current = true;
102
+ clearClosePoll();
88
103
  onErrorRef.current?.(new Error(authEvent.error ?? "Sign-in timed out. Please try again."));
89
104
  }
90
105
  // FAILED: do not call onError — wait for the postMessage from /auth/close
91
- }, [authEvent.status, authEvent.error, authEvent.data]);
106
+ }, [authEvent.status, authEvent.error, authEvent.data, clearClosePoll]);
92
107
  // postMessage fallback — fires when /auth/close sends window.opener.postMessage.
93
108
  // This covers two cases:
94
109
  // 1. RTDB is unavailable (the primary channel failed)
@@ -104,6 +119,7 @@ export function useGoogleLogin(options) {
104
119
  return;
105
120
  calledRef.current = true;
106
121
  setPopupPending(false);
122
+ clearClosePoll();
107
123
  authEventResetRef.current();
108
124
  if (event.data.status === "success") {
109
125
  const data = event.data.uid
@@ -119,7 +135,7 @@ export function useGoogleLogin(options) {
119
135
  };
120
136
  window.addEventListener("message", handleMessage);
121
137
  return () => window.removeEventListener("message", handleMessage);
122
- }, []); // mount once uses refs, no stale closure risk
138
+ }, [clearClosePoll]); // clearClosePoll has a stable identity effectively mount-once
123
139
  const mutate = useCallback(async () => {
124
140
  calledRef.current = false; // reset for each new auth flow
125
141
  const popup = window.open(`${window.location.origin}/auth.html`, "oauth_google", "width=500,height=660,left=400,top=100");
@@ -128,6 +144,16 @@ export function useGoogleLogin(options) {
128
144
  return;
129
145
  }
130
146
  setPopupPending(true);
147
+ clearClosePoll();
148
+ closePollRef.current = setInterval(() => {
149
+ if (popup.closed && !calledRef.current) {
150
+ calledRef.current = true;
151
+ clearClosePoll();
152
+ setPopupPending(false);
153
+ authEventResetRef.current();
154
+ onErrorRef.current?.(new Error("Sign-in was cancelled."));
155
+ }
156
+ }, 500);
131
157
  try {
132
158
  setInitiating(true);
133
159
  authEvent.reset();
@@ -142,6 +168,7 @@ export function useGoogleLogin(options) {
142
168
  }
143
169
  catch (err) {
144
170
  void normalizeError(err);
171
+ clearClosePoll();
145
172
  popup.close();
146
173
  setPopupPending(false);
147
174
  onErrorRef.current?.(err instanceof Error ? err : new Error("Failed to start sign-in."));
@@ -149,7 +176,7 @@ export function useGoogleLogin(options) {
149
176
  finally {
150
177
  setInitiating(false);
151
178
  }
152
- }, [authEvent]);
179
+ }, [authEvent, clearClosePoll]);
153
180
  const isLoading = initiating ||
154
181
  popupPending ||
155
182
  authEvent.status === RealtimeEventStatus.SUBSCRIBING ||
@@ -166,13 +193,12 @@ export function useRegister(options) {
166
193
  displayName: data.displayName?.trim() || "",
167
194
  acceptTerms: data.acceptTerms,
168
195
  });
169
- // Sign in via client SDK and exchange ID token for a server session cookie
196
+ // /api/auth/register already created the server-side session cookie +
197
+ // Firestore session doc. Sign in via the client SDK only so
198
+ // `auth.currentUser` is populated for client-side Firebase usage
199
+ // (RTDB presence, etc) — do NOT call /api/auth/session again here,
200
+ // that would create a second, orphaned session document.
170
201
  await getClientAuthProvider().signInWithEmailAndPassword(data.email.trim(), data.password);
171
- const currentUser = getClientSessionAdapter().getCurrentUser();
172
- if (currentUser) {
173
- const idToken = await currentUser.getIdToken(true);
174
- await apiClient.post(AUTH_ENDPOINTS.SESSION, { idToken });
175
- }
176
202
  return { success: true, ...response };
177
203
  },
178
204
  onSuccess: options?.onSuccess,
@@ -109,7 +109,8 @@ export interface UserSoftBan {
109
109
  /** Null or absent = permanent. Past date = expired (treated as lifted without deletion). */
110
110
  expiresAt?: Date | null;
111
111
  }
112
- export type SellerShippingMethod = "custom" | "shiprocket";
112
+ /** Manual shipping is the only supported method — sellers enter carrier + tracking directly, no carrier API integration. */
113
+ export type SellerShippingMethod = "custom";
113
114
  export interface SellerPickupAddress {
114
115
  locationName: string;
115
116
  name: string;
@@ -122,16 +123,11 @@ export interface SellerPickupAddress {
122
123
  pincode: string;
123
124
  country: string;
124
125
  isVerified: boolean;
125
- shiprocketAddressId?: number;
126
126
  }
127
127
  export interface SellerShippingConfig {
128
128
  method: SellerShippingMethod;
129
129
  customShippingPrice?: number;
130
130
  customCarrierName?: string;
131
- shiprocketEmail?: string;
132
- /** Shiprocket JWT — server-only, never returned to client. */
133
- shiprocketToken?: string;
134
- shiprocketTokenExpiry?: Date;
135
131
  pickupAddress?: SellerPickupAddress;
136
132
  isConfigured: boolean;
137
133
  }
@@ -5,6 +5,7 @@
5
5
  * for the cart feature.
6
6
  */
7
7
  import type { BaseDocument } from "../../../_internal/shared/types/base-document";
8
+ import type { ListingType } from "../../products/types/index";
8
9
  export interface CartItemDocument {
9
10
  itemId: string;
10
11
  productId: string;
@@ -22,7 +23,7 @@ export interface CartItemDocument {
22
23
  * carts) and cart-side UI badges. Replaces the legacy `isAuction`/`isPreOrder`
23
24
  * pair on the cart item.
24
25
  */
25
- listingType: "standard" | "auction" | "pre-order" | "prize-draw" | "classified" | "digital-code" | "live";
26
+ listingType: ListingType;
26
27
  /** True when item was added from an accepted Make-an-Offer */
27
28
  isOffer?: boolean;
28
29
  offerId?: string;
@@ -110,7 +111,7 @@ export type AddToCartInput = {
110
111
  /** Store slug (= storeId = store.id) */
111
112
  storeId: string;
112
113
  storeName: string;
113
- listingType: "standard" | "auction" | "pre-order" | "prize-draw" | "classified" | "digital-code" | "live";
114
+ listingType: ListingType;
114
115
  isOffer?: boolean;
115
116
  offerId?: string;
116
117
  lockedPrice?: number;
@@ -26,7 +26,7 @@ export declare const consultationBookingSchema: z.ZodObject<{
26
26
  adminNote: z.ZodOptional<z.ZodString>;
27
27
  createdAt: z.ZodOptional<z.ZodString>;
28
28
  }, "strip", z.ZodTypeAny, {
29
- status: "cancelled" | "pending" | "completed" | "confirmed" | "no_show";
29
+ status: "cancelled" | "pending" | "confirmed" | "completed" | "no_show";
30
30
  id: string;
31
31
  name: string;
32
32
  email: string;
@@ -43,7 +43,7 @@ export declare const consultationBookingSchema: z.ZodObject<{
43
43
  id: string;
44
44
  name: string;
45
45
  email: string;
46
- status?: "cancelled" | "pending" | "completed" | "confirmed" | "no_show" | undefined;
46
+ status?: "cancelled" | "pending" | "confirmed" | "completed" | "no_show" | undefined;
47
47
  message?: string | undefined;
48
48
  phone?: string | undefined;
49
49
  createdAt?: string | undefined;
@@ -9,12 +9,12 @@ export declare const coinHistoryEntrySchema: z.ZodObject<{
9
9
  orderId: z.ZodOptional<z.ZodString>;
10
10
  timestamp: z.ZodOptional<z.ZodString>;
11
11
  }, "strip", z.ZodTypeAny, {
12
- reason: "expiry" | "redemption" | "order_reward" | "referral" | "review_reward" | "manual_credit" | "manual_debit";
12
+ reason: "redemption" | "order_reward" | "referral" | "review_reward" | "manual_credit" | "manual_debit" | "expiry";
13
13
  delta: number;
14
14
  orderId?: string | undefined;
15
15
  timestamp?: string | undefined;
16
16
  }, {
17
- reason: "expiry" | "redemption" | "order_reward" | "referral" | "review_reward" | "manual_credit" | "manual_debit";
17
+ reason: "redemption" | "order_reward" | "referral" | "review_reward" | "manual_credit" | "manual_debit" | "expiry";
18
18
  delta: number;
19
19
  orderId?: string | undefined;
20
20
  timestamp?: string | undefined;
@@ -38,12 +38,12 @@ export declare const loyaltyBalanceSchema: z.ZodObject<{
38
38
  orderId: z.ZodOptional<z.ZodString>;
39
39
  timestamp: z.ZodOptional<z.ZodString>;
40
40
  }, "strip", z.ZodTypeAny, {
41
- reason: "expiry" | "redemption" | "order_reward" | "referral" | "review_reward" | "manual_credit" | "manual_debit";
41
+ reason: "redemption" | "order_reward" | "referral" | "review_reward" | "manual_credit" | "manual_debit" | "expiry";
42
42
  delta: number;
43
43
  orderId?: string | undefined;
44
44
  timestamp?: string | undefined;
45
45
  }, {
46
- reason: "expiry" | "redemption" | "order_reward" | "referral" | "review_reward" | "manual_credit" | "manual_debit";
46
+ reason: "redemption" | "order_reward" | "referral" | "review_reward" | "manual_credit" | "manual_debit" | "expiry";
47
47
  delta: number;
48
48
  orderId?: string | undefined;
49
49
  timestamp?: string | undefined;
@@ -52,7 +52,7 @@ export declare const loyaltyBalanceSchema: z.ZodObject<{
52
52
  uid: string;
53
53
  hcCoins: number;
54
54
  coinHistory?: {
55
- reason: "expiry" | "redemption" | "order_reward" | "referral" | "review_reward" | "manual_credit" | "manual_debit";
55
+ reason: "redemption" | "order_reward" | "referral" | "review_reward" | "manual_credit" | "manual_debit" | "expiry";
56
56
  delta: number;
57
57
  orderId?: string | undefined;
58
58
  timestamp?: string | undefined;
@@ -61,7 +61,7 @@ export declare const loyaltyBalanceSchema: z.ZodObject<{
61
61
  uid: string;
62
62
  hcCoins?: number | undefined;
63
63
  coinHistory?: {
64
- reason: "expiry" | "redemption" | "order_reward" | "referral" | "review_reward" | "manual_credit" | "manual_debit";
64
+ reason: "redemption" | "order_reward" | "referral" | "review_reward" | "manual_credit" | "manual_debit" | "expiry";
65
65
  delta: number;
66
66
  orderId?: string | undefined;
67
67
  timestamp?: string | undefined;
@@ -181,9 +181,14 @@ declare class OrderRepository extends BaseRepository<OrderDocument> {
181
181
  data: OrderDocument;
182
182
  }>>;
183
183
  /**
184
- * Cloud Functions: find shiprocket-shipped delivered orders eligible for payout.
184
+ * Cloud Functions: find delivered orders eligible for the weekly payout sweep.
185
+ *
186
+ * EMI orders that still have unpaid installments are excluded — the seller
187
+ * is only eligible once the buyer has fully paid off the order, not merely
188
+ * once it's delivered (a seller-enabled `allowShipBeforeEmiComplete` item
189
+ * can be delivered long before EMI collection finishes).
185
190
  */
186
- getEligibleShiprocket(): Promise<Array<{
191
+ getEligibleForPayoutSweep(): Promise<Array<{
187
192
  id: string;
188
193
  ref: DocumentReference;
189
194
  data: OrderDocument;
@@ -192,12 +197,25 @@ declare class OrderRepository extends BaseRepository<OrderDocument> {
192
197
  * Cloud Functions: find auto-payout eligible delivered orders older than windowDays business days.
193
198
  * @param windowDays - number of business days since delivery
194
199
  * @param cutoff - pre-computed business-day cutoff date (computed by caller)
200
+ *
201
+ * See {@link getEligibleForPayoutSweep} for the EMI-incomplete exclusion rationale.
195
202
  */
196
203
  getEligibleAutomatic(cutoff: Date): Promise<Array<{
197
204
  id: string;
198
205
  ref: DocumentReference;
199
206
  data: OrderDocument;
200
207
  }>>;
208
+ /**
209
+ * Cloud Functions: EMI reminder sweep — orders on an active (not yet fully
210
+ * paid) EMI plan. Per-installment due-date filtering happens in the job
211
+ * itself since `emiInstallments` is an array field Firestore can't range-
212
+ * query on.
213
+ */
214
+ getActiveEmiOrders(): Promise<Array<{
215
+ id: string;
216
+ ref: DocumentReference;
217
+ data: OrderDocument;
218
+ }>>;
201
219
  /**
202
220
  * Cloud Functions: stage a payout-requested update into a caller-owned WriteBatch.
203
221
  */
@@ -268,26 +268,34 @@ class OrderRepository extends BaseRepository {
268
268
  }));
269
269
  }
270
270
  /**
271
- * Cloud Functions: find shiprocket-shipped delivered orders eligible for payout.
271
+ * Cloud Functions: find delivered orders eligible for the weekly payout sweep.
272
+ *
273
+ * EMI orders that still have unpaid installments are excluded — the seller
274
+ * is only eligible once the buyer has fully paid off the order, not merely
275
+ * once it's delivered (a seller-enabled `allowShipBeforeEmiComplete` item
276
+ * can be delivered long before EMI collection finishes).
272
277
  */
273
- async getEligibleShiprocket() {
278
+ async getEligibleForPayoutSweep() {
274
279
  const snap = await this.db
275
280
  .collection(this.collection)
276
281
  .where(ORDER_FIELDS.PAYOUT_STATUS, "==", "eligible")
277
- .where(ORDER_FIELDS.SHIPPING_METHOD, "==", "shiprocket")
278
282
  .where(ORDER_FIELDS.STATUS, "==", OrderStatusValues.DELIVERED)
279
283
  .limit(500)
280
284
  .get();
281
- return snap.docs.map((d) => ({
285
+ return snap.docs
286
+ .map((d) => ({
282
287
  id: d.id,
283
288
  ref: d.ref,
284
289
  data: this.decryptOrder({ id: d.id, ...d.data() }),
285
- }));
290
+ }))
291
+ .filter((o) => !o.data.emiEnabled || o.data.emiComplete);
286
292
  }
287
293
  /**
288
294
  * Cloud Functions: find auto-payout eligible delivered orders older than windowDays business days.
289
295
  * @param windowDays - number of business days since delivery
290
296
  * @param cutoff - pre-computed business-day cutoff date (computed by caller)
297
+ *
298
+ * See {@link getEligibleForPayoutSweep} for the EMI-incomplete exclusion rationale.
291
299
  */
292
300
  async getEligibleAutomatic(cutoff) {
293
301
  const snap = await this.db
@@ -297,6 +305,27 @@ class OrderRepository extends BaseRepository {
297
305
  .where(ORDER_FIELDS.UPDATED_AT, "<=", cutoff)
298
306
  .limit(500)
299
307
  .get();
308
+ return snap.docs
309
+ .map((d) => ({
310
+ id: d.id,
311
+ ref: d.ref,
312
+ data: this.decryptOrder({ id: d.id, ...d.data() }),
313
+ }))
314
+ .filter((o) => !o.data.emiEnabled || o.data.emiComplete);
315
+ }
316
+ /**
317
+ * Cloud Functions: EMI reminder sweep — orders on an active (not yet fully
318
+ * paid) EMI plan. Per-installment due-date filtering happens in the job
319
+ * itself since `emiInstallments` is an array field Firestore can't range-
320
+ * query on.
321
+ */
322
+ async getActiveEmiOrders() {
323
+ const snap = await this.db
324
+ .collection(this.collection)
325
+ .where("emiEnabled", "==", true)
326
+ .where("emiComplete", "==", false)
327
+ .limit(500)
328
+ .get();
300
329
  return snap.docs.map((d) => ({
301
330
  id: d.id,
302
331
  ref: d.ref,
@@ -5,14 +5,14 @@ import type { OrderStatus, PaymentStatus } from "../types";
5
5
  import type { OrderType } from "../utils/order-splitter";
6
6
  import type { BaseDocument } from "../../../_internal/shared/types/base-document";
7
7
  import type { ListingType } from "../../products/types";
8
- export type ShippingMethod = "custom" | "shiprocket";
8
+ /** Manual shipping is the only supported method — sellers enter carrier + tracking directly, no carrier API integration. */
9
+ export type ShippingMethod = "custom";
9
10
  export type RefundType = "full" | "partial";
10
11
  export type OrderPayoutStatus = "eligible" | "requested" | "paid";
11
12
  export type RefundStatus = "pending" | "processing" | "completed" | "rejected";
12
13
  /** Runtime-accessible shipping method values â€" use instead of bare string literals. */
13
14
  export declare const ShippingMethodValues: {
14
15
  readonly CUSTOM: "custom";
15
- readonly SHIPROCKET: "shiprocket";
16
16
  };
17
17
  /** Runtime-accessible order status values â€" use instead of bare string literals. */
18
18
  export declare const OrderStatusValues: {
@@ -43,7 +43,24 @@ export declare const PaymentMethodValues: {
43
43
  readonly UPI_MANUAL: "upi_manual";
44
44
  readonly RAZORPAY: "razorpay";
45
45
  readonly ADMIN_BYPASS: "admin_bypass";
46
+ readonly EMI: "emi";
46
47
  };
48
+ export type EmiInstallmentStatus = "pending" | "paid" | "overdue";
49
+ export interface EmiInstallment {
50
+ /** 1-based installment number. */
51
+ index: number;
52
+ dueDate: Date;
53
+ /** Installment amount in paise (principal share + surcharge share for this installment). */
54
+ amount: number;
55
+ status: EmiInstallmentStatus;
56
+ paidAt?: Date;
57
+ /** Buyer-uploaded UTR/reference number for this installment's manual payment. */
58
+ transactionId?: string;
59
+ /** Signed-URL media slug for the buyer's payment proof for this installment. */
60
+ proofUrl?: string;
61
+ /** Set once the reminder sweep has notified the buyer for this installment, so it isn't re-sent on every sweep run. */
62
+ reminderSentAt?: Date;
63
+ }
47
64
  /** Runtime-accessible refund status values â€" use instead of bare string literals. */
48
65
  export declare const RefundStatusValues: {
49
66
  readonly PENDING: "pending";
@@ -141,15 +158,24 @@ export interface OrderDocument extends BaseDocument {
141
158
  platformFee?: number;
142
159
  depositAmount?: number;
143
160
  codRemainingAmount?: number;
161
+ /** COD handling fee charged to the buyer: max(codHandlingFeeMinInPaise, subtotal × codHandlingFeePercent / 100). Only set when paymentMethod === "cod". */
162
+ codHandlingFee?: number;
163
+ emiEnabled?: boolean;
164
+ /** Number of monthly installments the buyer chose (2–6). */
165
+ emiTenureMonths?: number;
166
+ /** Down payment collected at checkout, in paise (emiTokenPercent × seller subtotal). */
167
+ emiTokenAmount?: number;
168
+ /** Extra cost of choosing EMI over full payment, in paise — split between platform and seller. */
169
+ emiSurchargeAmount?: number;
170
+ emiInstallments?: EmiInstallment[];
171
+ /** Sum of unpaid installment amounts, in paise. 0 once all installments are paid. */
172
+ emiRemainingBalance?: number;
173
+ /** True once every installment's status is "paid". Gates shipment unless the product's `allowShipBeforeEmiComplete` flag is set. */
174
+ emiComplete?: boolean;
144
175
  shippingFee?: number;
145
176
  shippingMethod?: ShippingMethod;
146
177
  shippingCarrier?: string;
147
178
  trackingUrl?: string;
148
- shiprocketOrderId?: number;
149
- shiprocketShipmentId?: number;
150
- shiprocketAWB?: string;
151
- shiprocketStatus?: string;
152
- shiprocketUpdatedAt?: Date;
153
179
  payoutStatus?: OrderPayoutStatus;
154
180
  payoutId?: string;
155
181
  offerId?: string;
@@ -5,7 +5,6 @@ import { generateOrderId } from "../../../utils/id-generators";
5
5
  /** Runtime-accessible shipping method values â€" use instead of bare string literals. */
6
6
  export const ShippingMethodValues = {
7
7
  CUSTOM: "custom",
8
- SHIPROCKET: "shiprocket",
9
8
  };
10
9
  /** Runtime-accessible order status values â€" use instead of bare string literals. */
11
10
  export const OrderStatusValues = {
@@ -36,6 +35,7 @@ export const PaymentMethodValues = {
36
35
  UPI_MANUAL: "upi_manual",
37
36
  RAZORPAY: "razorpay",
38
37
  ADMIN_BYPASS: "admin_bypass",
38
+ EMI: "emi",
39
39
  };
40
40
  /** Runtime-accessible refund status values â€" use instead of bare string literals. */
41
41
  export const RefundStatusValues = {