@things-factory/sales-base 4.3.250 → 4.3.252

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,4 +1,4 @@
1
- import { getRepository, EntityManager } from 'typeorm'
1
+ import { getRepository, EntityManager, getConnection } from 'typeorm'
2
2
 
3
3
  import { Bizplace } from '@things-factory/biz-base'
4
4
  import { logger } from '@things-factory/env'
@@ -112,64 +112,12 @@ export class PowrupController {
112
112
  user?: User,
113
113
  trxMgr?: EntityManager
114
114
  ): Promise<void> {
115
- const bizplace: Bizplace = await trxMgr.getRepository(Bizplace).findOne({ domain: customerDomain })
116
- const powrup: Powrup = await trxMgr
117
- .getRepository(Powrup)
118
- .findOne({ where: { platform: Platform.POWRUP, active: true } })
119
-
120
- if (powrup) {
121
- for (let inventory of inventories) {
122
- let product: Product = inventory.product
123
- const productDetail: ProductDetail = inventory.productDetail
124
- const warehouseDomainId: string = inventory.domainId
125
- let qb = await trxMgr.getRepository(Inventory).createQueryBuilder('inv')
126
- qb.leftJoinAndSelect('inv.location', 'loc')
127
- .andWhere('"inv"."domain_id" = :domainId')
128
- .andWhere('"inv"."bizplace_id" = :bizplaceId')
129
- .andWhere('"inv"."product_id" = :productId')
130
- .andWhere('"inv"."product_detail_id" = :productDetailId')
131
- .andWhere('"inv"."status" = :status')
132
- .andWhere('"loc"."type" NOT IN (:...locationTypes)')
133
- .setParameters({
134
- domainId: warehouseDomainId,
135
- bizplaceId: bizplace.id,
136
- productId: product.id,
137
- productDetailId: productDetail.id,
138
- status: INVENTORY_STATUS.STORED,
139
- locationTypes: [LOCATION_TYPE.QUARANTINE]
140
- })
141
-
142
- let inventories: Inventory[] = await qb.getMany()
143
- let inventoryTotalQty: number = 0
144
- let inventoryTotalLockedQty: number = 0
145
- let inventoryBufferQty: number = 0
146
-
147
- inventories.forEach((inventory: Inventory) => {
148
- const { qty, lockedQty } = inventory
149
- inventoryTotalQty += qty
150
- inventoryTotalLockedQty += lockedQty
151
- if (inventory.location.type === LOCATION_TYPE.RESERVE) {
152
- inventoryBufferQty += qty
153
- }
154
- })
155
-
156
- const powrupInvs: any[] = [
157
- {
158
- refCode: productDetail.refCode,
159
- stock: {
160
- quantityTotal: inventoryTotalQty - inventoryTotalLockedQty - inventoryBufferQty || 0,
161
- quantityReserved: inventoryTotalLockedQty - inventoryBufferQty || 0,
162
- quantityBuffer: inventoryBufferQty || 0
163
- }
164
- }
165
- ]
166
-
167
- await PowrupAPI.updateStock(powrup, {
168
- context: { state: { domain: customerDomain || null, user: user || user } },
169
- warehouseDomainId,
170
- powrupInvs
171
- })
172
- }
115
+ if (trxMgr) {
116
+ await this.updateStockFunction(inventories, customerDomain, user, trxMgr)
117
+ } else {
118
+ await getConnection().transaction(async (tx: EntityManager) => {
119
+ await this.updateStockFunction(inventories, customerDomain, user, tx)
120
+ })
173
121
  }
174
122
  }
175
123
 
@@ -260,22 +208,18 @@ export class PowrupController {
260
208
  }
261
209
 
262
210
  const {
263
- documents,
264
211
  trackingNo,
265
- transporter
266
- }: { documents: any[]; trackingNo: string; transporter: string } = await PowrupAPI.fetchDocument(powrup, {
212
+ transporter,
213
+ printLabels
214
+ }: { trackingNo: string; transporter: string; printLabels: any[] } = await PowrupAPI.fetchDocument(powrup, {
267
215
  ...orderInformation,
268
216
  context: { state: { domain: domain || null, user: user || null } }
269
217
  })
270
218
 
271
219
  let updateInfo: any
272
- if (documents?.length) {
273
- documents.map(document => {
274
- if (document.type === 'invoice') {
275
- updateInfo = { ...updateInfo, invoice: document.download_url }
276
- } else if (document.type === 'airway_bill') {
277
- updateInfo = { ...updateInfo, airwayBill: document.download_url }
278
- }
220
+ if (printLabels?.length) {
221
+ printLabels.map(pl => {
222
+ updateInfo = { ...updateInfo, airwayBill: pl.awbUrl }
279
223
  })
280
224
 
281
225
  updateInfo = {
@@ -298,4 +242,75 @@ export class PowrupController {
298
242
  throw error
299
243
  }
300
244
  }
245
+
246
+ async updateStockFunction(
247
+ inventories: Inventory[],
248
+ customerDomain: Domain,
249
+ user?: User,
250
+ trxMgr?: EntityManager
251
+ ): Promise<void> {
252
+ const bizplace: Bizplace = await trxMgr.getRepository(Bizplace).findOne({ domain: customerDomain })
253
+ const powrup: Powrup = await trxMgr
254
+ .getRepository(Powrup)
255
+ .findOne({ where: { platform: Platform.POWRUP, active: true } })
256
+
257
+ if (powrup) {
258
+ for (let inventory of inventories) {
259
+ try {
260
+ let product: Product = inventory.product
261
+ const productDetail: ProductDetail = inventory.productDetail
262
+ const warehouseDomainId: string = inventory.domainId
263
+ let qb = trxMgr.getRepository(Inventory).createQueryBuilder('inv')
264
+ qb.leftJoinAndSelect('inv.location', 'loc')
265
+ .andWhere('"inv"."domain_id" = :domainId')
266
+ .andWhere('"inv"."bizplace_id" = :bizplaceId')
267
+ .andWhere('"inv"."product_id" = :productId')
268
+ .andWhere('"inv"."product_detail_id" = :productDetailId')
269
+ .andWhere('"inv"."status" = :status')
270
+ .andWhere('"loc"."type" NOT IN (:...locationTypes)')
271
+ .setParameters({
272
+ domainId: warehouseDomainId,
273
+ bizplaceId: bizplace.id,
274
+ productId: product.id,
275
+ productDetailId: productDetail.id,
276
+ status: INVENTORY_STATUS.STORED,
277
+ locationTypes: [LOCATION_TYPE.QUARANTINE]
278
+ })
279
+
280
+ let foundInventories: Inventory[] = await qb.getMany()
281
+ let inventoryTotalQty: number = 0
282
+ let inventoryTotalLockedQty: number = 0
283
+ let inventoryBufferQty: number = 0
284
+
285
+ foundInventories.forEach((inventory: Inventory) => {
286
+ const { qty, lockedQty } = inventory
287
+ inventoryTotalQty += qty
288
+ inventoryTotalLockedQty += lockedQty
289
+ if (inventory.location.type === LOCATION_TYPE.RESERVE) {
290
+ inventoryBufferQty += qty
291
+ }
292
+ })
293
+
294
+ const powrupInvs: any[] = [
295
+ {
296
+ refCode: productDetail.refCode,
297
+ stock: {
298
+ quantityTotal: inventoryTotalQty || 0,
299
+ quantityReserved: inventoryTotalLockedQty || 0,
300
+ quantityBuffer: inventoryBufferQty || 0
301
+ }
302
+ }
303
+ ]
304
+
305
+ await PowrupAPI.updateStock(powrup, {
306
+ context: { state: { domain: customerDomain || null, user: user || user } },
307
+ warehouseDomainId,
308
+ powrupInvs
309
+ })
310
+ } catch (e) {
311
+ console.log(e)
312
+ }
313
+ }
314
+ }
315
+ }
301
316
  }
@@ -13,9 +13,12 @@ import {
13
13
  EntityManager,
14
14
  getConnection,
15
15
  getRepository,
16
+ ILike,
16
17
  In,
17
18
  IsNull,
18
- Repository
19
+ Repository,
20
+ SelectQueryBuilder,
21
+ Brackets
19
22
  } from 'typeorm'
20
23
 
21
24
  import {
@@ -77,6 +80,8 @@ import { ShippingOrderPatch } from '../shipping-order/shipping-order-types'
77
80
  // receiveArrivalNoticeFunction
78
81
  // } from '../arrival-notice/arrival-notice-mutation'
79
82
  import { getDraftReleaseGoodFunction } from './draft-release-good-query'
83
+ import { LastMileDelivery } from '@things-factory/integration-lmd'
84
+ import { GeoCountry } from '@things-factory/geography'
80
85
 
81
86
  @Resolver(DraftReleaseGood)
82
87
  export class DraftReleaseGoodMutation {
@@ -244,7 +249,8 @@ export class DraftReleaseGoodMutation {
244
249
  'bizplace.domain',
245
250
  'domain',
246
251
  'creator',
247
- 'updater'
252
+ 'updater',
253
+ 'lastMileDelivery'
248
254
  ]
249
255
  })
250
256
 
@@ -523,6 +529,7 @@ export async function createDraftReleaseGoodFunction(
523
529
  let arrError: string[] = []
524
530
 
525
531
  const settingRepo: Repository<Setting> = tx?.getRepository(Setting) || getRepository(Setting)
532
+ const geoCountryRepo: Repository<GeoCountry> = tx?.getRepository(GeoCountry) || getRepository(GeoCountry)
526
533
 
527
534
  if (draftReleaseGood?.bizplace?.id) {
528
535
  const permittedBizplaces: Bizplace[] = await getPermittedBizplaces(domain, user)
@@ -567,6 +574,25 @@ export async function createDraftReleaseGoodFunction(
567
574
  draftReleaseGood.shippingOrder = newShippingOrder
568
575
  }
569
576
 
577
+ // standardise country
578
+ let deliveryCountry: GeoCountry = draftReleaseGood?.country
579
+ ? await geoCountryRepo.findOne({
580
+ where: [{ name: ILike(draftReleaseGood?.country) }, { description: ILike(draftReleaseGood?.country) }]
581
+ })
582
+ : null
583
+
584
+ let platformCountry: GeoCountry = draftReleaseGood?.platformCountry
585
+ ? await geoCountryRepo.findOne({
586
+ where: [{ name: ILike(draftReleaseGood.platformCountry) }, { description: ILike(draftReleaseGood.platformCountry) }]
587
+ })
588
+ : null
589
+
590
+ // assign lmd
591
+ let lmd: any = null
592
+ if (draftReleaseGood?.lmdOption) {
593
+ lmd = await autoAssignLmd(domain, deliveryCountry?.id, draftReleaseGood?.postalCode)
594
+ }
595
+
570
596
  // // 2. Create draft release good
571
597
  const createdDraftReleaseGood: DraftReleaseGood = await tx.getRepository(DraftReleaseGood).save({
572
598
  ...draftReleaseGood,
@@ -574,7 +600,8 @@ export async function createDraftReleaseGoodFunction(
574
600
  status: DRAFT_RELEASE_ORDER_STATUS.DRAFT,
575
601
  domain,
576
602
  creator: user,
577
- updater: user
603
+ updater: user,
604
+ lastMileDelivery: lmd
578
605
  })
579
606
 
580
607
  // // 3. Create draft release good product
@@ -826,4 +853,34 @@ export async function upsertDraftReleaseGoodProducts(
826
853
  } catch (error) {
827
854
  throw error
828
855
  }
856
+
857
+ }
858
+
859
+ async function autoAssignLmd(domain, countryId, postalCode) {
860
+ const qb: SelectQueryBuilder<LastMileDelivery> = getRepository(LastMileDelivery)
861
+ .createQueryBuilder('lmd')
862
+ .leftJoinAndSelect('lmd.lastMileDeliverySettings', 'lmds')
863
+ .innerJoinAndSelect('lmds.geoCountry', 'gc')
864
+ .where('lmd.domain_id = :domainId', { domainId: domain.id })
865
+ .andWhere('lower(lmd.status) = :status', { status: 'active' })
866
+ .andWhere('gc.id = :gcId', { gcId: countryId })
867
+ .andWhere(
868
+ new Brackets(qb => {
869
+ qb.where(`lmds.include_postal_code = ''`)
870
+ .orWhere('lmds.include_postal_code is null')
871
+ .orWhere('lmds.include_postal_code like :includePostCode', { includePostCode: `%${postalCode}%` })
872
+ })
873
+ )
874
+ .andWhere(
875
+ new Brackets(qb => {
876
+ qb.where(`lmds.exclude_postal_code = ''`)
877
+ .orWhere('lmds.exclude_postal_code is null')
878
+ .orWhere('lmds.exclude_postal_code not like :excludePostCode', { excludePostCode: `%${postalCode}%` })
879
+ })
880
+ )
881
+ .orderBy('lmd.rank')
882
+
883
+ const lmdResult: LastMileDelivery = await qb.getOne()
884
+
885
+ return lmdResult
829
886
  }
@@ -18,6 +18,7 @@ import { User } from '@things-factory/auth-base'
18
18
  import { Bizplace, ContactPoint } from '@things-factory/biz-base'
19
19
  import { config } from '@things-factory/env'
20
20
  import { Domain } from '@things-factory/shell'
21
+ import { LastMileDelivery } from '@things-factory/integration-lmd'
21
22
 
22
23
  import { OrderProduct, ReleaseGood, ShippingOrder, ShippingOrderInfo } from '../'
23
24
  import { ReleaseOrderType } from '../../constants'
@@ -331,4 +332,16 @@ export class DraftReleaseGood {
331
332
  @Column({ nullable: true })
332
333
  @Field({ nullable: true })
333
334
  stopId: string
335
+
336
+ // @Column({ nullable: true })
337
+ // @Field({ nullable: true })
338
+ // lastMileDeliveryId: string
339
+
340
+ @ManyToOne(type => LastMileDelivery)
341
+ @Field(type => LastMileDelivery, { nullable: true })
342
+ lastMileDelivery: LastMileDelivery
343
+
344
+ @RelationId((draftReleaseGood: DraftReleaseGood) => draftReleaseGood.lastMileDelivery)
345
+ lastMileDeliveryId?: string
334
346
  }
347
+
@@ -21,6 +21,7 @@ import { Product, ProductBundleSetting, ProductDetail } from '@things-factory/pr
21
21
  import { PartnerSetting, Setting } from '@things-factory/setting-base'
22
22
  import { Domain } from '@things-factory/shell'
23
23
  import { Inventory, ProductDetailStock } from '@things-factory/warehouse-base'
24
+ import { GeoCountry } from '@things-factory/geography'
24
25
 
25
26
  // import { NewOrderProduct } from '../order-product/order-product-types'
26
27
  import {
@@ -161,7 +162,7 @@ export class ReleaseGoodMutation {
161
162
  childTx
162
163
  )
163
164
  }
164
- } catch (error) {}
165
+ } catch (error) { }
165
166
  })
166
167
 
167
168
  if (errorsCaught.length)
@@ -682,8 +683,8 @@ export async function generateReleaseGoodFunction(
682
683
  orderMethod: releaseGood?.orderMethod
683
684
  ? releaseGood.orderMethod
684
685
  : releaseGood.orderInventories[0]?.inventory?.id
685
- ? ORDER_METHOD.SELECT_BY_PALLET
686
- : ORDER_METHOD.SELECT_BY_PRODUCT,
686
+ ? ORDER_METHOD.SELECT_BY_PALLET
687
+ : ORDER_METHOD.SELECT_BY_PRODUCT,
687
688
  status: ORDER_STATUS.PENDING,
688
689
  packageId: releaseGood?.packageId,
689
690
  storeName: releaseGood?.storeName,
@@ -950,7 +951,7 @@ export async function confirmReleaseGood(name: string, context: any, tx?: Entity
950
951
 
951
952
  let foundReleaseGood: ReleaseGood = await tx.getRepository(ReleaseGood).findOne({
952
953
  where: { name, status: ORDER_STATUS.PENDING },
953
- relations: ['domain', 'bizplace', 'bizplace.domain', 'bizplace.company', 'bizplace.company.domain', 'orderVass']
954
+ relations: ['domain', 'bizplace', 'bizplace.domain', 'bizplace.company', 'bizplace.company.domain', 'orderVass', "lastMileDelivery"]
954
955
  })
955
956
 
956
957
  if (!foundReleaseGood) throw new Error(`Release good order doesn't exists.`)
@@ -985,19 +986,6 @@ export async function confirmReleaseGood(name: string, context: any, tx?: Entity
985
986
  }
986
987
  }
987
988
 
988
- const customerBizplaceId: string = foundReleaseGood.bizplace.id
989
- const companyBizplace: Bizplace = await getCompanyBizplace(domain, null, customerBizplaceId, tx)
990
- const application: Application = await tx
991
- .getRepository(Application)
992
- .findOne({ domain: companyBizplace.domain, status: 'ACTIVE', type: ApplicationType.POWRUP })
993
-
994
- let updatePowrupStock = async powrup => {
995
- if (application) {
996
- const powrupController: PowrupController = new PowrupController()
997
- await powrupController.updateStock(foundOPs, domain, user, tx)
998
- }
999
- }
1000
-
1001
989
  const orderSource: string = foundReleaseGood.source
1002
990
  switch (orderSource) {
1003
991
  case ApplicationType.MMS:
@@ -1083,15 +1071,25 @@ export async function confirmReleaseGood(name: string, context: any, tx?: Entity
1083
1071
  updateSCStock(sellercraft)
1084
1072
  break
1085
1073
 
1086
- case ApplicationType.POWRUP:
1087
- updatePowrupStock(application)
1088
- break
1089
-
1090
1074
  default:
1091
1075
  updateSCStock(sellercraft)
1092
1076
  break
1093
1077
  }
1094
1078
 
1079
+ if (foundReleaseGood.type == 'b2b') {
1080
+ const customerDomain: Domain = foundReleaseGood.bizplace.domain
1081
+ const customerBizplaceId: string = foundReleaseGood.bizplace.id
1082
+ const companyBizplace: Bizplace = await getCompanyBizplace(domain, null, customerBizplaceId, tx)
1083
+ const application: Application = await tx
1084
+ .getRepository(Application)
1085
+ .findOne({ domain: companyBizplace.domain, status: 'ACTIVE', type: ApplicationType.POWRUP })
1086
+
1087
+ if (application) {
1088
+ const powrupController: PowrupController = new PowrupController()
1089
+ await powrupController.updateStock(foundOPs, customerDomain, user, tx)
1090
+ }
1091
+ }
1092
+
1095
1093
  // 1. RO Status change (PENDING => PENDING_RECEIVE)
1096
1094
  const releaseGood: ReleaseGood = await tx.getRepository(ReleaseGood).save({
1097
1095
  ...foundReleaseGood,
@@ -1169,7 +1167,7 @@ export async function receiveReleaseGood(name: string, context: any, tx: EntityM
1169
1167
 
1170
1168
  const foundReleaseGood: ReleaseGood = await tx.getRepository(ReleaseGood).findOne({
1171
1169
  where: { domain, name, status: ORDER_STATUS.PENDING_RECEIVE },
1172
- relations: ['bizplace', 'orderInventories', 'orderVass']
1170
+ relations: ['bizplace', 'orderInventories', 'orderVass', 'lastMileDelivery']
1173
1171
  })
1174
1172
 
1175
1173
  if (!foundReleaseGood) throw new Error(`Release good order doesn't exists.`)
@@ -1320,23 +1318,24 @@ export async function rejectReleaseGood(
1320
1318
  }
1321
1319
  break
1322
1320
 
1323
- case ApplicationType.POWRUP:
1324
- const customerBizplaceId: string = releaseGood.bizplace.id
1325
- const companyBizplace: Bizplace = await getCompanyBizplace(domain, null, customerBizplaceId, tx)
1326
- const application: Application = await tx
1327
- .getRepository(Application)
1328
- .findOne({ domain: companyBizplace.domain, status: 'ACTIVE', type: ApplicationType.POWRUP })
1329
-
1330
- if (application) {
1331
- const powrupController: PowrupController = new PowrupController()
1332
- await powrupController.updateStock(foundOPs, companyBizplace.domain, user, tx)
1333
- }
1334
- break
1335
-
1336
1321
  default:
1337
1322
  break
1338
1323
  }
1339
1324
 
1325
+ if (releaseGood.type == 'b2b') {
1326
+ const customerDomain: Domain = releaseGood.bizplace.domain
1327
+ const customerBizplaceId: string = releaseGood.bizplace.id
1328
+ const companyBizplace: Bizplace = await getCompanyBizplace(domain, null, customerBizplaceId, tx)
1329
+ const application: Application = await tx
1330
+ .getRepository(Application)
1331
+ .findOne({ domain: companyBizplace.domain, status: 'ACTIVE', type: ApplicationType.POWRUP })
1332
+
1333
+ if (application) {
1334
+ const powrupController: PowrupController = new PowrupController()
1335
+ await powrupController.updateStock(foundOPs, customerDomain, user, tx)
1336
+ }
1337
+ }
1338
+
1340
1339
  await tx.getRepository(OrderProduct).save(
1341
1340
  await Promise.all(
1342
1341
  foundOPs.map(async (op: OrderProduct) => {
@@ -1417,6 +1416,12 @@ export async function bulkGenerateReleaseGood(
1417
1416
 
1418
1417
  let bizplace: Bizplace = await tx.getRepository(Bizplace).findOne(bizplaceId)
1419
1418
 
1419
+ let geoCountries: GeoCountry = await tx.getRepository(GeoCountry).find()
1420
+ let geoCountry = null;
1421
+ if (geoCountries.length > 0) {
1422
+ geoCountry = geoCountries.find((gc) => gc?.name.toLowerCase() == releaseGood?.country.toLowerCase())
1423
+ }
1424
+
1420
1425
  let newReleaseGood: ReleaseGood = {
1421
1426
  ...releaseGood,
1422
1427
  name: roNoSetting
@@ -1433,7 +1438,7 @@ export async function bulkGenerateReleaseGood(
1433
1438
  city: releaseGood?.city || null,
1434
1439
  state: releaseGood?.state || null,
1435
1440
  postalCode: releaseGood?.postalCode || null,
1436
- country: releaseGood?.country || null,
1441
+ country: releaseGood?.country?.toLowerCase() == geoCountry?.name?.toLowerCase() ? geoCountry?.description : releaseGood?.country || null,
1437
1442
  phone1: releaseGood?.phone1 || null,
1438
1443
  phone2: releaseGood?.phone2 || null,
1439
1444
  email: releaseGood?.email || null,
@@ -1448,9 +1453,9 @@ export async function bulkGenerateReleaseGood(
1448
1453
  status: ORDER_STATUS.PENDING,
1449
1454
  creator: releaseGood?.creator || user,
1450
1455
  updater: releaseGood?.updater || user,
1456
+ lastMileDeliveryId: releaseGood.lastMileDeliveryId,
1451
1457
  assignedInventory: worksheetPickingAssignment?.value == 'true' ? false : true
1452
1458
  }
1453
-
1454
1459
  newReleaseGood = await tx.getRepository(ReleaseGood).save(newReleaseGood)
1455
1460
 
1456
1461
  /** Generate Shipping Order */
@@ -794,7 +794,6 @@ async function getConditions(
794
794
  let bundleWhereClause = `
795
795
  WHERE pb.status = 'ACTIVATED'
796
796
  `
797
-
798
797
  let whereClause = hasRemainingQty ? ` WHERE "remainQty" > 0 ` : ` WHERE 1 = 1 `
799
798
 
800
799
  let productDetailWhereClause = ``