@things-factory/sales-base 4.3.38 → 4.3.41
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/constants/order.js +2 -0
- package/dist-server/constants/order.js.map +1 -1
- package/dist-server/service/delivery-order/delivery-order-mutation.js +58 -6
- package/dist-server/service/delivery-order/delivery-order-mutation.js.map +1 -1
- package/dist-server/service/delivery-order/delivery-order-types.js +20 -0
- package/dist-server/service/delivery-order/delivery-order-types.js.map +1 -1
- package/dist-server/service/goods-receival-note/goods-receival-note-query.js +96 -5
- package/dist-server/service/goods-receival-note/goods-receival-note-query.js.map +1 -1
- package/dist-server/service/goods-receival-note/goods-receival-note-types.js +65 -1
- package/dist-server/service/goods-receival-note/goods-receival-note-types.js.map +1 -1
- package/dist-server/service/goods-receival-note/goods-receival-note.js +41 -0
- package/dist-server/service/goods-receival-note/goods-receival-note.js.map +1 -1
- package/dist-server/service/order-inventory/order-inventory-query.js +111 -142
- package/dist-server/service/order-inventory/order-inventory-query.js.map +1 -1
- package/dist-server/service/order-inventory/order-inventory.js +24 -0
- package/dist-server/service/order-inventory/order-inventory.js.map +1 -1
- package/dist-server/service/purchase-order/purchase-order-mutation.js +4 -1
- package/dist-server/service/purchase-order/purchase-order-mutation.js.map +1 -1
- package/dist-server/service/release-good/release-good-mutation.js +52 -8
- package/dist-server/service/release-good/release-good-mutation.js.map +1 -1
- package/dist-server/service/release-good/release-good-types.js +153 -1
- package/dist-server/service/release-good/release-good-types.js.map +1 -1
- package/dist-server/service/release-good/release-good.js +20 -0
- package/dist-server/service/release-good/release-good.js.map +1 -1
- package/dist-server/utils/datetime-util.js +49 -0
- package/dist-server/utils/datetime-util.js.map +1 -0
- package/dist-server/utils/index.js +1 -0
- package/dist-server/utils/index.js.map +1 -1
- package/dist-server/utils/inventory-util.js +19 -2
- package/dist-server/utils/inventory-util.js.map +1 -1
- package/package.json +12 -12
- package/server/constants/order.ts +2 -0
- package/server/service/delivery-order/delivery-order-mutation.ts +91 -16
- package/server/service/delivery-order/delivery-order-types.ts +15 -0
- package/server/service/goods-receival-note/goods-receival-note-query.ts +120 -10
- package/server/service/goods-receival-note/goods-receival-note-types.ts +48 -0
- package/server/service/goods-receival-note/goods-receival-note.ts +32 -0
- package/server/service/order-inventory/order-inventory-query.ts +121 -166
- package/server/service/order-inventory/order-inventory.ts +18 -0
- package/server/service/purchase-order/purchase-order-mutation.ts +5 -1
- package/server/service/release-good/release-good-mutation.ts +67 -13
- package/server/service/release-good/release-good-types.ts +112 -0
- package/server/service/release-good/release-good.ts +16 -0
- package/server/utils/datetime-util.ts +54 -0
- package/server/utils/index.ts +1 -0
- package/server/utils/inventory-util.ts +20 -2
|
@@ -1,12 +1,20 @@
|
|
|
1
|
+
import { PurchaseOrder } from './../purchase-order/purchase-order'
|
|
1
2
|
import { Arg, Args, Ctx, FieldResolver, Query, Resolver, Root } from 'type-graphql'
|
|
2
3
|
import { getRepository, SelectQueryBuilder } from 'typeorm'
|
|
4
|
+
import { IsNull, Not, In } from 'typeorm'
|
|
3
5
|
|
|
4
6
|
import { User } from '@things-factory/auth-base'
|
|
5
7
|
import { getPermittedBizplaceIds } from '@things-factory/biz-base'
|
|
6
8
|
import { buildQuery, Domain, ListParam } from '@things-factory/shell'
|
|
7
|
-
|
|
9
|
+
import { InventoryItem } from '@things-factory/warehouse-base'
|
|
8
10
|
import { GoodsReceivalNoteList } from '../'
|
|
9
11
|
import { GoodsReceivalNote } from './goods-receival-note'
|
|
12
|
+
import { ArrivalNotice } from '../arrival-notice/arrival-notice'
|
|
13
|
+
import { Partner } from '@things-factory/auth-base'
|
|
14
|
+
import { Bizplace, ContactPoint } from '@things-factory/biz-base'
|
|
15
|
+
import { OrderProduct } from '../order-product/order-product'
|
|
16
|
+
import { ReducedInventoryHistory } from '@things-factory/warehouse-base'
|
|
17
|
+
import { DateTimeConverter } from '../../utils/datetime-util'
|
|
10
18
|
|
|
11
19
|
@Resolver(GoodsReceivalNote)
|
|
12
20
|
export class GoodsReceivalNoteQuery {
|
|
@@ -123,12 +131,12 @@ export class GoodsReceivalNoteQuery {
|
|
|
123
131
|
[arrChildSortData.indexOf(sort.name) >= 0
|
|
124
132
|
? 'arrivalNotice.' + sort.name
|
|
125
133
|
: arrNameSortData.indexOf(sort.name) >= 0
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
134
|
+
? sort.name + '.name'
|
|
135
|
+
: arrGanStatusSortData.indexOf(sort.name) >= 0
|
|
136
|
+
? 'arrivalNotice.status'
|
|
137
|
+
: arrGrnStatuSortData.indexOf(sort.name) >= 0
|
|
138
|
+
? 'grn.status'
|
|
139
|
+
: 'grn.' + sort.name]: sort.desc ? 'DESC' : 'ASC'
|
|
132
140
|
}),
|
|
133
141
|
!params.sortings.some(e => e.name === 'status') ? { rank: 'ASC' } : {}
|
|
134
142
|
)
|
|
@@ -141,12 +149,114 @@ export class GoodsReceivalNoteQuery {
|
|
|
141
149
|
}
|
|
142
150
|
|
|
143
151
|
@Query(returns => GoodsReceivalNote)
|
|
144
|
-
async goodsReceivalNote(
|
|
152
|
+
async goodsReceivalNote(
|
|
153
|
+
@Arg('name') name: string,
|
|
154
|
+
@Arg('timezoneOffSet') timezoneOffSet: string,
|
|
155
|
+
@Ctx() context: any
|
|
156
|
+
): Promise<any> {
|
|
145
157
|
const { domain }: { domain: Domain } = context.state
|
|
146
|
-
|
|
158
|
+
|
|
159
|
+
const foundGRN: GoodsReceivalNote = await getRepository(GoodsReceivalNote).findOne({
|
|
147
160
|
where: { domain, name },
|
|
148
|
-
relations: [
|
|
161
|
+
relations: [
|
|
162
|
+
'domain',
|
|
163
|
+
'bizplace',
|
|
164
|
+
'bizplace.domain',
|
|
165
|
+
'bizplace.company',
|
|
166
|
+
'arrivalNotice',
|
|
167
|
+
'arrivalNotice.purchaseOrder'
|
|
168
|
+
]
|
|
169
|
+
})
|
|
170
|
+
|
|
171
|
+
const foundGAN: ArrivalNotice = foundGRN.arrivalNotice
|
|
172
|
+
const ownRefNo = foundGAN.refNo
|
|
173
|
+
|
|
174
|
+
const partnerBiz: Bizplace = foundGRN.bizplace
|
|
175
|
+
|
|
176
|
+
const partnerDomain: Partner = await getRepository(Partner).findOne({
|
|
177
|
+
where: { partnerDomain: partnerBiz.domain, domain },
|
|
178
|
+
relations: ['domain']
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
const domainOwner: Domain = partnerDomain.domain
|
|
182
|
+
const domainBizplace: Bizplace = await getRepository(Bizplace).findOne({
|
|
183
|
+
where: { domain: domainOwner },
|
|
184
|
+
relations: ['company']
|
|
149
185
|
})
|
|
186
|
+
|
|
187
|
+
const qbReducedInventory = await getRepository(ReducedInventoryHistory)
|
|
188
|
+
.createQueryBuilder('ivh')
|
|
189
|
+
.select('product_id', 'productId')
|
|
190
|
+
.addSelect('batch_id', 'batchId')
|
|
191
|
+
.addSelect('reusable_pallet_id', 'reusablePalletId')
|
|
192
|
+
.addSelect('packing_type', 'packingType')
|
|
193
|
+
.addSelect('sum(qty)', 'qty')
|
|
194
|
+
.addSelect('sum(uom_value)', 'uomValue')
|
|
195
|
+
.addSelect('uom', 'uom')
|
|
196
|
+
.addSelect('count(distinct pallet_id)', 'pallet')
|
|
197
|
+
.addSelect(`string_agg(distinct expiration_date::varchar,', ' order by expiration_date::varchar)`, 'expiryDate')
|
|
198
|
+
.addSelect(`string_agg(distinct pallet_id::varchar,', ' order by pallet_id::varchar)`, 'palletId')
|
|
199
|
+
.where('ivh.domain_id = :domainId', { domainId: domain.id })
|
|
200
|
+
.andWhere('ivh.ref_order_id = :refOrderId', { refOrderId: foundGAN.id })
|
|
201
|
+
.andWhere(`ivh.transaction_type = 'UNLOADING'`)
|
|
202
|
+
.groupBy('reusable_pallet_id')
|
|
203
|
+
.addGroupBy('product_id')
|
|
204
|
+
.addGroupBy('batch_id')
|
|
205
|
+
.addGroupBy('packing_type')
|
|
206
|
+
.addGroupBy('uom')
|
|
207
|
+
.getRawMany()
|
|
208
|
+
|
|
209
|
+
// 5. find domain contact point
|
|
210
|
+
const foundCP: ContactPoint = await getRepository(ContactPoint).findOne({
|
|
211
|
+
where: { domain, bizplace: domainBizplace }
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
const inboundInventories: any[] = await qbReducedInventory
|
|
215
|
+
|
|
216
|
+
const targetProducts: OrderProduct[] = await getRepository(OrderProduct).find({
|
|
217
|
+
where: { domain, arrivalNotice: foundGAN, actualPalletQty: Not(IsNull()), actualPackQty: Not(IsNull()) },
|
|
218
|
+
relations: ['product', 'arrivalNotice', 'arrivalNotice.purchaseOrder']
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
const data = {
|
|
222
|
+
grnNo: foundGRN.name,
|
|
223
|
+
ganNo: foundGAN.name,
|
|
224
|
+
refGANNo: foundGAN.refNo || '',
|
|
225
|
+
refGANNo2: foundGAN.refNo2 || '',
|
|
226
|
+
refGANNo3: foundGAN.refNo3 || '',
|
|
227
|
+
companyDomain: domainBizplace.company.name,
|
|
228
|
+
supplier: foundCP.name || '',
|
|
229
|
+
date: foundGAN.acceptedAt ? DateTimeConverter.datetime(foundGAN.acceptedAt, timezoneOffSet) : '',
|
|
230
|
+
productLists: targetProducts.map((item, idx) => {
|
|
231
|
+
let unloadInvHistory = inboundInventories.find(
|
|
232
|
+
ih =>
|
|
233
|
+
ih.productId == item.product.id &&
|
|
234
|
+
ih.batchId == item.batchId &&
|
|
235
|
+
ih.packingType == item.packingType &&
|
|
236
|
+
ih.uom == item.uom
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
return {
|
|
240
|
+
list_no: idx + 1,
|
|
241
|
+
po: item?.arrivalNotice?.purchaseOrder?.name ? item?.arrivalNotice?.purchaseOrder.name : '',
|
|
242
|
+
batchNo: item.batchId || '',
|
|
243
|
+
productSKU: `${item.product.sku}`,
|
|
244
|
+
productName: `${item.product.name}(${item.product.description})`,
|
|
245
|
+
productType: item.packingType,
|
|
246
|
+
productBatch: item.batchId,
|
|
247
|
+
expectedQty: item.packQty,
|
|
248
|
+
actualQty: unloadInvHistory.qty || item.actualPackQty,
|
|
249
|
+
actualUomValue: item.uomValue * item.actualPackQty,
|
|
250
|
+
productUom: `${unloadInvHistory.uom || item.uom}`,
|
|
251
|
+
expiryDate: unloadInvHistory.expiryDate || '',
|
|
252
|
+
unitPrice: item.unitPrice.toFixed(2) || 0.0,
|
|
253
|
+
manufactureDate: item.manufactureDate || '',
|
|
254
|
+
remark: (item.remark ? item.remark : '') + (item.issue ? ' [Issue]: ' + item.issue : '')
|
|
255
|
+
}
|
|
256
|
+
})
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return data
|
|
150
260
|
}
|
|
151
261
|
|
|
152
262
|
@FieldResolver(type => Domain)
|
|
@@ -11,6 +11,54 @@ export class GoodsReceivalNoteList {
|
|
|
11
11
|
total: number
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
// Need to review with better class name
|
|
15
|
+
@ObjectType()
|
|
16
|
+
export class ProductListsType {
|
|
17
|
+
|
|
18
|
+
@Field({ nullable: true })
|
|
19
|
+
po: string
|
|
20
|
+
|
|
21
|
+
@Field({ nullable: true })
|
|
22
|
+
batchNo: string
|
|
23
|
+
|
|
24
|
+
@Field({ nullable: true })
|
|
25
|
+
productSKU: string
|
|
26
|
+
|
|
27
|
+
@Field({ nullable: true })
|
|
28
|
+
productName: string
|
|
29
|
+
|
|
30
|
+
@Field({ nullable: true })
|
|
31
|
+
productType: string
|
|
32
|
+
|
|
33
|
+
@Field({ nullable: true })
|
|
34
|
+
productBatch: string
|
|
35
|
+
|
|
36
|
+
@Field({nullable:true})
|
|
37
|
+
@Field({ nullable: true })
|
|
38
|
+
expectedQty: number
|
|
39
|
+
|
|
40
|
+
@Field({ nullable: true })
|
|
41
|
+
actualQty: number
|
|
42
|
+
|
|
43
|
+
@Field({ nullable: true })
|
|
44
|
+
actualUomValue: number
|
|
45
|
+
|
|
46
|
+
@Field({ nullable: true })
|
|
47
|
+
productUom: string
|
|
48
|
+
|
|
49
|
+
@Field({ nullable: true })
|
|
50
|
+
expiryDate: string
|
|
51
|
+
|
|
52
|
+
@Field({ nullable: true })
|
|
53
|
+
unitPrice: number
|
|
54
|
+
|
|
55
|
+
@Field({ nullable: true })
|
|
56
|
+
manufactureDate: string
|
|
57
|
+
|
|
58
|
+
@Field({ nullable: true })
|
|
59
|
+
remark: string
|
|
60
|
+
}
|
|
61
|
+
|
|
14
62
|
@InputType()
|
|
15
63
|
export class NewGoodsReceivalNote {
|
|
16
64
|
@Field({ nullable: true })
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
UpdateDateColumn
|
|
17
17
|
} from 'typeorm'
|
|
18
18
|
import { ArrivalNotice } from '../'
|
|
19
|
+
import { ProductListsType } from './goods-receival-note-types'
|
|
19
20
|
|
|
20
21
|
@Entity()
|
|
21
22
|
@Index(
|
|
@@ -92,4 +93,35 @@ export class GoodsReceivalNote {
|
|
|
92
93
|
|
|
93
94
|
@Field(type => [Attachment], { nullable: true })
|
|
94
95
|
attachments: Attachment[]
|
|
96
|
+
|
|
97
|
+
@Field({nullable:true})
|
|
98
|
+
grnNo: string
|
|
99
|
+
|
|
100
|
+
@Field({nullable:true})
|
|
101
|
+
ganNo: string
|
|
102
|
+
|
|
103
|
+
@Field({nullable:true})
|
|
104
|
+
refGANNo: string
|
|
105
|
+
|
|
106
|
+
@Field({nullable:true})
|
|
107
|
+
refGANNo2: string
|
|
108
|
+
|
|
109
|
+
@Field({nullable:true})
|
|
110
|
+
refGANNo3: string
|
|
111
|
+
|
|
112
|
+
@Field({nullable:true})
|
|
113
|
+
timezoneOffSet: string
|
|
114
|
+
|
|
115
|
+
@Field(type=>[ProductListsType],{nullable:true})
|
|
116
|
+
productLists: ProductListsType[]
|
|
117
|
+
|
|
118
|
+
@Field({nullable:true})
|
|
119
|
+
companyDomain: string
|
|
120
|
+
|
|
121
|
+
@Field({nullable:true})
|
|
122
|
+
supplier: string
|
|
123
|
+
|
|
124
|
+
@Field({nullable:true})
|
|
125
|
+
date: string
|
|
126
|
+
|
|
95
127
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Arg, Args, Ctx, FieldResolver, Query, Resolver, Root } from 'type-graphql'
|
|
1
|
+
import { Arg, Args, Ctx, FieldResolver, Query, Resolver, Root, Directive } from 'type-graphql'
|
|
2
2
|
import { Brackets, EntityManager, getRepository, Like, SelectQueryBuilder } from 'typeorm'
|
|
3
3
|
|
|
4
4
|
import { User } from '@things-factory/auth-base'
|
|
@@ -438,194 +438,137 @@ export class OrderInventoryQuery {
|
|
|
438
438
|
}
|
|
439
439
|
}
|
|
440
440
|
|
|
441
|
+
@Directive('@transaction')
|
|
441
442
|
@Query(returns => OrderInventoryList)
|
|
442
443
|
async orderInventoriesOfMultipleReleaseOrders(
|
|
443
444
|
@Ctx() context: any,
|
|
444
445
|
@Arg('partnerId') partnerId: string,
|
|
446
|
+
@Arg('priority', { nullable: true }) priority: string,
|
|
447
|
+
@Arg('binNumber', { nullable: true }) binNumber: string,
|
|
445
448
|
@Arg('filters', type => [Filter], { nullable: true }) filters?: Filter[],
|
|
446
449
|
@Arg('sortings', type => [Sorting], { nullable: true }) sortings?: Sorting[]
|
|
447
450
|
): Promise<OrderInventoryList> {
|
|
448
451
|
try {
|
|
449
|
-
const { domain }: { domain: Domain } = context.state
|
|
450
|
-
const
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
})
|
|
452
|
+
const { domain, tx }: { domain: Domain; tx: EntityManager } = context.state
|
|
453
|
+
const withSkuParam: any = filters.find((param: any) => param.name === 'withSku')
|
|
454
|
+
const withToteParam: any = filters.find((param: any) => param.name === 'withTote')
|
|
455
|
+
const mergedPageParam: any = filters.find((param: any) => param.name === 'merged')
|
|
456
|
+
|
|
457
|
+
let sort = ''
|
|
458
|
+
let prioritySort = ''
|
|
459
|
+
let releaseOrderIdQuery = ''
|
|
460
|
+
|
|
461
|
+
// Require further evaluation. Potential performance issue.
|
|
462
|
+
if (mergedPageParam) {
|
|
463
|
+
releaseOrderIdQuery = `
|
|
464
|
+
select rg.id from release_goods rg
|
|
465
|
+
inner join order_inventories oi on oi.release_good_id = rg.id
|
|
466
|
+
inner join worksheet_details wd on wd.target_inventory_id = oi.id
|
|
467
|
+
inner join worksheets w on w.id = wd.worksheet_id
|
|
468
|
+
where rg.route_id is not null and rg.type = 'b2b'
|
|
469
|
+
and rg.domain_id = $1 and rg.bizplace_id = $2
|
|
470
|
+
and w.type in ('BATCH_PICKING', 'SORTING', 'LOADING') and w.status = 'EXECUTING'
|
|
471
|
+
and rg.id not in (select rg2.id from release_goods rg2
|
|
472
|
+
inner join worksheets w2 on w2.release_good_id = rg2.id
|
|
473
|
+
where rg2.domain_id = $1 and rg2.bizplace_id = $2
|
|
474
|
+
and rg2.route_id is not null and rg2.type = 'b2b'
|
|
475
|
+
and w2.type in ('PICKING'))
|
|
476
|
+
group by rg.id
|
|
477
|
+
`
|
|
476
478
|
} else {
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
479
|
+
releaseOrderIdQuery = `
|
|
480
|
+
select rg.id from release_goods rg
|
|
481
|
+
inner join worksheets w on w.release_good_id = rg.id
|
|
482
|
+
where rg.domain_id = $1 and rg.bizplace_id = $2
|
|
483
|
+
and rg.route_id is not null and rg.type = 'b2b'
|
|
484
|
+
and w.type in ('PICKING', 'LOADING') and w.status = 'EXECUTING'
|
|
485
|
+
and rg.id not in (select rg2.id from release_goods rg2
|
|
486
|
+
inner join order_inventories oi2 on oi2.release_good_id = rg2.id
|
|
487
|
+
inner join worksheet_details wd2 on wd2.target_inventory_id = oi2.id
|
|
488
|
+
inner join worksheets w2 on w2.id = wd2.worksheet_id
|
|
489
|
+
where rg2.route_id is not null and rg2.type = 'b2b'
|
|
490
|
+
and rg2.domain_id = $1 and rg2.bizplace_id = $2
|
|
491
|
+
and w2.type in ('BATCH_PICKING'))
|
|
492
|
+
group by rg.id
|
|
493
|
+
`
|
|
482
494
|
}
|
|
483
495
|
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
acc = { ...acc, ['rg.name']: order }
|
|
503
|
-
break
|
|
504
|
-
|
|
505
|
-
case 'productSku':
|
|
506
|
-
acc = { ...acc, ['Product.sku']: order }
|
|
507
|
-
break
|
|
508
|
-
|
|
509
|
-
case 'binNumber':
|
|
510
|
-
acc = { ...acc, ['bin_loc.name']: order }
|
|
511
|
-
break
|
|
512
|
-
}
|
|
496
|
+
await tx.query(
|
|
497
|
+
`
|
|
498
|
+
create temp table temp_route_label ON COMMIT drop as (
|
|
499
|
+
select distinct(ot.name) as "toteNumber", oi.id, rg3.name as "releaseGoodName", (case when ot.name is null then oi.release_qty else null end) as "releaseQty",
|
|
500
|
+
(case when ot.name is null then p.sku else null end) as "productSKU", (case when ot.name is null then p.name else null end) as "productName", (case when ot.name is null then l.name else null end) as "binNumber",
|
|
501
|
+
rg3.route_id as "routeId", rg3.store_id as "storeId", rg3.store_name as "storeName", rg3.stop_id as "stopId",
|
|
502
|
+
rg3.created_at as "createdAt" from order_inventories oi
|
|
503
|
+
inner join release_goods rg3 on rg3.id = oi.release_good_id
|
|
504
|
+
inner join products p on p.id = oi.product_id
|
|
505
|
+
left join locations l on l.id = oi.bin_location_id
|
|
506
|
+
left join order_tote_items oti on oti.order_inventory_id = oi.id
|
|
507
|
+
left join order_totes ot on ot.id = oti.order_tote_id
|
|
508
|
+
where oi.release_good_id in
|
|
509
|
+
(${releaseOrderIdQuery})
|
|
510
|
+
)
|
|
511
|
+
`,
|
|
512
|
+
[domain.id, partnerId]
|
|
513
|
+
)
|
|
513
514
|
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
515
|
+
let withSkuQuery = withSkuParam?.value == true ? `AND tmp."binNumber" is null AND tmp."toteNumber" is null` : ''
|
|
516
|
+
let withBinQuery = ''
|
|
517
|
+
let withToteQuery =
|
|
518
|
+
withToteParam?.value == true
|
|
519
|
+
? (withSkuParam?.value == true || binNumber ? `OR ` : 'AND ') + `tmp."toteNumber" is not null`
|
|
520
|
+
: ''
|
|
521
|
+
|
|
522
|
+
if (binNumber) {
|
|
523
|
+
if (binNumber !== 'all' && binNumber !== '') {
|
|
524
|
+
withBinQuery =
|
|
525
|
+
(withSkuParam?.value == true || withToteParam?.value == false ? `OR ` : `AND `) +
|
|
526
|
+
`tmp."binNumber" = '` +
|
|
527
|
+
binNumber +
|
|
528
|
+
`'`
|
|
529
|
+
} else if (binNumber == 'all') {
|
|
530
|
+
withBinQuery =
|
|
531
|
+
(withSkuParam?.value == true || withToteParam?.value == false ? `OR ` : `AND `) +
|
|
532
|
+
`tmp."binNumber" is not null`
|
|
533
|
+
}
|
|
517
534
|
}
|
|
518
535
|
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
return { items, total }
|
|
522
|
-
} catch (e) {
|
|
523
|
-
throw e
|
|
524
|
-
}
|
|
525
|
-
}
|
|
536
|
+
if (priority) {
|
|
537
|
+
prioritySort = ' order by '
|
|
526
538
|
|
|
527
|
-
|
|
528
|
-
async orderInventoriesOfMergedReleaseOrders(
|
|
529
|
-
@Ctx() context: any,
|
|
530
|
-
@Arg('partnerId') partnerId: string,
|
|
531
|
-
@Arg('filters', type => [Filter], { nullable: true }) filters?: Filter[],
|
|
532
|
-
@Arg('sortings', type => [Sorting], { nullable: true }) sortings?: Sorting[]
|
|
533
|
-
): Promise<OrderInventoryList> {
|
|
534
|
-
try {
|
|
535
|
-
const { domain }: { domain: Domain } = context.state
|
|
536
|
-
const binNumberParam: any = filters.find((param: any) => param.name === 'binNumber')
|
|
537
|
-
const priorityParam: any = filters.find((param: any) => param.name === 'priority')
|
|
538
|
-
let arrFilters = []
|
|
539
|
-
|
|
540
|
-
if (priorityParam) {
|
|
541
|
-
filters.splice(
|
|
542
|
-
filters.findIndex(item => item.name == 'priority'),
|
|
543
|
-
1
|
|
544
|
-
)
|
|
545
|
-
|
|
546
|
-
switch (priorityParam.value) {
|
|
539
|
+
switch (priority) {
|
|
547
540
|
case 'roSku':
|
|
548
|
-
|
|
549
|
-
sortings.push({ name: 'productSku', desc: false })
|
|
541
|
+
prioritySort = prioritySort + '"createdAt" desc, "productSKU" asc'
|
|
550
542
|
break
|
|
551
543
|
|
|
552
544
|
case 'roBin':
|
|
553
|
-
|
|
554
|
-
|
|
545
|
+
prioritySort = prioritySort + '"createdAt" desc, "binNumber" asc'
|
|
546
|
+
break
|
|
547
|
+
|
|
548
|
+
case 'roTote':
|
|
549
|
+
prioritySort = prioritySort + '"createdAt" desc, "toteNumber" asc'
|
|
555
550
|
break
|
|
556
551
|
|
|
557
552
|
case 'skuRo':
|
|
558
|
-
|
|
559
|
-
sortings.push({ name: 'releaseGood', desc: true })
|
|
553
|
+
prioritySort = prioritySort + '"productSKU" asc, "createdAt" desc'
|
|
560
554
|
break
|
|
561
555
|
|
|
562
556
|
case 'skuBin':
|
|
563
|
-
|
|
564
|
-
sortings.push({ name: 'binNumber', desc: false })
|
|
557
|
+
prioritySort = prioritySort + '"productSKU" asc, "binNumber" asc'
|
|
565
558
|
break
|
|
566
559
|
|
|
567
560
|
case 'binSku':
|
|
568
|
-
|
|
569
|
-
sortings.push({ name: 'productSku', desc: false })
|
|
561
|
+
prioritySort = prioritySort + '"binNumber" asc, "productSKU" asc'
|
|
570
562
|
break
|
|
571
563
|
|
|
572
564
|
case 'binRo':
|
|
573
|
-
|
|
574
|
-
sortings.push({ name: 'releaseGood', desc: true })
|
|
565
|
+
prioritySort = prioritySort + '"binNumber" asc, "createdAt" desc'
|
|
575
566
|
break
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
const releaseGoodsList: ReleaseGood[] = await getRepository(ReleaseGood).query(
|
|
580
|
-
`select oi.release_good_id as id from worksheets w
|
|
581
|
-
inner join worksheet_details wd on wd.worksheet_id =w.id
|
|
582
|
-
inner join order_inventories oi on oi.id =wd.target_inventory_id
|
|
583
|
-
inner join release_goods rg on rg.id = oi.release_good_id
|
|
584
|
-
and oi.status in ('PICKING', 'PICKED', 'SORTING', 'SORTED')
|
|
585
|
-
and w.type = 'BATCH_PICKING' and w.status != 'DEACTIVATED'
|
|
586
|
-
and rg.domain_id = '${domain.id}' and rg.bizplace_id = '${partnerId}'
|
|
587
|
-
and rg.route_id is not null
|
|
588
|
-
group by oi.release_good_id`
|
|
589
|
-
)
|
|
590
|
-
|
|
591
|
-
if (releaseGoodsList && releaseGoodsList.length) {
|
|
592
|
-
arrFilters.push({
|
|
593
|
-
name: 'releaseGoodId',
|
|
594
|
-
operator: 'in',
|
|
595
|
-
value: releaseGoodsList.map((foundRG: ReleaseGood) => foundRG.id),
|
|
596
|
-
relation: false
|
|
597
|
-
})
|
|
598
|
-
} else {
|
|
599
|
-
arrFilters.push({
|
|
600
|
-
name: 'releaseGoodId',
|
|
601
|
-
operator: 'is_null',
|
|
602
|
-
relation: false
|
|
603
|
-
})
|
|
604
|
-
}
|
|
605
567
|
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
qb.select('oi')
|
|
611
|
-
qb.innerJoinAndSelect('oi.releaseGood', 'rg')
|
|
612
|
-
qb.innerJoinAndSelect('oi.product', 'Product')
|
|
613
|
-
qb.leftJoinAndSelect('oi.binLocation', 'bin_loc')
|
|
614
|
-
qb.leftJoinAndSelect('oi.domain', 'domain')
|
|
615
|
-
qb.leftJoinAndSelect('oi.creator', 'creator')
|
|
616
|
-
qb.leftJoinAndSelect('oi.updater', 'updater')
|
|
617
|
-
|
|
618
|
-
if (binNumberParam) {
|
|
619
|
-
let binLocation: Location = await getRepository(Location).findOne({
|
|
620
|
-
where: { domain, name: binNumberParam.value }
|
|
621
|
-
})
|
|
622
|
-
|
|
623
|
-
filters.splice(
|
|
624
|
-
filters.findIndex(item => item.name == 'binNumber'),
|
|
625
|
-
1
|
|
626
|
-
)
|
|
627
|
-
|
|
628
|
-
qb.andWhere('bin_loc.id = :id', { id: binLocation.id })
|
|
568
|
+
case 'toteRo':
|
|
569
|
+
prioritySort = prioritySort + '"toteNumber" asc, "createdAt" desc'
|
|
570
|
+
break
|
|
571
|
+
}
|
|
629
572
|
}
|
|
630
573
|
|
|
631
574
|
if (sortings?.length !== 0) {
|
|
@@ -634,28 +577,40 @@ export class OrderInventoryQuery {
|
|
|
634
577
|
|
|
635
578
|
switch (sort.name) {
|
|
636
579
|
case 'roName':
|
|
637
|
-
acc =
|
|
638
|
-
break
|
|
639
|
-
|
|
640
|
-
case 'releaseGood':
|
|
641
|
-
acc = { ...acc, ['rg.created_at']: order }
|
|
580
|
+
acc = [...acc, '"releaseGoodName" ' + order]
|
|
642
581
|
break
|
|
643
582
|
|
|
644
583
|
case 'productSku':
|
|
645
|
-
acc =
|
|
584
|
+
acc = [...acc, '"productSKU" ' + order]
|
|
646
585
|
break
|
|
647
586
|
|
|
648
587
|
case 'binNumber':
|
|
649
|
-
acc =
|
|
588
|
+
acc = [...acc, '"binNumber" ' + order]
|
|
589
|
+
break
|
|
590
|
+
|
|
591
|
+
case 'toteNumber':
|
|
592
|
+
acc = [...acc, '"toteNumber" ' + order]
|
|
650
593
|
break
|
|
651
594
|
}
|
|
652
595
|
|
|
653
596
|
return acc
|
|
654
|
-
},
|
|
655
|
-
|
|
597
|
+
}, [])
|
|
598
|
+
|
|
599
|
+
sort = (priority ? ', ' : ' order by ') + sorter.toString()
|
|
656
600
|
}
|
|
657
601
|
|
|
658
|
-
|
|
602
|
+
let items = await tx.query(
|
|
603
|
+
`
|
|
604
|
+
select * from temp_route_label tmp where 1 = 1
|
|
605
|
+
${withSkuQuery}
|
|
606
|
+
${withBinQuery}
|
|
607
|
+
${withToteQuery}
|
|
608
|
+
${prioritySort}
|
|
609
|
+
${sort}
|
|
610
|
+
`
|
|
611
|
+
)
|
|
612
|
+
|
|
613
|
+
let total = items.length
|
|
659
614
|
|
|
660
615
|
return { items, total }
|
|
661
616
|
} catch (e) {
|
|
@@ -401,4 +401,22 @@ export class OrderInventory {
|
|
|
401
401
|
|
|
402
402
|
@Field({ nullable: true })
|
|
403
403
|
extraJsonData: string
|
|
404
|
+
|
|
405
|
+
@Field({ nullable: true })
|
|
406
|
+
binNumber: string
|
|
407
|
+
|
|
408
|
+
@Field({ nullable: true })
|
|
409
|
+
toteNumber: string
|
|
410
|
+
|
|
411
|
+
@Field({ nullable: true })
|
|
412
|
+
routeId: string
|
|
413
|
+
|
|
414
|
+
@Field({ nullable: true })
|
|
415
|
+
storeId: string
|
|
416
|
+
|
|
417
|
+
@Field({ nullable: true })
|
|
418
|
+
storeName: string
|
|
419
|
+
|
|
420
|
+
@Field({ nullable: true })
|
|
421
|
+
stopId: string
|
|
404
422
|
}
|
|
@@ -6,7 +6,7 @@ import { Attachment, createAttachments, deleteAttachmentsByRef } from '@things-f
|
|
|
6
6
|
import { User } from '@things-factory/auth-base'
|
|
7
7
|
import { Bizplace, ContactPoint, getPermittedBizplaces } from '@things-factory/biz-base'
|
|
8
8
|
import { generateId } from '@things-factory/id-rule-base'
|
|
9
|
-
import { Product } from '@things-factory/product-base'
|
|
9
|
+
import { Product, ProductDetail } from '@things-factory/product-base'
|
|
10
10
|
import { Setting } from '@things-factory/setting-base'
|
|
11
11
|
import { Domain } from '@things-factory/shell'
|
|
12
12
|
import { Location } from '@things-factory/warehouse-base'
|
|
@@ -433,12 +433,16 @@ export async function upsertPurchaseOrderProducts(
|
|
|
433
433
|
orderProducts = await Promise.all(
|
|
434
434
|
orderProducts.map(async (op: OrderProduct) => {
|
|
435
435
|
if (!op?.id) delete op.id
|
|
436
|
+
let foundProductDetail: ProductDetail = await tx
|
|
437
|
+
.getRepository(ProductDetail)
|
|
438
|
+
.findOne({ where: { product: op.product.id, packingType: op.packingType } })
|
|
436
439
|
return {
|
|
437
440
|
...op,
|
|
438
441
|
domain,
|
|
439
442
|
bizplace: bizplace,
|
|
440
443
|
name: op?.id ? op.name : OrderNoGenerator.orderProduct(),
|
|
441
444
|
product: await productRepo.findOne(op.product.id),
|
|
445
|
+
packingSize: foundProductDetail?.packingSize || 1,
|
|
442
446
|
purchaseOrder: purchaseOrder,
|
|
443
447
|
status: purchaseOrder.status,
|
|
444
448
|
creator: op?.id ? op.creator : user,
|