@things-factory/warehouse-base 5.0.14 → 6.0.0-alpha.0

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 (142) hide show
  1. package/dist-server/controllers/ecommerce/ecommerce-controller.js +1 -1
  2. package/dist-server/controllers/ecommerce/ecommerce-controller.js.map +1 -1
  3. package/dist-server/controllers/ecommerce/sellercraft-controller.js +64 -60
  4. package/dist-server/controllers/ecommerce/sellercraft-controller.js.map +1 -1
  5. package/dist-server/controllers/warehouse-controller.js +7 -5
  6. package/dist-server/controllers/warehouse-controller.js.map +1 -1
  7. package/dist-server/service/inventory/inventory-mutation.js +6 -6
  8. package/dist-server/service/inventory/inventory-mutation.js.map +1 -1
  9. package/dist-server/service/inventory/inventory-query.js +217 -195
  10. package/dist-server/service/inventory/inventory-query.js.map +1 -1
  11. package/dist-server/service/inventory/inventory-types.js +14 -15
  12. package/dist-server/service/inventory/inventory-types.js.map +1 -1
  13. package/dist-server/service/inventory/inventory.js +62 -42
  14. package/dist-server/service/inventory/inventory.js.map +1 -1
  15. package/dist-server/service/inventory-change/inventory-change-mutation.js +252 -216
  16. package/dist-server/service/inventory-change/inventory-change-mutation.js.map +1 -1
  17. package/dist-server/service/inventory-change/inventory-change-query.js +6 -7
  18. package/dist-server/service/inventory-change/inventory-change-query.js.map +1 -1
  19. package/dist-server/service/inventory-change/inventory-change.js +7 -7
  20. package/dist-server/service/inventory-change/inventory-change.js.map +1 -1
  21. package/dist-server/service/inventory-history/inventory-history-mutation.js +1 -1
  22. package/dist-server/service/inventory-history/inventory-history-mutation.js.map +1 -1
  23. package/dist-server/service/inventory-history/inventory-history-query.js +89 -99
  24. package/dist-server/service/inventory-history/inventory-history-query.js.map +1 -1
  25. package/dist-server/service/inventory-history/inventory-history-types.js +3 -3
  26. package/dist-server/service/inventory-history/inventory-history-types.js.map +1 -1
  27. package/dist-server/service/inventory-history/inventory-history.js +7 -7
  28. package/dist-server/service/inventory-history/inventory-history.js.map +1 -1
  29. package/dist-server/service/inventory-item/inventory-item-mutation.js +10 -10
  30. package/dist-server/service/inventory-item/inventory-item-mutation.js.map +1 -1
  31. package/dist-server/service/inventory-item/inventory-item-query.js +18 -17
  32. package/dist-server/service/inventory-item/inventory-item-query.js.map +1 -1
  33. package/dist-server/service/inventory-item/inventory-item-type.js +4 -5
  34. package/dist-server/service/inventory-item/inventory-item-type.js.map +1 -1
  35. package/dist-server/service/inventory-item/inventory-item.js +5 -5
  36. package/dist-server/service/inventory-item/inventory-item.js.map +1 -1
  37. package/dist-server/service/inventory-item-change/inventory-item-change-mutation.js +4 -4
  38. package/dist-server/service/inventory-item-change/inventory-item-change-mutation.js.map +1 -1
  39. package/dist-server/service/inventory-item-change/inventory-item-change-query.js +7 -9
  40. package/dist-server/service/inventory-item-change/inventory-item-change-query.js.map +1 -1
  41. package/dist-server/service/inventory-item-change/inventory-item-change-type.js +6 -7
  42. package/dist-server/service/inventory-item-change/inventory-item-change-type.js.map +1 -1
  43. package/dist-server/service/inventory-item-change/inventory-item-change.js +3 -4
  44. package/dist-server/service/inventory-item-change/inventory-item-change.js.map +1 -1
  45. package/dist-server/service/inventory-product/inventory-product-mutation.js +4 -4
  46. package/dist-server/service/inventory-product/inventory-product-mutation.js.map +1 -1
  47. package/dist-server/service/inventory-product/inventory-product-query.js +7 -9
  48. package/dist-server/service/inventory-product/inventory-product-query.js.map +1 -1
  49. package/dist-server/service/inventory-product/inventory-product-type.js +1 -2
  50. package/dist-server/service/inventory-product/inventory-product-type.js.map +1 -1
  51. package/dist-server/service/inventory-product/inventory-product.js +5 -5
  52. package/dist-server/service/inventory-product/inventory-product.js.map +1 -1
  53. package/dist-server/service/location/location-mutation.js +5 -5
  54. package/dist-server/service/location/location-mutation.js.map +1 -1
  55. package/dist-server/service/location/location-query.js +17 -19
  56. package/dist-server/service/location/location-query.js.map +1 -1
  57. package/dist-server/service/location/location-types.js +3 -3
  58. package/dist-server/service/location/location-types.js.map +1 -1
  59. package/dist-server/service/location/location.js +14 -14
  60. package/dist-server/service/location/location.js.map +1 -1
  61. package/dist-server/service/movement/movement-mutation.js +6 -5
  62. package/dist-server/service/movement/movement-mutation.js.map +1 -1
  63. package/dist-server/service/movement/movement-query.js +15 -15
  64. package/dist-server/service/movement/movement-query.js.map +1 -1
  65. package/dist-server/service/movement/movement-types.js +4 -5
  66. package/dist-server/service/movement/movement-types.js.map +1 -1
  67. package/dist-server/service/movement/movement.js +5 -5
  68. package/dist-server/service/movement/movement.js.map +1 -1
  69. package/dist-server/service/pallet/pallet-mutation.js +5 -5
  70. package/dist-server/service/pallet/pallet-mutation.js.map +1 -1
  71. package/dist-server/service/pallet/pallet-query.js +9 -11
  72. package/dist-server/service/pallet/pallet-query.js.map +1 -1
  73. package/dist-server/service/pallet/pallet-types.js +5 -6
  74. package/dist-server/service/pallet/pallet-types.js.map +1 -1
  75. package/dist-server/service/pallet/pallet.js +6 -6
  76. package/dist-server/service/pallet/pallet.js.map +1 -1
  77. package/dist-server/service/pallet-count/pallet-count-mutation.js +1 -1
  78. package/dist-server/service/pallet-count/pallet-count-mutation.js.map +1 -1
  79. package/dist-server/service/pallet-count/pallet-count-query.js +6 -8
  80. package/dist-server/service/pallet-count/pallet-count-query.js.map +1 -1
  81. package/dist-server/service/pallet-count/pallet-count.js +3 -4
  82. package/dist-server/service/pallet-count/pallet-count.js.map +1 -1
  83. package/dist-server/service/pallet-history/pallet-history-mutation.js +1 -1
  84. package/dist-server/service/pallet-history/pallet-history-mutation.js.map +1 -1
  85. package/dist-server/service/pallet-history/pallet-history-query.js +6 -8
  86. package/dist-server/service/pallet-history/pallet-history-query.js.map +1 -1
  87. package/dist-server/service/pallet-history/pallet-history.js +6 -6
  88. package/dist-server/service/pallet-history/pallet-history.js.map +1 -1
  89. package/dist-server/service/reduced-inventory-history/reduced-inventory-history.js +1 -1
  90. package/dist-server/service/reduced-inventory-history/reduced-inventory-history.js.map +1 -1
  91. package/dist-server/service/tote/tote-mutation.js +4 -4
  92. package/dist-server/service/tote/tote-mutation.js.map +1 -1
  93. package/dist-server/service/tote/tote-query.js +12 -13
  94. package/dist-server/service/tote/tote-query.js.map +1 -1
  95. package/dist-server/service/tote/tote-types.js +2 -3
  96. package/dist-server/service/tote/tote-types.js.map +1 -1
  97. package/dist-server/service/tote/tote.js +5 -5
  98. package/dist-server/service/tote/tote.js.map +1 -1
  99. package/dist-server/service/warehouse/warehouse-mutation.js +1 -1
  100. package/dist-server/service/warehouse/warehouse-mutation.js.map +1 -1
  101. package/dist-server/service/warehouse/warehouse-query.js +9 -10
  102. package/dist-server/service/warehouse/warehouse-query.js.map +1 -1
  103. package/dist-server/service/warehouse/warehouse.js +12 -12
  104. package/dist-server/service/warehouse/warehouse.js.map +1 -1
  105. package/dist-server/tsconfig.tsbuildinfo +1 -1
  106. package/dist-server/utils/inventory-util.js +16 -16
  107. package/dist-server/utils/inventory-util.js.map +1 -1
  108. package/package.json +8 -8
  109. package/server/controllers/ecommerce/ecommerce-controller.ts +1 -1
  110. package/server/controllers/ecommerce/sellercraft-controller.ts +75 -65
  111. package/server/controllers/warehouse-controller.ts +9 -4
  112. package/server/service/inventory/inventory-mutation.ts +28 -24
  113. package/server/service/inventory/inventory-query.ts +269 -304
  114. package/server/service/inventory/inventory.ts +50 -35
  115. package/server/service/inventory-change/inventory-change-mutation.ts +305 -256
  116. package/server/service/inventory-change/inventory-change-query.ts +9 -9
  117. package/server/service/inventory-history/inventory-history-mutation.ts +12 -15
  118. package/server/service/inventory-history/inventory-history-query.ts +158 -133
  119. package/server/service/inventory-item/inventory-item-mutation.ts +20 -17
  120. package/server/service/inventory-item/inventory-item-query.ts +28 -18
  121. package/server/service/inventory-item-change/inventory-item-change-mutation.ts +12 -9
  122. package/server/service/inventory-item-change/inventory-item-change-query.ts +10 -8
  123. package/server/service/inventory-product/inventory-product-mutation.ts +16 -12
  124. package/server/service/inventory-product/inventory-product-query.ts +7 -8
  125. package/server/service/location/location-mutation.ts +24 -24
  126. package/server/service/location/location-query.ts +27 -23
  127. package/server/service/location/location.ts +11 -10
  128. package/server/service/movement/movement-mutation.ts +7 -8
  129. package/server/service/movement/movement-query.ts +18 -16
  130. package/server/service/pallet/pallet-mutation.ts +18 -20
  131. package/server/service/pallet/pallet-query.ts +13 -14
  132. package/server/service/pallet-count/pallet-count-mutation.ts +20 -17
  133. package/server/service/pallet-count/pallet-count-query.ts +6 -7
  134. package/server/service/pallet-history/pallet-history-mutation.ts +15 -15
  135. package/server/service/pallet-history/pallet-history-query.ts +7 -8
  136. package/server/service/reduced-inventory-history/reduced-inventory-history.ts +1 -1
  137. package/server/service/tote/tote-mutation.ts +23 -22
  138. package/server/service/tote/tote-query.ts +18 -14
  139. package/server/service/warehouse/warehouse-mutation.ts +21 -18
  140. package/server/service/warehouse/warehouse-query.ts +11 -11
  141. package/server/service/warehouse/warehouse.ts +7 -7
  142. package/server/utils/inventory-util.ts +10 -10
