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.
Files changed (72) hide show
  1. package/lib/constants/marketplace-constants.d.ts +52 -0
  2. package/lib/constants/marketplace-constants.js +82 -0
  3. package/lib/constants/merchant-constants.d.ts +35 -0
  4. package/lib/constants/merchant-constants.js +35 -1
  5. package/lib/constants/product-constants.d.ts +6 -0
  6. package/lib/constants/product-constants.js +43 -1
  7. package/lib/constants/tax-constants.d.ts +19 -0
  8. package/lib/constants/tax-constants.js +70 -0
  9. package/lib/factories/Product/RetailProductFactory.d.ts +102 -0
  10. package/lib/factories/Product/RetailProductFactory.js +260 -0
  11. package/lib/form-states/Product/ProductFormState.d.ts +9 -0
  12. package/lib/form-states/Product/ProductFormState.js +46 -0
  13. package/lib/helpers/MarketplaceProductHelpers.d.ts +181 -0
  14. package/lib/helpers/MarketplaceProductHelpers.js +555 -0
  15. package/lib/helpers/OrderHelpers.d.ts +5 -2
  16. package/lib/helpers/OrderHelpers.js +18 -4
  17. package/lib/helpers/PricingHelpers.d.ts +29 -0
  18. package/lib/helpers/PricingHelpers.js +215 -0
  19. package/lib/helpers/ProductInventoryHelpers.d.ts +31 -0
  20. package/lib/helpers/ProductInventoryHelpers.js +66 -0
  21. package/lib/helpers/ProductSkuHelpers.d.ts +13 -0
  22. package/lib/helpers/ProductSkuHelpers.js +70 -0
  23. package/lib/helpers/TaxHelpers.d.ts +15 -0
  24. package/lib/helpers/TaxHelpers.js +76 -0
  25. package/lib/helpers/marketplace/CommissionPolicy.d.ts +20 -0
  26. package/lib/helpers/marketplace/CommissionPolicy.js +9 -0
  27. package/lib/helpers/marketplace/CommissionPolicyRegistry.d.ts +4 -0
  28. package/lib/helpers/marketplace/CommissionPolicyRegistry.js +21 -0
  29. package/lib/helpers/marketplace/EvenPerSellerStripeFeePolicy.d.ts +5 -0
  30. package/lib/helpers/marketplace/EvenPerSellerStripeFeePolicy.js +46 -0
  31. package/lib/helpers/marketplace/FeeAllocationPolicy.d.ts +10 -0
  32. package/lib/helpers/marketplace/FeeAllocationPolicy.js +36 -0
  33. package/lib/helpers/marketplace/FeeAllocationPolicyRegistry.d.ts +6 -0
  34. package/lib/helpers/marketplace/FeeAllocationPolicyRegistry.js +26 -0
  35. package/lib/helpers/marketplace/InventoryPolicy.d.ts +18 -0
  36. package/lib/helpers/marketplace/InventoryPolicy.js +7 -0
  37. package/lib/helpers/marketplace/InventoryPolicyRegistry.d.ts +4 -0
  38. package/lib/helpers/marketplace/InventoryPolicyRegistry.js +29 -0
  39. package/lib/helpers/marketplace/LineNetCommissionPolicy.d.ts +5 -0
  40. package/lib/helpers/marketplace/LineNetCommissionPolicy.js +25 -0
  41. package/lib/helpers/marketplace/MarketplaceErrors.d.ts +6 -0
  42. package/lib/helpers/marketplace/MarketplaceErrors.js +21 -0
  43. package/lib/helpers/marketplace/MarketplaceLedgerHelpers.d.ts +40 -0
  44. package/lib/helpers/marketplace/MarketplaceLedgerHelpers.js +120 -0
  45. package/lib/helpers/marketplace/MarketplaceLegacyAdapters.d.ts +53 -0
  46. package/lib/helpers/marketplace/MarketplaceLegacyAdapters.js +99 -0
  47. package/lib/helpers/marketplace/MarketplaceLineDisplayHelpers.d.ts +40 -0
  48. package/lib/helpers/marketplace/MarketplaceLineDisplayHelpers.js +125 -0
  49. package/lib/helpers/marketplace/MarketplaceOrderHelpers.d.ts +15 -0
  50. package/lib/helpers/marketplace/MarketplaceOrderHelpers.js +77 -0
  51. package/lib/helpers/marketplace/MultivariantLocationInventoryPolicy.d.ts +9 -0
  52. package/lib/helpers/marketplace/MultivariantLocationInventoryPolicy.js +60 -0
  53. package/lib/helpers/marketplace/OneOfAKindInventoryPolicy.d.ts +9 -0
  54. package/lib/helpers/marketplace/OneOfAKindInventoryPolicy.js +55 -0
  55. package/lib/helpers/marketplace/OriginalCommissionShareCommissionPolicy.d.ts +5 -0
  56. package/lib/helpers/marketplace/OriginalCommissionShareCommissionPolicy.js +26 -0
  57. package/lib/helpers/marketplace/ProportionalToLineNetPolicy.d.ts +5 -0
  58. package/lib/helpers/marketplace/ProportionalToLineNetPolicy.js +35 -0
  59. package/lib/helpers/marketplace/UntrackedStockInventoryPolicy.d.ts +7 -0
  60. package/lib/helpers/marketplace/UntrackedStockInventoryPolicy.js +23 -0
  61. package/lib/index.d.ts +18 -1
  62. package/lib/index.js +56 -1
  63. package/lib/models/Merchant.d.ts +86 -0
  64. package/lib/models/Merchant.js +86 -0
  65. package/lib/models/Product.d.ts +16 -0
  66. package/lib/models/Product.js +151 -0
  67. package/lib/types/merchant-types.d.ts +28 -0
  68. package/lib/types/pricing-types.d.ts +85 -0
  69. package/lib/types/pricing-types.js +5 -0
  70. package/lib/types/rerobe-order-types.d.ts +86 -0
  71. package/lib/types/rerobe-product-types.d.ts +19 -0
  72. package/package.json +1 -1
@@ -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;
@@ -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;
@@ -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
  /**
@@ -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
  };