fc-landmark 2.1.3 → 3.0.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.
- package/README.md +12 -12
- package/azure-pipelines.yml +45 -45
- package/dist/axios.js +29 -29
- package/dist/core.js +18 -18
- package/dist/globals.js +4 -4
- package/dist/index.js +6 -6
- package/dist/landmark.js +78 -78
- package/dist/shipment.js +212 -201
- package/dist/shipment.js.map +1 -1
- package/dist/tracking.js +92 -92
- package/dist/types.js +2 -2
- package/package.json +42 -31
- package/src/axios.ts +28 -28
- package/src/core.ts +12 -12
- package/src/globals.ts +4 -4
- package/src/index.ts +2 -2
- package/src/landmark.ts +67 -67
- package/src/shipment.spec.ts +179 -0
- package/src/shipment.ts +213 -193
- package/src/tracking.ts +82 -82
- package/src/types.ts +109 -102
- package/tests/shipment.js +456 -456
- package/tests/tracking.js +32 -32
- package/tsconfig.json +14 -12
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { xml2js } from 'xml-js';
|
|
2
|
+
import Shipment from './shipment';
|
|
3
|
+
|
|
4
|
+
const address = (country: string) => ({
|
|
5
|
+
name: 'Jane Doe',
|
|
6
|
+
attention_name: 'Jane',
|
|
7
|
+
address_line_1: '1 Main St',
|
|
8
|
+
address_line_2: '',
|
|
9
|
+
address_line_3: '',
|
|
10
|
+
city: 'Berlin',
|
|
11
|
+
state: 'BE',
|
|
12
|
+
zip: '10115',
|
|
13
|
+
country,
|
|
14
|
+
phone: 5551234,
|
|
15
|
+
email: 'jane@example.com',
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const shipmentInput = (pieceOverrides: Record<string, unknown> = {}) => ({
|
|
19
|
+
reference: 'REF-1',
|
|
20
|
+
shipto_address: address('DE'),
|
|
21
|
+
shipfrom_address: address('US'),
|
|
22
|
+
targetToCountry: 'DE',
|
|
23
|
+
_carrierRateObj: { servicecode: 'LGINTSTD' },
|
|
24
|
+
shipment_total_usd: 10,
|
|
25
|
+
currency: 'USD',
|
|
26
|
+
label_format: 'PDF',
|
|
27
|
+
weight_unit: 'LB',
|
|
28
|
+
dimension_unit: 'IN',
|
|
29
|
+
package: { weight: 1, length: 1, width: 1, height: 1 },
|
|
30
|
+
b2b: false,
|
|
31
|
+
pieces: [
|
|
32
|
+
{
|
|
33
|
+
sku: 'SKU-1',
|
|
34
|
+
description: 'T-shirt',
|
|
35
|
+
quantity: 1,
|
|
36
|
+
sale_price: 10,
|
|
37
|
+
hs_code: '610910',
|
|
38
|
+
origin_country_code: 'US',
|
|
39
|
+
weight: 1,
|
|
40
|
+
...pieceOverrides,
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const buildXml = (pieceOverrides?: Record<string, unknown>, dangerousGoodsDetails: unknown = '') =>
|
|
46
|
+
new Shipment().buildShipmentRequest(
|
|
47
|
+
shipmentInput(pieceOverrides),
|
|
48
|
+
dangerousGoodsDetails,
|
|
49
|
+
'user',
|
|
50
|
+
'pass',
|
|
51
|
+
true,
|
|
52
|
+
1766,
|
|
53
|
+
'EORI',
|
|
54
|
+
'IOSS',
|
|
55
|
+
'',
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
const itemXml = (xml: string): string => {
|
|
59
|
+
const start = xml.indexOf('<Item>');
|
|
60
|
+
const end = xml.indexOf('</Item>') + '</Item>'.length;
|
|
61
|
+
|
|
62
|
+
return xml.slice(start, end);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const itemChildNames = (xml: string): string[] => {
|
|
66
|
+
const parsed = xml2js(itemXml(xml), { compact: false }) as { elements: { elements: { name: string }[] }[] };
|
|
67
|
+
|
|
68
|
+
return parsed.elements[0].elements.map((element) => element.name);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const productIdentifiers = (xml: string): Record<string, string> | undefined => {
|
|
72
|
+
const parsed = xml2js(itemXml(xml), { compact: true }) as {
|
|
73
|
+
Item: { ProductIdentifiers?: Record<string, { _text: string }> };
|
|
74
|
+
};
|
|
75
|
+
const identifiers = parsed.Item.ProductIdentifiers;
|
|
76
|
+
if (!identifiers) return undefined;
|
|
77
|
+
|
|
78
|
+
return Object.fromEntries(Object.entries(identifiers).map(([name, value]) => [name, value._text]));
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const productIdentifierNames = (xml: string): string[] => {
|
|
82
|
+
const parsed = xml2js(itemXml(xml), { compact: false }) as {
|
|
83
|
+
elements: { elements: { name: string; elements?: { name: string }[] }[] }[];
|
|
84
|
+
};
|
|
85
|
+
const block = parsed.elements[0].elements.find((element) => element.name === 'ProductIdentifiers');
|
|
86
|
+
|
|
87
|
+
return (block?.elements ?? []).map((element) => element.name);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
describe('buildShipmentRequest items', () => {
|
|
91
|
+
it("builds today's item when a piece has no PIDs", () => {
|
|
92
|
+
expect(itemXml(buildXml())).toBe(
|
|
93
|
+
[
|
|
94
|
+
'<Item>',
|
|
95
|
+
' <Sku>SKU-1</Sku>',
|
|
96
|
+
' <Description>T-shirt</Description>',
|
|
97
|
+
' <Quantity>1</Quantity>',
|
|
98
|
+
' <UnitPrice>10</UnitPrice>',
|
|
99
|
+
' <HSCode>610910</HSCode>',
|
|
100
|
+
' <CountryOfOrigin>US</CountryOfOrigin>',
|
|
101
|
+
' </Item>',
|
|
102
|
+
].join('\n'),
|
|
103
|
+
);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('writes the PIDs into ProductIdentifiers, in the spec order, after CountryOfOrigin', () => {
|
|
107
|
+
const xml = buildXml({
|
|
108
|
+
merchant_pid: 'MPID-1',
|
|
109
|
+
ns_manufacturer_pid: 'MX-2024-BLK-L',
|
|
110
|
+
std_manufacturer_pid: '8712345678901',
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
expect(productIdentifiers(xml)).toStrictEqual({
|
|
114
|
+
MerchantProductID: 'MPID-1',
|
|
115
|
+
ManufacturerProductID: 'MX-2024-BLK-L',
|
|
116
|
+
HasStandardizedProductID: '1',
|
|
117
|
+
StandardizedProductID: '8712345678901',
|
|
118
|
+
});
|
|
119
|
+
expect(productIdentifierNames(xml)).toEqual([
|
|
120
|
+
'MerchantProductID',
|
|
121
|
+
'ManufacturerProductID',
|
|
122
|
+
'HasStandardizedProductID',
|
|
123
|
+
'StandardizedProductID',
|
|
124
|
+
]);
|
|
125
|
+
expect(itemChildNames(xml).slice(-2)).toEqual(['CountryOfOrigin', 'ProductIdentifiers']);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('declares no standardised code for Y081, without a StandardizedProductID', () => {
|
|
129
|
+
const xml = buildXml({ ns_manufacturer_pid: 'MX-1', std_manufacturer_pid: 'Y081' });
|
|
130
|
+
|
|
131
|
+
expect(productIdentifiers(xml)).toStrictEqual({
|
|
132
|
+
ManufacturerProductID: 'MX-1',
|
|
133
|
+
HasStandardizedProductID: '0',
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('sends only MerchantProductID when the piece has only a merchant PID', () => {
|
|
138
|
+
expect(productIdentifiers(buildXml({ merchant_pid: 'MPID-1' }))).toStrictEqual({
|
|
139
|
+
MerchantProductID: 'MPID-1',
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it('sends only ManufacturerProductID when the piece has only an NS PID', () => {
|
|
144
|
+
expect(productIdentifiers(buildXml({ ns_manufacturer_pid: 'MX-1' }))).toStrictEqual({
|
|
145
|
+
ManufacturerProductID: 'MX-1',
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('never sends StandardizedProductIDType, whatever the piece type', () => {
|
|
150
|
+
const xml = buildXml({ std_manufacturer_pid: '8712345678901', std_manufacturer_pid_type: 'EAN13' });
|
|
151
|
+
|
|
152
|
+
expect(xml).not.toContain('StandardizedProductIDType');
|
|
153
|
+
expect(productIdentifiers(xml)).toStrictEqual({
|
|
154
|
+
HasStandardizedProductID: '1',
|
|
155
|
+
StandardizedProductID: '8712345678901',
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it('escapes XML special characters in a PID', () => {
|
|
160
|
+
const xml = buildXml({ ns_manufacturer_pid: 'Model: A&B <X>' });
|
|
161
|
+
|
|
162
|
+
expect(xml).toContain('<ManufacturerProductID>Model: A&B <X></ManufacturerProductID>');
|
|
163
|
+
expect(productIdentifiers(xml)).toStrictEqual({ ManufacturerProductID: 'Model: A&B <X>' });
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it('keeps leading zeros', () => {
|
|
167
|
+
expect(productIdentifiers(buildXml({ std_manufacturer_pid: '0012345678905' }))).toStrictEqual({
|
|
168
|
+
HasStandardizedProductID: '1',
|
|
169
|
+
StandardizedProductID: '0012345678905',
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it('puts ProductIdentifiers before DangerousGoodsInformation', () => {
|
|
174
|
+
const dangerousGoodsDetails = { 'SKU-1': { UNCode: 'UN3481', CategoryCode: 'II', PackingInstructions: 'PI967' } };
|
|
175
|
+
const xml = buildXml({ merchant_pid: 'MPID-1' }, dangerousGoodsDetails);
|
|
176
|
+
|
|
177
|
+
expect(itemChildNames(xml).slice(-2)).toEqual(['ProductIdentifiers', 'DangerousGoodsInformation']);
|
|
178
|
+
});
|
|
179
|
+
});
|
package/src/shipment.ts
CHANGED
|
@@ -1,193 +1,213 @@
|
|
|
1
|
-
import { FlavorcloudShipmentResponse } from "./types";
|
|
2
|
-
import { MyGlobal as app } from './globals';
|
|
3
|
-
import { js2xml , xml2json} from 'xml-js';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
"
|
|
112
|
-
"
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
let
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
1
|
+
import { FlavorcloudShipmentResponse, LandmarkProductIdentifiers } from "./types";
|
|
2
|
+
import { MyGlobal as app } from './globals';
|
|
3
|
+
import { js2xml , xml2json} from 'xml-js';
|
|
4
|
+
|
|
5
|
+
const NO_STANDARDISED_CODE_DECLARATION = "Y081";
|
|
6
|
+
|
|
7
|
+
export default class Shipment {
|
|
8
|
+
constructor() {
|
|
9
|
+
|
|
10
|
+
}
|
|
11
|
+
getConsignee(shipto_address: any,targetToCountry:any): any {
|
|
12
|
+
|
|
13
|
+
const combinedAddress = shipto_address.address_line_1 + shipto_address.address_line_2 + shipto_address.address_line_3;
|
|
14
|
+
let consignee: any = {
|
|
15
|
+
"Name": shipto_address.name.slice(0, 50) ,
|
|
16
|
+
"Attention": shipto_address.attention_name.slice(0, 50) ,
|
|
17
|
+
"Address1": combinedAddress.substring(0,60),
|
|
18
|
+
"Address2": combinedAddress.substring(61,120),
|
|
19
|
+
"Address3": combinedAddress.substring(121,180),
|
|
20
|
+
"City": shipto_address.city,
|
|
21
|
+
"State": shipto_address.state,
|
|
22
|
+
"PostalCode": shipto_address.zip,
|
|
23
|
+
"Country": targetToCountry ? targetToCountry : shipto_address.country,
|
|
24
|
+
"Phone": shipto_address.phone.toString(),
|
|
25
|
+
"Email": shipto_address.email,
|
|
26
|
+
"ConsigneeTaxID": shipto_address.federal_tax_id ? shipto_address.federal_tax_id : ""
|
|
27
|
+
};
|
|
28
|
+
return consignee;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
getShipperInfo(shipfrom_address: any,targetFromCountry:any) {
|
|
32
|
+
const combinedAddress = shipfrom_address.address_line_1 + shipfrom_address.address_line_2 + shipfrom_address.address_line_3;
|
|
33
|
+
let shipper: any = {
|
|
34
|
+
"Name": shipfrom_address.name.slice(0, 50) ,
|
|
35
|
+
"Attention": shipfrom_address.attention_name.slice(0, 50) ,
|
|
36
|
+
"Address1": combinedAddress.substring(0,60),
|
|
37
|
+
"Address2": combinedAddress.substring(61,120),
|
|
38
|
+
"Address3": combinedAddress.substring(121,180),
|
|
39
|
+
"City": shipfrom_address.city,
|
|
40
|
+
"State": shipfrom_address.state,
|
|
41
|
+
"PostalCode": shipfrom_address.zip,
|
|
42
|
+
"Country": targetFromCountry ? targetFromCountry : shipfrom_address.country,
|
|
43
|
+
"Phone": shipfrom_address.phone.toString(),
|
|
44
|
+
"Email": shipfrom_address.email
|
|
45
|
+
};
|
|
46
|
+
return shipper;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
getVendorInfo(shipfrom_address: any,targetFromCountry:any,eroiNumber:any,iossNumber:any) {
|
|
50
|
+
const combinedAddress = shipfrom_address.address_line_1 + shipfrom_address.address_line_2 + shipfrom_address.address_line_3;
|
|
51
|
+
let shipper: any = {
|
|
52
|
+
"VendorName": shipfrom_address.name.slice(0, 50) ,
|
|
53
|
+
"Attention": shipfrom_address.attention_name.slice(0, 50) ,
|
|
54
|
+
"VendorAddress1": combinedAddress.substring(0,60),
|
|
55
|
+
"VendorAddress2": combinedAddress.substring(61,120),
|
|
56
|
+
"VendorAddress3": combinedAddress.substring(121,180),
|
|
57
|
+
"VendorCity": shipfrom_address.city,
|
|
58
|
+
"VendorState": shipfrom_address.state,
|
|
59
|
+
"VendorPostalCode": shipfrom_address.zip,
|
|
60
|
+
"VendorCountry": targetFromCountry ? targetFromCountry : shipfrom_address.country,
|
|
61
|
+
"VendorPhone": shipfrom_address.phone.toString(),
|
|
62
|
+
"VendorEmail": shipfrom_address.email,
|
|
63
|
+
"VendorBusinessNumber": "",
|
|
64
|
+
"VendorRGRNumber":"",
|
|
65
|
+
"VendorIOSSNumber":iossNumber,
|
|
66
|
+
"VendorEORINumber":eroiNumber
|
|
67
|
+
};
|
|
68
|
+
return shipper;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
getProductIdentifiers(item: any): LandmarkProductIdentifiers | undefined {
|
|
72
|
+
const identifiers: LandmarkProductIdentifiers = {};
|
|
73
|
+
if (item.merchant_pid) identifiers.MerchantProductID = item.merchant_pid;
|
|
74
|
+
if (item.ns_manufacturer_pid) identifiers.ManufacturerProductID = item.ns_manufacturer_pid;
|
|
75
|
+
|
|
76
|
+
const isNoStandardisedCodeDeclared = item.std_manufacturer_pid === NO_STANDARDISED_CODE_DECLARATION;
|
|
77
|
+
if (isNoStandardisedCodeDeclared) {
|
|
78
|
+
identifiers.HasStandardizedProductID = 0;
|
|
79
|
+
} else if (item.std_manufacturer_pid) {
|
|
80
|
+
identifiers.HasStandardizedProductID = 1;
|
|
81
|
+
identifiers.StandardizedProductID = item.std_manufacturer_pid;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return Object.keys(identifiers).length ? identifiers : undefined;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
buildShipmentRequest(args: any, dangerousGoodsDeatils: any = "", username:string,password:string,test:boolean,clientId:number,vendorEORINumber:any,vendorIOSSNumber:any,reqRegionValue:string): string{
|
|
88
|
+
try {
|
|
89
|
+
const EUCountries = ["BE", "BG", "CZ", "DK", "DE", "EE", "IE", "EL", "ES", "FR", "HR", "IT", "CY", "LV", "LT", "LU", "HU", "MT", "NL", "AT", "PL", "PT", "RO", "SI", "SK", "FI", "SE", "GR"];
|
|
90
|
+
let iossNumber=""
|
|
91
|
+
let regionValue = (reqRegionValue && reqRegionValue != "") ? reqRegionValue : "Landmark BUF"
|
|
92
|
+
if( EUCountries.indexOf(args.shipto_address.country.toUpperCase()) != -1 || EUCountries.indexOf(args.targetToCountry.toUpperCase()) != -1 ){
|
|
93
|
+
iossNumber = vendorIOSSNumber
|
|
94
|
+
}
|
|
95
|
+
let eroiNumber=""
|
|
96
|
+
if(args.shipto_address.country.toUpperCase() == "GB" || args.shipto_address.country.toUpperCase() == "UK"){
|
|
97
|
+
eroiNumber = vendorEORINumber
|
|
98
|
+
}
|
|
99
|
+
let importRequest :any = {
|
|
100
|
+
"Login": {
|
|
101
|
+
"Username": username,
|
|
102
|
+
"Password": password
|
|
103
|
+
},
|
|
104
|
+
"Test": test,
|
|
105
|
+
"ClientID": clientId ,
|
|
106
|
+
"Reference": args.reference,
|
|
107
|
+
"ShipTo": this.getConsignee(args.shipto_address,args.targetToCountry),
|
|
108
|
+
"ShippingLane": {
|
|
109
|
+
"Region" : regionValue
|
|
110
|
+
},
|
|
111
|
+
"ShipMethod": args._carrierRateObj.servicecode,
|
|
112
|
+
"OrderTotal": args.shipment_total_usd,
|
|
113
|
+
"ItemsCurrency": args.currency,
|
|
114
|
+
"ProduceLabel": true,
|
|
115
|
+
"LabelFormat": args.label_format,
|
|
116
|
+
"LabelEncoding": args.label_format.toLowerCase() == "zpl" ? "ZPL" : "LINKS" ,
|
|
117
|
+
"Packages":{
|
|
118
|
+
"Package": {
|
|
119
|
+
"WeightUnit":args.weight_unit,
|
|
120
|
+
"Weight":args.package.weight,
|
|
121
|
+
"DimensionsUnit":args.dimension_unit,
|
|
122
|
+
"Length":args.package.length,
|
|
123
|
+
"Width":args.package.width,
|
|
124
|
+
"Height":args.package.height,
|
|
125
|
+
"PackageReference":args.reference
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
"SendReturnToAddress": this.getShipperInfo(args.shipfrom_address,args.targetFromCountry),
|
|
129
|
+
"VendorInformation": this.getVendorInfo(args.shipfrom_address,args.targetFromCountry,eroiNumber,iossNumber),
|
|
130
|
+
"IsCommercialShipment": args.b2b ? 1 : 0,
|
|
131
|
+
}
|
|
132
|
+
// let items = args.pieces.map((item:any)=>{
|
|
133
|
+
// return {"Item":{
|
|
134
|
+
// "Sku": item.sku || 12345,
|
|
135
|
+
// "Description": item.description.substr(0,100),
|
|
136
|
+
// "Quantity": item.quantity,
|
|
137
|
+
// "UnitPrice": (item.sale_price == 0) ? 0.01 : item.sale_price,
|
|
138
|
+
// "HSCode": item.hs_code,
|
|
139
|
+
// "CountryOfOrigin": item.origin_country_code
|
|
140
|
+
// }
|
|
141
|
+
// }
|
|
142
|
+
// })
|
|
143
|
+
let items = args.pieces.map((item:any) => {
|
|
144
|
+
const productIdentifiers = this.getProductIdentifiers(item);
|
|
145
|
+
let itemObj: any = {
|
|
146
|
+
"Sku": item.sku || 12345,
|
|
147
|
+
"Description": item.description.substr(0, 100),
|
|
148
|
+
"Quantity": item.quantity,
|
|
149
|
+
"UnitPrice": (item.sale_price == 0) ? 0.01 : item.sale_price,
|
|
150
|
+
"HSCode": item.hs_code,
|
|
151
|
+
"CountryOfOrigin": item.origin_country_code,
|
|
152
|
+
...(productIdentifiers && { "ProductIdentifiers": productIdentifiers })
|
|
153
|
+
};
|
|
154
|
+
if(dangerousGoodsDeatils && dangerousGoodsDeatils[item.sku] && dangerousGoodsDeatils[item.sku]['UNCode']){
|
|
155
|
+
let dangerousGoodInformation = {
|
|
156
|
+
"ContainsDangerousGoods": 1,
|
|
157
|
+
"UNCode": dangerousGoodsDeatils[item.sku]['UNCode'] || "",
|
|
158
|
+
"PackingGroup": dangerousGoodsDeatils[item.sku]['CategoryCode'] || "",
|
|
159
|
+
"PackingInstructions": dangerousGoodsDeatils[item.sku]['PackingInstructions'] || "",
|
|
160
|
+
"ItemWeight": item.weight,
|
|
161
|
+
"ItemWeightUnit": args.weight_unit
|
|
162
|
+
}
|
|
163
|
+
itemObj["DangerousGoodsInformation"] = dangerousGoodInformation;
|
|
164
|
+
}
|
|
165
|
+
return itemObj;
|
|
166
|
+
});
|
|
167
|
+
importRequest["Items"] = { "Item": items };
|
|
168
|
+
let request :any = {
|
|
169
|
+
"ImportRequest": importRequest
|
|
170
|
+
}
|
|
171
|
+
const xmlData = js2xml(request, { compact: true, ignoreComment: true, spaces: 4 });
|
|
172
|
+
return xmlData;
|
|
173
|
+
} catch(e) {
|
|
174
|
+
throw app.FlclError?.create({className: 'Shipment', methodName: '_buildRequest', message: 'Exception while building the LandMark shipment request', cause: e, appendChildMsg: true}) || e;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
async createShipment(ShipmentRequest: string): Promise<any> {
|
|
179
|
+
try {
|
|
180
|
+
let configs = {
|
|
181
|
+
headers: {
|
|
182
|
+
'Content-Type' : 'application/xml'
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
let resp = await app.axios!.post(app.ship_url, ShipmentRequest, configs);
|
|
186
|
+
console.log(resp.data)
|
|
187
|
+
app.logger?.info({npm: 'fc-landmark', className: 'Landmark', methodName: 'createShipmet', propertyName: 'Landmark-RAW-RESPOSNE', propertyValue: resp.data});
|
|
188
|
+
let responsejson= xml2json(resp.data,{compact: true, spaces: 4}) ;
|
|
189
|
+
return JSON.parse(responsejson) ;
|
|
190
|
+
} catch(e) {
|
|
191
|
+
app.logger?.info({npm: 'fc-landmark', className: 'Landmark', methodName: 'createShipmet', propertyName: 'Landmark-RAW-RESPOSNE', data: {error: e}});
|
|
192
|
+
app.logger?.error(app.flclError!.create({npm: 'fc-landmark', className: 'Shipment', methodName: 'createShipment', propertyName: 'CREDITS_ERROR', cause: e}));
|
|
193
|
+
throw e;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
buildResponse(resp: any, args: any): FlavorcloudShipmentResponse{
|
|
198
|
+
let response: FlavorcloudShipmentResponse = {
|
|
199
|
+
provider_name: 'Landmark',
|
|
200
|
+
shipping_provider: 'Landmark',
|
|
201
|
+
carrier : 'Landmark',
|
|
202
|
+
tracking_number: resp['ImportResponse']['Result']['Packages']['Package']['TrackingNumber']['_text'],
|
|
203
|
+
provider_tracking_number: resp['ImportResponse']['Result']['Packages']['Package']['TrackingNumber']['_text'],
|
|
204
|
+
shipping_label: args.label_format.toLowerCase() == "zpl" ? resp['ImportResponse']['Result']['Packages']['Package']['LabelImages']['LabelImage']['_text'] : resp['ImportResponse']['Result']['ShipmentLabelLink']['_text'],
|
|
205
|
+
label_type: args.label_format.toLowerCase() == "zpl" ? "zplenc" : "url",
|
|
206
|
+
gross_weight: args.total_weight,
|
|
207
|
+
gross_weight_unit: args.weight_unit,
|
|
208
|
+
submitted_electronically: true
|
|
209
|
+
};
|
|
210
|
+
return response;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
}
|