rerobe-js-orm 4.9.4 → 4.9.5

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.
@@ -22,7 +22,6 @@ class MerchantFromFormState extends MerchantFactory_1.default {
22
22
  primaryDomain: fs.fields.primaryDomain.inputValue,
23
23
  socialLinks: fs.fields.socialLinks.selectedValue,
24
24
  organizationNumber: fs.fields.organizationNumber.inputValue,
25
- returnPolicy: fs.fields.returnPolicy.inputValue,
26
25
  };
27
26
  // Include organizationNumbers if it has entries
28
27
  const orgNumbers = (_a = fs.fields.organizationNumbers) === null || _a === void 0 ? void 0 : _a.selectedValue;
@@ -16,7 +16,6 @@ class MerchantFormState extends FormState_1.default {
16
16
  this.fields.legalName = this.fieldFactory('textInput', 'legalName');
17
17
  this.fields.organizationNumber = this.fieldFactory('textInput', 'organizationNumber');
18
18
  this.fields.organizationNumbers = this.fieldFactory('singleSelect', 'organizationNumbers');
19
- this.fields.returnPolicy = this.fieldFactory('textInput', 'returnPolicy');
20
19
  this.fields.phone = this.fieldFactory('textInput', 'phone');
21
20
  this.fields.address = this.fieldFactory('singleSelect', 'address');
22
21
  this.fields.currency = this.fieldFactory('singleSelect', 'currency', options_1.currencyOptions);
@@ -6,6 +6,7 @@ const order_constants_1 = require("../constants/order-constants");
6
6
  const translations_1 = require("../translations");
7
7
  const CryptoPolyfill_1 = require("./CryptoPolyfill");
8
8
  const PricingHelpers_1 = require("./PricingHelpers");
9
+ const ReturnPolicyHelpers_1 = require("./ReturnPolicyHelpers");
9
10
  const MarketplaceLineDisplayHelpers_1 = require("./marketplace/MarketplaceLineDisplayHelpers");
10
11
  class OrderHelpers {
11
12
  // Frozen-rate pricing snapshot for a single order line item. Reads
@@ -594,7 +595,7 @@ class OrderHelpers {
594
595
  };
595
596
  }
596
597
  buildReceiptObjFromOrder({ order, merchant, merchantLogoUrl = '', receiptNumber = '', additionalInfo = '', isRefund = false, refundId = null, originalReceiptNumber = null, includeMarketplaceSellerPrefix = false, }) {
597
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x;
598
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y;
598
599
  const { address: merchantAddress, legalName, name, contactEmail, phone = '', organizationNumber = '', primaryDomain, currency: storeCurrencyCode, returnPolicy, } = merchant;
599
600
  const currencyCode = ((_a = order.totalPricePresentment) === null || _a === void 0 ? void 0 : _a.currencyCode) || storeCurrencyCode;
600
601
  const presentmentLocale = (0, Utilities_1.getPresentmentLocaleByCurrencyCode)(currencyCode);
@@ -691,8 +692,14 @@ class OrderHelpers {
691
692
  translations_1.refundPurchaseTranslations[presentmentLocale] || translations_1.refundPurchaseTranslations['en-US'];
692
693
  }
693
694
  let info = additionalInfo;
694
- if (returnPolicy && !isRefund) {
695
- info = `${returnPolicy}`;
695
+ // Derive the return-policy line from the structured policy for the order's
696
+ // sales channel (legacy free-text policies pass through unchanged). Never
697
+ // shown on refund receipts.
698
+ const returnPolicyText = isRefund
699
+ ? ''
700
+ : ReturnPolicyHelpers_1.default.returnPolicyReceiptText(returnPolicy, (_d = order.salesChannel) !== null && _d !== void 0 ? _d : undefined);
701
+ if (returnPolicyText) {
702
+ info = returnPolicyText;
696
703
  if (additionalInfo) {
697
704
  info = `${info}\n\n${additionalInfo}`;
698
705
  }
@@ -708,29 +715,29 @@ class OrderHelpers {
708
715
  organizationNumber,
709
716
  primaryDomain, storeUrl: `https://${primaryDomain}`, orderDate: (0, Utilities_1.getFormattedTimestamp)(presentmentLocale, order === null || order === void 0 ? void 0 : order.createdAtTimestamp), receiptNumber, additionalInfo: info, isRefund, originalReceiptNumber: originalReceiptNumber || null, originalReceiptLabel: translations_1.originalReceiptTranslations[presentmentLocale] || translations_1.originalReceiptTranslations['en-US'], lineItems: buildLineItems(), subTotal: (0, Utilities_1.formatPrice)({
710
717
  currencyCode,
711
- amount: (_f = negateForRefund((_e = (_d = order.subtotalPricePresentment) === null || _d === void 0 ? void 0 : _d.amount) !== null && _e !== void 0 ? _e : '')) !== null && _f !== void 0 ? _f : '',
718
+ amount: (_g = negateForRefund((_f = (_e = order.subtotalPricePresentment) === null || _e === void 0 ? void 0 : _e.amount) !== null && _f !== void 0 ? _f : '')) !== null && _g !== void 0 ? _g : '',
712
719
  fractionDigits: 2,
713
720
  }), total: (0, Utilities_1.formatPrice)({
714
721
  currencyCode,
715
- amount: (_j = negateForRefund((_h = (_g = order.totalPricePresentment) === null || _g === void 0 ? void 0 : _g.amount) !== null && _h !== void 0 ? _h : '')) !== null && _j !== void 0 ? _j : '',
722
+ amount: (_k = negateForRefund((_j = (_h = order.totalPricePresentment) === null || _h === void 0 ? void 0 : _h.amount) !== null && _j !== void 0 ? _j : '')) !== null && _k !== void 0 ? _k : '',
716
723
  fractionDigits: 2,
717
724
  }), amountPaid: (0, Utilities_1.formatPrice)({
718
725
  currencyCode,
719
- amount: (_m = negateForRefund((_l = (_k = order.totalPricePresentment) === null || _k === void 0 ? void 0 : _k.amount) !== null && _l !== void 0 ? _l : '')) !== null && _m !== void 0 ? _m : '',
726
+ amount: (_o = negateForRefund((_m = (_l = order.totalPricePresentment) === null || _l === void 0 ? void 0 : _l.amount) !== null && _m !== void 0 ? _m : '')) !== null && _o !== void 0 ? _o : '',
720
727
  fractionDigits: 2,
721
728
  }), tax: (0, Utilities_1.formatPrice)({
722
729
  currencyCode,
723
- amount: (_q = negateForRefund((_p = (_o = order.totalTaxPresentment) === null || _o === void 0 ? void 0 : _o.amount) !== null && _p !== void 0 ? _p : '')) !== null && _q !== void 0 ? _q : '',
730
+ amount: (_r = negateForRefund((_q = (_p = order.totalTaxPresentment) === null || _p === void 0 ? void 0 : _p.amount) !== null && _q !== void 0 ? _q : '')) !== null && _r !== void 0 ? _r : '',
724
731
  fractionDigits: 2,
725
- }), taxRates: formattedTaxRates }, paymentTerminalInfo), receiptLabels), (Number(((_r = order.totalRefundedPresentment) === null || _r === void 0 ? void 0 : _r.amount) || 0) > 0 && {
732
+ }), taxRates: formattedTaxRates }, paymentTerminalInfo), receiptLabels), (Number(((_s = order.totalRefundedPresentment) === null || _s === void 0 ? void 0 : _s.amount) || 0) > 0 && {
726
733
  totalRefunded: (0, Utilities_1.formatPrice)({
727
734
  currencyCode,
728
- amount: (_t = (_s = order.totalRefundedPresentment) === null || _s === void 0 ? void 0 : _s.amount) !== null && _t !== void 0 ? _t : '',
735
+ amount: (_u = (_t = order.totalRefundedPresentment) === null || _t === void 0 ? void 0 : _t.amount) !== null && _u !== void 0 ? _u : '',
729
736
  fractionDigits: 2,
730
737
  }),
731
738
  netPayment: (0, Utilities_1.formatPrice)({
732
739
  currencyCode,
733
- amount: Number((_v = (_u = order.totalPricePresentment) === null || _u === void 0 ? void 0 : _u.amount) !== null && _v !== void 0 ? _v : 0) - Number((_x = (_w = order.totalRefundedPresentment) === null || _w === void 0 ? void 0 : _w.amount) !== null && _x !== void 0 ? _x : 0),
740
+ amount: Number((_w = (_v = order.totalPricePresentment) === null || _v === void 0 ? void 0 : _v.amount) !== null && _w !== void 0 ? _w : 0) - Number((_y = (_x = order.totalRefundedPresentment) === null || _x === void 0 ? void 0 : _x.amount) !== null && _y !== void 0 ? _y : 0),
734
741
  fractionDigits: 2,
735
742
  }),
736
743
  refundLineItems: (order.refunds || []).flatMap((refund) => (refund.refundLineItems || []).map((item) => {
@@ -0,0 +1,40 @@
1
+ type ReturnEvaluation = {
2
+ allowed: boolean;
3
+ reason: string;
4
+ windowEndMillis?: number;
5
+ };
6
+ export default class ReturnPolicyHelpers {
7
+ static CHANNELS: {
8
+ inStore: string;
9
+ online: string;
10
+ };
11
+ static REASONS: {
12
+ noPolicy: string;
13
+ noChannelMapping: string;
14
+ noSoldTimestamp: string;
15
+ returnsNotAllowed: string;
16
+ windowExpired: string;
17
+ withinWindow: string;
18
+ };
19
+ private static normChannel;
20
+ static parse(raw: any): ReturnPolicy | null;
21
+ static isConfigured(raw: any): boolean;
22
+ static defaultPolicy(): ReturnPolicy;
23
+ static channelKeyForSalesChannel(salesChannel: string): string | null;
24
+ static getChannelPolicy(raw: any, salesChannel: string): ReturnPolicyChannel | null;
25
+ static resolveSoldState(raw: any, salesChannel: string): string;
26
+ static getReturnWindowEndMillis(raw: any, salesChannel: string, soldAtMillis: number): number | null;
27
+ static evaluateReturn({ raw, salesChannel, soldAtMillis, nowMillis, }: {
28
+ raw: any;
29
+ salesChannel: string;
30
+ soldAtMillis?: number;
31
+ nowMillis?: number;
32
+ }): ReturnEvaluation;
33
+ static returnPolicyReceiptText(raw: any, salesChannel?: string): string;
34
+ static resolveEffectiveReturnPolicy({ ownPolicyRaw, marketplaceDefaultRaw, isManaged, }: {
35
+ ownPolicyRaw?: any;
36
+ marketplaceDefaultRaw?: any;
37
+ isManaged?: boolean;
38
+ }): ReturnPolicy | null;
39
+ }
40
+ export {};
@@ -0,0 +1,186 @@
1
+ "use strict";
2
+ // Return-policy business logic — the single home for everything that reads a
3
+ // merchant's `returnPolicy`:
4
+ // (a) parse/normalize the stored value (tolerant of legacy free-text strings
5
+ // and partial/malformed objects),
6
+ // (b) resolve the product sold-state for a sale (drives seller-payout hold),
7
+ // (c) enforce the return window on a refund/return,
8
+ // (d) derive human-readable receipt text,
9
+ // (e) resolve the *effective* policy for a managed (marketplace) merchant.
10
+ //
11
+ // Pure + dependency-free (constants only) so backend, web, and mobile share one
12
+ // rule instead of each reimplementing the channel join and the sold-state
13
+ // branch. Channel keys are the RETURN_POLICY_TYPES values (IN_STORE / ONLINE);
14
+ // SALES_CHANNEL_TO_RETURN_POLICY_MAPPING maps a sale's salesChannel onto them.
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ const product_constants_1 = require("../constants/product-constants");
17
+ const order_constants_1 = require("../constants/order-constants");
18
+ const MS_PER_DAY = 24 * 60 * 60 * 1000;
19
+ // Why a refund/return was allowed or blocked. Stable strings so callers can
20
+ // switch on them to build user-facing messages.
21
+ const REASONS = {
22
+ noPolicy: 'NO_POLICY', // merchant never configured a policy -> no enforcement
23
+ noChannelMapping: 'NO_CHANNEL_MAPPING', // unknown sales channel -> no enforcement
24
+ noSoldTimestamp: 'NO_SOLD_TIMESTAMP', // can't determine sale time -> don't block
25
+ returnsNotAllowed: 'RETURNS_NOT_ALLOWED', // channel explicitly disallows returns
26
+ windowExpired: 'RETURN_WINDOW_EXPIRED', // past returnPeriodDays from the sale
27
+ withinWindow: 'WITHIN_WINDOW', // ok: inside the window
28
+ };
29
+ class ReturnPolicyHelpers {
30
+ // Normalize a single raw channel entry. An absent/invalid entry becomes a
31
+ // concrete "returns off" channel. A present object defaults `allowed` to true
32
+ // when the flag is missing (faithful to the legacy `allowed !== false` rule);
33
+ // the settings UI always writes the flag explicitly.
34
+ static normChannel(ch) {
35
+ if (!ch || typeof ch !== 'object' || Array.isArray(ch)) {
36
+ return { allowed: false, returnPeriodDays: 0 };
37
+ }
38
+ const days = Number(ch.returnPeriodDays);
39
+ return {
40
+ allowed: ch.allowed !== false,
41
+ returnPeriodDays: days > 0 ? Math.floor(days) : 0,
42
+ };
43
+ }
44
+ // Parse a raw stored value into a structured ReturnPolicy, or null when the
45
+ // merchant has not configured a (structured) policy. Returns null for:
46
+ // undefined/null, '', legacy free-text strings, and objects that carry
47
+ // neither IN_STORE nor ONLINE. Idempotent on an already-parsed policy.
48
+ static parse(raw) {
49
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
50
+ return null;
51
+ }
52
+ const hasInStore = Object.prototype.hasOwnProperty.call(raw, order_constants_1.RETURN_POLICY_TYPES.inStore);
53
+ const hasOnline = Object.prototype.hasOwnProperty.call(raw, order_constants_1.RETURN_POLICY_TYPES.online);
54
+ if (!hasInStore && !hasOnline) {
55
+ return null;
56
+ }
57
+ return {
58
+ IN_STORE: this.normChannel(raw[order_constants_1.RETURN_POLICY_TYPES.inStore]),
59
+ ONLINE: this.normChannel(raw[order_constants_1.RETURN_POLICY_TYPES.online]),
60
+ };
61
+ }
62
+ // Is a raw value a configured (structured) policy?
63
+ static isConfigured(raw) {
64
+ return this.parse(raw) !== null;
65
+ }
66
+ // A fully-shaped "everything off" policy — a sensible starting point for the
67
+ // settings UI (merchant opts in per channel).
68
+ static defaultPolicy() {
69
+ return {
70
+ IN_STORE: { allowed: false, returnPeriodDays: 0 },
71
+ ONLINE: { allowed: false, returnPeriodDays: 0 },
72
+ };
73
+ }
74
+ // Map a sale's salesChannel to its policy channel key (IN_STORE | ONLINE), or
75
+ // null when the channel isn't mapped.
76
+ static channelKeyForSalesChannel(salesChannel) {
77
+ return order_constants_1.SALES_CHANNEL_TO_RETURN_POLICY_MAPPING[salesChannel] || null;
78
+ }
79
+ // The normalized channel policy that applies to a sale, or null when there's
80
+ // no configured policy / no channel mapping.
81
+ static getChannelPolicy(raw, salesChannel) {
82
+ const policy = this.parse(raw);
83
+ if (!policy)
84
+ return null;
85
+ const key = this.channelKeyForSalesChannel(salesChannel);
86
+ if (!key)
87
+ return null;
88
+ return policy[key] || null;
89
+ }
90
+ // Decide a sold product's state for a sale. Mirrors the legacy inline rule:
91
+ // no policy / unmapped channel -> SOLD (backwards compatible)
92
+ // returns disallowed OR 0-day -> SOLD_SELLER_PAYOUT_PROCESSING (pay now)
93
+ // returns allowed WITH a window -> SOLD (payout held through the window)
94
+ static resolveSoldState(raw, salesChannel) {
95
+ const channel = this.getChannelPolicy(raw, salesChannel);
96
+ if (!channel)
97
+ return product_constants_1.PRODUCT_STATES.sold;
98
+ if (!channel.allowed || channel.returnPeriodDays <= 0) {
99
+ return product_constants_1.PRODUCT_STATES.soldSellerPayoutProcessing;
100
+ }
101
+ return product_constants_1.PRODUCT_STATES.sold;
102
+ }
103
+ // The instant (ms) a return window closes for a sale, or null when there's no
104
+ // applicable window (no policy / not allowed / 0-day / no sale time).
105
+ static getReturnWindowEndMillis(raw, salesChannel, soldAtMillis) {
106
+ const channel = this.getChannelPolicy(raw, salesChannel);
107
+ if (!channel || !channel.allowed || channel.returnPeriodDays <= 0)
108
+ return null;
109
+ const soldAt = Number(soldAtMillis);
110
+ if (!(soldAt > 0))
111
+ return null;
112
+ return soldAt + channel.returnPeriodDays * MS_PER_DAY;
113
+ }
114
+ // Evaluate whether a return/refund should be permitted under the policy.
115
+ // Conservative by design: when nothing is configured (no policy, unmapped
116
+ // channel, or unknown sale time) it ALLOWS, so adding enforcement never
117
+ // breaks refunds for merchants who haven't opted in. It only blocks when the
118
+ // merchant's configured policy says so (disallowed channel or expired window).
119
+ static evaluateReturn({ raw, salesChannel, soldAtMillis, nowMillis, }) {
120
+ const policy = this.parse(raw);
121
+ if (!policy)
122
+ return { allowed: true, reason: REASONS.noPolicy };
123
+ const key = this.channelKeyForSalesChannel(salesChannel);
124
+ if (!key)
125
+ return { allowed: true, reason: REASONS.noChannelMapping };
126
+ const channel = policy[key];
127
+ if (!channel.allowed)
128
+ return { allowed: false, reason: REASONS.returnsNotAllowed };
129
+ if (channel.returnPeriodDays <= 0) {
130
+ // Allowed but no window configured -> nothing qualifies after the sale.
131
+ return { allowed: false, reason: REASONS.windowExpired, windowEndMillis: Number(soldAtMillis) || 0 };
132
+ }
133
+ const soldAt = Number(soldAtMillis);
134
+ if (!(soldAt > 0))
135
+ return { allowed: true, reason: REASONS.noSoldTimestamp };
136
+ const windowEndMillis = soldAt + channel.returnPeriodDays * MS_PER_DAY;
137
+ const now = Number(nowMillis) > 0 ? Number(nowMillis) : Date.now();
138
+ if (now <= windowEndMillis)
139
+ return { allowed: true, reason: REASONS.withinWindow, windowEndMillis };
140
+ return { allowed: false, reason: REASONS.windowExpired, windowEndMillis };
141
+ }
142
+ // Human-readable line for a receipt. Legacy free-text strings pass through
143
+ // unchanged. For a structured policy, prefer the sale's channel; without a
144
+ // channel, summarize whichever channel(s) accept returns. Returns '' when
145
+ // there's nothing meaningful to print (no policy, or returns not accepted).
146
+ static returnPolicyReceiptText(raw, salesChannel) {
147
+ if (typeof raw === 'string')
148
+ return raw.trim();
149
+ const policy = this.parse(raw);
150
+ if (!policy)
151
+ return '';
152
+ const lineFor = (ch) => {
153
+ if (!ch || !ch.allowed || ch.returnPeriodDays <= 0)
154
+ return '';
155
+ return `${ch.returnPeriodDays} day return policy`;
156
+ };
157
+ if (salesChannel) {
158
+ const key = this.channelKeyForSalesChannel(salesChannel);
159
+ if (key)
160
+ return lineFor(policy[key]);
161
+ }
162
+ const inStore = lineFor(policy.IN_STORE);
163
+ const online = lineFor(policy.ONLINE);
164
+ if (inStore && online) {
165
+ return inStore === online ? inStore : `In-store: ${inStore}\nOnline: ${online}`;
166
+ }
167
+ return inStore || online || '';
168
+ }
169
+ // Resolve the policy that actually governs a merchant. For a managed
170
+ // (marketplace) merchant the marketplace-wide default governs, falling back to
171
+ // the merchant's own policy only when the marketplace hasn't set one. For a
172
+ // standalone merchant, their own policy governs.
173
+ //
174
+ // FUTURE (per-merchant override): to let managed merchants override the
175
+ // marketplace default, flip the managed branch to
176
+ // `this.parse(ownPolicyRaw) || this.parse(marketplaceDefaultRaw)`.
177
+ static resolveEffectiveReturnPolicy({ ownPolicyRaw, marketplaceDefaultRaw, isManaged, }) {
178
+ if (isManaged) {
179
+ return this.parse(marketplaceDefaultRaw) || this.parse(ownPolicyRaw);
180
+ }
181
+ return this.parse(ownPolicyRaw);
182
+ }
183
+ }
184
+ ReturnPolicyHelpers.CHANNELS = order_constants_1.RETURN_POLICY_TYPES; // { inStore: 'IN_STORE', online: 'ONLINE' }
185
+ ReturnPolicyHelpers.REASONS = REASONS;
186
+ exports.default = ReturnPolicyHelpers;
package/lib/index.d.ts CHANGED
@@ -51,11 +51,12 @@ 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
53
  import ProductVariantHelpers from './helpers/ProductVariantHelpers';
54
+ import ReturnPolicyHelpers from './helpers/ReturnPolicyHelpers';
54
55
  import ProductInventoryHelpers, { PLACEHOLDER_VARIANT_ID } from './helpers/ProductInventoryHelpers';
55
56
  import RetailProductFactory from './factories/Product/RetailProductFactory';
56
57
  import { FALLBACK_TAX_COUNTRY_CODE, TAX_CATEGORIES, TAX_CATEGORY_ALIASES, TAX_CATEGORY_BASE_LABELS, TAX_CATEGORY_RATES } from './constants/tax-constants';
57
58
  import { ADMIN_SIMPLIFIED_STATES, ADMIN_STATES, PRODUCT_CLASS_VALUES, PRODUCT_STATES, PRODUCT_STATE_LABELS, RETAIL_EDITABLE_PRODUCT_STATES, getProductStateLabel, getRetailEditableProductStateOptions } from './constants/product-constants';
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, };
59
+ 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, ReturnPolicyHelpers, 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, };
59
60
  export type { PlaceholderVariantInput, PlaceholderVariantInventory, PlaceholderVariantLocation, } from './helpers/ProductInventoryHelpers';
60
61
  export type { RetailOwnershipInput, RetailAccountingInput, RetailLocationInput, ClothingDetailsInput, NonClothingDetailsInput, OneOfAKindClothingInput, MultivariantClothingInput, TrackedRetailInput, UntrackedRetailInput, } from './factories/Product/RetailProductFactory';
61
62
  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.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;
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.ReturnPolicyHelpers = 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");
@@ -128,6 +128,8 @@ Object.defineProperty(exports, "DEFAULT_SKU_LENGTH", { enumerable: true, get: fu
128
128
  Object.defineProperty(exports, "SKU_ALPHABET", { enumerable: true, get: function () { return ProductSkuHelpers_1.SKU_ALPHABET; } });
129
129
  const ProductVariantHelpers_1 = require("./helpers/ProductVariantHelpers");
130
130
  exports.ProductVariantHelpers = ProductVariantHelpers_1.default;
131
+ const ReturnPolicyHelpers_1 = require("./helpers/ReturnPolicyHelpers");
132
+ exports.ReturnPolicyHelpers = ReturnPolicyHelpers_1.default;
131
133
  const ProductInventoryHelpers_1 = require("./helpers/ProductInventoryHelpers");
132
134
  exports.ProductInventoryHelpers = ProductInventoryHelpers_1.default;
133
135
  Object.defineProperty(exports, "PLACEHOLDER_VARIANT_ID", { enumerable: true, get: function () { return ProductInventoryHelpers_1.PLACEHOLDER_VARIANT_ID; } });
@@ -190,7 +190,8 @@ export default class Merchant extends Base {
190
190
  hasStripeBluetoothReader?: boolean;
191
191
  organizationNumber?: string;
192
192
  organizationNumbers?: Record<string, string>;
193
- returnPolicy?: string;
193
+ returnPolicy?: ReturnPolicy | string;
194
+ managedReturnPolicyDefault?: ReturnPolicy;
194
195
  stripeRegion?: string;
195
196
  hasAutomatedPayouts?: boolean;
196
197
  hasAIQuickList?: boolean;
@@ -210,6 +211,8 @@ export default class Merchant extends Base {
210
211
  isMarketplaceSeller?: boolean;
211
212
  constructor(props?: any);
212
213
  static normalizeLabelPrinterConfig(input?: Partial<LabelPrinterConfig> | Record<string, any> | null): LabelPrinterConfig;
214
+ getReturnPolicy(): ReturnPolicy | null;
215
+ getManagedReturnPolicyDefault(): ReturnPolicy | null;
213
216
  toObj(): MerchantObj;
214
217
  toMerchantMutableData(): MerchantMutableData;
215
218
  isManagedMarketplaceMerchant(): boolean;
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const Base_1 = require("../Base");
4
4
  const merchant_constants_1 = require("../constants/merchant-constants");
5
+ const ReturnPolicyHelpers_1 = require("../helpers/ReturnPolicyHelpers");
5
6
  class Merchant extends Base_1.default {
6
7
  constructor(props) {
7
8
  super();
@@ -53,6 +54,9 @@ class Merchant extends Base_1.default {
53
54
  this.organizationNumbers = props.organizationNumbers;
54
55
  }
55
56
  this.returnPolicy = (props === null || props === void 0 ? void 0 : props.returnPolicy) || '';
57
+ if ((props === null || props === void 0 ? void 0 : props.managedReturnPolicyDefault) && typeof props.managedReturnPolicyDefault === 'object') {
58
+ this.managedReturnPolicyDefault = props.managedReturnPolicyDefault;
59
+ }
56
60
  this.subscriptionStatus = (props === null || props === void 0 ? void 0 : props.subscriptionStatus) || merchant_constants_1.SUBSCRIPTION_STATUSES.trialing;
57
61
  this.hasActiveWebshop = (props === null || props === void 0 ? void 0 : props.hasActiveWebshop) || false;
58
62
  this.accountMode = (props === null || props === void 0 ? void 0 : props.accountMode) || Merchant.MERCHANT_ACCOUNT_MODES.standalone;
@@ -167,6 +171,16 @@ class Merchant extends Base_1.default {
167
171
  layout,
168
172
  };
169
173
  }
174
+ // This merchant's own return policy, parsed/normalized (null when unset or a
175
+ // legacy free-text string). See ReturnPolicyHelpers for the resolution rules.
176
+ getReturnPolicy() {
177
+ return ReturnPolicyHelpers_1.default.parse(this.returnPolicy);
178
+ }
179
+ // The marketplace-wide default this merchant (as a marketplace/parent) applies
180
+ // to its managed merchants, parsed/normalized (null when unset).
181
+ getManagedReturnPolicyDefault() {
182
+ return ReturnPolicyHelpers_1.default.parse(this.managedReturnPolicyDefault);
183
+ }
170
184
  toObj() {
171
185
  const mObj = {
172
186
  name: this.name,
@@ -209,6 +223,9 @@ class Merchant extends Base_1.default {
209
223
  if (this.managedByMerchantId) {
210
224
  mObj.managedByMerchantId = this.managedByMerchantId;
211
225
  }
226
+ if (this.managedReturnPolicyDefault) {
227
+ mObj.managedReturnPolicyDefault = this.managedReturnPolicyDefault;
228
+ }
212
229
  if (typeof this.canUpgradeToStandalone === 'boolean') {
213
230
  mObj.canUpgradeToStandalone = this.canUpgradeToStandalone;
214
231
  }
@@ -6,6 +6,14 @@ type SocialLinksType = {
6
6
  pinterest: string;
7
7
  tiktok: string;
8
8
  };
9
+ type ReturnPolicyChannel = {
10
+ allowed: boolean;
11
+ returnPeriodDays: number;
12
+ };
13
+ type ReturnPolicy = {
14
+ IN_STORE: ReturnPolicyChannel;
15
+ ONLINE: ReturnPolicyChannel;
16
+ };
9
17
  type MerchantMutableData = {
10
18
  name: string;
11
19
  type: MerchantTypes | string;
@@ -30,7 +38,8 @@ type MerchantMutableData = {
30
38
  featureAccess?: MerchantFeatureAccess | null;
31
39
  organizationNumber?: string;
32
40
  organizationNumbers?: Record<string, string>;
33
- returnPolicy?: string;
41
+ returnPolicy?: ReturnPolicy | string;
42
+ managedReturnPolicyDefault?: ReturnPolicy;
34
43
  };
35
44
  type MerchantSystemOnlyMutableData = {
36
45
  paymentTier: RibbnPaymentTiers | string;
@@ -129,7 +138,6 @@ type MerchantFormFields = {
129
138
  legalName: TextInputFormField<string>;
130
139
  organizationNumber: TextInputFormField<string>;
131
140
  organizationNumbers: SingleSelectFormField<Record<string, string>>;
132
- returnPolicy: TextInputFormField<string>;
133
141
  phone: TextInputFormField<string>;
134
142
  address: SingleSelectFormField<AddressInput>;
135
143
  currency: SingleSelectFormField<string>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rerobe-js-orm",
3
- "version": "4.9.4",
3
+ "version": "4.9.5",
4
4
  "description": "ReRobe's Javascript ORM Framework",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",