@things-factory/sales-base 4.3.39 → 4.3.42

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.
Files changed (46) hide show
  1. package/dist-server/controllers/ecommerce/sellercraft-controller.js +2 -2
  2. package/dist-server/controllers/ecommerce/sellercraft-controller.js.map +1 -1
  3. package/dist-server/service/delivery-order/delivery-order-mutation.js +58 -6
  4. package/dist-server/service/delivery-order/delivery-order-mutation.js.map +1 -1
  5. package/dist-server/service/delivery-order/delivery-order-types.js +20 -0
  6. package/dist-server/service/delivery-order/delivery-order-types.js.map +1 -1
  7. package/dist-server/service/goods-receival-note/goods-receival-note-query.js +96 -5
  8. package/dist-server/service/goods-receival-note/goods-receival-note-query.js.map +1 -1
  9. package/dist-server/service/goods-receival-note/goods-receival-note-types.js +65 -1
  10. package/dist-server/service/goods-receival-note/goods-receival-note-types.js.map +1 -1
  11. package/dist-server/service/goods-receival-note/goods-receival-note.js +41 -0
  12. package/dist-server/service/goods-receival-note/goods-receival-note.js.map +1 -1
  13. package/dist-server/service/order-inventory/order-inventory-query.js +111 -142
  14. package/dist-server/service/order-inventory/order-inventory-query.js.map +1 -1
  15. package/dist-server/service/order-inventory/order-inventory.js +24 -0
  16. package/dist-server/service/order-inventory/order-inventory.js.map +1 -1
  17. package/dist-server/service/purchase-order/purchase-order-mutation.js +4 -1
  18. package/dist-server/service/purchase-order/purchase-order-mutation.js.map +1 -1
  19. package/dist-server/service/release-good/release-good-mutation.js +52 -8
  20. package/dist-server/service/release-good/release-good-mutation.js.map +1 -1
  21. package/dist-server/service/release-good/release-good-types.js +153 -1
  22. package/dist-server/service/release-good/release-good-types.js.map +1 -1
  23. package/dist-server/service/release-good/release-good.js +20 -0
  24. package/dist-server/service/release-good/release-good.js.map +1 -1
  25. package/dist-server/utils/datetime-util.js +49 -0
  26. package/dist-server/utils/datetime-util.js.map +1 -0
  27. package/dist-server/utils/index.js +1 -0
  28. package/dist-server/utils/index.js.map +1 -1
  29. package/dist-server/utils/inventory-util.js +19 -2
  30. package/dist-server/utils/inventory-util.js.map +1 -1
  31. package/package.json +12 -12
  32. package/server/controllers/ecommerce/sellercraft-controller.ts +2 -2
  33. package/server/service/delivery-order/delivery-order-mutation.ts +91 -16
  34. package/server/service/delivery-order/delivery-order-types.ts +15 -0
  35. package/server/service/goods-receival-note/goods-receival-note-query.ts +120 -10
  36. package/server/service/goods-receival-note/goods-receival-note-types.ts +48 -0
  37. package/server/service/goods-receival-note/goods-receival-note.ts +32 -0
  38. package/server/service/order-inventory/order-inventory-query.ts +121 -166
  39. package/server/service/order-inventory/order-inventory.ts +18 -0
  40. package/server/service/purchase-order/purchase-order-mutation.ts +5 -1
  41. package/server/service/release-good/release-good-mutation.ts +67 -13
  42. package/server/service/release-good/release-good-types.ts +112 -0
  43. package/server/service/release-good/release-good.ts +16 -0
  44. package/server/utils/datetime-util.ts +54 -0
  45. package/server/utils/index.ts +1 -0
  46. 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
