@shushed/helpers 0.0.226-fix-erp-631-20260105165305 → 0.0.226
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/dist/cjs/contracts/index.js +5 -1
- package/dist/cjs/contracts/product-draft.schema.json +159 -5
- package/dist/cjs/contracts/purchase-orderline.schema.json +135 -0
- package/dist/cjs/contracts/stock-movement.schema.json +144 -0
- package/dist/cjs/dist-dereferenced/index.js +5 -1
- package/dist/cjs/dist-dereferenced/messages/product-draft.js +1 -1
- package/dist/cjs/dist-dereferenced/product-draft.js +1 -1
- package/dist/cjs/dist-dereferenced/purchase-orderline.js +4 -0
- package/dist/cjs/dist-dereferenced/stock-movement.js +4 -0
- package/dist/cjs/dist-types/purchase-orderline.js +2 -0
- package/dist/cjs/dist-types/stock-movement.js +2 -0
- package/dist/cjs/src-public/airtable.js +96 -59
- package/dist/cjs/src-public/bcOrder.js +60 -77
- package/dist/cjs/src-public/centra.js +56 -5
- package/dist/cjs/src-public/env.js +1 -1
- package/dist/cjs/src-public/index.js +3 -1
- package/dist/cjs/src-public/pubsub.js +35 -10
- package/dist/cjs/src-public/runtime.js +48 -9
- package/dist/cjs/src-public/sitoo.js +349 -0
- package/dist/cjs/src-public/utils.js +3 -0
- package/dist/package.json +3 -2
- package/dist/types/contracts/index.d.ts +2 -0
- package/dist/types/dist-dereferenced/index.d.ts +2 -0
- package/dist/types/dist-dereferenced/messages/product-draft.d.ts +148 -1
- package/dist/types/dist-dereferenced/product-draft.d.ts +148 -1
- package/dist/types/dist-dereferenced/purchase-orderline.d.ts +114 -0
- package/dist/types/dist-dereferenced/stock-movement.d.ts +110 -0
- package/dist/types/dist-types/index.d.ts +2 -0
- package/dist/types/dist-types/messages/product-draft.d.ts +23 -4
- package/dist/types/dist-types/product-draft.d.ts +23 -4
- package/dist/types/dist-types/purchase-orderline.d.ts +31 -0
- package/dist/types/dist-types/stock-movement.d.ts +30 -0
- package/dist/types/src-public/airtable.d.ts +0 -9
- package/dist/types/src-public/centra.d.ts +3 -0
- package/dist/types/src-public/env.d.ts +1 -1
- package/dist/types/src-public/index.d.ts +1 -0
- package/dist/types/src-public/pubsub.d.ts +4 -1
- package/dist/types/src-public/runtime.d.ts +17 -4
- package/dist/types/src-public/sitoo.d.ts +254 -0
- package/dist/types/src-public/types.d.ts +6 -0
- package/dist/types/src-public/utils.d.ts +1 -1
- package/package.json +4 -3
|
@@ -42,71 +42,107 @@ class AirtableHelper extends runtime_1.default {
|
|
|
42
42
|
}
|
|
43
43
|
return existingRecord;
|
|
44
44
|
}
|
|
45
|
-
async updateMultiple(payload, options = {}
|
|
46
|
-
updatedRecords: [],
|
|
47
|
-
createdRecords: [],
|
|
48
|
-
records: []
|
|
49
|
-
}) {
|
|
45
|
+
async updateMultiple(payload, options = {}) {
|
|
50
46
|
let response = null;
|
|
51
47
|
const tableUrl = `https://api.airtable.com/v0/${this.baseId}/${this.tableId}`;
|
|
52
|
-
const
|
|
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
|
-
return record;
|
|
79
|
-
})
|
|
80
|
-
}),
|
|
48
|
+
const batchSize = 10;
|
|
49
|
+
let collectedResult = {
|
|
50
|
+
updatedRecords: [],
|
|
51
|
+
createdRecords: [],
|
|
52
|
+
records: []
|
|
53
|
+
};
|
|
54
|
+
const fieldsToMergeOn = (options.fieldsToMergeOn || [this.primaryKeyFieldName]);
|
|
55
|
+
const fieldsToMergeOnIds = fieldsToMergeOn.map(x => this.dictionary[x] || x);
|
|
56
|
+
let callIdx = 0;
|
|
57
|
+
const payloadDeduplicated = payload.filter((x, idx, self) => idx === self.findIndex((t) => fieldsToMergeOn.every(field => (0, lodash_isequal_1.default)(t[field], x[field]))));
|
|
58
|
+
const maxCallIdx = Math.ceil(payloadDeduplicated.length / batchSize);
|
|
59
|
+
while (callIdx < maxCallIdx) {
|
|
60
|
+
const currentBatch = payloadDeduplicated.slice(callIdx * batchSize, (callIdx + 1) * batchSize);
|
|
61
|
+
const recordsInBatch = currentBatch.map(x => {
|
|
62
|
+
const recordId = x.$recordId;
|
|
63
|
+
const fieldsWithoutRecordId = { ...x };
|
|
64
|
+
delete fieldsWithoutRecordId.$recordId;
|
|
65
|
+
const record = {
|
|
66
|
+
fields: AirtableHelper.convertToDictionary(this.dictionary, this.primaryKeyWritable === false
|
|
67
|
+
? AirtableHelper.removePrimaryKey(fieldsWithoutRecordId, this.primaryKeyFieldName)
|
|
68
|
+
: fieldsWithoutRecordId),
|
|
69
|
+
};
|
|
70
|
+
if (recordId) {
|
|
71
|
+
record.id = recordId;
|
|
72
|
+
}
|
|
73
|
+
return record;
|
|
81
74
|
});
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
75
|
+
try {
|
|
76
|
+
response = await fetch(`${tableUrl}`, {
|
|
77
|
+
method: "PATCH",
|
|
78
|
+
headers: {
|
|
79
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
80
|
+
"Content-Type": "application/json",
|
|
81
|
+
},
|
|
82
|
+
body: JSON.stringify({
|
|
83
|
+
performUpsert: {
|
|
84
|
+
fieldsToMergeOn: fieldsToMergeOnIds,
|
|
85
|
+
},
|
|
86
|
+
returnFieldsByFieldId: true,
|
|
87
|
+
typecast: options.typecast || false,
|
|
88
|
+
records: recordsInBatch
|
|
89
|
+
}),
|
|
90
|
+
});
|
|
91
|
+
if (!response.ok && response) {
|
|
92
|
+
const text = await response.text().catch(() => `${response?.status || 'unknown'}`);
|
|
93
|
+
throw new Error(text);
|
|
94
|
+
}
|
|
95
|
+
const resp = (await response.json());
|
|
96
|
+
collectedResult = {
|
|
97
|
+
updatedRecords: collectedResult.updatedRecords.concat(resp.updatedRecords),
|
|
98
|
+
createdRecords: collectedResult.createdRecords.concat(resp.createdRecords),
|
|
99
|
+
records: collectedResult.records.concat(resp.records.map(x => AirtableHelper.translateFields(this.dictionary, x)))
|
|
100
|
+
};
|
|
85
101
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
102
|
+
catch (err) {
|
|
103
|
+
const errorMessage = `Failed to update records in ${this.tableId} table (baseId: ${this.baseId}). Status: ${response?.status || 'unknown'}. Error: ${err.message}`;
|
|
104
|
+
const batchErrors = currentBatch.map(() => new Error(errorMessage));
|
|
105
|
+
collectedResult = {
|
|
106
|
+
updatedRecords: collectedResult.updatedRecords,
|
|
107
|
+
createdRecords: collectedResult.createdRecords,
|
|
108
|
+
records: collectedResult.records.concat(batchErrors)
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
finally {
|
|
112
|
+
callIdx += 1;
|
|
94
113
|
}
|
|
95
|
-
return nextCollectedResult;
|
|
96
114
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
115
|
+
const resultInOrder = [];
|
|
116
|
+
for (let i = 0; i < payload.length; i++) {
|
|
117
|
+
let j = 0;
|
|
118
|
+
let foundMatchingRecord = null;
|
|
119
|
+
while (j < collectedResult.records.length && foundMatchingRecord === null) {
|
|
120
|
+
let isMatching = true;
|
|
121
|
+
let k = 0;
|
|
122
|
+
while (k < fieldsToMergeOn.length && isMatching) {
|
|
123
|
+
const field = fieldsToMergeOn[k];
|
|
124
|
+
if (!(0, lodash_isequal_1.default)(collectedResult.records[j].fields[field], payload[i][field])) {
|
|
125
|
+
isMatching = false;
|
|
126
|
+
}
|
|
127
|
+
k += 1;
|
|
128
|
+
}
|
|
129
|
+
if (isMatching) {
|
|
130
|
+
foundMatchingRecord = j;
|
|
131
|
+
}
|
|
132
|
+
j += 1;
|
|
133
|
+
}
|
|
134
|
+
if (foundMatchingRecord !== null) {
|
|
135
|
+
resultInOrder.push(collectedResult.records[foundMatchingRecord]);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
resultInOrder.push(new Error(`Record ${payload[i][this.primaryKeyFieldName]} does not match any record in the response`));
|
|
107
139
|
}
|
|
108
|
-
return nextCollectedResult;
|
|
109
140
|
}
|
|
141
|
+
return {
|
|
142
|
+
updatedRecords: collectedResult.updatedRecords,
|
|
143
|
+
createdRecords: collectedResult.createdRecords,
|
|
144
|
+
records: resultInOrder
|
|
145
|
+
};
|
|
110
146
|
}
|
|
111
147
|
async upsert(payload) {
|
|
112
148
|
const existingRecord = await this.getExistingRecord(payload);
|
|
@@ -258,9 +294,10 @@ class AirtableHelper extends runtime_1.default {
|
|
|
258
294
|
const escapeFormulaValue = (value) => {
|
|
259
295
|
return value.replace(/"/g, '\\"');
|
|
260
296
|
};
|
|
297
|
+
const dedupedKeys = keys.filter((x, idx, self) => self.indexOf(x) === idx);
|
|
261
298
|
const batchSize = 50;
|
|
262
|
-
for (let i = 0; i <
|
|
263
|
-
const batch =
|
|
299
|
+
for (let i = 0; i < dedupedKeys.length; i += batchSize) {
|
|
300
|
+
const batch = dedupedKeys.slice(i, i + batchSize);
|
|
264
301
|
const orConditions = batch.map(key => `${this.dictionary[this.primaryKeyFieldName]} = "${escapeFormulaValue(key)}"`).join(', ');
|
|
265
302
|
const formula = `OR(${orConditions})`;
|
|
266
303
|
const records = await this.getExistingRecords(formula);
|
|
@@ -169,33 +169,30 @@ function transformMasterOrder(payload) {
|
|
|
169
169
|
if (desc)
|
|
170
170
|
skuByDescription[desc] = sku;
|
|
171
171
|
});
|
|
172
|
-
const
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
const amount = Number(line?.amount || line?.amount_excl_vat || 0);
|
|
176
|
-
const amountGross = Number(line?.amount_including_vat || line?.amount_incl_vat || 0);
|
|
177
|
-
const quantity = Number(line?.quantity || 0);
|
|
178
|
-
const hasStyleAndColour = itemNo.includes('-');
|
|
179
|
-
const hasSize = variantCode.trim().length > 0;
|
|
180
|
-
const hasValue = amount > 0 || amountGross > 0 || quantity > 0;
|
|
181
|
-
const hasQuantity = quantity > 0;
|
|
182
|
-
return Boolean(hasStyleAndColour && hasSize && hasValue && hasQuantity);
|
|
172
|
+
const isItemish = (type, itemNo, desc) => {
|
|
173
|
+
const t = String(type || '').toLowerCase();
|
|
174
|
+
return t.includes('item') || itemNo.includes('-') || desc.includes(' - ');
|
|
183
175
|
};
|
|
184
176
|
const returnedQtyBySku = {};
|
|
185
177
|
(payload.credit_memos || []).forEach((cm) => {
|
|
186
178
|
(cm.credit_memo_lines || []).forEach((l) => {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
}
|
|
179
|
+
const itemNo = String(l?.item_no || l?.no || '');
|
|
180
|
+
const desc = String(l?.description || '');
|
|
181
|
+
if (itemNo.toUpperCase() === 'X DELCHR' || itemNo.toUpperCase() === 'REFUND')
|
|
182
|
+
return;
|
|
183
|
+
if ((l?.quantity || 0) <= 0)
|
|
193
184
|
return;
|
|
185
|
+
const typeStr = String(l?.type || '').toLowerCase();
|
|
186
|
+
const isTypeItem = typeStr.includes('item');
|
|
187
|
+
if (isTypeItem) {
|
|
188
|
+
const variant = String(l?.variant_code || '');
|
|
189
|
+
const sku = variant ? `${itemNo}-${variant}` : itemNo;
|
|
190
|
+
returnedQtyBySku[sku] = (returnedQtyBySku[sku] || 0) + (l.quantity || 0);
|
|
191
|
+
}
|
|
192
|
+
else if (desc && skuByDescription[desc]) {
|
|
193
|
+
const sku = skuByDescription[desc];
|
|
194
|
+
returnedQtyBySku[sku] = (returnedQtyBySku[sku] || 0) + (l.quantity || 0);
|
|
194
195
|
}
|
|
195
|
-
const itemNo = String(l?.item_no || l?.no || '');
|
|
196
|
-
const variant = String(l?.variant_code || '');
|
|
197
|
-
const sku = variant ? `${itemNo}-${variant}` : itemNo;
|
|
198
|
-
returnedQtyBySku[sku] = (returnedQtyBySku[sku] || 0) + (l.quantity || 0);
|
|
199
196
|
});
|
|
200
197
|
});
|
|
201
198
|
(payload.sales || []).forEach((sale) => {
|
|
@@ -203,9 +200,14 @@ function transformMasterOrder(payload) {
|
|
|
203
200
|
if (!docTypeRaw.toLowerCase().includes('return'))
|
|
204
201
|
return;
|
|
205
202
|
(sale.sale_lines || []).forEach((l) => {
|
|
206
|
-
if (!isShippableItem(l))
|
|
207
|
-
return;
|
|
208
203
|
const itemNo = String(l?.item_no || l?.no || '');
|
|
204
|
+
const desc = String(l?.description || '');
|
|
205
|
+
if (itemNo.toUpperCase() === 'X DELCHR' || itemNo.toUpperCase() === 'REFUND')
|
|
206
|
+
return;
|
|
207
|
+
if ((l?.quantity || 0) <= 0)
|
|
208
|
+
return;
|
|
209
|
+
if (!isItemish(l?.type, itemNo, desc))
|
|
210
|
+
return;
|
|
209
211
|
const variant = String(l?.variant_code || '');
|
|
210
212
|
const sku = variant ? `${itemNo}-${variant}` : itemNo;
|
|
211
213
|
returnedQtyBySku[sku] = (returnedQtyBySku[sku] || 0) + (l.quantity || 0);
|
|
@@ -235,12 +237,18 @@ function transformMasterOrder(payload) {
|
|
|
235
237
|
const shippedQtyBySku = {};
|
|
236
238
|
(payload.shipments || []).forEach((s) => {
|
|
237
239
|
(s.shipment_lines || []).forEach((l) => {
|
|
238
|
-
if (!isShippableItem(l))
|
|
239
|
-
return;
|
|
240
240
|
const itemNo = String(l?.item_no || l?.no || "");
|
|
241
|
+
if (itemNo.toUpperCase() === 'X DELCHR')
|
|
242
|
+
return;
|
|
243
|
+
const desc = String(l?.description || '');
|
|
244
|
+
const looksProduct = itemNo.includes('-') || desc.includes(' - ');
|
|
245
|
+
const qty = Number(l?.quantity || 0);
|
|
246
|
+
if (!looksProduct)
|
|
247
|
+
return;
|
|
248
|
+
if (qty <= 0)
|
|
249
|
+
return;
|
|
241
250
|
const variant = String(l?.variant_code || "");
|
|
242
251
|
const sku = variant ? `${itemNo}-${variant}` : itemNo;
|
|
243
|
-
const qty = Number(l?.quantity || 0);
|
|
244
252
|
shippedQtyBySku[sku] = (shippedQtyBySku[sku] || 0) + qty;
|
|
245
253
|
});
|
|
246
254
|
});
|
|
@@ -511,30 +519,19 @@ function transformMasterOrder(payload) {
|
|
|
511
519
|
const d = new Date(source.includes("T") ? source : `${source}T00:00:00Z`);
|
|
512
520
|
return isNaN(d.getTime()) ? new Date().toISOString() : d.toISOString();
|
|
513
521
|
};
|
|
514
|
-
const mapCourierName = (shippingAgentCode) => {
|
|
515
|
-
if (!shippingAgentCode || typeof shippingAgentCode !== 'string')
|
|
516
|
-
return null;
|
|
517
|
-
const code = shippingAgentCode.toUpperCase().trim();
|
|
518
|
-
if (code === 'GLOBALE' || code === 'ROYALMAIL' || code === 'EVRI' || code === 'WAITROSE') {
|
|
519
|
-
return code;
|
|
520
|
-
}
|
|
521
|
-
return null;
|
|
522
|
-
};
|
|
523
|
-
const mapClassName = (serviceCode) => {
|
|
524
|
-
if (!serviceCode || typeof serviceCode !== 'string')
|
|
525
|
-
return 'STANDARD';
|
|
526
|
-
const code = serviceCode.toUpperCase().trim();
|
|
527
|
-
if (code.includes('24') || code.includes('EXPRESS') || code.includes('PRIORITY')) {
|
|
528
|
-
return 'PRIORITY';
|
|
529
|
-
}
|
|
530
|
-
return 'STANDARD';
|
|
531
|
-
};
|
|
532
522
|
const mappedShipments = (payload.shipments || []).map((s) => {
|
|
533
523
|
const rawLines = (s.shipment_lines || [])
|
|
534
|
-
.filter((l) =>
|
|
524
|
+
.filter((l) => (l?.quantity ?? 0) > 0)
|
|
525
|
+
.filter((l) => String(l?.item_no || '').toUpperCase() !== 'X DELCHR')
|
|
526
|
+
.filter((l) => {
|
|
527
|
+
const itemNo = String(l?.item_no || '');
|
|
528
|
+
const desc = String(l?.description || '');
|
|
529
|
+
const looksProduct = itemNo.includes('-') || desc.includes(' - ');
|
|
530
|
+
return looksProduct;
|
|
531
|
+
});
|
|
535
532
|
const qtyBySku = new Map();
|
|
536
533
|
rawLines.forEach((l) => {
|
|
537
|
-
const itemNo = String(l?.item_no ||
|
|
534
|
+
const itemNo = String(l?.item_no || '');
|
|
538
535
|
const variant = String(l?.variant_code || '');
|
|
539
536
|
const sku = variant ? `${itemNo}-${variant}` : itemNo;
|
|
540
537
|
const q = Number(l?.quantity || 0);
|
|
@@ -553,9 +550,6 @@ function transformMasterOrder(payload) {
|
|
|
553
550
|
status: statusVal,
|
|
554
551
|
type: statusVal === "SHIPPED" ? "SHIPPED-OUTBOUND" : undefined,
|
|
555
552
|
shipped_by: "TORQUE",
|
|
556
|
-
courier_name: mapCourierName(s.shipping_agent_code),
|
|
557
|
-
tracking_code: (s.torque_tracking_id && typeof s.torque_tracking_id === 'string') ? s.torque_tracking_id : null,
|
|
558
|
-
class_name: mapClassName(s.shipping_agent_service_code),
|
|
559
553
|
items: shipmentLines,
|
|
560
554
|
amount_net: money(0),
|
|
561
555
|
amount_gross: money(0),
|
|
@@ -564,27 +558,28 @@ function transformMasterOrder(payload) {
|
|
|
564
558
|
discount_amount_percent: 0,
|
|
565
559
|
};
|
|
566
560
|
});
|
|
567
|
-
const shipmentsBySku = new Map();
|
|
568
|
-
(payload.shipments || []).forEach((s) => {
|
|
569
|
-
(s.shipment_lines || []).forEach((sl) => {
|
|
570
|
-
if (!isShippableItem(sl))
|
|
571
|
-
return;
|
|
572
|
-
const itemNo = String(sl?.item_no || sl?.no || '');
|
|
573
|
-
const variant = String(sl?.variant_code || '');
|
|
574
|
-
const sku = variant ? `${itemNo}-${variant}` : itemNo;
|
|
575
|
-
if (!shipmentsBySku.has(sku)) {
|
|
576
|
-
shipmentsBySku.set(sku, s);
|
|
577
|
-
}
|
|
578
|
-
});
|
|
579
|
-
});
|
|
580
561
|
const returnShipments = (payload.credit_memos || [])
|
|
581
562
|
.filter((cm) => {
|
|
582
563
|
const lines = cm?.credit_memo_lines || [];
|
|
583
|
-
return lines.some((l) =>
|
|
564
|
+
return lines.some((l) => {
|
|
565
|
+
const itemNo = String(l?.item_no || l?.no || "");
|
|
566
|
+
const upper = itemNo.toUpperCase();
|
|
567
|
+
if (upper === 'X DELCHR' || upper === 'REFUND')
|
|
568
|
+
return false;
|
|
569
|
+
const looksProduct = itemNo.includes('-');
|
|
570
|
+
return (l?.quantity || 0) > 0 && looksProduct;
|
|
571
|
+
});
|
|
584
572
|
})
|
|
585
573
|
.map((cm, idx) => {
|
|
586
574
|
const rawLines = (cm.credit_memo_lines || [])
|
|
587
|
-
.filter((l) =>
|
|
575
|
+
.filter((l) => (l?.quantity || 0) > 0)
|
|
576
|
+
.filter((l) => {
|
|
577
|
+
const itemNo = String(l?.item_no || l?.no || '');
|
|
578
|
+
const upper = itemNo.toUpperCase();
|
|
579
|
+
if (upper === 'X DELCHR' || upper === 'REFUND')
|
|
580
|
+
return false;
|
|
581
|
+
return itemNo.includes('-');
|
|
582
|
+
});
|
|
588
583
|
const qtyBySku = new Map();
|
|
589
584
|
rawLines.forEach((l) => {
|
|
590
585
|
const itemNo = String(l?.item_no || l?.no || '');
|
|
@@ -594,7 +589,6 @@ function transformMasterOrder(payload) {
|
|
|
594
589
|
qtyBySku.set(sku, (qtyBySku.get(sku) || 0) + q);
|
|
595
590
|
});
|
|
596
591
|
const skus = Array.from(qtyBySku.keys()).sort();
|
|
597
|
-
const matchingShipment = skus.length > 0 ? shipmentsBySku.get(skus[0]) : null;
|
|
598
592
|
const lines = skus.map((sku, i) => ({
|
|
599
593
|
lineNumber: i + 1,
|
|
600
594
|
sku,
|
|
@@ -608,17 +602,6 @@ function transformMasterOrder(payload) {
|
|
|
608
602
|
status: "RECEIVED",
|
|
609
603
|
type: "SHIPPED-RETURN",
|
|
610
604
|
shipped_by: "CUSTOMER",
|
|
611
|
-
courier_name: mapCourierName(matchingShipment?.shipping_agent_code || cm.shipping_agent_code),
|
|
612
|
-
tracking_code: (() => {
|
|
613
|
-
if (matchingShipment?.torque_tracking_id && typeof matchingShipment.torque_tracking_id === 'string') {
|
|
614
|
-
return matchingShipment.torque_tracking_id;
|
|
615
|
-
}
|
|
616
|
-
if (cm.torque_tracking_id && typeof cm.torque_tracking_id === 'string') {
|
|
617
|
-
return cm.torque_tracking_id;
|
|
618
|
-
}
|
|
619
|
-
return null;
|
|
620
|
-
})(),
|
|
621
|
-
class_name: mapClassName(matchingShipment?.shipping_agent_service_code || cm.shipping_agent_service_code),
|
|
622
605
|
items: lines,
|
|
623
606
|
amount_net: money(0),
|
|
624
607
|
amount_gross: money(0),
|
|
@@ -783,7 +766,7 @@ function transformMasterOrder(payload) {
|
|
|
783
766
|
return acc + (s.amount_incl_vat || 0);
|
|
784
767
|
}
|
|
785
768
|
const lineAmounts = (s.shipment_lines || []).reduce((lineAcc, l) => {
|
|
786
|
-
if (
|
|
769
|
+
if (isDeliveryItem(l))
|
|
787
770
|
return lineAcc;
|
|
788
771
|
const orderLineNo = Number(l?.order_line_no || -1);
|
|
789
772
|
let sourceLine = orderLineNo > 0 ? sourceLineMap.get(orderLineNo) : null;
|
|
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
const crypto_1 = __importDefault(require("crypto"));
|
|
7
7
|
const env_1 = __importDefault(require("./env"));
|
|
8
8
|
const utils_1 = require("./utils");
|
|
9
|
-
const CACHE_EXPIRATION_MS = 1000 * 60 *
|
|
9
|
+
const CACHE_EXPIRATION_MS = 1000 * 60 * 5;
|
|
10
10
|
class CentraHelper extends env_1.default {
|
|
11
11
|
opts;
|
|
12
12
|
shaToken;
|
|
@@ -99,6 +99,12 @@ class CentraHelper extends env_1.default {
|
|
|
99
99
|
getCacheKeyForMarket(marketExternalId) {
|
|
100
100
|
return `${this.getCacheKeyForMarkets()}_${marketExternalId}`;
|
|
101
101
|
}
|
|
102
|
+
getCacheKeyForCampaigns() {
|
|
103
|
+
return `centra_${this.shaToken}_campaign_name`;
|
|
104
|
+
}
|
|
105
|
+
getCacheKeyForCampaign(campaignName) {
|
|
106
|
+
return `${this.getCacheKeyForCampaigns()}_${campaignName}`;
|
|
107
|
+
}
|
|
102
108
|
getCacheKeyForSizeCharts() {
|
|
103
109
|
return `centra_${this.shaToken}_size_chart_external_id`;
|
|
104
110
|
}
|
|
@@ -130,7 +136,7 @@ class CentraHelper extends env_1.default {
|
|
|
130
136
|
return `${this.getCacheKeyForCentraWarehouses()}_${warehouseExternalId}`;
|
|
131
137
|
}
|
|
132
138
|
getCacheKeyForCentraPricelists() {
|
|
133
|
-
return `centra_${this.shaToken}
|
|
139
|
+
return `centra_${this.shaToken}_pricelists_external_id`;
|
|
134
140
|
}
|
|
135
141
|
getCacheKeyForCentraPricelist(pricelistExternalId) {
|
|
136
142
|
return `${this.getCacheKeyForCentraPricelists()}_${pricelistExternalId}`;
|
|
@@ -218,7 +224,7 @@ class CentraHelper extends env_1.default {
|
|
|
218
224
|
return result;
|
|
219
225
|
}
|
|
220
226
|
async fetchCentraCampaigns(names) {
|
|
221
|
-
const limit = (names
|
|
227
|
+
const limit = names ? (names.length > 200 ? 200 : names.length) : 200;
|
|
222
228
|
let nextCursor = null;
|
|
223
229
|
const result = {};
|
|
224
230
|
do {
|
|
@@ -270,7 +276,7 @@ class CentraHelper extends env_1.default {
|
|
|
270
276
|
nextCursor = null;
|
|
271
277
|
}
|
|
272
278
|
if (campaignConnection && campaignConnection.edges?.length) {
|
|
273
|
-
for (let i =
|
|
279
|
+
for (let i = 0; i < campaignConnection.edges.length; i++) {
|
|
274
280
|
const { node } = campaignConnection.edges[i];
|
|
275
281
|
result[node.name] = node;
|
|
276
282
|
}
|
|
@@ -721,7 +727,9 @@ class CentraHelper extends env_1.default {
|
|
|
721
727
|
}
|
|
722
728
|
else {
|
|
723
729
|
for (const warehouse of warehouses) {
|
|
724
|
-
|
|
730
|
+
if (warehouse.externalId) {
|
|
731
|
+
warehouseToSet[warehouse.externalId] = warehouse;
|
|
732
|
+
}
|
|
725
733
|
}
|
|
726
734
|
await this.set(Object.entries(warehouseToSet).filter(([_, value]) => !(value instanceof Error)).map(([key, value]) => ({ name: this.getCacheKeyForCentraWarehouse(key), value: JSON.stringify(value) })), 'env', {
|
|
727
735
|
ephemeralMs: CACHE_EXPIRATION_MS,
|
|
@@ -797,6 +805,49 @@ class CentraHelper extends env_1.default {
|
|
|
797
805
|
}
|
|
798
806
|
return Object.assign({}, pricelistInCache, pricelistToSet);
|
|
799
807
|
}
|
|
808
|
+
async getCentraCampaigns(alwaysFetch = false) {
|
|
809
|
+
let campaignInCache = {};
|
|
810
|
+
let dedupedCampaignNamesInCache = [];
|
|
811
|
+
let campaignsToFetch = null;
|
|
812
|
+
if (!alwaysFetch) {
|
|
813
|
+
const campaignNamesInCache = await (this.get(this.getCacheKeyForCampaigns(), 'env', {
|
|
814
|
+
isEphemeral: true,
|
|
815
|
+
encrypted: false,
|
|
816
|
+
}).then(x => x ? JSON.parse(x) : null));
|
|
817
|
+
if (campaignNamesInCache) {
|
|
818
|
+
dedupedCampaignNamesInCache = campaignNamesInCache.filter((x, index, self) => self.indexOf(x) === index);
|
|
819
|
+
campaignInCache = Object.fromEntries(Object.entries(await this.get(dedupedCampaignNamesInCache.map((x) => this.getCacheKeyForCampaign(x)), 'env', {
|
|
820
|
+
isEphemeral: true,
|
|
821
|
+
encrypted: false,
|
|
822
|
+
})).map(([key, value]) => [key, value ? JSON.parse(value || 'null') : undefined]).filter(([_, value]) => value));
|
|
823
|
+
campaignsToFetch = dedupedCampaignNamesInCache.filter(x => !campaignInCache[x]);
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
const campaignToSet = {};
|
|
827
|
+
if (!campaignsToFetch || campaignsToFetch.length) {
|
|
828
|
+
const campaigns = await this.fetchCentraCampaigns();
|
|
829
|
+
if (CentraHelper.isCentraErrors(campaigns)) {
|
|
830
|
+
return new Error(`Failed to fetch campaigns: ${campaigns.errors.map((x) => x.message).join(', ')}`);
|
|
831
|
+
}
|
|
832
|
+
else {
|
|
833
|
+
for (const campaign of Object.values(campaigns)) {
|
|
834
|
+
campaignToSet[campaign.name] = campaign;
|
|
835
|
+
}
|
|
836
|
+
await this.set(Object.entries(campaignToSet).filter(([_, value]) => !(value instanceof Error)).map(([key, value]) => ({ name: this.getCacheKeyForCampaign(key), value: JSON.stringify(value) })), 'env', {
|
|
837
|
+
ephemeralMs: CACHE_EXPIRATION_MS,
|
|
838
|
+
encrypted: false,
|
|
839
|
+
});
|
|
840
|
+
await this.set([{
|
|
841
|
+
name: this.getCacheKeyForCampaigns(),
|
|
842
|
+
value: JSON.stringify(Object.keys(campaignToSet)),
|
|
843
|
+
}], 'env', {
|
|
844
|
+
ephemeralMs: CACHE_EXPIRATION_MS,
|
|
845
|
+
encrypted: false,
|
|
846
|
+
});
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
return Object.assign({}, campaignInCache, campaignToSet);
|
|
850
|
+
}
|
|
800
851
|
async getCentraMarkets(alwaysFetch = false) {
|
|
801
852
|
let marketInCache = {};
|
|
802
853
|
let dedupedMarketNamesInCache = [];
|
|
@@ -567,7 +567,7 @@ class EnvEngine extends runtime_1.default {
|
|
|
567
567
|
batchSize: 1,
|
|
568
568
|
subscriptionFilter: null,
|
|
569
569
|
batchWindowSeconds: 10,
|
|
570
|
-
}, Object.fromEntries(Object.entries(rnPartialConfig).filter(x => !(x === null || x === undefined))));
|
|
570
|
+
}, Object.fromEntries(Object.entries(rnPartialConfig).filter(([x]) => !(x === null || x === undefined))));
|
|
571
571
|
return rnConfig;
|
|
572
572
|
}
|
|
573
573
|
createOrUpdateRespectfulNudge(subscriptionName, rnPartialConfig) {
|
|
@@ -17,7 +17,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
17
17
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
18
|
};
|
|
19
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
-
exports.RedisConnectionError = exports.RateLimit = exports.setHeaders = exports.BCOrderHelper = exports.DatoHelper = exports.AirtableHelper = exports.CentraHelper = exports.BigQueryHelper = exports.JWKSHelper = exports.CloudTasksHelper = exports.Secrets = exports.SchedulerHelper = exports.Logging = exports.Runtime = exports.PubSubHelper = exports.EnvEngine = exports.validate = void 0;
|
|
20
|
+
exports.SitooHelper = exports.RedisConnectionError = exports.RateLimit = exports.setHeaders = exports.BCOrderHelper = exports.DatoHelper = exports.AirtableHelper = exports.CentraHelper = exports.BigQueryHelper = exports.JWKSHelper = exports.CloudTasksHelper = exports.Secrets = exports.SchedulerHelper = exports.Logging = exports.Runtime = exports.PubSubHelper = exports.EnvEngine = exports.validate = void 0;
|
|
21
21
|
var validate_1 = require("./validate");
|
|
22
22
|
Object.defineProperty(exports, "validate", { enumerable: true, get: function () { return __importDefault(validate_1).default; } });
|
|
23
23
|
__exportStar(require("./sanitize"), exports);
|
|
@@ -52,3 +52,5 @@ Object.defineProperty(exports, "setHeaders", { enumerable: true, get: function (
|
|
|
52
52
|
var rateLimit_1 = require("./rateLimit");
|
|
53
53
|
Object.defineProperty(exports, "RateLimit", { enumerable: true, get: function () { return __importDefault(rateLimit_1).default; } });
|
|
54
54
|
Object.defineProperty(exports, "RedisConnectionError", { enumerable: true, get: function () { return rateLimit_1.RedisConnectionError; } });
|
|
55
|
+
var sitoo_1 = require("./sitoo");
|
|
56
|
+
Object.defineProperty(exports, "SitooHelper", { enumerable: true, get: function () { return __importDefault(sitoo_1).default; } });
|
|
@@ -79,19 +79,44 @@ class PubSubHelper extends runtime_1.default {
|
|
|
79
79
|
}
|
|
80
80
|
const topic = pubSubPublishTopics[options.topicName];
|
|
81
81
|
const batches = payloads.length > 5 ? (0, lodash_chunk_1.default)(payloads, 10) : [payloads];
|
|
82
|
-
|
|
83
|
-
...options.extraAttributes,
|
|
84
|
-
source_system: options.sourceSystem,
|
|
85
|
-
target_system: options.targetSystem,
|
|
86
|
-
buildship_id: this.systemEnvName + '-' + this.workflowId + '-' + this.triggerId,
|
|
87
|
-
};
|
|
82
|
+
let nextAttributes = {};
|
|
88
83
|
const messageIds = [];
|
|
89
84
|
for (let i = 0; i < batches.length; i++) {
|
|
90
85
|
const batch = batches[i];
|
|
91
|
-
const results = await Promise.allSettled(batch.map((x) =>
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
86
|
+
const results = await Promise.allSettled(batch.map((x) => {
|
|
87
|
+
if (options.attributesGenerator) {
|
|
88
|
+
nextAttributes = Object.fromEntries(Object.entries(options.attributesGenerator(x)).filter(([_, v]) => v !== undefined && v !== null).map(([k, v]) => [k, typeof v === 'boolean' ? (v ? 'yes' : 'no') : `${v}`]));
|
|
89
|
+
}
|
|
90
|
+
if (typeof options.extraAttributes === 'function') {
|
|
91
|
+
nextAttributes = Object.fromEntries(Object.entries(options.extraAttributes ? Object.assign({}, nextAttributes, options.extraAttributes(x)) : nextAttributes).filter(([_, v]) => v !== undefined && v !== null).map(([k, v]) => [k, typeof v === 'boolean' ? (v ? 'yes' : 'no') : `${v}`]));
|
|
92
|
+
}
|
|
93
|
+
else if (typeof options.extraAttributes === 'object') {
|
|
94
|
+
for (const key in options.extraAttributes) {
|
|
95
|
+
let resultForKey;
|
|
96
|
+
if (typeof options.extraAttributes[key] === 'function') {
|
|
97
|
+
resultForKey = options.extraAttributes[key](x);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
resultForKey = options.extraAttributes[key];
|
|
101
|
+
}
|
|
102
|
+
if (typeof resultForKey === 'boolean') {
|
|
103
|
+
nextAttributes[key] = resultForKey ? 'yes' : 'no';
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
nextAttributes[key] = `${resultForKey}`;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
nextAttributes = Object.assign(nextAttributes, {
|
|
110
|
+
source_system: options.sourceSystem,
|
|
111
|
+
target_system: options.targetSystem,
|
|
112
|
+
buildship_id: this.systemEnvName + '-' + this.workflowId + '-' + this.triggerId,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
return topic.publishMessage({
|
|
116
|
+
data: Buffer.from(JSON.stringify(x)),
|
|
117
|
+
attributes: nextAttributes
|
|
118
|
+
});
|
|
119
|
+
}));
|
|
95
120
|
for (const result of results) {
|
|
96
121
|
if (result.status === 'fulfilled') {
|
|
97
122
|
messageIds.push(result.value);
|