rerobe-js-orm 4.7.0 → 4.7.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/constants/order-constants.d.ts +2 -0
- package/lib/constants/order-constants.js +2 -0
- package/lib/factories/Order/OrderFromTraderaEmail.d.ts +8 -0
- package/lib/factories/Order/OrderFromTraderaEmail.js +130 -0
- package/lib/index.d.ts +2 -1
- package/lib/index.js +3 -1
- package/lib/models/Order.d.ts +3 -1
- package/lib/models/Order.js +8 -1
- package/lib/types/rerobe-order-types.d.ts +1 -0
- package/package.json +1 -1
|
@@ -11,6 +11,7 @@ export namespace PAYMENT_TYPES {
|
|
|
11
11
|
let cash: string;
|
|
12
12
|
let mobilePayment: string;
|
|
13
13
|
let shopifyPayment: string;
|
|
14
|
+
let traderaPayment: string;
|
|
14
15
|
}
|
|
15
16
|
export namespace ORDER_STATES {
|
|
16
17
|
let draft: string;
|
|
@@ -23,6 +24,7 @@ export namespace SALES_CHANNELS {
|
|
|
23
24
|
let onlineStore: string;
|
|
24
25
|
let thirdParty: string;
|
|
25
26
|
let shopify: string;
|
|
27
|
+
let tradera: string;
|
|
26
28
|
let ahlens: string;
|
|
27
29
|
let ribbnMobilePOS: string;
|
|
28
30
|
let ribbnWebPOS: string;
|
|
@@ -14,6 +14,7 @@ exports.PAYMENT_TYPES = {
|
|
|
14
14
|
cash: 'CASH',
|
|
15
15
|
mobilePayment: 'MOBILE_PAYMENT',
|
|
16
16
|
shopifyPayment: 'SHOPIFY_PAYMENT',
|
|
17
|
+
traderaPayment: 'TRADERA_PAYMENT',
|
|
17
18
|
};
|
|
18
19
|
exports.ORDER_STATES = {
|
|
19
20
|
draft: 'DRAFT',
|
|
@@ -26,6 +27,7 @@ exports.SALES_CHANNELS = {
|
|
|
26
27
|
onlineStore: 'ONLINE_STORE',
|
|
27
28
|
thirdParty: 'THIRD_PARTY',
|
|
28
29
|
shopify: 'SHOPIFY',
|
|
30
|
+
tradera: 'TRADERA',
|
|
29
31
|
ahlens: 'AHLENS',
|
|
30
32
|
ribbnMobilePOS: 'RIBBN_MOBILE_POS',
|
|
31
33
|
ribbnWebPOS: 'RIBBN_WEB_POS',
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import Utilities from '../../helpers/Utilities';
|
|
2
|
+
export default class OrderFromTraderaEmail {
|
|
3
|
+
utilities: Utilities;
|
|
4
|
+
createOrderFromLineItems(emailHtml: any, providedLineItems?: ReRobeOrderLineItem[]): ReRobeOrderObj;
|
|
5
|
+
private normalizeEmailHtml;
|
|
6
|
+
private getMatch;
|
|
7
|
+
private parseAmount;
|
|
8
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const Order_1 = require("../../models/Order");
|
|
4
|
+
const order_constants_1 = require("../../constants/order-constants");
|
|
5
|
+
const Utilities_1 = require("../../helpers/Utilities");
|
|
6
|
+
class OrderFromTraderaEmail {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.utilities = new Utilities_1.default();
|
|
9
|
+
}
|
|
10
|
+
// Builds an order from raw email HTML and provided ReRobe line items (does not derive line items from email)
|
|
11
|
+
// Uses fixed shopper identity (email + customerName) for Tradera orders created via this method
|
|
12
|
+
createOrderFromLineItems(emailHtml, providedLineItems = []) {
|
|
13
|
+
const html = typeof emailHtml === 'string' ? emailHtml : String((emailHtml === null || emailHtml === void 0 ? void 0 : emailHtml.html) || emailHtml || '');
|
|
14
|
+
const normalized = this.normalizeEmailHtml(html);
|
|
15
|
+
const currencyCode = 'SEK';
|
|
16
|
+
// Extract listing id from email for traceability tag
|
|
17
|
+
const listingId = this.getMatch(/Object\s+No\s+(\d+)/i, normalized);
|
|
18
|
+
// Total amount and shipping (from email)
|
|
19
|
+
const totalAmountFromEmail = this.parseAmount(this.getMatch(/Total\s+amount:[\s\S]*?SEK\s*([0-9][0-9\s,.]*)/i, normalized));
|
|
20
|
+
// Shipping block parsing (from email)
|
|
21
|
+
const shippingBlockIdx = normalized.search(/>\s*Shipping\s*</i);
|
|
22
|
+
const shippingSlice = shippingBlockIdx >= 0 ? normalized.slice(shippingBlockIdx, shippingBlockIdx + 2000) : normalized;
|
|
23
|
+
const shippingAmount = this.parseAmount(this.getMatch(/SEK\s*([0-9][0-9\s,.]*)/i, shippingSlice));
|
|
24
|
+
const shippingTitle = this.getMatch(/SEK\s*[0-9][0-9\s,.]*\s*([^<\n\r]+)/i, shippingSlice).trim() || 'Shipping';
|
|
25
|
+
// Status URL (contact info, contains purchaseOrderId) if available
|
|
26
|
+
const statusUrl = this.getMatch(/href\s*=\s*"([^"']+buyer-info[^"']+)"/i, normalized) ||
|
|
27
|
+
this.getMatch(/href\s*=\s*"([^"']+purchaseOrderId=[^"']+)"/i, normalized) ||
|
|
28
|
+
'';
|
|
29
|
+
// Use provided line items as-is
|
|
30
|
+
const lineItems = Array.isArray(providedLineItems) ? providedLineItems : [];
|
|
31
|
+
// Compute subtotal: prefer email-derived (total - shipping) if present, otherwise sum line items
|
|
32
|
+
const subtotalFromEmail = Number.isFinite(totalAmountFromEmail) && totalAmountFromEmail > 0
|
|
33
|
+
? Math.max(0, (totalAmountFromEmail || 0) - (shippingAmount || 0))
|
|
34
|
+
: 0;
|
|
35
|
+
const subtotalFromItems = (lineItems || []).reduce((sum, li) => { var _a; return sum + Number(((_a = li === null || li === void 0 ? void 0 : li.originalTotalPrice) === null || _a === void 0 ? void 0 : _a.amount) || 0); }, 0);
|
|
36
|
+
const subtotalAmount = subtotalFromEmail || subtotalFromItems || 0;
|
|
37
|
+
const totalPriceAmount = Number.isFinite(totalAmountFromEmail) && totalAmountFromEmail > 0
|
|
38
|
+
? totalAmountFromEmail
|
|
39
|
+
: subtotalAmount + (shippingAmount || 0);
|
|
40
|
+
const shippingLine = {
|
|
41
|
+
id: '',
|
|
42
|
+
title: shippingTitle,
|
|
43
|
+
source: order_constants_1.SALES_CHANNELS.tradera,
|
|
44
|
+
discountedPrice: { amount: shippingAmount || 0, currencyCode },
|
|
45
|
+
originalPrice: { amount: shippingAmount || 0, currencyCode },
|
|
46
|
+
taxLines: [],
|
|
47
|
+
};
|
|
48
|
+
const nowIso = new Date().toISOString();
|
|
49
|
+
const order = new Order_1.default({
|
|
50
|
+
id: this.utilities.makeRandId(28),
|
|
51
|
+
documentId: this.utilities.makeRandId(28),
|
|
52
|
+
name: '',
|
|
53
|
+
currencyCode,
|
|
54
|
+
statusUrl,
|
|
55
|
+
email: 'traderashopper@myribbn.com',
|
|
56
|
+
financialStatus: Order_1.default.FINANCIAL_TYPES.pending,
|
|
57
|
+
fulfillmentStatus: Order_1.default.FULFILLMENT_TYPES.unfulfilled,
|
|
58
|
+
processedAt: nowIso,
|
|
59
|
+
orderNumber: '',
|
|
60
|
+
shippingAddress: null,
|
|
61
|
+
lineItems,
|
|
62
|
+
subtotalPrice: { amount: subtotalAmount, currencyCode },
|
|
63
|
+
totalPrice: { amount: totalPriceAmount, currencyCode },
|
|
64
|
+
totalTax: { amount: 0, currencyCode },
|
|
65
|
+
totalShippingPrice: { amount: shippingAmount || 0, currencyCode },
|
|
66
|
+
totalDiscount: { amount: 0, currencyCode },
|
|
67
|
+
taxLines: [],
|
|
68
|
+
discountApplications: [],
|
|
69
|
+
fulfillments: [],
|
|
70
|
+
refunds: [],
|
|
71
|
+
totalRefunded: { amount: 0, currencyCode },
|
|
72
|
+
shippingLine,
|
|
73
|
+
tags: ['source:tradera', listingId ? `objectNo:${listingId}` : null].filter(Boolean),
|
|
74
|
+
state: Order_1.default.ORDER_STATES.completed,
|
|
75
|
+
shippingType: order_constants_1.SHIPPING_TYPES.shipping,
|
|
76
|
+
paymentType: order_constants_1.PAYMENT_TYPES.traderaPayment,
|
|
77
|
+
salesChannel: order_constants_1.SALES_CHANNELS.tradera,
|
|
78
|
+
customerName: 'Tradera Shopper',
|
|
79
|
+
});
|
|
80
|
+
return order.toObj();
|
|
81
|
+
}
|
|
82
|
+
normalizeEmailHtml(input) {
|
|
83
|
+
if (!input)
|
|
84
|
+
return '';
|
|
85
|
+
return (String(input)
|
|
86
|
+
// remove quoted-printable soft line breaks
|
|
87
|
+
.replace(/=\r?\n/g, '')
|
|
88
|
+
// decode common QP equals
|
|
89
|
+
.replace(/=3D/g, '=')
|
|
90
|
+
.replace(/=20/g, ' ')
|
|
91
|
+
// collapse excessive whitespace
|
|
92
|
+
.replace(/[\t\r]+/g, ' '));
|
|
93
|
+
}
|
|
94
|
+
getMatch(regex, source) {
|
|
95
|
+
const m = source.match(regex);
|
|
96
|
+
return (m && m[1]) || '';
|
|
97
|
+
}
|
|
98
|
+
parseAmount(val) {
|
|
99
|
+
if (val === null || val === undefined)
|
|
100
|
+
return 0;
|
|
101
|
+
if (typeof val === 'number')
|
|
102
|
+
return Number.isFinite(val) ? Math.round((val + Number.EPSILON) * 100) / 100 : 0;
|
|
103
|
+
let s = String(val)
|
|
104
|
+
.replace(/[^0-9.,\s]/g, '')
|
|
105
|
+
.trim();
|
|
106
|
+
// Remove spaces used as thousand separators
|
|
107
|
+
s = s.replace(/\s+/g, '');
|
|
108
|
+
const hasComma = s.includes(',');
|
|
109
|
+
const hasDot = s.includes('.');
|
|
110
|
+
if (hasComma && hasDot) {
|
|
111
|
+
// Assume comma is thousands, dot is decimal
|
|
112
|
+
s = s.replace(/,/g, '');
|
|
113
|
+
}
|
|
114
|
+
else if (hasComma && !hasDot) {
|
|
115
|
+
const lastComma = s.lastIndexOf(',');
|
|
116
|
+
const decimalsLen = s.length - lastComma - 1;
|
|
117
|
+
if (decimalsLen === 2) {
|
|
118
|
+
// Comma as decimal separator
|
|
119
|
+
s = s.replace(/,/g, '.');
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
// Comma as thousands
|
|
123
|
+
s = s.replace(/,/g, '');
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
const num = Number(s);
|
|
127
|
+
return Number.isFinite(num) ? Math.round((num + Number.EPSILON) * 100) / 100 : 0;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
exports.default = OrderFromTraderaEmail;
|
package/lib/index.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ import OrderFromShopifyWebhook from './factories/Order/OrderFromShopifyWebhook';
|
|
|
19
19
|
import OrderFromShopifyAdminApi from './factories/Order/OrderFromShopifyAdminApi';
|
|
20
20
|
import OrderFromShopifyStorefrontApi from './factories/Order/OrderFromShopifyStorefrontApi';
|
|
21
21
|
import OrderFromApp from './factories/Order/OrderFromApp';
|
|
22
|
+
import OrderFromTraderaEmail from './factories/Order/OrderFromTraderaEmail';
|
|
22
23
|
import OrderFormStateFactory from './factories/FormState/Order/OrderFormStateFactory';
|
|
23
24
|
import RefundFormStateFactory from './factories/FormState/Order/RefundFormStateFactory';
|
|
24
25
|
import Product from './models/Product';
|
|
@@ -39,4 +40,4 @@ import MerchantConfigAutomatedPayoutsFormState from './form-states/Merchant/Merc
|
|
|
39
40
|
import ReRobeProductHelpers from './helpers/ReRobeProductHelpers';
|
|
40
41
|
import AnalyticsHelpers from './helpers/AnalyticsHelpers';
|
|
41
42
|
import OrderHelpers from './helpers/OrderHelpers';
|
|
42
|
-
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, OrderFormStateFactory, RefundFormStateFactory, PayoutAccount, PayoutAccountFormState, Merchant, MerchantFormState, MerchantFormStateFactory, MerchantConfigAutomatedPayouts, MerchantConfigAutomatedPayoutsFormState, ReRobeProductHelpers, User, AnalyticsHelpers, OrderHelpers, WebhookFormState, MerchantWebPage, ShopifyMerchantAccount, CustomerNotification, };
|
|
43
|
+
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, MerchantFormState, MerchantFormStateFactory, MerchantConfigAutomatedPayouts, MerchantConfigAutomatedPayoutsFormState, ReRobeProductHelpers, User, AnalyticsHelpers, OrderHelpers, WebhookFormState, MerchantWebPage, ShopifyMerchantAccount, CustomerNotification, };
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CustomerNotification = exports.ShopifyMerchantAccount = exports.MerchantWebPage = exports.WebhookFormState = exports.OrderHelpers = exports.AnalyticsHelpers = exports.User = exports.ReRobeProductHelpers = exports.MerchantConfigAutomatedPayoutsFormState = exports.MerchantConfigAutomatedPayouts = exports.MerchantFormStateFactory = exports.MerchantFormState = exports.Merchant = exports.PayoutAccountFormState = exports.PayoutAccount = exports.RefundFormStateFactory = exports.OrderFormStateFactory = 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;
|
|
3
|
+
exports.CustomerNotification = exports.ShopifyMerchantAccount = exports.MerchantWebPage = exports.WebhookFormState = exports.OrderHelpers = exports.AnalyticsHelpers = exports.User = exports.ReRobeProductHelpers = exports.MerchantConfigAutomatedPayoutsFormState = exports.MerchantConfigAutomatedPayouts = exports.MerchantFormStateFactory = exports.MerchantFormState = 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
4
|
const ProductFromShopifyJSClientJSONDoc_1 = require("./factories/Product/ProductFromShopifyJSClientJSONDoc");
|
|
5
5
|
exports.ProductFromShopifyJSClientJSONDoc = ProductFromShopifyJSClientJSONDoc_1.default;
|
|
6
6
|
const ProductFromAlgoliaJSONDoc_1 = require("./factories/Product/ProductFromAlgoliaJSONDoc");
|
|
@@ -43,6 +43,8 @@ const OrderFromShopifyStorefrontApi_1 = require("./factories/Order/OrderFromShop
|
|
|
43
43
|
exports.OrderFromShopifyStorefrontApi = OrderFromShopifyStorefrontApi_1.default;
|
|
44
44
|
const OrderFromApp_1 = require("./factories/Order/OrderFromApp");
|
|
45
45
|
exports.OrderFromApp = OrderFromApp_1.default;
|
|
46
|
+
const OrderFromTraderaEmail_1 = require("./factories/Order/OrderFromTraderaEmail");
|
|
47
|
+
exports.OrderFromTraderaEmail = OrderFromTraderaEmail_1.default;
|
|
46
48
|
const OrderFormStateFactory_1 = require("./factories/FormState/Order/OrderFormStateFactory");
|
|
47
49
|
exports.OrderFormStateFactory = OrderFormStateFactory_1.default;
|
|
48
50
|
const RefundFormStateFactory_1 = require("./factories/FormState/Order/RefundFormStateFactory");
|
package/lib/models/Order.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export default class Order extends Base {
|
|
|
13
13
|
cash: string;
|
|
14
14
|
mobilePayment: string;
|
|
15
15
|
shopifyPayment: string;
|
|
16
|
+
traderaPayment: string;
|
|
16
17
|
};
|
|
17
18
|
static ORDER_STATES: {
|
|
18
19
|
draft: string;
|
|
@@ -25,6 +26,7 @@ export default class Order extends Base {
|
|
|
25
26
|
onlineStore: string;
|
|
26
27
|
thirdParty: string;
|
|
27
28
|
shopify: string;
|
|
29
|
+
tradera: string;
|
|
28
30
|
ahlens: string;
|
|
29
31
|
ribbnMobilePOS: string;
|
|
30
32
|
ribbnWebPOS: string;
|
|
@@ -134,6 +136,6 @@ export default class Order extends Base {
|
|
|
134
136
|
})[];
|
|
135
137
|
name: string;
|
|
136
138
|
};
|
|
137
|
-
toObjForTypesense(): TypesenseOrderObj;
|
|
139
|
+
toObjForTypesense(productSkus?: string[]): TypesenseOrderObj;
|
|
138
140
|
toOrderInputObj(): any;
|
|
139
141
|
}
|
package/lib/models/Order.js
CHANGED
|
@@ -346,6 +346,12 @@ class Order extends Base_1.default {
|
|
|
346
346
|
name: 'productIds',
|
|
347
347
|
type: 'string[]',
|
|
348
348
|
},
|
|
349
|
+
{
|
|
350
|
+
facet: true,
|
|
351
|
+
name: 'productSkus',
|
|
352
|
+
type: 'string[]',
|
|
353
|
+
optional: true,
|
|
354
|
+
},
|
|
349
355
|
{
|
|
350
356
|
facet: true,
|
|
351
357
|
name: 'tags',
|
|
@@ -394,7 +400,7 @@ class Order extends Base_1.default {
|
|
|
394
400
|
name: 'dev_orders_20220809',
|
|
395
401
|
};
|
|
396
402
|
}
|
|
397
|
-
toObjForTypesense() {
|
|
403
|
+
toObjForTypesense(productSkus) {
|
|
398
404
|
const image = this.lineItems && this.lineItems[0] && this.lineItems[0].image && this.lineItems[0].image.originalSrc
|
|
399
405
|
? this.lineItems[0].image.originalSrc
|
|
400
406
|
: 'https://res.cloudinary.com/ribbn/image/fetch/e_blur:1000,o_20,q_50/https://cdn.shopify.com/s/files/1/0261/9686/9172/products/7AC16810-F519-4665-8891-7163EB29FBB7_1000x1000.jpg%3Fv%3D1634827512';
|
|
@@ -424,6 +430,7 @@ class Order extends Base_1.default {
|
|
|
424
430
|
paymentType: this.utilities.sanitizeString(this.paymentType),
|
|
425
431
|
shippingType: this.utilities.sanitizeString(this.shippingType),
|
|
426
432
|
productIds: this.utilities.sanitzeStringArr(this.lineItems.map((l) => l.productId)),
|
|
433
|
+
productSkus: productSkus ? this.utilities.sanitzeStringArr(productSkus) : undefined,
|
|
427
434
|
productTitles: this.utilities.sanitzeStringArr(this.lineItems.map((l) => l.title)),
|
|
428
435
|
productBrands: this.utilities.sanitzeStringArr(this.lineItems.map((l) => l.brand)),
|
|
429
436
|
tags: this.utilities.sanitzeStringArr(this.tags),
|