@things-factory/worksheet-base 3.7.5 → 3.7.6

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 (37) hide show
  1. package/dist-server/controllers/outbound/loading-worksheet-controller.js +4 -0
  2. package/dist-server/controllers/outbound/loading-worksheet-controller.js.map +1 -1
  3. package/dist-server/controllers/outbound/picking-worksheet-controller.js +121 -67
  4. package/dist-server/controllers/outbound/picking-worksheet-controller.js.map +1 -1
  5. package/dist-server/controllers/worksheet-controller.js +25 -0
  6. package/dist-server/controllers/worksheet-controller.js.map +1 -1
  7. package/dist-server/graphql/resolvers/worksheet/loading-worksheet.js +27 -2
  8. package/dist-server/graphql/resolvers/worksheet/loading-worksheet.js.map +1 -1
  9. package/dist-server/graphql/resolvers/worksheet/packing-worksheet.js +26 -0
  10. package/dist-server/graphql/resolvers/worksheet/packing-worksheet.js.map +1 -1
  11. package/dist-server/graphql/resolvers/worksheet/picking/complete-picking.js +27 -5
  12. package/dist-server/graphql/resolvers/worksheet/picking/complete-picking.js.map +1 -1
  13. package/dist-server/graphql/resolvers/worksheet/picking/fetch-and-assign-picking-task.js +72 -0
  14. package/dist-server/graphql/resolvers/worksheet/picking/fetch-and-assign-picking-task.js.map +1 -0
  15. package/dist-server/graphql/resolvers/worksheet/picking/index.js +2 -1
  16. package/dist-server/graphql/resolvers/worksheet/picking/index.js.map +1 -1
  17. package/dist-server/graphql/resolvers/worksheet/picking/picking.js +4 -4
  18. package/dist-server/graphql/resolvers/worksheet/picking/picking.js.map +1 -1
  19. package/dist-server/graphql/resolvers/worksheet/picking-worksheet.js +86 -57
  20. package/dist-server/graphql/resolvers/worksheet/picking-worksheet.js.map +1 -1
  21. package/dist-server/graphql/types/worksheet/index.js +5 -1
  22. package/dist-server/graphql/types/worksheet/index.js.map +1 -1
  23. package/dist-server/utils/inventory-util.js +25 -0
  24. package/dist-server/utils/inventory-util.js.map +1 -1
  25. package/package.json +7 -7
  26. package/server/controllers/outbound/loading-worksheet-controller.ts +20 -0
  27. package/server/controllers/outbound/picking-worksheet-controller.ts +148 -83
  28. package/server/controllers/worksheet-controller.ts +38 -0
  29. package/server/graphql/resolvers/worksheet/loading-worksheet.ts +33 -4
  30. package/server/graphql/resolvers/worksheet/packing-worksheet.ts +31 -3
  31. package/server/graphql/resolvers/worksheet/picking/complete-picking.ts +37 -5
  32. package/server/graphql/resolvers/worksheet/picking/fetch-and-assign-picking-task.ts +78 -0
  33. package/server/graphql/resolvers/worksheet/picking/index.ts +3 -1
  34. package/server/graphql/resolvers/worksheet/picking/picking.ts +5 -4
  35. package/server/graphql/resolvers/worksheet/picking-worksheet.ts +102 -62
  36. package/server/graphql/types/worksheet/index.ts +5 -1
  37. package/server/utils/inventory-util.ts +26 -0