- ? sort.name + '.name'
127
- : arrGanStatusSortData.indexOf(sort.name) >= 0
128
- ? 'arrivalNotice.status'
129
- : arrGrnStatuSortData.indexOf(sort.name) >= 0
130
- ? 'grn.status'
131
- : 'grn.' + sort.name]: sort.desc ? 'DESC' : 'ASC'
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(@Arg('name') name: string, @Ctx() context: any): Promise<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
- return await getRepository(GoodsReceivalNote).findOne({
158
+
159
+ const foundGRN: GoodsReceivalNote = await getRepository(GoodsReceivalNote).findOne({
147
160
  where: { domain, name },
148
- relations: ['domain', 'bizplace', 'bizplace.company', 'arrivalNotice', 'creator', 'updater']
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 binNumberParam: any = filters.find((param: any) => param.name === 'binNumber')
451
- let arrFilters = []
452
-
453
- if (binNumberParam) {
454
- let binLocation: Location = await getRepository(Location).findOne({
455
- where: { domain, name: binNumberParam.value }
456
- })
457
-
458
- filters.splice(
459
- filters.findIndex(item => item.name == 'binNumber'),
460
- 1
461
- )
462
- arrFilters.push({ ...binNumberParam, name: 'binLocationId', value: binLocation.id })
463
- }
464
-
465
- const releaseGoodsList: ReleaseGood[] = await getRepository(ReleaseGood).query(
466
- `select id from release_goods where domain_id = '${domain.id}' and bizplace_id = '${partnerId}' and route_id is not null and status = 'PICKING'`
467
- )
468
-
469
- if (releaseGoodsList && releaseGoodsList.length) {
470
- arrFilters.push({
471
- name: 'releaseGoodId',
472
- operator: 'in',
473
- value: releaseGoodsList.map((foundRG: ReleaseGood) => foundRG.id),
474
- relation: false
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
- arrFilters.push({
478
- name: 'releaseGoodId',
479
- operator: 'is_null',
480
- relation: false
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
- const params = { filters: arrFilters }
485
- const qb: SelectQueryBuilder<OrderInventory> = getRepository(OrderInventory).createQueryBuilder('oi')
486
- buildQuery(qb, params, context)
487
-
488
- qb.select('oi')
489
- qb.innerJoinAndSelect('oi.releaseGood', 'rg')
490
- qb.innerJoinAndSelect('oi.product', 'Product')
491
- qb.leftJoinAndSelect('oi.binLocation', 'bin_loc')
492
- qb.leftJoinAndSelect('oi.domain', 'domain')
493
- qb.leftJoinAndSelect('oi.creator', 'creator')
494
- qb.leftJoinAndSelect('oi.updater', 'updater')
495
-
496
- if (sortings?.length !== 0) {
497
- const sorter = (sortings || []).reduce((acc, sort) => {
498
- const order: string = sort.desc ? 'DESC' : 'ASC'
499
-
500
- switch (sort.name) {
501
- case 'roName':
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
- return acc
515
- }, {})
516
- qb.orderBy(sorter)
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
- const [items, total] = await qb.getManyAndCount()
520
-
521
- return { items, total }
522
- } catch (e) {
523
- throw e
524
- }
525
- }
536
+ if (priority) {
537
+ prioritySort = ' order by '
526
538
 
527
- @Query(returns => OrderInventoryList)
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
- sortings.push({ name: 'releaseGood', desc: true })
549
- sortings.push({ name: 'productSku', desc: false })
541
+ prioritySort = prioritySort + '"createdAt" desc, "productSKU" asc'
550
542
  break
551
543
 
552
544
  case 'roBin':
553
- sortings.push({ name: 'releaseGood', desc: true })
554
- sortings.push({ name: 'binNumber', desc: false })
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
- sortings.push({ name: 'productSku', desc: false })
559
- sortings.push({ name: 'releaseGood', desc: true })
553
+ prioritySort = prioritySort + '"productSKU" asc, "createdAt" desc'
560
554
  break
561
555
 
562
556
  case 'skuBin':
563
- sortings.push({ name: 'productSku', desc: false })
564
- sortings.push({ name: 'binNumber', desc: false })
557
+ prioritySort = prioritySort + '"productSKU" asc, "binNumber" asc'
565
558
  break
566
559
 
567
560
  case 'binSku':
568
- sortings.push({ name: 'binNumber', desc: false })
569
- sortings.push({ name: 'productSku', desc: false })
561
+ prioritySort = prioritySort + '"binNumber" asc, "productSKU" asc'
570
562
  break
571
563
 
572
564
  case 'binRo':
573
- sortings.push({ name: 'binNumber', desc: false })
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
- const params = { filters: arrFilters }
607
- const qb: SelectQueryBuilder<OrderInventory> = getRepository(OrderInventory).createQueryBuilder('oi')
608
- buildQuery(qb, params, context)
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 = { ...acc, ['rg.name']: order }
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 = { ...acc, ['Product.sku']: order }
584
+ acc = [...acc, '"productSKU" ' + order]
646
585
  break
647
586
 
648
587
  case 'binNumber':
649
- acc = { ...acc, ['bin_loc.name']: order }
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
- qb.orderBy(sorter)
597
+ }, [])
598
+
599
+ sort = (priority ? ', ' : ' order by ') + sorter.toString()
656
600
  }
657
601
 
658
- const [items, total] = await qb.getManyAndCount()
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,