@things-factory/worksheet-base 4.3.191 → 4.3.194
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-server/controllers/ecommerce/sellercraft-controller.js +1 -1
- package/dist-server/controllers/ecommerce/sellercraft-controller.js.map +1 -1
- package/dist-server/controllers/outbound/picking-worksheet-controller.js +1 -1
- package/dist-server/controllers/outbound/picking-worksheet-controller.js.map +1 -1
- package/dist-server/controllers/worksheet-controller.js +1 -1
- package/dist-server/controllers/worksheet-controller.js.map +1 -1
- package/dist-server/graphql/resolvers/worksheet/confirm-cancellation-release-order.js +3 -2
- package/dist-server/graphql/resolvers/worksheet/confirm-cancellation-release-order.js.map +1 -1
- package/dist-server/graphql/resolvers/worksheet/picking/complete-batch-picking.js +30 -1
- package/dist-server/graphql/resolvers/worksheet/picking/complete-batch-picking.js.map +1 -1
- package/dist-server/graphql/resolvers/worksheet/picking/complete-picking.js +25 -0
- package/dist-server/graphql/resolvers/worksheet/picking/complete-picking.js.map +1 -1
- package/dist-server/utils/lmd-util.js +138 -1
- package/dist-server/utils/lmd-util.js.map +1 -1
- package/package.json +9 -8
- package/server/controllers/ecommerce/sellercraft-controller.ts +1 -1
- package/server/controllers/outbound/picking-worksheet-controller.ts +34 -9
- package/server/controllers/worksheet-controller.ts +34 -12
- package/server/graphql/resolvers/worksheet/confirm-cancellation-release-order.ts +2 -1
- package/server/graphql/resolvers/worksheet/picking/complete-batch-picking.ts +34 -2
- package/server/graphql/resolvers/worksheet/picking/complete-picking.ts +27 -1
- package/server/utils/lmd-util.ts +186 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EntityManager, getManager, In } from 'typeorm'
|
|
1
|
+
import { EntityManager, getManager, In, getConnection } from 'typeorm'
|
|
2
2
|
|
|
3
3
|
import { ApplicationType, User } from '@things-factory/auth-base'
|
|
4
4
|
import { Bizplace, getMyBizplace } from '@things-factory/biz-base'
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
import { Setting } from '@things-factory/setting-base'
|
|
17
17
|
import { Domain } from '@things-factory/shell'
|
|
18
18
|
import { Inventory } from '@things-factory/warehouse-base'
|
|
19
|
+
import { logger } from '@things-factory/env'
|
|
19
20
|
|
|
20
21
|
import {
|
|
21
22
|
PackingWorksheetController,
|
|
@@ -190,8 +191,39 @@ export async function completeBatchPicking(
|
|
|
190
191
|
}
|
|
191
192
|
|
|
192
193
|
// trigger LMD API to create parcel
|
|
193
|
-
if (
|
|
194
|
+
if (
|
|
195
|
+
foundReleaseGood?.orderPackages?.length &&
|
|
196
|
+
foundReleaseGood.lmdOption &&
|
|
197
|
+
foundReleaseGood.lastMileDelivery &&
|
|
198
|
+
foundReleaseGood?.orderPackages?.some(op => op.parcelId == null)
|
|
199
|
+
) {
|
|
194
200
|
await createLmdParcel([foundReleaseGood], tx)
|
|
201
|
+
// trigger RTS
|
|
202
|
+
try {
|
|
203
|
+
const orderSource: string = foundReleaseGood.source
|
|
204
|
+
|
|
205
|
+
if (orderSource == ApplicationType.SELLERCRAFT) {
|
|
206
|
+
const sellercraft: Sellercraft = await tx.getRepository(Sellercraft).findOne({
|
|
207
|
+
domain: foundReleaseGood.bizplace.domain,
|
|
208
|
+
status: SellercraftStatus.ACTIVE
|
|
209
|
+
})
|
|
210
|
+
if (sellercraft) {
|
|
211
|
+
await getConnection().transaction(async tx => {
|
|
212
|
+
const sellercraftCtrl: SellercraftController = new SellercraftController(tx, null, null)
|
|
213
|
+
const rtsTriggerLevel: Setting = await tx.getRepository(Setting).findOne({
|
|
214
|
+
where: { domain: foundReleaseGood.domain, category: 'id-rule', name: 'rts-trigger-level' }
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
if (rtsTriggerLevel && parseInt(rtsTriggerLevel?.value || 0) == 1) {
|
|
218
|
+
await sellercraftCtrl.initiateOrderShipment(sellercraft, foundReleaseGood)
|
|
219
|
+
}
|
|
220
|
+
})
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
} catch (e) {
|
|
224
|
+
logger.error(`[get-lmd-awb-sof-trigger]: ${e}`)
|
|
225
|
+
}
|
|
226
|
+
//
|
|
195
227
|
}
|
|
196
228
|
//
|
|
197
229
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EntityManager, getManager, In } from 'typeorm'
|
|
1
|
+
import { EntityManager, getManager, In, getConnection } from 'typeorm'
|
|
2
2
|
|
|
3
3
|
import { ApplicationType, User } from '@things-factory/auth-base'
|
|
4
4
|
import { Bizplace, ContactPoint, getMyBizplace } from '@things-factory/biz-base'
|
|
@@ -460,6 +460,32 @@ export async function completePicking(
|
|
|
460
460
|
releaseGood?.orderPackages?.some(op => op.parcelId == null)
|
|
461
461
|
) {
|
|
462
462
|
await createLmdParcel([releaseGood], tx)
|
|
463
|
+
// trigger RTS
|
|
464
|
+
try {
|
|
465
|
+
const orderSource: string = releaseGood.source
|
|
466
|
+
|
|
467
|
+
if (orderSource == ApplicationType.SELLERCRAFT) {
|
|
468
|
+
const sellercraft: Sellercraft = await tx.getRepository(Sellercraft).findOne({
|
|
469
|
+
domain: releaseGood.bizplace.domain,
|
|
470
|
+
status: SellercraftStatus.ACTIVE
|
|
471
|
+
})
|
|
472
|
+
if (sellercraft) {
|
|
473
|
+
await getConnection().transaction(async tx => {
|
|
474
|
+
const sellercraftCtrl: SellercraftController = new SellercraftController(tx, null, null)
|
|
475
|
+
const rtsTriggerLevel: Setting = await tx.getRepository(Setting).findOne({
|
|
476
|
+
where: { domain: releaseGood.domain, category: 'id-rule', name: 'rts-trigger-level' }
|
|
477
|
+
})
|
|
478
|
+
|
|
479
|
+
if (rtsTriggerLevel && parseInt(rtsTriggerLevel?.value || 0) == 1) {
|
|
480
|
+
await sellercraftCtrl.initiateOrderShipment(sellercraft, releaseGood)
|
|
481
|
+
}
|
|
482
|
+
})
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
} catch (e) {
|
|
486
|
+
logger.error(`[get-lmd-awb-sof-trigger]: ${e}`)
|
|
487
|
+
}
|
|
488
|
+
//
|
|
463
489
|
}
|
|
464
490
|
//
|
|
465
491
|
} else {
|
package/server/utils/lmd-util.ts
CHANGED
|
@@ -1,14 +1,29 @@
|
|
|
1
|
+
import { getRepository, getConnection, SelectQueryBuilder } from 'typeorm'
|
|
2
|
+
import { v4 as uuidv4 } from 'uuid'
|
|
3
|
+
|
|
1
4
|
import { LastMileAPI, LastMileDelivery } from '@things-factory/integration-lmd'
|
|
2
5
|
import { logger } from '@things-factory/env'
|
|
3
6
|
import { GeoArea } from '@things-factory/geography'
|
|
4
7
|
import { Bizplace } from '@things-factory/biz-base'
|
|
5
8
|
import { ReleaseGood, OrderPackage } from '@things-factory/sales-base'
|
|
9
|
+
import { Board } from '@things-factory/board-service'
|
|
10
|
+
import { headlessModel, pdf } from '@things-factory/board-service'
|
|
11
|
+
import { Attachment, uploadAwb } from '@things-factory/attachment-base'
|
|
12
|
+
import { Sellercraft, SellercraftStatus } from '@things-factory/integration-sellercraft'
|
|
13
|
+
import { ApplicationType } from '@things-factory/auth-base'
|
|
14
|
+
import { Setting } from '@things-factory/setting-base'
|
|
15
|
+
|
|
16
|
+
// import { SellercraftController } from '../controllers'
|
|
17
|
+
|
|
18
|
+
const LMD_BOARDS = {
|
|
19
|
+
// dhl: 'operato-lmd-dhl-awb',
|
|
20
|
+
airspeed: 'operato-lmd-airspeed-awb'
|
|
21
|
+
}
|
|
6
22
|
|
|
7
23
|
export async function createLmdParcel(releaseGoods, tx) {
|
|
8
24
|
try {
|
|
9
25
|
let parcelsRequest = []
|
|
10
26
|
for (let releaseGood of releaseGoods) {
|
|
11
|
-
|
|
12
27
|
const lmd: LastMileDelivery = releaseGood.lastMileDelivery
|
|
13
28
|
|
|
14
29
|
const bizplace: Bizplace = await tx.getRepository(Bizplace).findOne({
|
|
@@ -27,6 +42,7 @@ export async function createLmdParcel(releaseGoods, tx) {
|
|
|
27
42
|
pickupAccountId: lmd?.pickupAccountId,
|
|
28
43
|
soldToAccountId: lmd?.soldToAccountId,
|
|
29
44
|
token: lmd?.accessToken,
|
|
45
|
+
staging: lmd?.staging,
|
|
30
46
|
|
|
31
47
|
recipient: releaseGood.attentionTo,
|
|
32
48
|
phone: releaseGood.phone1,
|
|
@@ -46,6 +62,8 @@ export async function createLmdParcel(releaseGoods, tx) {
|
|
|
46
62
|
pDistrict: senderGeoArea.cityName,
|
|
47
63
|
pState: senderGeoArea.stateName,
|
|
48
64
|
pCountry: senderGeoArea.countryCode,
|
|
65
|
+
|
|
66
|
+
handoverMethod: 1
|
|
49
67
|
}
|
|
50
68
|
|
|
51
69
|
let unprocessedOrderPackages: OrderPackage[] = releaseGood.orderPackages.filter(op => !op.parcelId)
|
|
@@ -79,8 +97,175 @@ export async function createLmdParcel(releaseGoods, tx) {
|
|
|
79
97
|
for (let parcel of res) {
|
|
80
98
|
await tx.getRepository(OrderPackage).update({ id: parcel.refNo }, { parcelId: parcel.parcelId })
|
|
81
99
|
}
|
|
100
|
+
|
|
101
|
+
const qb: SelectQueryBuilder<OrderPackage> = tx.getRepository(OrderPackage)
|
|
102
|
+
.createQueryBuilder('op')
|
|
103
|
+
.innerJoinAndSelect('op.releaseGood', 'rg')
|
|
104
|
+
.innerJoinAndSelect('rg.domain', 'd')
|
|
105
|
+
.innerJoinAndSelect('rg.bizplace', 'b')
|
|
106
|
+
.innerJoinAndSelect('b.domain', 'd2')
|
|
107
|
+
.leftJoinAndSelect('rg.lastMileDelivery', 'lmd')
|
|
108
|
+
.where('op.id IN (:...orderPackageIds)', { orderPackageIds: res.map(parcel => { return parcel.refNo }) })
|
|
109
|
+
|
|
110
|
+
const orderPackages: OrderPackage[] = await qb.getMany()
|
|
111
|
+
await processAwbAndTrackingNo(orderPackages, tx)
|
|
82
112
|
}
|
|
83
113
|
} catch (e) {
|
|
84
114
|
logger.error(`[lmd-create-parcel]: ${e}`)
|
|
85
115
|
}
|
|
86
116
|
}
|
|
117
|
+
|
|
118
|
+
export async function processAwbAndTrackingNo(orderPackages, tx) {
|
|
119
|
+
let releaseOrders: ReleaseGood = []
|
|
120
|
+
|
|
121
|
+
for (let orderPackage of orderPackages) {
|
|
122
|
+
// await getConnection().transaction(async tx => {
|
|
123
|
+
try {
|
|
124
|
+
let awbRes = await LastMileAPI.getAwb(
|
|
125
|
+
{ ...orderPackage.releaseGood.lastMileDelivery, platform: 'lmdMiddleware' },
|
|
126
|
+
{ parcelId: orderPackage.parcelId, staging: orderPackage.releaseGood.lastMileDelivery?.staging }
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
if (awbRes) {
|
|
130
|
+
let awbContent: any
|
|
131
|
+
const { deliveryConfirmationNo, tracking_no } = awbRes
|
|
132
|
+
if (awbRes.content) {
|
|
133
|
+
awbContent = Buffer.from(awbRes.content, 'base64')
|
|
134
|
+
} else {
|
|
135
|
+
awbContent = await constructAwb(orderPackage, awbRes)
|
|
136
|
+
}
|
|
137
|
+
const awb = await uploadAwbToS3(awbContent, orderPackage)
|
|
138
|
+
await tx.getRepository(OrderPackage).update(
|
|
139
|
+
{ id: orderPackage.id },
|
|
140
|
+
{ airwayBill: awb.url, trackingNo: deliveryConfirmationNo || tracking_no }
|
|
141
|
+
)
|
|
142
|
+
releaseOrders.push(orderPackage.releaseGood)
|
|
143
|
+
}
|
|
144
|
+
} catch (e) {
|
|
145
|
+
logger.error(e)
|
|
146
|
+
}
|
|
147
|
+
// })
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// trigger RTS
|
|
151
|
+
// try {
|
|
152
|
+
// let uniqueReleaseOrders: ReleaseGood = [...new Map(releaseOrders.map(item => [item['id'], item])).values()]
|
|
153
|
+
|
|
154
|
+
// for (let releaseOrder of uniqueReleaseOrders) {
|
|
155
|
+
// const orderSource: string = releaseOrder.source
|
|
156
|
+
|
|
157
|
+
// if (orderSource == ApplicationType.SELLERCRAFT) {
|
|
158
|
+
// const sellercraft: Sellercraft = await getRepository(Sellercraft).findOne({
|
|
159
|
+
// domain: releaseOrder.bizplace.domain,
|
|
160
|
+
// status: SellercraftStatus.ACTIVE
|
|
161
|
+
// })
|
|
162
|
+
// if (sellercraft) {
|
|
163
|
+
// await getConnection().transaction(async tx => {
|
|
164
|
+
// const sellercraftCtrl: SellercraftController = new SellercraftController(tx, null, null)
|
|
165
|
+
// const rtsTriggerLevel: Setting = await tx.getRepository(Setting).findOne({
|
|
166
|
+
// where: { domain: releaseOrder.domain, category: 'id-rule', name: 'rts-trigger-level' }
|
|
167
|
+
// })
|
|
168
|
+
|
|
169
|
+
// if (rtsTriggerLevel && parseInt(rtsTriggerLevel?.value || 0) == 1) {
|
|
170
|
+
// await sellercraftCtrl.initiateOrderShipment(sellercraft, releaseOrder)
|
|
171
|
+
// }
|
|
172
|
+
// })
|
|
173
|
+
// }
|
|
174
|
+
// }
|
|
175
|
+
// }
|
|
176
|
+
// } catch (e) {
|
|
177
|
+
// logger.error(`[get-lmd-awb-sof-trigger]: ${e}`)
|
|
178
|
+
// }
|
|
179
|
+
//
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
async function constructAwb(orderPackage, awbRes) {
|
|
183
|
+
const releaseOrder = orderPackage.releaseOrder
|
|
184
|
+
let {
|
|
185
|
+
shipmentID,
|
|
186
|
+
deliveryConfirmationNo,
|
|
187
|
+
deliveryDepotCode,
|
|
188
|
+
primarySortCode,
|
|
189
|
+
secondarySortCode,
|
|
190
|
+
recipient,
|
|
191
|
+
sender,
|
|
192
|
+
tracking_no,
|
|
193
|
+
courier
|
|
194
|
+
} = awbRes
|
|
195
|
+
|
|
196
|
+
let senderFullAddress = `${sender?.address}${sender?.address2 ? ', ' + sender?.address2 : ''}${
|
|
197
|
+
sender?.district ? ', ' + sender?.district : ''
|
|
198
|
+
}${sender?.city ? ', ' + sender?.city : ''}${sender?.postcode ? ', ' + sender?.postcode : ''}${
|
|
199
|
+
sender?.state ? ', ' + sender?.state : ''
|
|
200
|
+
}`
|
|
201
|
+
|
|
202
|
+
let recipientAddress1 = `${recipient?.address}${recipient?.address2 ? ', ' + recipient?.address2 : ''}${
|
|
203
|
+
recipient?.district ? ', ' + recipient?.district : ''
|
|
204
|
+
}`
|
|
205
|
+
|
|
206
|
+
let recipientAddress2 = `${recipient?.state}${recipient?.city ? ', ' + recipient?.city : ''}${
|
|
207
|
+
recipient?.postcode ? ', ' + recipient?.postcode : ''
|
|
208
|
+
}`
|
|
209
|
+
|
|
210
|
+
let data = {
|
|
211
|
+
senderFullAddress,
|
|
212
|
+
senderName: sender?.name,
|
|
213
|
+
recipientAddress1,
|
|
214
|
+
recipientAddress2,
|
|
215
|
+
recipientPhone: recipient?.phone,
|
|
216
|
+
recipientName: recipient?.name,
|
|
217
|
+
refId: shipmentID,
|
|
218
|
+
deliveryConfirmationNo: deliveryConfirmationNo || tracking_no,
|
|
219
|
+
deliveryDepotCode: deliveryDepotCode,
|
|
220
|
+
primarySortCode: primarySortCode,
|
|
221
|
+
secondarySortCode: secondarySortCode,
|
|
222
|
+
orderNo: releaseOrder?.refNo
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
let lmdBoard: Board = await getRepository(Board).findOne({
|
|
226
|
+
where: { name: LMD_BOARDS[courier] },
|
|
227
|
+
relations: ['domain']
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
if (!lmdBoard) throw new Error(`[get-lmd-awb] board is not found (RO: ${releaseOrder.name})`)
|
|
231
|
+
|
|
232
|
+
const { model } = await headlessModel({ domain: lmdBoard.domain, id: lmdBoard.id })
|
|
233
|
+
|
|
234
|
+
const result = await pdf({
|
|
235
|
+
id: lmdBoard.id,
|
|
236
|
+
model,
|
|
237
|
+
data,
|
|
238
|
+
options: {
|
|
239
|
+
format: 'A4'
|
|
240
|
+
},
|
|
241
|
+
context: { state: { domain: lmdBoard.domain } }
|
|
242
|
+
})
|
|
243
|
+
|
|
244
|
+
return result
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
async function uploadAwbToS3(result, orderPackage) {
|
|
248
|
+
const releaseOrder = orderPackage.releaseGood
|
|
249
|
+
const uuid = uuidv4()
|
|
250
|
+
const awb: any = await uploadAwb({
|
|
251
|
+
content: result,
|
|
252
|
+
title: uuid
|
|
253
|
+
})
|
|
254
|
+
|
|
255
|
+
if (!awb?.url) throw new Error(`[get-lmd-awb] awb was not uploaded for (RO: ${releaseOrder.name})`)
|
|
256
|
+
|
|
257
|
+
// create attachment
|
|
258
|
+
|
|
259
|
+
await getRepository(Attachment).insert({
|
|
260
|
+
name: uuid,
|
|
261
|
+
mimetype: 'application/pdf',
|
|
262
|
+
category: 'LMD_AWB',
|
|
263
|
+
refBy: orderPackage.id,
|
|
264
|
+
path: awb.url,
|
|
265
|
+
domain: releaseOrder.domain,
|
|
266
|
+
size: 0,
|
|
267
|
+
encoding: ''
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
return awb
|
|
271
|
+
}
|