@things-factory/warehouse-base 4.1.31 → 4.1.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-server/constants/inventory.js +8 -2
- package/dist-server/constants/inventory.js.map +1 -1
- package/dist-server/service/index.js +5 -0
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/service/inventory/inventory-query.js +100 -1
- package/dist-server/service/inventory/inventory-query.js.map +1 -1
- package/dist-server/service/inventory/inventory.js +10 -0
- package/dist-server/service/inventory/inventory.js.map +1 -1
- package/dist-server/service/inventory-item/index.js +9 -0
- package/dist-server/service/inventory-item/index.js.map +1 -0
- package/dist-server/service/inventory-item/inventory-item-mutation.js +207 -0
- package/dist-server/service/inventory-item/inventory-item-mutation.js.map +1 -0
- package/dist-server/service/inventory-item/inventory-item-query.js +150 -0
- package/dist-server/service/inventory-item/inventory-item-query.js.map +1 -0
- package/dist-server/service/inventory-item/inventory-item-type.js +115 -0
- package/dist-server/service/inventory-item/inventory-item-type.js.map +1 -0
- package/dist-server/service/inventory-item/inventory-item.js +124 -0
- package/dist-server/service/inventory-item/inventory-item.js.map +1 -0
- package/dist-server/service/inventory-product/index.js +9 -0
- package/dist-server/service/inventory-product/index.js.map +1 -0
- package/dist-server/service/inventory-product/inventory-product-mutation.js +120 -0
- package/dist-server/service/inventory-product/inventory-product-mutation.js.map +1 -0
- package/dist-server/service/inventory-product/inventory-product-query.js +87 -0
- package/dist-server/service/inventory-product/inventory-product-query.js.map +1 -0
- package/dist-server/service/inventory-product/inventory-product-type.js +95 -0
- package/dist-server/service/inventory-product/inventory-product-type.js.map +1 -0
- package/dist-server/service/inventory-product/inventory-product.js +107 -0
- package/dist-server/service/inventory-product/inventory-product.js.map +1 -0
- package/dist-server/utils/inventory-no-generator.js +3 -0
- package/dist-server/utils/inventory-no-generator.js.map +1 -1
- package/package.json +5 -5
- package/server/constants/inventory.ts +8 -1
- package/server/service/index.ts +5 -0
- package/server/service/inventory/inventory-query.ts +114 -0
- package/server/service/inventory/inventory.ts +8 -0
- package/server/service/inventory-item/index.ts +6 -0
- package/server/service/inventory-item/inventory-item-mutation.ts +210 -0
- package/server/service/inventory-item/inventory-item-query.ts +118 -0
- package/server/service/inventory-item/inventory-item-type.ts +74 -0
- package/server/service/inventory-item/inventory-item.ts +99 -0
- package/server/service/inventory-product/index.ts +6 -0
- package/server/service/inventory-product/inventory-product-mutation.ts +112 -0
- package/server/service/inventory-product/inventory-product-query.ts +43 -0
- package/server/service/inventory-product/inventory-product-type.ts +59 -0
- package/server/service/inventory-product/inventory-product.ts +88 -0
- package/server/utils/inventory-no-generator.ts +4 -0
|
@@ -752,6 +752,120 @@ export class InventoryQuery {
|
|
|
752
752
|
}
|
|
753
753
|
}
|
|
754
754
|
|
|
755
|
+
@Directive('@privilege(category: "inventory", privilege: "query")')
|
|
756
|
+
@Query(returns => InventoryList)
|
|
757
|
+
async nonLoadedInventories(
|
|
758
|
+
@Ctx() context: any,
|
|
759
|
+
@Arg('filters', type => [Filter], { nullable: true }) filters?: Filter[],
|
|
760
|
+
@Arg('pagination', type => Pagination, { nullable: true }) pagination?: Pagination,
|
|
761
|
+
@Arg('sortings', type => [Sorting], { nullable: true }) sortings?: Sorting[]
|
|
762
|
+
): Promise<InventoryList> {
|
|
763
|
+
const { domain, user }: { domain: Domain; user: User } = context.state
|
|
764
|
+
const { page, limit }: { page: number; limit: number } = pagination
|
|
765
|
+
|
|
766
|
+
try {
|
|
767
|
+
const productFilter = filters.find(x => x.name == 'product_info')
|
|
768
|
+
const roNoFilter = filters.find(x => x.name == 'ro_no')
|
|
769
|
+
const binLocationFilter = filters.find(x => x.name == 'bin_location')
|
|
770
|
+
|
|
771
|
+
filters = filters.filter(filter => ['product_info', 'ro_no', 'bin_location'].indexOf(filter.name) == -1)
|
|
772
|
+
|
|
773
|
+
const params = { filters, pagination }
|
|
774
|
+
const qb: SelectQueryBuilder<Inventory> = getRepository(Inventory).createQueryBuilder('Inventory')
|
|
775
|
+
buildQuery(qb, params, context)
|
|
776
|
+
|
|
777
|
+
qb.select('Inventory')
|
|
778
|
+
.addSelect('ReleaseGood.name', 'order_no')
|
|
779
|
+
.innerJoin('order_inventories', 'OrderInventory', 'Inventory.id = OrderInventory.inventory_id')
|
|
780
|
+
.innerJoin('OrderInventory.releaseGood', 'ReleaseGood')
|
|
781
|
+
.innerJoinAndSelect('Inventory.product', 'Product')
|
|
782
|
+
.leftJoinAndSelect('OrderInventory.binLocation', 'BinLocation')
|
|
783
|
+
.leftJoinAndSelect('Inventory.creator', 'Creator')
|
|
784
|
+
.leftJoinAndSelect('Inventory.updater', 'Updater')
|
|
785
|
+
.andWhere('ReleaseGood.status IN (:...releaseGoodStatus)', {
|
|
786
|
+
releaseGoodStatus: ['PICKING', 'LOADING']
|
|
787
|
+
})
|
|
788
|
+
.andWhere('OrderInventory.status IN (:...orderInventoryStatus)', {
|
|
789
|
+
orderInventoryStatus: ['PICKED', 'LOADING', 'LOADED']
|
|
790
|
+
})
|
|
791
|
+
|
|
792
|
+
if (productFilter) {
|
|
793
|
+
let productFilterValue = `%${productFilter.value.toLowerCase()}%`
|
|
794
|
+
qb.andWhere(qb => {
|
|
795
|
+
const subQuery = qb
|
|
796
|
+
.subQuery()
|
|
797
|
+
.select()
|
|
798
|
+
.from(Product, `products`)
|
|
799
|
+
.where(`products.id = Inventory.product_id`)
|
|
800
|
+
.andWhere(
|
|
801
|
+
new Brackets(qb => {
|
|
802
|
+
qb.where('Lower(products.sku) LIKE :productInfo', { productInfo: productFilterValue })
|
|
803
|
+
.orWhere('Lower(products.name) LIKE :productInfo', { productInfo: productFilterValue })
|
|
804
|
+
.orWhere('Lower(products.description) LIKE :productInfo', { productInfo: productFilterValue })
|
|
805
|
+
.orWhere('Lower(products.brand) LIKE :productInfo', { productInfo: productFilterValue })
|
|
806
|
+
})
|
|
807
|
+
)
|
|
808
|
+
.getQuery()
|
|
809
|
+
return `EXISTS ${subQuery}`
|
|
810
|
+
})
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
if (roNoFilter) {
|
|
814
|
+
const roNo: string = `%${roNoFilter.value.toLowerCase()}%`
|
|
815
|
+
qb.andWhere('ReleaseGood.name LIKE :roNo', { roNo })
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
if (binLocationFilter) {
|
|
819
|
+
const binLocation: string = `%${binLocationFilter.value.toLowerCase()}%`
|
|
820
|
+
qb.andWhere('BinLocation.name LIKE :binLocation', { binLocation })
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
if (sortings?.length !== 0) {
|
|
824
|
+
const sorter = (sortings || []).reduce((acc, sort) => {
|
|
825
|
+
const order: string = sort.desc ? 'DESC' : 'ASC'
|
|
826
|
+
|
|
827
|
+
switch (sort.name) {
|
|
828
|
+
case 'orderNo':
|
|
829
|
+
acc = { ...acc, ['ReleaseGood.name']: order }
|
|
830
|
+
break
|
|
831
|
+
|
|
832
|
+
case 'product_sku':
|
|
833
|
+
acc = { ...acc, ['Product.sku']: order }
|
|
834
|
+
break
|
|
835
|
+
|
|
836
|
+
case 'product_name':
|
|
837
|
+
acc = { ...acc, ['Product.name']: order }
|
|
838
|
+
break
|
|
839
|
+
|
|
840
|
+
case 'product_brand':
|
|
841
|
+
acc = { ...acc, ['Product.brand']: order }
|
|
842
|
+
|
|
843
|
+
case 'binLocation':
|
|
844
|
+
acc = { ...acc, ['BinLocation.name']: order }
|
|
845
|
+
break
|
|
846
|
+
|
|
847
|
+
default:
|
|
848
|
+
acc = { ...acc, [`Inventory.${sort.name}`]: order }
|
|
849
|
+
break
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
return acc
|
|
853
|
+
}, {})
|
|
854
|
+
qb.orderBy(sorter)
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
let items = await qb
|
|
858
|
+
.offset((page - 1) * limit)
|
|
859
|
+
.limit(limit)
|
|
860
|
+
.getRawMany()
|
|
861
|
+
|
|
862
|
+
let total = await qb.getCount()
|
|
863
|
+
return { items: items.map(item => new Inventory(item)), total }
|
|
864
|
+
} catch (error) {
|
|
865
|
+
throw error
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
|
|
755
869
|
@FieldResolver(type => Domain)
|
|
756
870
|
async domain(@Root() inventory: Inventory): Promise<Domain> {
|
|
757
871
|
return await getRepository(Domain).findOne(inventory.domainId)
|
|
@@ -255,6 +255,12 @@ export class Inventory {
|
|
|
255
255
|
@Field({ nullable: true })
|
|
256
256
|
changeCount?: number
|
|
257
257
|
|
|
258
|
+
@Field({ nullable: true })
|
|
259
|
+
binLocation?: string
|
|
260
|
+
|
|
261
|
+
@Field({ nullable: true })
|
|
262
|
+
orderNo?: string
|
|
263
|
+
|
|
258
264
|
constructor(obj?) {
|
|
259
265
|
if (obj) {
|
|
260
266
|
this.id = obj.Inventory_id
|
|
@@ -297,6 +303,8 @@ export class Inventory {
|
|
|
297
303
|
this.packingSize = obj.Inventory_packing_size
|
|
298
304
|
this.creatorId = obj.Inventory_creator_id
|
|
299
305
|
this.updaterId = obj.Inventory_updater_id
|
|
306
|
+
this.binLocation = obj.BinLocation_name
|
|
307
|
+
this.orderNo = obj.order_no
|
|
300
308
|
}
|
|
301
309
|
}
|
|
302
310
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { InventoryItem } from './inventory-item'
|
|
2
|
+
import { InventoryItemMutation } from './inventory-item-mutation'
|
|
3
|
+
import { InventoryItemQuery } from './inventory-item-query'
|
|
4
|
+
|
|
5
|
+
export const entities = [InventoryItem]
|
|
6
|
+
export const resolvers = [InventoryItemQuery, InventoryItemMutation]
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { Arg, Ctx, Directive, Mutation, Resolver } from 'type-graphql'
|
|
2
|
+
import { In } from 'typeorm'
|
|
3
|
+
|
|
4
|
+
import { Product } from '@things-factory/product-base'
|
|
5
|
+
|
|
6
|
+
import { INVENTORY_STATUS } from '../../constants'
|
|
7
|
+
import { InventoryNoGenerator } from '../../utils'
|
|
8
|
+
import { InventoryItem } from './inventory-item'
|
|
9
|
+
import { InventoryItemPatch, NewInventoryItem } from './inventory-item-type'
|
|
10
|
+
|
|
11
|
+
@Resolver(InventoryItem)
|
|
12
|
+
export class InventoryItemMutation {
|
|
13
|
+
@Directive('@transaction')
|
|
14
|
+
@Mutation(returns => InventoryItem, { description: 'To create new InventoryItem' })
|
|
15
|
+
async createInventoryItem(
|
|
16
|
+
@Arg('inventoryItem') inventoryItem: NewInventoryItem,
|
|
17
|
+
@Ctx() context: any
|
|
18
|
+
): Promise<InventoryItem> {
|
|
19
|
+
const { domain, user, tx } = context.state
|
|
20
|
+
|
|
21
|
+
return await tx.getRepository(InventoryItem).save({
|
|
22
|
+
...inventoryItem,
|
|
23
|
+
domain,
|
|
24
|
+
creator: user,
|
|
25
|
+
updater: user
|
|
26
|
+
})
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@Directive('@transaction')
|
|
30
|
+
@Mutation(returns => InventoryItem, { description: 'To modify InventoryItem information' })
|
|
31
|
+
async updateInventoryItem(
|
|
32
|
+
@Arg('id') id: string,
|
|
33
|
+
@Arg('patch') patch: InventoryItemPatch,
|
|
34
|
+
@Ctx() context: any
|
|
35
|
+
): Promise<InventoryItem> {
|
|
36
|
+
const { domain, user, tx } = context.state
|
|
37
|
+
|
|
38
|
+
const repository = tx.getRepository(InventoryItem)
|
|
39
|
+
const inventoryItem = await repository.findOne({
|
|
40
|
+
where: { domain, id }
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
return await repository.save({
|
|
44
|
+
...inventoryItem,
|
|
45
|
+
...patch,
|
|
46
|
+
updater: user
|
|
47
|
+
})
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@Directive('@transaction')
|
|
51
|
+
@Mutation(returns => Boolean, { description: 'To modify InventoryItem serial number' })
|
|
52
|
+
async updateInventoryItemSerialNumber(
|
|
53
|
+
@Arg('id') id: string,
|
|
54
|
+
@Arg('serialNumber') serialNumber: string,
|
|
55
|
+
@Ctx() context: any
|
|
56
|
+
): Promise<boolean> {
|
|
57
|
+
try {
|
|
58
|
+
const { domain, user, tx } = context.state
|
|
59
|
+
|
|
60
|
+
const repository = tx.getRepository(InventoryItem)
|
|
61
|
+
|
|
62
|
+
const inventoryItem = await repository.findOne({
|
|
63
|
+
where: { domain, id },
|
|
64
|
+
relations: ['product']
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
const product: Product = inventoryItem.product
|
|
68
|
+
const duplicatedSerialNumberCnt: number = await repository.count({
|
|
69
|
+
domain,
|
|
70
|
+
product,
|
|
71
|
+
serialNumber
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
if (duplicatedSerialNumberCnt) throw new Error(`Serial Number ${serialNumber} is duplicated`)
|
|
75
|
+
|
|
76
|
+
await repository.update({ id }, { serialNumber, updater: user })
|
|
77
|
+
|
|
78
|
+
return true
|
|
79
|
+
} catch (error) {
|
|
80
|
+
throw error
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
@Directive('@transaction')
|
|
85
|
+
@Mutation(returns => [InventoryItem], { description: "To modify multiple InventoryItems' information" })
|
|
86
|
+
async updateMultipleInventoryItem(
|
|
87
|
+
@Arg('patches', type => [InventoryItemPatch]) patches: InventoryItemPatch[],
|
|
88
|
+
@Ctx() context: any
|
|
89
|
+
): Promise<InventoryItem[]> {
|
|
90
|
+
const { domain, user, tx } = context.state
|
|
91
|
+
|
|
92
|
+
let results = []
|
|
93
|
+
const _createRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === '+')
|
|
94
|
+
const _updateRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === 'M')
|
|
95
|
+
const inventoryItemRepo = tx.getRepository(InventoryItem)
|
|
96
|
+
|
|
97
|
+
if (_createRecords.length > 0) {
|
|
98
|
+
for (let i = 0; i < _createRecords.length; i++) {
|
|
99
|
+
const newRecord = _createRecords[i]
|
|
100
|
+
|
|
101
|
+
const result = await inventoryItemRepo.save({
|
|
102
|
+
...newRecord,
|
|
103
|
+
domain,
|
|
104
|
+
creator: user,
|
|
105
|
+
updater: user
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
results.push({ ...result, cuFlag: '+' })
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (_updateRecords.length > 0) {
|
|
113
|
+
for (let i = 0; i < _updateRecords.length; i++) {
|
|
114
|
+
const newRecord = _updateRecords[i]
|
|
115
|
+
const inventoryItem = await inventoryItemRepo.findOne(newRecord.id)
|
|
116
|
+
|
|
117
|
+
const result = await inventoryItemRepo.save({
|
|
118
|
+
...inventoryItem,
|
|
119
|
+
...newRecord,
|
|
120
|
+
updater: user
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
results.push({ ...result, cuFlag: 'M' })
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return results
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
@Directive('@transaction')
|
|
131
|
+
@Mutation(returns => Boolean, { description: 'To delete InventoryItem' })
|
|
132
|
+
async deleteInventoryItem(@Arg('id') id: string, @Ctx() context: any): Promise<boolean> {
|
|
133
|
+
const { domain, tx } = context.state
|
|
134
|
+
|
|
135
|
+
await tx.getRepository(InventoryItem).delete({ domain, id })
|
|
136
|
+
|
|
137
|
+
return true
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
@Directive('@transaction')
|
|
141
|
+
@Mutation(returns => Boolean, { description: 'To delete multiple inventoryItems' })
|
|
142
|
+
async deleteInventoryItems(@Arg('ids', type => [String]) ids: string[], @Ctx() context: any): Promise<boolean> {
|
|
143
|
+
const { domain, tx } = context.state
|
|
144
|
+
|
|
145
|
+
await tx.getRepository(InventoryItem).delete({
|
|
146
|
+
domain,
|
|
147
|
+
id: In(ids)
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
return true
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
@Directive('@transaction')
|
|
154
|
+
@Mutation(returns => InventoryItem, { description: 'To update picked InventoryItem with new IventoryItem' })
|
|
155
|
+
async replacePickedInventoryItem(
|
|
156
|
+
@Arg('selectedSerialNumber') selectedSerialNumber: InventoryItemPatch,
|
|
157
|
+
@Arg('newSerialNumber') newSerialNumber: string,
|
|
158
|
+
@Ctx() context: any
|
|
159
|
+
): Promise<InventoryItem> {
|
|
160
|
+
const { domain, user, tx } = context.state
|
|
161
|
+
|
|
162
|
+
const repository = tx.getRepository(InventoryItem)
|
|
163
|
+
const foundSerialNumber = await repository.findOne({
|
|
164
|
+
where: { domain, serialNumber: newSerialNumber }
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
await repository.update(
|
|
168
|
+
{
|
|
169
|
+
domain,
|
|
170
|
+
id: selectedSerialNumber.id
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
status: INVENTORY_STATUS.STORED,
|
|
174
|
+
outboundOrderId: null,
|
|
175
|
+
updater: user
|
|
176
|
+
}
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
if (foundSerialNumber) {
|
|
180
|
+
if (foundSerialNumber.productId !== selectedSerialNumber.product?.id) {
|
|
181
|
+
throw new Error('Invalid Serial Number')
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (foundSerialNumber.inventoryId !== selectedSerialNumber.inventory?.id) {
|
|
185
|
+
throw new Error('Serial Number Registered Under Different Inventory')
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (foundSerialNumber.status !== INVENTORY_STATUS.STORED) {
|
|
189
|
+
throw new Error('Inventory Item is not available')
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
foundSerialNumber.status = INVENTORY_STATUS.PICKED
|
|
193
|
+
foundSerialNumber.updater = user
|
|
194
|
+
foundSerialNumber.outboundOrderId = selectedSerialNumber.outboundOrderId
|
|
195
|
+
|
|
196
|
+
return await repository.save(foundSerialNumber)
|
|
197
|
+
} else {
|
|
198
|
+
let inventoryItem: InventoryItem = new InventoryItem()
|
|
199
|
+
inventoryItem.name = InventoryNoGenerator.inventoryItemName()
|
|
200
|
+
inventoryItem.serialNumber = newSerialNumber
|
|
201
|
+
inventoryItem.status = INVENTORY_STATUS.PICKED
|
|
202
|
+
inventoryItem.outboundOrderId = selectedSerialNumber.outboundOrderId
|
|
203
|
+
inventoryItem.product = selectedSerialNumber.product
|
|
204
|
+
inventoryItem.inventory = selectedSerialNumber.inventory
|
|
205
|
+
inventoryItem.domain = domain
|
|
206
|
+
|
|
207
|
+
return await repository.save(inventoryItem)
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { Arg, Args, Ctx, FieldResolver, Query, Resolver, Root } from 'type-graphql'
|
|
2
|
+
import { Brackets, getRepository, SelectQueryBuilder } from 'typeorm'
|
|
3
|
+
|
|
4
|
+
import { User } from '@things-factory/auth-base'
|
|
5
|
+
import { convertListParams, Domain, ListParam } from '@things-factory/shell'
|
|
6
|
+
|
|
7
|
+
import { INVENTORY_STATUS } from '../../constants'
|
|
8
|
+
import { Inventory } from '../inventory/inventory'
|
|
9
|
+
import { InventoryItem } from './inventory-item'
|
|
10
|
+
import { InventoryItemList } from './inventory-item-type'
|
|
11
|
+
|
|
12
|
+
@Resolver(InventoryItem)
|
|
13
|
+
export class InventoryItemQuery {
|
|
14
|
+
@Query(returns => InventoryItem, { description: 'To fetch a InventoryItem' })
|
|
15
|
+
async inventoryItem(@Arg('id') id: string, @Ctx() context: any): Promise<InventoryItem> {
|
|
16
|
+
const { domain } = context.state
|
|
17
|
+
|
|
18
|
+
return await getRepository(InventoryItem).findOne({
|
|
19
|
+
where: { domain, id }
|
|
20
|
+
})
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@Query(returns => InventoryItemList, { description: 'To fetch multiple InventoryItems' })
|
|
24
|
+
async inventoryItems(@Args() params: ListParam, @Ctx() context: any): Promise<InventoryItemList> {
|
|
25
|
+
const { domain } = context.state
|
|
26
|
+
|
|
27
|
+
const convertedParams = convertListParams(params, domain.id)
|
|
28
|
+
const [items, total] = await getRepository(InventoryItem).findAndCount(convertedParams)
|
|
29
|
+
|
|
30
|
+
return { items, total }
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@Query(returns => InventoryItemList, { description: 'To fetch multiple InventoryItems by inventory' })
|
|
34
|
+
async inventoryItemsByInventory(@Args() params: ListParam, @Ctx() context: any): Promise<InventoryItemList> {
|
|
35
|
+
const { domain } = context.state
|
|
36
|
+
|
|
37
|
+
const page = params.pagination.page
|
|
38
|
+
const limit = params.pagination.limit
|
|
39
|
+
const sortings = params.sortings
|
|
40
|
+
|
|
41
|
+
let inventoryInfoFilter = params.filters.find(filter => filter.name == 'inventory_info')
|
|
42
|
+
let orderTypeFilter = params.filters.find(filter => filter.name == 'orderType')
|
|
43
|
+
let orderIdFilter = params.filters.find(filter => filter.name == 'orderId')
|
|
44
|
+
let productIdFilter = params.filters.find(filter => filter.name == 'productId')
|
|
45
|
+
|
|
46
|
+
let qb: SelectQueryBuilder<InventoryItem> = getRepository(InventoryItem).createQueryBuilder('ivi')
|
|
47
|
+
qb.leftJoinAndSelect('ivi.product', 'product').leftJoinAndSelect('ivi.inventory', 'inventory')
|
|
48
|
+
qb.where('ivi.product_id=:productId', { productId: productIdFilter.value })
|
|
49
|
+
qb.andWhere('inventory.status!=:inventoryStatus', { inventoryStatus: INVENTORY_STATUS.PARTIALLY_UNLOADED })
|
|
50
|
+
|
|
51
|
+
if (orderTypeFilter.value == 'inbound') {
|
|
52
|
+
qb.andWhere('ivi.inbound_order_id=:orderId', { orderId: orderIdFilter.value })
|
|
53
|
+
} else {
|
|
54
|
+
qb.andWhere('ivi.outbound_order_id=:orderId', { orderId: orderIdFilter.value })
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (inventoryInfoFilter) {
|
|
58
|
+
qb.andWhere(qb => {
|
|
59
|
+
const subQuery = qb
|
|
60
|
+
.subQuery()
|
|
61
|
+
.select()
|
|
62
|
+
.from(Inventory, `inventories`)
|
|
63
|
+
.where(`inventories.id = ivi.inventory_id`)
|
|
64
|
+
.andWhere(
|
|
65
|
+
new Brackets(qb => {
|
|
66
|
+
qb.where('Lower(inventories.pallet_id) LIKE :inventoryInfo', {
|
|
67
|
+
inventoryInfo: '%' + inventoryInfoFilter.value.toLowerCase() + '%'
|
|
68
|
+
})
|
|
69
|
+
.orWhere('Lower(inventories.carton_id) LIKE :inventoryInfo', {
|
|
70
|
+
inventoryInfo: '%' + inventoryInfoFilter.value.toLowerCase() + '%'
|
|
71
|
+
})
|
|
72
|
+
.orWhere('Lower(ivi.serial_number) LIKE :inventoryInfo', {
|
|
73
|
+
inventoryInfo: '%' + inventoryInfoFilter.value.toLowerCase() + '%'
|
|
74
|
+
})
|
|
75
|
+
})
|
|
76
|
+
)
|
|
77
|
+
.getQuery()
|
|
78
|
+
return `EXISTS ${subQuery}`
|
|
79
|
+
})
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (sortings?.length !== 0) {
|
|
83
|
+
const arrChildSortData = ['serial_number']
|
|
84
|
+
const sort = (sortings || []).reduce(
|
|
85
|
+
(acc, sort) => ({
|
|
86
|
+
...acc,
|
|
87
|
+
[arrChildSortData.indexOf(sort.name) >= 0 ? sort.name + '.name' : 'ivi.' + sort.name]: sort.desc
|
|
88
|
+
? 'DESC'
|
|
89
|
+
: 'ASC'
|
|
90
|
+
}),
|
|
91
|
+
{}
|
|
92
|
+
)
|
|
93
|
+
qb.orderBy(sort)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
qb.limit(limit)
|
|
97
|
+
qb.offset(limit * (page - 1))
|
|
98
|
+
|
|
99
|
+
let [items, total] = await qb.getManyAndCount()
|
|
100
|
+
|
|
101
|
+
return { items, total }
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
@FieldResolver(type => Domain)
|
|
105
|
+
async domain(@Root() inventoryItem: InventoryItem): Promise<Domain> {
|
|
106
|
+
return await getRepository(Domain).findOne(inventoryItem.domainId)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
@FieldResolver(type => User)
|
|
110
|
+
async updater(@Root() inventoryItem: InventoryItem): Promise<User> {
|
|
111
|
+
return await getRepository(User).findOne(inventoryItem.updaterId)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
@FieldResolver(type => User)
|
|
115
|
+
async creator(@Root() inventoryItem: InventoryItem): Promise<User> {
|
|
116
|
+
return await getRepository(User).findOne(inventoryItem.creatorId)
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { Field, ID, InputType, Int, ObjectType } from 'type-graphql'
|
|
2
|
+
|
|
3
|
+
import { ObjectRef } from '@things-factory/shell'
|
|
4
|
+
|
|
5
|
+
import { InventoryItem } from './inventory-item'
|
|
6
|
+
|
|
7
|
+
@InputType()
|
|
8
|
+
export class NewInventoryItem {
|
|
9
|
+
@Field()
|
|
10
|
+
name: string
|
|
11
|
+
|
|
12
|
+
@Field({ nullable: true })
|
|
13
|
+
serialNumber?: string
|
|
14
|
+
|
|
15
|
+
@Field({ nullable: true })
|
|
16
|
+
status?: string
|
|
17
|
+
|
|
18
|
+
@Field({ nullable: true })
|
|
19
|
+
source?: string
|
|
20
|
+
|
|
21
|
+
@Field(type => ObjectRef, { nullable: true })
|
|
22
|
+
product?: ObjectRef
|
|
23
|
+
|
|
24
|
+
@Field(type => ObjectRef, { nullable: true })
|
|
25
|
+
inventory?: ObjectRef
|
|
26
|
+
|
|
27
|
+
@Field({ nullable: true })
|
|
28
|
+
inboundOrderId?: string
|
|
29
|
+
|
|
30
|
+
@Field({ nullable: true })
|
|
31
|
+
outboundOrderId?: string
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@InputType()
|
|
35
|
+
export class InventoryItemPatch {
|
|
36
|
+
@Field(type => ID, { nullable: true })
|
|
37
|
+
id?: string
|
|
38
|
+
|
|
39
|
+
@Field({ nullable: true })
|
|
40
|
+
name?: string
|
|
41
|
+
|
|
42
|
+
@Field({ nullable: true })
|
|
43
|
+
serialNumber?: string
|
|
44
|
+
|
|
45
|
+
@Field({ nullable: true })
|
|
46
|
+
status?: string
|
|
47
|
+
|
|
48
|
+
@Field({ nullable: true })
|
|
49
|
+
source?: string
|
|
50
|
+
|
|
51
|
+
@Field(type => ObjectRef, { nullable: true })
|
|
52
|
+
product?: ObjectRef
|
|
53
|
+
|
|
54
|
+
@Field(type => ObjectRef, { nullable: true })
|
|
55
|
+
inventory?: ObjectRef
|
|
56
|
+
|
|
57
|
+
@Field({ nullable: true })
|
|
58
|
+
inboundOrderId?: string
|
|
59
|
+
|
|
60
|
+
@Field({ nullable: true })
|
|
61
|
+
outboundOrderId?: string
|
|
62
|
+
|
|
63
|
+
@Field({ nullable: true })
|
|
64
|
+
cuFlag: string
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@ObjectType()
|
|
68
|
+
export class InventoryItemList {
|
|
69
|
+
@Field(type => [InventoryItem])
|
|
70
|
+
items: InventoryItem[]
|
|
71
|
+
|
|
72
|
+
@Field(type => Int)
|
|
73
|
+
total: number
|
|
74
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { Field, ID, ObjectType } from 'type-graphql'
|
|
2
|
+
import {
|
|
3
|
+
Column,
|
|
4
|
+
CreateDateColumn,
|
|
5
|
+
Entity,
|
|
6
|
+
Index,
|
|
7
|
+
ManyToOne,
|
|
8
|
+
PrimaryGeneratedColumn,
|
|
9
|
+
RelationId,
|
|
10
|
+
UpdateDateColumn
|
|
11
|
+
} from 'typeorm'
|
|
12
|
+
|
|
13
|
+
import { User } from '@things-factory/auth-base'
|
|
14
|
+
import { Product } from '@things-factory/product-base'
|
|
15
|
+
import { Domain } from '@things-factory/shell'
|
|
16
|
+
|
|
17
|
+
import { Inventory } from '../inventory/inventory'
|
|
18
|
+
|
|
19
|
+
@Entity()
|
|
20
|
+
@Index('ix_inventory_item_0', (inventoryItem: InventoryItem) => [inventoryItem.domain, inventoryItem.name], {
|
|
21
|
+
unique: true
|
|
22
|
+
})
|
|
23
|
+
@ObjectType({ description: 'Entity for InventoryItem' })
|
|
24
|
+
export class InventoryItem {
|
|
25
|
+
@PrimaryGeneratedColumn('uuid')
|
|
26
|
+
@Field(type => ID)
|
|
27
|
+
readonly id: string
|
|
28
|
+
|
|
29
|
+
@ManyToOne(type => Domain)
|
|
30
|
+
@Field({ nullable: true })
|
|
31
|
+
domain?: Domain
|
|
32
|
+
|
|
33
|
+
@RelationId((inventoryItem: InventoryItem) => inventoryItem.domain)
|
|
34
|
+
domainId?: string
|
|
35
|
+
|
|
36
|
+
@Column()
|
|
37
|
+
@Field()
|
|
38
|
+
name: string
|
|
39
|
+
|
|
40
|
+
@Column({ nullable: true })
|
|
41
|
+
@Field({ nullable: true })
|
|
42
|
+
serialNumber?: string
|
|
43
|
+
|
|
44
|
+
@Column({ nullable: true })
|
|
45
|
+
@Field({ nullable: true })
|
|
46
|
+
status?: string
|
|
47
|
+
|
|
48
|
+
@Column({ nullable: true })
|
|
49
|
+
@Field({ nullable: true })
|
|
50
|
+
source?: string
|
|
51
|
+
|
|
52
|
+
@Column({ nullable: true })
|
|
53
|
+
@Field({ nullable: true })
|
|
54
|
+
inboundOrderId: string
|
|
55
|
+
|
|
56
|
+
@Column({ nullable: true })
|
|
57
|
+
@Field({ nullable: true })
|
|
58
|
+
outboundOrderId: string
|
|
59
|
+
|
|
60
|
+
@ManyToOne(type => Product)
|
|
61
|
+
@Field(type => Product, { nullable: true })
|
|
62
|
+
product?: Product
|
|
63
|
+
|
|
64
|
+
@RelationId((inventoryItem: InventoryItem) => inventoryItem.product)
|
|
65
|
+
productId?: string
|
|
66
|
+
|
|
67
|
+
@ManyToOne(type => Inventory)
|
|
68
|
+
@Field(type => Inventory)
|
|
69
|
+
inventory?: Inventory
|
|
70
|
+
|
|
71
|
+
@RelationId((inventoryItem: InventoryItem) => inventoryItem.inventory)
|
|
72
|
+
inventoryId?: string
|
|
73
|
+
|
|
74
|
+
@CreateDateColumn()
|
|
75
|
+
@Field({ nullable: true })
|
|
76
|
+
createdAt?: Date
|
|
77
|
+
|
|
78
|
+
@UpdateDateColumn()
|
|
79
|
+
@Field({ nullable: true })
|
|
80
|
+
updatedAt?: Date
|
|
81
|
+
|
|
82
|
+
@ManyToOne(type => User, {
|
|
83
|
+
nullable: true
|
|
84
|
+
})
|
|
85
|
+
@Field({ nullable: true })
|
|
86
|
+
creator?: User
|
|
87
|
+
|
|
88
|
+
@RelationId((inventoryItem: InventoryItem) => inventoryItem.creator)
|
|
89
|
+
creatorId?: string
|
|
90
|
+
|
|
91
|
+
@ManyToOne(type => User, {
|
|
92
|
+
nullable: true
|
|
93
|
+
})
|
|
94
|
+
@Field({ nullable: true })
|
|
95
|
+
updater?: User
|
|
96
|
+
|
|
97
|
+
@RelationId((inventoryItem: InventoryItem) => inventoryItem.creator)
|
|
98
|
+
updaterId?: string
|
|
99
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { InventoryProduct } from './inventory-product'
|
|
2
|
+
import { InventoryProductQuery } from './inventory-product-query'
|
|
3
|
+
import { InventoryProductMutation } from './inventory-product-mutation'
|
|
4
|
+
|
|
5
|
+
export const entities = [InventoryProduct]
|
|
6
|
+
export const resolvers = [InventoryProductQuery, InventoryProductMutation]
|