@things-factory/sales-base 4.3.212 → 4.3.214

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.
@@ -50,7 +50,6 @@ export class ArrivalNoticeMutation {
50
50
  @Mutation(returns => Boolean)
51
51
  async deleteArrivalNotice(@Arg('name') name: string, @Ctx() context: any): Promise<Boolean> {
52
52
  const { tx, user, domain }: { tx: EntityManager; user: User; domain: Domain } = context.state
53
-
54
53
  return await deleteArrivalNotice(tx, name, user, domain)
55
54
  }
56
55
 
@@ -81,7 +80,6 @@ export class ArrivalNoticeMutation {
81
80
  async confirmArrivalNotice(@Arg('name') name: string, @Ctx() context: any): Promise<ArrivalNotice> {
82
81
  const { tx }: { tx: EntityManager } = context.state
83
82
  const arrivalNotice: ArrivalNotice = await confirmArrivalNoticeFunction(name, context, tx)
84
-
85
83
  // If current GAN has cross docking
86
84
  if (arrivalNotice.crossDocking) {
87
85
  const { releaseGood } = await tx.getRepository(ArrivalNotice).findOne(arrivalNotice.id, {
@@ -399,55 +397,65 @@ export async function deleteArrivalNotice(
399
397
  user: User,
400
398
  domain: Domain
401
399
  ): Promise<boolean> {
402
- let foundArrivalNotice: ArrivalNotice = await tx.getRepository(ArrivalNotice).findOne({
403
- where: { domain, name },
404
- relations: ['bizplace', 'releaseGood', 'orderProducts', 'orderVass', 'collectionOrders', 'creator', 'updater']
405
- })
400
+ try {
401
+ let foundArrivalNotice: ArrivalNotice = await tx.getRepository(ArrivalNotice).findOne({
402
+ where: { domain, name },
403
+ relations: ['bizplace', 'releaseGood', 'orderProducts', 'orderVass', 'collectionOrders', 'creator', 'updater']
404
+ })
405
+ if (!foundArrivalNotice) throw new Error(`Arrival notice doesn't exists.`)
406
406
 
407
- if (!foundArrivalNotice) throw new Error(`Arrival notice doesn't exists.`)
407
+ const foundJS: JobSheet = await tx.getRepository(JobSheet).findOne({
408
+ where: {
409
+ bizplace: foundArrivalNotice.bizplace,
410
+ arrivalNoticeRefNo: foundArrivalNotice.name
411
+ }
412
+ })
408
413
 
409
- const foundJS: JobSheet = await tx.getRepository(JobSheet).findOne({
410
- where: {
411
- bizplace: foundArrivalNotice.bizplace,
412
- arrivalNoticeRefNo: foundArrivalNotice.name
414
+ if (foundJS) {
415
+ await tx.getRepository(JobSheet).createQueryBuilder()
416
+ .delete()
417
+ .from(JobSheet)
418
+ .where('id = :id', { id: foundJS.id })
419
+ .execute()
413
420
  }
414
- })
415
-
416
- if (foundJS) await tx.getRepository(JobSheet).delete({ arrivalNoticeRefNo: foundArrivalNotice.name })
417
421
 
418
- const foundOPs: OrderProduct[] = foundArrivalNotice.orderProducts
419
- const foundOVs: OrderVas[] = foundArrivalNotice.orderVass
422
+ const foundOPs: OrderProduct[] = foundArrivalNotice.orderProducts
423
+ const foundOVs: OrderVas[] = foundArrivalNotice.orderVass
420
424
 
421
- // 1. delete order products
422
- const productIds = foundOPs.map((product: OrderProduct) => product.id)
423
- if (productIds.length) {
424
- await tx.getRepository(OrderProduct).delete({ id: In(productIds) })
425
- }
425
+ // 1. delete order products
426
+ await tx.getRepository(OrderProduct).createQueryBuilder('op')
427
+ .delete()
428
+ .from(OrderProduct)
429
+ .where('arrival_notice_id = :arrivalNoticeId', { arrivalNoticeId: foundArrivalNotice.id })
430
+ .execute()
426
431
 
427
- // 2. delete order vass
428
- const vasIds = foundOVs.map((vas: OrderVas) => vas.id)
429
- if (vasIds.length) {
430
- await tx.getRepository(OrderVas).delete({ id: In(vasIds) })
431
- }
432
+ // 2. delete order vass
433
+ const vasIds = foundOVs.map((vas: OrderVas) => vas.id)
434
+ if (vasIds.length) {
435
+ await tx.getRepository(OrderVas).delete({ id: In(vasIds) })
436
+ }
432
437
 
433
- await tx.getRepository(ArrivalNotice).save({
434
- ...foundArrivalNotice,
435
- updater: user
436
- })
438
+ await tx.getRepository(ArrivalNotice).save({
439
+ ...foundArrivalNotice,
440
+ updater: user
441
+ })
437
442
 
438
- // 4. Remove relation with RO if it's cross docking
439
- if (foundArrivalNotice.crossDocking && foundArrivalNotice.releaseGood?.id) {
440
- let releaseGood: ReleaseGood = foundArrivalNotice.releaseGood
441
- releaseGood.arrivalNotice = null
442
- releaseGood = await tx.getRepository(ReleaseGood).save(releaseGood)
443
+ // 4. Remove relation with RO if it's cross docking
444
+ if (foundArrivalNotice.crossDocking && foundArrivalNotice.releaseGood?.id) {
445
+ let releaseGood: ReleaseGood = foundArrivalNotice.releaseGood
446
+ releaseGood.arrivalNotice = null
447
+ releaseGood = await tx.getRepository(ReleaseGood).save(releaseGood)
443
448
 
444
- await tx.getRepository(ArrivalNotice).delete({ domain, name })
445
- await deleteReleaseGood(tx, releaseGood.name, user, domain)
446
- } else {
447
- // 5. delete GAN
448
- await tx.getRepository(ArrivalNotice).delete({ domain, name })
449
+ await tx.getRepository(ArrivalNotice).delete({ domain, name })
450
+ await deleteReleaseGood(tx, releaseGood.name, user, domain)
451
+ } else {
452
+ // 5. delete GAN
453
+ await tx.getRepository(ArrivalNotice).delete({ domain, name })
454
+ }
455
+ return true
456
+ } catch (e) {
457
+ console.log(e)
449
458
  }
450
- return true
451
459
  }
452
460
 
453
461
  export async function generateArrivalNoticeFunction(
@@ -567,122 +575,127 @@ export async function confirmArrivalNoticeFunction(
567
575
  context: any,
568
576
  tx?: EntityManager
569
577
  ): Promise<ArrivalNotice> {
570
- const { user, domain }: { user: User; domain: Domain } = context.state
578
+ try {
579
+ const { user, domain }: { user: User; domain: Domain } = context.state
571
580
 
572
- const foundArrivalNotice: ArrivalNotice = await tx.getRepository(ArrivalNotice).findOne({
573
- where: { domain, name, status: ORDER_STATUS.PENDING },
574
- relations: [
575
- 'bizplace',
576
- 'bizplace.domain',
577
- 'releaseGood',
578
- 'orderProducts',
579
- 'orderProducts.product',
580
- 'orderVass',
581
- 'orderVass.vas',
582
- 'creator',
583
- 'updater'
584
- ]
585
- })
581
+ const foundArrivalNotice: ArrivalNotice = await tx.getRepository(ArrivalNotice).findOne({
582
+ where: { domain, name, status: ORDER_STATUS.PENDING },
583
+ relations: [
584
+ 'bizplace',
585
+ 'bizplace.domain',
586
+ 'releaseGood',
587
+ 'orderProducts',
588
+ 'orderProducts.product',
589
+ 'orderVass',
590
+ 'orderVass.vas',
591
+ 'creator',
592
+ 'updater'
593
+ ]
594
+ })
586
595
 
587
- let foundOPs: OrderProduct[] = foundArrivalNotice.orderProducts
588
- let foundOVs: OrderVas[] = foundArrivalNotice.orderVass
589
- let customerBizplace: Bizplace = foundArrivalNotice.bizplace
590
- let opStatus = ORDER_PRODUCT_STATUS.PENDING_RECEIVE
591
- let anStatus = ORDER_STATUS.PENDING_RECEIVE
592
- let ovStatus = ORDER_VAS_STATUS.PENDING_RECEIVE
593
- let acceptedByUser = null
594
- let acceptedTime = null
595
-
596
- const ganProcessingSetting: Setting = await tx.getRepository(Setting).findOne({
597
- where: { domain, category: 'id-rule', name: 'gan-order-processing' }
598
- })
596
+ let foundOPs: OrderProduct[] = foundArrivalNotice.orderProducts
597
+ let foundOVs: OrderVas[] = foundArrivalNotice.orderVass
598
+ let customerBizplace: Bizplace = foundArrivalNotice.bizplace
599
+ let opStatus = ORDER_PRODUCT_STATUS.PENDING_RECEIVE
600
+ let anStatus = ORDER_STATUS.PENDING_RECEIVE
601
+ let ovStatus = ORDER_VAS_STATUS.PENDING_RECEIVE
602
+ let acceptedByUser = null
603
+ let acceptedTime = null
599
604
 
600
- const partnerGanProcessingSetting: PartnerSetting = await tx.getRepository(PartnerSetting).findOne({
601
- where: { setting: ganProcessingSetting, domain, partnerDomain: customerBizplace?.domain }
602
- })
605
+ const ganProcessingSetting: Setting = await tx.getRepository(Setting).findOne({
606
+ where: { domain, category: 'id-rule', name: 'gan-order-processing' }
607
+ })
603
608
 
604
- // If status of GAN is PENDING_RECEIVE then directly to assign warehouse
605
- if (ganProcessingSetting) {
606
- let setting = !isNaN(partnerGanProcessingSetting?.value)
607
- ? partnerGanProcessingSetting?.value
608
- : ganProcessingSetting.value
609
-
610
- // CONFIRM to assign if setting value is 1
611
- if (setting == 1) {
612
- opStatus = ORDER_PRODUCT_STATUS.ARRIVED
613
- anStatus = ORDER_STATUS.ARRIVED
614
- ovStatus = ORDER_VAS_STATUS.ARRIVED
615
- acceptedByUser = user
616
- acceptedTime = new Date()
617
- }
618
- }
609
+ const partnerGanProcessingSetting: PartnerSetting = await tx.getRepository(PartnerSetting).findOne({
610
+ where: { setting: ganProcessingSetting, domain, partnerDomain: customerBizplace?.domain }
611
+ })
619
612
 
620
- if (!foundArrivalNotice) throw new Error(`Arrival notice doesn't exists.`)
613
+ // If status of GAN is PENDING_RECEIVE then directly to assign warehouse
621
614
 
622
- // 1. GAN Status change (PENDING => PENDING_RECEIVE)
623
- let arrivalNotice: ArrivalNotice = await tx.getRepository(ArrivalNotice).save({
624
- ...foundArrivalNotice,
625
- status: anStatus,
626
- updater: user,
627
- acceptedBy: acceptedByUser,
628
- acceptedAt: acceptedTime
629
- })
615
+ if (ganProcessingSetting) {
616
+ let setting = !isNaN(partnerGanProcessingSetting?.value)
617
+ ? partnerGanProcessingSetting?.value
618
+ : ganProcessingSetting.value
630
619
 
631
- foundOPs = foundOPs.map((op: OrderProduct) => {
632
- return { ...op, status: opStatus }
633
- })
634
- await tx.getRepository(OrderProduct).save(foundOPs)
620
+ // CONFIRM to assign if setting value is 1
621
+ if (setting == 1) {
622
+ opStatus = ORDER_PRODUCT_STATUS.ARRIVED
623
+ anStatus = ORDER_STATUS.ARRIVED
624
+ ovStatus = ORDER_VAS_STATUS.ARRIVED
625
+ acceptedByUser = user
626
+ acceptedTime = new Date()
627
+ }
628
+ }
635
629
 
636
- // 2. Update order vas status if it exists.
637
- if (foundOVs && foundOVs.length) {
638
- foundOVs = foundOVs.map((ov: OrderVas) => {
639
- return { ...ov, status: ovStatus }
630
+ if (!foundArrivalNotice) throw new Error(`Arrival notice doesn't exists.`)
631
+
632
+ // 1. GAN Status change (PENDING => PENDING_RECEIVE)
633
+ await tx.getRepository(ArrivalNotice).update({ id: foundArrivalNotice.id }, {
634
+ status: anStatus,
635
+ updater: user,
636
+ acceptedBy: acceptedByUser,
637
+ acceptedAt: acceptedTime
640
638
  })
641
639
 
642
- await tx.getRepository(OrderVas).save(foundOVs)
643
- }
640
+ let arrivalNotice: ArrivalNotice = await tx.getRepository(ArrivalNotice).findOne({ where: { id: foundArrivalNotice.id } })
644
641
 
645
- // notification logics
646
- // get Office Admin Users
647
- if (context?.state?.type != 'api') {
648
- const users: any[] = await tx
649
- .getRepository('users_roles')
650
- .createQueryBuilder('ur')
651
- .select('ur.users_id', 'id')
652
- .where(qb => {
653
- const subQuery = qb
654
- .subQuery()
655
- .select('role.id')
656
- .from(Role, 'role')
657
- .where("role.name = 'Office Admin'")
658
- .andWhere('role.domain_id = :domain', { domain: domain.id })
659
- .getQuery()
660
- return 'ur.roles_id IN ' + subQuery
661
- })
662
- .getRawMany()
642
+ await tx.getRepository(OrderProduct).createQueryBuilder()
643
+ .update(OrderProduct)
644
+ .set({ status: opStatus })
645
+ .whereInIds(foundOPs.map(op => op.id))
646
+ .execute();
663
647
 
664
- // send notification to Office Admin Users
665
- if (users?.length && context.header?.referer) {
666
- const receivers: any[] = users.map(user => user.id)
667
- const msg = {
668
- title: `New Arrival Notice from ${customerBizplace.name}`,
669
- body: `New incoming order, ${foundArrivalNotice.name} is pending for receiving`,
670
- url: context.header.referer,
671
- data: { url: context.header.referer }
672
- }
648
+ // 2. Update order vas status if it exists.
649
+ if (foundOVs && foundOVs.length) {
650
+ foundOVs = foundOVs.map((ov: OrderVas) => {
651
+ return { ...ov, status: ovStatus }
652
+ })
673
653
 
674
- /**
675
- * @notes Temporary off sendNotification due to suspect of causing wms down
676
- */
654
+ await tx.getRepository(OrderVas).save(foundOVs)
655
+ }
677
656
 
678
- // await sendNotification({
679
- // receivers,
680
- // message: { ...msg }
681
- // })
657
+ // notification logics
658
+ // get Office Admin Users
659
+ if (context?.state?.type != 'api') {
660
+ const users: any[] = await tx
661
+ .getRepository('users_roles')
662
+ .createQueryBuilder('ur')
663
+ .select('ur.users_id', 'id')
664
+ .where(qb => {
665
+ const subQuery = qb
666
+ .subQuery()
667
+ .select('role.id')
668
+ .from(Role, 'role')
669
+ .where("role.name = 'Office Admin'")
670
+ .andWhere('role.domain_id = :domain', { domain: domain.id })
671
+ .getQuery()
672
+ return 'ur.roles_id IN ' + subQuery
673
+ })
674
+ .getRawMany()
675
+ // send notification to Office Admin Users
676
+ if (users?.length && context.header?.referer) {
677
+ const receivers: any[] = users.map(user => user.id)
678
+ const msg = {
679
+ title: `New Arrival Notice from ${customerBizplace.name}`,
680
+ body: `New incoming order, ${foundArrivalNotice.name} is pending for receiving`,
681
+ url: context.header.referer,
682
+ data: { url: context.header.referer }
683
+ }
684
+ /**
685
+ * @notes Temporary off sendNotification due to suspect of causing wms down
686
+ */
687
+
688
+ // await sendNotification({
689
+ // receivers,
690
+ // message: { ...msg }
691
+ // })
692
+ }
682
693
  }
683
- }
684
694
 
685
- return arrivalNotice
695
+ return arrivalNotice
696
+ } catch (e) {
697
+ console.log(e)
698
+ }
686
699
  }
687
700
 
688
701
  export async function receiveArrivalNoticeFunction(_: any, name: String, context: any): Promise<ArrivalNotice> {
@@ -953,8 +966,8 @@ export async function rejectArrivalNotice(
953
966
  }
954
967
 
955
968
  /**
956
- * @notes Temporary off sendNotification due to suspect of causing wms down
957
- */
969
+ * @notes Temporary off sendNotification due to suspect of causing wms down
970
+ */
958
971
 
959
972
  // await sendNotification({
960
973
  // receivers,
@@ -972,8 +985,6 @@ export async function addArrivalNoticeProducts(
972
985
  user: User,
973
986
  tx?: EntityManager
974
987
  ): Promise<void> {
975
- const productRepo: Repository<Product> = tx?.getRepository(Product) || getRepository(Product)
976
- const productDetailRepo: Repository<ProductDetail> = tx?.getRepository(ProductDetail) || getRepository(ProductDetail)
977
988
  const orderProductRepo: Repository<OrderProduct> = tx?.getRepository(OrderProduct) || getRepository(OrderProduct)
978
989
 
979
990
  if (!arrivalNotice?.bizplace || !arrivalNotice?.orderProducts?.length) {
@@ -983,23 +994,44 @@ export async function addArrivalNoticeProducts(
983
994
  })
984
995
  }
985
996
 
986
- const createdOrderProducts: OrderProduct[] = await Promise.all(
987
- newOrderProducts.map(async (op: OrderProduct) => {
988
- return {
989
- ...op,
990
- domain,
991
- bizplace: arrivalNotice.bizplace,
992
- name: OrderNoGenerator.orderProduct(),
993
- product: await productRepo.findOne(op.product.id),
994
- productDetail: await productDetailRepo.findOne(op.productDetail.id),
995
- arrivalNotice,
996
- creator: user
997
- }
997
+ let createdOrderProducts: any[] = []
998
+
999
+ for (let index = 0; index < newOrderProducts.length; index++) {
1000
+ const op = newOrderProducts[index];
1001
+
1002
+ createdOrderProducts.push({
1003
+ name: OrderNoGenerator.orderProduct(),
1004
+ product_id: op.product.id,
1005
+ product_detail_id: op.productDetail.id,
1006
+ batch_id: op.batchId,
1007
+ batch_id_ref: op.batchIdRef,
1008
+ packing_type: op.packingType,
1009
+ packing_size: op.packingSize,
1010
+ uom: op.uom,
1011
+ uom_value: op.uomValue,
1012
+ pack_qty: op.packQty,
1013
+ total_uom_value: op.totalUomValue,
1014
+ unit_price: op.unitPrice,
1015
+ remark: op.remark,
1016
+ manufacture_date: op.manufactureDate,
1017
+ status: op.status,
1018
+ domain_id: domain.id,
1019
+ bizplace_id: arrivalNotice?.bizplaceId || arrivalNotice?.bizplace?.id || arrivalNotice?.bizplace,
1020
+ arrival_notice_id: arrivalNotice.id,
1021
+ creator_id: user.id,
1022
+ updater_id: user.id
1023
+
998
1024
  })
999
- )
1025
+ }
1000
1026
 
1001
- debug('gan-created-order-products', createdOrderProducts)
1002
- await orderProductRepo.save(createdOrderProducts)
1027
+ await orderProductRepo.query(
1028
+ `
1029
+ INSERT INTO order_products ("name", "product_detail_id", "product_id", "batch_id", "batch_id_ref", "packing_type", "packing_size", "uom", "uom_value", "pack_qty", "total_uom_value", "unit_price", "remark", "manufacture_date", "status", "domain_id", "bizplace_id", "arrival_notice_id", "creator_id", "updater_id")
1030
+ SELECT "name", "product_detail_id", "product_id", "batch_id", "batch_id_ref", "packing_type", "packing_size", "uom", "uom_value", "pack_qty", "total_uom_value", "unit_price", "remark", "manufacture_date", "status", "domain_id", "bizplace_id", "arrival_notice_id", "creator_id", "updater_id"
1031
+ FROM JSON_POPULATE_RECORDSET(NULL::order_products, $1) op
1032
+ `,
1033
+ [JSON.stringify(createdOrderProducts)]
1034
+ )
1003
1035
  }
1004
1036
 
1005
1037
  export async function editArrivalNoticeProducts(
@@ -49,12 +49,16 @@ export class ArrivalNoticeQuery {
49
49
 
50
50
  //separate query to improve typeorm mapping performance. Search for Related Order Product
51
51
  let orderProducts = await getRepository(OrderProduct).find({ where: { arrivalNotice: foundGAN }, relations: ['product', 'productDetail'] })
52
- foundGAN.orderProducts = orderProducts
53
-
52
+ foundGAN.orderProducts = await Promise.all(orderProducts.map(async (orderProduct) => {
53
+ orderProduct.unitPrice = orderProduct?.unitPrice ? parseFloat(orderProduct.unitPrice.toFixed(2)) : null;
54
+ orderProduct.adjustedUnitPrice = orderProduct?.adjustedUnitPrice ? parseFloat(orderProduct.adjustedUnitPrice.toFixed(2)) : null;
55
+ return orderProduct;
56
+ }))
57
+
54
58
  //separate query to improve typeorm mapping performance. Search for Related Order Inventory
55
59
  let orderInventories = await getRepository(OrderInventory).find({ where: { arrivalNotice: foundGAN }, relations: ['inventory', 'inventory.product', 'inventory.location'] })
56
60
  foundGAN.orderInventories = orderInventories
57
-
61
+
58
62
  if (name && !foundGAN) throw new Error(`Failed to find arrival notice with ${name}`)
59
63
 
60
64
  if (foundGAN) {
@@ -75,41 +79,6 @@ export class ArrivalNoticeQuery {
75
79
  }
76
80
  })
77
81
  : []
78
-
79
- // add productDetails data to orderProduct.product
80
- foundGAN.orderProducts = await Promise.all(
81
- foundGAN.orderProducts.map(async (orderProduct: OrderProduct) => {
82
- orderProduct.product['productDetails'] = await getRepository(ProductDetail).find({
83
- where: {
84
- product: orderProduct.product.id,
85
- packingType: orderProduct.packingType,
86
- packingSize: orderProduct.packingSize
87
- }
88
- })
89
- orderProduct.unitPrice = orderProduct?.unitPrice ? parseFloat(orderProduct.unitPrice.toFixed(2)) : null
90
- orderProduct.adjustedUnitPrice = orderProduct?.adjustedUnitPrice
91
- ? parseFloat(orderProduct.adjustedUnitPrice.toFixed(2))
92
- : null
93
- return orderProduct
94
- })
95
- )
96
-
97
- // add productDetails data to orderInventory.inventory.product if orderInventory is exist
98
- if (foundGAN.orderInventories && foundGAN.orderInventories.length) {
99
- foundGAN.orderInventories = await Promise.all(
100
- foundGAN.orderInventories.map(async (orderInventory: OrderInventory) => {
101
- orderInventory.inventory.product['productDetails'] = await getRepository(ProductDetail).find({
102
- where: {
103
- product: orderInventory.inventory.product.id,
104
- packingType: orderInventory.inventory.packingType,
105
- packingSize: orderInventory.inventory.packingSize
106
- }
107
- })
108
- return orderInventory
109
- })
110
- )
111
- }
112
-
113
82
  return {
114
83
  ...foundGAN,
115
84
  attachment: [...foundPOAttachments, ...foundAttachments]
@@ -354,7 +354,7 @@ export async function getDraftReleaseGoodFunction(_: any, name: any, context: an
354
354
  remainUomValueWithUom: foundProductInv ? foundProductInv.remainUomValueWithUom : 0,
355
355
  status: foundProductInv?.transferQty
356
356
  ? DRAFT_RELEASE_ORDER_STATUS.TRANSFER
357
- : foundProductInv?.remainQty || 0 < itm.releaseQty
357
+ : (foundProductInv?.remainQty || 0) < itm.releaseQty
358
358
  ? DRAFT_RELEASE_ORDER_STATUS.INSUFFICIENT
359
359
  : DRAFT_RELEASE_ORDER_STATUS.DRAFT
360
360
  }
@@ -66,6 +66,11 @@ import { Replenishment } from '../replenishment/replenishment'
66
66
  orderInventory.uom
67
67
  ])
68
68
  @Index('ix_order-inventory_5', (orderInventory: OrderInventory) => [orderInventory.releaseGood])
69
+
70
+
71
+ @Index('ix_order-inventory_6', (orderInventory: OrderInventory) => [orderInventory.id], {
72
+ unique: true
73
+ })
69
74
  @ObjectType()
70
75
  export class OrderInventory {
71
76
  @PrimaryGeneratedColumn('uuid')