@@ -1,69 +1,64 @@
1
- import {
2
- Arg,
3
- Args,
4
- Ctx,
5
- Directive,
6
- FieldResolver,
7
- Query,
8
- Resolver,
9
- Root,
10
- } from 'type-graphql';
1
+ import { Arg, Args, Ctx, Directive, FieldResolver, Query, Resolver, Root } from 'type-graphql'
11
2
  import {
12
3
  Brackets,
13
4
  EntityManager,
14
5
  Equal,
15
6
  getRepository,
16
7
  Not,
8
+ OrderByCondition,
17
9
  Repository,
18
- SelectQueryBuilder,
19
- } from 'typeorm';
10
+ SelectQueryBuilder
11
+ } from 'typeorm'
20
12
 
21
- import { User } from '@things-factory/auth-base';
22
- import {
23
- Bizplace,
24
- getPartnersCompanyBizplaces,
25
- getPermittedBizplaceIds,
26
- } from '@things-factory/biz-base';
27
- import {
28
- Product,
29
- ProductBundleSetting,
30
- ProductDetail,
31
- } from '@things-factory/product-base';
32
- import { Setting } from '@things-factory/setting-base';
33
- import {
34
- buildQuery,
35
- Domain,
36
- Filter,
37
- ListParam,
38
- Pagination,
39
- Sorting,
40
- } from '@things-factory/shell';
41
-
42
- import { INVENTORY_STATUS, LOCATION_TYPE } from '../../constants';
43
- import { InventoryChange } from '../inventory-change/inventory-change';
44
- import { Inventory } from './inventory';
45
- import { InventoryBundleGroupDetail, InventoryList } from './inventory-types';
13
+ import { User } from '@things-factory/auth-base'
14
+ import { Bizplace, getPartnersCompanyBizplaces, getPermittedBizplaceIds } from '@things-factory/biz-base'
15
+ import { logger } from '@things-factory/env'
16
+ import { Product, ProductBundleSetting } from '@things-factory/product-base'
17
+ import { Setting } from '@things-factory/setting-base'
18
+ import { buildQuery, Domain, Filter, ListParam, Pagination, Sorting } from '@things-factory/shell'
19
+
20
+ import { INVENTORY_STATUS, LOCATION_TYPE } from '../../constants'
21
+ import { InventoryChange } from '../inventory-change/inventory-change'
22
+ import { Inventory } from './inventory'
23
+ import { InventoryBundleGroupDetail, InventoryList } from './inventory-types'
46
24
 
47
25
  @Resolver(Inventory)
