@dotdev/harmony-sdk 1.11.0 → 1.13.0

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.
@@ -1,5 +1,5 @@
1
1
  import { IAxiosRetryConfig } from "axios-retry";
2
- import { AuthenticationToken, Carrier, CarrierShipment, CreateDiaryQueryParams, Diary, GetCarrierShipmentByTimeQueryParams, GetDiaryQueryParams, ProcessSaleOrderQueryParams, ProcessSaleOrderWithoutPaymentQueryParams, SizeGrid, Stock, StockBarcode, StockCategory, StockClassification, StockClassificationType, StockColor, StockLevel, StockLevelLookupQueryParams, StockLookupRequestParams, Warehouse } from "./modules";
2
+ import { AuthenticationToken, Carrier, CarrierShipment, CreateDiaryQueryParams, Diary, GetCarrierShipmentByTimeQueryParams, GetDiaryQueryParams, ProcessInvoiceQueryParams, ProcessSaleOrderQueryParams, ProcessSaleOrderWithoutPaymentQueryParams, SizeGrid, Stock, StockBarcode, StockCategory, StockClassification, StockClassificationType, StockColor, StockLevel, StockLevelLookupQueryParams, StockLookupRequestParams, Warehouse } from "./modules";
3
3
  import { GiftVoucher, GiftVoucherLookupQueryParams, GiftVoucherReservationQueryParams, GiftVoucherUsedQueryParams, GiftVoucherVerificationKeyQueryParams } from "./modules/gift-voucher/types";
