rerobe-js-orm 4.8.8 → 4.9.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/lib/constants/marketplace-constants.d.ts +52 -0
- package/lib/constants/marketplace-constants.js +82 -0
- package/lib/constants/product-constants.d.ts +6 -0
- package/lib/constants/product-constants.js +43 -1
- package/lib/constants/tax-constants.d.ts +19 -0
- package/lib/constants/tax-constants.js +70 -0
- package/lib/factories/Product/RetailProductFactory.d.ts +102 -0
- package/lib/factories/Product/RetailProductFactory.js +260 -0
- package/lib/form-states/Product/ProductFormState.d.ts +9 -0
- package/lib/form-states/Product/ProductFormState.js +46 -0
- package/lib/helpers/MarketplaceProductHelpers.d.ts +181 -0
- package/lib/helpers/MarketplaceProductHelpers.js +555 -0
- package/lib/helpers/OrderHelpers.d.ts +5 -2
- package/lib/helpers/OrderHelpers.js +18 -4
- package/lib/helpers/PricingHelpers.d.ts +29 -0
- package/lib/helpers/PricingHelpers.js +215 -0
- package/lib/helpers/ProductInventoryHelpers.d.ts +31 -0
- package/lib/helpers/ProductInventoryHelpers.js +66 -0
- package/lib/helpers/ProductSkuHelpers.d.ts +13 -0
- package/lib/helpers/ProductSkuHelpers.js +70 -0
- package/lib/helpers/TaxHelpers.d.ts +15 -0
- package/lib/helpers/TaxHelpers.js +76 -0
- package/lib/helpers/marketplace/CommissionPolicy.d.ts +20 -0
- package/lib/helpers/marketplace/CommissionPolicy.js +9 -0
- package/lib/helpers/marketplace/CommissionPolicyRegistry.d.ts +4 -0
- package/lib/helpers/marketplace/CommissionPolicyRegistry.js +21 -0
- package/lib/helpers/marketplace/EvenPerSellerStripeFeePolicy.d.ts +5 -0
- package/lib/helpers/marketplace/EvenPerSellerStripeFeePolicy.js +46 -0
- package/lib/helpers/marketplace/FeeAllocationPolicy.d.ts +10 -0
- package/lib/helpers/marketplace/FeeAllocationPolicy.js +36 -0
- package/lib/helpers/marketplace/FeeAllocationPolicyRegistry.d.ts +6 -0
- package/lib/helpers/marketplace/FeeAllocationPolicyRegistry.js +26 -0
- package/lib/helpers/marketplace/InventoryPolicy.d.ts +18 -0
- package/lib/helpers/marketplace/InventoryPolicy.js +7 -0
- package/lib/helpers/marketplace/InventoryPolicyRegistry.d.ts +4 -0
- package/lib/helpers/marketplace/InventoryPolicyRegistry.js +29 -0
- package/lib/helpers/marketplace/LineNetCommissionPolicy.d.ts +5 -0
- package/lib/helpers/marketplace/LineNetCommissionPolicy.js +25 -0
- package/lib/helpers/marketplace/MarketplaceErrors.d.ts +6 -0
- package/lib/helpers/marketplace/MarketplaceErrors.js +21 -0
- package/lib/helpers/marketplace/MarketplaceLedgerHelpers.d.ts +40 -0
- package/lib/helpers/marketplace/MarketplaceLedgerHelpers.js +120 -0
- package/lib/helpers/marketplace/MarketplaceLegacyAdapters.d.ts +53 -0
- package/lib/helpers/marketplace/MarketplaceLegacyAdapters.js +99 -0
- package/lib/helpers/marketplace/MarketplaceLineDisplayHelpers.d.ts +40 -0
- package/lib/helpers/marketplace/MarketplaceLineDisplayHelpers.js +125 -0
- package/lib/helpers/marketplace/MarketplaceOrderHelpers.d.ts +15 -0
- package/lib/helpers/marketplace/MarketplaceOrderHelpers.js +77 -0
- package/lib/helpers/marketplace/MultivariantLocationInventoryPolicy.d.ts +9 -0
- package/lib/helpers/marketplace/MultivariantLocationInventoryPolicy.js +60 -0
- package/lib/helpers/marketplace/OneOfAKindInventoryPolicy.d.ts +9 -0
- package/lib/helpers/marketplace/OneOfAKindInventoryPolicy.js +55 -0
- package/lib/helpers/marketplace/OriginalCommissionShareCommissionPolicy.d.ts +5 -0
- package/lib/helpers/marketplace/OriginalCommissionShareCommissionPolicy.js +26 -0
- package/lib/helpers/marketplace/ProportionalToLineNetPolicy.d.ts +5 -0
- package/lib/helpers/marketplace/ProportionalToLineNetPolicy.js +35 -0
- package/lib/helpers/marketplace/UntrackedStockInventoryPolicy.d.ts +7 -0
- package/lib/helpers/marketplace/UntrackedStockInventoryPolicy.js +23 -0
- package/lib/index.d.ts +18 -1
- package/lib/index.js +56 -1
- package/lib/models/Product.d.ts +16 -0
- package/lib/models/Product.js +140 -0
- package/lib/types/pricing-types.d.ts +85 -0
- package/lib/types/pricing-types.js +5 -0
- package/lib/types/rerobe-order-types.d.ts +86 -0
- package/lib/types/rerobe-product-types.d.ts +19 -0
- package/package.json +1 -1
|
@@ -0,0 +1,555 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MarketplaceOwnershipError = exports.MarketplaceCommissionRateError = void 0;
|
|
4
|
+
const ReRobeProductHelpers_1 = require("./ReRobeProductHelpers");
|
|
5
|
+
const marketplace_constants_1 = require("../constants/marketplace-constants");
|
|
6
|
+
const CommissionPolicyRegistry = require("./marketplace/CommissionPolicyRegistry");
|
|
7
|
+
const FeeAllocationPolicyRegistry = require("./marketplace/FeeAllocationPolicyRegistry");
|
|
8
|
+
const InventoryPolicyRegistry = require("./marketplace/InventoryPolicyRegistry");
|
|
9
|
+
var MarketplaceErrors_1 = require("./marketplace/MarketplaceErrors");
|
|
10
|
+
Object.defineProperty(exports, "MarketplaceCommissionRateError", { enumerable: true, get: function () { return MarketplaceErrors_1.MarketplaceCommissionRateError; } });
|
|
11
|
+
Object.defineProperty(exports, "MarketplaceOwnershipError", { enumerable: true, get: function () { return MarketplaceErrors_1.MarketplaceOwnershipError; } });
|
|
12
|
+
const MarketplaceErrors_2 = require("./marketplace/MarketplaceErrors");
|
|
13
|
+
const roundMoney = (value) => Number(Number(value || 0).toFixed(2));
|
|
14
|
+
const normalizeVariantOptionsInput = (options) => {
|
|
15
|
+
if (!options)
|
|
16
|
+
return undefined;
|
|
17
|
+
if (Array.isArray(options)) {
|
|
18
|
+
const normalized = options.reduce((acc, option) => {
|
|
19
|
+
const key = (option === null || option === void 0 ? void 0 : option.name) || (option === null || option === void 0 ? void 0 : option.key) || (option === null || option === void 0 ? void 0 : option.label) || '';
|
|
20
|
+
const value = option === null || option === void 0 ? void 0 : option.value;
|
|
21
|
+
if (key && value !== undefined && value !== null && String(value).trim()) {
|
|
22
|
+
acc[String(key)] = String(value);
|
|
23
|
+
}
|
|
24
|
+
return acc;
|
|
25
|
+
}, {});
|
|
26
|
+
return Object.keys(normalized).length ? normalized : undefined;
|
|
27
|
+
}
|
|
28
|
+
if (typeof options === 'object')
|
|
29
|
+
return options;
|
|
30
|
+
return undefined;
|
|
31
|
+
};
|
|
32
|
+
// Pulls a `VariantSelectionInput` out of an order line item, supporting the
|
|
33
|
+
// shapes the backend currently produces:
|
|
34
|
+
// - `lineItem.variant.id` (canonical ReRobe lines)
|
|
35
|
+
// - `lineItem.variantId` (flattened shape some callers emit)
|
|
36
|
+
// - `lineItem.variant.options` (options-map lines used by the form-state)
|
|
37
|
+
// - `lineItem.selectedOptions` (Shopify/storefront shape we ingest)
|
|
38
|
+
// Returns `undefined` when nothing variant-shaped is present so call-sites
|
|
39
|
+
// fall back to product-level pricing/snapshotting without surprises.
|
|
40
|
+
const deriveVariantSelectionFromLineItem = (lineItem) => {
|
|
41
|
+
if (!lineItem || typeof lineItem !== 'object')
|
|
42
|
+
return undefined;
|
|
43
|
+
const variantId = (lineItem.variant && lineItem.variant.id) ||
|
|
44
|
+
lineItem.variantId ||
|
|
45
|
+
(lineItem.variant && lineItem.variant.variantId) ||
|
|
46
|
+
'';
|
|
47
|
+
const options = (lineItem.variant && lineItem.variant.options) || lineItem.variantOptions || lineItem.selectedOptions || undefined;
|
|
48
|
+
const normalizedOptions = normalizeVariantOptionsInput(options);
|
|
49
|
+
if (!variantId && !normalizedOptions)
|
|
50
|
+
return undefined;
|
|
51
|
+
const selection = {};
|
|
52
|
+
if (variantId)
|
|
53
|
+
selection.variantId = String(variantId);
|
|
54
|
+
if (normalizedOptions)
|
|
55
|
+
selection.options = normalizedOptions;
|
|
56
|
+
return selection;
|
|
57
|
+
};
|
|
58
|
+
class MarketplaceProductHelpers {
|
|
59
|
+
static registerCommissionPolicy(policy) {
|
|
60
|
+
CommissionPolicyRegistry.register(policy);
|
|
61
|
+
}
|
|
62
|
+
static getCommissionPolicy(basis) {
|
|
63
|
+
return CommissionPolicyRegistry.get(basis);
|
|
64
|
+
}
|
|
65
|
+
static hasCommissionPolicy(basis) {
|
|
66
|
+
return CommissionPolicyRegistry.has(basis);
|
|
67
|
+
}
|
|
68
|
+
static emptyMarketplace() {
|
|
69
|
+
return {
|
|
70
|
+
visibleToMerchantIds: [],
|
|
71
|
+
listings: {},
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
static uniqueStrings(values = []) {
|
|
75
|
+
return Array.from(new Set((Array.isArray(values) ? values : [])
|
|
76
|
+
.filter((v) => v !== undefined && v !== null && String(v).trim())
|
|
77
|
+
.map((v) => String(v))));
|
|
78
|
+
}
|
|
79
|
+
static normalizeMarketplace(input) {
|
|
80
|
+
const visibleToMerchantIds = this.uniqueStrings((input === null || input === void 0 ? void 0 : input.visibleToMerchantIds) || []);
|
|
81
|
+
const rawListings = (input === null || input === void 0 ? void 0 : input.listings) && typeof input.listings === 'object' ? input.listings : {};
|
|
82
|
+
const listings = Object.keys(rawListings).reduce((acc, parentMarketplaceId) => {
|
|
83
|
+
const listing = rawListings[parentMarketplaceId] || {};
|
|
84
|
+
if (!parentMarketplaceId)
|
|
85
|
+
return acc;
|
|
86
|
+
acc[parentMarketplaceId] = {
|
|
87
|
+
relationshipId: String(listing.relationshipId || ''),
|
|
88
|
+
relationshipType: String(listing.relationshipType || ''),
|
|
89
|
+
status: String(listing.status || marketplace_constants_1.DEFAULT_MARKETPLACE_LISTING_STATUS),
|
|
90
|
+
listedAt: listing.listedAt === undefined || listing.listedAt === null ? null : Number(listing.listedAt),
|
|
91
|
+
updatedAt: listing.updatedAt === undefined || listing.updatedAt === null ? null : Number(listing.updatedAt),
|
|
92
|
+
};
|
|
93
|
+
return acc;
|
|
94
|
+
}, {});
|
|
95
|
+
return {
|
|
96
|
+
visibleToMerchantIds,
|
|
97
|
+
listings,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
static buildMarketplace({ productMerchantId = '', listings = [], }) {
|
|
101
|
+
const normalizedListings = listings.reduce((acc, listing) => {
|
|
102
|
+
if (!(listing === null || listing === void 0 ? void 0 : listing.parentMarketplaceId))
|
|
103
|
+
return acc;
|
|
104
|
+
acc[listing.parentMarketplaceId] = {
|
|
105
|
+
relationshipId: String(listing.relationshipId || ''),
|
|
106
|
+
relationshipType: String(listing.relationshipType || marketplace_constants_1.DEFAULT_MARKETPLACE_RELATIONSHIP_TYPE),
|
|
107
|
+
status: String(listing.status || marketplace_constants_1.DEFAULT_MARKETPLACE_LISTING_STATUS),
|
|
108
|
+
listedAt: listing.listedAt === undefined || listing.listedAt === null ? null : Number(listing.listedAt),
|
|
109
|
+
updatedAt: listing.updatedAt === undefined || listing.updatedAt === null ? null : Number(listing.updatedAt),
|
|
110
|
+
};
|
|
111
|
+
return acc;
|
|
112
|
+
}, {});
|
|
113
|
+
const activeParentIds = Object.keys(normalizedListings).filter((parentId) => { var _a; return ((_a = normalizedListings[parentId]) === null || _a === void 0 ? void 0 : _a.status) !== marketplace_constants_1.MARKETPLACE_LISTING_STATUSES.removed; });
|
|
114
|
+
return {
|
|
115
|
+
visibleToMerchantIds: this.uniqueStrings([productMerchantId, ...activeParentIds]),
|
|
116
|
+
listings: normalizedListings,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
static buildTypesenseFields(marketplace) {
|
|
120
|
+
const normalized = this.normalizeMarketplace(marketplace);
|
|
121
|
+
const marketplaceParentMerchantIds = Object.keys(normalized.listings).filter((parentId) => { var _a; return ((_a = normalized.listings[parentId]) === null || _a === void 0 ? void 0 : _a.status) !== marketplace_constants_1.MARKETPLACE_LISTING_STATUSES.removed; });
|
|
122
|
+
const marketplaceRelationshipIds = this.uniqueStrings(marketplaceParentMerchantIds.map((parentId) => { var _a; return (_a = normalized.listings[parentId]) === null || _a === void 0 ? void 0 : _a.relationshipId; }));
|
|
123
|
+
return {
|
|
124
|
+
marketplaceVisibleToMerchantIds: this.uniqueStrings(normalized.visibleToMerchantIds),
|
|
125
|
+
marketplaceParentMerchantIds,
|
|
126
|
+
marketplaceRelationshipIds,
|
|
127
|
+
isMarketplaceVisible: marketplaceParentMerchantIds.length > 0,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
static toRate(value) {
|
|
131
|
+
return Number(ReRobeProductHelpers_1.default.commissionFixer(value === undefined || value === null ? '0' : value));
|
|
132
|
+
}
|
|
133
|
+
static roundMoney(value) {
|
|
134
|
+
return roundMoney(value);
|
|
135
|
+
}
|
|
136
|
+
static lineNetFromProduct(product, quantity = 1, variant) {
|
|
137
|
+
const priceSource = (variant === null || variant === void 0 ? void 0 : variant.isOnSale) === 'yes' && variant.salePrice ? variant.salePrice : variant === null || variant === void 0 ? void 0 : variant.price;
|
|
138
|
+
const productPriceSource = product.isOnSale === 'yes' && Boolean(product.clearanceTimestamp) && product.salePrice
|
|
139
|
+
? product.salePrice
|
|
140
|
+
: product.price;
|
|
141
|
+
const unitPrice = Number(priceSource || productPriceSource || 0);
|
|
142
|
+
return roundMoney(unitPrice * (quantity || 1));
|
|
143
|
+
}
|
|
144
|
+
static selectVariant(product, selection = {}) {
|
|
145
|
+
const variants = Array.isArray(product.variantInventory) ? product.variantInventory : [];
|
|
146
|
+
if (!variants.length)
|
|
147
|
+
return null;
|
|
148
|
+
const variant = variants.find((v) => selection.variantId && (v === null || v === void 0 ? void 0 : v.id) === selection.variantId) ||
|
|
149
|
+
variants.find((v) => {
|
|
150
|
+
if (!selection.options)
|
|
151
|
+
return false;
|
|
152
|
+
const optionKeys = Object.keys(selection.options);
|
|
153
|
+
return optionKeys.every((key) => { var _a, _b; return ((_a = v === null || v === void 0 ? void 0 : v.options) === null || _a === void 0 ? void 0 : _a[key]) === ((_b = selection.options) === null || _b === void 0 ? void 0 : _b[key]); });
|
|
154
|
+
}) ||
|
|
155
|
+
null;
|
|
156
|
+
if (!variant)
|
|
157
|
+
return null;
|
|
158
|
+
return {
|
|
159
|
+
variantId: String(variant.id || ''),
|
|
160
|
+
sku: String(variant.sku || product.sku || ''),
|
|
161
|
+
options: variant.options || {},
|
|
162
|
+
price: String(variant.price || product.price || ''),
|
|
163
|
+
compareAtPrice: variant.compareAtPrice || null,
|
|
164
|
+
salePrice: variant.salePrice || null,
|
|
165
|
+
isOnSale: variant.isOnSale || null,
|
|
166
|
+
taxable: variant.taxable || (product.isTaxable === 'yes' ? 'yes' : product.isTaxable === 'no' ? 'no' : null),
|
|
167
|
+
taxCategory: String(product.taxCategory || 'STANDARD'),
|
|
168
|
+
locations: Array.isArray(variant.locations)
|
|
169
|
+
? variant.locations.map((loc) => (Object.assign(Object.assign({}, loc), { availableAmount: Number(loc === null || loc === void 0 ? void 0 : loc.availableAmount) || 0, incomingAmount: Number(loc === null || loc === void 0 ? void 0 : loc.incomingAmount) || 0 })))
|
|
170
|
+
: [],
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
static buildLineSnapshot({ product, parentMerchantId, managedMerchantId, relationshipId, sellerDisplayName, lineDisplayTitle, marketplaceCommissionRate, originalProductCommissionRate, marketplaceCommissionBasis = marketplace_constants_1.DEFAULT_MARKETPLACE_COMMISSION_BASIS, quantity = 1, currencyCode = '', discountAmount = 0, taxAmount = 0, stripeFeeAllocatedAmount = 0, ribbnFeeAllocatedAmount = 0, variantSelection = {}, }) {
|
|
174
|
+
const variant = this.selectVariant(product, variantSelection);
|
|
175
|
+
const q = Number(quantity) > 0 ? Number(quantity) : 1;
|
|
176
|
+
const lineNetAmount = this.lineNetFromProduct(product, q, variant || undefined);
|
|
177
|
+
const safeDiscount = roundMoney(Math.max(0, Number(discountAmount) || 0));
|
|
178
|
+
const taxableAmount = roundMoney(Math.max(0, lineNetAmount - safeDiscount));
|
|
179
|
+
const safeTax = roundMoney(Number(taxAmount) || 0);
|
|
180
|
+
const lineGrossAmount = roundMoney(taxableAmount + safeTax);
|
|
181
|
+
const originalRate = this.toRate(originalProductCommissionRate === undefined ? product.reRobeCommission || '0' : originalProductCommissionRate);
|
|
182
|
+
const marketplaceRate = this.toRate(marketplaceCommissionRate);
|
|
183
|
+
const safeStripeFee = roundMoney(Number(stripeFeeAllocatedAmount) || 0);
|
|
184
|
+
const safeRibbnFee = roundMoney(Number(ribbnFeeAllocatedAmount) || 0);
|
|
185
|
+
const policy = this.getCommissionPolicy(marketplaceCommissionBasis);
|
|
186
|
+
const policyResult = policy.calculate({ taxableAmount, originalRate, marketplaceRate }, { stripeFee: safeStripeFee, ribbnFee: safeRibbnFee });
|
|
187
|
+
const marketplaceProceedsAmount = roundMoney(policyResult.marketplaceCommissionAmount + safeStripeFee);
|
|
188
|
+
return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ isMarketplaceItem: true, parentMerchantId: String(parentMerchantId || ''), managedMerchantId: String(managedMerchantId || product.merchantId || product.vendorId || ''), relationshipId: String(relationshipId || ''), productId: String(product.documentId || '') }, ((variant === null || variant === void 0 ? void 0 : variant.variantId) ? { variantId: variant.variantId } : {})), (sellerDisplayName ? { sellerDisplayName: String(sellerDisplayName) } : {})), (lineDisplayTitle ? { lineDisplayTitle: String(lineDisplayTitle) } : {})), { originalProductCommissionRate: String(originalRate), marketplaceCommissionRate: String(marketplaceRate), marketplaceCommissionBasis: policy.basis, quantity: q, currencyCode, amounts: {
|
|
189
|
+
lineNetAmount,
|
|
190
|
+
discountAmount: safeDiscount,
|
|
191
|
+
taxableAmount,
|
|
192
|
+
taxAmount: safeTax,
|
|
193
|
+
lineGrossAmount,
|
|
194
|
+
originalProductCommissionAmount: policyResult.originalProductCommissionAmount,
|
|
195
|
+
marketplaceCommissionAmount: policyResult.marketplaceCommissionAmount,
|
|
196
|
+
stripeFeeAllocatedAmount: safeStripeFee,
|
|
197
|
+
ribbnFeeAllocatedAmount: safeRibbnFee,
|
|
198
|
+
sellerProceedsAmount: policyResult.sellerProceedsAmount,
|
|
199
|
+
managedMerchantProceedsAmount: policyResult.managedMerchantProceedsAmount,
|
|
200
|
+
marketplaceProceedsAmount,
|
|
201
|
+
} }), (variant ? { variant } : {}));
|
|
202
|
+
}
|
|
203
|
+
// Derives a `VariantSelectionInput` from an order line item. Exposed so
|
|
204
|
+
// backend/web callers that load a product separately can resolve variant
|
|
205
|
+
// identity from a line item without re-implementing the shape juggling
|
|
206
|
+
// (canonical `variant.id` vs. flattened `variantId` vs. options maps).
|
|
207
|
+
static deriveVariantSelectionFromLineItem(lineItem) {
|
|
208
|
+
return deriveVariantSelectionFromLineItem(lineItem);
|
|
209
|
+
}
|
|
210
|
+
static buildLineSnapshotFromListing({ product, parentMerchantId, relationship = null, lineItem = {}, quantity, currencyCode, marketplaceCommissionRate, originalProductCommissionRate, marketplaceCommissionBasis, discountAmount, taxAmount, stripeFeeAllocatedAmount = 0, ribbnFeeAllocatedAmount = 0, variantSelection, }) {
|
|
211
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
212
|
+
if (!product || !parentMerchantId)
|
|
213
|
+
return null;
|
|
214
|
+
const managedMerchantId = String(product.merchantId || product.vendorId || '');
|
|
215
|
+
if (!managedMerchantId || managedMerchantId === parentMerchantId)
|
|
216
|
+
return null;
|
|
217
|
+
const marketplace = this.normalizeMarketplace(product.marketplace);
|
|
218
|
+
const listing = marketplace.listings[parentMerchantId];
|
|
219
|
+
if (!listing || listing.status === marketplace_constants_1.MARKETPLACE_LISTING_STATUSES.removed) {
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
const q = Number(quantity !== null && quantity !== void 0 ? quantity : lineItem === null || lineItem === void 0 ? void 0 : lineItem.quantity) > 0 ? Number(quantity !== null && quantity !== void 0 ? quantity : lineItem === null || lineItem === void 0 ? void 0 : lineItem.quantity) : 1;
|
|
223
|
+
const originalAmount = Number((_a = lineItem === null || lineItem === void 0 ? void 0 : lineItem.originalTotalPrice) === null || _a === void 0 ? void 0 : _a.amount);
|
|
224
|
+
const discountedAmount = Number((_b = lineItem === null || lineItem === void 0 ? void 0 : lineItem.discountedPrice) === null || _b === void 0 ? void 0 : _b.amount);
|
|
225
|
+
const safeOriginal = Number.isFinite(originalAmount) ? originalAmount : this.lineNetFromProduct(product, q);
|
|
226
|
+
const safeDiscounted = Number.isFinite(discountedAmount) ? discountedAmount : safeOriginal;
|
|
227
|
+
const resolvedDiscount = discountAmount === undefined ? Math.max(0, safeOriginal - safeDiscounted) : Number(discountAmount) || 0;
|
|
228
|
+
const resolvedTax = taxAmount === undefined
|
|
229
|
+
? Number((_f = (_d = (_c = lineItem === null || lineItem === void 0 ? void 0 : lineItem.taxAmount) === null || _c === void 0 ? void 0 : _c.amount) !== null && _d !== void 0 ? _d : (_e = lineItem === null || lineItem === void 0 ? void 0 : lineItem.taxAmountWithDiscount) === null || _e === void 0 ? void 0 : _e.amount) !== null && _f !== void 0 ? _f : 0) || 0
|
|
230
|
+
: Number(taxAmount) || 0;
|
|
231
|
+
const resolvedCurrency = currencyCode ||
|
|
232
|
+
((_g = lineItem === null || lineItem === void 0 ? void 0 : lineItem.originalTotalPrice) === null || _g === void 0 ? void 0 : _g.currencyCode) ||
|
|
233
|
+
((_h = lineItem === null || lineItem === void 0 ? void 0 : lineItem.discountedPrice) === null || _h === void 0 ? void 0 : _h.currencyCode) ||
|
|
234
|
+
((_j = lineItem === null || lineItem === void 0 ? void 0 : lineItem.presentmentTotalPrice) === null || _j === void 0 ? void 0 : _j.currencyCode) ||
|
|
235
|
+
'';
|
|
236
|
+
const resolvedCommission = marketplaceCommissionRate === undefined || marketplaceCommissionRate === null
|
|
237
|
+
? (_k = relationship === null || relationship === void 0 ? void 0 : relationship.marketplaceCommission) !== null && _k !== void 0 ? _k : '0'
|
|
238
|
+
: marketplaceCommissionRate;
|
|
239
|
+
const resolvedVariantSelection = variantSelection && (variantSelection.variantId || variantSelection.options)
|
|
240
|
+
? variantSelection
|
|
241
|
+
: deriveVariantSelectionFromLineItem(lineItem) || {};
|
|
242
|
+
return this.buildLineSnapshot({
|
|
243
|
+
product,
|
|
244
|
+
parentMerchantId,
|
|
245
|
+
managedMerchantId,
|
|
246
|
+
relationshipId: String((relationship === null || relationship === void 0 ? void 0 : relationship.documentId) || listing.relationshipId || ''),
|
|
247
|
+
sellerDisplayName: String(product.vendorName || ''),
|
|
248
|
+
lineDisplayTitle: String(product.title || product.brand || ''),
|
|
249
|
+
marketplaceCommissionRate: resolvedCommission,
|
|
250
|
+
originalProductCommissionRate,
|
|
251
|
+
marketplaceCommissionBasis: marketplaceCommissionBasis || (relationship === null || relationship === void 0 ? void 0 : relationship.marketplaceCommissionBasis) || marketplace_constants_1.DEFAULT_MARKETPLACE_COMMISSION_BASIS,
|
|
252
|
+
quantity: q,
|
|
253
|
+
currencyCode: resolvedCurrency,
|
|
254
|
+
discountAmount: resolvedDiscount,
|
|
255
|
+
taxAmount: resolvedTax,
|
|
256
|
+
stripeFeeAllocatedAmount,
|
|
257
|
+
ribbnFeeAllocatedAmount,
|
|
258
|
+
variantSelection: resolvedVariantSelection,
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
static prorateAmounts(amounts, ratio) {
|
|
262
|
+
const safeRatio = Math.max(0, Math.min(1, Number(ratio) || 0));
|
|
263
|
+
return Object.keys(amounts).reduce((acc, key) => {
|
|
264
|
+
acc[key] = roundMoney(Number(amounts[key] || 0) * safeRatio);
|
|
265
|
+
return acc;
|
|
266
|
+
}, {});
|
|
267
|
+
}
|
|
268
|
+
static buildReturnAdjustment({ snapshot, quantityReturned }) {
|
|
269
|
+
// Use nullish coalescing so an explicit 0 means "no quantity returned"
|
|
270
|
+
// (zero-amount adjustment), while undefined/null still defaults to the
|
|
271
|
+
// full snapshot quantity (used by the post-payout refund flow).
|
|
272
|
+
const requested = quantityReturned === undefined || quantityReturned === null ? snapshot.quantity : Number(quantityReturned);
|
|
273
|
+
const returned = Math.max(0, Math.min(requested, snapshot.quantity));
|
|
274
|
+
const ratio = snapshot.quantity > 0 ? returned / snapshot.quantity : 0;
|
|
275
|
+
return {
|
|
276
|
+
quantityReturned: returned,
|
|
277
|
+
amounts: this.prorateAmounts(snapshot.amounts, ratio),
|
|
278
|
+
remainingQuantity: snapshot.quantity - returned,
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
static transformVariantInventory({ product, variantId, locationId = '', quantity = 1 }, direction) {
|
|
282
|
+
const variants = Array.isArray(product.variantInventory) ? product.variantInventory : [];
|
|
283
|
+
const qty = Math.max(0, Number(quantity) || 0);
|
|
284
|
+
return variants.map((variant) => {
|
|
285
|
+
if (variant.id !== variantId)
|
|
286
|
+
return variant;
|
|
287
|
+
const locations = Array.isArray(variant.locations) ? variant.locations : [];
|
|
288
|
+
const nextLocations = locations.map((loc, index) => {
|
|
289
|
+
if (locationId && loc.id !== locationId)
|
|
290
|
+
return loc;
|
|
291
|
+
if (!locationId && index > 0)
|
|
292
|
+
return loc;
|
|
293
|
+
const availableAmount = Number(loc.availableAmount) || 0;
|
|
294
|
+
return Object.assign(Object.assign({}, loc), { availableAmount: direction === 'restore' ? availableAmount + qty : Math.max(0, availableAmount - qty) });
|
|
295
|
+
});
|
|
296
|
+
return Object.assign(Object.assign({}, variant), { locations: nextLocations });
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
static decrementVariantInventory(params) {
|
|
300
|
+
return this.transformVariantInventory(params, 'decrement');
|
|
301
|
+
}
|
|
302
|
+
static restoreVariantInventory(params) {
|
|
303
|
+
return this.transformVariantInventory(params, 'restore');
|
|
304
|
+
}
|
|
305
|
+
// ---------------------------------------------------------------------
|
|
306
|
+
// Inventory dispatch (delegates to the InventoryPolicy registry)
|
|
307
|
+
// ---------------------------------------------------------------------
|
|
308
|
+
static registerInventoryPolicy(policy, position = 'append') {
|
|
309
|
+
InventoryPolicyRegistry.register(policy, position);
|
|
310
|
+
}
|
|
311
|
+
static findInventoryPolicy(product) {
|
|
312
|
+
return InventoryPolicyRegistry.find(product);
|
|
313
|
+
}
|
|
314
|
+
static adjustInventory(product, params, direction) {
|
|
315
|
+
if (!product)
|
|
316
|
+
return {};
|
|
317
|
+
const policy = InventoryPolicyRegistry.find(product);
|
|
318
|
+
if (!policy)
|
|
319
|
+
return {};
|
|
320
|
+
return direction === 'restore' ? policy.restore(product, params) : policy.decrement(product, params);
|
|
321
|
+
}
|
|
322
|
+
// Single entry point backend callers use to adjust inventory for one order
|
|
323
|
+
// line. Resolves `variantId` and `quantity` from the line item itself when
|
|
324
|
+
// not passed explicitly, derives variant identity from the same shapes
|
|
325
|
+
// `buildLineSnapshotFromListing` supports, then dispatches through the
|
|
326
|
+
// policy registry. The `defaultLocationId` (typically a merchant's default
|
|
327
|
+
// fulfillment location) is honored by both the multivariant and
|
|
328
|
+
// one-of-a-kind policies when no explicit `locationId` is supplied.
|
|
329
|
+
static adjustVariantInventoryForLine(product, { lineItem = {}, variantId, locationId, defaultLocationId, quantity, }, direction = 'decrement') {
|
|
330
|
+
if (!product)
|
|
331
|
+
return {};
|
|
332
|
+
const inferred = deriveVariantSelectionFromLineItem(lineItem) || {};
|
|
333
|
+
const inferredVariant = !variantId && !inferred.variantId ? this.selectVariant(product, inferred) : null;
|
|
334
|
+
const resolvedVariantId = String(variantId || inferred.variantId || (inferredVariant === null || inferredVariant === void 0 ? void 0 : inferredVariant.variantId) || '');
|
|
335
|
+
const quantityInput = quantity === undefined ? lineItem === null || lineItem === void 0 ? void 0 : lineItem.quantity : quantity;
|
|
336
|
+
const lineQty = Number(quantityInput);
|
|
337
|
+
const resolvedQuantity = quantityInput === undefined || quantityInput === null || !Number.isFinite(lineQty) ? 1 : Math.max(0, lineQty);
|
|
338
|
+
return this.adjustInventory(product, {
|
|
339
|
+
variantId: resolvedVariantId,
|
|
340
|
+
locationId: locationId || '',
|
|
341
|
+
defaultLocationId: defaultLocationId || '',
|
|
342
|
+
quantity: resolvedQuantity,
|
|
343
|
+
}, direction);
|
|
344
|
+
}
|
|
345
|
+
// ---------------------------------------------------------------------
|
|
346
|
+
// Fee allocation (delegates to the FeeAllocationPolicy registry)
|
|
347
|
+
// ---------------------------------------------------------------------
|
|
348
|
+
static registerFeeAllocationPolicy(policy) {
|
|
349
|
+
FeeAllocationPolicyRegistry.register(policy);
|
|
350
|
+
}
|
|
351
|
+
static getFeeAllocationPolicy(basis) {
|
|
352
|
+
return FeeAllocationPolicyRegistry.get(basis);
|
|
353
|
+
}
|
|
354
|
+
static allocateFee(context, basis = marketplace_constants_1.DEFAULT_STRIPE_FEE_ALLOCATION_BASIS) {
|
|
355
|
+
const policy = FeeAllocationPolicyRegistry.get(basis);
|
|
356
|
+
return policy.allocate(context);
|
|
357
|
+
}
|
|
358
|
+
static allocateStripeFee(context) {
|
|
359
|
+
return this.allocateFee(context, marketplace_constants_1.DEFAULT_STRIPE_FEE_ALLOCATION_BASIS);
|
|
360
|
+
}
|
|
361
|
+
static allocateRibbnFee(context) {
|
|
362
|
+
return this.allocateFee(context, marketplace_constants_1.DEFAULT_RIBBN_FEE_ALLOCATION_BASIS);
|
|
363
|
+
}
|
|
364
|
+
static buildFeeBasketFromProducts({ merchantId, products = [], }) {
|
|
365
|
+
return (Array.isArray(products) ? products : []).map((product, index) => ({
|
|
366
|
+
lineKey: `${String((product === null || product === void 0 ? void 0 : product.documentId) || 'product')}:${index}`,
|
|
367
|
+
sellerMerchantId: String((product === null || product === void 0 ? void 0 : product.vendorId) || (product === null || product === void 0 ? void 0 : product.merchantId) || ''),
|
|
368
|
+
lineNetAmount: (product === null || product === void 0 ? void 0 : product.vendorId) && product.vendorId !== merchantId ? Number((product === null || product === void 0 ? void 0 : product.salePrice) || (product === null || product === void 0 ? void 0 : product.price) || 0) : 0,
|
|
369
|
+
quantity: 1,
|
|
370
|
+
}));
|
|
371
|
+
}
|
|
372
|
+
static applyStripeFeeRecoupBumpToProducts({ merchantId, products = [], totalFeeAmount, basis = marketplace_constants_1.DEFAULT_STRIPE_FEE_ALLOCATION_BASIS, }) {
|
|
373
|
+
if (!merchantId || !Array.isArray(products) || products.length === 0) {
|
|
374
|
+
return products;
|
|
375
|
+
}
|
|
376
|
+
const safeTotal = Number(totalFeeAmount);
|
|
377
|
+
if (!Number.isFinite(safeTotal) || safeTotal <= 0) {
|
|
378
|
+
return products;
|
|
379
|
+
}
|
|
380
|
+
const basket = this.buildFeeBasketFromProducts({ merchantId, products });
|
|
381
|
+
const allocationsByLineKey = this.allocateFee({ totalFeeAmount: safeTotal, basket }, basis).reduce((acc, allocation) => {
|
|
382
|
+
acc[allocation.lineKey] = Number(allocation.amount || 0);
|
|
383
|
+
return acc;
|
|
384
|
+
}, {});
|
|
385
|
+
return products.map((product, index) => {
|
|
386
|
+
const sellerId = String((product === null || product === void 0 ? void 0 : product.vendorId) || (product === null || product === void 0 ? void 0 : product.merchantId) || '');
|
|
387
|
+
if (!sellerId || sellerId === merchantId)
|
|
388
|
+
return product;
|
|
389
|
+
const linePrice = Number((product === null || product === void 0 ? void 0 : product.salePrice) || (product === null || product === void 0 ? void 0 : product.price) || 0);
|
|
390
|
+
if (!Number.isFinite(linePrice) || linePrice <= 0)
|
|
391
|
+
return product;
|
|
392
|
+
const lineKey = `${String((product === null || product === void 0 ? void 0 : product.documentId) || 'product')}:${index}`;
|
|
393
|
+
const allocatedFee = Number(allocationsByLineKey[lineKey] || 0);
|
|
394
|
+
if (!allocatedFee)
|
|
395
|
+
return product;
|
|
396
|
+
const baseCommission = Number((product === null || product === void 0 ? void 0 : product.reRobeCommission) || 0);
|
|
397
|
+
const effective = baseCommission + allocatedFee / linePrice;
|
|
398
|
+
return Object.assign(Object.assign({}, product), { reRobeCommission: String(Number(effective.toFixed(6))) });
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
// ---------------------------------------------------------------------
|
|
402
|
+
// Listing transitions (immutable updates that bump updatedAt)
|
|
403
|
+
// ---------------------------------------------------------------------
|
|
404
|
+
static upsertListing(marketplace, parentMarketplaceId, partial = {}, options = {}) {
|
|
405
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
406
|
+
if (!parentMarketplaceId) {
|
|
407
|
+
return this.normalizeMarketplace(marketplace);
|
|
408
|
+
}
|
|
409
|
+
const ts = typeof options.at === 'number' ? options.at : Date.now();
|
|
410
|
+
const current = this.normalizeMarketplace(marketplace);
|
|
411
|
+
const existing = current.listings[parentMarketplaceId];
|
|
412
|
+
const ownerMerchantId = partial.ownerMerchantId || '';
|
|
413
|
+
const nextListing = {
|
|
414
|
+
relationshipId: String((_b = (_a = partial.relationshipId) !== null && _a !== void 0 ? _a : existing === null || existing === void 0 ? void 0 : existing.relationshipId) !== null && _b !== void 0 ? _b : ''),
|
|
415
|
+
relationshipType: String((_d = (_c = partial.relationshipType) !== null && _c !== void 0 ? _c : existing === null || existing === void 0 ? void 0 : existing.relationshipType) !== null && _d !== void 0 ? _d : marketplace_constants_1.MARKETPLACE_RELATIONSHIP_TYPES.marketplaceSeller),
|
|
416
|
+
status: String((_f = (_e = partial.status) !== null && _e !== void 0 ? _e : existing === null || existing === void 0 ? void 0 : existing.status) !== null && _f !== void 0 ? _f : marketplace_constants_1.DEFAULT_MARKETPLACE_LISTING_STATUS),
|
|
417
|
+
listedAt: (_g = existing === null || existing === void 0 ? void 0 : existing.listedAt) !== null && _g !== void 0 ? _g : (partial.listedAt === undefined ? ts : partial.listedAt),
|
|
418
|
+
updatedAt: ts,
|
|
419
|
+
};
|
|
420
|
+
const nextListings = Object.assign(Object.assign({}, current.listings), { [parentMarketplaceId]: nextListing });
|
|
421
|
+
const activeParentIds = Object.keys(nextListings).filter((id) => { var _a; return ((_a = nextListings[id]) === null || _a === void 0 ? void 0 : _a.status) !== marketplace_constants_1.MARKETPLACE_LISTING_STATUSES.removed; });
|
|
422
|
+
return {
|
|
423
|
+
visibleToMerchantIds: this.uniqueStrings([ownerMerchantId, ...activeParentIds]),
|
|
424
|
+
listings: nextListings,
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
static pauseListing(marketplace, parentMarketplaceId, options = {}) {
|
|
428
|
+
return this.upsertListing(marketplace, parentMarketplaceId, { status: marketplace_constants_1.MARKETPLACE_LISTING_STATUSES.paused, ownerMerchantId: options.ownerMerchantId }, options);
|
|
429
|
+
}
|
|
430
|
+
static resumeListing(marketplace, parentMarketplaceId, options = {}) {
|
|
431
|
+
return this.upsertListing(marketplace, parentMarketplaceId, { status: marketplace_constants_1.MARKETPLACE_LISTING_STATUSES.active, ownerMerchantId: options.ownerMerchantId }, options);
|
|
432
|
+
}
|
|
433
|
+
static removeListing(marketplace, parentMarketplaceId, options = {}) {
|
|
434
|
+
return this.upsertListing(marketplace, parentMarketplaceId, { status: marketplace_constants_1.MARKETPLACE_LISTING_STATUSES.removed, ownerMerchantId: options.ownerMerchantId }, options);
|
|
435
|
+
}
|
|
436
|
+
static buildCanonicalMarketplaceListingPatch({ product, parentMerchantId, relationshipId = '', relationshipType = marketplace_constants_1.MARKETPLACE_RELATIONSHIP_TYPES.marketplaceSeller, listingStatus = marketplace_constants_1.MARKETPLACE_LISTING_STATUSES.active, at = Date.now(), }) {
|
|
437
|
+
if (!(product === null || product === void 0 ? void 0 : product.documentId) || !parentMerchantId)
|
|
438
|
+
return null;
|
|
439
|
+
const ownerMerchantId = String(product.merchantId || product.vendorId || '');
|
|
440
|
+
if (!ownerMerchantId)
|
|
441
|
+
return null;
|
|
442
|
+
const current = this.normalizeMarketplace(product.marketplace);
|
|
443
|
+
const existing = current.listings[parentMerchantId];
|
|
444
|
+
const nextMarketplace = this.upsertListing(current, parentMerchantId, {
|
|
445
|
+
relationshipId,
|
|
446
|
+
relationshipType,
|
|
447
|
+
status: listingStatus,
|
|
448
|
+
ownerMerchantId,
|
|
449
|
+
}, { at });
|
|
450
|
+
const listingUnchanged = existing &&
|
|
451
|
+
existing.relationshipId === relationshipId &&
|
|
452
|
+
existing.relationshipType === relationshipType &&
|
|
453
|
+
existing.status === listingStatus;
|
|
454
|
+
const visibleUnchanged = JSON.stringify(this.uniqueStrings(current.visibleToMerchantIds).sort()) ===
|
|
455
|
+
JSON.stringify(this.uniqueStrings(nextMarketplace.visibleToMerchantIds).sort());
|
|
456
|
+
return listingUnchanged && visibleUnchanged ? null : { marketplace: nextMarketplace };
|
|
457
|
+
}
|
|
458
|
+
// ---------------------------------------------------------------------
|
|
459
|
+
// Shim helpers (replace ad-hoc backend/web logic with one ORM source)
|
|
460
|
+
// ---------------------------------------------------------------------
|
|
461
|
+
// Replaces backend `Procedure.resolveProductsWithEffectiveCommission` for
|
|
462
|
+
// a single product+relationship pair. Backend keeps the Firestore lookup
|
|
463
|
+
// and dispatches the override via this helper.
|
|
464
|
+
static resolveEffectiveCommission(product, relationship, contextMerchantId) {
|
|
465
|
+
const baseCommission = String((product === null || product === void 0 ? void 0 : product.reRobeCommission) || '');
|
|
466
|
+
if (!product || !relationship)
|
|
467
|
+
return baseCommission;
|
|
468
|
+
if (relationship.isActive === false)
|
|
469
|
+
return baseCommission;
|
|
470
|
+
if (relationship.relationshipType &&
|
|
471
|
+
relationship.relationshipType !== marketplace_constants_1.MARKETPLACE_RELATIONSHIP_TYPES.marketplaceSeller) {
|
|
472
|
+
return baseCommission;
|
|
473
|
+
}
|
|
474
|
+
if (contextMerchantId && relationship.parentMerchantId && relationship.parentMerchantId !== contextMerchantId) {
|
|
475
|
+
return baseCommission;
|
|
476
|
+
}
|
|
477
|
+
if (contextMerchantId && product.vendorId && product.vendorId === contextMerchantId) {
|
|
478
|
+
return baseCommission;
|
|
479
|
+
}
|
|
480
|
+
const override = relationship.marketplaceCommission;
|
|
481
|
+
if (override === undefined || override === null || override === '')
|
|
482
|
+
return baseCommission;
|
|
483
|
+
return String(override);
|
|
484
|
+
}
|
|
485
|
+
static applyEffectiveCommissionToProducts({ products = [], relationships = [], contextMerchantId, }) {
|
|
486
|
+
if (!Array.isArray(products) || products.length === 0)
|
|
487
|
+
return products;
|
|
488
|
+
const relationshipsBySellerId = (Array.isArray(relationships) ? relationships : []).reduce((acc, relationship) => {
|
|
489
|
+
const sellerId = String((relationship === null || relationship === void 0 ? void 0 : relationship.childMerchantId) || '');
|
|
490
|
+
if (sellerId)
|
|
491
|
+
acc[sellerId] = relationship;
|
|
492
|
+
return acc;
|
|
493
|
+
}, {});
|
|
494
|
+
return products.map((product) => {
|
|
495
|
+
const relationship = relationshipsBySellerId[String((product === null || product === void 0 ? void 0 : product.vendorId) || (product === null || product === void 0 ? void 0 : product.merchantId) || '')];
|
|
496
|
+
if (!relationship)
|
|
497
|
+
return product;
|
|
498
|
+
const effectiveCommission = this.resolveEffectiveCommission(product, relationship, contextMerchantId);
|
|
499
|
+
if (effectiveCommission === String((product === null || product === void 0 ? void 0 : product.reRobeCommission) || ''))
|
|
500
|
+
return product;
|
|
501
|
+
return Object.assign(Object.assign({}, product), { reRobeCommission: effectiveCommission });
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
// Replaces ad-hoc per-component branches in
|
|
505
|
+
// RetailProductQuickEntry / QuickProductUpload / SimplifiedManagedProductDetails.
|
|
506
|
+
// Always returns the canonical seller-owned shape regardless of `isActingAs`.
|
|
507
|
+
// `isActingAs` and `parentMerchantId` are accepted for API compatibility
|
|
508
|
+
// with the call sites being migrated, but ownership is intentionally
|
|
509
|
+
// independent of who initiated the create — marketplace visibility for the
|
|
510
|
+
// parent is derived later via `product.marketplace` and indexed Typesense
|
|
511
|
+
// fields.
|
|
512
|
+
static buildSellerProductOwnership(params) {
|
|
513
|
+
const sellerMerchantId = params === null || params === void 0 ? void 0 : params.sellerMerchantId;
|
|
514
|
+
if (!sellerMerchantId) {
|
|
515
|
+
throw new MarketplaceErrors_2.MarketplaceOwnershipError('sellerMerchantId is required');
|
|
516
|
+
}
|
|
517
|
+
return {
|
|
518
|
+
merchantId: sellerMerchantId,
|
|
519
|
+
vendorId: sellerMerchantId,
|
|
520
|
+
merchants: [sellerMerchantId],
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
static defaultSellerCommission() {
|
|
524
|
+
return marketplace_constants_1.MARKETPLACE_SELLER_DEFAULT_COMMISSION;
|
|
525
|
+
}
|
|
526
|
+
// Builds the Typesense filter expression that scopes parent-marketplace
|
|
527
|
+
// act-as searches to a single managed merchant. Returning an empty
|
|
528
|
+
// string allows callers to short-circuit without producing a malformed
|
|
529
|
+
// filter expression like `vendorId:=`.
|
|
530
|
+
static buildActAsTypesenseFilter(managedMerchantId) {
|
|
531
|
+
if (!managedMerchantId)
|
|
532
|
+
return '';
|
|
533
|
+
return `vendorId:=${String(managedMerchantId)}`;
|
|
534
|
+
}
|
|
535
|
+
// Normalizes an arbitrary commission rate input (string / number /
|
|
536
|
+
// comma-decimal) into the canonical `'0'..'1'` string. Throws a typed
|
|
537
|
+
// error for inputs outside the valid range so callers can surface UX
|
|
538
|
+
// copy without re-implementing validation.
|
|
539
|
+
static normalizeCommissionRate(value) {
|
|
540
|
+
if (value === null || value === undefined || value === '') {
|
|
541
|
+
throw new MarketplaceErrors_2.MarketplaceCommissionRateError('commission rate is required');
|
|
542
|
+
}
|
|
543
|
+
const sanitized = String(value).trim().replace(',', '.');
|
|
544
|
+
const numeric = Number(sanitized);
|
|
545
|
+
if (!Number.isFinite(numeric)) {
|
|
546
|
+
throw new MarketplaceErrors_2.MarketplaceCommissionRateError(`commission rate '${value}' is not a finite number`);
|
|
547
|
+
}
|
|
548
|
+
const normalized = numeric > 1 ? numeric / 100 : numeric;
|
|
549
|
+
if (normalized < 0 || normalized > 1) {
|
|
550
|
+
throw new MarketplaceErrors_2.MarketplaceCommissionRateError(`commission rate '${value}' must be between 0 and 1 inclusive`);
|
|
551
|
+
}
|
|
552
|
+
return String(Number(normalized.toFixed(6)));
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
exports.default = MarketplaceProductHelpers;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { OrderLinePricing, OrderLinePricingLike } from '../types/pricing-types';
|
|
1
2
|
export default class OrderHelpers {
|
|
3
|
+
getLinePricing(line: OrderLinePricingLike | null | undefined): OrderLinePricing;
|
|
2
4
|
getOrderIdFromShopifyObj(order: ShopifyRestApiOrderObj): string | number | null;
|
|
3
5
|
getShippingTypeFromShopifyObj(shippingLines: ShippingLineRest[] | null | undefined): string;
|
|
4
6
|
getPaymentTypeUsingTags(tags: string | null | undefined): string | null;
|
|
5
7
|
getSalesChannelUsingTags(tags: string | null | undefined): string | null;
|
|
6
|
-
buildLineItemFromProduct(product: CompleteProduct, currencyCode: string, quantity?: number, taxProps?: RibbnTaxProps): ReRobeOrderLineItem;
|
|
8
|
+
buildLineItemFromProduct(product: CompleteProduct, currencyCode: string, quantity?: number, taxProps?: RibbnTaxProps, marketplace?: MarketplaceLineSnapshot): ReRobeOrderLineItem;
|
|
7
9
|
toFixedPointPrice(price: number | string): string;
|
|
8
10
|
getAmountSumByField(array: OrderRefund[] | ReRobeOrderLineItem[], fieldKey: string): number;
|
|
9
11
|
getOrderInfoWithRefundsAndFulfillments(order: CompleteOrder): OrderWithRefundsAndFulfillmentsInfoObj;
|
|
@@ -47,7 +49,7 @@ export default class OrderHelpers {
|
|
|
47
49
|
getPaymentTerminalReceiptInfo(payload?: any): PaymentTerminalReceiptInfo;
|
|
48
50
|
getFormattedFulfillmentLocation(order: ReRobeOrderObj): string;
|
|
49
51
|
generateReceiptLabels(locale: string, paymentMethod: string, entryMode?: string): ReceiptLabels;
|
|
50
|
-
buildReceiptObjFromOrder({ order, merchant, merchantLogoUrl, receiptNumber, additionalInfo, isRefund, refundId, originalReceiptNumber, }: {
|
|
52
|
+
buildReceiptObjFromOrder({ order, merchant, merchantLogoUrl, receiptNumber, additionalInfo, isRefund, refundId, originalReceiptNumber, includeMarketplaceSellerPrefix, }: {
|
|
51
53
|
order: ReRobeOrderObj;
|
|
52
54
|
merchant: MerchantObj;
|
|
53
55
|
merchantLogoUrl: string;
|
|
@@ -56,6 +58,7 @@ export default class OrderHelpers {
|
|
|
56
58
|
isRefund?: boolean;
|
|
57
59
|
refundId?: string | null;
|
|
58
60
|
originalReceiptNumber?: string | null;
|
|
61
|
+
includeMarketplaceSellerPrefix?: boolean;
|
|
59
62
|
}): ReceiptObj;
|
|
60
63
|
/**
|
|
61
64
|
* Generates an idempotency key from a ReRobeOrderObj to prevent duplicate order creation
|
|
@@ -5,7 +5,17 @@ const Utilities_1 = require("../helpers/Utilities");
|
|
|
5
5
|
const order_constants_1 = require("../constants/order-constants");
|
|
6
6
|
const translations_1 = require("../translations");
|
|
7
7
|
const CryptoPolyfill_1 = require("./CryptoPolyfill");
|
|
8
|
+
const PricingHelpers_1 = require("./PricingHelpers");
|
|
9
|
+
const MarketplaceLineDisplayHelpers_1 = require("./marketplace/MarketplaceLineDisplayHelpers");
|
|
8
10
|
class OrderHelpers {
|
|
11
|
+
// Frozen-rate pricing snapshot for a single order line item. Reads
|
|
12
|
+
// `line.taxRate` (captured at order creation) so the gross display
|
|
13
|
+
// reflects the tax actually charged, not whatever the current catalog
|
|
14
|
+
// says. Non-breaking — `buildReceiptObjFromOrder` continues to compute
|
|
15
|
+
// its own gross math inline; new callers can opt in via this accessor.
|
|
16
|
+
getLinePricing(line) {
|
|
17
|
+
return PricingHelpers_1.default.getOrderLinePricing(line);
|
|
18
|
+
}
|
|
9
19
|
getOrderIdFromShopifyObj(order) {
|
|
10
20
|
const { id, tags } = order;
|
|
11
21
|
if (!tags) {
|
|
@@ -66,7 +76,7 @@ class OrderHelpers {
|
|
|
66
76
|
}
|
|
67
77
|
return null;
|
|
68
78
|
}
|
|
69
|
-
buildLineItemFromProduct(product, currencyCode, quantity = 1, taxProps = {}) {
|
|
79
|
+
buildLineItemFromProduct(product, currencyCode, quantity = 1, taxProps = {}, marketplace) {
|
|
70
80
|
var _a;
|
|
71
81
|
const q = quantity || 1;
|
|
72
82
|
const getImgSrc = () => {
|
|
@@ -78,7 +88,7 @@ class OrderHelpers {
|
|
|
78
88
|
}
|
|
79
89
|
return '';
|
|
80
90
|
};
|
|
81
|
-
|
|
91
|
+
const lineItem = {
|
|
82
92
|
title: product.title,
|
|
83
93
|
quantity: q,
|
|
84
94
|
variant: {
|
|
@@ -119,6 +129,10 @@ class OrderHelpers {
|
|
|
119
129
|
},
|
|
120
130
|
handle: product.handle || '',
|
|
121
131
|
};
|
|
132
|
+
if (marketplace) {
|
|
133
|
+
lineItem.marketplace = marketplace;
|
|
134
|
+
}
|
|
135
|
+
return lineItem;
|
|
122
136
|
}
|
|
123
137
|
toFixedPointPrice(price) {
|
|
124
138
|
return Number(price).toFixed(2);
|
|
@@ -579,7 +593,7 @@ class OrderHelpers {
|
|
|
579
593
|
entryModeLabel,
|
|
580
594
|
};
|
|
581
595
|
}
|
|
582
|
-
buildReceiptObjFromOrder({ order, merchant, merchantLogoUrl = '', receiptNumber = '', additionalInfo = '', isRefund = false, refundId = null, originalReceiptNumber = null, }) {
|
|
596
|
+
buildReceiptObjFromOrder({ order, merchant, merchantLogoUrl = '', receiptNumber = '', additionalInfo = '', isRefund = false, refundId = null, originalReceiptNumber = null, includeMarketplaceSellerPrefix = false, }) {
|
|
583
597
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x;
|
|
584
598
|
const { address: merchantAddress, legalName, name, contactEmail, phone = '', organizationNumber = '', primaryDomain, currency: storeCurrencyCode, returnPolicy, } = merchant;
|
|
585
599
|
const currencyCode = ((_a = order.totalPricePresentment) === null || _a === void 0 ? void 0 : _a.currencyCode) || storeCurrencyCode;
|
|
@@ -594,7 +608,7 @@ class OrderHelpers {
|
|
|
594
608
|
if (isRefund) {
|
|
595
609
|
totalPrice = -Math.abs(totalPrice);
|
|
596
610
|
}
|
|
597
|
-
let title =
|
|
611
|
+
let title = (0, MarketplaceLineDisplayHelpers_1.formatMarketplaceLineDisplayTitle)({ lineItem: l }, { includeSellerPrefix: includeMarketplaceSellerPrefix });
|
|
598
612
|
if (Number(l === null || l === void 0 ? void 0 : l.quantity) > 1) {
|
|
599
613
|
const unitPrice = isRefund
|
|
600
614
|
? -Math.abs(Number((_c = (_b = l === null || l === void 0 ? void 0 : l.originalUnitPrice) === null || _b === void 0 ? void 0 : _b.amount) !== null && _c !== void 0 ? _c : 0))
|