@things-factory/sales-base 4.0.25 → 4.0.26
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/service/arrival-notice/arrival-notice-query.js +1 -1
- package/dist-server/service/job-sheet/job-sheet-query.js +2 -0
- package/dist-server/service/job-sheet/job-sheet-query.js.map +1 -1
- package/dist-server/service/release-good/release-good-mutation.js +6 -160
- package/dist-server/service/release-good/release-good-mutation.js.map +1 -1
- package/dist-server/service/release-good/release-good-query.js +135 -99
- package/dist-server/service/release-good/release-good-query.js.map +1 -1
- package/dist-server/service/release-good/release-good-types.js +30 -2
- package/dist-server/service/release-good/release-good-types.js.map +1 -1
- package/dist-server/service/release-good/release-good.js +59 -1
- package/dist-server/service/release-good/release-good.js.map +1 -1
- package/package.json +12 -12
- package/server/service/arrival-notice/arrival-notice-query.ts +1 -1
- package/server/service/job-sheet/job-sheet-query.ts +3 -1
- package/server/service/release-good/release-good-mutation.ts +4 -198
- package/server/service/release-good/release-good-query.ts +158 -115
- package/server/service/release-good/release-good-types.ts +24 -2
- package/server/service/release-good/release-good.ts +43 -0
|
@@ -450,7 +450,7 @@ export async function validateBulkArrivalNoticesFunction(
|
|
|
450
450
|
ELSE CASE WHEN tp.batch_id ISNULL THEN 'batch no. is required'
|
|
451
451
|
ELSE CASE WHEN tp.ref_no ISNULL OR tp.ref_no = '' THEN 'ref no. is required'
|
|
452
452
|
ELSE CASE WHEN tp.eta_date ISNULL OR tp.eta_date = '' THEN 'eta date is required'
|
|
453
|
-
ELSE CASE WHEN tp.eta_date::
|
|
453
|
+
ELSE CASE WHEN tp.eta_date::date < now()::date THEN 'backdate is not allowed'
|
|
454
454
|
ELSE CASE WHEN tp.container_no NOTNULL AND tp.container_size ISNULL OR tp.container_no ISNULL AND tp.container_size NOTNULL THEN 'incomplete container information'
|
|
455
455
|
ELSE '' END END END END END END END END AS remark
|
|
456
456
|
FROM
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { User } from '@things-factory/auth-base'
|
|
2
2
|
import { getPermittedBizplaceIds } from '@things-factory/biz-base'
|
|
3
3
|
import { buildQuery, Domain, Filter, Pagination, Sorting } from '@things-factory/shell'
|
|
4
|
-
import { Arg, Ctx, FieldResolver, Query, Resolver, Root } from 'type-graphql'
|
|
4
|
+
import { Arg, Ctx, FieldResolver, Query, Resolver, Root, Directive } from 'type-graphql'
|
|
5
5
|
import { EntityManager, getRepository, SelectQueryBuilder } from 'typeorm'
|
|
6
6
|
import { ArrivalNotice, JobSheetList } from '../'
|
|
7
7
|
import { JobSheet } from './job-sheet'
|
|
8
8
|
|
|
9
9
|
@Resolver(JobSheet)
|
|
10
10
|
export class JobSheetQuery {
|
|
11
|
+
@Directive('@transaction')
|
|
11
12
|
@Query(returns => JobSheetList)
|
|
12
13
|
async jobSheets(
|
|
13
14
|
@Ctx() context: any,
|
|
@@ -65,6 +66,7 @@ export class JobSheetQuery {
|
|
|
65
66
|
return { items, total }
|
|
66
67
|
}
|
|
67
68
|
|
|
69
|
+
@Directive('transaction')
|
|
68
70
|
@Query(returns => JobSheet)
|
|
69
71
|
async jobSheet(@Arg('arrivalNoticeRefNo') arrivalNoticeRefNo: string, @Ctx() context: any): Promise<JobSheet> {
|
|
70
72
|
const { domain, tx }: { domain: Domain; tx: EntityManager } = context.state
|
|
@@ -6,7 +6,6 @@ import { Attachment, createAttachments } from '@things-factory/attachment-base'
|
|
|
6
6
|
import { Partner, Role, User } from '@things-factory/auth-base'
|
|
7
7
|
import {
|
|
8
8
|
Bizplace,
|
|
9
|
-
getCompanyBizplace,
|
|
10
9
|
getDomainUsers,
|
|
11
10
|
getMyBizplace,
|
|
12
11
|
getOutletBizplace,
|
|
@@ -20,7 +19,7 @@ import { sendNotification } from '@things-factory/notification'
|
|
|
20
19
|
import { Product, ProductBundleSetting } from '@things-factory/product-base'
|
|
21
20
|
import { PartnerSetting, Setting } from '@things-factory/setting-base'
|
|
22
21
|
import { Domain } from '@things-factory/shell'
|
|
23
|
-
import { Inventory
|
|
22
|
+
import { Inventory } from '@things-factory/warehouse-base'
|
|
24
23
|
|
|
25
24
|
import {
|
|
26
25
|
ArrivalNotice,
|
|
@@ -49,6 +48,7 @@ import { ValidationError } from '../../errors'
|
|
|
49
48
|
import { InventoryUtil, OrderNoGenerator } from '../../utils'
|
|
50
49
|
import { confirmArrivalNoticeFunction, deleteArrivalNotice } from '../arrival-notice/arrival-notice-mutation'
|
|
51
50
|
import { ReleaseGood } from './release-good'
|
|
51
|
+
import { bulkReleaseGoodsAvailableItemsFunction } from './release-good-query'
|
|
52
52
|
|
|
53
53
|
@Resolver(ReleaseGood)
|
|
54
54
|
export class ReleaseGoodMutation {
|
|
@@ -108,7 +108,7 @@ export class ReleaseGoodMutation {
|
|
|
108
108
|
// update orderInventories if availableItems are valid
|
|
109
109
|
releaseGoods[i].orderInventories = availableItems
|
|
110
110
|
|
|
111
|
-
const createdReleaseGood: ReleaseGood = await
|
|
111
|
+
const createdReleaseGood: ReleaseGood = await bulkGenerateReleaseGood(
|
|
112
112
|
releaseGoods[i],
|
|
113
113
|
bizplaceId,
|
|
114
114
|
roNoSetting,
|
|
@@ -734,200 +734,6 @@ export async function generateReleaseGoodFunction(
|
|
|
734
734
|
}
|
|
735
735
|
}
|
|
736
736
|
|
|
737
|
-
export async function bulkReleaseGoodsAvailableItemsFunction(
|
|
738
|
-
rawReleaseGoods: any[],
|
|
739
|
-
bizplaceId: string,
|
|
740
|
-
context: any,
|
|
741
|
-
tx?: EntityManager
|
|
742
|
-
): Promise<any[]> {
|
|
743
|
-
const { domain }: { domain: Domain } = context.state
|
|
744
|
-
const companyBizplaceId: Bizplace = await getCompanyBizplace(null, null, bizplaceId)
|
|
745
|
-
|
|
746
|
-
if (!rawReleaseGoods) return
|
|
747
|
-
|
|
748
|
-
const json_oi = JSON.stringify(
|
|
749
|
-
rawReleaseGoods.map(raw => {
|
|
750
|
-
return {
|
|
751
|
-
sku: raw.sku,
|
|
752
|
-
packing_type: raw.packingType,
|
|
753
|
-
packing_size: raw.packingSize,
|
|
754
|
-
uom: raw.uom,
|
|
755
|
-
release_qty: raw.releaseQty
|
|
756
|
-
}
|
|
757
|
-
})
|
|
758
|
-
)
|
|
759
|
-
|
|
760
|
-
await tx.query(
|
|
761
|
-
`
|
|
762
|
-
CREATE TEMP TABLE temp_order_products(
|
|
763
|
-
product_id VARCHAR(50),
|
|
764
|
-
sku VARCHAR(150),
|
|
765
|
-
product_info VARCHAR(250),
|
|
766
|
-
packing_type VARCHAR(50),
|
|
767
|
-
packing_size INT,
|
|
768
|
-
uom VARCHAR(10),
|
|
769
|
-
release_qty INT
|
|
770
|
-
);
|
|
771
|
-
`
|
|
772
|
-
)
|
|
773
|
-
|
|
774
|
-
await tx.query(
|
|
775
|
-
`
|
|
776
|
-
INSERT INTO temp_order_products
|
|
777
|
-
SELECT p.id AS product_id, js.sku,
|
|
778
|
-
CASE WHEN p.description NOT IN (NULL, '', '-') THEN CONCAT(p.name, '(', p.description, ')')
|
|
779
|
-
ELSE p.name END AS product_info,
|
|
780
|
-
CASE WHEN js.packing_type NOTNULL AND js.packing_size NOTNULL THEN js.packing_type ELSE pd.packing_type END,
|
|
781
|
-
CASE WHEN js.packing_type NOTNULL AND js.packing_size NOTNULL THEN js.packing_size ELSE pd.packing_size END,
|
|
782
|
-
CASE WHEN js.uom NOTNULL THEN js.uom ELSE pd.uom END,
|
|
783
|
-
js.release_qty
|
|
784
|
-
FROM JSON_POPULATE_RECORDSET(NULL::temp_order_products,'${json_oi}') js
|
|
785
|
-
LEFT JOIN products p ON js.sku = p.sku AND p.bizplace_id = $1
|
|
786
|
-
LEFT JOIN product_details pd ON p.id = pd.product_id AND pd.is_default = TRUE;
|
|
787
|
-
`,
|
|
788
|
-
[companyBizplaceId.id]
|
|
789
|
-
)
|
|
790
|
-
|
|
791
|
-
let availableItems = await tx.query(
|
|
792
|
-
`
|
|
793
|
-
WITH inv AS (
|
|
794
|
-
SELECT i.product_id, foo.sku, foo.product_info, i.batch_id, i.packing_type, i.packing_size, i.uom,
|
|
795
|
-
SUM(i.qty - COALESCE(i.locked_qty, 0)) - COALESCE(
|
|
796
|
-
(
|
|
797
|
-
SELECT SUM(oi.release_qty) FROM order_inventories oi
|
|
798
|
-
WHERE oi.status IN ('PENDING', 'PENDING_RECEIVE', 'PENDING_WORKSHEET', 'PENDING_SPLIT')
|
|
799
|
-
AND oi.inventory_id IS null
|
|
800
|
-
AND oi.product_id = i.product_id::uuid
|
|
801
|
-
AND oi.packing_type = i.packing_type
|
|
802
|
-
AND oi.uom = i.uom
|
|
803
|
-
AND oi.domain_id = $1
|
|
804
|
-
AND oi.bizplace_id = $2
|
|
805
|
-
), 0) as "remain_qty",
|
|
806
|
-
SUM(i.uom_value - COALESCE(i.locked_uom_value, 0)) - COALESCE(
|
|
807
|
-
(
|
|
808
|
-
SELECT SUM(oi.release_uom_value) FROM order_inventories oi
|
|
809
|
-
WHERE oi.status IN ('PENDING', 'PENDING_RECEIVE', 'PENDING_WORKSHEET', 'PENDING_SPLIT')
|
|
810
|
-
AND oi.inventory_id IS null
|
|
811
|
-
AND oi.product_id = i.product_id::uuid
|
|
812
|
-
AND oi.packing_type = i.packing_type
|
|
813
|
-
AND oi.uom = i.uom
|
|
814
|
-
AND oi.domain_id = $1
|
|
815
|
-
AND oi.bizplace_id = $2
|
|
816
|
-
), 0) as "remain_uom_value"
|
|
817
|
-
FROM inventories i
|
|
818
|
-
LEFT JOIN locations l
|
|
819
|
-
ON i.location_id = l.id
|
|
820
|
-
INNER JOIN (
|
|
821
|
-
SELECT top.product_id, top.sku, top.product_info, top.packing_type, top.packing_size, top.uom
|
|
822
|
-
FROM temp_order_products top
|
|
823
|
-
GROUP BY top.product_id, top.sku, top.product_info, top.packing_type, top.packing_size, top.uom
|
|
824
|
-
) AS foo
|
|
825
|
-
ON i.product_id = foo.product_id::uuid
|
|
826
|
-
AND i.packing_type = foo.packing_type
|
|
827
|
-
AND i.packing_size = foo.packing_size
|
|
828
|
-
AND i.uom = foo.uom
|
|
829
|
-
AND i.domain_id = $1
|
|
830
|
-
AND i.bizplace_id = $2
|
|
831
|
-
WHERE l.type NOT IN ($3, $4)
|
|
832
|
-
GROUP BY i.product_id, foo.sku,foo.product_info, i.batch_id, i.packing_type, i.packing_size, i.uom
|
|
833
|
-
ORDER BY foo.sku, remain_qty
|
|
834
|
-
) SELECT * FROM inv WHERE remain_qty > 0
|
|
835
|
-
`,
|
|
836
|
-
[domain.id, bizplaceId, LOCATION_TYPE.QUARANTINE, LOCATION_TYPE.RESERVE]
|
|
837
|
-
)
|
|
838
|
-
|
|
839
|
-
await tx.query('DROP TABLE temp_order_products')
|
|
840
|
-
|
|
841
|
-
availableItems = availableItems.map(item => {
|
|
842
|
-
return {
|
|
843
|
-
productId: item.product_id,
|
|
844
|
-
productInfo: item.product_info,
|
|
845
|
-
sku: item.sku,
|
|
846
|
-
batchId: item.batch_id,
|
|
847
|
-
packingType: item.packing_type,
|
|
848
|
-
packingSize: item.packing_size,
|
|
849
|
-
uom: item.uom,
|
|
850
|
-
remainQty: item.remain_qty,
|
|
851
|
-
remainUomValue: item.remain_uom_value
|
|
852
|
-
}
|
|
853
|
-
})
|
|
854
|
-
|
|
855
|
-
return _extractData(rawReleaseGoods, availableItems)
|
|
856
|
-
}
|
|
857
|
-
|
|
858
|
-
function _extractData(rawData, validatedData) {
|
|
859
|
-
return rawData.map(raw => {
|
|
860
|
-
const idx = validatedData.findIndex(val => {
|
|
861
|
-
const comparison = ['packingType', 'packingSize', 'uom']
|
|
862
|
-
|
|
863
|
-
let a: any = {},
|
|
864
|
-
b: any = {}
|
|
865
|
-
|
|
866
|
-
comparison.forEach(cc => {
|
|
867
|
-
if (raw[cc]) {
|
|
868
|
-
a[cc] = raw[cc]
|
|
869
|
-
b[cc] = val[cc]
|
|
870
|
-
}
|
|
871
|
-
})
|
|
872
|
-
|
|
873
|
-
a = JSON.stringify(Object.fromEntries(Object.entries(a).sort()))
|
|
874
|
-
b = JSON.stringify(Object.fromEntries(Object.entries(b).sort()))
|
|
875
|
-
|
|
876
|
-
return val.sku == raw.sku && a === b
|
|
877
|
-
})
|
|
878
|
-
|
|
879
|
-
let releaseUomValue: number = 0
|
|
880
|
-
|
|
881
|
-
// if sku is matched, assign qty and product id
|
|
882
|
-
if (idx >= 0) {
|
|
883
|
-
const uomValuePerQty: number =
|
|
884
|
-
Math.round((validatedData[idx].remainUomValue / validatedData[idx].remainQty) * 100) / 100
|
|
885
|
-
|
|
886
|
-
// use Math.round again because 4.2 * 6 = 25.200000000000003
|
|
887
|
-
releaseUomValue = Math.round(uomValuePerQty * raw.releaseQty * 100) / 100
|
|
888
|
-
|
|
889
|
-
// assign qty to rawData as much as possible
|
|
890
|
-
raw.assignedQty =
|
|
891
|
-
validatedData[idx].remainQty >= raw.releaseQty
|
|
892
|
-
? raw.releaseQty > 0
|
|
893
|
-
? raw.releaseQty
|
|
894
|
-
: 0
|
|
895
|
-
: validatedData[idx].remainQty > 0
|
|
896
|
-
? validatedData[idx].remainQty
|
|
897
|
-
: 0
|
|
898
|
-
|
|
899
|
-
raw.assignedUomValue =
|
|
900
|
-
validatedData[idx].remainUomValue >= releaseUomValue
|
|
901
|
-
? releaseUomValue > 0
|
|
902
|
-
? releaseUomValue
|
|
903
|
-
: 0
|
|
904
|
-
: validatedData[idx].remainUomValue > 0
|
|
905
|
-
? validatedData[idx].remainUomValue
|
|
906
|
-
: 0
|
|
907
|
-
|
|
908
|
-
// deduct qty & uomValue from validateData
|
|
909
|
-
validatedData[idx].remainQty -= raw.assignedQty
|
|
910
|
-
validatedData[idx].remainUomValue -= raw.assignedUomValue
|
|
911
|
-
|
|
912
|
-
raw.productId = validatedData[idx].productId
|
|
913
|
-
raw.productInfo = validatedData[idx].productInfo
|
|
914
|
-
raw.packingType = validatedData[idx].packingType
|
|
915
|
-
raw.packingSize = validatedData[idx].packingSize
|
|
916
|
-
raw.uom = validatedData[idx].uom
|
|
917
|
-
raw.batchId = validatedData[idx].batchId
|
|
918
|
-
} else {
|
|
919
|
-
raw.assignedQty = 0
|
|
920
|
-
raw.assignedUomValue = 0
|
|
921
|
-
raw.productId = null
|
|
922
|
-
}
|
|
923
|
-
|
|
924
|
-
return {
|
|
925
|
-
...raw,
|
|
926
|
-
releaseUomValue
|
|
927
|
-
}
|
|
928
|
-
})
|
|
929
|
-
}
|
|
930
|
-
|
|
931
737
|
export async function confirmReleaseGood(name: string, context: any, tx?: EntityManager): Promise<ReleaseGood> {
|
|
932
738
|
const { user, domain }: { user: User; domain: Domain } = context.state
|
|
933
739
|
|
|
@@ -1308,7 +1114,7 @@ export async function rejectReleaseGood(
|
|
|
1308
1114
|
return releaseGood
|
|
1309
1115
|
}
|
|
1310
1116
|
|
|
1311
|
-
export async function
|
|
1117
|
+
export async function bulkGenerateReleaseGood(
|
|
1312
1118
|
releaseGood: any,
|
|
1313
1119
|
bizplaceId: string,
|
|
1314
1120
|
roNoSetting: any,
|
|
@@ -7,7 +7,7 @@ import { User } from '@things-factory/auth-base'
|
|
|
7
7
|
import { Bizplace, getCompanyBizplace, getMyBizplace, getPermittedBizplaceIds } from '@things-factory/biz-base'
|
|
8
8
|
import { Product } from '@things-factory/product-base'
|
|
9
9
|
import { buildQuery, Domain, Filter, ListParam, Pagination, Sorting } from '@things-factory/shell'
|
|
10
|
-
import { Inventory } from '@things-factory/warehouse-base'
|
|
10
|
+
import { Inventory, LOCATION_TYPE } from '@things-factory/warehouse-base'
|
|
11
11
|
|
|
12
12
|
import {
|
|
13
13
|
InventoryInfos,
|
|
@@ -477,120 +477,10 @@ export class ReleaseGoodQuery {
|
|
|
477
477
|
@Arg('rawReleaseGoods', type => [NewReleaseGood], { nullable: true }) rawReleaseGoods: NewReleaseGood[],
|
|
478
478
|
@Arg('bizplaceId', type => String) bizplaceId: string
|
|
479
479
|
): Promise<ReleaseGood[]> {
|
|
480
|
-
const {
|
|
481
|
-
const
|
|
482
|
-
|
|
483
|
-
if (!rawReleaseGoods) return
|
|
484
|
-
|
|
485
|
-
const json_oi = JSON.stringify(
|
|
486
|
-
rawReleaseGoods.map(raw => {
|
|
487
|
-
return {
|
|
488
|
-
sku: raw.sku,
|
|
489
|
-
packing_type: raw.packingType,
|
|
490
|
-
packing_size: raw.packingSize,
|
|
491
|
-
uom: raw.uom,
|
|
492
|
-
release_qty: raw.releaseQty
|
|
493
|
-
}
|
|
494
|
-
})
|
|
495
|
-
)
|
|
480
|
+
const { tx }: { tx: EntityManager } = context.state
|
|
481
|
+
const availableItems: any[] = await bulkReleaseGoodsAvailableItemsFunction(rawReleaseGoods, bizplaceId, context, tx)
|
|
496
482
|
|
|
497
|
-
|
|
498
|
-
`
|
|
499
|
-
CREATE TEMP TABLE temp_order_products(
|
|
500
|
-
product_id VARCHAR(50),
|
|
501
|
-
sku VARCHAR(150),
|
|
502
|
-
packing_type VARCHAR(50),
|
|
503
|
-
packing_size INT,
|
|
504
|
-
uom VARCHAR(10),
|
|
505
|
-
release_qty INT
|
|
506
|
-
);
|
|
507
|
-
`
|
|
508
|
-
)
|
|
509
|
-
|
|
510
|
-
await tx.query(
|
|
511
|
-
`
|
|
512
|
-
INSERT INTO temp_order_products
|
|
513
|
-
SELECT p.id AS product_id, js.sku,
|
|
514
|
-
CASE WHEN js.packing_type NOTNULL AND js.packing_size NOTNULL THEN js.packing_type ELSE pd.packing_type END,
|
|
515
|
-
CASE WHEN js.packing_type NOTNULL AND js.packing_size NOTNULL THEN js.packing_size ELSE pd.packing_size END,
|
|
516
|
-
CASE WHEN js.uom NOTNULL THEN js.uom ELSE pd.uom END,
|
|
517
|
-
js.release_qty
|
|
518
|
-
FROM JSON_POPULATE_RECORDSET(NULL::temp_order_products,'${json_oi}') js
|
|
519
|
-
LEFT JOIN products p ON js.sku = p.sku AND p.bizplace_id = $1
|
|
520
|
-
LEFT JOIN product_details pd ON p.id = pd.product_id AND pd.is_default = TRUE;
|
|
521
|
-
`,
|
|
522
|
-
[companyBizplaceId.id]
|
|
523
|
-
)
|
|
524
|
-
|
|
525
|
-
let availableItems = await tx.query(
|
|
526
|
-
`
|
|
527
|
-
SELECT i.product_id, foo.sku, i.batch_id, i.packing_type, i.packing_size, i.uom,
|
|
528
|
-
SUM(i.qty - COALESCE(i.locked_qty, 0)) - COALESCE(
|
|
529
|
-
(
|
|
530
|
-
SELECT SUM(oi.release_qty) FROM order_inventories oi
|
|
531
|
-
WHERE (
|
|
532
|
-
oi.status = 'PENDING'
|
|
533
|
-
OR oi.status = 'PENDING_RECEIVE'
|
|
534
|
-
OR oi.status = 'PENDING_WORKSHEET'
|
|
535
|
-
OR oi.status = 'PENDING_SPLIT'
|
|
536
|
-
)
|
|
537
|
-
AND oi.inventory_id IS null
|
|
538
|
-
AND oi.product_id = i.product_id::uuid
|
|
539
|
-
AND oi.packing_type = i.packing_type
|
|
540
|
-
AND oi.uom = i.uom
|
|
541
|
-
AND oi.domain_id = $1
|
|
542
|
-
AND oi.bizplace_id = $2
|
|
543
|
-
), 0) as "remain_qty",
|
|
544
|
-
SUM(i.uom_value - COALESCE(i.locked_uom_value, 0)) - COALESCE(
|
|
545
|
-
(
|
|
546
|
-
SELECT SUM(oi.release_uom_value) FROM order_inventories oi
|
|
547
|
-
WHERE (
|
|
548
|
-
oi.status = 'PENDING'
|
|
549
|
-
OR oi.status = 'PENDING_RECEIVE'
|
|
550
|
-
OR oi.status = 'PENDING_WORKSHEET'
|
|
551
|
-
OR oi.status = 'PENDING_SPLIT'
|
|
552
|
-
)
|
|
553
|
-
AND oi.inventory_id IS null
|
|
554
|
-
AND oi.product_id = i.product_id::uuid
|
|
555
|
-
AND oi.packing_type = i.packing_type
|
|
556
|
-
AND oi.uom = i.uom
|
|
557
|
-
AND oi.domain_id = $1
|
|
558
|
-
AND oi.bizplace_id = $2
|
|
559
|
-
), 0) as "remain_uom_value"
|
|
560
|
-
FROM inventories i
|
|
561
|
-
INNER JOIN (
|
|
562
|
-
SELECT top.product_id, top.sku, top.packing_type, top.packing_size, top.uom
|
|
563
|
-
FROM temp_order_products top
|
|
564
|
-
GROUP BY top.product_id, top.sku, top.packing_type, top.packing_size, top.uom
|
|
565
|
-
) AS foo
|
|
566
|
-
ON i.product_id = foo.product_id::uuid
|
|
567
|
-
AND i.packing_type = foo.packing_type
|
|
568
|
-
AND i.packing_size = foo.packing_size
|
|
569
|
-
AND i.uom = foo.uom
|
|
570
|
-
AND i.domain_id = $1
|
|
571
|
-
AND i.bizplace_id = $2
|
|
572
|
-
GROUP BY i.product_id, foo.sku, i.batch_id, i.packing_type, i.packing_size, i.uom
|
|
573
|
-
ORDER BY foo.sku, remain_qty
|
|
574
|
-
`,
|
|
575
|
-
[domain.id, bizplaceId]
|
|
576
|
-
)
|
|
577
|
-
|
|
578
|
-
await tx.query('DROP TABLE temp_order_products')
|
|
579
|
-
|
|
580
|
-
availableItems = availableItems.map(item => {
|
|
581
|
-
return {
|
|
582
|
-
productId: item.product_id,
|
|
583
|
-
sku: item.sku,
|
|
584
|
-
batchId: item.batch_id,
|
|
585
|
-
packingType: item.packing_type,
|
|
586
|
-
packingSize: item.packing_size,
|
|
587
|
-
uom: item.uom,
|
|
588
|
-
remainQty: item.remain_qty,
|
|
589
|
-
remainUomValue: item.remain_uom_value
|
|
590
|
-
}
|
|
591
|
-
})
|
|
592
|
-
|
|
593
|
-
return _extractData(rawReleaseGoods, availableItems)
|
|
483
|
+
return availableItems
|
|
594
484
|
}
|
|
595
485
|
|
|
596
486
|
@FieldResolver(type => Domain)
|
|
@@ -689,6 +579,134 @@ async function dropOITempTable(domain: Domain, tx: EntityManager) {
|
|
|
689
579
|
await tx.query(`DROP TABLE oi`)
|
|
690
580
|
}
|
|
691
581
|
|
|
582
|
+
export async function bulkReleaseGoodsAvailableItemsFunction(
|
|
583
|
+
rawReleaseGoods: any[],
|
|
584
|
+
bizplaceId: string,
|
|
585
|
+
context: any,
|
|
586
|
+
tx?: EntityManager
|
|
587
|
+
): Promise<any[]> {
|
|
588
|
+
const { domain }: { domain: Domain } = context.state
|
|
589
|
+
const companyBizplaceId: Bizplace = await getCompanyBizplace(null, null, bizplaceId)
|
|
590
|
+
|
|
591
|
+
if (!rawReleaseGoods) return
|
|
592
|
+
const json_oi = JSON.stringify(
|
|
593
|
+
rawReleaseGoods.map(raw => {
|
|
594
|
+
return {
|
|
595
|
+
sku: raw.sku,
|
|
596
|
+
packing_type: raw.packingType,
|
|
597
|
+
packing_size: raw.packingSize,
|
|
598
|
+
uom: raw.uom,
|
|
599
|
+
release_qty: raw.releaseQty
|
|
600
|
+
}
|
|
601
|
+
})
|
|
602
|
+
)
|
|
603
|
+
|
|
604
|
+
await tx.query(
|
|
605
|
+
`
|
|
606
|
+
CREATE TEMP TABLE raw_release_goods(
|
|
607
|
+
product_id VARCHAR(50),
|
|
608
|
+
product_detail_id VARCHAR(50),
|
|
609
|
+
sku VARCHAR(150),
|
|
610
|
+
product_info VARCHAR(250),
|
|
611
|
+
packing_type VARCHAR(50),
|
|
612
|
+
packing_size INT,
|
|
613
|
+
uom VARCHAR(10),
|
|
614
|
+
release_qty INT
|
|
615
|
+
);
|
|
616
|
+
`
|
|
617
|
+
)
|
|
618
|
+
|
|
619
|
+
await tx.query(
|
|
620
|
+
`
|
|
621
|
+
INSERT INTO raw_release_goods
|
|
622
|
+
SELECT p.id AS product_id,
|
|
623
|
+
pd.id AS product_detail_id,
|
|
624
|
+
js.sku,
|
|
625
|
+
CASE WHEN p.description NOT IN (NULL, '', '-') THEN CONCAT(p.name, '(', p.description, ')')
|
|
626
|
+
ELSE p.name END AS product_info,
|
|
627
|
+
CASE WHEN js.packing_type NOTNULL AND js.packing_size NOTNULL THEN js.packing_type ELSE pd.packing_type END,
|
|
628
|
+
CASE WHEN js.packing_type NOTNULL AND js.packing_size NOTNULL THEN js.packing_size ELSE pd.packing_size END,
|
|
629
|
+
CASE WHEN js.uom NOTNULL THEN js.uom ELSE pd.uom END
|
|
630
|
+
FROM JSON_POPULATE_RECORDSET(NULL::raw_release_goods, $1) js
|
|
631
|
+
LEFT JOIN products p ON js.sku = p.sku AND p.bizplace_id = $2
|
|
632
|
+
LEFT JOIN product_details pd ON p.id = pd.product_id
|
|
633
|
+
AND CASE WHEN js.packing_type NOTNULL AND js.packing_size NOTNULL AND js.uom NOTNULL
|
|
634
|
+
THEN pd.packing_type = js.packing_type AND pd.packing_size = js.packing_size AND pd.uom = js.uom
|
|
635
|
+
WHEN js.packing_type NOTNULL AND js.packing_size NOTNULL AND js.uom ISNULL
|
|
636
|
+
THEN pd.packing_type = js.packing_type AND pd.packing_size = js.packing_size AND pd.is_default IS TRUE
|
|
637
|
+
WHEN js.packing_type ISNULL AND js.packing_size ISNULL AND js.uom NOTNULL
|
|
638
|
+
THEN pd.uom = js.uom AND pd.is_default IS TRUE ELSE pd.is_default IS TRUE
|
|
639
|
+
END;
|
|
640
|
+
`,
|
|
641
|
+
[json_oi, companyBizplaceId.id]
|
|
642
|
+
)
|
|
643
|
+
|
|
644
|
+
let availableItems = await tx.query(
|
|
645
|
+
`
|
|
646
|
+
WITH inv AS (
|
|
647
|
+
SELECT i.product_id, foo.product_detail_id, foo.sku, foo.product_info, i.batch_id, i.packing_type, i.packing_size, i.uom,
|
|
648
|
+
SUM(i.qty - COALESCE(i.locked_qty, 0)) - COALESCE(
|
|
649
|
+
(
|
|
650
|
+
SELECT SUM(oi.release_qty) FROM order_inventories oi
|
|
651
|
+
WHERE oi.status IN ('PENDING', 'PENDING_RECEIVE', 'PENDING_WORKSHEET', 'PENDING_SPLIT')
|
|
652
|
+
AND oi.inventory_id IS null
|
|
653
|
+
AND oi.product_id = i.product_id::uuid
|
|
654
|
+
AND oi.packing_type = i.packing_type
|
|
655
|
+
AND oi.uom = i.uom
|
|
656
|
+
AND oi.domain_id = $1
|
|
657
|
+
AND oi.bizplace_id = $2
|
|
658
|
+
), 0) as "remain_qty",
|
|
659
|
+
SUM(i.uom_value - COALESCE(i.locked_uom_value, 0)) - COALESCE(
|
|
660
|
+
(
|
|
661
|
+
SELECT SUM(oi.release_uom_value) FROM order_inventories oi
|
|
662
|
+
WHERE oi.status IN ('PENDING', 'PENDING_RECEIVE', 'PENDING_WORKSHEET', 'PENDING_SPLIT')
|
|
663
|
+
AND oi.inventory_id IS null
|
|
664
|
+
AND oi.product_id = i.product_id::uuid
|
|
665
|
+
AND oi.packing_type = i.packing_type
|
|
666
|
+
AND oi.uom = i.uom
|
|
667
|
+
AND oi.domain_id = $1
|
|
668
|
+
AND oi.bizplace_id = $2
|
|
669
|
+
), 0) as "remain_uom_value"
|
|
670
|
+
FROM inventories i
|
|
671
|
+
LEFT JOIN locations l
|
|
672
|
+
ON i.location_id = l.id
|
|
673
|
+
INNER JOIN (
|
|
674
|
+
SELECT rrg.product_id, rrg.product_detail_id, rrg.sku, rrg.product_info, rrg.packing_type, rrg.packing_size, rrg.uom
|
|
675
|
+
FROM raw_release_goods rrg
|
|
676
|
+
GROUP BY rrg.product_id, rrg.product_detail_id, rrg.sku, rrg.product_info, rrg.packing_type, rrg.packing_size, rrg.uom
|
|
677
|
+
) AS foo
|
|
678
|
+
ON i.product_id = foo.product_id::uuid
|
|
679
|
+
AND i.packing_type = foo.packing_type
|
|
680
|
+
AND i.packing_size = foo.packing_size
|
|
681
|
+
AND i.uom = foo.uom
|
|
682
|
+
AND i.domain_id = $1
|
|
683
|
+
AND i.bizplace_id = $2
|
|
684
|
+
WHERE l.type NOT IN ($3, $4)
|
|
685
|
+
GROUP BY i.product_id, foo.product_detail_id, foo.sku,foo.product_info, i.batch_id, i.packing_type, i.packing_size, i.uom
|
|
686
|
+
ORDER BY foo.sku, remain_qty
|
|
687
|
+
) SELECT * FROM inv WHERE remain_qty > 0
|
|
688
|
+
`,
|
|
689
|
+
[domain.id, bizplaceId, LOCATION_TYPE.QUARANTINE, LOCATION_TYPE.RESERVE]
|
|
690
|
+
)
|
|
691
|
+
|
|
692
|
+
availableItems = availableItems.map(item => {
|
|
693
|
+
return {
|
|
694
|
+
productId: item.product_id,
|
|
695
|
+
productDetailId: item.product_detail_id,
|
|
696
|
+
productInfo: item.product_info,
|
|
697
|
+
sku: item.sku,
|
|
698
|
+
batchId: item.batch_id,
|
|
699
|
+
packingType: item.packing_type,
|
|
700
|
+
packingSize: item.packing_size,
|
|
701
|
+
uom: item.uom,
|
|
702
|
+
remainQty: item.remain_qty,
|
|
703
|
+
remainUomValue: item.remain_uom_value
|
|
704
|
+
}
|
|
705
|
+
})
|
|
706
|
+
|
|
707
|
+
return _extractData(rawReleaseGoods, availableItems)
|
|
708
|
+
}
|
|
709
|
+
|
|
692
710
|
function _extractData(rawData, validatedData) {
|
|
693
711
|
return rawData.map(raw => {
|
|
694
712
|
const idx = validatedData.findIndex(val => {
|
|
@@ -737,6 +755,7 @@ function _extractData(rawData, validatedData) {
|
|
|
737
755
|
validatedData[idx].remainUomValue -= raw.assignedUomValue
|
|
738
756
|
|
|
739
757
|
raw.productId = validatedData[idx].productId
|
|
758
|
+
raw.productDetailId = validatedData[idx].productDetailId
|
|
740
759
|
raw.packingType = validatedData[idx].packingType
|
|
741
760
|
raw.packingSize = validatedData[idx].packingSize
|
|
742
761
|
raw.uom = validatedData[idx].uom
|
|
@@ -747,9 +766,25 @@ function _extractData(rawData, validatedData) {
|
|
|
747
766
|
raw.productId = null
|
|
748
767
|
}
|
|
749
768
|
|
|
769
|
+
let releaseDate = _getStdDateStr(new Date(raw.releaseDate || ''))
|
|
770
|
+
|
|
750
771
|
return {
|
|
751
772
|
...raw,
|
|
752
|
-
releaseUomValue
|
|
773
|
+
releaseUomValue,
|
|
774
|
+
errorMsg:
|
|
775
|
+
!raw.productId || !raw.productDetailId
|
|
776
|
+
? 'product not found'
|
|
777
|
+
: raw.releaseQty <= 0
|
|
778
|
+
? 'invalid release qty'
|
|
779
|
+
: raw.assignedQty < raw.releaseQty
|
|
780
|
+
? 'insufficient stock'
|
|
781
|
+
: raw.releaseDate == ''
|
|
782
|
+
? 'release date is empty'
|
|
783
|
+
: releaseDate < _getStdDateStr(new Date())
|
|
784
|
+
? 'backdate is not allowed'
|
|
785
|
+
: !raw.refNo
|
|
786
|
+
? 'ref no is empty'
|
|
787
|
+
: ''
|
|
753
788
|
}
|
|
754
789
|
})
|
|
755
790
|
}
|
|
@@ -772,3 +807,11 @@ function getConditionValues(
|
|
|
772
807
|
return condition
|
|
773
808
|
}, {})
|
|
774
809
|
}
|
|
810
|
+
|
|
811
|
+
function _getStdDateStr(date) {
|
|
812
|
+
if (isNaN(date.getFullYear())) return ''
|
|
813
|
+
else {
|
|
814
|
+
date.setHours(date.getHours() + 8)
|
|
815
|
+
return date.toISOString().split('T')[0]
|
|
816
|
+
}
|
|
817
|
+
}
|
|
@@ -308,6 +308,13 @@ export class NewReleaseGood {
|
|
|
308
308
|
@Field({ nullable: true })
|
|
309
309
|
partnerBizplaceId: string
|
|
310
310
|
|
|
311
|
+
/* Mainly used for rawReleaseGood*/
|
|
312
|
+
@Field({ nullable: true })
|
|
313
|
+
productId: string
|
|
314
|
+
|
|
315
|
+
@Field({ nullable: true })
|
|
316
|
+
productDetailId: string
|
|
317
|
+
|
|
311
318
|
@Field({ nullable: true })
|
|
312
319
|
sku: string
|
|
313
320
|
|
|
@@ -315,13 +322,28 @@ export class NewReleaseGood {
|
|
|
315
322
|
packingType: string
|
|
316
323
|
|
|
317
324
|
@Field({ nullable: true })
|
|
318
|
-
packingSize:
|
|
325
|
+
packingSize: number
|
|
319
326
|
|
|
320
327
|
@Field({ nullable: true })
|
|
321
328
|
uom: string
|
|
322
329
|
|
|
323
330
|
@Field({ nullable: true })
|
|
324
|
-
releaseQty:
|
|
331
|
+
releaseQty: number
|
|
332
|
+
|
|
333
|
+
@Field({ nullable: true })
|
|
334
|
+
assignedQty: number
|
|
335
|
+
|
|
336
|
+
@Field({ nullable: true })
|
|
337
|
+
assignedUomValue: number
|
|
338
|
+
|
|
339
|
+
@Field({ nullable: true })
|
|
340
|
+
remainQty: number
|
|
341
|
+
|
|
342
|
+
@Field({ nullable: true })
|
|
343
|
+
remainUomValue: number
|
|
344
|
+
|
|
345
|
+
@Field({ nullable: true })
|
|
346
|
+
errorMsg: string
|
|
325
347
|
}
|
|
326
348
|
|
|
327
349
|
@InputType()
|
|
@@ -344,4 +344,47 @@ export class ReleaseGood {
|
|
|
344
344
|
|
|
345
345
|
@Field(type => ShippingOrderInfo, { nullable: true })
|
|
346
346
|
shippingOrderInfo?: ShippingOrderInfo
|
|
347
|
+
|
|
348
|
+
/* Mainly used for rawReleaseGood*/
|
|
349
|
+
@Field({ nullable: true })
|
|
350
|
+
productId: string
|
|
351
|
+
|
|
352
|
+
@Field({ nullable: true })
|
|
353
|
+
productDetailId: string
|
|
354
|
+
|
|
355
|
+
@Field({ nullable: true })
|
|
356
|
+
productInfo: string
|
|
357
|
+
|
|
358
|
+
@Field({ nullable: true })
|
|
359
|
+
sku: string
|
|
360
|
+
|
|
361
|
+
@Field({ nullable: true })
|
|
362
|
+
batchId: string
|
|
363
|
+
|
|
364
|
+
@Field({ nullable: true })
|
|
365
|
+
packingType: string
|
|
366
|
+
|
|
367
|
+
@Field({ nullable: true })
|
|
368
|
+
packingSize: number
|
|
369
|
+
|
|
370
|
+
@Field({ nullable: true })
|
|
371
|
+
uom: string
|
|
372
|
+
|
|
373
|
+
@Field({ nullable: true })
|
|
374
|
+
releaseQty: number
|
|
375
|
+
|
|
376
|
+
@Field({ nullable: true })
|
|
377
|
+
assignedQty: number
|
|
378
|
+
|
|
379
|
+
@Field({ nullable: true })
|
|
380
|
+
assignedUomValue: number
|
|
381
|
+
|
|
382
|
+
@Field({ nullable: true })
|
|
383
|
+
remainQty: number
|
|
384
|
+
|
|
385
|
+
@Field({ nullable: true })
|
|
386
|
+
remainUomValue: number
|
|
387
|
+
|
|
388
|
+
@Field({ nullable: true })
|
|
389
|
+
errorMsg: string
|
|
347
390
|
}
|