@things-factory/worksheet-base 4.3.356 → 4.3.358
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/worksheet.js +2 -1
- package/dist-server/constants/worksheet.js.map +1 -1
- package/dist-server/controllers/inspect/cycle-count-worksheet-controller.js +691 -257
- package/dist-server/controllers/inspect/cycle-count-worksheet-controller.js.map +1 -1
- package/dist-server/controllers/outbound/picking-worksheet-controller.js +76 -0
- package/dist-server/controllers/outbound/picking-worksheet-controller.js.map +1 -1
- package/dist-server/controllers/worksheet-controller.js +9 -2
- package/dist-server/controllers/worksheet-controller.js.map +1 -1
- package/dist-server/entities/worksheet-detail.js +9 -4
- package/dist-server/entities/worksheet-detail.js.map +1 -1
- package/dist-server/entities/worksheet.js +4 -0
- package/dist-server/entities/worksheet.js.map +1 -1
- package/dist-server/graphql/resolvers/worksheet/check-stock-take-current-location.js +18 -11
- package/dist-server/graphql/resolvers/worksheet/check-stock-take-current-location.js.map +1 -1
- package/dist-server/graphql/resolvers/worksheet/cycle-count-adjustment.js +75 -48
- package/dist-server/graphql/resolvers/worksheet/cycle-count-adjustment.js.map +1 -1
- package/dist-server/graphql/resolvers/worksheet/cycle-count-worksheet-for-carton.js +82 -0
- package/dist-server/graphql/resolvers/worksheet/cycle-count-worksheet-for-carton.js.map +1 -0
- package/dist-server/graphql/resolvers/worksheet/cycle-count-worksheet-for-pallet.js +82 -0
- package/dist-server/graphql/resolvers/worksheet/cycle-count-worksheet-for-pallet.js.map +1 -0
- package/dist-server/graphql/resolvers/worksheet/generate-worksheet/generate-cycle-count-worksheet-carton.js +17 -0
- package/dist-server/graphql/resolvers/worksheet/generate-worksheet/generate-cycle-count-worksheet-carton.js.map +1 -0
- package/dist-server/graphql/resolvers/worksheet/generate-worksheet/generate-cycle-count-worksheet.js +4 -4
- package/dist-server/graphql/resolvers/worksheet/generate-worksheet/generate-cycle-count-worksheet.js.map +1 -1
- package/dist-server/graphql/resolvers/worksheet/generate-worksheet/index.js +2 -1
- package/dist-server/graphql/resolvers/worksheet/generate-worksheet/index.js.map +1 -1
- package/dist-server/graphql/resolvers/worksheet/index.js +3 -2
- package/dist-server/graphql/resolvers/worksheet/index.js.map +1 -1
- package/dist-server/graphql/resolvers/worksheet/inspecting/add-extra-inventory.js +16 -0
- package/dist-server/graphql/resolvers/worksheet/inspecting/add-extra-inventory.js.map +1 -0
- package/dist-server/graphql/resolvers/worksheet/inspecting/check-missing-inventory-carton.js +16 -0
- package/dist-server/graphql/resolvers/worksheet/inspecting/check-missing-inventory-carton.js.map +1 -0
- package/dist-server/graphql/resolvers/worksheet/inspecting/check-missing-inventory.js +16 -0
- package/dist-server/graphql/resolvers/worksheet/inspecting/check-missing-inventory.js.map +1 -0
- package/dist-server/graphql/resolvers/worksheet/inspecting/index.js +9 -5
- package/dist-server/graphql/resolvers/worksheet/inspecting/index.js.map +1 -1
- package/dist-server/graphql/resolvers/worksheet/inspecting/inspecting-carton.js +16 -0
- package/dist-server/graphql/resolvers/worksheet/inspecting/inspecting-carton.js.map +1 -0
- package/dist-server/graphql/resolvers/worksheet/inspecting/inspecting-pallet.js +16 -0
- package/dist-server/graphql/resolvers/worksheet/inspecting/inspecting-pallet.js.map +1 -0
- package/dist-server/graphql/resolvers/worksheet/inspecting/relocate-inventory-carton.js +16 -0
- package/dist-server/graphql/resolvers/worksheet/inspecting/relocate-inventory-carton.js.map +1 -0
- package/dist-server/graphql/resolvers/worksheet/inspecting/relocate-inventory.js +16 -0
- package/dist-server/graphql/resolvers/worksheet/inspecting/relocate-inventory.js.map +1 -0
- package/dist-server/graphql/resolvers/worksheet/inspecting/undo-inspection-carton.js +16 -0
- package/dist-server/graphql/resolvers/worksheet/inspecting/undo-inspection-carton.js.map +1 -0
- package/dist-server/graphql/resolvers/worksheet/not-tally-target-inventories.js +9 -5
- package/dist-server/graphql/resolvers/worksheet/not-tally-target-inventories.js.map +1 -1
- package/dist-server/graphql/resolvers/worksheet/worksheet-with-pagination.js +9 -7
- package/dist-server/graphql/resolvers/worksheet/worksheet-with-pagination.js.map +1 -1
- package/dist-server/graphql/resolvers/worksheet/worksheets.js +23 -9
- package/dist-server/graphql/resolvers/worksheet/worksheets.js.map +1 -1
- package/dist-server/graphql/resolvers/worksheet-detail/create-worksheet-detail.js +8 -1
- package/dist-server/graphql/resolvers/worksheet-detail/create-worksheet-detail.js.map +1 -1
- package/dist-server/graphql/resolvers/worksheet-detail/worksheet-detail.js +12 -1
- package/dist-server/graphql/resolvers/worksheet-detail/worksheet-detail.js.map +1 -1
- package/dist-server/graphql/types/worksheet/index.js +65 -9
- package/dist-server/graphql/types/worksheet/index.js.map +1 -1
- package/dist-server/graphql/types/worksheet/inventory-check-worksheet.js +2 -1
- package/dist-server/graphql/types/worksheet/inventory-check-worksheet.js.map +1 -1
- package/dist-server/graphql/types/worksheet/worksheet-detail-info.js +3 -0
- package/dist-server/graphql/types/worksheet/worksheet-detail-info.js.map +1 -1
- package/dist-server/graphql/types/worksheet/worksheet.js +2 -0
- package/dist-server/graphql/types/worksheet/worksheet.js.map +1 -1
- package/dist-server/graphql/types/worksheet-detail/new-worksheet-detail.js +1 -0
- package/dist-server/graphql/types/worksheet-detail/new-worksheet-detail.js.map +1 -1
- package/dist-server/graphql/types/worksheet-detail/worksheet-detail-patch.js +1 -0
- package/dist-server/graphql/types/worksheet-detail/worksheet-detail-patch.js.map +1 -1
- package/dist-server/graphql/types/worksheet-detail/worksheet-detail.js +1 -0
- package/dist-server/graphql/types/worksheet-detail/worksheet-detail.js.map +1 -1
- package/dist-server/utils/lmd-util.js +9 -8
- package/dist-server/utils/lmd-util.js.map +1 -1
- package/package.json +10 -10
- package/server/constants/worksheet.ts +2 -1
- package/server/controllers/inspect/cycle-count-worksheet-controller.ts +904 -296
- package/server/controllers/outbound/picking-worksheet-controller.ts +95 -1
- package/server/controllers/worksheet-controller.ts +10 -4
- package/server/entities/worksheet-detail.ts +7 -10
- package/server/entities/worksheet.ts +3 -0
- package/server/graphql/resolvers/worksheet/check-stock-take-current-location.ts +21 -14
- package/server/graphql/resolvers/worksheet/cycle-count-adjustment.ts +114 -51
- package/server/graphql/resolvers/worksheet/cycle-count-worksheet-for-carton.ts +90 -0
- package/server/graphql/resolvers/worksheet/cycle-count-worksheet-for-pallet.ts +91 -0
- package/server/graphql/resolvers/worksheet/generate-worksheet/generate-cycle-count-worksheet-carton.ts +57 -0
- package/server/graphql/resolvers/worksheet/generate-worksheet/generate-cycle-count-worksheet.ts +17 -11
- package/server/graphql/resolvers/worksheet/generate-worksheet/index.ts +2 -0
- package/server/graphql/resolvers/worksheet/index.ts +4 -2
- package/server/graphql/resolvers/worksheet/inspecting/{add-extra-pallet.ts → add-extra-inventory.ts} +27 -12
- package/server/graphql/resolvers/worksheet/inspecting/check-missing-inventory-carton.ts +24 -0
- package/server/graphql/resolvers/worksheet/inspecting/{check-missing-pallet.ts → check-missing-inventory.ts} +10 -5
- package/server/graphql/resolvers/worksheet/inspecting/index.ts +17 -9
- package/server/graphql/resolvers/worksheet/inspecting/inspecting-carton.ts +51 -0
- package/server/graphql/resolvers/worksheet/inspecting/{inspecting.ts → inspecting-pallet.ts} +5 -5
- package/server/graphql/resolvers/worksheet/inspecting/relocate-inventory-carton.ts +62 -0
- package/server/graphql/resolvers/worksheet/inspecting/{relocate-pallet.ts → relocate-inventory.ts} +15 -5
- package/server/graphql/resolvers/worksheet/inspecting/undo-inspection-carton.ts +24 -0
- package/server/graphql/resolvers/worksheet/not-tally-target-inventories.ts +11 -7
- package/server/graphql/resolvers/worksheet/worksheet-with-pagination.ts +9 -7
- package/server/graphql/resolvers/worksheet/worksheets.ts +57 -38
- package/server/graphql/resolvers/worksheet-detail/create-worksheet-detail.ts +10 -2
- package/server/graphql/resolvers/worksheet-detail/worksheet-detail.ts +12 -1
- package/server/graphql/types/worksheet/index.ts +65 -9
- package/server/graphql/types/worksheet/inventory-check-worksheet.ts +2 -1
- package/server/graphql/types/worksheet/worksheet-detail-info.ts +3 -0
- package/server/graphql/types/worksheet/worksheet.ts +2 -0
- package/server/graphql/types/worksheet-detail/new-worksheet-detail.ts +1 -0
- package/server/graphql/types/worksheet-detail/worksheet-detail-patch.ts +1 -0
- package/server/graphql/types/worksheet-detail/worksheet-detail.ts +1 -0
- package/server/utils/lmd-util.ts +25 -6
- package/tsconfig.json +1 -1
- package/dist-server/graphql/resolvers/worksheet/cycle-count-worksheet.js +0 -74
- package/dist-server/graphql/resolvers/worksheet/cycle-count-worksheet.js.map +0 -1
- package/dist-server/graphql/resolvers/worksheet/inspecting/add-extra-pallet.js +0 -16
- package/dist-server/graphql/resolvers/worksheet/inspecting/add-extra-pallet.js.map +0 -1
- package/dist-server/graphql/resolvers/worksheet/inspecting/check-missing-pallet.js +0 -16
- package/dist-server/graphql/resolvers/worksheet/inspecting/check-missing-pallet.js.map +0 -1
- package/dist-server/graphql/resolvers/worksheet/inspecting/inspecting.js +0 -16
- package/dist-server/graphql/resolvers/worksheet/inspecting/inspecting.js.map +0 -1
- package/dist-server/graphql/resolvers/worksheet/inspecting/relocate-pallet.js +0 -16
- package/dist-server/graphql/resolvers/worksheet/inspecting/relocate-pallet.js.map +0 -1
- package/server/graphql/resolvers/worksheet/cycle-count-worksheet.ts +0 -80
|
@@ -5,176 +5,315 @@ const typeorm_1 = require("typeorm");
|
|
|
5
5
|
const biz_base_1 = require("@things-factory/biz-base");
|
|
6
6
|
const sales_base_1 = require("@things-factory/sales-base");
|
|
7
7
|
const warehouse_base_1 = require("@things-factory/warehouse-base");
|
|
8
|
+
const product_base_1 = require("@things-factory/product-base");
|
|
9
|
+
const setting_base_1 = require("@things-factory/setting-base");
|
|
10
|
+
const id_rule_base_1 = require("@things-factory/id-rule-base");
|
|
8
11
|
const constants_1 = require("../../constants");
|
|
9
12
|
const entities_1 = require("../../entities");
|
|
10
13
|
const utils_1 = require("../../utils");
|
|
11
14
|
const worksheet_controller_1 = require("../worksheet-controller");
|
|
12
15
|
class CycleCountWorksheetController extends worksheet_controller_1.WorksheetController {
|
|
13
|
-
async
|
|
14
|
-
|
|
16
|
+
async createCycleCountWorksheet(customerBizplace, customerId, executionDate, inventoryCheckItem, selectedLocation, limit) {
|
|
17
|
+
const cycleCount = await (0, sales_base_1.generateCycleCount)(this.trxMgr, this.domain, this.user, executionDate, customerId);
|
|
18
|
+
// Find out inventories which is target for cycle counting
|
|
19
|
+
const qb = this.trxMgr.getRepository(warehouse_base_1.Inventory).createQueryBuilder('INV');
|
|
20
|
+
qb.leftJoinAndSelect('INV.location', 'LOC')
|
|
21
|
+
.leftJoinAndSelect('INV.product', 'PROD')
|
|
22
|
+
.leftJoinAndSelect('INV.productDetail', 'PD')
|
|
23
|
+
.where('INV.domain_id = :domainId', { domainId: this.domain.id })
|
|
24
|
+
.andWhere('INV.bizplace_id = :bizplaceId', { bizplaceId: customerBizplace.id })
|
|
25
|
+
.andWhere('INV.status = :status', { status: warehouse_base_1.INVENTORY_STATUS.STORED });
|
|
26
|
+
if (inventoryCheckItem && inventoryCheckItem.length > 0) {
|
|
27
|
+
let keyval = {
|
|
28
|
+
batchId: 'batch_id',
|
|
29
|
+
batchIdRef: 'batch_id_ref',
|
|
30
|
+
productDetailId: 'product_detail_id'
|
|
31
|
+
};
|
|
32
|
+
qb.andWhere(new typeorm_1.Brackets(qb => {
|
|
33
|
+
inventoryCheckItem.forEach((itm, idx) => {
|
|
34
|
+
qb.orWhere(new typeorm_1.Brackets(qb2 => {
|
|
35
|
+
let first = true;
|
|
36
|
+
for (var prop in itm) {
|
|
37
|
+
if (first) {
|
|
38
|
+
first = false;
|
|
39
|
+
qb2.where(`INV.${keyval[prop]} ${itm[prop] == null ? 'is null' : " = '" + itm[prop] + "'"}`);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
qb2.andWhere(`INV.${keyval[prop]} ${itm[prop] == null ? 'is null' : " = '" + itm[prop] + "'"}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}));
|
|
46
|
+
});
|
|
47
|
+
}));
|
|
48
|
+
}
|
|
49
|
+
else if (selectedLocation && selectedLocation.length > 0) {
|
|
50
|
+
// If selectedLocation is provided
|
|
51
|
+
// Query inventory items located at the selected location
|
|
52
|
+
qb.andWhere('INV.location_id IN (:...locationIds)', { locationIds: selectedLocation });
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
if (limit > 0) {
|
|
56
|
+
qb.orderBy('RANDOM()').limit(limit);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
let inventories = await qb.getMany();
|
|
60
|
+
if (!inventories.length) {
|
|
61
|
+
throw new Error(`Failed to find inventories`);
|
|
62
|
+
}
|
|
63
|
+
let cycleCountWorksheet = new entities_1.Worksheet();
|
|
64
|
+
cycleCountWorksheet.domain = this.domain;
|
|
65
|
+
cycleCountWorksheet.bizplace = customerBizplace;
|
|
66
|
+
cycleCountWorksheet.name = utils_1.WorksheetNoGenerator.cycleCount();
|
|
67
|
+
cycleCountWorksheet.inventoryCheck = cycleCount;
|
|
68
|
+
cycleCountWorksheet.type = constants_1.WORKSHEET_TYPE.CYCLE_COUNT;
|
|
69
|
+
cycleCountWorksheet.status = constants_1.WORKSHEET_STATUS.DEACTIVATED;
|
|
70
|
+
cycleCountWorksheet.checkCount = 1;
|
|
71
|
+
cycleCountWorksheet.creator = this.user;
|
|
72
|
+
cycleCountWorksheet.updater = this.user;
|
|
73
|
+
cycleCountWorksheet = await this.trxMgr.getRepository(entities_1.Worksheet).save(cycleCountWorksheet);
|
|
74
|
+
// generate order inventory mapping with inventory ID
|
|
75
|
+
let targetInventoryCheckItems = [];
|
|
76
|
+
for (let i = 0; i < inventories.length; i++) {
|
|
77
|
+
const inventory = inventories[i];
|
|
78
|
+
let targetInventoryCheckItem = new sales_base_1.InventoryCheckItem();
|
|
79
|
+
targetInventoryCheckItem.domain = this.domain;
|
|
80
|
+
targetInventoryCheckItem.bizplace = customerBizplace;
|
|
81
|
+
targetInventoryCheckItem.status = sales_base_1.INVENTORY_CHECK_ITEM_STATUS.PENDING;
|
|
82
|
+
targetInventoryCheckItem.name = sales_base_1.OrderNoGenerator.inventoryCheckItem();
|
|
83
|
+
targetInventoryCheckItem.inventoryCheck = cycleCount;
|
|
84
|
+
targetInventoryCheckItem.originQty = inventory.qty;
|
|
85
|
+
targetInventoryCheckItem.originWeight = 0;
|
|
86
|
+
targetInventoryCheckItem.originUomValue = inventory.uomValue;
|
|
87
|
+
targetInventoryCheckItem.originBatchNo = inventory.batchId;
|
|
88
|
+
targetInventoryCheckItem.originLocation = inventory.location;
|
|
89
|
+
targetInventoryCheckItem.inventory = inventory;
|
|
90
|
+
targetInventoryCheckItem.product = inventory.product;
|
|
91
|
+
targetInventoryCheckItem.productDetail = inventory.productDetail;
|
|
92
|
+
targetInventoryCheckItem.countNo = 1;
|
|
93
|
+
targetInventoryCheckItem.creator = this.user;
|
|
94
|
+
targetInventoryCheckItem.updater = this.user;
|
|
95
|
+
targetInventoryCheckItems.push(targetInventoryCheckItem);
|
|
96
|
+
inventory.updater = this.user;
|
|
97
|
+
}
|
|
98
|
+
targetInventoryCheckItems = await this.trxMgr
|
|
99
|
+
.getRepository(sales_base_1.InventoryCheckItem)
|
|
100
|
+
.save(targetInventoryCheckItems, { chunk: 500 });
|
|
101
|
+
inventories = await this.trxMgr.getRepository(warehouse_base_1.Inventory).save(inventories, { chunk: 500 });
|
|
102
|
+
let cycleCountWorksheetDetails = [];
|
|
103
|
+
for (let i = 0; i < targetInventoryCheckItems.length; i++) {
|
|
104
|
+
let targetInventoryCheckItem = targetInventoryCheckItems[i];
|
|
105
|
+
let cycleCountWorksheetDetail = new entities_1.WorksheetDetail();
|
|
106
|
+
cycleCountWorksheetDetail.domain = this.domain;
|
|
107
|
+
cycleCountWorksheetDetail.bizplace = customerBizplace;
|
|
108
|
+
cycleCountWorksheetDetail.worksheet = cycleCountWorksheet;
|
|
109
|
+
cycleCountWorksheetDetail.name = utils_1.WorksheetNoGenerator.cycleCountDetail();
|
|
110
|
+
cycleCountWorksheetDetail.targetInventoryCheckItem = targetInventoryCheckItem;
|
|
111
|
+
cycleCountWorksheetDetail.type = constants_1.WORKSHEET_TYPE.CYCLE_COUNT;
|
|
112
|
+
cycleCountWorksheetDetail.status = constants_1.WORKSHEET_STATUS.DEACTIVATED;
|
|
113
|
+
cycleCountWorksheetDetail.creator = this.user;
|
|
114
|
+
cycleCountWorksheetDetail.updater = this.user;
|
|
115
|
+
cycleCountWorksheetDetails.push(cycleCountWorksheetDetail);
|
|
116
|
+
}
|
|
117
|
+
await this.trxMgr.getRepository(entities_1.WorksheetDetail).save(cycleCountWorksheetDetails, { chunk: 500 });
|
|
118
|
+
return cycleCountWorksheet;
|
|
119
|
+
}
|
|
120
|
+
async createNextRoundCycleCountWorksheet(customerId, existingInventoryCheck, nextExecutionDate, currentCycleCountWorksheet, inventoryCheckItemIds) {
|
|
121
|
+
try {
|
|
122
|
+
// Step 1: Create a new cycle count worksheet for the next round
|
|
123
|
+
let nextRoundWorksheet = new entities_1.Worksheet();
|
|
124
|
+
Object.assign(nextRoundWorksheet, currentCycleCountWorksheet);
|
|
125
|
+
nextRoundWorksheet.id = undefined;
|
|
126
|
+
nextRoundWorksheet.domain = this.domain;
|
|
127
|
+
nextRoundWorksheet.bizplace = customerId;
|
|
128
|
+
nextRoundWorksheet.name = utils_1.WorksheetNoGenerator.cycleCount();
|
|
129
|
+
nextRoundWorksheet.status = constants_1.WORKSHEET_STATUS.EXECUTING;
|
|
130
|
+
nextRoundWorksheet.endedAt = null;
|
|
131
|
+
nextRoundWorksheet.updater = this.user;
|
|
132
|
+
nextRoundWorksheet.worksheetDetails = null;
|
|
133
|
+
nextRoundWorksheet.checkCount = currentCycleCountWorksheet.checkCount + 1;
|
|
134
|
+
nextRoundWorksheet.inventoryCheck = existingInventoryCheck;
|
|
135
|
+
nextRoundWorksheet.type = constants_1.WORKSHEET_TYPE.CYCLE_COUNT;
|
|
136
|
+
// Step 2: Save the new Worksheet
|
|
137
|
+
await this.trxMgr.getRepository(entities_1.Worksheet).save(nextRoundWorksheet);
|
|
138
|
+
// Step 3: Fetch current InventoryCheckItems
|
|
139
|
+
const currentInventoryCheckItems = await this.trxMgr
|
|
140
|
+
.getRepository(sales_base_1.InventoryCheckItem)
|
|
141
|
+
.findByIds(inventoryCheckItemIds);
|
|
142
|
+
// Step 4: Create new InventoryCheckItems based on the current ones
|
|
143
|
+
const nextRoundInventoryCheckItems = currentInventoryCheckItems.map(currentItem => {
|
|
144
|
+
let nextRoundItem = new sales_base_1.InventoryCheckItem();
|
|
145
|
+
Object.assign(nextRoundItem, currentItem);
|
|
146
|
+
nextRoundItem.id = undefined;
|
|
147
|
+
nextRoundItem.domain = this.domain;
|
|
148
|
+
nextRoundItem.bizplace = customerId;
|
|
149
|
+
nextRoundItem.inventoryCheck = currentItem.inventoryCheckId;
|
|
150
|
+
nextRoundItem.status = sales_base_1.INVENTORY_CHECK_ITEM_STATUS.INSPECTING;
|
|
151
|
+
nextRoundItem.name = sales_base_1.OrderNoGenerator.inventoryCheckItem();
|
|
152
|
+
nextRoundItem.originQty = currentItem.inspectedQty || currentItem.originQty;
|
|
153
|
+
nextRoundItem.originUomValue = currentItem.inspectedUomValue || currentItem.originUomValue;
|
|
154
|
+
nextRoundItem.originBatchNo = currentItem.inspectedBatchNo || currentItem.originBatchNo;
|
|
155
|
+
nextRoundItem.originLocation = currentItem.inspectedLocationId || currentItem.originLocationId;
|
|
156
|
+
nextRoundItem.inspectedQty = null;
|
|
157
|
+
nextRoundItem.inspectedUomValue = null;
|
|
158
|
+
nextRoundItem.inspectedBatchNo = null;
|
|
159
|
+
nextRoundItem.inspectedLocationId = null;
|
|
160
|
+
nextRoundItem.countNo = currentItem.countNo + 1;
|
|
161
|
+
nextRoundItem.inventory = currentItem.inventoryId;
|
|
162
|
+
nextRoundItem.product = currentItem.productId;
|
|
163
|
+
nextRoundItem.productDetail = currentItem.productDetailId;
|
|
164
|
+
nextRoundItem.creator = this.user;
|
|
165
|
+
nextRoundItem.updater = this.user;
|
|
166
|
+
return nextRoundItem;
|
|
167
|
+
});
|
|
168
|
+
// Step 5: Save the new InventoryCheckItems
|
|
169
|
+
await this.trxMgr.getRepository(sales_base_1.InventoryCheckItem).save(nextRoundInventoryCheckItems, { chunk: 500 });
|
|
170
|
+
// Step 6: Create a new cycle count worksheet details for the next round
|
|
171
|
+
let nextRoundWorksheetDetails = nextRoundInventoryCheckItems.map(newItem => {
|
|
172
|
+
let detail = new entities_1.WorksheetDetail();
|
|
173
|
+
detail.domain = this.domain;
|
|
174
|
+
detail.bizplace = customerId;
|
|
175
|
+
detail.worksheet = nextRoundWorksheet;
|
|
176
|
+
detail.name = utils_1.WorksheetNoGenerator.cycleCountDetail();
|
|
177
|
+
detail.targetInventoryCheckItem = newItem;
|
|
178
|
+
detail.type = constants_1.WORKSHEET_TYPE.CYCLE_COUNT;
|
|
179
|
+
detail.status = constants_1.WORKSHEET_STATUS.EXECUTING;
|
|
180
|
+
detail.creator = this.user;
|
|
181
|
+
detail.updater = this.user;
|
|
182
|
+
return detail;
|
|
183
|
+
});
|
|
184
|
+
// Step 7: Save the new Worksheet Details
|
|
185
|
+
await this.trxMgr.getRepository(entities_1.WorksheetDetail).save(nextRoundWorksheetDetails, { chunk: 500 });
|
|
186
|
+
// Step 8: Mark the selected inventory as TERMINATED
|
|
187
|
+
currentInventoryCheckItems.forEach(item => {
|
|
188
|
+
item.status = sales_base_1.INVENTORY_CHECK_ITEM_STATUS.TERMINATED;
|
|
189
|
+
item.updater = this.user;
|
|
190
|
+
});
|
|
191
|
+
await this.trxMgr.getRepository(sales_base_1.InventoryCheckItem).save(currentInventoryCheckItems);
|
|
192
|
+
// Step 9: Directly update the worksheet details
|
|
193
|
+
await this.trxMgr
|
|
194
|
+
.getRepository(entities_1.WorksheetDetail)
|
|
195
|
+
.createQueryBuilder()
|
|
196
|
+
.update(entities_1.WorksheetDetail)
|
|
197
|
+
.set({
|
|
198
|
+
status: constants_1.WORKSHEET_STATUS.DONE,
|
|
199
|
+
updater: this.user
|
|
200
|
+
})
|
|
201
|
+
.where('targetInventoryCheckItem IN (:...ids)', { ids: currentInventoryCheckItems.map(item => item.id) })
|
|
202
|
+
.execute();
|
|
203
|
+
// Check if any record is not DONE
|
|
204
|
+
const notDoneCount = await this.trxMgr.getRepository(entities_1.WorksheetDetail).count({
|
|
205
|
+
where: {
|
|
206
|
+
worksheet: currentCycleCountWorksheet,
|
|
207
|
+
status: (0, typeorm_1.Not)((0, typeorm_1.Equal)(constants_1.WORKSHEET_STATUS.DONE))
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
if (notDoneCount === 0) {
|
|
211
|
+
// Step 11: Update status of existing InventoryCheck
|
|
212
|
+
existingInventoryCheck.status = sales_base_1.ORDER_STATUS.INSPECTING;
|
|
213
|
+
existingInventoryCheck.updater = this.user;
|
|
214
|
+
await this.trxMgr.getRepository(sales_base_1.InventoryCheck).save(existingInventoryCheck);
|
|
215
|
+
// Step 12: Mark the current worksheet as DONE
|
|
216
|
+
currentCycleCountWorksheet.status = constants_1.WORKSHEET_STATUS.DONE;
|
|
217
|
+
currentCycleCountWorksheet.updater = this.user;
|
|
218
|
+
await this.trxMgr.getRepository(entities_1.Worksheet).save(currentCycleCountWorksheet);
|
|
219
|
+
}
|
|
220
|
+
existingInventoryCheck.executionDate = nextExecutionDate;
|
|
221
|
+
existingInventoryCheck.updater = this.user;
|
|
222
|
+
await this.trxMgr.getRepository(sales_base_1.InventoryCheck).save(existingInventoryCheck);
|
|
223
|
+
return nextRoundWorksheet;
|
|
224
|
+
}
|
|
225
|
+
catch (error) {
|
|
226
|
+
console.error('An error occurred while creating the next round cycle count worksheet:', error);
|
|
227
|
+
throw new Error('Failed to create next round cycle count worksheet');
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
async generateCycleCountWorksheet(executionDate, customerId, inventoryCheckItemIds = [], inventoryCheckItem = [], limit = 0, selectedLocation = [], cycleCountNo) {
|
|
15
231
|
const customerBizplace = await this.trxMgr.getRepository(biz_base_1.Bizplace).findOne(customerId);
|
|
16
|
-
|
|
232
|
+
const foundInventoryCheck = await this.trxMgr.getRepository(sales_base_1.InventoryCheck).findOne({
|
|
233
|
+
where: {
|
|
234
|
+
domain: this.domain,
|
|
235
|
+
bizplace: customerBizplace,
|
|
236
|
+
name: cycleCountNo
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
const worksheetRepository = this.trxMgr.getRepository(entities_1.Worksheet);
|
|
240
|
+
const foundCycleCountWorksheet = await worksheetRepository.findOne({
|
|
17
241
|
where: {
|
|
18
242
|
domain: this.domain,
|
|
19
243
|
bizplace: customerBizplace,
|
|
20
244
|
type: (0, typeorm_1.In)([constants_1.WORKSHEET_TYPE.CYCLE_COUNT, constants_1.WORKSHEET_TYPE.CYCLE_COUNT_RECHECK]),
|
|
21
245
|
status: (0, typeorm_1.Not)(constants_1.WORKSHEET_STATUS.DONE)
|
|
22
246
|
},
|
|
23
|
-
|
|
247
|
+
order: {
|
|
248
|
+
checkCount: 'DESC'
|
|
249
|
+
},
|
|
250
|
+
relations: ['worksheetDetails', 'worksheetDetails.targetInventoryCheckItem', 'inventoryCheck']
|
|
24
251
|
});
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
// Update status of target inventories (NOT_TALLY => INSPECTING)
|
|
28
|
-
let targetInventories = await this.trxMgr
|
|
29
|
-
.getRepository(sales_base_1.OrderInventory)
|
|
30
|
-
.findByIds(orderInventoryIds);
|
|
31
|
-
targetInventories.forEach((targetInventory) => {
|
|
32
|
-
targetInventory.status = sales_base_1.ORDER_INVENTORY_STATUS.INSPECTING;
|
|
33
|
-
targetInventory.updater = this.user;
|
|
34
|
-
});
|
|
35
|
-
await this.trxMgr.getRepository(sales_base_1.OrderInventory).save(targetInventories);
|
|
36
|
-
// Update status of worksheet (NOT_TALLY => EXECUTING)
|
|
37
|
-
foundCycleCountWorksheet.type = constants_1.WORKSHEET_TYPE.CYCLE_COUNT_RECHECK;
|
|
38
|
-
foundCycleCountWorksheet.status = constants_1.WORKSHEET_STATUS.EXECUTING;
|
|
39
|
-
foundCycleCountWorksheet.endedAt = null;
|
|
40
|
-
foundCycleCountWorksheet.updater = this.user;
|
|
41
|
-
await this.trxMgr.getRepository(entities_1.Worksheet).save(foundCycleCountWorksheet);
|
|
42
|
-
// Update status of worksheet details (NOT_TALLY => EXECUTING)
|
|
43
|
-
let worksheetDetails = foundCycleCountWorksheet.worksheetDetails.filter((wsd) => orderInventoryIds.indexOf(wsd.targetInventory.id) >= 0);
|
|
44
|
-
worksheetDetails.forEach((wsd) => {
|
|
45
|
-
wsd.status = constants_1.WORKSHEET_STATUS.EXECUTING;
|
|
46
|
-
wsd.updater = this.user;
|
|
47
|
-
});
|
|
48
|
-
await this.trxMgr.getRepository(entities_1.WorksheetDetail).save(worksheetDetails);
|
|
49
|
-
// Update status of cycle count
|
|
50
|
-
const cycleCount = foundCycleCountWorksheet.inventoryCheck;
|
|
51
|
-
cycleCount.status = sales_base_1.ORDER_STATUS.INSPECTING;
|
|
52
|
-
cycleCount.updater = this.user;
|
|
53
|
-
await this.trxMgr.getRepository(sales_base_1.InventoryCheck).save(cycleCount);
|
|
54
|
-
return foundCycleCountWorksheet;
|
|
252
|
+
if (inventoryCheckItemIds.length) {
|
|
253
|
+
return await this.createNextRoundCycleCountWorksheet(customerId, foundInventoryCheck, executionDate, foundCycleCountWorksheet, inventoryCheckItemIds);
|
|
55
254
|
}
|
|
56
255
|
else {
|
|
57
|
-
// Create first round of cycle count with whole pallets
|
|
58
256
|
if (foundCycleCountWorksheet) {
|
|
59
|
-
throw new Error(
|
|
60
|
-
}
|
|
61
|
-
const cycleCount = await (0, sales_base_1.generateCycleCount)(this.trxMgr, this.domain, this.user, executionDate, customerId);
|
|
62
|
-
// Find out inventories which is target for cycle counting
|
|
63
|
-
const qb = this.trxMgr.getRepository(warehouse_base_1.Inventory).createQueryBuilder('INV');
|
|
64
|
-
qb.leftJoinAndSelect('INV.location', 'LOC')
|
|
65
|
-
.where('INV.domain_id = :domainId', { domainId: this.domain.id })
|
|
66
|
-
.andWhere('INV.bizplace_id = :bizplaceId', { bizplaceId: customerBizplace.id })
|
|
67
|
-
.andWhere('INV.status = :status', { status: warehouse_base_1.INVENTORY_STATUS.STORED })
|
|
68
|
-
.andWhere(new typeorm_1.Brackets(qb => {
|
|
69
|
-
qb.where('"INV"."locked_qty" ISNULL');
|
|
70
|
-
qb.orWhere('"INV"."locked_qty" = 0');
|
|
71
|
-
}));
|
|
72
|
-
if (orderInventory && orderInventory.length > 0) {
|
|
73
|
-
let keyval = {
|
|
74
|
-
batchId: 'batch_id',
|
|
75
|
-
batchIdRef: 'batch_id_ref',
|
|
76
|
-
productDetailId: 'product_detail_id'
|
|
77
|
-
};
|
|
78
|
-
qb.andWhere(new typeorm_1.Brackets(qb => {
|
|
79
|
-
orderInventory.forEach((itm, idx) => {
|
|
80
|
-
// sample itm value
|
|
81
|
-
// batchId: 'WO00019730', batchIdRef: null, productDetailId: '1d679587-c713-42d6-bd0a-74e587e39cc7'
|
|
82
|
-
qb.orWhere(new typeorm_1.Brackets(qb2 => {
|
|
83
|
-
let first = true;
|
|
84
|
-
for (var prop in itm) {
|
|
85
|
-
if (first) {
|
|
86
|
-
first = false;
|
|
87
|
-
qb2.where(`INV.${keyval[prop]} ${itm[prop] == null ? 'is null' : " = '" + itm[prop] + "'"}`);
|
|
88
|
-
}
|
|
89
|
-
else {
|
|
90
|
-
qb2.andWhere(`INV.${keyval[prop]} ${itm[prop] == null ? 'is null' : " = '" + itm[prop] + "'"}`);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}));
|
|
94
|
-
});
|
|
95
|
-
}));
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
if (limit > 0) {
|
|
99
|
-
qb.orderBy('RANDOM()').limit(limit);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
let inventories = await qb.getMany();
|
|
103
|
-
if (!inventories.length) {
|
|
104
|
-
throw new Error(`Failed to find inventories`);
|
|
105
|
-
}
|
|
106
|
-
let cycleCountWorksheet = new entities_1.Worksheet();
|
|
107
|
-
cycleCountWorksheet.domain = this.domain;
|
|
108
|
-
cycleCountWorksheet.bizplace = customerBizplace;
|
|
109
|
-
cycleCountWorksheet.name = utils_1.WorksheetNoGenerator.cycleCount();
|
|
110
|
-
cycleCountWorksheet.inventoryCheck = cycleCount;
|
|
111
|
-
cycleCountWorksheet.type = constants_1.WORKSHEET_TYPE.CYCLE_COUNT;
|
|
112
|
-
cycleCountWorksheet.status = constants_1.WORKSHEET_STATUS.DEACTIVATED;
|
|
113
|
-
cycleCountWorksheet.creator = this.user;
|
|
114
|
-
cycleCountWorksheet.updater = this.user;
|
|
115
|
-
cycleCountWorksheet = await this.trxMgr.getRepository(entities_1.Worksheet).save(cycleCountWorksheet);
|
|
116
|
-
// generate order inventory mapping with inventory ID
|
|
117
|
-
let targetInventories = [];
|
|
118
|
-
for (let i = 0; i < inventories.length; i++) {
|
|
119
|
-
const inventory = inventories[i];
|
|
120
|
-
let targetInventory = new sales_base_1.OrderInventory();
|
|
121
|
-
targetInventory.domain = this.domain;
|
|
122
|
-
targetInventory.bizplace = customerBizplace;
|
|
123
|
-
targetInventory.status = sales_base_1.ORDER_INVENTORY_STATUS.PENDING;
|
|
124
|
-
targetInventory.name = sales_base_1.OrderNoGenerator.orderInventory();
|
|
125
|
-
targetInventory.inventoryCheck = cycleCount;
|
|
126
|
-
targetInventory.originQty = inventory.qty;
|
|
127
|
-
targetInventory.originWeight = 0;
|
|
128
|
-
targetInventory.originUomValue = inventory.uomValue;
|
|
129
|
-
targetInventory.originBatchNo = inventory.batchId;
|
|
130
|
-
targetInventory.originLocation = inventory.location;
|
|
131
|
-
targetInventory.releaseQty = 0;
|
|
132
|
-
targetInventory.releaseWeight = 0;
|
|
133
|
-
targetInventory.releaseUomValue = 0;
|
|
134
|
-
targetInventory.inventory = inventory;
|
|
135
|
-
targetInventory.creator = this.user;
|
|
136
|
-
targetInventory.updater = this.user;
|
|
137
|
-
targetInventories.push(targetInventory);
|
|
138
|
-
inventory.lockedQty = inventory.qty;
|
|
139
|
-
inventory.lockedWeight = 0;
|
|
140
|
-
inventory.lockedUomValue = inventory.uomValue;
|
|
141
|
-
inventory.updater = this.user;
|
|
257
|
+
throw new Error('Unfinished cycle count worksheet exists.');
|
|
142
258
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
cycleCountWorksheetDetail.targetInventory = targetInventory;
|
|
154
|
-
cycleCountWorksheetDetail.type = constants_1.WORKSHEET_TYPE.CYCLE_COUNT;
|
|
155
|
-
cycleCountWorksheetDetail.status = constants_1.WORKSHEET_STATUS.DEACTIVATED;
|
|
156
|
-
cycleCountWorksheetDetail.creator = this.user;
|
|
157
|
-
cycleCountWorksheetDetail.updater = this.user;
|
|
158
|
-
cycleCountWorksheetDetails.push(cycleCountWorksheetDetail);
|
|
259
|
+
return await this.createCycleCountWorksheet(customerBizplace, customerId, executionDate, inventoryCheckItem, selectedLocation, limit);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
async generateCycleCountWorksheetCarton(executionDate, customerId, cycleCountNo, cartonIds = [], batchIds = [], productDetailIds = [], locationNames = []) {
|
|
263
|
+
const customerBizplace = await this.trxMgr.getRepository(biz_base_1.Bizplace).findOne(customerId);
|
|
264
|
+
const foundInventoryCheck = await this.trxMgr.getRepository(sales_base_1.InventoryCheck).findOne({
|
|
265
|
+
where: {
|
|
266
|
+
domain: this.domain,
|
|
267
|
+
bizplace: customerBizplace,
|
|
268
|
+
name: cycleCountNo
|
|
159
269
|
}
|
|
160
|
-
|
|
161
|
-
|
|
270
|
+
});
|
|
271
|
+
const worksheetRepository = this.trxMgr.getRepository(entities_1.Worksheet);
|
|
272
|
+
const foundCycleCountWorksheet = await worksheetRepository.findOne({
|
|
273
|
+
where: {
|
|
274
|
+
domain: this.domain,
|
|
275
|
+
bizplace: customerBizplace,
|
|
276
|
+
type: (0, typeorm_1.In)([constants_1.WORKSHEET_TYPE.CYCLE_COUNT, constants_1.WORKSHEET_TYPE.CYCLE_COUNT_RECHECK]),
|
|
277
|
+
status: (0, typeorm_1.Not)(constants_1.WORKSHEET_STATUS.DONE)
|
|
278
|
+
},
|
|
279
|
+
order: {
|
|
280
|
+
checkCount: 'DESC'
|
|
281
|
+
},
|
|
282
|
+
relations: ['worksheetDetails', 'worksheetDetails.targetInventoryCheckItem', 'inventoryCheck']
|
|
283
|
+
});
|
|
284
|
+
const qb = this.trxMgr.getRepository(sales_base_1.InventoryCheckItem).createQueryBuilder('inventoryCheckItem');
|
|
285
|
+
qb.innerJoinAndSelect('inventoryCheckItem.inventory', 'inventory')
|
|
286
|
+
.innerJoinAndSelect('inventoryCheckItem.productDetail', 'productDetail')
|
|
287
|
+
.innerJoinAndSelect('inventoryCheckItem.originLocation', 'location')
|
|
288
|
+
.where('inventory.cartonId IN (:...cartonIds)', { cartonIds })
|
|
289
|
+
.andWhere('inventory.batchId IN (:...batchIds)', { batchIds })
|
|
290
|
+
.andWhere('productDetail.id IN (:...productDetailIds)', { productDetailIds })
|
|
291
|
+
.andWhere('location.name IN (:...locationNames)', { locationNames })
|
|
292
|
+
.andWhere('inventoryCheckItem.domain_id = :domainId', { domainId: this.domain.id })
|
|
293
|
+
.andWhere('inventoryCheckItem.bizplace_id = :bizplaceId', { bizplaceId: customerBizplace.id })
|
|
294
|
+
.andWhere('inventoryCheckItem.inventory_check_id = :inventoryCheckId', {
|
|
295
|
+
inventoryCheckId: foundInventoryCheck.id
|
|
296
|
+
});
|
|
297
|
+
const inventoryCheckItems = await qb.getMany();
|
|
298
|
+
const inventoryCheckItemIds = inventoryCheckItems.map(item => item.id);
|
|
299
|
+
if (inventoryCheckItemIds.length) {
|
|
300
|
+
return await this.createNextRoundCycleCountWorksheet(customerId, foundInventoryCheck, executionDate, foundCycleCountWorksheet, inventoryCheckItemIds);
|
|
162
301
|
}
|
|
163
302
|
}
|
|
164
303
|
async activateCycleCount(worksheetNo) {
|
|
165
304
|
let worksheet = await this.findActivatableWorksheet(worksheetNo, constants_1.WORKSHEET_TYPE.CYCLE_COUNT, [
|
|
166
305
|
'inventoryCheck',
|
|
167
306
|
'worksheetDetails',
|
|
168
|
-
'worksheetDetails.
|
|
307
|
+
'worksheetDetails.targetInventoryCheckItem'
|
|
169
308
|
]);
|
|
170
309
|
let worksheetDetails = worksheet.worksheetDetails;
|
|
171
|
-
let
|
|
172
|
-
for (let i = 0; i <
|
|
173
|
-
let
|
|
174
|
-
|
|
175
|
-
|
|
310
|
+
let targetInventoryCheckItems = worksheetDetails.map((wsd) => wsd.targetInventoryCheckItem);
|
|
311
|
+
for (let i = 0; i < targetInventoryCheckItems.length; i++) {
|
|
312
|
+
let targetInventoryCheckItem = targetInventoryCheckItems[i];
|
|
313
|
+
targetInventoryCheckItem.status = sales_base_1.INVENTORY_CHECK_ITEM_STATUS.INSPECTING;
|
|
314
|
+
targetInventoryCheckItem.updater = this.user;
|
|
176
315
|
}
|
|
177
|
-
await this.trxMgr.getRepository(sales_base_1.
|
|
316
|
+
await this.trxMgr.getRepository(sales_base_1.InventoryCheckItem).save(targetInventoryCheckItems, { chunk: 500 });
|
|
178
317
|
for (let i = 0; i < worksheetDetails.length; i++) {
|
|
179
318
|
let foundWSD = worksheetDetails[i];
|
|
180
319
|
foundWSD.status = constants_1.WORKSHEET_STATUS.EXECUTING;
|
|
@@ -191,91 +330,213 @@ class CycleCountWorksheetController extends worksheet_controller_1.WorksheetCont
|
|
|
191
330
|
await this.updateRefOrder(cycleCount);
|
|
192
331
|
return worksheet;
|
|
193
332
|
}
|
|
194
|
-
async
|
|
195
|
-
let worksheetDetail = await this.findExecutableWorksheetDetailByName(worksheetDetailName, constants_1.WORKSHEET_TYPE.CYCLE_COUNT, ['
|
|
196
|
-
let
|
|
197
|
-
const
|
|
198
|
-
const
|
|
199
|
-
const isChanged = batchId !== inspectedBatchNo || qty !== inspectedQty || uomValue !== inspectedUomValue;
|
|
333
|
+
async inspectingPallet(worksheetDetailName, inspectedBatchNo, inspectedQty, inspectedUomValue) {
|
|
334
|
+
let worksheetDetail = await this.findExecutableWorksheetDetailByName(worksheetDetailName, constants_1.WORKSHEET_TYPE.CYCLE_COUNT, ['targetInventoryCheckItem', 'targetInventoryCheckItem.inventory', 'targetInventoryCheckItem.inventory.location']);
|
|
335
|
+
let targetInventoryCheckItem = worksheetDetail.targetInventoryCheckItem;
|
|
336
|
+
const { originBatchNo, originQty, originUomValue } = targetInventoryCheckItem;
|
|
337
|
+
const isChanged = originBatchNo !== inspectedBatchNo || originQty !== inspectedQty || originUomValue !== inspectedUomValue;
|
|
200
338
|
const worksheetDetailStatus = isChanged ? constants_1.WORKSHEET_STATUS.NOT_TALLY : constants_1.WORKSHEET_STATUS.DONE;
|
|
201
|
-
const
|
|
202
|
-
? sales_base_1.
|
|
203
|
-
: sales_base_1.
|
|
339
|
+
const targetInventoryCheckItemStatus = isChanged
|
|
340
|
+
? sales_base_1.INVENTORY_CHECK_ITEM_STATUS.NOT_TALLY
|
|
341
|
+
: sales_base_1.INVENTORY_CHECK_ITEM_STATUS.INSPECTED;
|
|
204
342
|
worksheetDetail.status = worksheetDetailStatus;
|
|
205
343
|
worksheetDetail.updater = this.user;
|
|
206
344
|
await this.trxMgr.getRepository(entities_1.WorksheetDetail).save(worksheetDetail);
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
await this.updateOrderTargets([
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
345
|
+
targetInventoryCheckItem.inspectedBatchNo = inspectedBatchNo;
|
|
346
|
+
targetInventoryCheckItem.inspectedQty = inspectedQty;
|
|
347
|
+
targetInventoryCheckItem.inspectedUomValue = inspectedUomValue;
|
|
348
|
+
targetInventoryCheckItem.inspectedLocation = targetInventoryCheckItem.inventory.location;
|
|
349
|
+
targetInventoryCheckItem.status = targetInventoryCheckItemStatus;
|
|
350
|
+
targetInventoryCheckItem.updater = this.user;
|
|
351
|
+
await this.updateOrderTargets([targetInventoryCheckItem]);
|
|
352
|
+
}
|
|
353
|
+
async inspectingCarton(productDetailId, cartonId, batchId, locationId, inspectedBatchNo, inspectedQty, inspectedUomValue) {
|
|
354
|
+
var _a, _b, _c, _d;
|
|
355
|
+
const productDetail = await this.trxMgr.getRepository(product_base_1.ProductDetail).findOne({
|
|
356
|
+
where: { id: productDetailId },
|
|
357
|
+
relations: ['product']
|
|
358
|
+
});
|
|
359
|
+
let qb = this.trxMgr
|
|
360
|
+
.getRepository(warehouse_base_1.Inventory)
|
|
361
|
+
.createQueryBuilder('inv')
|
|
362
|
+
.where('inv.product_detail_id = :productDetailId', { productDetailId })
|
|
363
|
+
.andWhere('inv.carton_id = :cartonId', { cartonId })
|
|
364
|
+
.andWhere('inv.batch_id = :batchId', { batchId })
|
|
365
|
+
.andWhere('inv.location_id = :locationId', { locationId });
|
|
366
|
+
let orderByField = 'created_at';
|
|
367
|
+
let orderByDirection = 'ASC';
|
|
368
|
+
switch (productDetail.product.pickingStrategy) {
|
|
369
|
+
case 'LIFO':
|
|
370
|
+
orderByDirection = 'DESC';
|
|
371
|
+
break;
|
|
372
|
+
case 'FEFO':
|
|
373
|
+
orderByField = 'expiration_date';
|
|
374
|
+
break;
|
|
375
|
+
case 'FMFO':
|
|
376
|
+
orderByField = 'manufacture_date';
|
|
377
|
+
break;
|
|
378
|
+
}
|
|
379
|
+
qb.addOrderBy(`"inv"."${orderByField}"`, orderByDirection);
|
|
380
|
+
if (['FEFO', 'FMFO'].includes(productDetail.product.pickingStrategy)) {
|
|
381
|
+
qb.addOrderBy('"inv"."created_at"', 'ASC');
|
|
382
|
+
}
|
|
383
|
+
const inventories = await qb.getMany();
|
|
384
|
+
const inventoryIds = inventories.map(inv => inv.id);
|
|
385
|
+
const inventoryCheckItems = await this.trxMgr
|
|
386
|
+
.getRepository(sales_base_1.InventoryCheckItem)
|
|
387
|
+
.createQueryBuilder('inventoryCheckItem')
|
|
388
|
+
.leftJoinAndSelect('inventoryCheckItem.inventory', 'inventory')
|
|
389
|
+
.where('inventory.id IN (:...ids)', { ids: inventoryIds })
|
|
390
|
+
.andWhere('inventoryCheckItem.status = :status', { status: 'INSPECTING' })
|
|
391
|
+
.getMany();
|
|
392
|
+
const totalOriginQty = inventoryCheckItems.reduce((total, item) => total + (item.originQty || 0), 0);
|
|
393
|
+
const totalOriginUomValue = inventoryCheckItems.reduce((total, item) => total + (item.originUomValue || 0), 0);
|
|
394
|
+
const hasQtyDiscrepancy = totalOriginQty !== inspectedQty;
|
|
395
|
+
const hasUomValueDiscrepancy = totalOriginUomValue !== inspectedUomValue;
|
|
396
|
+
const hasBatchNoDiscrepancy = inventoryCheckItems.some(checkItem => checkItem.originBatchNo !== inspectedBatchNo);
|
|
397
|
+
const hasDiscrepancies = hasQtyDiscrepancy || hasUomValueDiscrepancy || hasBatchNoDiscrepancy;
|
|
398
|
+
let inventoryCheckItemStatus;
|
|
399
|
+
let worksheetDetailStatus;
|
|
400
|
+
if (inventoryCheckItems.length > 1) {
|
|
401
|
+
inventoryCheckItemStatus = hasDiscrepancies
|
|
402
|
+
? sales_base_1.INVENTORY_CHECK_ITEM_STATUS.GROUP_NOT_TALLY
|
|
403
|
+
: sales_base_1.INVENTORY_CHECK_ITEM_STATUS.INSPECTED;
|
|
404
|
+
worksheetDetailStatus = hasDiscrepancies ? constants_1.WORKSHEET_STATUS.NOT_TALLY : constants_1.WORKSHEET_STATUS.DONE;
|
|
405
|
+
}
|
|
406
|
+
else {
|
|
407
|
+
inventoryCheckItemStatus = hasDiscrepancies
|
|
408
|
+
? sales_base_1.INVENTORY_CHECK_ITEM_STATUS.NOT_TALLY
|
|
409
|
+
: sales_base_1.INVENTORY_CHECK_ITEM_STATUS.INSPECTED;
|
|
410
|
+
worksheetDetailStatus = hasDiscrepancies ? constants_1.WORKSHEET_STATUS.NOT_TALLY : constants_1.WORKSHEET_STATUS.DONE;
|
|
411
|
+
}
|
|
412
|
+
let totalInspectedQty = inspectedQty;
|
|
413
|
+
let totalInspectedUomValue = inspectedUomValue;
|
|
414
|
+
for (const checkItem of inventoryCheckItems) {
|
|
415
|
+
const qtyToInspect = totalInspectedQty > 0 ? Math.min(totalInspectedQty, checkItem.originQty) : 0;
|
|
416
|
+
const uomValueToInspect = totalInspectedUomValue > 0 ? Math.min(totalInspectedUomValue, checkItem.originUomValue) : 0;
|
|
417
|
+
checkItem.inspectedQty = ((_a = checkItem.inspectedQty) !== null && _a !== void 0 ? _a : 0) + qtyToInspect;
|
|
418
|
+
totalInspectedQty -= qtyToInspect;
|
|
419
|
+
checkItem.inspectedUomValue = ((_b = checkItem.inspectedUomValue) !== null && _b !== void 0 ? _b : 0) + uomValueToInspect;
|
|
420
|
+
totalInspectedUomValue -= uomValueToInspect;
|
|
421
|
+
checkItem.inspectedBatchNo = inspectedBatchNo;
|
|
422
|
+
checkItem.inspectedLocation = checkItem.originLocationId;
|
|
423
|
+
checkItem.status = inventoryCheckItemStatus;
|
|
424
|
+
checkItem.updater = this.user;
|
|
425
|
+
await this.trxMgr.getRepository(sales_base_1.InventoryCheckItem).save(checkItem);
|
|
426
|
+
let worksheetDetail = await this.trxMgr.getRepository(entities_1.WorksheetDetail).findOne({
|
|
427
|
+
where: { targetInventoryCheckItem: checkItem.id, type: constants_1.WORKSHEET_TYPE.CYCLE_COUNT }
|
|
428
|
+
});
|
|
429
|
+
if (worksheetDetail) {
|
|
430
|
+
worksheetDetail.status = worksheetDetailStatus;
|
|
431
|
+
worksheetDetail.updater = this.user;
|
|
432
|
+
await this.trxMgr.getRepository(entities_1.WorksheetDetail).save(worksheetDetail);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
if (totalInspectedQty > 0 && totalInspectedUomValue > 0 && inventoryCheckItems.length > 0) {
|
|
436
|
+
const lastItem = inventoryCheckItems[inventoryCheckItems.length - 1];
|
|
437
|
+
lastItem.inspectedQty = ((_c = lastItem.inspectedQty) !== null && _c !== void 0 ? _c : 0) + totalInspectedQty;
|
|
438
|
+
lastItem.inspectedUomValue = ((_d = lastItem.inspectedUomValue) !== null && _d !== void 0 ? _d : 0) + totalInspectedUomValue;
|
|
439
|
+
await this.trxMgr.getRepository(sales_base_1.InventoryCheckItem).save(lastItem);
|
|
221
440
|
}
|
|
222
441
|
}
|
|
223
442
|
async undoInspection(worksheetDetailName) {
|
|
224
|
-
let worksheetDetail = await this.findWorksheetDetail({ domain: this.domain, name: worksheetDetailName, status: (0, typeorm_1.Not)((0, typeorm_1.Equal)(constants_1.WORKSHEET_STATUS.EXECUTING)) }, ['
|
|
225
|
-
let
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
? sales_base_1.
|
|
234
|
-
: sales_base_1.
|
|
235
|
-
|
|
236
|
-
await this.updateOrderTargets([
|
|
443
|
+
let worksheetDetail = await this.findWorksheetDetail({ domain: this.domain, name: worksheetDetailName, status: (0, typeorm_1.Not)((0, typeorm_1.Equal)(constants_1.WORKSHEET_STATUS.EXECUTING)) }, ['targetInventoryCheckItem', 'targetInventoryCheckItem.inventory']);
|
|
444
|
+
let targetInventoryCheckItem = worksheetDetail.targetInventoryCheckItem;
|
|
445
|
+
targetInventoryCheckItem.inspectedBatchNo = null;
|
|
446
|
+
targetInventoryCheckItem.inspectedQty = null;
|
|
447
|
+
targetInventoryCheckItem.inspectedWeight = null;
|
|
448
|
+
targetInventoryCheckItem.inspectedUomValue = null;
|
|
449
|
+
targetInventoryCheckItem.inspectedLocation = null;
|
|
450
|
+
targetInventoryCheckItem.status =
|
|
451
|
+
targetInventoryCheckItem.status === sales_base_1.INVENTORY_CHECK_ITEM_STATUS.RELOCATED
|
|
452
|
+
? sales_base_1.INVENTORY_CHECK_ITEM_STATUS.MISSING
|
|
453
|
+
: sales_base_1.INVENTORY_CHECK_ITEM_STATUS.INSPECTING;
|
|
454
|
+
targetInventoryCheckItem.updater = this.user;
|
|
455
|
+
await this.updateOrderTargets([targetInventoryCheckItem]);
|
|
237
456
|
worksheetDetail.status =
|
|
238
|
-
|
|
457
|
+
targetInventoryCheckItem.status === sales_base_1.INVENTORY_CHECK_ITEM_STATUS.MISSING
|
|
239
458
|
? constants_1.WORKSHEET_STATUS.NOT_TALLY
|
|
240
459
|
: constants_1.WORKSHEET_STATUS.EXECUTING;
|
|
241
460
|
worksheetDetail.updater = this.user;
|
|
242
461
|
await this.trxMgr.getRepository(entities_1.WorksheetDetail).save(worksheetDetail);
|
|
243
|
-
const inventory = targetInventory.inventory;
|
|
244
|
-
inventory.lockedQty = inventory.qty;
|
|
245
|
-
inventory.lockedWeight = inventory.weight;
|
|
246
|
-
inventory.lockedUomValue = inventory.uomValue;
|
|
247
|
-
inventory.updater = this.user;
|
|
248
|
-
await this.trxMgr.getRepository(warehouse_base_1.Inventory).save(inventory, { chunk: 500 });
|
|
249
462
|
}
|
|
250
|
-
async
|
|
251
|
-
let
|
|
252
|
-
|
|
463
|
+
async undoInspectionCarton(productDetailId, cartonId, batchId, locationId) {
|
|
464
|
+
let qb = this.trxMgr.getRepository(warehouse_base_1.Inventory).createQueryBuilder('inv');
|
|
465
|
+
qb.where('inv.product_detail_id = :productDetailId', { productDetailId })
|
|
466
|
+
.andWhere('inv.carton_id = :cartonId', { cartonId })
|
|
467
|
+
.andWhere('inv.batch_id = :batchId', { batchId })
|
|
468
|
+
.andWhere('inv.location_id = :locationId', { locationId });
|
|
469
|
+
const inventories = await qb.getMany();
|
|
470
|
+
const inventoryCheckItems = await Promise.all(inventories.map(inventory => this.trxMgr.getRepository(sales_base_1.InventoryCheckItem).findOne({ where: { inventory: inventory.id } })));
|
|
471
|
+
for (const checkItem of inventoryCheckItems) {
|
|
472
|
+
checkItem.inspectedBatchNo = null;
|
|
473
|
+
checkItem.inspectedQty = null;
|
|
474
|
+
checkItem.inspectedWeight = null;
|
|
475
|
+
checkItem.inspectedUomValue = null;
|
|
476
|
+
checkItem.inspectedLocation = null;
|
|
477
|
+
checkItem.status = sales_base_1.INVENTORY_CHECK_ITEM_STATUS.INSPECTING;
|
|
478
|
+
checkItem.updater = this.user;
|
|
479
|
+
let worksheetDetail = await this.trxMgr.getRepository(entities_1.WorksheetDetail).findOne({
|
|
480
|
+
where: { targetInventoryCheckItem: checkItem.id, type: constants_1.WORKSHEET_TYPE.CYCLE_COUNT },
|
|
481
|
+
relations: ['targetInventoryCheckItem']
|
|
482
|
+
});
|
|
483
|
+
if (worksheetDetail) {
|
|
484
|
+
worksheetDetail.status = constants_1.WORKSHEET_STATUS.EXECUTING;
|
|
485
|
+
worksheetDetail.updater = this.user;
|
|
486
|
+
await this.trxMgr.getRepository(entities_1.WorksheetDetail).save(worksheetDetail);
|
|
487
|
+
}
|
|
488
|
+
await this.trxMgr.getRepository(sales_base_1.InventoryCheckItem).save(checkItem);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
async checkMissingInventory(worksheetDetailName) {
|
|
492
|
+
let worksheetDetail = await this.findExecutableWorksheetDetailByName(worksheetDetailName, constants_1.WORKSHEET_TYPE.CYCLE_COUNT, ['targetInventoryCheckItem']);
|
|
493
|
+
let targetInventoryCheckItem = worksheetDetail.targetInventoryCheckItem;
|
|
253
494
|
worksheetDetail.status = constants_1.WORKSHEET_STATUS.NOT_TALLY;
|
|
254
495
|
worksheetDetail.updater = this.user;
|
|
255
496
|
await this.trxMgr.getRepository(entities_1.WorksheetDetail).save(worksheetDetail);
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
await this.updateOrderTargets([
|
|
497
|
+
targetInventoryCheckItem.status = sales_base_1.INVENTORY_CHECK_ITEM_STATUS.MISSING;
|
|
498
|
+
targetInventoryCheckItem.updater = this.user;
|
|
499
|
+
await this.updateOrderTargets([targetInventoryCheckItem]);
|
|
259
500
|
}
|
|
260
|
-
async
|
|
501
|
+
async checkMissingInventoryCarton(productDetailId, cartonId, batchId, locationId) {
|
|
502
|
+
let qb = this.trxMgr.getRepository(warehouse_base_1.Inventory).createQueryBuilder('inv');
|
|
503
|
+
qb.where('inv.product_detail_id = :productDetailId', { productDetailId })
|
|
504
|
+
.andWhere('inv.carton_id = :cartonId', { cartonId })
|
|
505
|
+
.andWhere('inv.batch_id = :batchId', { batchId })
|
|
506
|
+
.andWhere('inv.location_id = :locationId', { locationId });
|
|
507
|
+
const inventories = await qb.getMany();
|
|
508
|
+
const inventoryCheckItems = await Promise.all(inventories.map(inventory => this.trxMgr.getRepository(sales_base_1.InventoryCheckItem).findOne({ where: { inventory: inventory.id } })));
|
|
509
|
+
for (const checkItem of inventoryCheckItems) {
|
|
510
|
+
checkItem.inspectedBatchNo = null;
|
|
511
|
+
checkItem.inspectedQty = null;
|
|
512
|
+
checkItem.inspectedWeight = null;
|
|
513
|
+
checkItem.inspectedUomValue = null;
|
|
514
|
+
checkItem.inspectedLocation = null;
|
|
515
|
+
checkItem.status = sales_base_1.INVENTORY_CHECK_ITEM_STATUS.MISSING;
|
|
516
|
+
checkItem.updater = this.user;
|
|
517
|
+
let worksheetDetail = await this.trxMgr.getRepository(entities_1.WorksheetDetail).findOne({
|
|
518
|
+
where: { targetInventoryCheckItem: checkItem.id, type: constants_1.WORKSHEET_TYPE.CYCLE_COUNT },
|
|
519
|
+
relations: ['targetInventoryCheckItem']
|
|
520
|
+
});
|
|
521
|
+
if (worksheetDetail) {
|
|
522
|
+
worksheetDetail.status = constants_1.WORKSHEET_STATUS.NOT_TALLY;
|
|
523
|
+
worksheetDetail.updater = this.user;
|
|
524
|
+
await this.trxMgr.getRepository(entities_1.WorksheetDetail).save(worksheetDetail);
|
|
525
|
+
}
|
|
526
|
+
await this.trxMgr.getRepository(sales_base_1.InventoryCheckItem).save(checkItem);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
async addExtraInventory(cycleCountNo, inspectedLocation, productDetailId, productId, inspectedBatchNo, inspectedQty, inspectedUomValue, countNo) {
|
|
530
|
+
var _a;
|
|
531
|
+
let today = new Date(), year = today.getFullYear(), month = today.getMonth(), date = today.getDate();
|
|
261
532
|
const inventoryCheck = await this.findRefOrder(sales_base_1.InventoryCheck, {
|
|
262
533
|
name: cycleCountNo,
|
|
263
534
|
status: sales_base_1.ORDER_STATUS.INSPECTING
|
|
264
|
-
}, ['bizplace']);
|
|
265
|
-
const bizplace =
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
.andWhere('INV.bizplace = :bizplaceId', { bizplaceId: bizplace.id })
|
|
270
|
-
.andWhere('INV.palletId = :palletId', { palletId })
|
|
271
|
-
.andWhere('INV.status = :status', { status: warehouse_base_1.INVENTORY_STATUS.STORED })
|
|
272
|
-
.andWhere(new typeorm_1.Brackets(qb => {
|
|
273
|
-
qb.where('INV.lockedQty ISNULL');
|
|
274
|
-
qb.orWhere('INV.lockedQty = 0');
|
|
275
|
-
}))
|
|
276
|
-
.getOne();
|
|
277
|
-
if (!inventory)
|
|
278
|
-
throw new Error('Failed to find inventory');
|
|
535
|
+
}, ['bizplace', 'bizplace.domain']);
|
|
536
|
+
const bizplace = await this.trxMgr.getRepository(biz_base_1.Bizplace).findOne({
|
|
537
|
+
where: { id: inventoryCheck.bizplace.id },
|
|
538
|
+
relations: ['domain']
|
|
539
|
+
});
|
|
279
540
|
const worksheet = await this.trxMgr.getRepository(entities_1.Worksheet).findOne({
|
|
280
541
|
where: {
|
|
281
542
|
domain: this.domain,
|
|
@@ -285,45 +546,113 @@ class CycleCountWorksheetController extends worksheet_controller_1.WorksheetCont
|
|
|
285
546
|
}
|
|
286
547
|
});
|
|
287
548
|
const location = await this.trxMgr.getRepository(warehouse_base_1.Location).findOne({
|
|
288
|
-
where: { domain: this.domain, name:
|
|
549
|
+
where: { domain: this.domain, name: inspectedLocation },
|
|
550
|
+
relations: ['warehouse']
|
|
551
|
+
});
|
|
552
|
+
const productDetail = await this.trxMgr.getRepository(product_base_1.ProductDetail).findOne({
|
|
553
|
+
where: { id: productDetailId }
|
|
554
|
+
});
|
|
555
|
+
const product = await this.trxMgr.getRepository(product_base_1.Product).findOne({
|
|
556
|
+
where: { id: productId }
|
|
557
|
+
});
|
|
558
|
+
const total = await this.trxMgr.getRepository(warehouse_base_1.Inventory).count({
|
|
559
|
+
createdAt: (0, typeorm_1.MoreThan)(new Date(year, month, date))
|
|
560
|
+
});
|
|
561
|
+
const yy = String(year).substr(String(year).length - 2);
|
|
562
|
+
const mm = String(month + 1).padStart(2, '0');
|
|
563
|
+
const dd = String(date).padStart(2, '0');
|
|
564
|
+
const dateStr = yy + mm + dd;
|
|
565
|
+
let newInventory = new warehouse_base_1.Inventory();
|
|
566
|
+
newInventory.bizplace = bizplace;
|
|
567
|
+
newInventory.domain = this.domain;
|
|
568
|
+
newInventory.name = warehouse_base_1.InventoryNoGenerator.inventoryName();
|
|
569
|
+
newInventory.palletId = await (0, id_rule_base_1.generateId)({
|
|
570
|
+
domain: this.domain,
|
|
571
|
+
type: 'adjustment_pallet_id',
|
|
572
|
+
seed: {
|
|
573
|
+
batchId: inspectedBatchNo,
|
|
574
|
+
date: dateStr
|
|
575
|
+
}
|
|
576
|
+
});
|
|
577
|
+
const warehouseCartonSetting = await this.trxMgr.getRepository(setting_base_1.Setting).findOne({
|
|
578
|
+
where: { domain: this.domain, category: 'id-rule', name: 'enable-carton-label', value: true }
|
|
579
|
+
});
|
|
580
|
+
const partnerCartonSetting = await this.trxMgr.getRepository(setting_base_1.PartnerSetting).findOne({
|
|
581
|
+
where: {
|
|
582
|
+
setting: warehouseCartonSetting,
|
|
583
|
+
domain: this.domain,
|
|
584
|
+
partnerDomain: (_a = inventoryCheck.bizplace) === null || _a === void 0 ? void 0 : _a.domain,
|
|
585
|
+
value: true
|
|
586
|
+
}
|
|
289
587
|
});
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
588
|
+
if ((partnerCartonSetting === null || partnerCartonSetting === void 0 ? void 0 : partnerCartonSetting.value) || (warehouseCartonSetting === null || warehouseCartonSetting === void 0 ? void 0 : warehouseCartonSetting.value)) {
|
|
589
|
+
let cartonId = await (0, id_rule_base_1.generateId)({
|
|
590
|
+
domain: this.domain,
|
|
591
|
+
type: 'adjustment_carton_id',
|
|
592
|
+
seed: { date: dateStr }
|
|
593
|
+
});
|
|
594
|
+
if (!cartonId)
|
|
595
|
+
throw new Error('No adjustment carton id setting rule found');
|
|
596
|
+
newInventory.cartonId = cartonId;
|
|
597
|
+
}
|
|
598
|
+
newInventory.batchId = inspectedBatchNo;
|
|
599
|
+
newInventory.product = product;
|
|
600
|
+
newInventory.productDetail = productDetail;
|
|
601
|
+
newInventory.packingType = productDetail.packingType;
|
|
602
|
+
newInventory.packingSize = productDetail.packingSize;
|
|
603
|
+
newInventory.uom = productDetail.uom;
|
|
604
|
+
newInventory.qty = inspectedQty;
|
|
605
|
+
newInventory.uomValue = inspectedUomValue;
|
|
606
|
+
newInventory.location = location;
|
|
607
|
+
newInventory.warehouse = location.warehouse;
|
|
608
|
+
newInventory.zone = location.zone;
|
|
609
|
+
newInventory.status = warehouse_base_1.INVENTORY_STATUS.CC_ADDED;
|
|
610
|
+
newInventory.creator = this.user;
|
|
611
|
+
newInventory.updater = this.user;
|
|
612
|
+
await this.trxMgr.getRepository(warehouse_base_1.Inventory).save(newInventory);
|
|
613
|
+
let targetInventoryCheckItem = new sales_base_1.InventoryCheckItem();
|
|
614
|
+
targetInventoryCheckItem.domain = this.domain;
|
|
615
|
+
targetInventoryCheckItem.bizplace = bizplace;
|
|
616
|
+
targetInventoryCheckItem.status = sales_base_1.INVENTORY_CHECK_ITEM_STATUS.ADDED;
|
|
617
|
+
targetInventoryCheckItem.name = sales_base_1.OrderNoGenerator.inventoryCheckItem();
|
|
618
|
+
targetInventoryCheckItem.inventoryCheck = inventoryCheck;
|
|
619
|
+
targetInventoryCheckItem.inventory = newInventory;
|
|
620
|
+
targetInventoryCheckItem.inspectedBatchNo = inspectedBatchNo;
|
|
621
|
+
targetInventoryCheckItem.inspectedQty = inspectedQty;
|
|
622
|
+
targetInventoryCheckItem.inspectedUomValue = inspectedUomValue;
|
|
623
|
+
targetInventoryCheckItem.inspectedLocation = location;
|
|
624
|
+
targetInventoryCheckItem.productDetail = productDetail;
|
|
625
|
+
targetInventoryCheckItem.product = product;
|
|
626
|
+
targetInventoryCheckItem.countNo = countNo;
|
|
627
|
+
targetInventoryCheckItem.creator = this.user;
|
|
628
|
+
targetInventoryCheckItem.updater = this.user;
|
|
629
|
+
await this.trxMgr.getRepository(sales_base_1.InventoryCheckItem).save(targetInventoryCheckItem);
|
|
305
630
|
let worksheetDetail = new entities_1.WorksheetDetail();
|
|
306
631
|
worksheetDetail.domain = this.domain;
|
|
307
632
|
worksheetDetail.bizplace = bizplace;
|
|
308
633
|
worksheetDetail.worksheet = worksheet;
|
|
309
634
|
worksheetDetail.name = utils_1.WorksheetNoGenerator.cycleCountDetail();
|
|
310
|
-
worksheetDetail.
|
|
635
|
+
worksheetDetail.targetInventoryCheckItem = targetInventoryCheckItem;
|
|
311
636
|
worksheetDetail.type = constants_1.WORKSHEET_TYPE.CYCLE_COUNT;
|
|
312
637
|
worksheetDetail.status = constants_1.WORKSHEET_STATUS.NOT_TALLY;
|
|
313
638
|
worksheetDetail.creator = this.user;
|
|
314
639
|
worksheetDetail.updater = this.user;
|
|
315
640
|
await this.trxMgr.getRepository(entities_1.WorksheetDetail).save(worksheetDetail);
|
|
316
641
|
}
|
|
317
|
-
async
|
|
642
|
+
async relocateInventory(worksheetDetailName, inspectedBatchNo, inspectedQty, inspectedUomValue, inspectedLocationName) {
|
|
318
643
|
var _a;
|
|
319
644
|
let worksheetDetail = await this.trxMgr.getRepository(entities_1.WorksheetDetail).findOne({
|
|
320
645
|
where: { domain: this.domain, name: worksheetDetailName, type: constants_1.WORKSHEET_TYPE.CYCLE_COUNT },
|
|
321
|
-
relations: [
|
|
646
|
+
relations: [
|
|
647
|
+
'targetInventoryCheckItem',
|
|
648
|
+
'targetInventoryCheckItem.inventory',
|
|
649
|
+
'targetInventoryCheckItem.inventory.location'
|
|
650
|
+
]
|
|
322
651
|
});
|
|
323
652
|
if (!worksheetDetail)
|
|
324
653
|
throw new Error('Failed to find worksheet detail');
|
|
325
|
-
let
|
|
326
|
-
const location = (_a =
|
|
654
|
+
let targetInventoryCheckItem = worksheetDetail.targetInventoryCheckItem;
|
|
655
|
+
const location = (_a = targetInventoryCheckItem === null || targetInventoryCheckItem === void 0 ? void 0 : targetInventoryCheckItem.inventory) === null || _a === void 0 ? void 0 : _a.location;
|
|
327
656
|
if (location.name === inspectedLocationName)
|
|
328
657
|
throw new Error(`You can't relocate at same location`);
|
|
329
658
|
const inspectedLocation = await this.trxMgr.getRepository(warehouse_base_1.Location).findOne({
|
|
@@ -332,14 +661,121 @@ class CycleCountWorksheetController extends worksheet_controller_1.WorksheetCont
|
|
|
332
661
|
worksheetDetail.status = constants_1.WORKSHEET_STATUS.NOT_TALLY;
|
|
333
662
|
worksheetDetail.updater = this.user;
|
|
334
663
|
await this.trxMgr.getRepository(entities_1.WorksheetDetail).save(worksheetDetail);
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
await this.updateOrderTargets([
|
|
664
|
+
targetInventoryCheckItem.inspectedLocation = inspectedLocation;
|
|
665
|
+
targetInventoryCheckItem.inspectedBatchNo = inspectedBatchNo;
|
|
666
|
+
targetInventoryCheckItem.inspectedQty = inspectedQty;
|
|
667
|
+
targetInventoryCheckItem.inspectedWeight = 0;
|
|
668
|
+
targetInventoryCheckItem.inspectedUomValue = inspectedUomValue;
|
|
669
|
+
targetInventoryCheckItem.status = sales_base_1.INVENTORY_CHECK_ITEM_STATUS.RELOCATED;
|
|
670
|
+
targetInventoryCheckItem.updater = this.user;
|
|
671
|
+
await this.updateOrderTargets([targetInventoryCheckItem]);
|
|
672
|
+
}
|
|
673
|
+
async relocateInventoryCarton(productDetailId, cartonId, batchId, locationId, inspectedBatchNo, inspectedQty, inspectedUomValue, inspectedLocationName) {
|
|
674
|
+
var _a, _b, _c, _d;
|
|
675
|
+
const productDetail = await this.trxMgr.getRepository(product_base_1.ProductDetail).findOne({
|
|
676
|
+
where: { id: productDetailId },
|
|
677
|
+
relations: ['product']
|
|
678
|
+
});
|
|
679
|
+
let qb = this.trxMgr
|
|
680
|
+
.getRepository(warehouse_base_1.Inventory)
|
|
681
|
+
.createQueryBuilder('inv')
|
|
682
|
+
.where('inv.product_detail_id = :productDetailId', { productDetailId })
|
|
683
|
+
.andWhere('inv.carton_id = :cartonId', { cartonId })
|
|
684
|
+
.andWhere('inv.batch_id = :batchId', { batchId })
|
|
685
|
+
.andWhere('inv.location_id = :locationId', { locationId });
|
|
686
|
+
let orderByField = 'created_at';
|
|
687
|
+
let orderByDirection = 'ASC';
|
|
688
|
+
switch (productDetail.product.pickingStrategy) {
|
|
689
|
+
case 'LIFO':
|
|
690
|
+
orderByDirection = 'DESC';
|
|
691
|
+
break;
|
|
692
|
+
case 'FEFO':
|
|
693
|
+
orderByField = 'expiration_date';
|
|
694
|
+
break;
|
|
695
|
+
case 'FMFO':
|
|
696
|
+
orderByField = 'manufacture_date';
|
|
697
|
+
break;
|
|
698
|
+
}
|
|
699
|
+
qb.addOrderBy(`"inv"."${orderByField}"`, orderByDirection);
|
|
700
|
+
if (['FEFO', 'FMFO'].includes(productDetail.product.pickingStrategy)) {
|
|
701
|
+
qb.addOrderBy('"inv"."created_at"', 'ASC');
|
|
702
|
+
}
|
|
703
|
+
const inventories = await qb.getMany();
|
|
704
|
+
if (inventories.length === 0) {
|
|
705
|
+
throw new Error('No inventories found.');
|
|
706
|
+
}
|
|
707
|
+
const location = await this.trxMgr.getRepository(warehouse_base_1.Location).findOne({
|
|
708
|
+
where: { id: locationId }
|
|
709
|
+
});
|
|
710
|
+
if (location.name === inspectedLocationName) {
|
|
711
|
+
throw new Error(`You can't relocate to the same location.`);
|
|
712
|
+
}
|
|
713
|
+
const inspectedLocation = await this.trxMgr.getRepository(warehouse_base_1.Location).findOne({
|
|
714
|
+
where: { name: inspectedLocationName, domain: this.domain }
|
|
715
|
+
});
|
|
716
|
+
if (!inspectedLocation) {
|
|
717
|
+
throw new Error(`Inspected location "${inspectedLocationName}" not found.`);
|
|
718
|
+
}
|
|
719
|
+
const inventoryIds = inventories.map(inv => inv.id);
|
|
720
|
+
const inventoryCheckItems = await this.trxMgr
|
|
721
|
+
.getRepository(sales_base_1.InventoryCheckItem)
|
|
722
|
+
.createQueryBuilder('inventoryCheckItem')
|
|
723
|
+
.leftJoinAndSelect('inventoryCheckItem.inventory', 'inventory')
|
|
724
|
+
.where('inventory.id IN (:...ids)', { ids: inventoryIds })
|
|
725
|
+
.andWhere('inventoryCheckItem.status = :status', { status: 'INSPECTING' })
|
|
726
|
+
.getMany();
|
|
727
|
+
if (inventoryCheckItems.length === 0) {
|
|
728
|
+
throw new Error('No inventory check items found.');
|
|
729
|
+
}
|
|
730
|
+
const totalOriginQty = inventoryCheckItems.reduce((total, item) => total + (item.originQty || 0), 0);
|
|
731
|
+
const totalOriginUomValue = inventoryCheckItems.reduce((total, item) => total + (item.originUomValue || 0), 0);
|
|
732
|
+
const hasQtyDiscrepancy = totalOriginQty !== inspectedQty;
|
|
733
|
+
const hasUomValueDiscrepancy = totalOriginUomValue !== inspectedUomValue;
|
|
734
|
+
const hasBatchNoDiscrepancy = inventoryCheckItems.some(checkItem => checkItem.originBatchNo !== inspectedBatchNo);
|
|
735
|
+
const hasLocationDiscrepancy = inventoryCheckItems.some(checkItem => checkItem.originLocationId !== inspectedLocation.id);
|
|
736
|
+
const hasDiscrepancies = hasQtyDiscrepancy || hasUomValueDiscrepancy || hasBatchNoDiscrepancy || hasLocationDiscrepancy;
|
|
737
|
+
let inventoryCheckItemStatus, worksheetDetailStatus;
|
|
738
|
+
if (inventoryCheckItems.length > 1) {
|
|
739
|
+
inventoryCheckItemStatus = hasDiscrepancies
|
|
740
|
+
? sales_base_1.INVENTORY_CHECK_ITEM_STATUS.RELOCATED
|
|
741
|
+
: sales_base_1.INVENTORY_CHECK_ITEM_STATUS.INSPECTED;
|
|
742
|
+
worksheetDetailStatus = hasDiscrepancies ? constants_1.WORKSHEET_STATUS.NOT_TALLY : constants_1.WORKSHEET_STATUS.DONE;
|
|
743
|
+
}
|
|
744
|
+
else {
|
|
745
|
+
inventoryCheckItemStatus = hasDiscrepancies
|
|
746
|
+
? sales_base_1.INVENTORY_CHECK_ITEM_STATUS.RELOCATED
|
|
747
|
+
: sales_base_1.INVENTORY_CHECK_ITEM_STATUS.INSPECTED;
|
|
748
|
+
worksheetDetailStatus = hasDiscrepancies ? constants_1.WORKSHEET_STATUS.NOT_TALLY : constants_1.WORKSHEET_STATUS.DONE;
|
|
749
|
+
}
|
|
750
|
+
let totalInspectedQty = inspectedQty;
|
|
751
|
+
let totalInspectedUomValue = inspectedUomValue;
|
|
752
|
+
for (const checkItem of inventoryCheckItems) {
|
|
753
|
+
const qtyToInspect = totalInspectedQty > 0 ? Math.min(totalInspectedQty, checkItem.originQty) : 0;
|
|
754
|
+
const uomValueToInspect = totalInspectedUomValue > 0 ? Math.min(totalInspectedUomValue, checkItem.originUomValue) : 0;
|
|
755
|
+
checkItem.inspectedQty = ((_a = checkItem.inspectedQty) !== null && _a !== void 0 ? _a : 0) + qtyToInspect;
|
|
756
|
+
totalInspectedQty -= qtyToInspect;
|
|
757
|
+
checkItem.inspectedUomValue = ((_b = checkItem.inspectedUomValue) !== null && _b !== void 0 ? _b : 0) + uomValueToInspect;
|
|
758
|
+
totalInspectedUomValue -= uomValueToInspect;
|
|
759
|
+
checkItem.inspectedBatchNo = inspectedBatchNo;
|
|
760
|
+
checkItem.inspectedLocation = inspectedLocation;
|
|
761
|
+
checkItem.status = inventoryCheckItemStatus;
|
|
762
|
+
checkItem.updater = this.user;
|
|
763
|
+
await this.trxMgr.getRepository(sales_base_1.InventoryCheckItem).save(checkItem);
|
|
764
|
+
let worksheetDetail = await this.trxMgr.getRepository(entities_1.WorksheetDetail).findOne({
|
|
765
|
+
where: { targetInventoryCheckItem: checkItem.id, type: constants_1.WORKSHEET_TYPE.CYCLE_COUNT }
|
|
766
|
+
});
|
|
767
|
+
if (worksheetDetail) {
|
|
768
|
+
worksheetDetail.status = worksheetDetailStatus;
|
|
769
|
+
worksheetDetail.updater = this.user;
|
|
770
|
+
await this.trxMgr.getRepository(entities_1.WorksheetDetail).save(worksheetDetail);
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
if (totalInspectedQty > 0 && totalInspectedUomValue > 0 && inventoryCheckItems.length > 0) {
|
|
774
|
+
const lastItem = inventoryCheckItems[inventoryCheckItems.length - 1];
|
|
775
|
+
lastItem.inspectedQty = ((_c = lastItem.inspectedQty) !== null && _c !== void 0 ? _c : 0) + totalInspectedQty;
|
|
776
|
+
lastItem.inspectedUomValue = ((_d = lastItem.inspectedUomValue) !== null && _d !== void 0 ? _d : 0) + totalInspectedUomValue;
|
|
777
|
+
await this.trxMgr.getRepository(sales_base_1.InventoryCheckItem).save(lastItem);
|
|
778
|
+
}
|
|
343
779
|
}
|
|
344
780
|
async completeCycleCount(inventoryCheckNo) {
|
|
345
781
|
const inventoryCheck = await this.findRefOrder(sales_base_1.InventoryCheck, {
|
|
@@ -353,37 +789,35 @@ class CycleCountWorksheetController extends worksheet_controller_1.WorksheetCont
|
|
|
353
789
|
type: (0, typeorm_1.In)([constants_1.WORKSHEET_TYPE.CYCLE_COUNT, constants_1.WORKSHEET_TYPE.CYCLE_COUNT_RECHECK]),
|
|
354
790
|
inventoryCheck
|
|
355
791
|
},
|
|
356
|
-
relations: [
|
|
792
|
+
relations: [
|
|
793
|
+
'worksheetDetails',
|
|
794
|
+
'worksheetDetails.targetInventoryCheckItem',
|
|
795
|
+
'worksheetDetails.targetInventoryCheckItem.inventory'
|
|
796
|
+
]
|
|
357
797
|
});
|
|
358
798
|
this.checkRecordValidity(worksheet, { status: constants_1.WORKSHEET_STATUS.EXECUTING });
|
|
359
799
|
const worksheetDetails = worksheet.worksheetDetails;
|
|
360
|
-
const
|
|
361
|
-
const {
|
|
362
|
-
if (
|
|
363
|
-
result.
|
|
800
|
+
const targetInventoryCheckItems = worksheetDetails.map((wsd) => wsd.targetInventoryCheckItem);
|
|
801
|
+
const { tallyTargetInventoryCheckItems, notTallyTargetInventoryCheckItems } = targetInventoryCheckItems.reduce((result, targetInventoryCheckItem) => {
|
|
802
|
+
if (targetInventoryCheckItem.status !== sales_base_1.INVENTORY_CHECK_ITEM_STATUS.INSPECTED) {
|
|
803
|
+
result.notTallyTargetInventoryCheckItems.push(targetInventoryCheckItem);
|
|
364
804
|
}
|
|
365
805
|
else {
|
|
366
|
-
result.
|
|
806
|
+
result.tallyTargetInventoryCheckItems.push(targetInventoryCheckItem);
|
|
367
807
|
}
|
|
368
808
|
return result;
|
|
369
809
|
}, {
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
});
|
|
373
|
-
const tallyInventories = tallyTargetInventories.map(targetInventory => targetInventory.inventory);
|
|
374
|
-
tallyTargetInventories.forEach((targetInventory) => {
|
|
375
|
-
targetInventory.status = sales_base_1.ORDER_INVENTORY_STATUS.TERMINATED;
|
|
376
|
-
targetInventory.updater = this.user;
|
|
810
|
+
tallyTargetInventoryCheckItems: [],
|
|
811
|
+
notTallyTargetInventoryCheckItems: []
|
|
377
812
|
});
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
inventory.lockedUomValue = 0;
|
|
383
|
-
inventory.updater = this.user;
|
|
813
|
+
const tallyInventories = tallyTargetInventoryCheckItems.map(targetInventoryCheckItem => targetInventoryCheckItem.inventory);
|
|
814
|
+
tallyTargetInventoryCheckItems.forEach((targetInventoryCheckItem) => {
|
|
815
|
+
targetInventoryCheckItem.status = sales_base_1.INVENTORY_CHECK_ITEM_STATUS.TERMINATED;
|
|
816
|
+
targetInventoryCheckItem.updater = this.user;
|
|
384
817
|
});
|
|
818
|
+
await this.trxMgr.getRepository(sales_base_1.InventoryCheckItem).save(tallyTargetInventoryCheckItems, { chunk: 500 });
|
|
385
819
|
await this.trxMgr.getRepository(warehouse_base_1.Inventory).save(tallyInventories, { chunk: 500 });
|
|
386
|
-
if (
|
|
820
|
+
if (notTallyTargetInventoryCheckItems.length) {
|
|
387
821
|
worksheet.status = constants_1.WORKSHEET_STATUS.NOT_TALLY;
|
|
388
822
|
inventoryCheck.status = sales_base_1.ORDER_STATUS.PENDING_REVIEW;
|
|
389
823
|
}
|