@@ -19,6 +19,7 @@ import {
19
19
  import { EcommerceController } from '../../../../controllers/ecommerce'
20
20
  import { WorksheetController } from '../../../../controllers/worksheet-controller'
21
21
  import { Worksheet, WorksheetDetail } from '../../../../entities'
22
+ import { Setting, PartnerSetting } from '@things-factory/setting-base'
22
23
 
23
24
  export const completePickingResolver = {
24
25
  async completePicking(_: any, { releaseGoodNo }, context: any) {
@@ -187,10 +188,30 @@ export async function completePicking(
187
188
 
188
189
  if (releaseGood.packingOption) {
189
190
  const packingWSCtrl: PackingWorksheetController = new PackingWorksheetController(tx, domain, user)
190
- await packingWSCtrl.generatePackingWorksheet(releaseGoodNo)
191
+
192
+ const directActivatePackingWorksheet: Setting = await tx.getRepository(Setting).findOne({
193
+ where: { domain: domain, category: 'id-rule', name: 'enable-direct-activate-packing-worksheet' }
194
+ })
195
+ const partnerDirectActivatePackingWorksheetSetting: PartnerSetting = await tx.getRepository(PartnerSetting).findOne({
196
+ where: { setting: directActivatePackingWorksheet, domain: domain, partnerDomain: releaseGood.bizplace?.domain }
197
+ })
198
+
199
+ let packingWorksheet: Worksheet = await packingWSCtrl.generatePackingWorksheet(releaseGoodNo)
200
+
201
+ if (
202
+ directActivatePackingWorksheet != undefined && (directActivatePackingWorksheet.value).toLowerCase() == 'true'
203
+ ) {
204
+ if (partnerDirectActivatePackingWorksheetSetting != undefined) {
205
+ if ((partnerDirectActivatePackingWorksheetSetting.value).toLowerCase() == 'true')
206
+ await packingWSCtrl.activatePacking(packingWorksheet.name)
207
+ } else {
208
+ await packingWSCtrl.activatePacking(packingWorksheet.name)
209
+ }
210
+ }
211
+
191
212
  } else {
192
213
  // Find Existing Loading Worksheet if any
193
- const existLoadingWorksheet: Worksheet = await tx.getRepository(Worksheet).findOne({
214
+ let existLoadingWorksheet: Worksheet = await tx.getRepository(Worksheet).findOne({
194
215
  where: {
195
216
  releaseGood,
196
217
  type: WORKSHEET_TYPE.LOADING,
@@ -211,10 +232,21 @@ export async function completePicking(
211
232
 
212
233
  const loadingWorksheetDetails: WorksheetDetail[] = loadingWorksheet.worksheetDetails
213
234
  await loadingWSCtrl.activateLoading(loadingWorksheet.name, loadingWorksheetDetails)
214
- } else {
215
- throw new Error(
216
- 'Picking completion has been triggered twice, loading worksheet has been generated. Kindly proceed to loading.'
235
+ }
236
+ else {
237
+ const loadingWSCtrl: LoadingWorksheetController = new LoadingWorksheetController(tx, domain, user)
238
+ let loadingWorksheet: Worksheet = await loadingWSCtrl.updateLoadingWorksheet(
239
+ releaseGoodNo,
240
+ pickedTargetInventories,
241
+ existLoadingWorksheet
217
242
  )
243
+
244
+ if (!loadingWorksheet.worksheetDetails?.length) {
245
+ loadingWorksheet = await pickingWSCtrl.findWorksheetById(loadingWorksheet.id)
246
+ }
247
+
248
+ const loadingWorksheetDetails: WorksheetDetail[] = loadingWorksheet.worksheetDetails
249
+ await loadingWSCtrl.activateLoading(loadingWorksheet.name, loadingWorksheetDetails)
218
250
  }
219
251
  }
220
252
  }
@@ -0,0 +1,78 @@
1
+ import { EntityManager, getRepository } from 'typeorm'
2
+
3
+ import { User } from '@things-factory/auth-base'
4
+ import { Setting } from '@things-factory/setting-base'
5
+ import { Domain } from '@things-factory/shell'
6
+
7
+ import { WORKSHEET_STATUS, WORKSHEET_TYPE } from '../../../../constants'
8
+ import { Worksheet } from '../../../../entities'
9
+ import { pickingWorksheet } from '../picking-worksheet'
10
+ import { activatePicking } from './activate-picking'
11
+
12
+ export const fetchAndAssignPickingTaskResolver = {
13
+ async fetchAndAssignPickingTask(_: any, {}, context: any) {
14
+ const { tx, domain, user }: { tx: EntityManager; domain: Domain; user: User } = context.state
15
+ const assignee: User = await tx.getRepository(User).findOne(user.id, { relations: ['domains'] })
16
+ if ((assignee?.domains || []).every((userDomain: Domain) => userDomain.id !== domain.id))
17
+ throw new Error('Target user is not belong to current domain')
18
+
19
+ if (!assignee) throw new Error('failed to find target user')
20
+
21
+ let worksheet: Worksheet
22
+ worksheet = await tx.getRepository(Worksheet).findOne({
23
+ relations: ['releaseGood'],
24
+ where: [
25
+ {
26
+ domain,
27
+ type: WORKSHEET_TYPE.PICKING,
28
+ status: WORKSHEET_STATUS.EXECUTING,
29
+ assignee: assignee
30
+ },
31
+ {
32
+ domain,
33
+ type: WORKSHEET_TYPE.PICKING,
34
+ status: WORKSHEET_STATUS.DEACTIVATED,
35
+ assignee: assignee
36
+ }
37
+ ],
38
+ order: {
39
+ name: 'ASC'
40
+ }
41
+ })
42
+
43
+ if (!worksheet) {
44
+ worksheet = await tx.getRepository(Worksheet).findOne({
45
+ relations: ['releaseGood'],
46
+ where: [
47
+ {
48
+ domain,
49
+ type: WORKSHEET_TYPE.PICKING,
50
+ status: WORKSHEET_STATUS.EXECUTING,
51
+ assignee: null
52
+ },
53
+ {
54
+ domain,
55
+ type: WORKSHEET_TYPE.PICKING,
56
+ status: WORKSHEET_STATUS.DEACTIVATED,
57
+ assignee: null
58
+ }
59
+ ]
60
+ })
61
+
62
+ await getRepository(Worksheet).update({ id: worksheet.id }, { assignee: assignee })
63
+ }
64
+
65
+ if (worksheet.status == WORKSHEET_STATUS.DEACTIVATED) await activatePicking(tx, domain, user, worksheet.name)
66
+
67
+ const locationSortingRules: Setting = await tx.getRepository(Setting).findOne({
68
+ where: { domain, name: 'rule-for-picking-product' }
69
+ })
70
+
71
+ const sortingRule = JSON.parse(locationSortingRules.value)
72
+ const locationSortingRule = Object.keys(sortingRule).map(field => {
73
+ return { name: field, desc: sortingRule[field] === 'DESC' }
74
+ })
75
+
76
+ return await pickingWorksheet(domain, worksheet.releaseGood.name, locationSortingRule, tx)
77
+ }
78
+ }
@@ -2,6 +2,7 @@ import { activateBatchPickingResolver } from './activate-batch-picking'
2
2
  import { activatePickingResolver } from './activate-picking'
3
3
  import { assignPickingInventoriesResolver } from './assign-picking-inventories'
4
4
  import { assignPickingWorkerResolver } from './assign-picking-worker'
5
+ import { fetchAndAssignPickingTaskResolver } from './fetch-and-assign-picking-task'
5
6
  import { batchPickingResolver } from './batch-picking'
6
7
  import { completeBatchPickingResolver } from './complete-batch-picking'
7
8
  import { completePickingResolver } from './complete-picking'
@@ -21,5 +22,6 @@ export const Mutations = {
21
22
  ...batchPickingResolver,
22
23
  ...completePickingResolver,
23
24
  ...completeBatchPickingResolver,
24
- ...assignPickingWorkerResolver
25
+ ...assignPickingWorkerResolver,
26
+ ...fetchAndAssignPickingTaskResolver
25
27
  }
@@ -4,9 +4,9 @@ import { EntityManager } from 'typeorm'
4
4
  import { PickingWorksheetController } from '../../../../controllers'
5
5
 
6
6
  export const pickingResolver = {
7
- async picking(_: any, { worksheetDetailName, worksheetType, palletId, locationName, releaseQty }, context: any) {
7
+ async picking(_: any, { worksheetDetailName, worksheetType, palletId, locationName, releaseQty, binLocation }, context: any) {
8
8
  const { tx, domain, user }: { tx: EntityManager; domain: Domain; user: User } = context.state
9
- await picking(tx, domain, user, worksheetDetailName, worksheetType, palletId, locationName, releaseQty)
9
+ await picking(tx, domain, user, worksheetDetailName, worksheetType, palletId, locationName, releaseQty, binLocation)
10
10
  }
11
11
  }
12
12
 
@@ -18,8 +18,9 @@ export async function picking(
18
18
  worksheetType: string,
19
19
  palletId: string,
20
20
  locationName: string,
21
- releaseQty: number
21
+ releaseQty: number,
22
+ binLocation?: string
22
23
  ) {
23
24
  const worksheetController: PickingWorksheetController = new PickingWorksheetController(tx, domain, user)
24
- await worksheetController.picking(worksheetDetailName, worksheetType, palletId, locationName, releaseQty)
25
+ await worksheetController.picking(worksheetDetailName, worksheetType, palletId, locationName, releaseQty, binLocation)
25
26
  }
@@ -1,8 +1,8 @@
1
- import { createQueryBuilder, getRepository, SelectQueryBuilder } from 'typeorm'
1
+ import { EntityManager, In, SelectQueryBuilder } from 'typeorm'
2
2
 
3
3
  import { ORDER_INVENTORY_STATUS, OrderInventory, ReleaseGood } from '@things-factory/sales-base'
4
4
  import { Domain } from '@things-factory/shell'
5
- import { Inventory } from '@things-factory/warehouse-base'
5
+ import { Inventory, Location } from '@things-factory/warehouse-base'
6
6
 
7
7
  import { WORKSHEET_STATUS, WORKSHEET_TYPE } from '../../../constants'
8
8
  import { WorksheetDetail } from '../../../entities'
@@ -10,71 +10,111 @@ import { fetchExecutingWorksheet } from '../../../utils'
10
10
 
11
11
  export const pickingWorksheetResolver = {
12
12
  async pickingWorksheet(_: any, { releaseGoodNo, locationSortingRules }, context: any) {
13
- const { domain }: { domain: Domain } = context.state
14
- const releaseGood: ReleaseGood = await getRepository(ReleaseGood).findOne({
15
- where: { domain, name: releaseGoodNo /*status: ORDER_STATUS.PICKING*/ },
16
- relations: ['bizplace', 'bizplace.domain']
17
- })
18
- if (!releaseGood) throw new Error(`Couldn't find picking worksheet by order no (${releaseGoodNo})`)
19
-
20
- const worksheet = await fetchExecutingWorksheet(
21
- domain,
22
- releaseGood.bizplace,
23
- ['bizplace'],
24
- WORKSHEET_TYPE.PICKING,
25
- releaseGood
26
- )
13
+ const { domain, tx }: { domain: Domain; tx: EntityManager } = context.state
27
14
 
28
- const qb: SelectQueryBuilder<WorksheetDetail> = createQueryBuilder(WorksheetDetail, 'WSD')
29
- qb.leftJoinAndSelect('WSD.targetInventory', 'T_INV')
30
- .leftJoinAndSelect('T_INV.inventory', 'INV')
31
- .leftJoinAndSelect('T_INV.product', 'PROD')
32
- .leftJoinAndSelect('INV.location', 'LOC')
15
+ return await pickingWorksheet(domain, releaseGoodNo, locationSortingRules, tx)
16
+ }
17
+ }
33
18
 
34
- if (locationSortingRules?.length > 0) {
35
- locationSortingRules.forEach((rule: { name: string; desc: boolean }) => {
36
- qb.addOrderBy(`LOC.${rule.name}`, rule.desc ? 'DESC' : 'ASC')
37
- })
38
- }
19
+ export async function pickingWorksheet(
20
+ domain: Domain,
21
+ releaseGoodNo: String,
22
+ locationSortingRules: any,
23
+ tx: EntityManager
24
+ ) {
25
+ let releaseGood: ReleaseGood = await tx.getRepository(ReleaseGood).findOne({
26
+ where: { domain, name: releaseGoodNo /*status: ORDER_STATUS.PICKING*/ },
27
+ relations: ['bizplace', 'bizplace.domain']
28
+ })
39
29
 
40
- const worksheetDetails: WorksheetDetail[] = await qb
41
- .where('"WSD"."worksheet_id" = :worksheetId', { worksheetId: worksheet.id })
42
- .andWhere('"WSD"."status" != :status', { status: WORKSHEET_STATUS.REPLACED })
43
- .andWhere('"T_INV"."status" != :t_invstatus', { t_invstatus: ORDER_INVENTORY_STATUS.CANCELLED })
44
- .getMany()
30
+ // Find Release Order based on Bin
31
+ if (!releaseGood) {
32
+ const binLocation: Location = await tx.getRepository(Location).findOne({
33
+ where: { domain, name: releaseGoodNo }
34
+ })
45
35
 
46
- return {
47
- worksheetInfo: {
48
- bizplaceName: releaseGood.bizplace.name,
49
- partnerDomainId: releaseGood.bizplace?.domain.id,
50
- startedAt: worksheet.startedAt,
51
- refNo: releaseGood.refNo,
52
- refNo2: releaseGood.refNo2,
53
- releaseGood
36
+ const orderInventoryByBin: OrderInventory = await tx.getRepository(OrderInventory).findOne({
37
+ where: {
38
+ domain,
39
+ binLocation,
40
+ status: In([ORDER_INVENTORY_STATUS.PICKING, ORDER_INVENTORY_STATUS.PICKED])
41
+ },
42
+ order: {
43
+ createdAt: 'ASC'
54
44
  },
55
- worksheetDetailInfos: worksheetDetails.map(async (pickingWSD: WorksheetDetail) => {
56
- const targetInventory: OrderInventory = pickingWSD.targetInventory
57
- const inventory: Inventory = targetInventory.inventory
58
- return {
59
- name: pickingWSD.name,
60
- palletId: inventory?.palletId,
61
- cartonId: inventory?.cartonId,
62
- batchId: inventory?.batchId,
63
- batchIdRef: inventory?.batchIdRef,
64
- product: inventory?.product,
65
- qty: inventory?.qty,
66
- releaseQty: targetInventory.releaseQty,
67
- pickedQty: targetInventory.pickedQty,
68
- status: pickingWSD.status,
69
- description: pickingWSD.description,
70
- targetName: targetInventory.name,
71
- packingType: inventory?.packingType,
72
- packingSize: inventory?.packingSize,
73
- expirationDate: inventory?.expirationDate,
74
- location: inventory?.location,
75
- relatedOrderInv: targetInventory
76
- }
77
- })
45
+ relations: ['releaseGood', 'releaseGood.bizplace', 'releaseGood.bizplace.domain']
46
+ })
47
+
48
+ if (orderInventoryByBin?.releaseGood) {
49
+ releaseGoodNo = orderInventoryByBin.releaseGood.name
50
+ releaseGood = orderInventoryByBin.releaseGood
78
51
  }
79
52
  }
53
+
54
+ if (!releaseGood) throw new Error(`Couldn't find picking worksheet by order no (${releaseGoodNo})`)
55
+
56
+ const worksheet = await fetchExecutingWorksheet(
57
+ domain,
58
+ releaseGood.bizplace,
59
+ ['bizplace'],
60
+ WORKSHEET_TYPE.PICKING,
61
+ releaseGood,
62
+ tx
63
+ )
64
+
65
+ const qb: SelectQueryBuilder<WorksheetDetail> = tx.createQueryBuilder(WorksheetDetail, 'WSD')
66
+ qb.leftJoinAndSelect('WSD.targetInventory', 'T_INV')
67
+ .leftJoinAndSelect('T_INV.binLocation', 'BIN_LOC')
68
+ .leftJoinAndSelect('T_INV.inventory', 'INV')
69
+ .leftJoinAndSelect('T_INV.product', 'PROD')
70
+ .leftJoinAndSelect('INV.location', 'LOC')
71
+
72
+ if (locationSortingRules?.length > 0) {
73
+ locationSortingRules.forEach((rule: { name: string; desc: boolean }) => {
74
+ qb.addOrderBy(`LOC.${rule.name}`, rule.desc ? 'DESC' : 'ASC')
75
+ })
76
+ }
77
+
78
+ qb.addOrderBy(`PROD.name`, 'ASC')
79
+
80
+ const worksheetDetails: WorksheetDetail[] = await qb
81
+ .where('"WSD"."worksheet_id" = :worksheetId', { worksheetId: worksheet.id })
82
+ .andWhere('"WSD"."status" != :status', { status: WORKSHEET_STATUS.REPLACED })
83
+ .andWhere('"T_INV"."status" != :t_invstatus', { t_invstatus: ORDER_INVENTORY_STATUS.CANCELLED })
84
+ .getMany()
85
+
86
+ return {
87
+ worksheetInfo: {
88
+ bizplaceName: releaseGood.bizplace.name,
89
+ partnerDomainId: releaseGood.bizplace?.domain.id,
90
+ startedAt: worksheet.startedAt,
91
+ refNo: releaseGood.refNo,
92
+ refNo2: releaseGood.refNo2,
93
+ releaseGood
94
+ },
95
+ worksheetDetailInfos: worksheetDetails.map(async (pickingWSD: WorksheetDetail) => {
96
+ const targetInventory: OrderInventory = pickingWSD.targetInventory
97
+ const inventory: Inventory = targetInventory.inventory
98
+ return {
99
+ name: pickingWSD.name,
100
+ palletId: inventory?.palletId,
101
+ cartonId: inventory?.cartonId,
102
+ batchId: inventory?.batchId,
103
+ batchIdRef: inventory?.batchIdRef,
104
+ product: inventory?.product,
105
+ qty: inventory?.qty,
106
+ binLocation: targetInventory?.binLocation || '',
107
+ releaseQty: targetInventory.releaseQty,
108
+ pickedQty: targetInventory.pickedQty,
109
+ status: pickingWSD.status,
110
+ description: pickingWSD.description,
111
+ targetName: targetInventory.name,
112
+ packingType: inventory?.packingType,
113
+ packingSize: inventory?.packingSize,
114
+ expirationDate: inventory?.expirationDate,
115
+ location: inventory?.location,
116
+ relatedOrderInv: targetInventory
117
+ }
118
+ })
119
+ }
80
120
  }
@@ -290,6 +290,7 @@ export const Mutation = /* GraphQL */ `
290
290
  cartonId: String
291
291
  locationName: String!
292
292
  releaseQty: Int!
293
+ binLocation: String
293
294
  ): Boolean @privilege(category: "worksheet_execute", privilege: "mutation") @transaction
294
295
 
295
296
  scanProductPicking (
@@ -515,6 +516,9 @@ export const Mutation = /* GraphQL */ `
515
516
  worksheetId: String!
516
517
  userId: String!
517
518
  ): Boolean @privilege(category: "worksheet_control", privilege: "mutation") @transaction
519
+
520
+ fetchAndAssignPickingTask
521
+ : ExecutingWorksheet @privilege(category: "worksheet_control", privilege: "mutation") @transaction
518
522
 
519
523
  palletizingPallets (
520
524
  refOrderNo: String!
@@ -588,7 +592,7 @@ export const Query = /* GraphQL */ `
588
592
 
589
593
  pickingWorksheet (
590
594
  releaseGoodNo: String!, locationSortingRules: [Sorting]
591
- ): ExecutingWorksheet @privilege(category: "worksheet", privilege: "query")
595
+ ): ExecutingWorksheet @privilege(category: "worksheet", privilege: "query") @transaction
592
596
 
593
597
  sortingWorksheet (
594
598
  releaseGoodNo: String!
@@ -59,10 +59,36 @@ export async function generateInventoryHistory(
59
59
  palletId: inventory.palletId,
60
60
  seq: seq - 1
61
61
  })
62
+
62
63
  openingQty = lastInvHistory.openingQty + lastInvHistory.qty
63
64
  openingUomValue = lastInvHistory.openingUomValue + lastInvHistory.uomValue
64
65
  }
65
66
 
67
+ if (transactionType == 'PICKING' || transactionType == 'UNLOADING') {
68
+ const [findSameOrderHistory, total]: InventoryHistory = await invHistoryRepo.findAndCount({
69
+ domain: inventory.domain,
70
+ palletId: inventory.palletId,
71
+ refOrderId: refOrder.id
72
+ })
73
+
74
+ if (findSameOrderHistory) {
75
+ let prevTotalQty = 0
76
+ let prevTotalUomValue = 0
77
+ for (let oh of findSameOrderHistory) {
78
+ prevTotalQty += oh.qty
79
+ prevTotalUomValue += oh.uomValue
80
+ }
81
+ qty -= prevTotalQty
82
+ uomValue -= prevTotalUomValue
83
+ }
84
+ } else if (transactionType == 'UNDO_UNLOADING' || transactionType == 'RETURN') {
85
+ qty = qty
86
+ uomValue = uomValue
87
+ } else {
88
+ qty = 0
89
+ uomValue = 0
90
+ }
91
+
66
92
  let inventoryHistory: InventoryHistory = new InventoryHistory()
67
93
  inventoryHistory.name = InventoryNoGenerator.inventoryHistoryName()
68
94
  inventoryHistory.description = inventory.description