@things-factory/sales-base 4.3.59 → 4.3.62

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/constants/release-good.js +5 -1
  2. package/dist-server/constants/release-good.js.map +1 -1
  3. package/dist-server/service/delivery-order/delivery-order-mutation.js +6 -15
  4. package/dist-server/service/delivery-order/delivery-order-mutation.js.map +1 -1
  5. package/dist-server/service/draft-release-good/draft-release-good-mutation.js +26 -19
  6. package/dist-server/service/draft-release-good/draft-release-good-mutation.js.map +1 -1
  7. package/dist-server/service/draft-release-good/draft-release-good-query.js +36 -3
  8. package/dist-server/service/draft-release-good/draft-release-good-query.js.map +1 -1
  9. package/dist-server/service/manifest/manifest-mutation.js +7 -3
  10. package/dist-server/service/manifest/manifest-mutation.js.map +1 -1
  11. package/dist-server/service/order-inventory/order-inventory-query.js +54 -27
  12. package/dist-server/service/order-inventory/order-inventory-query.js.map +1 -1
  13. package/dist-server/service/order-inventory/order-inventory.js +4 -2
  14. package/dist-server/service/order-inventory/order-inventory.js.map +1 -1
  15. package/dist-server/service/order-product/order-product-query.js +35 -4
  16. package/dist-server/service/order-product/order-product-query.js.map +1 -1
  17. package/dist-server/service/release-good/release-good-mutation.js +102 -37
  18. package/dist-server/service/release-good/release-good-mutation.js.map +1 -1
  19. package/dist-server/service/release-good/release-good-query.js +80 -7
  20. package/dist-server/service/release-good/release-good-query.js.map +1 -1
  21. package/dist-server/service/release-good/release-good-types.js +41 -20
  22. package/dist-server/service/release-good/release-good-types.js.map +1 -1
  23. package/dist-server/service/release-good/release-good.js +25 -6
  24. package/dist-server/service/release-good/release-good.js.map +1 -1
  25. package/dist-server/service/shipping-order/shipping-order-types.js +21 -1
  26. package/dist-server/service/shipping-order/shipping-order-types.js.map +1 -1
  27. package/dist-server/service/shipping-order/shipping-order.js +22 -2
  28. package/dist-server/service/shipping-order/shipping-order.js.map +1 -1
  29. package/dist-server/utils/inventory-util.js +69 -30
  30. package/dist-server/utils/inventory-util.js.map +1 -1
  31. package/package.json +7 -7
  32. package/server/constants/release-good.ts +6 -3
  33. package/server/service/delivery-order/delivery-order-mutation.ts +5 -11
  34. package/server/service/draft-release-good/draft-release-good-mutation.ts +41 -22
  35. package/server/service/draft-release-good/draft-release-good-query.ts +56 -14
  36. package/server/service/manifest/manifest-mutation.ts +10 -3
  37. package/server/service/order-inventory/order-inventory-query.ts +68 -36
  38. package/server/service/order-inventory/order-inventory.ts +4 -2
  39. package/server/service/order-product/order-product-query.ts +45 -8
  40. package/server/service/release-good/release-good-mutation.ts +165 -50
  41. package/server/service/release-good/release-good-query.ts +126 -41
  42. package/server/service/release-good/release-good-types.ts +25 -6
  43. package/server/service/release-good/release-good.ts +24 -8
  44. package/server/service/shipping-order/shipping-order-types.ts +16 -1
  45. package/server/service/shipping-order/shipping-order.ts +18 -2
  46. package/server/utils/inventory-util.ts +107 -54
@@ -38,7 +38,7 @@ export class DraftReleaseGoodQuery {
38
38
  @Query(returns => DraftReleaseGoodList, { description: 'To fetch multiple DraftReleaseGoods' })
39
39
  async draftReleaseGoods(@Args() params: ListParam, @Ctx() context: any): Promise<DraftReleaseGoodList> {
40
40
  try {
41
- const { domain, user, tx }: { domain: Domain; user: User, tx: EntityManager } = context.state
41
+ const { domain, user, tx }: { domain: Domain; user: User; tx: EntityManager } = context.state
42
42
 
43
43
  const statusFilter = params.filters.find(e => e.name === 'status')
44
44
  const bizplaceFilter = params.filters.find(param => param.name === 'bizplaceId')
@@ -55,7 +55,9 @@ export class DraftReleaseGoodQuery {
55
55
  })
56
56
  }
57
57
 
58
- params.filters = params.filters.filter(itm => itm.name !== 'noOfItems' && itm.name !== 'sku' && itm.name !== 'status')
58
+ params.filters = params.filters.filter(
59
+ itm => itm.name !== 'noOfItems' && itm.name !== 'sku' && itm.name !== 'status'
60
+ )
59
61
 
60
62
  if (orderRemarkFilter) {
61
63
  const orderRemarkIdx = params.filters.findIndex(param => param.name === 'orderRemark')
@@ -104,7 +106,8 @@ export class DraftReleaseGoodQuery {
104
106
  })
105
107
  }
