@mohasinac/appkit 4.42.18 → 4.44.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.
- package/dist/_internal/client/features/lottery/LotteryDetailView.js +22 -1
- package/dist/_internal/server/features/categories/adapters.d.ts +47 -0
- package/dist/_internal/server/features/categories/adapters.js +235 -0
- package/dist/_internal/server/features/checkout/actions.js +161 -22
- package/dist/_internal/server/features/checkout/expand-order-items.js +34 -0
- package/dist/_internal/server/features/orders/adapters.js +21 -0
- package/dist/_internal/server/features/products/list-public.d.ts +24 -0
- package/dist/_internal/server/features/products/list-public.js +10 -2
- package/dist/_internal/server/features/refunds/actions.js +1 -1
- package/dist/_internal/server/features/seo/sitemap.js +54 -15
- package/dist/_internal/server/features/stores/adapters.d.ts +1 -1
- package/dist/_internal/server/features/stores/adapters.js +6 -0
- package/dist/_internal/server/functions/scheduled.d.ts +4 -2
- package/dist/_internal/server/functions/scheduled.js +64 -6
- package/dist/_internal/server/jobs/core/adminAnalytics.d.ts +0 -1
- package/dist/_internal/server/jobs/core/adminAnalytics.js +9 -1
- package/dist/_internal/server/jobs/core/analyticsAlertEvaluate.d.ts +47 -0
- package/dist/_internal/server/jobs/core/analyticsAlertEvaluate.js +468 -0
- package/dist/_internal/server/jobs/core/autoPayoutEligibility.js +14 -1
- package/dist/_internal/server/jobs/core/countersReconcile.js +24 -8
- package/dist/_internal/server/jobs/core/onCategoryWrite.js +59 -0
- package/dist/_internal/server/jobs/core/onProductWrite.js +31 -0
- package/dist/_internal/server/jobs/core/onReviewWrite.js +8 -0
- package/dist/_internal/server/jobs/core/onStoreWrite.d.ts +1 -1
- package/dist/_internal/server/jobs/core/onStoreWrite.js +8 -2
- package/dist/_internal/server/jobs/core/priceIndexRollup.d.ts +47 -0
- package/dist/_internal/server/jobs/core/priceIndexRollup.js +234 -0
- package/dist/_internal/server/jobs/core/revalidateNotify.d.ts +28 -0
- package/dist/_internal/server/jobs/core/revalidateNotify.js +125 -0
- package/dist/_internal/server/jobs/core/{testerSandboxCleanup.d.ts → testDataCleanup.d.ts} +3 -3
- package/dist/_internal/server/jobs/core/{testerSandboxCleanup.js → testDataCleanup.js} +3 -3
- package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.js +5 -1
- package/dist/_internal/server/jobs/handlers/analyticsAlertEvaluate.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/analyticsAlertEvaluate.js +2 -0
- package/dist/_internal/server/jobs/handlers/index.d.ts +3 -1
- package/dist/_internal/server/jobs/handlers/index.js +3 -1
- package/dist/_internal/server/jobs/handlers/messages.d.ts +5 -2
- package/dist/_internal/server/jobs/handlers/messages.js +5 -2
- package/dist/_internal/server/jobs/handlers/priceIndexRollup.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/priceIndexRollup.js +2 -0
- package/dist/_internal/server/jobs/handlers/testDataCleanup.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/testDataCleanup.js +2 -0
- package/dist/_internal/shared/actions/action-registry.js +34 -0
- package/dist/_internal/shared/cache/revalidate-targets.d.ts +49 -0
- package/dist/_internal/shared/cache/revalidate-targets.js +157 -0
- package/dist/_internal/shared/checkout/order-math.d.ts +113 -3
- package/dist/_internal/shared/checkout/order-math.js +194 -7
- package/dist/_internal/shared/features/categories/price-guidance.d.ts +110 -0
- package/dist/_internal/shared/features/categories/price-guidance.js +136 -0
- package/dist/_internal/shared/features/site-settings/gst-registration.d.ts +90 -0
- package/dist/_internal/shared/features/site-settings/gst-registration.js +126 -0
- package/dist/_internal/shared/fees/calculator.d.ts +105 -0
- package/dist/_internal/shared/fees/calculator.js +143 -0
- package/dist/_internal/shared/listing-types/art/config.d.ts +0 -6
- package/dist/_internal/shared/listing-types/classified/config.d.ts +0 -6
- package/dist/_internal/shared/listing-types/digital-code/config.d.ts +0 -6
- package/dist/_internal/shared/listing-types/live/config.d.ts +0 -6
- package/dist/_internal/shared/listing-types/standard/config.d.ts +0 -6
- package/dist/_internal/shared/listing-types/stickers/config.d.ts +0 -6
- package/dist/_internal/shared/templating/placeholders.d.ts +70 -0
- package/dist/_internal/shared/templating/placeholders.js +73 -0
- package/dist/client.d.ts +2 -0
- package/dist/client.js +1 -0
- package/dist/constants/api-endpoints.d.ts +42 -0
- package/dist/constants/api-endpoints.js +14 -0
- package/dist/features/admin/actions/admin-actions.d.ts +1 -1
- package/dist/features/admin/actions/admin-actions.js +1 -1
- package/dist/features/admin/components/AdminCategoryEditorView.js +269 -3
- package/dist/features/admin/components/AdminProductEditorView.js +8 -1
- package/dist/features/admin/components/AdminProductsView.js +78 -7
- package/dist/features/admin/components/AdminSiteSettingsView.js +20 -1
- package/dist/features/admin/components/AdminTaxCodeEditorView.d.ts +10 -0
- package/dist/features/admin/components/AdminTaxCodeEditorView.js +160 -0
- package/dist/features/admin/components/AdminTaxCodesView.d.ts +13 -0
- package/dist/features/admin/components/AdminTaxCodesView.js +86 -0
- package/dist/features/admin/components/AdminTesterChecklistView.js +1 -1
- package/dist/features/admin/components/analytics/AdminTopProductsTable.js +1 -1
- package/dist/features/auctions/components/AuctionBottomActions.js +10 -1
- package/dist/features/auctions/components/AuctionDetailPageView.js +2 -1
- package/dist/features/auctions/components/AuctionLiveStatusBadge.d.ts +20 -0
- package/dist/features/auctions/components/AuctionLiveStatusBadge.js +21 -0
- package/dist/features/auctions/components/PlaceBidFormClient.d.ts +1 -1
- package/dist/features/auctions/components/PlaceBidFormClient.js +20 -2
- package/dist/features/auctions/hooks/useIsAuctionEnded.d.ts +41 -0
- package/dist/features/auctions/hooks/useIsAuctionEnded.js +76 -0
- package/dist/features/auth/schemas/firestore.d.ts +0 -1
- package/dist/features/blog/api/route.js +16 -1
- package/dist/features/blog/schemas/firestore.d.ts +2 -2
- package/dist/features/catalogue/components/CatalogueItemEditorView.js +14 -3
- package/dist/features/categories/actions/category-actions.d.ts +2 -2
- package/dist/features/categories/actions/category-actions.js +22 -10
- package/dist/features/categories/api/[id]/description-template/route.d.ts +45 -0
- package/dist/features/categories/api/[id]/description-template/route.js +252 -0
- package/dist/features/categories/api/route.js +156 -11
- package/dist/features/categories/components/CategoriesIndexListing.d.ts +1 -3
- package/dist/features/categories/components/CategoriesIndexListing.js +1 -1
- package/dist/features/categories/components/CategoriesIndexPageView.d.ts +27 -1
- package/dist/features/categories/components/CategoriesIndexPageView.js +24 -33
- package/dist/features/categories/components/CategoryDetailPageView.js +43 -10
- package/dist/features/categories/components/CategoryTemplatePicker.d.ts +65 -0
- package/dist/features/categories/components/CategoryTemplatePicker.js +170 -0
- package/dist/features/categories/constants/listing-categories.d.ts +17 -0
- package/dist/features/categories/constants/listing-categories.js +53 -0
- package/dist/features/categories/hooks/useCategoryTree.js +28 -2
- package/dist/features/categories/repository/categories.repository.d.ts +73 -12
- package/dist/features/categories/repository/categories.repository.js +203 -42
- package/dist/features/categories/repository/price-index.repository.d.ts +115 -0
- package/dist/features/categories/repository/price-index.repository.js +85 -0
- package/dist/features/categories/schemas/category-content.d.ts +206 -0
- package/dist/features/categories/schemas/category-content.js +28 -0
- package/dist/features/categories/schemas/firestore.d.ts +74 -5
- package/dist/features/categories/schemas/firestore.js +74 -3
- package/dist/features/categories/schemas/index.d.ts +1047 -0
- package/dist/features/categories/schemas/index.js +96 -0
- package/dist/features/categories/server.d.ts +1 -0
- package/dist/features/categories/server.js +7 -0
- package/dist/features/categories/types/index.d.ts +9 -0
- package/dist/features/events/schemas/firestore.d.ts +2 -2
- package/dist/features/faq/schemas/firestore.d.ts +2 -1
- package/dist/features/faq/schemas/firestore.js +20 -8
- package/dist/features/faq/utils/getHomepageFaqsCached.d.ts +20 -0
- package/dist/features/faq/utils/getHomepageFaqsCached.js +22 -0
- package/dist/features/homepage/components/MarketplaceHomepageView.js +13 -3
- package/dist/features/homepage/lib/live-stats.js +18 -8
- package/dist/features/media/MediaImage.js +19 -2
- package/dist/features/orders/schemas/firestore.d.ts +70 -0
- package/dist/features/orders/types/index.d.ts +55 -0
- package/dist/features/products/actions/product-actions.d.ts +0 -9
- package/dist/features/products/actions/product-actions.js +25 -0
- package/dist/features/products/columns/index.d.ts +0 -1
- package/dist/features/products/columns/index.js +5 -1
- package/dist/features/products/components/ArtStickersListView.js +7 -1
- package/dist/features/products/components/PrizeDrawsSection.js +5 -0
- package/dist/features/products/components/ProductFilters.d.ts +0 -9
- package/dist/features/products/components/ProductForm.d.ts +27 -1
- package/dist/features/products/components/ProductForm.js +26 -12
- package/dist/features/products/components/ProductsIndexPageView.js +1 -1
- package/dist/features/products/constants/sieve.d.ts +0 -6
- package/dist/features/products/constants/sieve.js +35 -2
- package/dist/features/products/repository/products.repository.d.ts +115 -1
- package/dist/features/products/repository/products.repository.js +491 -39
- package/dist/features/products/schemas/firestore.d.ts +65 -5
- package/dist/features/products/schemas/firestore.js +9 -0
- package/dist/features/products/schemas/product-features.d.ts +140 -2
- package/dist/features/products/schemas/product-features.js +62 -1
- package/dist/features/promotions/repository/coupons.repository.js +6 -1
- package/dist/features/promotions/schemas/firestore.d.ts +44 -1
- package/dist/features/promotions/schemas/firestore.js +76 -2
- package/dist/features/reviews/repository/reviews.repository.d.ts +22 -0
- package/dist/features/reviews/repository/reviews.repository.js +35 -0
- package/dist/features/seller/actions/seller-actions.js +17 -2
- package/dist/features/seller/components/PrintCenterView.d.ts +3 -2
- package/dist/features/seller/components/PrintCenterView.js +3 -2
- package/dist/features/seller/components/SellerAnalyticsAlertsView.js +21 -11
- package/dist/features/seller/components/SellerOrdersView.js +6 -1
- package/dist/features/seller/components/SellerPayoutSettingsView.js +19 -3
- package/dist/features/seller/components/SellerProductShell.d.ts +50 -2
- package/dist/features/seller/components/SellerProductShell.js +101 -9
- package/dist/features/seller/components/SellerProductsFilterDrawer.d.ts +13 -1
- package/dist/features/seller/components/SellerProductsFilterDrawer.js +2 -2
- package/dist/features/seller/components/SellerProductsView.js +108 -3
- package/dist/features/seller/types/index.d.ts +17 -0
- package/dist/features/seller/utils/product-draft-mapping.d.ts +13 -0
- package/dist/features/seller/utils/product-draft-mapping.js +17 -0
- package/dist/features/store-extensions/constants/alert-metrics.d.ts +86 -0
- package/dist/features/store-extensions/constants/alert-metrics.js +142 -0
- package/dist/features/store-extensions/schemas/firestore.d.ts +19 -1
- package/dist/features/stores/schemas/firestore.d.ts +31 -2
- package/dist/features/tax-codes/repository/tax-codes.repository.d.ts +55 -0
- package/dist/features/tax-codes/repository/tax-codes.repository.js +131 -0
- package/dist/features/tax-codes/schemas/firestore.d.ts +125 -0
- package/dist/features/tax-codes/schemas/firestore.js +82 -0
- package/dist/features/tax-codes/schemas/tax-code-form.d.ts +63 -0
- package/dist/features/tax-codes/schemas/tax-code-form.js +152 -0
- package/dist/features/tax-codes/schemas/tax-codes.validators.d.ts +107 -0
- package/dist/features/tax-codes/schemas/tax-codes.validators.js +85 -0
- package/dist/features/tester/actions/index.d.ts +0 -1
- package/dist/features/tester/actions/index.js +0 -1
- package/dist/features/tester/components/AdminTesterFeedbackIssuesView.js +1 -1
- package/dist/features/tester/components/AdminTesterFeedbackListView.js +1 -1
- package/dist/features/tester/components/index.d.ts +0 -4
- package/dist/features/tester/components/index.js +0 -2
- package/dist/features/tester/repository/tester-checklist-item.repository.d.ts +1 -20
- package/dist/features/tester/repository/tester-checklist-item.repository.js +0 -52
- package/dist/features/tester/schemas/firestore.d.ts +0 -6
- package/dist/features/tester/seed-data/authored/admin__admin-detail-round-trips.js +3 -3
- package/dist/features/tester/seed-data/authored/admin__site-system.js +4 -5
- package/dist/features/tester/seed-data/authored/content-discovery__category-counts-and-rollup.js +2 -2
- package/dist/features/tester/seed-data/authored/index.js +0 -2
- package/dist/features/tester/seed-data/authored/page-wiring__reachability.js +0 -19
- package/dist/features/tester/seed-data/tester-checklist-seed-data.js +10 -29
- package/dist/index.d.ts +21 -7
- package/dist/index.js +53 -7
- package/dist/next/routing/route-map.d.ts +2 -4
- package/dist/next/routing/route-map.js +1 -2
- package/dist/repositories/index.d.ts +1 -0
- package/dist/repositories/index.js +1 -0
- package/dist/schemas/registry.d.ts +506 -0
- package/dist/seed/_helpers/brand-rows.d.ts +35 -0
- package/dist/seed/_helpers/brand-rows.js +576 -0
- package/dist/seed/_helpers/category-content.d.ts +39 -0
- package/dist/seed/_helpers/category-content.js +634 -0
- package/dist/seed/_helpers/category-forest.d.ts +2 -0
- package/dist/seed/_helpers/category-forest.js +585 -243
- package/dist/seed/_helpers/category-models.d.ts +5 -0
- package/dist/seed/_helpers/category-models.js +1364 -0
- package/dist/seed/_helpers/category-tree.js +17 -1
- package/dist/seed/_helpers/character-features.d.ts +10 -0
- package/dist/seed/_helpers/character-features.js +118 -0
- package/dist/seed/_helpers/media.d.ts +1 -1
- package/dist/seed/_helpers/media.js +44 -8
- package/dist/seed/_helpers/search-txt-wrappers.d.ts +10 -0
- package/dist/seed/_helpers/search-txt-wrappers.js +12 -1
- package/dist/seed/categories-seed-data.js +147 -169
- package/dist/seed/index.d.ts +1 -0
- package/dist/seed/index.js +1 -0
- package/dist/seed/manifest.d.ts +1 -1
- package/dist/seed/manifest.js +5 -0
- package/dist/seed/orders-seed-data.js +5 -3
- package/dist/seed/product-features-seed-data.d.ts +1 -8
- package/dist/seed/product-features-seed-data.js +358 -154
- package/dist/seed/products-art-seed-data.js +16 -4
- package/dist/seed/products-auctions-seed-data.js +6 -6
- package/dist/seed/products-classifieds-seed-data.js +17 -7
- package/dist/seed/products-digital-codes-seed-data.js +12 -12
- package/dist/seed/products-preorders-seed-data.js +8 -8
- package/dist/seed/products-prize-draws-seed-data.js +25 -8
- package/dist/seed/products-standard-seed-data.js +10 -60
- package/dist/seed/products-stickers-seed-data.js +6 -6
- package/dist/seed/site-settings-seed-data.js +24 -0
- package/dist/seed/store-extensions-seed-data.js +10 -4
- package/dist/seed/tax-codes-seed-data.d.ts +34 -0
- package/dist/seed/tax-codes-seed-data.js +100 -0
- package/dist/seed/test-data-ttl.d.ts +29 -0
- package/dist/seed/test-data-ttl.js +31 -0
- package/dist/server-entry.d.ts +1 -1
- package/dist/server-entry.js +6 -1
- package/dist/server.d.ts +4 -1
- package/dist/server.js +11 -2
- package/dist/styles.css +40 -0
- package/dist/ui/components/PaginatedSelect.d.ts +14 -0
- package/dist/ui/components/PaginatedSelect.js +0 -0
- package/dist/ui/components/PaginatedSelect.style.css +40 -0
- package/dist/utils/media-url.d.ts +26 -0
- package/dist/utils/media-url.js +144 -0
- package/dist/utils/physical-location.d.ts +23 -0
- package/dist/utils/physical-location.js +52 -0
- package/dist/utils/search-txt-builders.d.ts +20 -0
- package/dist/utils/search-txt-builders.js +36 -0
- package/package.json +1 -1
- package/scripts/seed-cli.mjs +4 -1
- package/dist/_internal/server/jobs/handlers/testerSandboxCleanup.d.ts +0 -2
- package/dist/_internal/server/jobs/handlers/testerSandboxCleanup.js +0 -2
- package/dist/features/tester/actions/leaderboard-actions.d.ts +0 -3
- package/dist/features/tester/actions/leaderboard-actions.js +0 -5
- package/dist/features/tester/components/BugHunterLeaderboardView.d.ts +0 -23
- package/dist/features/tester/components/BugHunterLeaderboardView.js +0 -18
- package/dist/features/tester/components/TesterHubView.d.ts +0 -5
- package/dist/features/tester/components/TesterHubView.js +0 -110
- package/dist/features/tester/seed-data/authored/public-pages__bug-hunters.d.ts +0 -2
- package/dist/features/tester/seed-data/authored/public-pages__bug-hunters.js +0 -78
- package/dist/features/tester/seed-data/tester-ttl.d.ts +0 -4
- package/dist/features/tester/seed-data/tester-ttl.js +0 -6
|
@@ -107,6 +107,149 @@ export function computeShipmentProtectionFee(subtotal, addonSelected, rates) {
|
|
|
107
107
|
const percentFee = roundRupees(subtotal * (percent / 100));
|
|
108
108
|
return Math.max(min, percentFee);
|
|
109
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* The rate used when nobody has determined one — HSN 95030020, non-electronic
|
|
112
|
+
* toys, which is nearly this whole catalogue.
|
|
113
|
+
*
|
|
114
|
+
* 🛑 A LAST RESORT, not a mechanism. The real resolution order is the
|
|
115
|
+
* product's own `gstRate` → the category's `taxCodeId` → this. A listing that
|
|
116
|
+
* reaches this constant means its category has no tax code, and THAT is the
|
|
117
|
+
* defect to fix; every use must warn and flag the product for triage. The
|
|
118
|
+
* measure of success is that it fires for nothing.
|
|
119
|
+
*
|
|
120
|
+
* It exists because the alternative is worse in one direction specifically:
|
|
121
|
+
* under GST-inclusive pricing the tax is already inside the price, so backing
|
|
122
|
+
* out 0% would treat the whole amount as taxable value, pay the seller all of
|
|
123
|
+
* it, and leave us owing tax on money already handed over. Exclusive pricing
|
|
124
|
+
* merely fails to collect, which does not lose money we hold.
|
|
125
|
+
*
|
|
126
|
+
* Belongs in `siteSettings.gst` the day a rate revision has to land without a
|
|
127
|
+
* deploy — `TaxCodeDocument.effectiveFrom` records that toys have already
|
|
128
|
+
* moved once — but a constant is the honest starting point rather than a
|
|
129
|
+
* settings field nobody has a reason to change.
|
|
130
|
+
*/
|
|
131
|
+
export const DEFAULT_GST_RATE = 5;
|
|
132
|
+
/**
|
|
133
|
+
* Whether this is an intra-state supply (CGST+SGST) or inter-state (IGST).
|
|
134
|
+
*
|
|
135
|
+
* 🛑 NOT a raw `===` on two strings, which is what `createOrderForGroup` and
|
|
136
|
+
* `previewCheckoutPricing` both did. `constants/geo/subdivisions.ts` opens by
|
|
137
|
+
* recording why that fails: the same `state` field held *"Karnataka",
|
|
138
|
+
* "karnataka", "KA" and "Karnatka" depending on which of the three surfaces
|
|
139
|
+
* created the row*. A picker now fixes new addresses, but the store's state
|
|
140
|
+
* and every pre-picker row still arrive unnormalised.
|
|
141
|
+
*
|
|
142
|
+
* 🛑 Returns `null` for "cannot tell", and the distinction matters. The old
|
|
143
|
+
* expression was `!!storeState && storeState === buyerState`, so a store with
|
|
144
|
+
* no address resolved to `false` — i.e. **silently inter-state**, reported as
|
|
145
|
+
* full IGST. Note what this defect is and is not: IGST total equals
|
|
146
|
+
* CGST+SGST total, so **the buyer pays exactly the same amount either way**.
|
|
147
|
+
* It is a compliance and reporting defect on the invoice, not an overcharge —
|
|
148
|
+
* which is why it is safe to surface as `null` and let the caller log rather
|
|
149
|
+
* than guess.
|
|
150
|
+
*/
|
|
151
|
+
export function isIntraStateSupply(storeState, buyerState) {
|
|
152
|
+
const a = normaliseStateName(storeState);
|
|
153
|
+
const b = normaliseStateName(buyerState);
|
|
154
|
+
if (!a || !b)
|
|
155
|
+
return null;
|
|
156
|
+
return a === b;
|
|
157
|
+
}
|
|
158
|
+
/** Lowercase, collapse whitespace, drop punctuation — "Tamil Nadu." → "tamil nadu". */
|
|
159
|
+
function normaliseStateName(raw) {
|
|
160
|
+
if (!raw)
|
|
161
|
+
return null;
|
|
162
|
+
const cleaned = raw
|
|
163
|
+
.normalize("NFKD")
|
|
164
|
+
.toLowerCase()
|
|
165
|
+
.replace(/[^a-z\s]/g, " ")
|
|
166
|
+
.replace(/\s+/g, " ")
|
|
167
|
+
.trim();
|
|
168
|
+
return cleaned.length > 0 ? cleaned : null;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Back the tax OUT of a tax-inclusive amount: `gross × 100 / (100 + rate)`.
|
|
172
|
+
*
|
|
173
|
+
* 🛑 **Every price in this system is tax-inclusive.** A listing's `price` is
|
|
174
|
+
* what the buyer pays; the GST is inside it and is remitted from it. That is
|
|
175
|
+
* the Indian B2C convention, it is what worldhobbyshop asserts in its own
|
|
176
|
+
* JSON-LD (`valueAddedTaxIncluded: true`), and it is what makes two listings
|
|
177
|
+
* at ₹999 cost the same regardless of which seller posted them.
|
|
178
|
+
*
|
|
179
|
+
* A seller who would rather think in ex-tax terms sets
|
|
180
|
+
* `StoreDocument.pricesIncludeGst: false`, and their typed price is grossed up
|
|
181
|
+
* **once, at write time**, by `ProductRepository`. So the flag is an
|
|
182
|
+
* AUTHORING convenience and never a display or checkout mode — the money
|
|
183
|
+
* paths have no branch on it at all, which is the whole point: a mode flag
|
|
184
|
+
* read in five places is five places to drift.
|
|
185
|
+
*
|
|
186
|
+
* `rate <= 0` returns the amount unchanged — an exempt supply has no tax to
|
|
187
|
+
* back out, and dividing by 100 would be a silent no-op that merely looked
|
|
188
|
+
* like arithmetic.
|
|
189
|
+
*/
|
|
190
|
+
export function taxableFromInclusive(gross, rate) {
|
|
191
|
+
if (rate <= 0)
|
|
192
|
+
return roundRupees(gross);
|
|
193
|
+
return roundRupees((gross * 100) / (100 + rate)); // audit-money-units-ok: tax back-out, not a paise conversion
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* The inverse: gross an EX-TAX amount up to its tax-inclusive equivalent,
|
|
197
|
+
* `taxable × (100 + rate) / 100`.
|
|
198
|
+
*
|
|
199
|
+
* Used in exactly one place — `ProductRepository`, when a store with
|
|
200
|
+
* `pricesIncludeGst: false` saves a price. That is the whole extent of the
|
|
201
|
+
* flag: one conversion, at write time, after which the stored price is
|
|
202
|
+
* tax-inclusive like every other and no money path can tell the difference.
|
|
203
|
+
*
|
|
204
|
+
* ₹999 ex-tax at 5% → ₹1,048.95 inclusive, which backs out to ₹999.00 again.
|
|
205
|
+
* The round trip is exact at 2dp for every rate in the union, asserted rather
|
|
206
|
+
* than assumed.
|
|
207
|
+
*/
|
|
208
|
+
export function grossFromTaxable(taxable, rate) {
|
|
209
|
+
if (rate <= 0)
|
|
210
|
+
return roundRupees(taxable);
|
|
211
|
+
return roundRupees((taxable * (100 + rate)) / 100); // audit-money-units-ok: tax gross-up, not a paise conversion
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* The breakdown of a tax-INCLUSIVE amount, with two invariants guaranteed by
|
|
215
|
+
* construction rather than by arithmetic luck:
|
|
216
|
+
*
|
|
217
|
+
* **taxable + gstAmount === gross** (to the paisa)
|
|
218
|
+
* **cgst + sgst === gstAmount** (to the paisa)
|
|
219
|
+
*
|
|
220
|
+
* 🛑 Why this exists instead of `calculateGst(rate, intra, taxableFromInclusive(...))`.
|
|
221
|
+
*
|
|
222
|
+
* That composition rounds TWICE and overshoots. Measured on the ₹999 @ 5% case
|
|
223
|
+
* the plan itself specifies: the taxable rounds UP to 951.43, then
|
|
224
|
+
* `calculateGst`'s intra branch takes `half = round(47.5715 / 2) = 23.79` and
|
|
225
|
+
* returns `round(half × 2) = 47.58` — so taxable + tax came to **₹999.01** and
|
|
226
|
+
* the invoice no longer reconciled with the ₹999 the buyer was charged.
|
|
227
|
+
*
|
|
228
|
+
* Under the old add-on-top model that could not happen: the tax was whatever
|
|
229
|
+
* it was and the total was defined as price + tax, so the invariant was free.
|
|
230
|
+
* Making prices inclusive is what turns it into something that must be
|
|
231
|
+
* enforced — the tax is now a PARTITION of a fixed amount, not an addition to
|
|
232
|
+
* it.
|
|
233
|
+
*
|
|
234
|
+
* So the tax is the **exact complement** of the taxable value, and the split
|
|
235
|
+
* assigns the remainder to the second half rather than rounding both. This is
|
|
236
|
+
* the same discipline `allocateAcrossMembers` already applies, and the same
|
|
237
|
+
* class of defect as the `Math.round(gstAmount / 2)` split that C0c's defect 2
|
|
238
|
+
* removed — one level further out.
|
|
239
|
+
*/
|
|
240
|
+
export function calculateGstInclusive(rate, intraState, gross) {
|
|
241
|
+
if (rate <= 0) {
|
|
242
|
+
const t = roundRupees(gross);
|
|
243
|
+
return { taxableAmount: t, cgst: 0, sgst: 0, igst: 0, gstAmount: 0 };
|
|
244
|
+
}
|
|
245
|
+
const taxableAmount = taxableFromInclusive(gross, rate);
|
|
246
|
+
const gstAmount = roundRupees(gross - taxableAmount);
|
|
247
|
+
if (intraState) {
|
|
248
|
+
const cgst = roundRupees(gstAmount / 2); // audit-money-units-ok: halving a tax amount
|
|
249
|
+
return { taxableAmount, cgst, sgst: roundRupees(gstAmount - cgst), igst: 0, gstAmount };
|
|
250
|
+
}
|
|
251
|
+
return { taxableAmount, cgst: 0, sgst: 0, igst: gstAmount, gstAmount };
|
|
252
|
+
}
|
|
110
253
|
export function calculateGst(rate, intraState, taxableAmount) {
|
|
111
254
|
const gstAmount = roundRupees(taxableAmount * (rate / 100));
|
|
112
255
|
if (intraState) {
|
|
@@ -48,9 +48,6 @@ export declare const config: {
|
|
|
48
48
|
}, {
|
|
49
49
|
readonly value: string;
|
|
50
50
|
readonly label: "Recently Updated";
|
|
51
|
-
}, {
|
|
52
|
-
readonly value: string;
|
|
53
|
-
readonly label: "Most Viewed";
|
|
54
51
|
}];
|
|
55
52
|
publicSortOptions: readonly [{
|
|
56
53
|
readonly value: string;
|
|
@@ -70,9 +67,6 @@ export declare const config: {
|
|
|
70
67
|
}, {
|
|
71
68
|
readonly value: string;
|
|
72
69
|
readonly label: "Name: Z–A";
|
|
73
|
-
}, {
|
|
74
|
-
readonly value: string;
|
|
75
|
-
readonly label: "Most Viewed";
|
|
76
70
|
}];
|
|
77
71
|
extraFacetKeys: readonly string[];
|
|
78
72
|
};
|
|
@@ -48,9 +48,6 @@ export declare const config: {
|
|
|
48
48
|
}, {
|
|
49
49
|
readonly value: string;
|
|
50
50
|
readonly label: "Recently Updated";
|
|
51
|
-
}, {
|
|
52
|
-
readonly value: string;
|
|
53
|
-
readonly label: "Most Viewed";
|
|
54
51
|
}];
|
|
55
52
|
publicSortOptions: readonly [{
|
|
56
53
|
readonly value: string;
|
|
@@ -70,9 +67,6 @@ export declare const config: {
|
|
|
70
67
|
}, {
|
|
71
68
|
readonly value: string;
|
|
72
69
|
readonly label: "Name: Z–A";
|
|
73
|
-
}, {
|
|
74
|
-
readonly value: string;
|
|
75
|
-
readonly label: "Most Viewed";
|
|
76
70
|
}];
|
|
77
71
|
extraFacetKeys: readonly string[];
|
|
78
72
|
};
|
|
@@ -56,9 +56,6 @@ export declare const config: {
|
|
|
56
56
|
}, {
|
|
57
57
|
readonly value: string;
|
|
58
58
|
readonly label: "Recently Updated";
|
|
59
|
-
}, {
|
|
60
|
-
readonly value: string;
|
|
61
|
-
readonly label: "Most Viewed";
|
|
62
59
|
}];
|
|
63
60
|
publicSortOptions: readonly [{
|
|
64
61
|
readonly value: string;
|
|
@@ -78,9 +75,6 @@ export declare const config: {
|
|
|
78
75
|
}, {
|
|
79
76
|
readonly value: string;
|
|
80
77
|
readonly label: "Name: Z–A";
|
|
81
|
-
}, {
|
|
82
|
-
readonly value: string;
|
|
83
|
-
readonly label: "Most Viewed";
|
|
84
78
|
}];
|
|
85
79
|
extraFacetKeys: readonly string[];
|
|
86
80
|
};
|
|
@@ -48,9 +48,6 @@ export declare const config: {
|
|
|
48
48
|
}, {
|
|
49
49
|
readonly value: string;
|
|
50
50
|
readonly label: "Recently Updated";
|
|
51
|
-
}, {
|
|
52
|
-
readonly value: string;
|
|
53
|
-
readonly label: "Most Viewed";
|
|
54
51
|
}];
|
|
55
52
|
publicSortOptions: readonly [{
|
|
56
53
|
readonly value: string;
|
|
@@ -70,9 +67,6 @@ export declare const config: {
|
|
|
70
67
|
}, {
|
|
71
68
|
readonly value: string;
|
|
72
69
|
readonly label: "Name: Z–A";
|
|
73
|
-
}, {
|
|
74
|
-
readonly value: string;
|
|
75
|
-
readonly label: "Most Viewed";
|
|
76
70
|
}];
|
|
77
71
|
extraFacetKeys: readonly string[];
|
|
78
72
|
};
|
|
@@ -48,9 +48,6 @@ export declare const config: {
|
|
|
48
48
|
}, {
|
|
49
49
|
readonly value: string;
|
|
50
50
|
readonly label: "Recently Updated";
|
|
51
|
-
}, {
|
|
52
|
-
readonly value: string;
|
|
53
|
-
readonly label: "Most Viewed";
|
|
54
51
|
}];
|
|
55
52
|
publicSortOptions: readonly [{
|
|
56
53
|
readonly value: string;
|
|
@@ -70,9 +67,6 @@ export declare const config: {
|
|
|
70
67
|
}, {
|
|
71
68
|
readonly value: string;
|
|
72
69
|
readonly label: "Name: Z–A";
|
|
73
|
-
}, {
|
|
74
|
-
readonly value: string;
|
|
75
|
-
readonly label: "Most Viewed";
|
|
76
70
|
}];
|
|
77
71
|
extraFacetKeys: readonly string[];
|
|
78
72
|
};
|
|
@@ -48,9 +48,6 @@ export declare const config: {
|
|
|
48
48
|
}, {
|
|
49
49
|
readonly value: string;
|
|
50
50
|
readonly label: "Recently Updated";
|
|
51
|
-
}, {
|
|
52
|
-
readonly value: string;
|
|
53
|
-
readonly label: "Most Viewed";
|
|
54
51
|
}];
|
|
55
52
|
publicSortOptions: readonly [{
|
|
56
53
|
readonly value: string;
|
|
@@ -70,9 +67,6 @@ export declare const config: {
|
|
|
70
67
|
}, {
|
|
71
68
|
readonly value: string;
|
|
72
69
|
readonly label: "Name: Z–A";
|
|
73
|
-
}, {
|
|
74
|
-
readonly value: string;
|
|
75
|
-
readonly label: "Most Viewed";
|
|
76
70
|
}];
|
|
77
71
|
extraFacetKeys: readonly string[];
|
|
78
72
|
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `{{placeholder}}` interpolation — the ONE implementation.
|
|
3
|
+
*
|
|
4
|
+
* Promoted out of `features/faq/schemas/firestore.ts`, where it had served 63
|
|
5
|
+
* FAQs since the feature shipped. Category description templates need exactly
|
|
6
|
+
* the same thing, and writing a second regex for it is Root Cause #75's shape:
|
|
7
|
+
* one of the two eventually learns about a case the other does not, and the
|
|
8
|
+
* copy a caller reaches is the one they happened to import.
|
|
9
|
+
*
|
|
10
|
+
* `features/faq/schemas/firestore.ts` re-exports these under its own names, so
|
|
11
|
+
* nothing in the FAQ feature changed and no FAQ call site moved.
|
|
12
|
+
*
|
|
13
|
+
* 🛑 NOT a template ENGINE. There are no conditionals, loops, filters or
|
|
14
|
+
* nesting, and none should be added here — a category body is author-facing
|
|
15
|
+
* copy with a handful of named slots, and a real engine would mean user input
|
|
16
|
+
* being evaluated. `\w+` is the whole grammar, which is also why it is safe to
|
|
17
|
+
* run over HTML.
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Every placeholder name in `text`, in source order, INCLUDING duplicates.
|
|
21
|
+
*
|
|
22
|
+
* Duplicates are kept deliberately: a caller counting unfilled slots wants to
|
|
23
|
+
* know a body says `{{year}}` three times, and `usedPlaceholders` below is the
|
|
24
|
+
* de-duplicated form for callers that want the set instead.
|
|
25
|
+
*/
|
|
26
|
+
export declare function extractPlaceholders(text: string): string[];
|
|
27
|
+
/** The distinct placeholder names in `text`, in first-appearance order. */
|
|
28
|
+
export declare function usedPlaceholders(text: string): string[];
|
|
29
|
+
/**
|
|
30
|
+
* What a slot may resolve to.
|
|
31
|
+
*
|
|
32
|
+
* 🛑 Declared once and shared with `missingPlaceholders`, which only tests key
|
|
33
|
+
* PRESENCE and so does not care about the value type at all. It was
|
|
34
|
+
* `Record<string, unknown>` for exactly that reason, and
|
|
35
|
+
* `audit-unknown-leakage` was right to reject it: `unknown` at a boundary is
|
|
36
|
+
* how a caller ends up casting, and a cast is where this codebase's worst
|
|
37
|
+
* defects live. Sharing the real type costs nothing and means the two
|
|
38
|
+
* functions cannot disagree about what a value is.
|
|
39
|
+
*/
|
|
40
|
+
export type PlaceholderValues = Readonly<Record<string, string | number | null | undefined>>;
|
|
41
|
+
export interface InterpolateResult {
|
|
42
|
+
/** The text with every slot replaced. */
|
|
43
|
+
text: string;
|
|
44
|
+
/** Slot names that had no value — the caller reports these to the author. */
|
|
45
|
+
unresolved: string[];
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Replace every `{{slot}}` with its value.
|
|
49
|
+
*
|
|
50
|
+
* 🛑 An unresolved slot becomes the EMPTY STRING, never the literal
|
|
51
|
+
* `{{series}}`, and never a placeholder-ish stand-in like `[series]`. A
|
|
52
|
+
* literal brace pair reaching a published product description is the single
|
|
53
|
+
* most visible way this feature can fail, and it is what the `unresolved` list
|
|
54
|
+
* exists to prevent: the caller surfaces "2 of 9 slots could not be filled:
|
|
55
|
+
* {{year}}, {{type}}" rather than silently shipping the braces.
|
|
56
|
+
*
|
|
57
|
+
* A value that is present but empty/whitespace counts as UNRESOLVED. `{{brand}}`
|
|
58
|
+
* resolving to `""` because the brand lookup returned nothing is exactly the
|
|
59
|
+
* case an author needs told about, and treating it as resolved would hide it.
|
|
60
|
+
*/
|
|
61
|
+
export declare function interpolate(text: string, values: PlaceholderValues): InterpolateResult;
|
|
62
|
+
/**
|
|
63
|
+
* Which of `text`'s slots have no value in `available`.
|
|
64
|
+
*
|
|
65
|
+
* Separate from `interpolate` because validation runs at AUTHORING time, when
|
|
66
|
+
* there is a schema to check against but no real product to fill from — the
|
|
67
|
+
* admin editor wants to know a template names `{{sereis}}` before anyone
|
|
68
|
+
* publishes from it.
|
|
69
|
+
*/
|
|
70
|
+
export declare function missingPlaceholders(text: string, available: PlaceholderValues): string[];
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `{{placeholder}}` interpolation — the ONE implementation.
|
|
3
|
+
*
|
|
4
|
+
* Promoted out of `features/faq/schemas/firestore.ts`, where it had served 63
|
|
5
|
+
* FAQs since the feature shipped. Category description templates need exactly
|
|
6
|
+
* the same thing, and writing a second regex for it is Root Cause #75's shape:
|
|
7
|
+
* one of the two eventually learns about a case the other does not, and the
|
|
8
|
+
* copy a caller reaches is the one they happened to import.
|
|
9
|
+
*
|
|
10
|
+
* `features/faq/schemas/firestore.ts` re-exports these under its own names, so
|
|
11
|
+
* nothing in the FAQ feature changed and no FAQ call site moved.
|
|
12
|
+
*
|
|
13
|
+
* 🛑 NOT a template ENGINE. There are no conditionals, loops, filters or
|
|
14
|
+
* nesting, and none should be added here — a category body is author-facing
|
|
15
|
+
* copy with a handful of named slots, and a real engine would mean user input
|
|
16
|
+
* being evaluated. `\w+` is the whole grammar, which is also why it is safe to
|
|
17
|
+
* run over HTML.
|
|
18
|
+
*/
|
|
19
|
+
/** The slot syntax. One capture group: the bare name, no braces. */
|
|
20
|
+
const PLACEHOLDER_RE = /\{\{(\w+)\}\}/g;
|
|
21
|
+
/**
|
|
22
|
+
* Every placeholder name in `text`, in source order, INCLUDING duplicates.
|
|
23
|
+
*
|
|
24
|
+
* Duplicates are kept deliberately: a caller counting unfilled slots wants to
|
|
25
|
+
* know a body says `{{year}}` three times, and `usedPlaceholders` below is the
|
|
26
|
+
* de-duplicated form for callers that want the set instead.
|
|
27
|
+
*/
|
|
28
|
+
export function extractPlaceholders(text) {
|
|
29
|
+
return Array.from(text.matchAll(PLACEHOLDER_RE), (m) => m[1]);
|
|
30
|
+
}
|
|
31
|
+
/** The distinct placeholder names in `text`, in first-appearance order. */
|
|
32
|
+
export function usedPlaceholders(text) {
|
|
33
|
+
return Array.from(new Set(extractPlaceholders(text)));
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Replace every `{{slot}}` with its value.
|
|
37
|
+
*
|
|
38
|
+
* 🛑 An unresolved slot becomes the EMPTY STRING, never the literal
|
|
39
|
+
* `{{series}}`, and never a placeholder-ish stand-in like `[series]`. A
|
|
40
|
+
* literal brace pair reaching a published product description is the single
|
|
41
|
+
* most visible way this feature can fail, and it is what the `unresolved` list
|
|
42
|
+
* exists to prevent: the caller surfaces "2 of 9 slots could not be filled:
|
|
43
|
+
* {{year}}, {{type}}" rather than silently shipping the braces.
|
|
44
|
+
*
|
|
45
|
+
* A value that is present but empty/whitespace counts as UNRESOLVED. `{{brand}}`
|
|
46
|
+
* resolving to `""` because the brand lookup returned nothing is exactly the
|
|
47
|
+
* case an author needs told about, and treating it as resolved would hide it.
|
|
48
|
+
*/
|
|
49
|
+
export function interpolate(text, values) {
|
|
50
|
+
const unresolved = [];
|
|
51
|
+
const out = text.replace(PLACEHOLDER_RE, (_match, name) => {
|
|
52
|
+
const raw = values[name];
|
|
53
|
+
const value = raw == null ? "" : String(raw);
|
|
54
|
+
if (value.trim() === "") {
|
|
55
|
+
if (!unresolved.includes(name))
|
|
56
|
+
unresolved.push(name);
|
|
57
|
+
return "";
|
|
58
|
+
}
|
|
59
|
+
return value;
|
|
60
|
+
});
|
|
61
|
+
return { text: out, unresolved };
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Which of `text`'s slots have no value in `available`.
|
|
65
|
+
*
|
|
66
|
+
* Separate from `interpolate` because validation runs at AUTHORING time, when
|
|
67
|
+
* there is a schema to check against but no real product to fill from — the
|
|
68
|
+
* admin editor wants to know a template names `{{sereis}}` before anyone
|
|
69
|
+
* publishes from it.
|
|
70
|
+
*/
|
|
71
|
+
export function missingPlaceholders(text, available) {
|
|
72
|
+
return usedPlaceholders(text).filter((name) => !(name in available));
|
|
73
|
+
}
|
package/dist/client.d.ts
CHANGED
|
@@ -488,6 +488,8 @@ export type { CodHandlingFeeRates, WhatsAppNotifyFeeRates, GiftWrapFeeRates, Shi
|
|
|
488
488
|
export { FAQPageContent } from "./features/faq/index";
|
|
489
489
|
export type { FAQCategory, FAQCategoryItem, FAQSortOption } from "./features/faq/index";
|
|
490
490
|
export { CategoryInlineSelect } from "./features/seller/components/CategoryInlineSelect";
|
|
491
|
+
export { CategoryTemplatePicker, variantForCondition } from "./features/categories/components/CategoryTemplatePicker";
|
|
492
|
+
export type { CategoryTemplatePickerProps, CategoryTemplateApply } from "./features/categories/components/CategoryTemplatePicker";
|
|
491
493
|
export { BrandInlineSelect } from "./features/seller/components/BrandInlineSelect";
|
|
492
494
|
export { API_ENDPOINTS } from "./constants/index";
|
|
493
495
|
export { SELLER_LISTING_TABS, type SellerListingTabId, } from "./features/products/constants/listing-tabs";
|
package/dist/client.js
CHANGED
|
@@ -486,6 +486,7 @@ export { checkEmiEligibility, computeEmiSchedule, computeBuyerEmiQuote, } from "
|
|
|
486
486
|
export { computeCodHandlingFee } from "./_internal/shared/fees/calculator"; // reexport-from-internal-ok: pure fee-calc utility consumed directly by public checkout UI (CheckoutRouteClient.tsx), same category as the sibling computeEmiSchedule/checkEmiEligibility re-export two lines above
|
|
487
487
|
export { FAQPageContent } from "./features/faq/index";
|
|
488
488
|
export { CategoryInlineSelect } from "./features/seller/components/CategoryInlineSelect";
|
|
489
|
+
export { CategoryTemplatePicker, variantForCondition } from "./features/categories/components/CategoryTemplatePicker";
|
|
489
490
|
export { BrandInlineSelect } from "./features/seller/components/BrandInlineSelect";
|
|
490
491
|
export { API_ENDPOINTS } from "./constants/index";
|
|
491
492
|
// [CLIENT-SAFE] Pure, zero-import constant files — dashboard filter-tab
|
|
@@ -96,6 +96,9 @@ export declare const ADMIN_ENDPOINTS: {
|
|
|
96
96
|
readonly PAYMENTS_SETTINGS: "/api/admin/payments/settings";
|
|
97
97
|
readonly PRODUCTS: "/api/admin/products";
|
|
98
98
|
readonly PRODUCT_BY_ID: (id: string) => string;
|
|
99
|
+
/** One request for up to 50 flag writes — replaces a client-side `forEach`
|
|
100
|
+
* of single-row PATCHes that fired one invocation per selected row. */
|
|
101
|
+
readonly PRODUCTS_BULK: "/api/admin/products/bulk";
|
|
99
102
|
readonly ORDERS: "/api/admin/orders";
|
|
100
103
|
readonly ORDER_BY_ID: (id: string) => string;
|
|
101
104
|
readonly ORDER_REFUND: (id: string) => string;
|
|
@@ -198,6 +201,8 @@ export declare const ADMIN_ENDPOINTS: {
|
|
|
198
201
|
readonly SUBLISTING_CATEGORY_BY_ID: (id: string) => string;
|
|
199
202
|
readonly PRODUCT_FEATURES: "/api/admin/features";
|
|
200
203
|
readonly PRODUCT_FEATURE_BY_ID: (id: string) => string;
|
|
204
|
+
readonly TAX_CODES: "/api/admin/tax-codes";
|
|
205
|
+
readonly TAX_CODE_BY_ID: (id: string) => string;
|
|
201
206
|
readonly TEAM: "/api/admin/team";
|
|
202
207
|
readonly TEAM_MEMBER: (uid: string) => string;
|
|
203
208
|
readonly USER_HARD_BAN: (uid: string) => string;
|
|
@@ -259,6 +264,15 @@ export declare const CATEGORY_ENDPOINTS: {
|
|
|
259
264
|
readonly ROOT: (pageSize?: number) => string;
|
|
260
265
|
/** @param qs — pre-built querystring (no leading `?`) for structured filters */
|
|
261
266
|
readonly FILTERED: (qs: string) => string;
|
|
267
|
+
/**
|
|
268
|
+
* The inherited description template plus the category's public product
|
|
269
|
+
* defaults, for the seller form's template picker.
|
|
270
|
+
*
|
|
271
|
+
* `variant` narrows which body is wanted (`pre_owned`, `new_in_box`, …) and
|
|
272
|
+
* is part of the cache key — the response is edge-cached for an hour, so a
|
|
273
|
+
* category change in the form costs zero function invocations on a hit.
|
|
274
|
+
*/
|
|
275
|
+
readonly DESCRIPTION_TEMPLATE: (id: string, variant?: string) => string;
|
|
262
276
|
};
|
|
263
277
|
export declare const CHECKOUT_ENDPOINTS: {
|
|
264
278
|
readonly PREFLIGHT: "/api/checkout/preflight";
|
|
@@ -563,6 +577,9 @@ export declare const API_ENDPOINTS: {
|
|
|
563
577
|
readonly PAYMENTS_SETTINGS: "/api/admin/payments/settings";
|
|
564
578
|
readonly PRODUCTS: "/api/admin/products";
|
|
565
579
|
readonly PRODUCT_BY_ID: (id: string) => string;
|
|
580
|
+
/** One request for up to 50 flag writes — replaces a client-side `forEach`
|
|
581
|
+
* of single-row PATCHes that fired one invocation per selected row. */
|
|
582
|
+
readonly PRODUCTS_BULK: "/api/admin/products/bulk";
|
|
566
583
|
readonly ORDERS: "/api/admin/orders";
|
|
567
584
|
readonly ORDER_BY_ID: (id: string) => string;
|
|
568
585
|
readonly ORDER_REFUND: (id: string) => string;
|
|
@@ -665,6 +682,8 @@ export declare const API_ENDPOINTS: {
|
|
|
665
682
|
readonly SUBLISTING_CATEGORY_BY_ID: (id: string) => string;
|
|
666
683
|
readonly PRODUCT_FEATURES: "/api/admin/features";
|
|
667
684
|
readonly PRODUCT_FEATURE_BY_ID: (id: string) => string;
|
|
685
|
+
readonly TAX_CODES: "/api/admin/tax-codes";
|
|
686
|
+
readonly TAX_CODE_BY_ID: (id: string) => string;
|
|
668
687
|
readonly TEAM: "/api/admin/team";
|
|
669
688
|
readonly TEAM_MEMBER: (uid: string) => string;
|
|
670
689
|
readonly USER_HARD_BAN: (uid: string) => string;
|
|
@@ -726,6 +745,15 @@ export declare const API_ENDPOINTS: {
|
|
|
726
745
|
readonly ROOT: (pageSize?: number) => string;
|
|
727
746
|
/** @param qs — pre-built querystring (no leading `?`) for structured filters */
|
|
728
747
|
readonly FILTERED: (qs: string) => string;
|
|
748
|
+
/**
|
|
749
|
+
* The inherited description template plus the category's public product
|
|
750
|
+
* defaults, for the seller form's template picker.
|
|
751
|
+
*
|
|
752
|
+
* `variant` narrows which body is wanted (`pre_owned`, `new_in_box`, …) and
|
|
753
|
+
* is part of the cache key — the response is edge-cached for an hour, so a
|
|
754
|
+
* category change in the form costs zero function invocations on a hit.
|
|
755
|
+
*/
|
|
756
|
+
readonly DESCRIPTION_TEMPLATE: (id: string, variant?: string) => string;
|
|
729
757
|
};
|
|
730
758
|
readonly BEFORE_AFTER: {
|
|
731
759
|
readonly LIST: "/api/before-after";
|
|
@@ -1032,6 +1060,9 @@ export declare const API_ROUTES: {
|
|
|
1032
1060
|
readonly PAYMENTS_SETTINGS: "/api/admin/payments/settings";
|
|
1033
1061
|
readonly PRODUCTS: "/api/admin/products";
|
|
1034
1062
|
readonly PRODUCT_BY_ID: (id: string) => string;
|
|
1063
|
+
/** One request for up to 50 flag writes — replaces a client-side `forEach`
|
|
1064
|
+
* of single-row PATCHes that fired one invocation per selected row. */
|
|
1065
|
+
readonly PRODUCTS_BULK: "/api/admin/products/bulk";
|
|
1035
1066
|
readonly ORDERS: "/api/admin/orders";
|
|
1036
1067
|
readonly ORDER_BY_ID: (id: string) => string;
|
|
1037
1068
|
readonly ORDER_REFUND: (id: string) => string;
|
|
@@ -1134,6 +1165,8 @@ export declare const API_ROUTES: {
|
|
|
1134
1165
|
readonly SUBLISTING_CATEGORY_BY_ID: (id: string) => string;
|
|
1135
1166
|
readonly PRODUCT_FEATURES: "/api/admin/features";
|
|
1136
1167
|
readonly PRODUCT_FEATURE_BY_ID: (id: string) => string;
|
|
1168
|
+
readonly TAX_CODES: "/api/admin/tax-codes";
|
|
1169
|
+
readonly TAX_CODE_BY_ID: (id: string) => string;
|
|
1137
1170
|
readonly TEAM: "/api/admin/team";
|
|
1138
1171
|
readonly TEAM_MEMBER: (uid: string) => string;
|
|
1139
1172
|
readonly USER_HARD_BAN: (uid: string) => string;
|
|
@@ -1195,6 +1228,15 @@ export declare const API_ROUTES: {
|
|
|
1195
1228
|
readonly ROOT: (pageSize?: number) => string;
|
|
1196
1229
|
/** @param qs — pre-built querystring (no leading `?`) for structured filters */
|
|
1197
1230
|
readonly FILTERED: (qs: string) => string;
|
|
1231
|
+
/**
|
|
1232
|
+
* The inherited description template plus the category's public product
|
|
1233
|
+
* defaults, for the seller form's template picker.
|
|
1234
|
+
*
|
|
1235
|
+
* `variant` narrows which body is wanted (`pre_owned`, `new_in_box`, …) and
|
|
1236
|
+
* is part of the cache key — the response is edge-cached for an hour, so a
|
|
1237
|
+
* category change in the form costs zero function invocations on a hit.
|
|
1238
|
+
*/
|
|
1239
|
+
readonly DESCRIPTION_TEMPLATE: (id: string, variant?: string) => string;
|
|
1198
1240
|
};
|
|
1199
1241
|
readonly BEFORE_AFTER: {
|
|
1200
1242
|
readonly LIST: "/api/before-after";
|
|
@@ -127,6 +127,9 @@ export const ADMIN_ENDPOINTS = {
|
|
|
127
127
|
PAYMENTS_SETTINGS: "/api/admin/payments/settings",
|
|
128
128
|
PRODUCTS: "/api/admin/products",
|
|
129
129
|
PRODUCT_BY_ID: (id) => `/api/admin/products/${id}`,
|
|
130
|
+
/** One request for up to 50 flag writes — replaces a client-side `forEach`
|
|
131
|
+
* of single-row PATCHes that fired one invocation per selected row. */
|
|
132
|
+
PRODUCTS_BULK: "/api/admin/products/bulk",
|
|
130
133
|
ORDERS: "/api/admin/orders",
|
|
131
134
|
ORDER_BY_ID: (id) => `/api/admin/orders/${id}`,
|
|
132
135
|
ORDER_REFUND: (id) => `/api/admin/orders/${id}/refund`,
|
|
@@ -230,6 +233,8 @@ export const ADMIN_ENDPOINTS = {
|
|
|
230
233
|
SUBLISTING_CATEGORY_BY_ID: (id) => `/api/admin/sublisting-categories/${id}`,
|
|
231
234
|
PRODUCT_FEATURES: "/api/admin/features",
|
|
232
235
|
PRODUCT_FEATURE_BY_ID: (id) => `/api/admin/features/${id}`,
|
|
236
|
+
TAX_CODES: "/api/admin/tax-codes",
|
|
237
|
+
TAX_CODE_BY_ID: (id) => `/api/admin/tax-codes/${id}`,
|
|
233
238
|
TEAM: "/api/admin/team",
|
|
234
239
|
TEAM_MEMBER: (uid) => `/api/admin/team/${uid}`,
|
|
235
240
|
USER_HARD_BAN: (uid) => `/api/admin/users/${uid}/hard-ban`,
|
|
@@ -303,6 +308,15 @@ export const CATEGORY_ENDPOINTS = {
|
|
|
303
308
|
ROOT: (pageSize = 20) => `/api/categories?tier=0&pageSize=${pageSize}`,
|
|
304
309
|
/** @param qs — pre-built querystring (no leading `?`) for structured filters */
|
|
305
310
|
FILTERED: (qs) => `/api/categories?${qs}`,
|
|
311
|
+
/**
|
|
312
|
+
* The inherited description template plus the category's public product
|
|
313
|
+
* defaults, for the seller form's template picker.
|
|
314
|
+
*
|
|
315
|
+
* `variant` narrows which body is wanted (`pre_owned`, `new_in_box`, …) and
|
|
316
|
+
* is part of the cache key — the response is edge-cached for an hour, so a
|
|
317
|
+
* category change in the form costs zero function invocations on a hit.
|
|
318
|
+
*/
|
|
319
|
+
DESCRIPTION_TEMPLATE: (id, variant) => `/api/categories/${id}/description-template${variant ? `?variant=${variant}` : ""}`,
|
|
306
320
|
};
|
|
307
321
|
// ---------------------------------------------------------------------------
|
|
308
322
|
// Checkout
|
|
@@ -27,7 +27,7 @@ export declare function adminUpdateUser(adminId: string, uid: string, input: Use
|
|
|
27
27
|
* removed. Orders, reviews, addresses, payouts, etc. are left untouched —
|
|
28
28
|
* they're business/audit records that reference this uid and deleting
|
|
29
29
|
* them would corrupt other parties' (sellers', buyers') own history, the
|
|
30
|
-
* same reasoning
|
|
30
|
+
* same reasoning testDataCleanup already documents for why it leaves
|
|
31
31
|
* orders/reviews/wishlists/history alone when a test product disappears.
|
|
32
32
|
*/
|
|
33
33
|
export declare function adminDeleteUser(adminId: string, uid: string): Promise<void>;
|
|
@@ -156,7 +156,7 @@ export async function adminUpdateUser(adminId, uid, input) {
|
|
|
156
156
|
* removed. Orders, reviews, addresses, payouts, etc. are left untouched —
|
|
157
157
|
* they're business/audit records that reference this uid and deleting
|
|
158
158
|
* them would corrupt other parties' (sellers', buyers') own history, the
|
|
159
|
-
* same reasoning
|
|
159
|
+
* same reasoning testDataCleanup already documents for why it leaves
|
|
160
160
|
* orders/reviews/wishlists/history alone when a test product disappears.
|
|
161
161
|
*/
|
|
162
162
|
export async function adminDeleteUser(adminId, uid) {
|