rerobe-js-orm 4.8.7 → 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/merchant-constants.d.ts +35 -0
- package/lib/constants/merchant-constants.js +35 -1
- 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/Merchant.d.ts +86 -0
- package/lib/models/Merchant.js +86 -0
- package/lib/models/Product.d.ts +16 -0
- package/lib/models/Product.js +151 -0
- package/lib/types/merchant-types.d.ts +28 -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
package/lib/models/Merchant.d.ts
CHANGED
|
@@ -1,4 +1,35 @@
|
|
|
1
1
|
import Base from '../Base';
|
|
2
|
+
export type LabelTextSource = 'merchantName' | 'title' | 'price';
|
|
3
|
+
export type LabelTextElement = {
|
|
4
|
+
source: LabelTextSource | string;
|
|
5
|
+
visible: boolean;
|
|
6
|
+
fontSize: number;
|
|
7
|
+
paddingTop: number;
|
|
8
|
+
transform: 'uppercase' | 'none' | string;
|
|
9
|
+
};
|
|
10
|
+
export type LabelBarcodeConfig = {
|
|
11
|
+
visible: boolean;
|
|
12
|
+
heightDots: number;
|
|
13
|
+
moduleWidth: 1 | 2;
|
|
14
|
+
paddingBottom: number;
|
|
15
|
+
};
|
|
16
|
+
export type LabelSkuConfig = {
|
|
17
|
+
visible: boolean;
|
|
18
|
+
fontSize: number;
|
|
19
|
+
};
|
|
20
|
+
export type LabelLayout = {
|
|
21
|
+
topElements: LabelTextElement[];
|
|
22
|
+
barcode: LabelBarcodeConfig;
|
|
23
|
+
sku: LabelSkuConfig;
|
|
24
|
+
};
|
|
25
|
+
export type LabelPrinterConfig = {
|
|
26
|
+
protocol: string;
|
|
27
|
+
widthMm: number;
|
|
28
|
+
heightMm: number;
|
|
29
|
+
dpi: number;
|
|
30
|
+
symbology: string;
|
|
31
|
+
layout: LabelLayout;
|
|
32
|
+
};
|
|
2
33
|
export default class Merchant extends Base {
|
|
3
34
|
static MERCHANT_TYPES: {
|
|
4
35
|
individual: string;
|
|
@@ -46,6 +77,58 @@ export default class Merchant extends Base {
|
|
|
46
77
|
upgradeToStandalone: string;
|
|
47
78
|
};
|
|
48
79
|
static DEFAULT_MARKETPLACE_SELLER_CAPABILITIES: string[];
|
|
80
|
+
static LABEL_PRINTER_BARCODE_SYMBOLOGIES: {
|
|
81
|
+
code128: string;
|
|
82
|
+
ean13: string;
|
|
83
|
+
};
|
|
84
|
+
static LABEL_PRINTER_PROTOCOLS: {
|
|
85
|
+
zebraZpl: string;
|
|
86
|
+
};
|
|
87
|
+
static LABEL_PRINTER_CONFIG_DEFAULTS: {
|
|
88
|
+
protocol: string;
|
|
89
|
+
widthMm: number;
|
|
90
|
+
heightMm: number;
|
|
91
|
+
dpi: number;
|
|
92
|
+
symbology: string;
|
|
93
|
+
layout: {
|
|
94
|
+
topElements: {
|
|
95
|
+
source: string;
|
|
96
|
+
visible: boolean;
|
|
97
|
+
fontSize: number;
|
|
98
|
+
paddingTop: number;
|
|
99
|
+
transform: string;
|
|
100
|
+
}[];
|
|
101
|
+
barcode: {
|
|
102
|
+
visible: boolean;
|
|
103
|
+
heightDots: number;
|
|
104
|
+
moduleWidth: number;
|
|
105
|
+
paddingBottom: number;
|
|
106
|
+
};
|
|
107
|
+
sku: {
|
|
108
|
+
visible: boolean;
|
|
109
|
+
fontSize: number;
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
};
|
|
113
|
+
static DEFAULT_LABEL_LAYOUT: {
|
|
114
|
+
topElements: {
|
|
115
|
+
source: string;
|
|
116
|
+
visible: boolean;
|
|
117
|
+
fontSize: number;
|
|
118
|
+
paddingTop: number;
|
|
119
|
+
transform: string;
|
|
120
|
+
}[];
|
|
121
|
+
barcode: {
|
|
122
|
+
visible: boolean;
|
|
123
|
+
heightDots: number;
|
|
124
|
+
moduleWidth: number;
|
|
125
|
+
paddingBottom: number;
|
|
126
|
+
};
|
|
127
|
+
sku: {
|
|
128
|
+
visible: boolean;
|
|
129
|
+
fontSize: number;
|
|
130
|
+
};
|
|
131
|
+
};
|
|
49
132
|
static INDUSTRY_TYPES: {
|
|
50
133
|
beauty: string;
|
|
51
134
|
clothing: string;
|
|
@@ -112,6 +195,8 @@ export default class Merchant extends Base {
|
|
|
112
195
|
hasAutomatedPayouts?: boolean;
|
|
113
196
|
hasAIQuickList?: boolean;
|
|
114
197
|
hasReceiptPrinter?: boolean;
|
|
198
|
+
hasLabelPrinter?: boolean;
|
|
199
|
+
labelPrinterConfig?: LabelPrinterConfig;
|
|
115
200
|
hasActiveWebshop?: boolean;
|
|
116
201
|
stripeSubscription?: StripeSubscription;
|
|
117
202
|
subscriptionStatus?: string;
|
|
@@ -124,6 +209,7 @@ export default class Merchant extends Base {
|
|
|
124
209
|
featureAccess?: MerchantFeatureAccess | null;
|
|
125
210
|
isMarketplaceSeller?: boolean;
|
|
126
211
|
constructor(props?: any);
|
|
212
|
+
static normalizeLabelPrinterConfig(input?: Partial<LabelPrinterConfig> | Record<string, any> | null): LabelPrinterConfig;
|
|
127
213
|
toObj(): MerchantObj;
|
|
128
214
|
toMerchantMutableData(): MerchantMutableData;
|
|
129
215
|
isManagedMarketplaceMerchant(): boolean;
|
package/lib/models/Merchant.js
CHANGED
|
@@ -90,6 +90,82 @@ class Merchant extends Base_1.default {
|
|
|
90
90
|
if (props === null || props === void 0 ? void 0 : props.hasReceiptPrinter) {
|
|
91
91
|
this.hasReceiptPrinter = props.hasReceiptPrinter;
|
|
92
92
|
}
|
|
93
|
+
if (props === null || props === void 0 ? void 0 : props.hasLabelPrinter) {
|
|
94
|
+
this.hasLabelPrinter = props.hasLabelPrinter;
|
|
95
|
+
}
|
|
96
|
+
if ((props === null || props === void 0 ? void 0 : props.labelPrinterConfig) && typeof props.labelPrinterConfig === 'object') {
|
|
97
|
+
this.labelPrinterConfig = Merchant.normalizeLabelPrinterConfig(props.labelPrinterConfig);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// Coerce arbitrary input into a fully-populated, type-safe LabelPrinterConfig
|
|
101
|
+
// by layering it over the defaults. Migrates legacy `showFields` shapes
|
|
102
|
+
// into the new `layout` schema so older stored configs keep working.
|
|
103
|
+
static normalizeLabelPrinterConfig(input) {
|
|
104
|
+
const defaults = Merchant.LABEL_PRINTER_CONFIG_DEFAULTS;
|
|
105
|
+
const raw = (input || {});
|
|
106
|
+
const protocol = typeof raw.protocol === 'string' && raw.protocol ? raw.protocol : defaults.protocol;
|
|
107
|
+
const symbology = typeof raw.symbology === 'string' && raw.symbology ? raw.symbology : defaults.symbology;
|
|
108
|
+
const layout = (() => {
|
|
109
|
+
const fallback = defaults.layout;
|
|
110
|
+
const rawLayout = raw.layout && typeof raw.layout === 'object' ? raw.layout : null;
|
|
111
|
+
const legacyShowFields = raw.showFields && typeof raw.showFields === 'object' ? raw.showFields : null;
|
|
112
|
+
if (!rawLayout && legacyShowFields) {
|
|
113
|
+
return {
|
|
114
|
+
topElements: fallback.topElements.map((el) => (Object.assign(Object.assign({}, el), { visible: legacyShowFields[el.source] !== false }))),
|
|
115
|
+
barcode: Object.assign({}, fallback.barcode),
|
|
116
|
+
sku: Object.assign(Object.assign({}, fallback.sku), { visible: legacyShowFields.sku !== false }),
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
if (!rawLayout) {
|
|
120
|
+
return {
|
|
121
|
+
topElements: fallback.topElements.map((el) => (Object.assign({}, el))),
|
|
122
|
+
barcode: Object.assign({}, fallback.barcode),
|
|
123
|
+
sku: Object.assign({}, fallback.sku),
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
const rawTop = Array.isArray(rawLayout.topElements) ? rawLayout.topElements : [];
|
|
127
|
+
const topElements = rawTop
|
|
128
|
+
.map((entry, index) => {
|
|
129
|
+
if (!entry || typeof entry !== 'object')
|
|
130
|
+
return null;
|
|
131
|
+
const fb = fallback.topElements.find((e) => e.source === entry.source) ||
|
|
132
|
+
fallback.topElements[index] ||
|
|
133
|
+
fallback.topElements[0];
|
|
134
|
+
return {
|
|
135
|
+
source: typeof entry.source === 'string' ? entry.source : fb.source,
|
|
136
|
+
visible: typeof entry.visible === 'boolean' ? entry.visible : fb.visible,
|
|
137
|
+
fontSize: Number(entry.fontSize) > 0 ? Number(entry.fontSize) : fb.fontSize,
|
|
138
|
+
paddingTop: Number(entry.paddingTop) >= 0 ? Number(entry.paddingTop) : fb.paddingTop,
|
|
139
|
+
transform: entry.transform === 'uppercase' || entry.transform === 'none' ? entry.transform : fb.transform,
|
|
140
|
+
};
|
|
141
|
+
})
|
|
142
|
+
.filter(Boolean);
|
|
143
|
+
const rawBarcode = (rawLayout.barcode || {});
|
|
144
|
+
const barcode = {
|
|
145
|
+
visible: typeof rawBarcode.visible === 'boolean' ? rawBarcode.visible : fallback.barcode.visible,
|
|
146
|
+
heightDots: Number(rawBarcode.heightDots) > 0 ? Number(rawBarcode.heightDots) : fallback.barcode.heightDots,
|
|
147
|
+
moduleWidth: rawBarcode.moduleWidth === 2 ? 2 : 1,
|
|
148
|
+
paddingBottom: Number(rawBarcode.paddingBottom) >= 0 ? Number(rawBarcode.paddingBottom) : fallback.barcode.paddingBottom,
|
|
149
|
+
};
|
|
150
|
+
const rawSku = (rawLayout.sku || {});
|
|
151
|
+
const sku = {
|
|
152
|
+
visible: typeof rawSku.visible === 'boolean' ? rawSku.visible : fallback.sku.visible,
|
|
153
|
+
fontSize: Number(rawSku.fontSize) > 0 ? Number(rawSku.fontSize) : fallback.sku.fontSize,
|
|
154
|
+
};
|
|
155
|
+
return {
|
|
156
|
+
topElements: topElements.length > 0 ? topElements : fallback.topElements.map((el) => (Object.assign({}, el))),
|
|
157
|
+
barcode,
|
|
158
|
+
sku,
|
|
159
|
+
};
|
|
160
|
+
})();
|
|
161
|
+
return {
|
|
162
|
+
protocol,
|
|
163
|
+
widthMm: Number(raw.widthMm) > 0 ? Number(raw.widthMm) : defaults.widthMm,
|
|
164
|
+
heightMm: Number(raw.heightMm) > 0 ? Number(raw.heightMm) : defaults.heightMm,
|
|
165
|
+
dpi: Number(raw.dpi) > 0 ? Number(raw.dpi) : defaults.dpi,
|
|
166
|
+
symbology,
|
|
167
|
+
layout,
|
|
168
|
+
};
|
|
93
169
|
}
|
|
94
170
|
toObj() {
|
|
95
171
|
const mObj = {
|
|
@@ -166,6 +242,12 @@ class Merchant extends Base_1.default {
|
|
|
166
242
|
if (this.hasReceiptPrinter) {
|
|
167
243
|
mObj.hasReceiptPrinter = this.hasReceiptPrinter;
|
|
168
244
|
}
|
|
245
|
+
if (this.hasLabelPrinter) {
|
|
246
|
+
mObj.hasLabelPrinter = this.hasLabelPrinter;
|
|
247
|
+
}
|
|
248
|
+
if (this.labelPrinterConfig) {
|
|
249
|
+
mObj.labelPrinterConfig = this.labelPrinterConfig;
|
|
250
|
+
}
|
|
169
251
|
if (this.organizationNumbers && Object.keys(this.organizationNumbers).length > 0) {
|
|
170
252
|
mObj.organizationNumbers = this.organizationNumbers;
|
|
171
253
|
}
|
|
@@ -222,6 +304,10 @@ Merchant.MERCHANT_ACCOUNT_CLASSES = merchant_constants_1.MERCHANT_ACCOUNT_CLASSE
|
|
|
222
304
|
Merchant.MERCHANT_RELATIONSHIP_TYPES = merchant_constants_1.MERCHANT_RELATIONSHIP_TYPES;
|
|
223
305
|
Merchant.MARKETPLACE_SELLER_CAPABILITIES = merchant_constants_1.MARKETPLACE_SELLER_CAPABILITIES;
|
|
224
306
|
Merchant.DEFAULT_MARKETPLACE_SELLER_CAPABILITIES = merchant_constants_1.DEFAULT_MARKETPLACE_SELLER_CAPABILITIES;
|
|
307
|
+
Merchant.LABEL_PRINTER_BARCODE_SYMBOLOGIES = merchant_constants_1.LABEL_PRINTER_BARCODE_SYMBOLOGIES;
|
|
308
|
+
Merchant.LABEL_PRINTER_PROTOCOLS = merchant_constants_1.LABEL_PRINTER_PROTOCOLS;
|
|
309
|
+
Merchant.LABEL_PRINTER_CONFIG_DEFAULTS = merchant_constants_1.LABEL_PRINTER_CONFIG_DEFAULTS;
|
|
310
|
+
Merchant.DEFAULT_LABEL_LAYOUT = merchant_constants_1.DEFAULT_LABEL_LAYOUT;
|
|
225
311
|
Merchant.INDUSTRY_TYPES = merchant_constants_1.INDUSTRY_TYPES;
|
|
226
312
|
Merchant.UNIT_SYSTEM_TYPES = merchant_constants_1.UNIT_SYSTEM_TYPES;
|
|
227
313
|
Merchant.METRIC_WEIGHT_TYPES = merchant_constants_1.METRIC_WEIGHT_TYPES;
|
package/lib/models/Product.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import Base from '../Base';
|
|
2
|
+
import { ProductPricing, TaxResolution, VariantPricing } from '../types/pricing-types';
|
|
2
3
|
export default class Product extends Base {
|
|
3
4
|
attributes: ProductAttributes;
|
|
4
5
|
filterAttributes: ProductFilterAttributes;
|
|
@@ -9,6 +10,21 @@ export default class Product extends Base {
|
|
|
9
10
|
constructor(props?: any);
|
|
10
11
|
toPartialObj(): ShopifyProduct;
|
|
11
12
|
toObj(): CompleteProduct;
|
|
13
|
+
isUntrackedStock(): boolean;
|
|
14
|
+
hasActiveMarketplaceListing(): boolean;
|
|
15
|
+
getActiveMarketplaceListings(): {
|
|
16
|
+
parentMarketplaceId: string;
|
|
17
|
+
listing: ProductMarketplaceListing;
|
|
18
|
+
}[];
|
|
19
|
+
getMarketplaceListingForParent(parentMarketplaceId: string): ProductMarketplaceListing | null;
|
|
20
|
+
isMarketplaceVisibleTo(parentMarketplaceId: string): boolean;
|
|
21
|
+
getResolvedTaxRate(countryCode: string): TaxResolution;
|
|
22
|
+
getPricing(countryCode: string): ProductPricing;
|
|
23
|
+
getVariantPricing(variantId: string, countryCode: string): VariantPricing | null;
|
|
24
|
+
getEffectiveSku(): string;
|
|
25
|
+
getEffectiveVariantSku(variantId: string): string;
|
|
26
|
+
describeVariant(variantId: string): string;
|
|
27
|
+
diagnoseVariantInventory(): 'no_variants' | 'all_zero_qty' | 'ok';
|
|
12
28
|
toProductInputObjForShopify(location?: string): any;
|
|
13
29
|
toProductInputObjForShopifyV2(locationId: string, weightUnit?: string): any[];
|
|
14
30
|
/**
|
package/lib/models/Product.js
CHANGED
|
@@ -2,8 +2,12 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const Base_1 = require("../Base");
|
|
4
4
|
const product_constants_1 = require("../constants/product-constants");
|
|
5
|
+
const marketplace_constants_1 = require("../constants/marketplace-constants");
|
|
5
6
|
const options_1 = require("../form-states/Product/options");
|
|
6
7
|
const ReRobeProductHelpers_1 = require("../helpers/ReRobeProductHelpers");
|
|
8
|
+
const MarketplaceProductHelpers_1 = require("../helpers/MarketplaceProductHelpers");
|
|
9
|
+
const PricingHelpers_1 = require("../helpers/PricingHelpers");
|
|
10
|
+
const ProductSkuHelpers_1 = require("../helpers/ProductSkuHelpers");
|
|
7
11
|
class Product extends Base_1.default {
|
|
8
12
|
constructor(props) {
|
|
9
13
|
super();
|
|
@@ -44,6 +48,7 @@ class Product extends Base_1.default {
|
|
|
44
48
|
isTaxable: (props === null || props === void 0 ? void 0 : props.isTaxable) || '',
|
|
45
49
|
taxCategory: (props === null || props === void 0 ? void 0 : props.taxCategory) || 'STANDARD',
|
|
46
50
|
productClass: (props === null || props === void 0 ? void 0 : props.productClass) || 'UNIQUE',
|
|
51
|
+
marketplace: MarketplaceProductHelpers_1.default.normalizeMarketplace(props === null || props === void 0 ? void 0 : props.marketplace),
|
|
47
52
|
};
|
|
48
53
|
this.filterAttributes = {
|
|
49
54
|
documentId: (props === null || props === void 0 ? void 0 : props.documentId) || this.utilities.makeRandId(28),
|
|
@@ -164,6 +169,112 @@ class Product extends Base_1.default {
|
|
|
164
169
|
}
|
|
165
170
|
return obj;
|
|
166
171
|
}
|
|
172
|
+
// True for retail products that should be treated as having indefinite
|
|
173
|
+
// stock (cafe items, services, etc.). The web app marks these by writing
|
|
174
|
+
// `stockStatus = 'IN_STOCK_UNLIMITED'` on the product when the merchant
|
|
175
|
+
// toggles "Track stock" off in retail quick entry. Ordering, refund, and
|
|
176
|
+
// payout flows must skip per-location quantity decrements/restores when
|
|
177
|
+
// this returns true. Mirrors the legacy backend `isUntrackedStockProduct`
|
|
178
|
+
// shim so it lives in one place.
|
|
179
|
+
isUntrackedStock() {
|
|
180
|
+
return String(this.filterAttributes.stockStatus || '').trim() === marketplace_constants_1.STOCK_STATUSES.inStockUnlimited;
|
|
181
|
+
}
|
|
182
|
+
// Marketplace listing accessors — all return safe empty values when the
|
|
183
|
+
// product has no marketplace metadata, so legacy products are unaffected.
|
|
184
|
+
hasActiveMarketplaceListing() {
|
|
185
|
+
return this.getActiveMarketplaceListings().length > 0;
|
|
186
|
+
}
|
|
187
|
+
getActiveMarketplaceListings() {
|
|
188
|
+
const marketplace = MarketplaceProductHelpers_1.default.normalizeMarketplace(this.attributes.marketplace);
|
|
189
|
+
return Object.keys(marketplace.listings)
|
|
190
|
+
.map((parentMarketplaceId) => ({ parentMarketplaceId, listing: marketplace.listings[parentMarketplaceId] }))
|
|
191
|
+
.filter(({ listing }) => listing && listing.status !== marketplace_constants_1.MARKETPLACE_LISTING_STATUSES.removed);
|
|
192
|
+
}
|
|
193
|
+
getMarketplaceListingForParent(parentMarketplaceId) {
|
|
194
|
+
if (!parentMarketplaceId)
|
|
195
|
+
return null;
|
|
196
|
+
const marketplace = MarketplaceProductHelpers_1.default.normalizeMarketplace(this.attributes.marketplace);
|
|
197
|
+
return marketplace.listings[parentMarketplaceId] || null;
|
|
198
|
+
}
|
|
199
|
+
isMarketplaceVisibleTo(parentMarketplaceId) {
|
|
200
|
+
const listing = this.getMarketplaceListingForParent(parentMarketplaceId);
|
|
201
|
+
if (!listing)
|
|
202
|
+
return false;
|
|
203
|
+
return listing.status !== marketplace_constants_1.MARKETPLACE_LISTING_STATUSES.removed;
|
|
204
|
+
}
|
|
205
|
+
// Pricing accessors. Resolve once for the merchant's country and project
|
|
206
|
+
// every price-like field into both stored (net) and displayable (gross)
|
|
207
|
+
// forms. Backwards-compatible: legacy callers that read raw
|
|
208
|
+
// `attributes.price` continue to work; new callers can use these to get
|
|
209
|
+
// a single source of truth for gross/net display math without hand-
|
|
210
|
+
// rolling tax-rate lookups in every UI/service.
|
|
211
|
+
getResolvedTaxRate(countryCode) {
|
|
212
|
+
return PricingHelpers_1.default.resolveTaxRate({
|
|
213
|
+
countryCode,
|
|
214
|
+
taxCategory: this.attributes.taxCategory,
|
|
215
|
+
isTaxable: this.attributes.isTaxable,
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
getPricing(countryCode) {
|
|
219
|
+
return PricingHelpers_1.default.getProductPricing({
|
|
220
|
+
isTaxable: this.attributes.isTaxable,
|
|
221
|
+
taxCategory: this.attributes.taxCategory,
|
|
222
|
+
price: this.attributes.price,
|
|
223
|
+
salePrice: this.consignmentAttributes.salePrice,
|
|
224
|
+
compareAtPrice: this.attributes.compareAtPrice,
|
|
225
|
+
costPerItem: this.attributes.costPerItem,
|
|
226
|
+
}, { countryCode });
|
|
227
|
+
}
|
|
228
|
+
getVariantPricing(variantId, countryCode) {
|
|
229
|
+
const variants = (this.attributes.variantInventory || []);
|
|
230
|
+
const variant = variants.find((v) => v && v.id === variantId);
|
|
231
|
+
if (!variant)
|
|
232
|
+
return null;
|
|
233
|
+
return PricingHelpers_1.default.getVariantPricing(variant, {
|
|
234
|
+
isTaxable: this.attributes.isTaxable,
|
|
235
|
+
taxCategory: this.attributes.taxCategory,
|
|
236
|
+
}, { countryCode });
|
|
237
|
+
}
|
|
238
|
+
// SKU and variant-description accessors. Centralize the parent-SKU
|
|
239
|
+
// fallback and the human-readable options join so every label printer,
|
|
240
|
+
// receipt builder, and admin list view that surfaces a variant uses
|
|
241
|
+
// the same rule. Returns '' for missing SKUs / variants rather than
|
|
242
|
+
// throwing — callers were doing their own fallback anyway.
|
|
243
|
+
getEffectiveSku() {
|
|
244
|
+
return String(this.attributes.sku || '').trim();
|
|
245
|
+
}
|
|
246
|
+
getEffectiveVariantSku(variantId) {
|
|
247
|
+
const variants = (this.attributes.variantInventory || []);
|
|
248
|
+
const variant = variants.find((v) => v && v.id === variantId) || null;
|
|
249
|
+
return ProductSkuHelpers_1.default.effectiveVariantSku({ sku: this.attributes.sku }, variant);
|
|
250
|
+
}
|
|
251
|
+
describeVariant(variantId) {
|
|
252
|
+
const variants = (this.attributes.variantInventory || []);
|
|
253
|
+
const variant = variants.find((v) => v && v.id === variantId);
|
|
254
|
+
if (!variant)
|
|
255
|
+
return '';
|
|
256
|
+
return ProductSkuHelpers_1.default.describeVariantOptions(variant.options || {});
|
|
257
|
+
}
|
|
258
|
+
// Diagnose whether a variant-inventory product is purchasable. Mirrors
|
|
259
|
+
// the readiness gate the retail entry exposes as a confirm-before-save
|
|
260
|
+
// dialog: a multivariant product with no variants generated yet, or
|
|
261
|
+
// with every variant carrying zero across all locations, is technically
|
|
262
|
+
// savable but customers won't be able to buy anything from it. Returns
|
|
263
|
+
// 'ok' for non-multivariant products (single-row / unique inventory
|
|
264
|
+
// are handled by other checks).
|
|
265
|
+
diagnoseVariantInventory() {
|
|
266
|
+
const variants = (this.attributes.variantInventory || []);
|
|
267
|
+
if (this.attributes.productClass !== 'MULTIVARIANT')
|
|
268
|
+
return 'ok';
|
|
269
|
+
if (!variants.length)
|
|
270
|
+
return 'no_variants';
|
|
271
|
+
const allZero = variants.every((v) => {
|
|
272
|
+
const locs = Array.isArray(v === null || v === void 0 ? void 0 : v.locations) ? v.locations : [];
|
|
273
|
+
const total = locs.reduce((acc, loc) => acc + (Number(loc === null || loc === void 0 ? void 0 : loc.availableAmount) || 0), 0);
|
|
274
|
+
return total <= 0;
|
|
275
|
+
});
|
|
276
|
+
return allZero ? 'all_zero_qty' : 'ok';
|
|
277
|
+
}
|
|
167
278
|
toProductInputObjForShopify(location) {
|
|
168
279
|
const productInputObj = {
|
|
169
280
|
title: this.attributes.title,
|
|
@@ -505,6 +616,7 @@ class Product extends Base_1.default {
|
|
|
505
616
|
const createdAtTimestamp = this.utilities.sanitizeMillisTimeStamp(this.timestampAttributes.createdAtTimestamp);
|
|
506
617
|
const { createdAtHour, createdAtDay, createdAtMonth, createdAtYear } = this.utilities.formatTimestamp(createdAtTimestamp);
|
|
507
618
|
const [priceSold, commissionFee, productionFee, fulfillmentFee] = ReRobeProductHelpers_1.default.buildReRobeEarningsV2(this.toObj(), isCanonicalMerchant);
|
|
619
|
+
const marketplaceFields = MarketplaceProductHelpers_1.default.buildTypesenseFields(this.attributes.marketplace);
|
|
508
620
|
const merchantValue = commissionFee + productionFee + fulfillmentFee;
|
|
509
621
|
const sellerValue = priceSold - merchantValue;
|
|
510
622
|
const calculatedCommission = merchantValue / priceSold;
|
|
@@ -523,6 +635,10 @@ class Product extends Base_1.default {
|
|
|
523
635
|
isTaxable: this.utilities.sanitizeString(this.attributes.isTaxable),
|
|
524
636
|
merchants: this.utilities.sanitzeStringArr(this.attributes.merchants),
|
|
525
637
|
merchantId: this.utilities.sanitizeString(this.attributes.merchantId),
|
|
638
|
+
marketplaceVisibleToMerchantIds: marketplaceFields.marketplaceVisibleToMerchantIds,
|
|
639
|
+
marketplaceParentMerchantIds: marketplaceFields.marketplaceParentMerchantIds,
|
|
640
|
+
marketplaceRelationshipIds: marketplaceFields.marketplaceRelationshipIds,
|
|
641
|
+
isMarketplaceVisible: marketplaceFields.isMarketplaceVisible,
|
|
526
642
|
price: this.utilities.sanitizeNumber(this.attributes.price),
|
|
527
643
|
merchantValue: this.utilities.sanitizeNumber(merchantValue),
|
|
528
644
|
sellerValue: this.utilities.sanitizeNumber(sellerValue),
|
|
@@ -979,6 +1095,30 @@ class Product extends Base_1.default {
|
|
|
979
1095
|
name: 'merchants',
|
|
980
1096
|
type: 'string[]',
|
|
981
1097
|
},
|
|
1098
|
+
{
|
|
1099
|
+
facet: false,
|
|
1100
|
+
optional: true,
|
|
1101
|
+
name: 'marketplaceVisibleToMerchantIds',
|
|
1102
|
+
type: 'string[]',
|
|
1103
|
+
},
|
|
1104
|
+
{
|
|
1105
|
+
facet: false,
|
|
1106
|
+
optional: true,
|
|
1107
|
+
name: 'marketplaceParentMerchantIds',
|
|
1108
|
+
type: 'string[]',
|
|
1109
|
+
},
|
|
1110
|
+
{
|
|
1111
|
+
facet: false,
|
|
1112
|
+
optional: true,
|
|
1113
|
+
name: 'marketplaceRelationshipIds',
|
|
1114
|
+
type: 'string[]',
|
|
1115
|
+
},
|
|
1116
|
+
{
|
|
1117
|
+
facet: true,
|
|
1118
|
+
optional: true,
|
|
1119
|
+
name: 'isMarketplaceVisible',
|
|
1120
|
+
type: 'bool',
|
|
1121
|
+
},
|
|
982
1122
|
{
|
|
983
1123
|
facet: false,
|
|
984
1124
|
optional: true,
|
|
@@ -1072,6 +1212,17 @@ class Product extends Base_1.default {
|
|
|
1072
1212
|
name: 'sku',
|
|
1073
1213
|
type: 'string',
|
|
1074
1214
|
},
|
|
1215
|
+
{
|
|
1216
|
+
// Flat array of every non-empty `variantInventory[].sku` so a
|
|
1217
|
+
// scanner / search bar can resolve a variant-level barcode to
|
|
1218
|
+
// the parent product. Maintained by the onWriteProduct trigger
|
|
1219
|
+
// (projection of variantInventory.sku → variantSkus). Empty
|
|
1220
|
+
// array for single-SKU products.
|
|
1221
|
+
facet: true,
|
|
1222
|
+
optional: true,
|
|
1223
|
+
name: 'variantSkus',
|
|
1224
|
+
type: 'string[]',
|
|
1225
|
+
},
|
|
1075
1226
|
{
|
|
1076
1227
|
facet: true,
|
|
1077
1228
|
optional: true,
|
|
@@ -52,11 +52,39 @@ type MerchantSystemOnlyMutableData = {
|
|
|
52
52
|
hasAutomatedPayouts?: boolean;
|
|
53
53
|
hasAIQuickList?: boolean;
|
|
54
54
|
hasReceiptPrinter?: boolean;
|
|
55
|
+
hasLabelPrinter?: boolean;
|
|
56
|
+
labelPrinterConfig?: LabelPrinterConfigData;
|
|
55
57
|
hasActiveWebshop?: boolean;
|
|
56
58
|
subscriptionStatus?: string;
|
|
57
59
|
channelPartners?: string[];
|
|
58
60
|
isMarketplaceSeller?: boolean;
|
|
59
61
|
};
|
|
62
|
+
type LabelPrinterConfigData = {
|
|
63
|
+
protocol: string;
|
|
64
|
+
widthMm: number;
|
|
65
|
+
heightMm: number;
|
|
66
|
+
dpi: number;
|
|
67
|
+
symbology: string;
|
|
68
|
+
layout: {
|
|
69
|
+
topElements: {
|
|
70
|
+
source: string;
|
|
71
|
+
visible: boolean;
|
|
72
|
+
fontSize: number;
|
|
73
|
+
paddingTop: number;
|
|
74
|
+
transform: string;
|
|
75
|
+
}[];
|
|
76
|
+
barcode: {
|
|
77
|
+
visible: boolean;
|
|
78
|
+
heightDots: number;
|
|
79
|
+
moduleWidth: 1 | 2;
|
|
80
|
+
paddingBottom: number;
|
|
81
|
+
};
|
|
82
|
+
sku: {
|
|
83
|
+
visible: boolean;
|
|
84
|
+
fontSize: number;
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
};
|
|
60
88
|
type MerchantObj = MerchantMutableData & MerchantSystemOnlyMutableData;
|
|
61
89
|
type MerchantTypes = 'INDIVIDUAL' | 'BUSINESS';
|
|
62
90
|
type MerchantAccountMode = 'STANDALONE' | 'MANAGED';
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { TaxCategoryValue } from '../constants/tax-constants';
|
|
2
|
+
export type IsTaxableValue = 'yes' | 'no' | boolean | string | undefined | null;
|
|
3
|
+
export interface CatalogRateInput {
|
|
4
|
+
countryCode: string;
|
|
5
|
+
taxCategory: string | null | undefined;
|
|
6
|
+
isTaxable: IsTaxableValue;
|
|
7
|
+
}
|
|
8
|
+
export interface FrozenRateInput {
|
|
9
|
+
taxRate: number | string | null | undefined;
|
|
10
|
+
isTaxable: IsTaxableValue;
|
|
11
|
+
}
|
|
12
|
+
export type RateInput = CatalogRateInput | FrozenRateInput;
|
|
13
|
+
export interface TaxResolution {
|
|
14
|
+
rate: number;
|
|
15
|
+
category?: TaxCategoryValue;
|
|
16
|
+
taxable: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface ProductPricing {
|
|
19
|
+
rate: number;
|
|
20
|
+
taxable: boolean;
|
|
21
|
+
priceNet: string;
|
|
22
|
+
salePriceNet: string;
|
|
23
|
+
compareAtPriceNet: string;
|
|
24
|
+
costPerItemNet: string;
|
|
25
|
+
priceGross: string;
|
|
26
|
+
salePriceGross: string;
|
|
27
|
+
compareAtPriceGross: string;
|
|
28
|
+
costPerItemGross: string;
|
|
29
|
+
}
|
|
30
|
+
export interface VariantPricing {
|
|
31
|
+
rate: number;
|
|
32
|
+
taxable: boolean;
|
|
33
|
+
priceNet: string;
|
|
34
|
+
salePriceNet: string;
|
|
35
|
+
compareAtPriceNet: string;
|
|
36
|
+
costPerItemNet: string;
|
|
37
|
+
priceGross: string;
|
|
38
|
+
salePriceGross: string;
|
|
39
|
+
compareAtPriceGross: string;
|
|
40
|
+
costPerItemGross: string;
|
|
41
|
+
}
|
|
42
|
+
export interface OrderLinePricing {
|
|
43
|
+
rate: number;
|
|
44
|
+
taxable: boolean;
|
|
45
|
+
unitPriceNet: string;
|
|
46
|
+
unitPriceGross: string;
|
|
47
|
+
totalPriceNet: string;
|
|
48
|
+
totalPriceGross: string;
|
|
49
|
+
salePriceNet: string;
|
|
50
|
+
salePriceGross: string;
|
|
51
|
+
}
|
|
52
|
+
export interface ProductPricingLike {
|
|
53
|
+
isTaxable?: IsTaxableValue;
|
|
54
|
+
taxCategory?: string | null;
|
|
55
|
+
price?: string | number | null;
|
|
56
|
+
salePrice?: string | number | null;
|
|
57
|
+
compareAtPrice?: string | number | null;
|
|
58
|
+
costPerItem?: string | number | null;
|
|
59
|
+
}
|
|
60
|
+
export interface VariantPricingLike {
|
|
61
|
+
taxable?: IsTaxableValue;
|
|
62
|
+
price?: string | number | null;
|
|
63
|
+
salePrice?: string | number | null;
|
|
64
|
+
compareAtPrice?: string | number | null;
|
|
65
|
+
costPerItem?: string | number | null;
|
|
66
|
+
}
|
|
67
|
+
export interface OrderLinePricingLike {
|
|
68
|
+
isTaxable?: IsTaxableValue;
|
|
69
|
+
taxRate?: number | string | null;
|
|
70
|
+
originalUnitPrice?: {
|
|
71
|
+
amount?: number | string | null;
|
|
72
|
+
} | null;
|
|
73
|
+
originalTotalPrice?: {
|
|
74
|
+
amount?: number | string | null;
|
|
75
|
+
} | null;
|
|
76
|
+
salePrice?: {
|
|
77
|
+
amount?: number | string | null;
|
|
78
|
+
} | number | string | null;
|
|
79
|
+
}
|
|
80
|
+
export interface TaxCategoryOption {
|
|
81
|
+
value: string;
|
|
82
|
+
label: string;
|
|
83
|
+
rate: number;
|
|
84
|
+
rateLabel: string;
|
|
85
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Shared pricing types. Cross-cutting between Product (catalog) and Order
|
|
3
|
+
// (frozen-rate) surfaces, kept dependency-free so they can be consumed by
|
|
4
|
+
// helpers, models, and form-states without circular imports.
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -351,7 +351,93 @@ interface ReRobeOrderLineItem extends OrderLineItem {
|
|
|
351
351
|
discountedPrice?: Money;
|
|
352
352
|
taxAmountWithDiscount?: Money;
|
|
353
353
|
handle?: string;
|
|
354
|
+
marketplace?: MarketplaceLineSnapshot;
|
|
354
355
|
}
|
|
356
|
+
type MarketplaceCommissionBasis = 'LINE_NET_EXCLUDING_TAX' | 'ORIGINAL_COMMISSION_SHARE' | string;
|
|
357
|
+
type MarketplaceLineAmounts = {
|
|
358
|
+
lineNetAmount: number;
|
|
359
|
+
discountAmount: number;
|
|
360
|
+
taxableAmount: number;
|
|
361
|
+
taxAmount: number;
|
|
362
|
+
lineGrossAmount: number;
|
|
363
|
+
originalProductCommissionAmount: number;
|
|
364
|
+
marketplaceCommissionAmount: number;
|
|
365
|
+
stripeFeeAllocatedAmount: number;
|
|
366
|
+
ribbnFeeAllocatedAmount: number;
|
|
367
|
+
sellerProceedsAmount: number;
|
|
368
|
+
managedMerchantProceedsAmount: number;
|
|
369
|
+
marketplaceProceedsAmount: number;
|
|
370
|
+
};
|
|
371
|
+
type MarketplaceVariantSnapshot = {
|
|
372
|
+
variantId: string;
|
|
373
|
+
sku: string;
|
|
374
|
+
options: VariantOptions;
|
|
375
|
+
price: string;
|
|
376
|
+
compareAtPrice?: string | null;
|
|
377
|
+
salePrice?: string | null;
|
|
378
|
+
isOnSale?: 'yes' | 'no' | null;
|
|
379
|
+
taxable?: 'yes' | 'no' | null;
|
|
380
|
+
taxCategory: string;
|
|
381
|
+
locations: InventoryLocation[];
|
|
382
|
+
};
|
|
383
|
+
type MarketplaceLineSnapshot = {
|
|
384
|
+
isMarketplaceItem: boolean;
|
|
385
|
+
parentMerchantId: string;
|
|
386
|
+
managedMerchantId: string;
|
|
387
|
+
relationshipId: string;
|
|
388
|
+
productId: string;
|
|
389
|
+
variantId?: string;
|
|
390
|
+
sellerDisplayName?: string;
|
|
391
|
+
lineDisplayTitle?: string;
|
|
392
|
+
originalProductCommissionRate: string;
|
|
393
|
+
marketplaceCommissionRate: string;
|
|
394
|
+
marketplaceCommissionBasis: MarketplaceCommissionBasis;
|
|
395
|
+
quantity: number;
|
|
396
|
+
currencyCode: string;
|
|
397
|
+
amounts: MarketplaceLineAmounts;
|
|
398
|
+
variant?: MarketplaceVariantSnapshot;
|
|
399
|
+
};
|
|
400
|
+
type MarketplaceReturnAdjustment = {
|
|
401
|
+
quantityReturned: number;
|
|
402
|
+
amounts: MarketplaceLineAmounts;
|
|
403
|
+
remainingQuantity: number;
|
|
404
|
+
};
|
|
405
|
+
type MarketplaceLedgerStatus = 'PENDING_RETURN_PERIOD' | 'PAYABLE' | 'PAID_OUT' | 'RETURNED_BEFORE_PAYOUT' | 'REFUNDED_AFTER_PAYOUT' | 'TRANSFER_REVERSED' | string;
|
|
406
|
+
type MarketplaceLedgerLifecycleTimestamps = {
|
|
407
|
+
createdAtTimestamp?: number | null;
|
|
408
|
+
pendingReturnPeriodAtTimestamp?: number | null;
|
|
409
|
+
payableAtTimestamp?: number | null;
|
|
410
|
+
paidOutAtTimestamp?: number | null;
|
|
411
|
+
returnedBeforePayoutAtTimestamp?: number | null;
|
|
412
|
+
refundedAfterPayoutAtTimestamp?: number | null;
|
|
413
|
+
transferReversedAtTimestamp?: number | null;
|
|
414
|
+
updatedAtTimestamp?: number | null;
|
|
415
|
+
};
|
|
416
|
+
type MarketplaceLedgerEntry = {
|
|
417
|
+
documentId?: string;
|
|
418
|
+
parentOrderId: string;
|
|
419
|
+
parentOrderLineItemId?: string;
|
|
420
|
+
parentMerchantId: string;
|
|
421
|
+
managedMerchantId: string;
|
|
422
|
+
relationshipId: string;
|
|
423
|
+
productId: string;
|
|
424
|
+
variantId?: string;
|
|
425
|
+
status: MarketplaceLedgerStatus;
|
|
426
|
+
snapshot: MarketplaceLineSnapshot;
|
|
427
|
+
returnDeadlineTimestamp?: number | null;
|
|
428
|
+
lifecycle: MarketplaceLedgerLifecycleTimestamps;
|
|
429
|
+
};
|
|
430
|
+
type MarketplaceFeeAllocation = {
|
|
431
|
+
lineKey: string;
|
|
432
|
+
amount: number;
|
|
433
|
+
};
|
|
434
|
+
type MarketplaceFeeBasketLine = {
|
|
435
|
+
lineKey: string;
|
|
436
|
+
sellerMerchantId: string;
|
|
437
|
+
lineNetAmount: number;
|
|
438
|
+
taxableAmount?: number;
|
|
439
|
+
quantity?: number;
|
|
440
|
+
};
|
|
355
441
|
type OrderLineItemConnection = {
|
|
356
442
|
edges: OrderLineItemEdge[];
|
|
357
443
|
};
|