48
26
  export class InventoryQuery {
27
+ /**
28
+ * Combined single query resolver to perform extraction of data with or without pagination
29
+ * @param context
30
+ * @param filters
31
+ * @param pagination
32
+ * @param sortings
33
+ * @param locationSortingRules
34
+ * @param exportItem
35
+ * @returns
36
+ */
49
37
  @Directive('@privilege(category: "inventory", privilege: "query")')
50
38
  @Directive('@transaction')
51
39
  @Query(returns => InventoryList)
52
40
  async inventories(
53
- @Ctx() context: any,
41
+ @Ctx() context: ResolverContext,
54
42
  @Arg('filters', type => [Filter], { nullable: true }) filters?: Filter[],
55
43
  @Arg('pagination', type => Pagination, { nullable: true }) pagination?: Pagination,
56
44
  @Arg('sortings', type => [Sorting], { nullable: true }) sortings?: Sorting[],
57
- @Arg('locationSortingRules', type => [Sorting], { nullable: true }) locationSortingRules?: Sorting[]
45
+ @Arg('locationSortingRules', type => [Sorting], { nullable: true }) locationSortingRules?: Sorting[],
46
+ @Arg('exportItem', type => Boolean, { nullable: true }) exportItem?: Boolean
58
47
  ): Promise<InventoryList> {
59
- const { domain, user, tx }: { domain: Domain; user: User; tx: EntityManager } = context.state
48
+ const { domain, user, tx } = context.state
49
+ const { page, limit } = pagination || {}
60
50
 
61
51
  try {
62
- const productFilters = filters.find(x => x.name == 'product_info')
63
- filters = filters.filter(x => x.name != 'product_info')
52
+ //Define special filters
53
+ const productFilters = filters.find((filter: any) => filter.name == 'productInfo')
54
+ const remainOnlyParam = filters.find((filter: any) => filter.name == 'remainOnly')
55
+ const bizplace = filters.find((filter: any) => filter.name === 'bizplace')
56
+
57
+ filters = filters.filter(x => ['productInfo', 'remainOnly'].indexOf(x.name) < 0)
58
+
64
59
  const params = { filters, pagination }
65
60
 
66
- if (!params.filters.find((filter: any) => filter.name === 'bizplace')) {
61
+ if (!bizplace) {
67
62
  params.filters.push({
68
63
  name: 'bizplace',
69
64
  operator: 'in',
@@ -72,56 +67,49 @@ export class InventoryQuery {
72
67
  })
73
68
  }
74
69
 
75
- const remainOnlyParam: { name: string; operator: string; value: boolean } = params?.filters?.find(
76
- (f: { name: string; operator: string; value: any }) => f.name === 'remainOnly'
77
- )
78
-
79
- let remainOnly: boolean = false
80
- if (typeof remainOnlyParam?.value !== 'undefined') {
81
- remainOnly = remainOnlyParam.value
82
- params.filters = params.filters.filter(
83
- (f: { name: string; operator: string; value: any }) => f.name !== 'remainOnly'
84
- )
85
- }
86
-
87
- const unlockOnlyParam: { name: string; operator: string; value: boolean } = params?.filters?.find(
88
- (f: { name: string; operator: string; value: any }) => f.name === 'unlockOnly'
89
- )
90
-
91
- let unlockOnly: boolean = false
92
- if (typeof unlockOnlyParam?.value !== 'undefined') {
93
- unlockOnly = unlockOnlyParam.value
94
- params.filters = params.filters.filter(
95
- (f: { name: string; operator: string; value: any }) => f.name !== 'unlockOnly'
96
- )
97
- }
70
+ const remainOnly: boolean = remainOnlyParam?.value || false
98
71
 
99
- const qb: SelectQueryBuilder<Inventory> = getRepository(Inventory).createQueryBuilder('iv')
72
+ // Define Query data
73
+ const qb: SelectQueryBuilder<Inventory> = tx.getRepository(Inventory).createQueryBuilder('inventory')
100
74
  buildQuery(qb, params, context, {
101
75
  searchables: ['warehouse', 'product', 'batchId', 'location', 'palletId']
102
76
  })
103
77
 
104
- qb.leftJoinAndSelect('iv.bizplace', 'bizplace')
105
- .leftJoinAndSelect('iv.product', 'product')
106
- .leftJoinAndSelect('iv.warehouse', 'warehouse')
107
- .leftJoinAndSelect('iv.location', 'location')
108
- .leftJoin('iv.inventoryItems', 'ivi')
109
- .loadRelationCountAndMap('iv.inventoryItemCount', 'iv.inventoryItems', 'ivic', qb =>
110
- qb.andWhere('ivic.status = :ivicStatus', {
111
- ivicStatus: INVENTORY_STATUS.STORED
112
- })
78
+ qb.leftJoinAndSelect('inventory.bizplace', 'bizplace')
79
+ .leftJoinAndSelect('inventory.product', 'product')
80
+ .leftJoinAndSelect('product.productDetails', 'productDetail', 'productDetail.id = inventory.product_detail_id')
81
+ .leftJoinAndSelect('inventory.warehouse', 'warehouse')
82
+ .leftJoinAndSelect('inventory.location', 'location')
83
+ .leftJoinAndSelect('inventory.creator', 'creator')
84
+ .leftJoinAndSelect('inventory.updater', 'updater')
85
+
86
+ // To get aggregated serial number in csv and total number of stored serial number
87
+ .leftJoinAndSelect(
88
+ subQuery => {
89
+ return subQuery
90
+ .select('inventoryItems.inventory_id', 'inventory_item_inventory_id')
91
+ .addSelect(
92
+ `SUM(case when "inventoryItems"."status" = 'STORED' then 1 else 0 end)`,
93
+ 'inventory_item_count'
94
+ )
95
+ .addSelect(`string_agg(inventoryItems.serial_number, ', ')`, 'serial_numbers')
96
+ .from('inventory_items', 'inventoryItems')
97
+ .where(`inventoryItems.domain_id = :domainId`, { domainId: domain.id })
98
+ .andWhere(`inventoryItems.status = :ivicStatus`, { ivicStatus: INVENTORY_STATUS.STORED })
99
+ .groupBy('inventoryItems.inventory_id')
100
+ },
101
+ 'inventoryItems',
102
+ '"inventoryItems"."inventory_item_inventory_id" = "inventory"."id"'
113
103
  )
114
104
 
105
+ // To get inventory with remaining qty
115
106
  if (remainOnly) {
116
- qb.andWhere('iv.qty > 0')
117
- .andWhere('CASE WHEN iv.lockedQty IS NULL THEN 0 ELSE iv.lockedQty END >= 0')
118
- .andWhere('iv.qty - CASE WHEN iv.lockedQty IS NULL THEN 0 ELSE iv.lockedQty END > 0')
119
- }
120
-
121
- if (unlockOnly) {
122
- qb.andWhere('CASE WHEN iv.lockedQty IS NULL THEN 0 ELSE iv.lockedQty END = 0')
107
+ qb.andWhere('inventory.qty > 0')
108
+ .andWhere('CASE WHEN inventory.lockedQty IS NULL THEN 0 ELSE inventory.lockedQty END >= 0')
109
+ .andWhere('inventory.qty - CASE WHEN inventory.lockedQty IS NULL THEN 0 ELSE inventory.lockedQty END > 0')
123
110
  }
124
111
 
112
+ // Filter based on multiple product parameters and allow to search in csv format
125
113
  if (productFilters) {
126
114
  let productFilterValue = `%${productFilters.value.toLowerCase()}%`
127
115
  qb.andWhere(qb => {
@@ -129,7 +117,7 @@ export class InventoryQuery {
129
117
  .subQuery()
130
118
  .select()
131
119
  .from(Product, `products`)
132
- .where(`products.id = iv.product_id`)
120
+ .where(`products.id = Inventory.product_id`) // @chrislim Does the uppercase I in Inventory affect? I can see the rest are in lowercase i
133
121
  .andWhere(
134
122
  new Brackets(qb => {
135
123
  qb.where('Lower(products.sku) LIKE :productInfo', { productInfo: productFilterValue })
@@ -143,12 +131,13 @@ export class InventoryQuery {
143
131
  })
144
132
  }
145
133
 
134
+ // Apply sorting based on child data
146
135
  if (sortings?.length !== 0) {
147
136
  const arrChildSortData = ['bizplace', 'product', 'location', 'warehouse', 'zone']
148
- const sort = (sortings || []).reduce(
137
+ const sort: OrderByCondition = (sortings || []).reduce(
149
138
  (acc, sort) => ({
150
139
  ...acc,
151
- [arrChildSortData.indexOf(sort.name) >= 0 ? sort.name + '.name' : 'iv.' + sort.name]: sort.desc
140
+ [arrChildSortData.indexOf(sort.name) >= 0 ? sort.name + '.name' : 'inventory.' + sort.name]: sort.desc
152
141
  ? 'DESC'
153
142
  : 'ASC'
154
143
  }),
@@ -158,53 +147,38 @@ export class InventoryQuery {
158
147
  }
159
148
 
160
149
  if (locationSortingRules?.length > 0) {
161
- locationSortingRules.forEach((rule: { name: string; desc: boolean }) => {
150
+ locationSortingRules.forEach(rule => {
162
151
  qb.addOrderBy(`location.${rule.name}`, rule.desc ? 'DESC' : 'ASC')
163
152
  })
164
153
  }
165
154
 
166
- let [items, total] = await qb.getManyAndCount()
167
- items = await Promise.all(
168
- items.map(async (item: Inventory) => {
169
- let [productDetails, inventoryItems] = await Promise.all([
170
- getRepository(ProductDetail).find({
171
- where: {
172
- product: item.product.id,
173
- packingType: item.packingType,
174
- packingSize: item.packingSize
175
- }
176
- }),
177
- tx.query(
178
- `
179
- SELECT string_agg(ii.serial_number, ', ') AS "serialNumbers"
180
- FROM inventory_items ii
181
- WHERE ii.inventory_id = $1
182
- GROUP BY ii.inventory_id
183
- `,
184
- [item.id]
185
- )
186
- ])
155
+ // Fetch all row for exporting
156
+ if (exportItem != true && page && limit) {
157
+ qb.offset((page - 1) * limit).limit(limit)
158
+ }
187
159
 
188
- item.product['productDetails'] = productDetails
189
- return {
190
- ...item,
191
- remainQty: item.qty - (item.lockedQty ? item.lockedQty : 0),
192
- remainUomValue: item.uomValue - (item.lockedUomValue ? item.lockedUomValue : 0),
193
- serialNumbers: inventoryItems[0]?.serialNumbers
194
- }
195
- })
196
- )
160
+ let items = (await qb.getRawMany()).map(item => {
161
+ return {
162
+ ...new Inventory(item),
163
+ serialNumbers: item.serial_numbers
164
+ }
165
+ })
166
+ let total = await qb.getCount()
197
167
 
198
- return { items, total }
168
+ return {
169
+ items,
170
+ total
171
+ }
199
172
  } catch (error) {
173
+ logger.error(`inventory-query[inventories]: ${error}`)
200
174
  throw error
201
175
  }
202
176
  }
203
177
 
204
178
  @Directive('@privilege(category: "inventory", privilege: "query")')
205
179
  @Query(returns => Inventory)
206
- async inventory(@Arg('palletId') palletId: string, @Ctx() context: any): Promise<Inventory> {
207
- const { domain }: { domain: Domain } = context.state
180
+ async inventory(@Arg('palletId') palletId: string, @Ctx() context: ResolverContext): Promise<Inventory> {
181
+ const { domain } = context.state
208
182
 
209
183
  return await getRepository(Inventory).findOne({
210
184
  where: { domain: domain, palletId },
@@ -214,11 +188,11 @@ export class InventoryQuery {
214
188
 
215
189
  @Directive('@privilege(category: "inventory", privilege: "query")')
216
190
  @Query(returns => Inventory)
217
- async inventoryByPallet(@Arg('palletId') palletId: string, @Ctx() context: any): Promise<Inventory> {
218
- const { domain }: { domain: Domain } = context.state
191
+ async inventoryByPallet(@Arg('palletId') palletId: string, @Ctx() context: ResolverContext): Promise<Inventory> {
192
+ const { domain } = context.state
219
193
 
220
194
  return await getRepository(Inventory).findOne({
221
- where: { domain, palletId, status: Not(Equal(INVENTORY_STATUS.TERMINATED)) },
195
+ where: { domain: { id: domain.id }, palletId, status: Not(Equal(INVENTORY_STATUS.TERMINATED)) },
222
196
  relations: ['domain', 'bizplace', 'product', 'location', 'warehouse', 'creator', 'updater']
223
197
  })
224
198
  }
@@ -226,9 +200,9 @@ export class InventoryQuery {
226
200
  @Directive('@privilege(category: "inventory", privilege: "query")')
227
201
  @Directive('@transaction')
228
202
  @Query(returns => InventoryList)
229
- async inventoriesByProduct(@Args() params: ListParam, @Ctx() context: any): Promise<InventoryList> {
203
+ async inventoriesByProduct(@Args() params: ListParam, @Ctx() context: ResolverContext): Promise<InventoryList> {
230
204
  try {
231
- const { domain, user, tx }: { domain: Domain; user: User; tx: EntityManager } = context.state
205
+ const { domain, user, tx } = context.state
232
206
  let permittedBizplaceIds: string[] = await getPermittedBizplaceIds(domain, user)
233
207
  const partnersCompanyBizplaces: Bizplace[] = await getPartnersCompanyBizplaces(domain, user)
234
208
 
@@ -237,10 +211,13 @@ export class InventoryQuery {
237
211
 
238
212
  let bizplaceFilter = params.filters.find(filter => filter.name == 'bizplace')
239
213
  let productFilter = params.filters.find(filter => filter.name == 'product')
240
- let productTypeFilter = params.filters.find(filter => filter.name == 'type')
214
+ let packingTypeFilter = params.filters.find(filter => filter.name == 'packingType')
241
215
  let availableStockFilter = params.filters.find(filter => filter.name == 'availableStock')
242
216
  let lowStockFilter = params.filters.find(filter => filter.name == 'lowStock')
243
217
  let overStockFilter = params.filters.find(filter => filter.name == 'overStock')
218
+ let quarantineStockFilter = params.filters.find(filter => filter.name == 'quarantineStock')
219
+ let reserveStockFilter = params.filters.find(filter => filter.name == 'reserveStock')
220
+ let productTypeFilter = params.filters.find(filter => filter.name == 'type')
244
221
 
245
222
  if (bizplaceFilter) {
246
223
  const bizplaceQueryBuilder: SelectQueryBuilder<Bizplace> = getRepository(Bizplace).createQueryBuilder('b')
@@ -304,31 +281,111 @@ export class InventoryQuery {
304
281
  )`
305
282
  }
306
283
 
284
+ let qtyStockQuery = ''
285
+
307
286
  let availableStockQuery = ''
287
+
288
+ if (reserveStockFilter?.value) {
289
+ qtyStockQuery += `\nAND SUM("reserveQty") > 0`
290
+ }
291
+
292
+ if (quarantineStockFilter?.value) {
293
+ qtyStockQuery += `\nAND SUM("quarantineQty") > 0`
294
+ }
295
+
296
+ if (availableStockFilter?.value) {
297
+ qtyStockQuery += ` AND SUM("availableQty") > 0`
298
+ }
299
+
308
300
  if (availableStockFilter?.value) {
309
301
  availableStockQuery = ` AND SUM("Inventory"."qty") > 0`
310
302
  }
311
303
 
312
- let thresholdQuery = ''
313
- if (lowStockFilter?.value) {
314
- thresholdQuery = `AND COALESCE("ProductDetailBizplaceSetting"."min_qty", "Product"."min_qty",0) > SUM("Inventory"."qty")`
304
+ if (availableStockFilter?.value && quarantineStockFilter?.value) {
305
+ qtyStockQuery = ''
306
+ qtyStockQuery += `\nAND (SUM("availableQty") > 0 \n OR SUM("quarantineQty") > 0)`
315
307
  }
316
308
 
317
- if (overStockFilter?.value) {
318
- thresholdQuery = `AND COALESCE("ProductDetailBizplaceSetting"."max_qty", "Product"."max_qty",0) > 0 AND
319
- COALESCE("ProductDetailBizplaceSetting"."max_qty", "Product"."max_qty",0) < SUM("Inventory"."qty")`
309
+ if (availableStockFilter?.value && reserveStockFilter?.value) {
310
+ qtyStockQuery = ''
311
+ qtyStockQuery += `\nAND (SUM("availableQty") > 0 \n OR SUM("reserveQty") > 0)`
312
+ }
313
+
314
+ if (quarantineStockFilter?.value && reserveStockFilter?.value) {
315
+ qtyStockQuery = ''
316
+ qtyStockQuery += `\nAND (SUM("quarantineQty") > 0 \n OR SUM("reserveQty") > 0)`
317
+ }
318
+
319
+ let inventoryQuery = ''
320
+ if (packingTypeFilter) {
321
+ let packingTypeValue = packingTypeFilter.value
322
+ .toLowerCase()
323
+ .split(',')
324
+ .map(prod => {
325
+ return "'%" + prod.trim().replace(/'/g, "''") + "%'"
326
+ })
327
+ .join(',')
328
+
329
+ inventoryQuery =
330
+ inventoryQuery +
331
+ ` AND (
332
+ Lower("Inventory"."packing_type") LIKE ANY(ARRAY[${packingTypeValue}])
333
+ )`
334
+ }
335
+
336
+ let thresholdQuery = ''
337
+ if (lowStockFilter?.value && overStockFilter?.value) {
338
+ throw new Error('invalid filter combination')
339
+ } else if (lowStockFilter?.value && !overStockFilter?.value) {
340
+ thresholdQuery = `AND SUM(COALESCE("minQty", 0)) > SUM("availableQty")`
341
+ } else if (!lowStockFilter?.value && overStockFilter?.value) {
342
+ thresholdQuery = `AND SUM(COALESCE("maxQty", 0)) > 0 AND SUM(COALESCE("maxQty", 0)) < SUM("availableQty")`
320
343
  }
321
344
 
345
+ await tx.query(
346
+ `
347
+ CREATE TEMP TABLE order_inventories_by_products AS (
348
+ SELECT "product_id", "packing_type", sum("release_qty") AS "total_release_qty" FROM order_inventories oi
349
+ WHERE "type" = 'RELEASE_OF_GOODS'
350
+ AND "domain_id" = $1
351
+ AND "inventory_id" ISNULL
352
+ AND "status" IN ('PENDING','PENDING_RECEIVE','PENDING_WORKSHEET','READY_TO_PICK'/*, 'PENDING_SPLIT' kiv sebab kalau pending split, ada yang dah assign tapi belum delete*/)
353
+ GROUP BY "product_id", "packing_type"
354
+ )`,
355
+ [domain.id]
356
+ )
357
+
322
358
  await tx.query(
323
359
  `
324
360
  create temp table temp_inv_history AS
325
361
  (
326
362
  SELECT "Product"."id" AS "id", "Product"."sku" AS "sku", "Product"."brand" AS "brand", "Product"."name" AS "name", "Product"."type" AS "type", "Product"."description" AS "description",
363
+ "Inventory"."packing_type" AS "packingType",
327
364
  "Product"."weight" AS "weight", "ProductRef"."id" AS "productRefId",
328
365
  "ProductRef"."description" AS "productRefDesciption", "Bizplace"."id" AS "bizplaceId", "Bizplace"."name" AS "bizplaceName", SUM("Inventory"."qty") AS "qty" ,
329
366
  CASE WHEN SUM("Inventory"."qty") > 0 THEN SUM(COALESCE("Inventory"."unit_cost", 0) * "Inventory"."qty")/ SUM("Inventory"."qty") ELSE 0 END AS "averageUnitCost",
330
367
  COALESCE("ProductDetailBizplaceSetting"."min_qty", "Product"."min_qty",0) AS "minQty",
331
- COALESCE("ProductDetailBizplaceSetting"."max_qty", "Product"."max_qty",0) AS "maxQty"
368
+ COALESCE("ProductDetailBizplaceSetting"."max_qty", "Product"."max_qty",0) AS "maxQty",
369
+ CASE WHEN "Location"."type" NOT IN ('${LOCATION_TYPE.QUARANTINE}','${LOCATION_TYPE.RESERVE}')
370
+ THEN
371
+ CASE WHEN SUM("Inventory"."qty") > 0
372
+ THEN SUM("Inventory"."qty")-SUM(COALESCE("Inventory"."locked_qty", 0) + COALESCE("OrderInventoriesByProduct"."total_release_qty", 0))
373
+ ELSE 0 END
374
+ ELSE 0 END AS "availableQty",
375
+ SUM(COALESCE("Inventory"."locked_qty", 0) + COALESCE("OrderInventoriesByProduct"."total_release_qty", 0)) AS "releaseQty",
376
+ CASE WHEN "Location"."type" = '${LOCATION_TYPE.QUARANTINE}'
377
+ THEN
378
+ CASE WHEN SUM("Inventory"."qty") > 0
379
+ THEN SUM("Inventory"."qty")-SUM(COALESCE("Inventory"."locked_qty", 0) + COALESCE("OrderInventoriesByProduct"."total_release_qty", 0))
380
+ ELSE 0 END
381
+ ELSE 0 END AS "quarantineQty",
382
+ CASE WHEN "Location"."type" = '${LOCATION_TYPE.RESERVE}'
383
+ THEN
384
+ CASE WHEN SUM("Inventory"."qty") > 0
385
+ THEN SUM("Inventory"."qty")-SUM(COALESCE("Inventory"."locked_qty", 0) + COALESCE("OrderInventoriesByProduct"."total_release_qty", 0))
386
+ ELSE 0 END
387
+ ELSE 0 END AS "reserveQty",
388
+ CASE WHEN "Location"."type" = '${LOCATION_TYPE.BIN}' THEN SUM("Inventory"."qty") ELSE 0 END AS "binQty"
332
389
  FROM "inventories" "Inventory"
333
390
  LEFT JOIN "products" "Product" ON "Product"."id"="Inventory"."product_id"
334
391
  LEFT JOIN "product_details" "ProductDetails" ON "ProductDetails"."product_id" = "Product"."id"
@@ -337,31 +394,53 @@ export class InventoryQuery {
337
394
  AND "ProductDetailBizplaceSetting"."domain_id" = "Inventory"."domain_id"
338
395
  LEFT JOIN "products" "ProductRef" ON "ProductRef"."id"="Product"."product_ref_id"
339
396
  INNER JOIN "bizplaces" "Bizplace" ON "Bizplace"."id"="Inventory"."bizplace_id"
397
+ INNER JOIN "locations" "Location" ON "Location"."id" = "Inventory"."location_id"
398
+ LEFT JOIN "order_inventories_by_products" "OrderInventoriesByProduct"
399
+ ON "OrderInventoriesByProduct"."product_id" = "Inventory"."product_id"
400
+ AND "OrderInventoriesByProduct"."packing_type" = "Inventory"."packing_type"
340
401
  WHERE "Inventory"."qty" >= 0
341
402
  AND "Inventory"."status" <> 'MISSING'
342
403
  AND "Inventory"."domain_id" = $1
343
404
  ${bizplaceQuery}
344
405
  ${productQuery}
345
- GROUP BY "Product"."id", "ProductRef"."id", "Bizplace"."id", "ProductDetailBizplaceSetting"."id"
406
+ GROUP BY "Product"."id", "Bizplace"."id", "ProductDetailBizplaceSetting"."id", "Inventory"."packing_type", "Location"."type", "ProductRef"."id"
346
407
  HAVING 1 = 1
347
408
  ${availableStockQuery}
348
- ${thresholdQuery}
349
409
  )`,
350
410
  [domain.id]
351
411
  )
352
412
 
413
+ await tx.query(
414
+ `
415
+ CREATE TEMP TABLE grouped_inventories_product AS (
416
+ SELECT "id", "sku", "brand", "name", "description",
417
+ "packingType", "bizplaceId", "bizplaceName", sum("averageUnitCost") AS "averageUnitCost",
418
+ sum("minQty") AS "minQty", sum("maxQty") AS "maxQty",
419
+ sum("availableQty") AS "availableQty",
420
+ sum("quarantineQty") AS "quarantineQty",
421
+ sum("reserveQty") AS "reserveQty",
422
+ sum("releaseQty") AS "releaseQty",
423
+ sum("availableQty" + "quarantineQty" + "releaseQty" + "reserveQty" - "binQty") AS "warehouseQty"
424
+ FROM temp_inv_history
425
+ GROUP BY "id", "sku", "brand", "name", "description", "packingType", "bizplaceId", "bizplaceName"
426
+ HAVING 1=1
427
+ ${qtyStockQuery}
428
+ ${thresholdQuery}
429
+ )
430
+ `
431
+ )
353
432
  const results: any = await tx.query(
354
433
  `
355
- SELECT * FROM temp_inv_history
356
- ORDER BY "bizplaceName", "sku"
434
+ SELECT * FROM grouped_inventories_product
435
+ ORDER BY "bizplaceName", "sku"
357
436
  OFFSET $1 LIMIT $2
358
437
  `,
359
438
  [(page - 1) * limit, limit]
360
439
  )
361
440
 
362
- const total: any = await tx.query(`SELECT COUNT(*) FROM temp_inv_history`)
441
+ const total: any = await tx.query(`SELECT COUNT(*) FROM grouped_inventories_product`)
363
442
 
364
- tx.query(`drop table temp_inv_history`)
443
+ await tx.query(`drop table temp_inv_history, order_inventories_by_products, grouped_inventories_product`)
365
444
 
366
445
  return {
367
446
  items: results.map((item: any) => {
@@ -372,15 +451,20 @@ export class InventoryQuery {
372
451
  sku: item.sku,
373
452
  brand: item.brand,
374
453
  description: item.description,
375
- type: item.type,
376
- weight: item.weight,
377
- productRefId: item.productRefId,
378
- bizplaceId: item.bizplaceId,
379
454
  minQty: item.minQty,
380
455
  maxQty: item.maxQty
381
456
  },
457
+ bizplace: {
458
+ id: item.bizplaceId,
459
+ name: item.bizplaceName
460
+ },
461
+ packingType: item.packingType,
382
462
  averageUnitCost: item.averageUnitCost,
383
- qty: item.qty
463
+ availableQty: item.availableQty,
464
+ releaseQty: item.releaseQty,
465
+ quarantineQty: item.quarantineQty,
466
+ reserveQty: item.reserveQty,
467
+ warehouseQty: item.warehouseQty
384
468
  }
385
469
  }),
386
470
  total: total[0].count
@@ -393,7 +477,7 @@ export class InventoryQuery {
393
477
  @Directive('@transaction')
394
478
  @Query(returns => InventoryList)
395
479
  async inventoriesByStrategy(
396
- @Ctx() context: any,
480
+ @Ctx() context: ResolverContext,
397
481
  @Arg('worksheetId') worksheetId: string,
398
482
  @Arg('batchId') batchId: string,
399
483
  @Arg('productName') productName: string,
@@ -405,10 +489,10 @@ export class InventoryQuery {
405
489
  @Arg('locationSortingRules', type => [Sorting], { nullable: true }) locationSortingRules?: Sorting[],
406
490
  @Arg('bizplaceId', { nullable: true }) bizplaceId?: string
407
491
  ): Promise<InventoryList> {
408
- const { domain, tx }: { domain: Domain; tx: EntityManager } = context.state
492
+ const { domain, tx } = context.state
409
493
 
410
494
  const inventoryAssignmentSetting: Setting = await tx.getRepository(Setting).findOne({
411
- where: { domain, name: 'rule-for-inventory-assignment' }
495
+ where: { domain: { id: domain.id }, name: 'rule-for-inventory-assignment' }
412
496
  })
413
497
 
414
498
  if (!locationSortingRules && inventoryAssignmentSetting) {
@@ -441,17 +525,17 @@ export class InventoryQuery {
441
525
  async checkProductIdenticality(
442
526
  @Arg('palletA') palletA: string,
443
527
  @Arg('palletB') palletB: string,
444
- @Ctx() context: any
528
+ @Ctx() context: ResolverContext
445
529
  ): Promise<Boolean> {
446
- const { tx }: { tx: EntityManager } = context.state
530
+ const { tx } = context.state
447
531
  const invRepo: Repository<Inventory> = tx.getRepository(Inventory)
448
532
  const invA: Inventory = await invRepo.findOne({
449
- where: { domain: context.state.domain, palletId: palletA, status: INVENTORY_STATUS.STORED },
533
+ where: { domain: { id: context.state.domain.id }, palletId: palletA, status: INVENTORY_STATUS.STORED },
450
534
  relations: ['product']
451
535
  })
452
536
 
453
537
  const invB: Inventory = await invRepo.findOne({
454
- where: { domain: context.state.domain, palletId: palletB, status: INVENTORY_STATUS.STORED },
538
+ where: { domain: { id: context.state.domain.id }, palletId: palletB, status: INVENTORY_STATUS.STORED },
455
539
  relations: ['product']
456
540
  })
457
541
 
@@ -467,11 +551,16 @@ export class InventoryQuery {
467
551
  @Arg('cartonA') cartonA: string,
468
552
  @Arg('palletA') palletA: string,
469
553
  @Arg('cartonB') cartonB: string,
470
- @Ctx() context: any
554
+ @Ctx() context: ResolverContext
471
555
  ) {
472
556
  const invRepo: Repository<Inventory> = getRepository(Inventory)
473
557
  const invA: Inventory = await invRepo.findOne({
474
- where: { domain: context.state.domain, palletId: palletA, cartonId: cartonA, status: INVENTORY_STATUS.STORED },
558
+ where: {
559
+ domain: { id: context.state.domain.id },
560
+ palletId: palletA,
561
+ cartonId: cartonA,
562
+ status: INVENTORY_STATUS.STORED
563
+ },
475
564
  relations: ['product']
476
565
  })
477
566
 
@@ -499,13 +588,13 @@ export class InventoryQuery {
499
588
  async checkInventoryOwner(
500
589
  @Arg('palletId') palletId: string,
501
590
  @Arg('bizplaceName') bizplaceName: string,
502
- @Ctx() context: any
591
+ @Ctx() context: ResolverContext
503
592
  ): Promise<Boolean> {
504
593
  const invRepo: Repository<Inventory> = getRepository(Inventory)
505
594
  const bizRepo: Repository<Bizplace> = getRepository(Bizplace)
506
595
 
507
596
  const inventory: Inventory = await invRepo.findOne({
508
- where: { domain: context.state.domain, palletId, status: INVENTORY_STATUS.STORED },
597
+ where: { domain: { id: context.state.domain.id }, palletId, status: INVENTORY_STATUS.STORED },
509
598
  relations: ['bizplace']
510
599
  })
511
600
 
@@ -523,12 +612,12 @@ export class InventoryQuery {
523
612
  @Directive('@privilege(category: "inventory", privilege: "query")')
524
613
  @Query(returns => InventoryBundleGroupDetail)
525
614
  async inventoriesByBundle(
526
- @Ctx() context: any,
615
+ @Ctx() context: ResolverContext,
527
616
  @Arg('filters', type => [Filter], { nullable: true }) filters?: Filter[],
528
617
  @Arg('pagination', type => Pagination, { nullable: true }) pagination?: Pagination,
529
618
  @Arg('sortings', type => [Sorting], { nullable: true }) sortings?: Sorting[]
530
619
  ): Promise<InventoryBundleGroupDetail> {
531
- const { domain, user }: { domain: Domain; user: User } = context.state
620
+ const { domain, user } = context.state
532
621
 
533
622
  const params = { filters, pagination }
534
623
 
@@ -551,7 +640,7 @@ export class InventoryQuery {
551
640
  })
552
641
  }
553
642
 
554
- const remainOnlyParam: { name: string; operator: string; value: boolean } = params?.filters?.find(
643
+ const remainOnlyParam = params?.filters?.find(
555
644
  (f: { name: string; operator: string; value: any }) => f.name === 'remainOnly'
556
645
  )
557
646
 
@@ -563,7 +652,7 @@ export class InventoryQuery {
563
652
  )
564
653
  }
565
654
 
566
- const unlockOnlyParam: { name: string; operator: string; value: boolean } = params?.filters?.find(
655
+ const unlockOnlyParam = params?.filters?.find(
567
656
  (f: { name: string; operator: string; value: any }) => f.name === 'unlockOnly'
568
657
  )
569
658
 
@@ -687,151 +776,12 @@ export class InventoryQuery {
687
776
  return { bundleGroup, bundleSetting }
688
777
  }
689
778
 
690
- @Directive('@privilege(category: "inventory", privilege: "query")')
691
- @Query(returns => InventoryList)
692
- async inventoriesForExport(
693
- @Ctx() context: any,
694
- @Arg('filters', type => [Filter], { nullable: true }) filters?: Filter[],
695
- @Arg('pagination', type => Pagination, { nullable: true }) pagination?: Pagination,
696
- @Arg('sortings', type => [Sorting], { nullable: true }) sortings?: Sorting[],
697
- @Arg('locationSortingRules', type => [Sorting], { nullable: true }) locationSortingRules?: Sorting[]
698
- ): Promise<InventoryList> {
699
- const { domain, user } = context.state
700
- const { page, limit } = pagination
701
-
702
- try {
703
- const productFilters = filters.find(x => x.name == 'product_info')
704
- filters = filters.filter(x => x.name != 'product_info')
705
- const params = { filters, pagination }
706
-
707
- if (!params.filters.find((filter: any) => filter.name === 'bizplace')) {
708
- throw new Error('Please select a customer for export.')
709
- }
710
-
711
- const remainOnlyParam: { name: string; operator: string; value: boolean } = params?.filters?.find(
712
- (f: { name: string; operator: string; value: any }) => f.name === 'remainOnly'
713
- )
714
-
715
- let remainOnly: boolean = false
716
- if (typeof remainOnlyParam?.value !== 'undefined') {
717
- remainOnly = remainOnlyParam.value
718
- params.filters = params.filters.filter(
719
- (f: { name: string; operator: string; value: any }) => f.name !== 'remainOnly'
720
- )
721
- }
722
-
723
- const unlockOnlyParam: { name: string; operator: string; value: boolean } = params?.filters?.find(
724
- (f: { name: string; operator: string; value: any }) => f.name === 'unlockOnly'
725
- )
726
-
727
- let unlockOnly: boolean = false
728
- if (typeof unlockOnlyParam?.value !== 'undefined') {
729
- unlockOnly = unlockOnlyParam.value
730
- params.filters = params.filters.filter(
731
- (f: { name: string; operator: string; value: any }) => f.name !== 'unlockOnly'
732
- )
733
- }
734
-
735
- const qb: SelectQueryBuilder<Inventory> = getRepository(Inventory).createQueryBuilder('Inventory')
736
- buildQuery(qb, params, context)
737
-
738
- qb.leftJoinAndSelect('Inventory.bizplace', 'Bizplace')
739
- .leftJoinAndSelect('Inventory.product', 'Product')
740
- .leftJoinAndSelect('Inventory.warehouse', 'Warehouse')
741
- .leftJoinAndSelect('Inventory.location', 'Location')
742
- .leftJoinAndSelect('Inventory.creator', 'Creator')
743
- .leftJoinAndSelect('Inventory.updater', 'Updater')
744
- .leftJoinAndSelect(
745
- subQuery => {
746
- return subQuery
747
- .select('ii.inventory_id', 'inventory_id')
748
- .addSelect(`string_agg(ii.serial_number, ', ')`, 'serial_numbers')
749
- .from('inventory_items', 'ii')
750
- .where(`ii.domain_id = :domainId`, { domainId: domain.id })
751
- .groupBy('ii.inventory_id')
752
- },
753
- 'ii2',
754
- 'ii2.inventory_id = Inventory.id'
755
- )
756
-
757
- if (remainOnly) {
758
- qb.andWhere('Inventory.qty > 0')
759
- .andWhere('CASE WHEN Inventory.locked_qty IS NULL THEN 0 ELSE Inventory.locked_qty END >= 0')
760
- .andWhere('Inventory.qty - CASE WHEN Inventory.locked_qty IS NULL THEN 0 ELSE Inventory.locked_qty END > 0')
761
- }
762
-
763
- if (unlockOnly) {
764
- qb.andWhere('CASE WHEN Inventory.locked_qty IS NULL THEN 0 ELSE Inventory.locked_qty END = 0')
765
- }
766
-
767
- if (productFilters) {
768
- let productFilterValue = `%${productFilters.value.toLowerCase()}%`
769
- qb.andWhere(qb => {
770
- const subQuery = qb
771
- .subQuery()
772
- .select()
773
- .from(Product, `products`)
774
- .where(`products.id = Inventory.product_id`)
775
- .andWhere(
776
- new Brackets(qb => {
777
- qb.where('Lower(products.sku) LIKE :productInfo', { productInfo: productFilterValue })
778
- .orWhere('Lower(products.name) LIKE :productInfo', { productInfo: productFilterValue })
779
- .orWhere('Lower(products.description) LIKE :productInfo', { productInfo: productFilterValue })
780
- .orWhere('Lower(products.brand) LIKE :productInfo', { productInfo: productFilterValue })
781
- })
782
- )
783
- .getQuery()
784
- return `EXISTS ${subQuery}`
785
- })
786
- }
787
-
788
- if (sortings?.length !== 0) {
789
- const arrChildSortData = ['bizplace', 'product', 'location', 'warehouse', 'zone']
790
- const sort = (sortings || []).reduce(
791
- (acc, sort) => ({
792
- ...acc,
793
- [arrChildSortData.indexOf(sort.name) >= 0 ? sort.name + '.name' : 'Inventory.' + sort.name]: sort.desc
794
- ? 'DESC'
795
- : 'ASC'
796
- }),
797
- {}
798
- )
799
- qb.orderBy(sort)
800
- }
801
-
802
- if (locationSortingRules?.length > 0) {
803
- locationSortingRules.forEach((rule: { name: string; desc: boolean }) => {
804
- qb.addOrderBy(`location.${rule.name}`, rule.desc ? 'DESC' : 'ASC')
805
- })
806
- }
807
-
808
- let items = await qb
809
- .offset((page - 1) * limit)
810
- .limit(limit)
811
- .getRawMany()
812
-
813
- let total = await qb.getCount()
814
-
815
- return {
816
- items: items.map(item => {
817
- return {
818
- ...new Inventory(item),
819
- serialNumbers: item.serial_numbers
820
- }
821
- }),
822
- total
823
- }
824
- } catch (error) {
825
- throw error
826
- }
827
- }
828
-
829
779
  @Directive('@privilege(category: "inventory", privilege: "query")')
830
780
  @Directive('@transaction')
831
781
  @Query(returns => InventoryList)
832
- async inventoriesGroupByProduct(@Args() params: ListParam, @Ctx() context: any): Promise<InventoryList> {
782
+ async inventoriesGroupByProduct(@Args() params: ListParam, @Ctx() context: ResolverContext): Promise<InventoryList> {
833
783
  try {
834
- const { domain, user, tx }: { domain: Domain; user: User; tx: EntityManager } = context.state
784
+ const { domain, user, tx } = context.state
835
785
  let permittedBizplaceIds: string[] = await getPermittedBizplaceIds(domain, user)
836
786
  const partnersCompanyBizplaces: Bizplace[] = await getPartnersCompanyBizplaces(domain, user)
837
787
 
@@ -1002,17 +952,17 @@ export class InventoryQuery {
1002
952
 
1003
953
  @FieldResolver(type => Domain)
1004
954
  async domain(@Root() inventory: Inventory): Promise<Domain> {
1005
- return await getRepository(Domain).findOne(inventory.domainId)
955
+ return await getRepository(Domain).findOneBy({ id: inventory.domainId })
1006
956
  }
1007
957
 
1008
958
  @FieldResolver(type => User)
1009
959
  async updater(@Root() inventory: Inventory): Promise<User> {
1010
- return await getRepository(User).findOne(inventory.updaterId)
960
+ return await getRepository(User).findOneBy({ id: inventory.updaterId })
1011
961
  }
1012
962
 
1013
963
  @FieldResolver(type => User)
1014
964
  async creator(@Root() inventory: Inventory): Promise<User> {
1015
- return await getRepository(User).findOne(inventory.creatorId)
965
+ return await getRepository(User).findOneBy({ id: inventory.creatorId })
1016
966
  }
1017
967
 
1018
968
  /*
@@ -1022,7 +972,7 @@ export class InventoryQuery {
1022
972
  @FieldResolver(type => Number)
1023
973
  async changeCount(@Root() inventory: Inventory): Promise<Number> {
1024
974
  return await getRepository(InventoryChange).count({
1025
- where: { inventory }
975
+ where: { inventory: { id: inventory.id } }
1026
976
  })
1027
977
  }
1028
978
 
@@ -1071,6 +1021,19 @@ export class InventoryQuery {
1071
1021
 
1072
1022
  return items[0]?.arrivalNoticeRefNo || ''
1073
1023
  }
1024
+
1025
+ @FieldResolver(type => String)
1026
+ async arrivalNoticeNo(@Root() inventory: Inventory): Promise<String> {
1027
+ if (!inventory.refOrderId) return ''
1028
+
1029
+ let items: any = await getRepository(Inventory).query(`
1030
+ SELECT an.name as "arrivalNoticeNo" FROM arrival_notices an
1031
+ WHERE an.id = '${inventory.refOrderId}'
1032
+ LIMIT 1
1033
+ `)
1034
+
1035
+ return items[0]?.arrivalNoticeNo || ''
1036
+ }
1074
1037
  }
1075
1038
 
1076
1039
  export async function inventoriesByStrategy(
@@ -1153,6 +1116,7 @@ export async function inventoriesByStrategy(
1153
1116
 
1154
1117
  case 'FEFO':
1155
1118
  qb.orderBy('"INV"."expiration_date"', 'ASC')
1119
+ qb.addOrderBy('"INV"."created_at"', 'ASC')
1156
1120
  if (locationSortingRules?.length > 0) {
1157
1121
  locationSortingRules.forEach((rule: { name: string; desc: boolean }, idx: number) => {
1158
1122
  qb.addOrderBy(`LOC.${rule.name}`, rule.desc ? 'DESC' : 'ASC')
@@ -1162,6 +1126,7 @@ export async function inventoriesByStrategy(
1162
1126
 
1163
1127
  case 'FMFO':
1164
1128
  qb.orderBy('"INV"."manufacture_date"', 'ASC')
1129
+ qb.addOrderBy('"INV"."created_at"', 'ASC')
1165
1130
  if (locationSortingRules?.length > 0) {
1166
1131
  locationSortingRules.forEach((rule: { name: string; desc: boolean }, idx: number) => {
1167
1132
  qb.addOrderBy(`LOC.${rule.name}`, rule.desc ? 'DESC' : 'ASC')