rerobe-js-orm 4.9.0 → 4.9.2
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/helpers/ProductVariantHelpers.d.ts +17 -0
- package/lib/helpers/ProductVariantHelpers.js +90 -0
- package/lib/index.d.ts +2 -1
- package/lib/index.js +3 -1
- package/lib/models/Product.d.ts +11 -0
- package/lib/models/Product.js +32 -0
- package/lib/types/rerobe-product-types.d.ts +1 -0
- package/package.json +4 -2
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
type VariantOptions = {
|
|
2
|
+
[k: string]: string;
|
|
3
|
+
};
|
|
4
|
+
export default class ProductVariantHelpers {
|
|
5
|
+
static optionsLabel(options: VariantOptions | null | undefined, separator?: string): string;
|
|
6
|
+
static variantLabel(lineItem: any, separator?: string): string;
|
|
7
|
+
static resolveChosenVariant(product: any, { variantId, sku }?: {
|
|
8
|
+
variantId?: string;
|
|
9
|
+
sku?: string;
|
|
10
|
+
}): any;
|
|
11
|
+
static mapOptionsToAttributes(options: VariantOptions | null | undefined): {
|
|
12
|
+
size?: string;
|
|
13
|
+
standardSize?: string;
|
|
14
|
+
color?: string;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Variant display + business logic — the single home for turning a chosen
|
|
3
|
+
// MULTIVARIANT variant into:
|
|
4
|
+
// (a) a human-readable label for cart / order / receipt surfaces,
|
|
5
|
+
// (b) concrete product attribute fields when cloning a variant into a
|
|
6
|
+
// standalone UNIQUE unit, and
|
|
7
|
+
// (c) the resolved variantInventory row a sale / clone refers to.
|
|
8
|
+
//
|
|
9
|
+
// Pure + dependency-free so backend, web, and mobile share one rule instead of
|
|
10
|
+
// each reimplementing the options join, the Shopify "Default Title" exclusion,
|
|
11
|
+
// and the find-by-id-then-sku fallback. `variantOptions` stays the source of
|
|
12
|
+
// truth for what was sold; mapOptionsToAttributes only mirrors the well-known
|
|
13
|
+
// axes onto filter attributes so a sold unit looks like a normal product.
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
// Shopify emits this placeholder title for products with no real variants; it
|
|
16
|
+
// should never render as a chosen variant.
|
|
17
|
+
const SHOPIFY_DEFAULT_TITLE = 'default title';
|
|
18
|
+
// Display default. Cart / order detail / receipt all use the middot; the legacy
|
|
19
|
+
// label printer keeps ProductSkuHelpers.describeVariantOptions (" / ").
|
|
20
|
+
const DEFAULT_SEPARATOR = ' · ';
|
|
21
|
+
class ProductVariantHelpers {
|
|
22
|
+
// Join a raw options map's values, e.g. { Size: 'M', Color: 'R' } -> "M · R".
|
|
23
|
+
// Empty/absent values are dropped. Returns '' for a non-object input.
|
|
24
|
+
static optionsLabel(options, separator = DEFAULT_SEPARATOR) {
|
|
25
|
+
if (!options || typeof options !== 'object' || Array.isArray(options)) {
|
|
26
|
+
return '';
|
|
27
|
+
}
|
|
28
|
+
return Object.keys(options)
|
|
29
|
+
.map((k) => String(options[k] == null ? '' : options[k]).trim())
|
|
30
|
+
.filter(Boolean)
|
|
31
|
+
.join(separator);
|
|
32
|
+
}
|
|
33
|
+
// Human-readable variant label for a line item / variant-bearing object.
|
|
34
|
+
// Prefers the chosen `variantOptions`, then a Shopify `variant.title` /
|
|
35
|
+
// `variantTitle` (ignoring the "Default Title" placeholder). Returns '' when
|
|
36
|
+
// there is no variant to show.
|
|
37
|
+
static variantLabel(lineItem, separator = DEFAULT_SEPARATOR) {
|
|
38
|
+
if (!lineItem || typeof lineItem !== 'object')
|
|
39
|
+
return '';
|
|
40
|
+
const fromOptions = this.optionsLabel(lineItem.variantOptions, separator);
|
|
41
|
+
if (fromOptions)
|
|
42
|
+
return fromOptions;
|
|
43
|
+
const title = (lineItem.variant && lineItem.variant.title) || lineItem.variantTitle || '';
|
|
44
|
+
const trimmed = String(title).trim();
|
|
45
|
+
if (trimmed && trimmed.toLowerCase() !== SHOPIFY_DEFAULT_TITLE) {
|
|
46
|
+
return trimmed;
|
|
47
|
+
}
|
|
48
|
+
return '';
|
|
49
|
+
}
|
|
50
|
+
// Resolve which variantInventory row a sale / clone refers to. Variants are
|
|
51
|
+
// identified by their stable `id`; sku is often null on POS-created variants,
|
|
52
|
+
// so id is primary and sku is the fallback. Returns null when unresolved.
|
|
53
|
+
static resolveChosenVariant(product, { variantId = '', sku = '' } = {}) {
|
|
54
|
+
const variants = product && Array.isArray(product.variantInventory) ? product.variantInventory : [];
|
|
55
|
+
const byId = variantId ? variants.find((v) => v && String(v.id || '') === String(variantId)) : null;
|
|
56
|
+
if (byId)
|
|
57
|
+
return byId;
|
|
58
|
+
const bySku = sku ? variants.find((v) => v && String(v.sku || '').trim() === String(sku).trim()) : null;
|
|
59
|
+
return bySku || null;
|
|
60
|
+
}
|
|
61
|
+
// Best-effort map of a variant's chosen options onto concrete product filter
|
|
62
|
+
// attributes, so a cloned single-unit product looks like a normal product to
|
|
63
|
+
// search / filtering / display. Only the well-known axes are mapped (size,
|
|
64
|
+
// color — English + Swedish keys, case-insensitive); unknown axes are left to
|
|
65
|
+
// `variantOptions`, which remains authoritative. Empty values never overwrite.
|
|
66
|
+
static mapOptionsToAttributes(options) {
|
|
67
|
+
const out = {};
|
|
68
|
+
if (!options || typeof options !== 'object' || Array.isArray(options)) {
|
|
69
|
+
return out;
|
|
70
|
+
}
|
|
71
|
+
Object.keys(options).forEach((rawKey) => {
|
|
72
|
+
const key = String(rawKey || '')
|
|
73
|
+
.trim()
|
|
74
|
+
.toLowerCase();
|
|
75
|
+
const value = String(options[rawKey] == null ? '' : options[rawKey]).trim();
|
|
76
|
+
if (!value)
|
|
77
|
+
return;
|
|
78
|
+
if (key === 'size' || key === 'storlek') {
|
|
79
|
+
out.size = value;
|
|
80
|
+
out.standardSize = value;
|
|
81
|
+
}
|
|
82
|
+
else if (key === 'color' || key === 'colour' || key === 'färg' || key === 'farg') {
|
|
83
|
+
out.color = value;
|
|
84
|
+
}
|
|
85
|
+
// Any other axis intentionally stays only in variantOptions.
|
|
86
|
+
});
|
|
87
|
+
return out;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
exports.default = ProductVariantHelpers;
|
package/lib/index.d.ts
CHANGED
|
@@ -50,11 +50,12 @@ import * as MarketplaceOrderHelpers from './helpers/marketplace/MarketplaceOrder
|
|
|
50
50
|
import TaxHelpers from './helpers/TaxHelpers';
|
|
51
51
|
import PricingHelpers from './helpers/PricingHelpers';
|
|
52
52
|
import ProductSkuHelpers, { DEFAULT_SKU_LENGTH, SKU_ALPHABET } from './helpers/ProductSkuHelpers';
|
|
53
|
+
import ProductVariantHelpers from './helpers/ProductVariantHelpers';
|
|
53
54
|
import ProductInventoryHelpers, { PLACEHOLDER_VARIANT_ID } from './helpers/ProductInventoryHelpers';
|
|
54
55
|
import RetailProductFactory from './factories/Product/RetailProductFactory';
|
|
55
56
|
import { FALLBACK_TAX_COUNTRY_CODE, TAX_CATEGORIES, TAX_CATEGORY_ALIASES, TAX_CATEGORY_BASE_LABELS, TAX_CATEGORY_RATES } from './constants/tax-constants';
|
|
56
57
|
import { ADMIN_SIMPLIFIED_STATES, ADMIN_STATES, PRODUCT_CLASS_VALUES, PRODUCT_STATES, PRODUCT_STATE_LABELS, RETAIL_EDITABLE_PRODUCT_STATES, getProductStateLabel, getRetailEditableProductStateOptions } from './constants/product-constants';
|
|
57
|
-
export { RibbnFile, ProductFromAlgoliaJSONDoc, ProductFromShopifyWebhookJSONDoc, ProductFromShopifyJSClientJSONDoc, ProductFormStateFactory, ProductCollectionFormStateFactory, ProductCollectionHelpers, SellRequestFormStateFactory, PickUpFormStateFactory, AddressFormStateFactory, UserFormStateFactory, UserFromShopifyWebhookJSONDoc, UserFromAuthTemplateMethod, DraftOrderFromMirakl, DraftOrderFromApp, ChatRoomFromNewUserSignUp, KlarnaSessionFactory, Product, ProductStateManager, Order, OrderFromShopifyWebhook, OrderFromShopifyAdminApi, OrderFromShopifyStorefrontApi, OrderFromApp, OrderFromTraderaEmail, OrderFormStateFactory, RefundFormStateFactory, PayoutAccount, PayoutAccountFormState, Merchant, MERCHANT_ACCOUNT_MODES, MERCHANT_ACCOUNT_CLASSES, MERCHANT_RELATIONSHIP_TYPES, MARKETPLACE_SELLER_CAPABILITIES, DEFAULT_MARKETPLACE_SELLER_CAPABILITIES, MerchantFormState, MerchantFormStateFactory, MerchantConfigAutomatedPayouts, MerchantConfigAutomatedPayoutsFormState, ReRobeProductHelpers, MarketplaceProductHelpers, MarketplaceLedgerHelpers, MarketplaceLegacyAdapters, MarketplaceLineDisplayHelpers, MarketplaceOrderHelpers, MARKETPLACE_LISTING_STATUSES, MARKETPLACE_COMMISSION_BASES, MARKETPLACE_RELATIONSHIP_TYPES, MARKETPLACE_FEE_TYPES, MARKETPLACE_FEE_ALLOCATION_BASES, MARKETPLACE_LEDGER_STATUSES, MARKETPLACE_INVENTORY_POLICY_KINDS, MARKETPLACE_SELLER_DEFAULT_COMMISSION, STOCK_STATUSES, DEFAULT_MARKETPLACE_LISTING_STATUS, DEFAULT_MARKETPLACE_COMMISSION_BASIS, DEFAULT_MARKETPLACE_RELATIONSHIP_TYPE, DEFAULT_STRIPE_FEE_ALLOCATION_BASIS, DEFAULT_RIBBN_FEE_ALLOCATION_BASIS, DEFAULT_MARKETPLACE_LEDGER_STATUS, User, AnalyticsHelpers, OrderHelpers, WebhookFormState, MerchantWebPage, ShopifyMerchantAccount, CustomerNotification, TaxHelpers, PricingHelpers, ProductSkuHelpers, ProductInventoryHelpers, RetailProductFactory, SKU_ALPHABET, DEFAULT_SKU_LENGTH, PLACEHOLDER_VARIANT_ID, TAX_CATEGORIES, TAX_CATEGORY_RATES, TAX_CATEGORY_BASE_LABELS, TAX_CATEGORY_ALIASES, FALLBACK_TAX_COUNTRY_CODE, PRODUCT_STATES, PRODUCT_STATE_LABELS, PRODUCT_CLASS_VALUES, ADMIN_STATES, ADMIN_SIMPLIFIED_STATES, RETAIL_EDITABLE_PRODUCT_STATES, getProductStateLabel, getRetailEditableProductStateOptions, };
|
|
58
|
+
export { RibbnFile, ProductFromAlgoliaJSONDoc, ProductFromShopifyWebhookJSONDoc, ProductFromShopifyJSClientJSONDoc, ProductFormStateFactory, ProductCollectionFormStateFactory, ProductCollectionHelpers, SellRequestFormStateFactory, PickUpFormStateFactory, AddressFormStateFactory, UserFormStateFactory, UserFromShopifyWebhookJSONDoc, UserFromAuthTemplateMethod, DraftOrderFromMirakl, DraftOrderFromApp, ChatRoomFromNewUserSignUp, KlarnaSessionFactory, Product, ProductStateManager, Order, OrderFromShopifyWebhook, OrderFromShopifyAdminApi, OrderFromShopifyStorefrontApi, OrderFromApp, OrderFromTraderaEmail, OrderFormStateFactory, RefundFormStateFactory, PayoutAccount, PayoutAccountFormState, Merchant, MERCHANT_ACCOUNT_MODES, MERCHANT_ACCOUNT_CLASSES, MERCHANT_RELATIONSHIP_TYPES, MARKETPLACE_SELLER_CAPABILITIES, DEFAULT_MARKETPLACE_SELLER_CAPABILITIES, MerchantFormState, MerchantFormStateFactory, MerchantConfigAutomatedPayouts, MerchantConfigAutomatedPayoutsFormState, ReRobeProductHelpers, MarketplaceProductHelpers, MarketplaceLedgerHelpers, MarketplaceLegacyAdapters, MarketplaceLineDisplayHelpers, MarketplaceOrderHelpers, MARKETPLACE_LISTING_STATUSES, MARKETPLACE_COMMISSION_BASES, MARKETPLACE_RELATIONSHIP_TYPES, MARKETPLACE_FEE_TYPES, MARKETPLACE_FEE_ALLOCATION_BASES, MARKETPLACE_LEDGER_STATUSES, MARKETPLACE_INVENTORY_POLICY_KINDS, MARKETPLACE_SELLER_DEFAULT_COMMISSION, STOCK_STATUSES, DEFAULT_MARKETPLACE_LISTING_STATUS, DEFAULT_MARKETPLACE_COMMISSION_BASIS, DEFAULT_MARKETPLACE_RELATIONSHIP_TYPE, DEFAULT_STRIPE_FEE_ALLOCATION_BASIS, DEFAULT_RIBBN_FEE_ALLOCATION_BASIS, DEFAULT_MARKETPLACE_LEDGER_STATUS, User, AnalyticsHelpers, OrderHelpers, WebhookFormState, MerchantWebPage, ShopifyMerchantAccount, CustomerNotification, TaxHelpers, PricingHelpers, ProductSkuHelpers, ProductVariantHelpers, ProductInventoryHelpers, RetailProductFactory, SKU_ALPHABET, DEFAULT_SKU_LENGTH, PLACEHOLDER_VARIANT_ID, TAX_CATEGORIES, TAX_CATEGORY_RATES, TAX_CATEGORY_BASE_LABELS, TAX_CATEGORY_ALIASES, FALLBACK_TAX_COUNTRY_CODE, PRODUCT_STATES, PRODUCT_STATE_LABELS, PRODUCT_CLASS_VALUES, ADMIN_STATES, ADMIN_SIMPLIFIED_STATES, RETAIL_EDITABLE_PRODUCT_STATES, getProductStateLabel, getRetailEditableProductStateOptions, };
|
|
58
59
|
export type { PlaceholderVariantInput, PlaceholderVariantInventory, PlaceholderVariantLocation, } from './helpers/ProductInventoryHelpers';
|
|
59
60
|
export type { RetailOwnershipInput, RetailAccountingInput, RetailLocationInput, ClothingDetailsInput, NonClothingDetailsInput, OneOfAKindClothingInput, MultivariantClothingInput, TrackedRetailInput, UntrackedRetailInput, } from './factories/Product/RetailProductFactory';
|
|
60
61
|
export type { TaxCategoryValue } from './constants/tax-constants';
|
package/lib/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MARKETPLACE_FEE_ALLOCATION_BASES = exports.MARKETPLACE_FEE_TYPES = exports.MARKETPLACE_RELATIONSHIP_TYPES = exports.MARKETPLACE_COMMISSION_BASES = exports.MARKETPLACE_LISTING_STATUSES = exports.MarketplaceOrderHelpers = exports.MarketplaceLineDisplayHelpers = exports.MarketplaceLegacyAdapters = exports.MarketplaceLedgerHelpers = exports.MarketplaceProductHelpers = exports.ReRobeProductHelpers = exports.MerchantConfigAutomatedPayoutsFormState = exports.MerchantConfigAutomatedPayouts = exports.MerchantFormStateFactory = exports.MerchantFormState = exports.DEFAULT_MARKETPLACE_SELLER_CAPABILITIES = exports.MARKETPLACE_SELLER_CAPABILITIES = exports.MERCHANT_RELATIONSHIP_TYPES = exports.MERCHANT_ACCOUNT_CLASSES = exports.MERCHANT_ACCOUNT_MODES = exports.Merchant = exports.PayoutAccountFormState = exports.PayoutAccount = exports.RefundFormStateFactory = exports.OrderFormStateFactory = exports.OrderFromTraderaEmail = exports.OrderFromApp = exports.OrderFromShopifyStorefrontApi = exports.OrderFromShopifyAdminApi = exports.OrderFromShopifyWebhook = exports.Order = exports.ProductStateManager = exports.Product = exports.KlarnaSessionFactory = exports.ChatRoomFromNewUserSignUp = exports.DraftOrderFromApp = exports.DraftOrderFromMirakl = exports.UserFromAuthTemplateMethod = exports.UserFromShopifyWebhookJSONDoc = exports.UserFormStateFactory = exports.AddressFormStateFactory = exports.PickUpFormStateFactory = exports.SellRequestFormStateFactory = exports.ProductCollectionHelpers = exports.ProductCollectionFormStateFactory = exports.ProductFormStateFactory = exports.ProductFromShopifyJSClientJSONDoc = exports.ProductFromShopifyWebhookJSONDoc = exports.ProductFromAlgoliaJSONDoc = exports.RibbnFile = void 0;
|
|
4
|
-
exports.getRetailEditableProductStateOptions = exports.getProductStateLabel = exports.RETAIL_EDITABLE_PRODUCT_STATES = exports.ADMIN_SIMPLIFIED_STATES = exports.ADMIN_STATES = exports.PRODUCT_CLASS_VALUES = exports.PRODUCT_STATE_LABELS = exports.PRODUCT_STATES = exports.FALLBACK_TAX_COUNTRY_CODE = exports.TAX_CATEGORY_ALIASES = exports.TAX_CATEGORY_BASE_LABELS = exports.TAX_CATEGORY_RATES = exports.TAX_CATEGORIES = exports.PLACEHOLDER_VARIANT_ID = exports.DEFAULT_SKU_LENGTH = exports.SKU_ALPHABET = exports.RetailProductFactory = exports.ProductInventoryHelpers = exports.ProductSkuHelpers = exports.PricingHelpers = exports.TaxHelpers = exports.CustomerNotification = exports.ShopifyMerchantAccount = exports.MerchantWebPage = exports.WebhookFormState = exports.OrderHelpers = exports.AnalyticsHelpers = exports.User = exports.DEFAULT_MARKETPLACE_LEDGER_STATUS = exports.DEFAULT_RIBBN_FEE_ALLOCATION_BASIS = exports.DEFAULT_STRIPE_FEE_ALLOCATION_BASIS = exports.DEFAULT_MARKETPLACE_RELATIONSHIP_TYPE = exports.DEFAULT_MARKETPLACE_COMMISSION_BASIS = exports.DEFAULT_MARKETPLACE_LISTING_STATUS = exports.STOCK_STATUSES = exports.MARKETPLACE_SELLER_DEFAULT_COMMISSION = exports.MARKETPLACE_INVENTORY_POLICY_KINDS = exports.MARKETPLACE_LEDGER_STATUSES = void 0;
|
|
4
|
+
exports.getRetailEditableProductStateOptions = exports.getProductStateLabel = exports.RETAIL_EDITABLE_PRODUCT_STATES = exports.ADMIN_SIMPLIFIED_STATES = exports.ADMIN_STATES = exports.PRODUCT_CLASS_VALUES = exports.PRODUCT_STATE_LABELS = exports.PRODUCT_STATES = exports.FALLBACK_TAX_COUNTRY_CODE = exports.TAX_CATEGORY_ALIASES = exports.TAX_CATEGORY_BASE_LABELS = exports.TAX_CATEGORY_RATES = exports.TAX_CATEGORIES = exports.PLACEHOLDER_VARIANT_ID = exports.DEFAULT_SKU_LENGTH = exports.SKU_ALPHABET = exports.RetailProductFactory = exports.ProductInventoryHelpers = exports.ProductVariantHelpers = exports.ProductSkuHelpers = exports.PricingHelpers = exports.TaxHelpers = exports.CustomerNotification = exports.ShopifyMerchantAccount = exports.MerchantWebPage = exports.WebhookFormState = exports.OrderHelpers = exports.AnalyticsHelpers = exports.User = exports.DEFAULT_MARKETPLACE_LEDGER_STATUS = exports.DEFAULT_RIBBN_FEE_ALLOCATION_BASIS = exports.DEFAULT_STRIPE_FEE_ALLOCATION_BASIS = exports.DEFAULT_MARKETPLACE_RELATIONSHIP_TYPE = exports.DEFAULT_MARKETPLACE_COMMISSION_BASIS = exports.DEFAULT_MARKETPLACE_LISTING_STATUS = exports.STOCK_STATUSES = exports.MARKETPLACE_SELLER_DEFAULT_COMMISSION = exports.MARKETPLACE_INVENTORY_POLICY_KINDS = exports.MARKETPLACE_LEDGER_STATUSES = void 0;
|
|
5
5
|
const ProductFromShopifyJSClientJSONDoc_1 = require("./factories/Product/ProductFromShopifyJSClientJSONDoc");
|
|
6
6
|
exports.ProductFromShopifyJSClientJSONDoc = ProductFromShopifyJSClientJSONDoc_1.default;
|
|
7
7
|
const ProductFromAlgoliaJSONDoc_1 = require("./factories/Product/ProductFromAlgoliaJSONDoc");
|
|
@@ -126,6 +126,8 @@ const ProductSkuHelpers_1 = require("./helpers/ProductSkuHelpers");
|
|
|
126
126
|
exports.ProductSkuHelpers = ProductSkuHelpers_1.default;
|
|
127
127
|
Object.defineProperty(exports, "DEFAULT_SKU_LENGTH", { enumerable: true, get: function () { return ProductSkuHelpers_1.DEFAULT_SKU_LENGTH; } });
|
|
128
128
|
Object.defineProperty(exports, "SKU_ALPHABET", { enumerable: true, get: function () { return ProductSkuHelpers_1.SKU_ALPHABET; } });
|
|
129
|
+
const ProductVariantHelpers_1 = require("./helpers/ProductVariantHelpers");
|
|
130
|
+
exports.ProductVariantHelpers = ProductVariantHelpers_1.default;
|
|
129
131
|
const ProductInventoryHelpers_1 = require("./helpers/ProductInventoryHelpers");
|
|
130
132
|
exports.ProductInventoryHelpers = ProductInventoryHelpers_1.default;
|
|
131
133
|
Object.defineProperty(exports, "PLACEHOLDER_VARIANT_ID", { enumerable: true, get: function () { return ProductInventoryHelpers_1.PLACEHOLDER_VARIANT_ID; } });
|
package/lib/models/Product.d.ts
CHANGED
|
@@ -24,6 +24,17 @@ export default class Product extends Base {
|
|
|
24
24
|
getEffectiveSku(): string;
|
|
25
25
|
getEffectiveVariantSku(variantId: string): string;
|
|
26
26
|
describeVariant(variantId: string): string;
|
|
27
|
+
buildVariantCloneData({ chosenVariantId, chosenVariantSku, price, imageUrls, overrides, }?: {
|
|
28
|
+
chosenVariantId?: string;
|
|
29
|
+
chosenVariantSku?: string;
|
|
30
|
+
price?: string | number;
|
|
31
|
+
imageUrls?: string[];
|
|
32
|
+
overrides?: {
|
|
33
|
+
[k: string]: any;
|
|
34
|
+
};
|
|
35
|
+
}): {
|
|
36
|
+
[k: string]: any;
|
|
37
|
+
};
|
|
27
38
|
diagnoseVariantInventory(): 'no_variants' | 'all_zero_qty' | 'ok';
|
|
28
39
|
toProductInputObjForShopify(location?: string): any;
|
|
29
40
|
toProductInputObjForShopifyV2(locationId: string, weightUnit?: string): any[];
|
package/lib/models/Product.js
CHANGED
|
@@ -8,6 +8,7 @@ const ReRobeProductHelpers_1 = require("../helpers/ReRobeProductHelpers");
|
|
|
8
8
|
const MarketplaceProductHelpers_1 = require("../helpers/MarketplaceProductHelpers");
|
|
9
9
|
const PricingHelpers_1 = require("../helpers/PricingHelpers");
|
|
10
10
|
const ProductSkuHelpers_1 = require("../helpers/ProductSkuHelpers");
|
|
11
|
+
const ProductVariantHelpers_1 = require("../helpers/ProductVariantHelpers");
|
|
11
12
|
class Product extends Base_1.default {
|
|
12
13
|
constructor(props) {
|
|
13
14
|
super();
|
|
@@ -255,6 +256,33 @@ class Product extends Base_1.default {
|
|
|
255
256
|
return '';
|
|
256
257
|
return ProductSkuHelpers_1.default.describeVariantOptions(variant.options || {});
|
|
257
258
|
}
|
|
259
|
+
// Build the data for ONE concrete, single-unit clone of a chosen variant —
|
|
260
|
+
// a UNIQUE product carrying the variant's identity (options / sku / price)
|
|
261
|
+
// and back-linked to this parent so its stock can be decremented at sale
|
|
262
|
+
// time. The clone is HIDDEN until sold (kept out of the seller's catalog /
|
|
263
|
+
// counts; reaped by the abandoned-clone cron if the cart is dropped) and
|
|
264
|
+
// tagged `clonedProduct` + `variantClone`. The chosen options are also
|
|
265
|
+
// mirrored onto concrete filter attributes (size / color) so the unit looks
|
|
266
|
+
// like a normal product to search / display, while `variantOptions` stays
|
|
267
|
+
// authoritative.
|
|
268
|
+
//
|
|
269
|
+
// Pure: returns the clone's data object. The caller assigns a documentId and
|
|
270
|
+
// persists it (and may create N copies for quantity > 1).
|
|
271
|
+
buildVariantCloneData({ chosenVariantId = '', chosenVariantSku = '', price = '', imageUrls = [], overrides = {}, } = {}) {
|
|
272
|
+
const parent = this.toObj();
|
|
273
|
+
const chosenVariant = ProductVariantHelpers_1.default.resolveChosenVariant(parent, {
|
|
274
|
+
variantId: chosenVariantId,
|
|
275
|
+
sku: chosenVariantSku,
|
|
276
|
+
});
|
|
277
|
+
const variantOptions = (chosenVariant && chosenVariant.options) || {};
|
|
278
|
+
const resolvedPrice = price || (chosenVariant && chosenVariant.price) || parent.price || '0';
|
|
279
|
+
const resolvedImageUrls = Array.isArray(imageUrls) && imageUrls.length ? imageUrls : parent.imageUrls || [];
|
|
280
|
+
const resolvedSku = (chosenVariant && chosenVariant.sku) || parent.sku || '';
|
|
281
|
+
const systemTags = Array.isArray(parent.systemTags)
|
|
282
|
+
? parent.systemTags.filter((tag) => tag !== 'templateProduct')
|
|
283
|
+
: [];
|
|
284
|
+
return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, parent), { productClass: product_constants_1.PRODUCT_CLASS_VALUES.UNIQUE, variantInventory: [], status: product_constants_1.PRODUCT_STATES.hidden, systemTags: [...new Set([...systemTags, 'clonedProduct', 'variantClone'])], price: String(resolvedPrice), imageUrls: resolvedImageUrls, sku: resolvedSku }), ProductVariantHelpers_1.default.mapOptionsToAttributes(variantOptions)), { variantOptions, originalVariantProductId: parent.documentId || '', chosenVariantId: (chosenVariant && chosenVariant.id) || chosenVariantId || '', chosenVariantSku: resolvedSku, bookedTimestamp: null, openTimestamp: null }), overrides);
|
|
285
|
+
}
|
|
258
286
|
// Diagnose whether a variant-inventory product is purchasable. Mirrors
|
|
259
287
|
// the readiness gate the retail entry exposes as a confirm-before-save
|
|
260
288
|
// dialog: a multivariant product with no variants generated yet, or
|
|
@@ -633,6 +661,10 @@ class Product extends Base_1.default {
|
|
|
633
661
|
primaryAgeCategory: this.utilities.sanitizeString(this.filterAttributes.primaryAgeCategory),
|
|
634
662
|
isOnSale: this.utilities.sanitizeString(this.consignmentAttributes.isOnSale),
|
|
635
663
|
isTaxable: this.utilities.sanitizeString(this.attributes.isTaxable),
|
|
664
|
+
// Reduced-rate gross display in product lists needs the category (12% FOOD
|
|
665
|
+
// / 6% CULTURE etc.); without it the list defaults to STANDARD (25%) and
|
|
666
|
+
// over-states the listing price for reduced-rate products.
|
|
667
|
+
taxCategory: this.utilities.sanitizeString(this.attributes.taxCategory),
|
|
636
668
|
merchants: this.utilities.sanitzeStringArr(this.attributes.merchants),
|
|
637
669
|
merchantId: this.utilities.sanitizeString(this.attributes.merchantId),
|
|
638
670
|
marketplaceVisibleToMerchantIds: marketplaceFields.marketplaceVisibleToMerchantIds,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rerobe-js-orm",
|
|
3
|
-
"version": "4.9.
|
|
3
|
+
"version": "4.9.2",
|
|
4
4
|
"description": "ReRobe's Javascript ORM Framework",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -21,7 +21,9 @@
|
|
|
21
21
|
"type": "git",
|
|
22
22
|
"url": "git+https://github.com/ReRobe/rerobe-object-factories.git"
|
|
23
23
|
},
|
|
24
|
-
"keywords": [
|
|
24
|
+
"keywords": [
|
|
25
|
+
"ribbn"
|
|
26
|
+
],
|
|
25
27
|
"license": "ISC",
|
|
26
28
|
"bugs": {
|
|
27
29
|
"url": "https://github.com/ReRobe/rerobe-product/issues"
|