rerobe-js-orm 4.7.1 → 4.7.3

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.
@@ -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,9 @@
1
+ import Utilities from '../../helpers/Utilities';
2
+ export default class OrderFromTraderaEmail {
3
+ utilities: Utilities;
4
+ getObjectNumbers(emailHtml: any): string[];
5
+ createOrderFromLineItems(emailHtml: any, providedLineItems?: ReRobeOrderLineItem[]): ReRobeOrderObj;
6
+ private normalizeEmailHtml;
7
+ private getMatch;
8
+ private parseAmount;
9
+ }
@@ -0,0 +1,143 @@
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
+ // Extracts all Tradera listing ids ("Object No") from the email HTML
11
+ getObjectNumbers(emailHtml) {
12
+ const html = typeof emailHtml === 'string' ? emailHtml : String((emailHtml === null || emailHtml === void 0 ? void 0 : emailHtml.html) || emailHtml || '');
13
+ const normalized = this.normalizeEmailHtml(html);
14
+ const results = [];
15
+ const regex = /Object\s+No\s+(\d+)/gi;
16
+ for (const m of normalized.matchAll(regex)) {
17
+ const id = (m && m[1]) || '';
18
+ if (id && !results.includes(id))
19
+ results.push(id);
20
+ }
21
+ return results;
22
+ }
23
+ // Builds an order from raw email HTML and provided ReRobe line items (does not derive line items from email)
24
+ // Uses fixed shopper identity (email + customerName) for Tradera orders created via this method
25
+ createOrderFromLineItems(emailHtml, providedLineItems = []) {
26
+ const html = typeof emailHtml === 'string' ? emailHtml : String((emailHtml === null || emailHtml === void 0 ? void 0 : emailHtml.html) || emailHtml || '');
27
+ const normalized = this.normalizeEmailHtml(html);
28
+ const currencyCode = 'SEK';
29
+ // Extract listing id from email for traceability tag
30
+ const listingId = this.getMatch(/Object\s+No\s+(\d+)/i, normalized);
31
+ // Total amount and shipping (from email)
32
+ const totalAmountFromEmail = this.parseAmount(this.getMatch(/Total\s+amount:[\s\S]*?SEK\s*([0-9][0-9\s,.]*)/i, normalized));
33
+ // Shipping block parsing (from email)
34
+ const shippingBlockIdx = normalized.search(/>\s*Shipping\s*</i);
35
+ const shippingSlice = shippingBlockIdx >= 0 ? normalized.slice(shippingBlockIdx, shippingBlockIdx + 2000) : normalized;
36
+ const shippingAmount = this.parseAmount(this.getMatch(/SEK\s*([0-9][0-9\s,.]*)/i, shippingSlice));
37
+ const shippingTitle = this.getMatch(/SEK\s*[0-9][0-9\s,.]*\s*([^<\n\r]+)/i, shippingSlice).trim() || 'Shipping';
38
+ // Status URL (contact info, contains purchaseOrderId) if available
39
+ const statusUrl = this.getMatch(/href\s*=\s*"([^"']+buyer-info[^"']+)"/i, normalized) ||
40
+ this.getMatch(/href\s*=\s*"([^"']+purchaseOrderId=[^"']+)"/i, normalized) ||
41
+ '';
42
+ // Use provided line items as-is
43
+ const lineItems = Array.isArray(providedLineItems) ? providedLineItems : [];
44
+ // Compute subtotal: prefer email-derived (total - shipping) if present, otherwise sum line items
45
+ const subtotalFromEmail = Number.isFinite(totalAmountFromEmail) && totalAmountFromEmail > 0
46
+ ? Math.max(0, (totalAmountFromEmail || 0) - (shippingAmount || 0))
47
+ : 0;
48
+ 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);
49
+ const subtotalAmount = subtotalFromEmail || subtotalFromItems || 0;
50
+ const totalPriceAmount = Number.isFinite(totalAmountFromEmail) && totalAmountFromEmail > 0
51
+ ? totalAmountFromEmail
52
+ : subtotalAmount + (shippingAmount || 0);
53
+ const shippingLine = {
54
+ id: '',
55
+ title: shippingTitle,
56
+ source: order_constants_1.SALES_CHANNELS.tradera,
57
+ discountedPrice: { amount: shippingAmount || 0, currencyCode },
58
+ originalPrice: { amount: shippingAmount || 0, currencyCode },
59
+ taxLines: [],
60
+ };
61
+ const nowIso = new Date().toISOString();
62
+ const order = new Order_1.default({
63
+ id: this.utilities.makeRandId(28),
64
+ documentId: this.utilities.makeRandId(28),
65
+ name: '',
66
+ currencyCode,
67
+ statusUrl,
68
+ email: 'traderashopper@myribbn.com',
69
+ financialStatus: Order_1.default.FINANCIAL_TYPES.pending,
70
+ fulfillmentStatus: Order_1.default.FULFILLMENT_TYPES.unfulfilled,
71
+ processedAt: nowIso,
72
+ orderNumber: '',
73
+ shippingAddress: null,
74
+ lineItems,
75
+ subtotalPrice: { amount: subtotalAmount, currencyCode },
76
+ totalPrice: { amount: totalPriceAmount, currencyCode },
77
+ totalTax: { amount: 0, currencyCode },
78
+ totalShippingPrice: { amount: shippingAmount || 0, currencyCode },
79
+ totalDiscount: { amount: 0, currencyCode },
80
+ taxLines: [],
81
+ discountApplications: [],
82
+ fulfillments: [],
83
+ refunds: [],
84
+ totalRefunded: { amount: 0, currencyCode },
85
+ shippingLine,
86
+ tags: ['source:tradera', listingId ? `objectNo:${listingId}` : null].filter(Boolean),
87
+ state: Order_1.default.ORDER_STATES.completed,
88
+ shippingType: order_constants_1.SHIPPING_TYPES.shipping,
89
+ paymentType: order_constants_1.PAYMENT_TYPES.traderaPayment,
90
+ salesChannel: order_constants_1.SALES_CHANNELS.tradera,
91
+ customerName: 'Tradera Shopper',
92
+ });
93
+ return order.toObj();
94
+ }
95
+ normalizeEmailHtml(input) {
96
+ if (!input)
97
+ return '';
98
+ return (String(input)
99
+ // remove quoted-printable soft line breaks
100
+ .replace(/=\r?\n/g, '')
101
+ // decode common QP equals
102
+ .replace(/=3D/g, '=')
103
+ .replace(/=20/g, ' ')
104
+ // collapse excessive whitespace
105
+ .replace(/[\t\r]+/g, ' '));
106
+ }
107
+ getMatch(regex, source) {
108
+ const m = source.match(regex);
109
+ return (m && m[1]) || '';
110
+ }
111
+ parseAmount(val) {
112
+ if (val === null || val === undefined)
113
+ return 0;
114
+ if (typeof val === 'number')
115
+ return Number.isFinite(val) ? Math.round((val + Number.EPSILON) * 100) / 100 : 0;
116
+ let s = String(val)
117
+ .replace(/[^0-9.,\s]/g, '')
118
+ .trim();
119
+ // Remove spaces used as thousand separators
120
+ s = s.replace(/\s+/g, '');
121
+ const hasComma = s.includes(',');
122
+ const hasDot = s.includes('.');
123
+ if (hasComma && hasDot) {
124
+ // Assume comma is thousands, dot is decimal
125
+ s = s.replace(/,/g, '');
126
+ }
127
+ else if (hasComma && !hasDot) {
128
+ const lastComma = s.lastIndexOf(',');
129
+ const decimalsLen = s.length - lastComma - 1;
130
+ if (decimalsLen === 2) {
131
+ // Comma as decimal separator
132
+ s = s.replace(/,/g, '.');
133
+ }
134
+ else {
135
+ // Comma as thousands
136
+ s = s.replace(/,/g, '');
137
+ }
138
+ }
139
+ const num = Number(s);
140
+ return Number.isFinite(num) ? Math.round((num + Number.EPSILON) * 100) / 100 : 0;
141
+ }
142
+ }
143
+ 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");
@@ -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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rerobe-js-orm",
3
- "version": "4.7.1",
3
+ "version": "4.7.3",
4
4
  "description": "ReRobe's Javascript ORM Framework",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",