106
108
 
107
- tx.query(`
109
+ tx.query(
110
+ `
108
111
  create temp table temp_op_calculation on commit drop as (
109
112
  select drg1.id, sum(case when wboi."remainQty" >= op.release_qty then 0 else 1 end) as insufficient_count, count(*) as total_row
110
113
  from draft_release_goods drg1
@@ -119,12 +122,17 @@ export class DraftReleaseGoodQuery {
119
122
  where op.domain_id = $1 and drg1.status ='DRAFT'
120
123
  group by drg1.id
121
124
  )
122
- `, [domain.id])
125
+ `,
126
+ [domain.id]
127
+ )
123
128
 
124
129
  const qb: SelectQueryBuilder<DraftReleaseGood> = tx.getRepository(DraftReleaseGood).createQueryBuilder('drg')
125
130
  buildQuery(qb, params, context)
126
131
  qb.addSelect('COALESCE("cc".rank, 99999)', 'rank')
127
- qb.addSelect(`CASE WHEN "drg".status = 'DRAFT' and (tmp_calc.insufficient_count > 0 or tmp_calc.total_row = 0) then 'INSUFFICIENT' else "drg".status END`, 'computed_status')
132
+ qb.addSelect(
133
+ `CASE WHEN "drg".status = 'DRAFT' and (tmp_calc.insufficient_count > 0 or tmp_calc.total_row = 0) then 'INSUFFICIENT' else "drg".status END`,
134
+ 'computed_status'
135
+ )
128
136
  qb.leftJoin(`temp_op_calculation`, 'tmp_calc', 'tmp_calc.id = drg.id')
129
137
  qb.leftJoinAndSelect('drg.domain', 'domain')
130
138
  qb.leftJoinAndSelect('drg.bizplace', 'bizplace')
@@ -205,10 +213,11 @@ export class DraftReleaseGoodQuery {
205
213
  )
206
214
 
207
215
  qb.orderBy(sort)
216
+ qb.offset((params.pagination.page - 1) * params.pagination.limit)
217
+ qb.limit(params.pagination.limit)
208
218
 
209
219
  let [items, total] = await Promise.all([qb.getRawMany(), qb.getCount()])
210
220
 
211
-
212
221
  items = items.map(itm => {
213
222
  return {
214
223
  id: itm.drg_id,
@@ -234,7 +243,6 @@ export class DraftReleaseGoodQuery {
234
243
  } catch (error) {
235
244
  throw error
236
245
  }
237
-
238
246
  }
239
247
  }
240
248
 
@@ -260,7 +268,6 @@ export async function getDraftReleaseGoodFunction(_: any, name: any, context: an
260
268
 
261
269
  if (!result?.id) throw new Error(`Failed to find draft release good ${name}`)
262
270
 
263
-
264
271
  let foundPermittedBizplace: Bizplace
265
272
  let companyBizplace: Bizplace
266
273
 
@@ -282,17 +289,53 @@ export async function getDraftReleaseGoodFunction(_: any, name: any, context: an
282
289
 
283
290
  let productInventory
284
291
  if (result.orderProducts.length > 0)
285
- productInventory = await InventoryUtil.bizplaceProductInventory(bizplaces, { filters: [{ name: 'bizplaceId', operator: 'eq', value: result.bizplace.id }, { name: 'productId', operator: 'in', value: [...result.orderProducts.filter(itm => itm?.product).map(itm => { return itm.product.id }), ...result.orderProducts.filter(itm => itm?.productBundle).map(itm => { return itm.productBundle.id })] }] }, context, tx)
292
+ productInventory = await InventoryUtil.bizplaceProductInventory(
293
+ bizplaces,
294
+ {
295
+ filters: [
296
+ { name: 'bizplaceId', operator: 'eq', value: result.bizplace.id },
297
+ {
298
+ name: 'productId',
299
+ operator: 'in',
300
+ value: [
301
+ ...result.orderProducts
302
+ .filter(itm => itm?.product)
303
+ .map(itm => {
304
+ return itm.product.id
305
+ }),
306
+ ...result.orderProducts
307
+ .filter(itm => itm?.productBundle)
308
+ .map(itm => {
309
+ return itm.productBundle.id
310
+ })
311
+ ]
312
+ }
313
+ ]
314
+ },
315
+ context,
316
+ tx
317
+ )
286
318
 
287
319
  result.orderProducts = result.orderProducts.map(itm => {
288
- let foundProductInv = productInventory?.items.find(i => (i.productId == itm?.product?.id || i.productId == itm?.productBundle?.id) && i.packingType == itm.packingType && i.packingSize == itm.packingSize && i.uom == itm.uom)
320
+ let foundProductInv = productInventory?.items.find(
321
+ i =>
322
+ (i.productId == itm?.product?.id || i.productId == itm?.productBundle?.id) &&
323
+ i.packingType == itm.packingType &&
324
+ i.packingSize == itm.packingSize &&
325
+ i.uom == itm.uom
326
+ )
289
327
  return {
290
328
  ...itm,
291
- product: itm.product || { id: foundProductInv.productId, name: foundProductInv.productName, brand: foundProductInv.productBrand, sku: foundProductInv.productSKU },
329
+ product: itm.product || {
330
+ id: foundProductInv.productId,
331
+ name: foundProductInv.productName,
332
+ brand: foundProductInv.productBrand,
333
+ sku: foundProductInv.productSKU
334
+ },
292
335
  groupType: foundProductInv ? foundProductInv.groupType : 'SINGLE',
293
336
  remainQty: foundProductInv ? foundProductInv.remainQty : 0,
294
337
  remainUomValue: foundProductInv ? foundProductInv.remainUomValue : 0,
295
- remainUomValueWithUom: foundProductInv ? foundProductInv.remainUomValueWithUom : 0,
338
+ remainUomValueWithUom: foundProductInv ? foundProductInv.remainUomValueWithUom : 0
296
339
  }
297
340
  })
298
341
  const foundAttachments: Attachment[] = await tx.getRepository(Attachment).find({
@@ -307,8 +350,7 @@ export async function getDraftReleaseGoodFunction(_: any, name: any, context: an
307
350
  ...result,
308
351
  attachment: foundAttachments
309
352
  }
310
-
311
353
  } catch (error) {
312
354
  console.error(error)
313
355
  }
314
- }
356
+ }
@@ -44,7 +44,9 @@ export class ManifestMutation {
44
44
  if (removeOrders?.length > 0) {
45
45
  //check if user removing all tracking no, if yes then delete
46
46
  let totalTrackingNo = await tx.getRepository(ReleaseGood).count({ where: { manifest: manifestId } })
47
- await tx.getRepository(ReleaseGood).update({ domain, refNo: In(removeOrders) }, { manifest: null })
47
+ await tx
48
+ .getRepository(ReleaseGood)
49
+ .update({ domain, refNo: In(removeOrders) }, { manifest: null, manifestedBy: null, manifestedAt: null })
48
50
  if (removeOrders.length == totalTrackingNo) {
49
51
  await tx.getRepository(Manifest).delete(manifestId)
50
52
  return false
@@ -101,6 +103,8 @@ export class ManifestMutation {
101
103
  .findOne({ domain, refNo: item.refNo, trackingNo: item.trackingNo })
102
104
  releaseOrder.manifest = manifest
103
105
  releaseOrder.updater = user
106
+ releaseOrder.manifestedBy = user.id
107
+ releaseOrder.manifestedAt = new Date()
104
108
  await tx.getRepository(ReleaseGood).save(releaseOrder)
105
109
  })
106
110
  )
@@ -117,7 +121,7 @@ export class ManifestMutation {
117
121
  @Arg('shippingProvider', { nullable: true }) shippingProvider: string,
118
122
  @Ctx() context: any
119
123
  ): Promise<boolean> {
120
- const { domain, tx } = context.state
124
+ const { domain, user, tx } = context.state
121
125
  const releaseGoodRepo = tx.getRepository(ReleaseGood)
122
126
  //check if order belongs to same shipping provider
123
127
  let foundReleaseOrder = await releaseGoodRepo.findOne({ where: { trackingNo }, relations: ['manifest'] })
@@ -134,7 +138,10 @@ export class ManifestMutation {
134
138
  throw new Error(i18next.t('error.tracking_no_belongs_to_x', { x: foundReleaseOrder.transporter }))
135
139
  }
136
140
 
137
- await releaseGoodRepo.update({ id: foundReleaseOrder.id }, { manifest: manifestId })
141
+ await releaseGoodRepo.update(
142
+ { id: foundReleaseOrder.id },
143
+ { manifest: manifestId, manifestedAt: new Date(), manifestedBy: user }
144
+ )
138
145
 
139
146
  return true
140
147
  }
@@ -1,11 +1,11 @@
1
- import { Arg, Args, Ctx, FieldResolver, Query, Resolver, Root, Directive } from 'type-graphql'
1
+ import { Arg, Args, Ctx, Directive, FieldResolver, Query, Resolver, Root } from 'type-graphql'
2
2
  import { Brackets, EntityManager, getRepository, Like, SelectQueryBuilder } from 'typeorm'
3
3
 
4
4
  import { User } from '@things-factory/auth-base'
5
5
  import { getPermittedBizplaceIds } from '@things-factory/biz-base'
6
6
  import { Product } from '@things-factory/product-base'
7
7
  import { buildQuery, convertListParams, Domain, Filter, ListParam, Pagination, Sorting } from '@things-factory/shell'
8
- import { Inventory, InventoryPatch, Location } from '@things-factory/warehouse-base'
8
+ import { Inventory, InventoryPatch } from '@things-factory/warehouse-base'
9
9
 
10
10
  import { ORDER_INVENTORY_STATUS, ORDER_STATUS } from '../../constants'
11
11
  import { ArrivalNotice } from '../arrival-notice/arrival-notice'
@@ -23,58 +23,90 @@ export class OrderInventoryQuery {
23
23
  @Query(returns => OrderInventoryList)
24
24
  async orderInventories(@Ctx() context: any, @Args() params: ListParam): Promise<OrderInventoryList> {
25
25
  const { domain }: { domain: Domain } = context.state
26
- let filters = params.filters
26
+ const arrivalNoticeNoParam: any = params.filters.find((param: any) => param.name === 'arrivalNoticeNo')
27
+ const releaseGoodNoParam: any = params.filters.find((param: any) => param.name === 'releaseGoodNo')
27
28
 
28
- // in case client side passes arrival notice or release good number as filter (single value only)
29
- const anParam = filters.find(
30
- (filter: filterInterface) => filter.name === 'arrivalNoticeNo' && filter.operator === 'eq'
31
- )
32
- const rgParam = filters.find(
33
- (filter: filterInterface) => filter.name === 'releaseGoodNo' && filter.operator === 'eq'
34
- )
35
-
36
- if (anParam && !filters.some((filter: filterInterface) => filter.name === 'arrivalNotice')) {
29
+ if (arrivalNoticeNoParam && arrivalNoticeNoParam?.value) {
37
30
  const foundArrivalNotice: ArrivalNotice = await getRepository(ArrivalNotice).findOne({
38
31
  where: {
39
- name: anParam.value,
32
+ name: arrivalNoticeNoParam.value,
40
33
  domain
41
34
  }
42
35
  })
43
36
 
44
37
  if (foundArrivalNotice) {
45
- filters = params.filters.filter((filter: filterInterface) => filter.name !== 'arrivalNoticeNo')
46
- params.filters = [...filters, { name: 'arrivalNotice', operator: 'eq', value: foundArrivalNotice.id }]
47
- } else throw new Error(`Cannot find result for order "${anParam.value}"`)
38
+ params.filters.splice(
39
+ params.filters.findIndex(item => item.name == 'arrivalNoticeNo'),
40
+ 1
41
+ )
42
+ params.filters.push({ name: 'arrivalNoticeId', operator: 'eq', value: foundArrivalNotice.id })
43
+ } else {
44
+ throw new Error(`Cannot find result for order "${arrivalNoticeNoParam.value}"`)
45
+ }
48
46
  }
49
47
 
50
- if (rgParam && !filters.some(filter => filter.name === 'releaseGood')) {
48
+ if (releaseGoodNoParam && releaseGoodNoParam?.value) {
51
49
  const foundReleaseGood: ReleaseGood = await getRepository(ReleaseGood).findOne({
52
50
  where: {
53
- name: rgParam.value,
51
+ name: releaseGoodNoParam.value,
54
52
  domain
55
53
  }
56
54
  })
57
55
 
58
56
  if (foundReleaseGood) {
59
- filters = params.filters.filter(filter => filter.name !== 'releaseGoodNo')
60
- params.filters = [...filters, { name: 'releaseGood', operator: 'eq', value: foundReleaseGood.id }]
61
- } else throw new Error(`Cannot find result for order "${rgParam.value}"`)
57
+ params.filters.splice(
58
+ params.filters.findIndex(item => item.name == 'releaseGoodNo'),
59
+ 1
60
+ )
61
+ params.filters.push({ name: 'releaseGoodId', operator: 'eq', value: foundReleaseGood.id })
62
+ } else {
63
+ throw new Error(`Cannot find result for order "${releaseGoodNoParam.value}"`)
64
+ }
62
65
  }
63
66
 
64
- const convertedParams = convertListParams(params)
65
- const [items, total] = await getRepository(OrderInventory).findAndCount({
66
- ...convertedParams,
67
- relations: [
68
- 'domain',
69
- 'arrivalNotice',
70
- 'inventory',
71
- 'inventory.product',
72
- 'releaseGood',
73
- 'deliveryOrder',
74
- 'creator',
75
- 'updater'
76
- ]
77
- })
67
+ const qb: SelectQueryBuilder<OrderInventory> = getRepository(OrderInventory).createQueryBuilder('oi')
68
+ buildQuery(qb, params, context)
69
+
70
+ qb.leftJoinAndSelect('oi.domain', 'domain')
71
+ qb.leftJoinAndSelect('oi.arrivalNotice', 'arrivalNotice')
72
+ qb.leftJoinAndSelect('oi.orderProduct', 'orderProduct')
73
+ qb.leftJoinAndSelect('oi.inventory', 'inventory')
74
+ qb.leftJoinAndSelect('inventory.product', 'product')
75
+ qb.leftJoinAndSelect('inventory.location', 'location')
76
+ qb.leftJoinAndSelect('oi.releaseGood', 'releaseGood')
77
+ qb.leftJoinAndSelect('oi.deliveryOrder', 'deliveryOrder')
78
+ qb.leftJoinAndSelect('oi.creator', 'creator')
79
+ qb.leftJoinAndSelect('oi.updater', 'updater')
80
+
81
+ let sort = {}
82
+ if (params?.sortings) {
83
+ if (params.sortings.some(e => e.name === 'inventoryPalletId')) {
84
+ // overwrite the worksheet status sorting since inventory check status is needed
85
+ sort = {
86
+ 'inventory.palletId': params.sortings[params.sortings.findIndex(item => item.name == 'inventoryPalletId')]
87
+ .desc
88
+ ? 'DESC'
89
+ : 'ASC',
90
+ 'oi.createdAt': params.sortings[params.sortings.findIndex(item => item.name == 'createdAt')]?.desc
91
+ ? 'DESC'
92
+ : 'ASC'
93
+ }
94
+ } else if (params.sortings.some(e => e.name === 'createdAt')) {
95
+ sort = {
96
+ ...sort,
97
+ 'oi.createdAt': params.sortings[params.sortings.findIndex(item => item.name == 'createdAt')]?.desc
98
+ ? 'DESC'
99
+ : 'ASC'
100
+ }
101
+ }
102
+ } else {
103
+ sort = { 'oi.createdAt': 'ASC' }
104
+ }
105
+
106
+ qb.orderBy(sort)
107
+
108
+ let [items, total] = await qb.getManyAndCount()
109
+
78
110
  return { items, total }
79
111
  }
80
112
 
@@ -457,7 +489,7 @@ export class OrderInventoryQuery {
457
489
  let sort = ''
458
490
  let prioritySort = ''
459
491
  let releaseOrderIdQuery = ''
460
-
492
+
461
493
  // Require further evaluation. Potential performance issue.
462
494
  if (mergedPageParam) {
463
495
  releaseOrderIdQuery = `
@@ -62,6 +62,9 @@ import { TransferOrder } from '../transfer-order/transfer-order'
62
62
  orderInventory.releaseQty,
63
63
  orderInventory.uom
64
64
  ])
65
+ @Index('ix_order-inventory_5', (orderInventory: OrderInventory) => [
66
+ orderInventory.releaseGood
67
+ ])
65
68
  @ObjectType()
66
69
  export class OrderInventory {
67
70
  @PrimaryGeneratedColumn('uuid')
@@ -334,9 +337,8 @@ export class OrderInventory {
334
337
  @Field({ nullable: true })
335
338
  loadedAt: Date
336
339
 
337
- @Column({ nullable: true })
338
340
  @Field({ nullable: true })
339
- shippedAt: Date
341
+ dispatchedAt: Date
340
342
 
341
343
  @CreateDateColumn()
342
344
  @Field()
@@ -1,7 +1,9 @@
1
- import { User } from '@things-factory/auth-base'
2
- import { convertListParams, Domain, Filter, Pagination, Sorting } from '@things-factory/shell'
3
1
  import { Arg, Ctx, FieldResolver, Query, Resolver, Root } from 'type-graphql'
4
- import { getRepository } from 'typeorm'
2
+ import { Brackets, getRepository, SelectQueryBuilder } from 'typeorm'
3
+
4
+ import { User } from '@things-factory/auth-base'
5
+ import { Domain, Filter, Pagination, Sorting } from '@things-factory/shell'
6
+
5
7
  import { OrderProductList } from '../'
6
8
  import { OrderProduct } from './order-product'
7
9
 
@@ -14,11 +16,46 @@ export class OrderProductQuery {
14
16
  @Arg('pagination', type => Pagination, { nullable: true }) pagination?: Pagination,
15
17
  @Arg('sortings', type => [Sorting], { nullable: true }) sortings?: Sorting[]
16
18
  ): Promise<OrderProductList> {
17
- const convertedParams = convertListParams({ filters, pagination, sortings })
18
- const [items, total] = await getRepository(OrderProduct).findAndCount({
19
- ...convertedParams,
20
- relations: ['domain', 'bizplace', 'bizplace.company', 'arrivalNotice', 'product', 'creator', 'updater']
21
- })
19
+ const { domain, user }: { domain: Domain; user: User } = context.state
20
+ const params = { filters, pagination }
21
+
22
+ const releaseGoodFilters = params.filters.filter(x => x.name == 'releaseGood')
23
+ const productFilters = params.filters.filter(x => x.name == 'productInfo')
24
+ const productFilterColumns = ['sku', 'brand_sku', 'name', 'description', 'brand', 'sub_brand']
25
+ params.filters = params.filters.filter(x => x.name != 'productInfo')
26
+
27
+ let qb: SelectQueryBuilder<OrderProduct> = await getRepository(OrderProduct).createQueryBuilder('op')
28
+ qb.leftJoinAndSelect('op.product', 'product')
29
+ .leftJoinAndSelect('op.domain', 'domain')
30
+ .leftJoinAndSelect('op.bizplace', 'bizplace')
31
+ .leftJoinAndSelect('bizplace.company', 'company')
32
+ .leftJoinAndSelect('op.arrivalNotice', 'an')
33
+ .leftJoinAndSelect('op.releaseGood', 'rg')
34
+ .leftJoinAndSelect('op.creator', 'creator')
35
+ .leftJoinAndSelect('op.updater', 'updater')
36
+ .andWhere('op.domain_id = :domainId', { domainId: domain.id })
37
+ .andWhere('op.release_good_id IN (:...releaseGoodId)', { releaseGoodId: releaseGoodFilters[0].value })
38
+
39
+ if (productFilters && productFilters.length > 0) {
40
+ let productInfo = productFilters[0]
41
+ let productValue = productInfo.value
42
+ .toLowerCase()
43
+ .split(',')
44
+ .map(prod => {
45
+ return "'%" + prod.trim().replace(/'/g, "''") + "%'"
46
+ })
47
+ .join(',')
48
+ qb.andWhere(
49
+ new Brackets(qb2 => {
50
+ productFilterColumns.forEach(filter => {
51
+ qb2.orWhere(`Lower("product"."${filter}") LIKE ANY(ARRAY[${productValue}])`)
52
+ })
53
+ })
54
+ )
55
+ }
56
+
57
+ let [items, total] = await qb.getManyAndCount()
58
+
22
59
  return { items, total }
23
60
  }
24
61