rerobe-js-orm 4.9.14 → 4.9.16

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.
@@ -31,6 +31,7 @@ export namespace SALES_CHANNELS {
31
31
  let ribbnSellThroughChannelPartner: string;
32
32
  let ribbnSellOnChannelPartner: string;
33
33
  }
34
+ export const POS_SALES_CHANNELS: string[];
34
35
  export namespace FULFILLMENT_TYPES {
35
36
  let fulfilled: string;
36
37
  let partiallyFulfilled: string;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SALES_CHANNEL_TO_RETURN_POLICY_MAPPING = exports.RETURN_POLICY_TYPES = exports.FINANCIAL_TYPES = exports.FULFILLMENT_TYPES = exports.SALES_CHANNELS = exports.ORDER_STATES = exports.PAYMENT_TYPES = exports.SHIPPING_TYPES = void 0;
3
+ exports.SALES_CHANNEL_TO_RETURN_POLICY_MAPPING = exports.RETURN_POLICY_TYPES = exports.FINANCIAL_TYPES = exports.FULFILLMENT_TYPES = exports.POS_SALES_CHANNELS = exports.SALES_CHANNELS = exports.ORDER_STATES = exports.PAYMENT_TYPES = exports.SHIPPING_TYPES = void 0;
4
4
  exports.SHIPPING_TYPES = {
5
5
  localPickUp: 'LOCAL_PICK_UP',
6
6
  localDelivery: 'LOCAL_DELIVERY',
@@ -34,6 +34,11 @@ exports.SALES_CHANNELS = {
34
34
  ribbnSellThroughChannelPartner: 'RIBBN_SELL_THROUGH_CHANNEL_PARTNER',
35
35
  ribbnSellOnChannelPartner: 'RIBBN_SELL_ON_CHANNEL_PARTNER',
36
36
  };
37
+ // Point-of-sale / in-person channels: the customer is handed the goods at the
38
+ // moment of sale, so every item is fulfilled at sale time (there is no separate
39
+ // fulfillment step, and no per-item fulfillment record is created). `store` is a
40
+ // legacy in-person store-sale channel, treated the same.
41
+ exports.POS_SALES_CHANNELS = [exports.SALES_CHANNELS.ribbnWebPOS, exports.SALES_CHANNELS.ribbnMobilePOS, exports.SALES_CHANNELS.store];
37
42
  exports.FULFILLMENT_TYPES = {
38
43
  fulfilled: 'FULFILLED',
39
44
  partiallyFulfilled: 'PARTIALLY_FULFILLED',
@@ -15,6 +15,9 @@ export default class OrderHelpers {
15
15
  currencyCode: string;
16
16
  };
17
17
  getAmountSumByField(array: OrderRefund[] | ReRobeOrderLineItem[], fieldKey: string): number;
18
+ isPosOrder(order: {
19
+ salesChannel?: string | null;
20
+ } | null | undefined): boolean;
18
21
  getOrderInfoWithRefundsAndFulfillments(order: CompleteOrder): OrderWithRefundsAndFulfillmentsInfoObj;
19
22
  getUpdatedOrderObjWithRefunds(orderObj: CompleteOrder, refundObj: OrderRefund): CompleteOrder;
20
23
  getUpdatedOrderObjWithFulfillment(orderObj: CompleteOrder, fulfillmentObj: FulfillmentAdmin, totalUnfulfilledItems: number): CompleteOrder;
@@ -160,11 +160,21 @@ class OrderHelpers {
160
160
  getAmountSumByField(array, fieldKey) {
161
161
  return array.map((item) => { var _a; return Number(((_a = item[fieldKey]) === null || _a === void 0 ? void 0 : _a.amount) || 0); }).reduce((a, b) => a + b, 0);
162
162
  }
163
+ // Point-of-sale / in-person sale (Ribbn POS or the Ribbn Mobile App): goods are
164
+ // handed over at the moment of sale, so all items are fulfilled at sale time.
165
+ isPosOrder(order) {
166
+ return order_constants_1.POS_SALES_CHANNELS.includes((order && order.salesChannel) || '');
167
+ }
163
168
  getOrderInfoWithRefundsAndFulfillments(order) {
164
169
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
165
170
  const orderRefunds = order.refunds ? [...order.refunds] : [];
166
171
  const orderFulfillment = order.fulfillments ? [...order.fulfillments] : [];
167
172
  const orderLineItems = order.lineItems && Array.isArray(order.lineItems) ? [...order.lineItems] : [];
173
+ // POS / in-person orders fulfill every item at sale and never create per-item
174
+ // fulfillment records, so without this they'd all bucket as "unfulfilled"
175
+ // (and a refund would strand the non-returned items there). When there are no
176
+ // real fulfillment records, baseline every item as fulfilled instead.
177
+ const posFulfilledBaseline = this.isPosOrder(order) && !orderFulfillment.length;
168
178
  const subtotalPrice = Object.assign(Object.assign({}, order.subtotalPrice), { amount: this.getSubtotalPrice(orderLineItems) });
169
179
  const subtotalPricePresentment = Object.assign(Object.assign({}, order.subtotalPricePresentment), { amount: this.getAmountSumByField(orderLineItems, 'presentmentTotalPrice') });
170
180
  const preparedOrder = {
@@ -226,6 +236,10 @@ class OrderHelpers {
226
236
  });
227
237
  preparedOrder.fulfilledItems = preparedOrder.activeLineItems.filter(({ fulfilledQuantity }) => fulfilledQuantity > 0);
228
238
  }
239
+ else if (posFulfilledBaseline) {
240
+ preparedOrder.activeLineItems = preparedOrder.activeLineItems.map((item) => (Object.assign(Object.assign({}, item), { fulfilledQuantity: Number(item.quantity), unfulfilledQuantity: 0 })));
241
+ preparedOrder.fulfilledItems = [...preparedOrder.activeLineItems];
242
+ }
229
243
  preparedOrder.unfulfilledItems = preparedOrder.activeLineItems.filter(({ unfulfilledQuantity }) => unfulfilledQuantity > 0);
230
244
  if (!orderRefunds.length) {
231
245
  return preparedOrder;
@@ -277,6 +291,16 @@ class OrderHelpers {
277
291
  }, { refundedQuantity: 0, canceledQuantity: 0 });
278
292
  // 3. fulfilledQuantity = (sum of order.fulfillment) - refundedQuantity
279
293
  // 4. quantity = unfulfilled quantity (prev quantity - sum of order.fulfillment) - cancelled
294
+ //
295
+ // POS / in-person: every item started fulfilled, so a return (recorded as a
296
+ // refund OR a cancel, depending on the refund flow) comes out of the
297
+ // fulfilled quantity — never out of unfulfilled (which is 0 here). Otherwise
298
+ // a returned POS item would stay in the fulfilled bucket AND show as removed.
299
+ if (posFulfilledBaseline) {
300
+ return Object.assign(Object.assign(Object.assign({}, item), { fulfilledQuantity: Number(item.fulfilledQuantity) -
301
+ refundedAndCanceledQuantity.refundedQuantity -
302
+ refundedAndCanceledQuantity.canceledQuantity, unfulfilledQuantity: 0 }), refundedAndCanceledQuantity);
303
+ }
280
304
  return Object.assign(Object.assign(Object.assign({}, item), { fulfilledQuantity: Number(item.fulfilledQuantity) - refundedAndCanceledQuantity.refundedQuantity, unfulfilledQuantity: Number(item.unfulfilledQuantity) - refundedAndCanceledQuantity.canceledQuantity }), refundedAndCanceledQuantity);
281
305
  });
282
306
  // Active lineItems - not refunded and not removed(not canceled) positions
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rerobe-js-orm",
3
- "version": "4.9.14",
3
+ "version": "4.9.16",
4
4
  "description": "ReRobe's Javascript ORM Framework",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",