4
4
  export declare class HarmonyAPI {
5
5
  private baseUrl;
@@ -24,7 +24,8 @@ export declare class HarmonyAPI {
24
24
  stockLevelLookupByWarehouseQuickView(params: StockLevelLookupQueryParams, sessionId: string): Promise<StockLevel[]>;
25
25
  processSalesOrder(params: ProcessSaleOrderQueryParams, sessionId: string): Promise<boolean>;
26
26
  processSalesOrderWithoutPayment(params: ProcessSaleOrderWithoutPaymentQueryParams, sessionId: string): Promise<boolean>;
27
- mapOrderPayloadToXml(params: Partial<ProcessSaleOrderQueryParams>, sessionId: string): Promise<string>;
27
+ mapOrderPayloadToXml(params: Partial<ProcessSaleOrderQueryParams>, sessionId: string, method?: "ProcessSalesOrder" | "ProcessSalesOrderWithoutPayment" | "ProcessInvoice"): Promise<string>;
28
+ processInvoice(params: ProcessInvoiceQueryParams, sessionId: string): Promise<boolean>;
28
29
  processReturns(params: ProcessSaleOrderQueryParams, sessionId: string): Promise<boolean>;
29
30
  modifyExistingSalesOrder(params: ProcessSaleOrderQueryParams, sessionId: string): Promise<boolean>;
30
31
  cancelExistingSalesOrder(params: ProcessSaleOrderQueryParams, sessionId: string): Promise<boolean>;
@@ -86,8 +86,14 @@ export class HarmonyAPI {
86
86
  async processSalesOrderWithoutPayment(params, sessionId) {
87
87
  return await this.pointOfSaleModule.processSalesOrderWithoutPayment(params, sessionId);
88
88
  }
89
- async mapOrderPayloadToXml(params, sessionId) {
90
- return await this.pointOfSaleModule.mapOrderPayloadToXml(params, sessionId);
89
+ // Temporary workaround to return payload to Core
90
+ // TODO: Update API helper function to return payload with every API call
91
+ async mapOrderPayloadToXml(params, sessionId, method) {
92
+ return await this.pointOfSaleModule.mapOrderPayloadToXml(params, sessionId, method);
93
+ }
94
+ // Post fulfilled orders
95
+ async processInvoice(params, sessionId) {
96
+ return await this.pointOfSaleModule.processInvoice(params, sessionId);
91
97
  }
92
98
  async processReturns(params, sessionId) {
93
99
  return await this.pointOfSaleModule.processReturns(params, sessionId);
@@ -1,5 +1,6 @@
1
- import { ProcessSaleOrderQueryDebtor, ProcessSaleOrderQueryExtra, ProcessSaleOrderQueryHeader, ProcessSaleOrderQueryParams, ProcessSaleOrderQueryStock, ProcessSaleOrderWithoutPaymentQueryParams } from "../types";
1
+ import { ProcessInvoiceQueryParams, ProcessSaleOrderQueryDebtor, ProcessSaleOrderQueryExtra, ProcessSaleOrderQueryHeader, ProcessSaleOrderQueryParams, ProcessSaleOrderQueryStock, ProcessSaleOrderWithoutPaymentQueryParams } from "../types";
2
2
  export declare function mapProcessSaleOrderQueryParams(params: ProcessSaleOrderQueryParams): string;
3
+ export declare function mapProcessInvoiceQueryParams(params: ProcessInvoiceQueryParams): string;
3
4
  export declare function mapProcessSaleOrderWithoutPaymentQueryParams(params: ProcessSaleOrderWithoutPaymentQueryParams): string;
4
5
  export declare function mapProcessSaleOrderBaseQueryParams(params: ProcessSaleOrderWithoutPaymentQueryParams): {
5
6
  mode: import("../types").PosQueryMode | undefined;
@@ -13,3 +14,4 @@ export declare function mapProcessSaleOrderQueryHeaders(params: ProcessSaleOrder
13
14
  export declare function mapProcessSaleOrderQueryExtra(params: ProcessSaleOrderQueryExtra): string;
14
15
  export declare function mapProcessSaleOrderQueryStock(params: ProcessSaleOrderQueryStock): string;
15
16
  export declare function mapProcessSaleOrderQueryDebtor(params: ProcessSaleOrderQueryDebtor): string;
17
+ export declare function mapPosInvoiceQuery(params: ProcessInvoiceQueryParams): string;
@@ -7,6 +7,15 @@ export function mapProcessSaleOrderQueryParams(params) {
7
7
  };
8
8
  return Utils.toXml(Utils.deleteEmptyProps(body));
9
9
  }
10
+ export function mapProcessInvoiceQueryParams(params) {
11
+ // XML body in JSON format, to be converted to XML string
12
+ const body = {
13
+ ...mapProcessSaleOrderBaseQueryParams(params),
14
+ invoice: mapPosInvoiceQuery(params),
15
+ debtor: mapProcessSaleOrderQueryDebtor((params?.debtor ?? [])[0]),
16
+ };
17
+ return Utils.toXml(Utils.deleteEmptyProps(body));
18
+ }
10
19
  export function mapProcessSaleOrderWithoutPaymentQueryParams(params) {
11
20
  return Utils.toXml(Utils.deleteEmptyProps(mapProcessSaleOrderBaseQueryParams(params)));
12
21
  }
@@ -148,3 +157,12 @@ export function mapProcessSaleOrderQueryDebtor(params) {
148
157
  };
149
158
  return Utils.deleteEmptyProps(body);
150
159
  }
160
+ export function mapPosInvoiceQuery(params) {
161
+ const body = {
162
+ invoice_price_inc: params?.invoice?.invoicePriceInc,
163
+ rounding: params?.invoice?.rounding,
164
+ total_tax: params?.invoice?.totalTax,
165
+ cash_drawer_id: params?.invoice?.cashDrawerId,
166
+ };
167
+ return Utils.deleteEmptyProps(body);
168
+ }
@@ -1,5 +1,5 @@
1
1
  import { AxiosInstance } from "axios";
2
- import { ProcessSaleOrderQueryParams, ProcessSaleOrderWithoutPaymentQueryParams } from "./types";
2
+ import { ProcessInvoiceQueryParams, ProcessSaleOrderQueryParams, ProcessSaleOrderWithoutPaymentQueryParams } from "./types";
3
3
  export declare class PointOfSaleModule {
4
4
  private axiosInstance;
5
5
  private readonly SERVICE_URL;
@@ -21,7 +21,7 @@ export declare class PointOfSaleModule {
21
21
  * @param {ProcessSaleOrderQueryParams} params
22
22
  * @param {string} sessionId
23
23
  */
24
- mapOrderPayloadToXml(params: Partial<ProcessSaleOrderQueryParams>, sessionId: string, method?: "ProcessSalesOrder" | "ProcessSalesOrderWithoutPayment"): Promise<string>;
24
+ mapOrderPayloadToXml(params: Partial<ProcessSaleOrderQueryParams>, sessionId: string, method?: "ProcessSalesOrder" | "ProcessSalesOrderWithoutPayment" | "ProcessInvoice"): Promise<string>;
25
25
  /**
26
26
  * Function to call the ProcessSalesOrderWithoutPayment endpoint in Harmony Point Of Sale service
27
27
  *
@@ -31,6 +31,13 @@ export declare class PointOfSaleModule {
31
31
  * @returns {Promise<boolean>}
32
32
  */
33
33
  processSalesOrderWithoutPayment(params: ProcessSaleOrderWithoutPaymentQueryParams, sessionId: string): Promise<boolean>;
34
+ /**
35
+ * Function to call the ProcessInvoice endpoint in Harmony Point Of Sale service
36
+ * This is used to post orders that are already fulfilled (e.g. POS orders)
37
+ * @param params query params
38
+ * @param sessionId authenticated session ID string
39
+ */
40
+ processInvoice(params: ProcessInvoiceQueryParams, sessionId: string): Promise<boolean>;
34
41
  /**
35
42
  * Function to call the ProcessReturns endpoint in Harmony Point Of Sale service
36
43
  *
@@ -1,6 +1,6 @@
1
1
  import { ApiHelper, Utils } from "../../helpers";
2
2
  import { ServiceAlias } from "../shared";
3
- import { mapProcessSaleOrderQueryDebtor, mapProcessSaleOrderQueryExtra, mapProcessSaleOrderQueryHeaders, mapProcessSaleOrderQueryParams, mapProcessSaleOrderQueryStock, mapProcessSaleOrderWithoutPaymentQueryParams, } from "./mappings/process-sale-order.mapper";
3
+ import { mapPosInvoiceQuery, mapProcessInvoiceQueryParams, mapProcessSaleOrderQueryDebtor, mapProcessSaleOrderQueryExtra, mapProcessSaleOrderQueryHeaders, mapProcessSaleOrderQueryParams, mapProcessSaleOrderQueryStock, mapProcessSaleOrderWithoutPaymentQueryParams, } from "./mappings/process-sale-order.mapper";
4
4
  import { promisify } from "util";
5
5
  import { parseString } from "xml2js";
6
6
  const parseXml = promisify(parseString);
@@ -51,7 +51,13 @@ export class PointOfSaleModule {
51
51
  extra: mapProcessSaleOrderQueryExtra(params?.extra),
52
52
  stock: params?.stock?.map(mapProcessSaleOrderQueryStock),
53
53
  };
54
- if (method === "ProcessSalesOrder") {
54
+ if (method === "ProcessInvoice") {
55
+ body = {
56
+ ...body,
57
+ invoice: mapPosInvoiceQuery(params),
58
+ };
59
+ }
60
+ if (method === "ProcessSalesOrder" || method === "ProcessInvoice") {
55
61
  body = {
56
62
  ...body,
57
63
  debtor: mapProcessSaleOrderQueryDebtor((params?.debtor ?? [])[0]),
@@ -93,6 +99,22 @@ export class PointOfSaleModule {
93
99
  throw await ApiHelper.parseError(error);
94
100
  }
95
101
  }
102
+ /**
103
+ * Function to call the ProcessInvoice endpoint in Harmony Point Of Sale service
104
+ * This is used to post orders that are already fulfilled (e.g. POS orders)
105
+ * @param params query params
106
+ * @param sessionId authenticated session ID string
107
+ */
108
+ async processInvoice(params, sessionId) {
109
+ try {
110
+ const requestBody = mapProcessInvoiceQueryParams(params);
111
+ const response = await ApiHelper.sendServiceRequest(this.SERVICE_URL, ["ProcessInvoice", "Request"], sessionId, ServiceAlias.POINT_OF_SALE, this.axiosInstance, requestBody);
112
+ return Boolean(response?.result[0] ?? "false");
113
+ }
114
+ catch (error) {
115
+ throw await ApiHelper.parseError(error);
116
+ }
117
+ }
96
118
  /**
97
119
  * Function to call the ProcessReturns endpoint in Harmony Point Of Sale service
98
120
  *
@@ -363,4 +363,205 @@ describe("PointOfSaleModule", () => {
363
363
  expect(Utils.removeEmptySpaces(actualPayload)).toEqual(Utils.removeEmptySpaces(expectedPayload));
364
364
  mAxios.post.mockClear();
365
365
  });
366
+ test("ProcessInvoice should process the order correctly and return response", async () => {
367
+ const token = "test-token";
368
+ const ns = "S";
369
+ const expectedPayload = `
370
+ <${ns}:Envelope xmlns:${ns}="http://schemas.xmlsoap.org/soap/envelope/" xmlns:${ServiceAlias.POINT_OF_SALE}="http://${ServiceAlias.POINT_OF_SALE}.ws.fbsaust.com.au">
371
+ <${ns}:Header>
372
+ <${ServiceAlias.POINT_OF_SALE}:SessionId>${token}</${ServiceAlias.POINT_OF_SALE}:SessionId>
373
+ </${ns}:Header>
374
+ <${ns}:Body>
375
+ <${ServiceAlias.POINT_OF_SALE}:ProcessInvoiceRequest>
376
+ <mode>U</mode>
377
+ <audit_no>106942</audit_no>
378
+ <header>
379
+ <order_no>W00106943</order_no>
380
+ <customer_order_no>W00106943</customer_order_no>
381
+ <transaction_date>02-06-2015</transaction_date>
382
+ <transaction_time_hour>11</transaction_time_hour>
383
+ <transaction_time_min>52</transaction_time_min>
384
+ <transaction_time_sec>0</transaction_time_sec>
385
+ <shop_debtor>ABC</shop_debtor>
386
+ <diary>0005353</diary>
387
+ <diary_name_1>AMMY</diary_name_1>
388
+ <diary_name_2>WHITE</diary_name_2>
389
+ <warehouse>WEB</warehouse>
390
+ <agent_zone_1>1111</agent_zone_1>
391
+ <terminal_id>online</terminal_id>
392
+ <user>WEB</user>
393
+ <order_lines>0</order_lines>
394
+ <order_deposit_total>119.95</order_deposit_total>
395
+ <order_version>0</order_version>
396
+ <originator_software>WEB</originator_software>
397
+ <account_sale_flag>Y</account_sale_flag>
398
+ </header>
399
+ <extra>
400
+ <delivery_address_1>37</delivery_address_1>
401
+ <delivery_address_2>HOTHAM ST</delivery_address_2>
402
+ <delivery_address_3>ST KILDA EAST</delivery_address_3>
403
+ <delivery_address_4>VIC</delivery_address_4>
404
+ <delivery_postcode>3111</delivery_postcode>
405
+ <delivery_instruction_1>Enter backdoor</delivery_instruction_1>
406
+ <delivery_instruction_2>Then frontdoor</delivery_instruction_2>
407
+ <carrier>APOST</carrier>
408
+ <email>test@example.com</email>
409
+ <telephone_home>0444888885</telephone_home>
410
+ <telephone_mobile>0444888884</telephone_mobile>
411
+ <telephone_work>0444888883</telephone_work>
412
+ <billing_surname>DOE</billing_surname>
413
+ <billing_first_name>JOHN</billing_first_name>
414
+ <billing_address_1>37</billing_address_1>
415
+ <billing_address_2>HOTHAM ST</billing_address_2>
416
+ <billing_address_3>ST KILDA EAST</billing_address_3>
417
+ <billing_address_4>VIC</billing_address_4>
418
+ <billing_postcode>3111</billing_postcode>
419
+ <billing_telephone_home>0444888888</billing_telephone_home>
420
+ <billing_telephone_mobile>0444888887</billing_telephone_mobile>
421
+ <billing_telephone_work>0444888886</billing_telephone_work>
422
+ <customised_info>CUSTOM</customised_info>
423
+ </extra>
424
+ <stock>
425
+ <stock>7281VL.100</stock>
426
+ <stock_description>3/4 SLV CROSS OVER DRESS W/ TUCKS</stock_description>
427
+ <size>S</size>
428
+ <qdp>0</qdp>
429
+ <pdp>2</pdp>
430
+ <invoice_qty>0</invoice_qty>
431
+ <order_qty>1</order_qty>
432
+ <discount_price>119.95</discount_price>
433
+ <line_tax>0</line_tax>
434
+ <discount_rate>30</discount_rate>
435
+ <discount_reason>210</discount_reason>
436
+ <current_rrp_inc>149.95</current_rrp_inc>
437
+ </stock>
438
+ <invoice>
439
+ <invoice_price_inc>100.1</invoice_price_inc>
440
+ <rounding>1.1</rounding>
441
+ <total_tax>2.1</total_tax>
442
+ <cash_drawer_id>BIONLINE</cash_drawer_id>
443
+ </invoice>
444
+ <debtor>
445
+ <payment_type>4</payment_type>
446
+ <payment_amount>119.95</payment_amount>
447
+ <invoice_price_inc>0</invoice_price_inc>
448
+ <rounding>0</rounding>
449
+ <total_tax>0</total_tax>
450
+ <card_name>PPAL</card_name>
451
+ <card_no>ABC123</card_no>
452
+ <card_expiry_month>0</card_expiry_month>
453
+ <card_expiry_year>0</card_expiry_year>
454
+ <cash_drawer_id>ABC1</cash_drawer_id>
455
+ <reservation_history_no>0</reservation_history_no>
456
+ </debtor>
457
+ </${ServiceAlias.POINT_OF_SALE}:ProcessInvoiceRequest>
458
+ </${ns}:Body>
459
+ </${ns}:Envelope>
460
+ `;
461
+ const params = {
462
+ mode: PosQueryMode.UPDATE,
463
+ auditNo: "106942",
464
+ header: {
465
+ orderNo: "W00106943",
466
+ customerOrderNo: "W00106943",
467
+ transactionDate: "02-06-2015",
468
+ transactionTimeHour: 11,
469
+ transactionTimeMin: 52,
470
+ transactionTimeSec: 0,
471
+ shopDebtor: "ABC",
472
+ diary: "0005353",
473
+ diaryName1: "AMMY",
474
+ diaryName2: "WHITE",
475
+ warehouse: "WEB",
476
+ agentZone1: 1111,
477
+ terminalId: "online",
478
+ user: "WEB",
479
+ orderLines: 0,
480
+ orderDepositTotal: 119.95,
481
+ orderVersion: 0,
482
+ originatorSoftware: "WEB",
483
+ accountSaleFlag: AccountSaleFlag.YES,
484
+ },
485
+ stock: [
486
+ {
487
+ stock: "7281VL.100",
488
+ stockDescription: "3/4 SLV CROSS OVER DRESS W/ TUCKS",
489
+ size: "S",
490
+ qdp: 0,
491
+ pdp: 2,
492
+ invoiceQty: 0.0,
493
+ orderQty: 1.0,
494
+ discountPrice: 119.95,
495
+ lineTax: 0.0,
496
+ discountRate: 30.0,
497
+ discountReason: "210",
498
+ currentRrpInc: 149.95,
499
+ },
500
+ ],
501
+ invoice: {
502
+ invoicePriceInc: 100.1,
503
+ rounding: 1.1,
504
+ totalTax: 2.1,
505
+ cashDrawerId: 'BIONLINE'
506
+ },
507
+ extra: {
508
+ deliveryAddress1: "37",
509
+ deliveryAddress2: "HOTHAM ST",
510
+ deliveryAddress3: "ST KILDA EAST",
511
+ deliveryAddress4: "VIC",
512
+ deliveryPostcode: "3111",
513
+ deliveryInstruction1: "Enter backdoor",
514
+ deliveryInstruction2: "Then frontdoor",
515
+ telephoneHome: "0444888885",
516
+ telephoneMobile: "0444888884",
517
+ telephoneWork: "0444888883",
518
+ email: "test@example.com",
519
+ billingAddress1: "37",
520
+ billingAddress2: "HOTHAM ST",
521
+ billingAddress3: "ST KILDA EAST",
522
+ billingAddress4: "VIC",
523
+ billingPostcode: "3111",
524
+ billingFirstname: "JOHN",
525
+ billingSurname: "DOE",
526
+ billingTelephoneHome: "0444888888",
527
+ billingTelephoneMobile: "0444888887",
528
+ billingTelephoneWork: "0444888886",
529
+ carrier: "APOST",
530
+ customisedInfo: "CUSTOM",
531
+ },
532
+ debtor: [
533
+ {
534
+ paymentType: PosPaymentType.CARD,
535
+ paymentAmount: 119.95,
536
+ invoicePriceInc: 0.0,
537
+ rounding: 0.0,
538
+ totalTax: 0.0,
539
+ cardName: CardName.PAYPAL,
540
+ cardNo: "ABC123",
541
+ cardExpiryMonth: 0,
542
+ cardExpiryYear: 0,
543
+ cashDrawerId: "ABC1",
544
+ reservationHistoryNo: 0,
545
+ },
546
+ ],
547
+ };
548
+ const mockedResp = `
549
+ <?xml version='1.0' encoding='UTF-8'?>
550
+ <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
551
+ <S:Body><ns2:ProcessInvoiceResponse xmlns:ns2="http://pos.ws.fbsaust.com.au">
552
+ <result>true</result>
553
+ </ns2:ProcessInvoiceResponse></S:Body>
554
+ </S:Envelope>
555
+ `;
556
+ const expectedResult = true;
557
+ mAxios.post.mockResolvedValueOnce({ data: mockedResp });
558
+ const response = await posModule.processInvoice(params, token);
559
+ // Test that expected response is correct
560
+ expect(typeof response).toEqual("boolean");
561
+ expect(response).toEqual(expectedResult);
562
+ const actualPayload = mAxios.post.mock.calls[0][1];
563
+ // Test that actual payload sent in the API matches expected payload
564
+ expect(Utils.removeEmptySpaces(actualPayload)).toEqual(Utils.removeEmptySpaces(expectedPayload));
565
+ mAxios.post.mockClear();
566
+ });
366
567
  });
@@ -3,6 +3,9 @@ import { BooleanResponse } from "../../shared";
3
3
  export interface ProcessSaleOrderQueryParams extends ProcessSaleOrderWithoutPaymentQueryParams {
4
4
  debtor: ProcessSaleOrderQueryDebtor[];
5
5
  }
6
+ export interface ProcessInvoiceQueryParams extends ProcessSaleOrderQueryParams {
7
+ invoice: PosQueryInvoice;
8
+ }
6
9
  export interface ProcessSaleOrderWithoutPaymentQueryParams extends PosBaseQueryParams {
7
10
  header: ProcessSaleOrderQueryHeader;
8
11
  extra: ProcessSaleOrderQueryExtra;
@@ -67,3 +70,4 @@ export interface ProcessSaleOrderQueryStock extends PosQueryStock {
67
70
  }
68
71
  export type ProcessSaleOrderQueryDebtor = PosQueryInvoice & PosQueryDebtor;
69
72
  export type ProcessSalesOrderResponse = BooleanResponse;
73
+ export type ProcessInvoiceResponse = BooleanResponse;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dotdev/harmony-sdk",
3
- "version": "1.11.0",
3
+ "version": "1.13.0",
4
4
  "description": "Harmony API SDK",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",