@things-factory/worksheet-base 4.3.755 → 4.3.756

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.
@@ -1,179 +1,266 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.findSortingReleaseOrdersByTaskNoResolver = void 0;
4
- const typeorm_1 = require("typeorm");
5
4
  const sales_base_1 = require("@things-factory/sales-base");
6
- const shell_1 = require("@things-factory/shell");
7
5
  const auth_base_1 = require("@things-factory/auth-base");
8
- const warehouse_base_1 = require("@things-factory/warehouse-base");
9
6
  const controllers_1 = require("../../../controllers/");
10
7
  const setting_base_1 = require("@things-factory/setting-base");
11
8
  const constants_1 = require("../../../constants");
12
9
  const entities_1 = require("../../../entities");
10
+ // Simple in-memory cache for settings with TTL
11
+ const settingsCache = new Map();
12
+ const SETTINGS_CACHE_TTL = 5 * 60 * 1000; // 5 minutes
13
+ /**
14
+ * Get setting with caching to avoid repeated database queries
15
+ */
16
+ async function getCachedSetting(tx, domain, category, name) {
17
+ const cacheKey = `${domain.id}:${category}:${name}`;
18
+ const cached = settingsCache.get(cacheKey);
19
+ if (cached && cached.expiry > Date.now()) {
20
+ return cached.value;
21
+ }
22
+ const setting = await tx.getRepository(setting_base_1.Setting).findOne({
23
+ where: { domain, category, name }
24
+ });
25
+ settingsCache.set(cacheKey, { value: setting || null, expiry: Date.now() + SETTINGS_CACHE_TTL });
26
+ return setting || null;
27
+ }
28
+ /**
29
+ * Find worksheet by release good name - returns task info if found
30
+ */
31
+ async function findWorksheetByReleaseGoodName(tx, domain, taskNo) {
32
+ const result = await tx
33
+ .getRepository(entities_1.Worksheet)
34
+ .createQueryBuilder('ws')
35
+ .select('ws.task_no', 'taskNo')
36
+ .addSelect('ws.status', 'wsStatus')
37
+ .addSelect('rg.name', 'releaseGoodName')
38
+ .addSelect('rg.status', 'releaseGoodStatus')
39
+ .innerJoin('worksheet_details', 'wd', `ws.id = wd.worksheet_id`)
40
+ .innerJoin('order_inventories', 'oi', `wd.target_inventory_id = oi.id AND wd."type" = 'SORTING'`)
41
+ .innerJoin('release_goods', 'rg', `rg.id = oi.release_good_id`)
42
+ .where('rg.domain_id = :domainId', { domainId: domain.id })
43
+ .andWhere('rg.name = :name', { name: taskNo })
44
+ .andWhere('rg.status IN (:...statuses)', {
45
+ statuses: [sales_base_1.ORDER_STATUS.READY_TO_SORT, sales_base_1.ORDER_STATUS.SORTING, sales_base_1.ORDER_STATUS.LOADING, sales_base_1.ORDER_STATUS.DONE]
46
+ })
47
+ .andWhere('ws.type = :type', { type: constants_1.WORKSHEET_TYPE.SORTING })
48
+ .getRawOne();
49
+ if (!result)
50
+ return null;
51
+ if (result.releaseGoodStatus === 'LOADING' || result.releaseGoodStatus === 'DONE') {
52
+ throw new Error(`Release Good already sorted`);
53
+ }
54
+ return {
55
+ taskNo: result.taskNo,
56
+ selectedReleaseGood: result.releaseGoodName,
57
+ status: result.wsStatus
58
+ };
59
+ }
60
+ /**
61
+ * Find worksheet by taskNo directly - optimized to only load needed relations
62
+ */
63
+ async function findWorksheetByTaskNo(tx, domain, taskNo, loadWorksheetDetails = false) {
64
+ const relations = loadWorksheetDetails ? ['bizplace', 'bizplace.domain', 'worksheetDetails'] : ['bizplace', 'bizplace.domain'];
65
+ return tx.getRepository(entities_1.Worksheet).findOne({
66
+ where: { taskNo, type: constants_1.WORKSHEET_TYPE.SORTING, domain },
67
+ relations
68
+ });
69
+ }
70
+ /**
71
+ * Find worksheet by bin location - combines location lookup and worksheet query
72
+ * Returns both taskNo and worksheet status in a single optimized query
73
+ */
74
+ async function findWorksheetByBinLocation(tx, domain, binName) {
75
+ // Combined query: location -> order inventory -> worksheet in one go
76
+ const result = await tx
77
+ .getRepository(sales_base_1.OrderInventory)
78
+ .createQueryBuilder('oi')
79
+ .select('ws2.task_no', 'taskNo')
80
+ .addSelect('ws2.id', 'worksheetId')
81
+ .addSelect('ws2.status', 'status')
82
+ .innerJoin('locations', 'loc', 'oi.bin_location_id = loc.id')
83
+ .innerJoin('worksheets', 'ws', `oi.ref_worksheet_id = ws.id AND ws.type = 'BATCH_PICKING'`)
84
+ .innerJoin('worksheets', 'ws2', `ws2.task_no = ws.task_no AND ws2.type = 'SORTING'`)
85
+ .innerJoin('release_goods', 'rg', 'rg.id = oi.release_good_id')
86
+ .where('oi.domain_id = :domainId', { domainId: domain.id })
87
+ .andWhere('loc.domain_id = :domainId', { domainId: domain.id })
88
+ .andWhere('loc.name = :binName', { binName })
89
+ .andWhere('oi.status IN (:...orderInventoryStatus)', {
90
+ orderInventoryStatus: [sales_base_1.ORDER_INVENTORY_STATUS.READY_TO_SORT, sales_base_1.ORDER_INVENTORY_STATUS.SORTING]
91
+ })
92
+ .andWhere('rg.status IN (:...statuses)', {
93
+ statuses: [sales_base_1.ORDER_STATUS.READY_TO_SORT, sales_base_1.ORDER_STATUS.SORTING]
94
+ })
95
+ .andWhere('ws2.status IN (:...worksheetStatuses)', {
96
+ worksheetStatuses: [constants_1.WORKSHEET_STATUS.DEACTIVATED, constants_1.WORKSHEET_STATUS.EXECUTING]
97
+ })
98
+ .getRawOne();
99
+ if (!result) {
100
+ throw new Error(`Bin do not have any batch picking order.`);
101
+ }
102
+ return {
103
+ taskNo: result.taskNo,
104
+ worksheetId: result.worksheetId,
105
+ status: result.status
106
+ };
107
+ }
108
+ /**
109
+ * Handle worksheet activation if needed
110
+ */
111
+ async function handleWorksheetActivation(tx, domain, user, task) {
112
+ var _a, _b, _c;
113
+ if (task.status !== 'DEACTIVATED')
114
+ return;
115
+ const sortingWSCtrl = new controllers_1.SortingWorksheetController(tx, domain, user);
116
+ // Use cached settings
117
+ const directActivateSetting = await getCachedSetting(tx, domain, 'id-rule', 'enable-direct-activate-sorting-worksheet');
118
+ if (!directActivateSetting || ((_a = directActivateSetting.value) === null || _a === void 0 ? void 0 : _a.toLowerCase()) !== 'true') {
119
+ throw new Error('Kindly go to sorting worksheet page to activate the sorting worksheet');
120
+ }
121
+ // Only fetch partner setting if main setting is enabled
122
+ const partnerSetting = await tx.getRepository(setting_base_1.PartnerSetting).findOne({
123
+ where: {
124
+ setting: directActivateSetting,
125
+ domain: domain,
126
+ partnerDomain: (_b = task.bizplace) === null || _b === void 0 ? void 0 : _b.domain
127
+ }
128
+ });
129
+ // If partner setting exists and is false, don't activate
130
+ if (partnerSetting && ((_c = partnerSetting.value) === null || _c === void 0 ? void 0 : _c.toLowerCase()) !== 'true') {
131
+ throw new Error('Kindly go to sorting worksheet page to activate the sorting worksheet');
132
+ }
133
+ // Load worksheet details only when needed for activation
134
+ if (!task.worksheetDetails) {
135
+ const taskWithDetails = await tx.getRepository(entities_1.Worksheet).findOne({
136
+ where: { id: task.id },
137
+ relations: ['worksheetDetails']
138
+ });
139
+ task.worksheetDetails = (taskWithDetails === null || taskWithDetails === void 0 ? void 0 : taskWithDetails.worksheetDetails) || [];
140
+ }
141
+ await sortingWSCtrl.activateSorting(task.name, task.worksheetDetails);
142
+ }
143
+ /**
144
+ * Build and execute release goods query with item counts in a SINGLE query
145
+ * Optimizations:
146
+ * - Removed redundant Domain join (filter directly on ws.domain_id)
147
+ * - Combined release goods + counts into one query using aggregate functions
148
+ */
149
+ async function getReleaseGoodsWithCounts(tx, domain, taskNo) {
150
+ // Single query that gets release goods with their counts using aggregation
151
+ const releaseGoods = await tx
152
+ .getRepository(entities_1.Worksheet)
153
+ .createQueryBuilder('ws')
154
+ .select('rg.id', 'id')
155
+ .addSelect('rg.name', 'name')
156
+ .addSelect('rg.refNo', 'refNo')
157
+ .addSelect('rg.refNo2', 'refNo2')
158
+ .addSelect('rg.status', 'status')
159
+ .addSelect('rg.district', 'district')
160
+ .addSelect('rg.attention_company', 'attentionCompany')
161
+ .addSelect('rg.delivery_address_1', 'deliveryAddress1')
162
+ .addSelect('rg.delivery_address_2', 'deliveryAddress2')
163
+ .addSelect('rg.delivery_address_3', 'deliveryAddress3')
164
+ .addSelect('rg.delivery_address_4', 'deliveryAddress4')
165
+ .addSelect('rg.delivery_address_5', 'deliveryAddress5')
166
+ .addSelect('rg.created_at', 'createdAt')
167
+ .addSelect('u.name', 'sortedByUser')
168
+ // Counts computed directly in the same query
169
+ .addSelect('COUNT(oi.id)', 'totalCount')
170
+ .addSelect('SUM(CASE WHEN oi.sorted_qty = oi.release_qty THEN 1 ELSE 0 END)', 'completedCount')
171
+ .innerJoin(entities_1.WorksheetDetail, 'wsd', 'ws.id = wsd.worksheet_id')
172
+ .innerJoin(sales_base_1.OrderInventory, 'oi', 'oi.id = wsd.target_inventory_id')
173
+ .innerJoin(sales_base_1.ReleaseGood, 'rg', 'rg.id = oi.release_good_id')
174
+ .leftJoin(auth_base_1.User, 'u', 'rg.sorted_by_id = u.id')
175
+ // Filter directly on ws.domain_id - no need to join Domain table
176
+ .where('ws.domain_id = :domainId', { domainId: domain.id })
177
+ .andWhere('ws.taskNo = :taskNo', { taskNo })
178
+ .andWhere('ws.type = :worksheetType', { worksheetType: constants_1.WORKSHEET_TYPE.SORTING })
179
+ .andWhere('ws.status = :worksheetStatus', { worksheetStatus: constants_1.WORKSHEET_STATUS.EXECUTING })
180
+ .groupBy('rg.id')
181
+ .addGroupBy('rg.name')
182
+ .addGroupBy('rg.refNo')
183
+ .addGroupBy('rg.refNo2')
184
+ .addGroupBy('rg.status')
185
+ .addGroupBy('rg.district')
186
+ .addGroupBy('rg.attention_company')
187
+ .addGroupBy('rg.delivery_address_1')
188
+ .addGroupBy('rg.delivery_address_2')
189
+ .addGroupBy('rg.delivery_address_3')
190
+ .addGroupBy('rg.delivery_address_4')
191
+ .addGroupBy('rg.delivery_address_5')
192
+ .addGroupBy('rg.created_at')
193
+ .addGroupBy('u.name')
194
+ .orderBy('rg.created_at', 'ASC')
195
+ .getRawMany();
196
+ // Transform results to include itemCounts
197
+ return releaseGoods.map(rg => {
198
+ const total = parseInt(rg.totalCount) || 0;
199
+ const completed = parseInt(rg.completedCount) || 0;
200
+ return {
201
+ id: rg.id,
202
+ name: rg.name,
203
+ refNo: rg.refNo,
204
+ refNo2: rg.refNo2,
205
+ status: rg.status,
206
+ district: rg.district,
207
+ attentionCompany: rg.attentionCompany,
208
+ deliveryAddress1: rg.deliveryAddress1,
209
+ deliveryAddress2: rg.deliveryAddress2,
210
+ deliveryAddress3: rg.deliveryAddress3,
211
+ deliveryAddress4: rg.deliveryAddress4,
212
+ deliveryAddress5: rg.deliveryAddress5,
213
+ sortedByUser: rg.sortedByUser,
214
+ itemCounts: {
215
+ total,
216
+ pending: total - completed
217
+ }
218
+ };
219
+ });
220
+ }
13
221
  exports.findSortingReleaseOrdersByTaskNoResolver = {
14
222
  async findSortingReleaseOrdersByTaskNo(_, { taskNo }, context) {
15
- var _a;
223
+ const startTime = Date.now();
16
224
  const { domain, tx, user } = context.state;
17
225
  let selectedReleaseGood = null;
18
- let ws = await tx
19
- .getRepository(entities_1.Worksheet)
20
- .createQueryBuilder('ws')
21
- .addSelect('rg.name', 'release_good_name')
22
- .addSelect('rg.status', 'release_good_status')
23
- .innerJoin('worksheet_details', 'wd', `ws.id = wd.worksheet_id`)
24
- .innerJoin('order_inventories', 'oi', `wd.target_inventory_id = oi.id and wd."type" ='SORTING'`)
25
- .innerJoin('release_goods', 'rg', `rg.id = oi.release_good_id`)
26
- .where('rg.domain_id = :domainId', { domainId: domain.id })
27
- .andWhere('rg.name = :name', { name: taskNo })
28
- .andWhere('rg.status IN (:...statuses)', {
29
- statuses: [sales_base_1.ORDER_STATUS.READY_TO_SORT, sales_base_1.ORDER_STATUS.SORTING, sales_base_1.ORDER_STATUS.LOADING, sales_base_1.ORDER_STATUS.DONE]
30
- })
31
- .andWhere('ws.type = :type', { type: constants_1.WORKSHEET_TYPE.SORTING })
32
- .getRawOne();
33
- if (ws) {
34
- if (ws.release_good_status == 'LOADING' || ws.release_good_status == 'DONE') {
35
- throw new Error(`Release Good already sorted`);
36
- }
37
- selectedReleaseGood = ws.release_good_name;
38
- taskNo = ws.ws_task_no;
226
+ let task = null;
227
+ let resolvedTaskNo = taskNo;
228
+ // Step 1: Try to find by release good name first (most common case)
229
+ const releaseGoodResult = await findWorksheetByReleaseGoodName(tx, domain, taskNo);
230
+ if (releaseGoodResult) {
231
+ selectedReleaseGood = releaseGoodResult.selectedReleaseGood;
232
+ resolvedTaskNo = releaseGoodResult.taskNo;
233
+ // Only load worksheetDetails if we need them for activation
234
+ const needsActivation = releaseGoodResult.status === 'DEACTIVATED';
235
+ task = await findWorksheetByTaskNo(tx, domain, resolvedTaskNo, needsActivation);
39
236
  }
40
- let task = await tx.getRepository(entities_1.Worksheet).findOne({
41
- where: { taskNo, type: constants_1.WORKSHEET_TYPE.SORTING, domain },
42
- relations: ['bizplace', 'bizplace.domain', 'worksheetDetails']
43
- });
44
- // Find Task based on Bin
237
+ // Step 2: Try to find by worksheet taskNo directly
238
+ if (!task) {
239
+ task = await findWorksheetByTaskNo(tx, domain, taskNo, false);
240
+ }
241
+ // Step 3: Try to find by bin location
45
242
  if (!task) {
46
- const binLocation = await tx.getRepository(warehouse_base_1.Location).findOne({
47
- where: { domain, name: taskNo }
48
- });
49
- if (binLocation) {
50
- const qb = tx
51
- .getRepository(sales_base_1.OrderInventory)
52
- .createQueryBuilder('orderInventory');
53
- qb.innerJoinAndSelect('orderInventory.releaseGood', 'releaseGood')
54
- .innerJoinAndSelect('worksheets', 'ws', `orderInventory.ref_worksheet_id = ws.id AND ws.type = 'BATCH_PICKING'`)
55
- .innerJoinAndSelect('worksheets', 'ws2', `ws2.task_no = ws.task_no AND ws2.type = 'SORTING'`)
56
- .innerJoinAndSelect('releaseGood.bizplace', 'bizplace')
57
- .innerJoinAndSelect('bizplace.domain', 'domain')
58
- .where('orderInventory.domain_id = :domainId', { domainId: domain.id })
59
- .andWhere('orderInventory.status IN (:...orderInventoryStatus)', {
60
- orderInventoryStatus: [sales_base_1.ORDER_INVENTORY_STATUS.READY_TO_SORT, sales_base_1.ORDER_INVENTORY_STATUS.SORTING]
61
- })
62
- .andWhere('orderInventory.bin_location_id = :locationId', { locationId: binLocation.id })
63
- .andWhere('releaseGood.status IN (:...statuses)', {
64
- statuses: [sales_base_1.ORDER_STATUS.READY_TO_SORT, sales_base_1.ORDER_STATUS.SORTING]
65
- });
66
- const orderInventoryByBin = await qb.getRawOne();
67
- if (orderInventoryByBin === null || orderInventoryByBin === void 0 ? void 0 : orderInventoryByBin.releaseGood_id) {
68
- taskNo = orderInventoryByBin.ws_task_no;
69
- task = await tx.getRepository(entities_1.Worksheet).findOne({
70
- where: {
71
- taskNo,
72
- status: (0, typeorm_1.In)([constants_1.WORKSHEET_STATUS.DEACTIVATED, constants_1.WORKSHEET_STATUS.EXECUTING]),
73
- type: constants_1.WORKSHEET_TYPE.SORTING,
74
- domain
75
- },
76
- relations: ['worksheetDetails']
77
- });
78
- }
79
- else {
80
- throw new Error(`Bin do not have any batch picking order.`);
81
- }
243
+ const binResult = await findWorksheetByBinLocation(tx, domain, taskNo);
244
+ if (binResult) {
245
+ resolvedTaskNo = binResult.taskNo;
246
+ // Only load worksheetDetails if we need them for activation
247
+ const needsActivation = binResult.status === 'DEACTIVATED';
248
+ task = await findWorksheetByTaskNo(tx, domain, resolvedTaskNo, needsActivation);
82
249
  }
83
250
  }
84
- if (!task)
251
+ if (!task) {
85
252
  throw new Error('Unable to find task no.');
86
- if (task.status === 'DEACTIVATED') {
87
- const sortingWSCtrl = new controllers_1.SortingWorksheetController(tx, domain, user);
88
- const directActivateSortingWorksheet = await tx.getRepository(setting_base_1.Setting).findOne({
89
- where: { domain: domain, category: 'id-rule', name: 'enable-direct-activate-sorting-worksheet' }
90
- });
91
- const partnerDirectActivateSortingWorksheetSetting = await tx
92
- .getRepository(setting_base_1.PartnerSetting)
93
- .findOne({
94
- where: {
95
- setting: directActivateSortingWorksheet,
96
- domain: domain,
97
- partnerDomain: (_a = task.bizplace) === null || _a === void 0 ? void 0 : _a.domain
98
- }
99
- });
100
- if (directActivateSortingWorksheet != undefined && directActivateSortingWorksheet.value.toLowerCase() == 'true') {
101
- if (partnerDirectActivateSortingWorksheetSetting != undefined) {
102
- if (partnerDirectActivateSortingWorksheetSetting.value.toLowerCase() == 'true')
103
- await sortingWSCtrl.activateSorting(task.name, task.worksheetDetails);
104
- }
105
- else {
106
- await sortingWSCtrl.activateSorting(task.name, task.worksheetDetails);
107
- }
108
- }
109
- else {
110
- throw new Error('Kindly go to sorting worksheet page to activate the sorting worksheet');
111
- }
112
253
  }
113
- const qb = tx
114
- .getRepository(entities_1.Worksheet)
115
- .createQueryBuilder('ws')
116
- .select('rg.id as id')
117
- .addSelect('rg.name as name')
118
- .addSelect('rg.refNo as "refNo"')
119
- .addSelect('rg.refNo2 as "refNo2"')
120
- .addSelect('rg.status as status')
121
- .addSelect('rg.district as "district"')
122
- .addSelect('rg.attention_company as "attentionCompany"')
123
- .addSelect('rg.delivery_address_1 as "deliveryAddress1"')
124
- .addSelect('rg.delivery_address_2 as "deliveryAddress2"')
125
- .addSelect('rg.delivery_address_3 as "deliveryAddress3"')
126
- .addSelect('rg.delivery_address_4 as "deliveryAddress4"')
127
- .addSelect('rg.delivery_address_5 as "deliveryAddress5"')
128
- .addSelect('user.name as "sortedByUser"')
129
- .innerJoin(shell_1.Domain, 'domain', 'ws.domain_id = domain.id')
130
- .innerJoin(entities_1.WorksheetDetail, 'wsd', 'ws.id = wsd.worksheet_id')
131
- .innerJoin(sales_base_1.OrderInventory, 'oi', 'oi.id = wsd.target_inventory_id')
132
- .innerJoin(sales_base_1.ReleaseGood, 'rg', 'rg.id = oi.release_good_id')
133
- .leftJoin(auth_base_1.User, 'user', 'rg.sorted_by_id = user.id')
134
- .where('domain.id = :domainId', { domainId: domain.id })
135
- .andWhere('ws.taskNo = :taskNo', { taskNo: taskNo })
136
- .andWhere('ws.type = :worksheetType', { worksheetType: constants_1.WORKSHEET_TYPE.SORTING })
137
- .andWhere('ws.status = :worksheetStatus', { worksheetStatus: constants_1.WORKSHEET_STATUS.EXECUTING })
138
- .groupBy('rg.id')
139
- .addGroupBy('rg.name')
140
- .addGroupBy('rg.status')
141
- .addGroupBy('user.name')
142
- .orderBy('rg.createdAt', 'ASC');
143
- const releaseGoods = await qb.getRawMany();
144
- if (releaseGoods.length > 0) {
145
- // Get counts for all release goods in a single query (avoids N+1 problem)
146
- const releaseGoodIds = releaseGoods.map(rg => rg.id);
147
- const countsResult = await tx
148
- .getRepository(sales_base_1.OrderInventory)
149
- .createQueryBuilder('orderInventory')
150
- .innerJoin(entities_1.WorksheetDetail, 'wsd', 'orderInventory.id = wsd.target_inventory_id')
151
- .innerJoin(entities_1.Worksheet, 'ws', 'wsd.worksheet_id = ws.id')
152
- .select('orderInventory.release_good_id', 'releaseGoodId')
153
- .addSelect('COUNT(*)', 'total')
154
- .addSelect('SUM(CASE WHEN orderInventory.sortedQty = orderInventory.releaseQty THEN 1 ELSE 0 END)', 'completed')
155
- .where('orderInventory.release_good_id IN (:...releaseGoodIds)', { releaseGoodIds })
156
- .andWhere('orderInventory.domain_id = :domainId', { domainId: domain.id })
157
- .andWhere('ws.taskNo = :taskNo', { taskNo: taskNo })
158
- .andWhere('ws.type = :worksheetType', { worksheetType: constants_1.WORKSHEET_TYPE.SORTING })
159
- .andWhere('ws.status = :worksheetStatus', { worksheetStatus: constants_1.WORKSHEET_STATUS.EXECUTING })
160
- .groupBy('orderInventory.release_good_id')
161
- .getRawMany();
162
- // Build a map for quick lookup
163
- const countsById = new Map(countsResult.map(c => [
164
- c.releaseGoodId,
165
- { total: parseInt(c.total) || 0, completed: parseInt(c.completed) || 0 }
166
- ]));
167
- // Assign itemCounts to each release good
168
- for (const releaseGood of releaseGoods) {
169
- const counts = countsById.get(releaseGood.id) || { total: 0, completed: 0 };
170
- releaseGood['itemCounts'] = {
171
- total: counts.total,
172
- pending: counts.total - counts.completed
173
- };
174
- }
254
+ // Step 4: Handle activation if needed
255
+ await handleWorksheetActivation(tx, domain, user, task);
256
+ // Step 5: Get release goods with counts
257
+ const releaseGoods = await getReleaseGoodsWithCounts(tx, domain, resolvedTaskNo);
258
+ // Performance logging (only in development/debug mode)
259
+ const elapsed = Date.now() - startTime;
260
+ if (elapsed > 1000) {
261
+ console.warn(`[PERF] findSortingReleaseOrdersByTaskNo took ${elapsed}ms for taskNo: ${taskNo}`);
175
262
  }
176
- return { releaseGoods, taskNo, selectedReleaseGood };
263
+ return { releaseGoods, taskNo: resolvedTaskNo, selectedReleaseGood };
177
264
  }
178
265
  };
179
266
  //# sourceMappingURL=find-sorting-release-orders-by-task-no.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"find-sorting-release-orders-by-task-no.js","sourceRoot":"","sources":["../../../../server/graphql/resolvers/worksheet/find-sorting-release-orders-by-task-no.ts"],"names":[],"mappings":";;;AAAA,qCAA+D;AAE/D,2DAKmC;AACnC,iDAA8C;AAC9C,yDAAgD;AAChD,mEAAyD;AACzD,uDAAkE;AAClE,+DAAsE;AAEtE,kDAAqE;AACrE,gDAA0G;AAE7F,QAAA,wCAAwC,GAAG;IACtD,KAAK,CAAC,gCAAgC,CAAC,CAAM,EAAE,EAAE,MAAM,EAAE,EAAE,OAAY;;QACrE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,GAAsD,OAAO,CAAC,KAAK,CAAA;QAE7F,IAAI,mBAAmB,GAAG,IAAI,CAAA;QAC9B,IAAI,EAAE,GAAG,MAAM,EAAE;aACd,aAAa,CAAC,oBAAe,CAAC;aAC9B,kBAAkB,CAAC,IAAI,CAAC;aACxB,SAAS,CAAC,SAAS,EAAE,mBAAmB,CAAC;aACzC,SAAS,CAAC,WAAW,EAAE,qBAAqB,CAAC;aAC7C,SAAS,CAAC,mBAAmB,EAAE,IAAI,EAAE,yBAAyB,CAAC;aAC/D,SAAS,CAAC,mBAAmB,EAAE,IAAI,EAAE,yDAAyD,CAAC;aAC/F,SAAS,CAAC,eAAe,EAAE,IAAI,EAAE,4BAA4B,CAAC;aAC9D,KAAK,CAAC,0BAA0B,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;aAC1D,QAAQ,CAAC,iBAAiB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;aAC7C,QAAQ,CAAC,6BAA6B,EAAE;YACvC,QAAQ,EAAE,CAAC,yBAAY,CAAC,aAAa,EAAE,yBAAY,CAAC,OAAO,EAAE,yBAAY,CAAC,OAAO,EAAE,yBAAY,CAAC,IAAI,CAAC;SACtG,CAAC;aACD,QAAQ,CAAC,iBAAiB,EAAE,EAAE,IAAI,EAAE,0BAAc,CAAC,OAAO,EAAE,CAAC;aAC7D,SAAS,EAAE,CAAA;QAEd,IAAI,EAAE,EAAE;YACN,IAAI,EAAE,CAAC,mBAAmB,IAAI,SAAS,IAAI,EAAE,CAAC,mBAAmB,IAAI,MAAM,EAAE;gBAC3E,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAA;aAC/C;YAED,mBAAmB,GAAG,EAAE,CAAC,iBAAiB,CAAA;YAC1C,MAAM,GAAG,EAAE,CAAC,UAAU,CAAA;SACvB;QAED,IAAI,IAAI,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,oBAAe,CAAC,CAAC,OAAO,CAAC;YACzD,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,0BAAc,CAAC,OAAO,EAAE,MAAM,EAAE;YACvD,SAAS,EAAE,CAAC,UAAU,EAAE,iBAAiB,EAAE,kBAAkB,CAAC;SAC/D,CAAC,CAAA;QAEF,yBAAyB;QACzB,IAAI,CAAC,IAAI,EAAE;YACT,MAAM,WAAW,GAAa,MAAM,EAAE,CAAC,aAAa,CAAC,yBAAQ,CAAC,CAAC,OAAO,CAAC;gBACrE,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE;aAChC,CAAC,CAAA;YAEF,IAAI,WAAW,EAAE;gBACf,MAAM,EAAE,GAA6C,EAAE;qBACpD,aAAa,CAAC,2BAAoB,CAAC;qBACnC,kBAAkB,CAAC,gBAAgB,CAAC,CAAA;gBAEvC,EAAE,CAAC,kBAAkB,CAAC,4BAA4B,EAAE,aAAa,CAAC;qBAC/D,kBAAkB,CACjB,YAAY,EACZ,IAAI,EACJ,uEAAuE,CACxE;qBACA,kBAAkB,CAAC,YAAY,EAAE,KAAK,EAAE,mDAAmD,CAAC;qBAC5F,kBAAkB,CAAC,sBAAsB,EAAE,UAAU,CAAC;qBACtD,kBAAkB,CAAC,iBAAiB,EAAE,QAAQ,CAAC;qBAC/C,KAAK,CAAC,sCAAsC,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;qBACtE,QAAQ,CAAC,qDAAqD,EAAE;oBAC/D,oBAAoB,EAAE,CAAC,mCAAsB,CAAC,aAAa,EAAE,mCAAsB,CAAC,OAAO,CAAC;iBAC7F,CAAC;qBACD,QAAQ,CAAC,8CAA8C,EAAE,EAAE,UAAU,EAAE,WAAW,CAAC,EAAE,EAAE,CAAC;qBACxF,QAAQ,CAAC,sCAAsC,EAAE;oBAChD,QAAQ,EAAE,CAAC,yBAAY,CAAC,aAAa,EAAE,yBAAY,CAAC,OAAO,CAAC;iBAC7D,CAAC,CAAA;gBAEJ,MAAM,mBAAmB,GAAG,MAAM,EAAE,CAAC,SAAS,EAAE,CAAA;gBAChD,IAAI,mBAAmB,aAAnB,mBAAmB,uBAAnB,mBAAmB,CAAE,cAAc,EAAE;oBACvC,MAAM,GAAG,mBAAmB,CAAC,UAAU,CAAA;oBACvC,IAAI,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,oBAAe,CAAC,CAAC,OAAO,CAAC;wBACrD,KAAK,EAAE;4BACL,MAAM;4BACN,MAAM,EAAE,IAAA,YAAE,EAAC,CAAC,4BAAgB,CAAC,WAAW,EAAE,4BAAgB,CAAC,SAAS,CAAC,CAAC;4BACtE,IAAI,EAAE,0BAAc,CAAC,OAAO;4BAC5B,MAAM;yBACP;wBACD,SAAS,EAAE,CAAC,kBAAkB,CAAC;qBAChC,CAAC,CAAA;iBACH;qBAAM;oBACL,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAA;iBAC5D;aACF;SACF;QAED,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAA;QAErD,IAAI,IAAI,CAAC,MAAM,KAAK,aAAa,EAAE;YACjC,MAAM,aAAa,GAA+B,IAAI,wCAA0B,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,CAAA;YAElG,MAAM,8BAA8B,GAAY,MAAM,EAAE,CAAC,aAAa,CAAC,sBAAO,CAAC,CAAC,OAAO,CAAC;gBACtF,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,0CAA0C,EAAE;aACjG,CAAC,CAAA;YAEF,MAAM,4CAA4C,GAAmB,MAAM,EAAE;iBAC1E,aAAa,CAAC,6BAAc,CAAC;iBAC7B,OAAO,CAAC;gBACP,KAAK,EAAE;oBACL,OAAO,EAAE,8BAA8B;oBACvC,MAAM,EAAE,MAAM;oBACd,aAAa,EAAE,MAAA,IAAI,CAAC,QAAQ,0CAAE,MAAM;iBACrC;aACF,CAAC,CAAA;YAEJ,IAAI,8BAA8B,IAAI,SAAS,IAAI,8BAA8B,CAAC,KAAK,CAAC,WAAW,EAAE,IAAI,MAAM,EAAE;gBAC/G,IAAI,4CAA4C,IAAI,SAAS,EAAE;oBAC7D,IAAI,4CAA4C,CAAC,KAAK,CAAC,WAAW,EAAE,IAAI,MAAM;wBAC5E,MAAM,aAAa,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAA;iBACxE;qBAAM;oBACL,MAAM,aAAa,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAA;iBACtE;aACF;iBAAM;gBACL,MAAM,IAAI,KAAK,CAAC,uEAAuE,CAAC,CAAA;aACzF;SACF;QAED,MAAM,EAAE,GAAwC,EAAE;aAC/C,aAAa,CAAC,oBAAe,CAAC;aAC9B,kBAAkB,CAAC,IAAI,CAAC;aACxB,MAAM,CAAC,aAAa,CAAC;aACrB,SAAS,CAAC,iBAAiB,CAAC;aAC5B,SAAS,CAAC,qBAAqB,CAAC;aAChC,SAAS,CAAC,uBAAuB,CAAC;aAClC,SAAS,CAAC,qBAAqB,CAAC;aAChC,SAAS,CAAC,2BAA2B,CAAC;aACtC,SAAS,CAAC,4CAA4C,CAAC;aACvD,SAAS,CAAC,6CAA6C,CAAC;aACxD,SAAS,CAAC,6CAA6C,CAAC;aACxD,SAAS,CAAC,6CAA6C,CAAC;aACxD,SAAS,CAAC,6CAA6C,CAAC;aACxD,SAAS,CAAC,6CAA6C,CAAC;aACxD,SAAS,CAAC,6BAA6B,CAAC;aACxC,SAAS,CAAC,cAAM,EAAE,QAAQ,EAAE,0BAA0B,CAAC;aACvD,SAAS,CAAC,0BAAqB,EAAE,KAAK,EAAE,0BAA0B,CAAC;aACnE,SAAS,CAAC,2BAAoB,EAAE,IAAI,EAAE,iCAAiC,CAAC;aACxE,SAAS,CAAC,wBAAiB,EAAE,IAAI,EAAE,4BAA4B,CAAC;aAChE,QAAQ,CAAC,gBAAI,EAAE,MAAM,EAAE,2BAA2B,CAAC;aACnD,KAAK,CAAC,uBAAuB,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;aACvD,QAAQ,CAAC,qBAAqB,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;aACnD,QAAQ,CAAC,0BAA0B,EAAE,EAAE,aAAa,EAAE,0BAAc,CAAC,OAAO,EAAE,CAAC;aAC/E,QAAQ,CAAC,8BAA8B,EAAE,EAAE,eAAe,EAAE,4BAAgB,CAAC,SAAS,EAAE,CAAC;aACzF,OAAO,CAAC,OAAO,CAAC;aAChB,UAAU,CAAC,SAAS,CAAC;aACrB,UAAU,CAAC,WAAW,CAAC;aACvB,UAAU,CAAC,WAAW,CAAC;aACvB,OAAO,CAAC,cAAc,EAAE,KAAK,CAAC,CAAA;QAEjC,MAAM,YAAY,GAAwB,MAAM,EAAE,CAAC,UAAU,EAAE,CAAA;QAE/D,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE;YAC3B,0EAA0E;YAC1E,MAAM,cAAc,GAAG,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;YACpD,MAAM,YAAY,GAAG,MAAM,EAAE;iBAC1B,aAAa,CAAC,2BAAoB,CAAC;iBACnC,kBAAkB,CAAC,gBAAgB,CAAC;iBACpC,SAAS,CAAC,0BAAqB,EAAE,KAAK,EAAE,6CAA6C,CAAC;iBACtF,SAAS,CAAC,oBAAe,EAAE,IAAI,EAAE,0BAA0B,CAAC;iBAC5D,MAAM,CAAC,gCAAgC,EAAE,eAAe,CAAC;iBACzD,SAAS,CAAC,UAAU,EAAE,OAAO,CAAC;iBAC9B,SAAS,CACR,uFAAuF,EACvF,WAAW,CACZ;iBACA,KAAK,CAAC,wDAAwD,EAAE,EAAE,cAAc,EAAE,CAAC;iBACnF,QAAQ,CAAC,sCAAsC,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;iBACzE,QAAQ,CAAC,qBAAqB,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;iBACnD,QAAQ,CAAC,0BAA0B,EAAE,EAAE,aAAa,EAAE,0BAAc,CAAC,OAAO,EAAE,CAAC;iBAC/E,QAAQ,CAAC,8BAA8B,EAAE,EAAE,eAAe,EAAE,4BAAgB,CAAC,SAAS,EAAE,CAAC;iBACzF,OAAO,CAAC,gCAAgC,CAAC;iBACzC,UAAU,EAAE,CAAA;YAEf,+BAA+B;YAC/B,MAAM,UAAU,GAAG,IAAI,GAAG,CACxB,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpB,CAAC,CAAC,aAAa;gBACf,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE;aACzE,CAAC,CACH,CAAA;YAED,yCAAyC;YACzC,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE;gBACtC,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAA;gBAC3E,WAAW,CAAC,YAAY,CAAC,GAAG;oBAC1B,KAAK,EAAE,MAAM,CAAC,KAAK;oBACnB,OAAO,EAAE,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,SAAS;iBACzC,CAAA;aACF;SACF;QAED,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAA;IACtD,CAAC;CACF,CAAA"}
1
+ {"version":3,"file":"find-sorting-release-orders-by-task-no.js","sourceRoot":"","sources":["../../../../server/graphql/resolvers/worksheet/find-sorting-release-orders-by-task-no.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@things-factory/worksheet-base",
3
- "version": "4.3.755",
3
+ "version": "4.3.756",
4
4
  "main": "dist-server/index.js",
5
5
  "browser": "client/index.js",
6
6
  "things-factory": true,
@@ -46,5 +46,5 @@
46
46
  "puppeteer": "21.0.3",
47
47
  "uuid": "^9.0.0"
48
48
  },
49
- "gitHead": "7cd08ee86623f4ab057bd7bbc63f0f2d1be6659b"
49
+ "gitHead": "b16ce3a1cde77139646a0812c3b198a854e48a19"
50
50
  }
@@ -8,199 +8,330 @@ import {
8
8
  } from '@things-factory/sales-base'
9
9
  import { Domain } from '@things-factory/shell'
10
10
  import { User } from '@things-factory/auth-base'
11
- import { Location } from '@things-factory/warehouse-base'
12
11
  import { SortingWorksheetController } from '../../../controllers/'
13
12
  import { PartnerSetting, Setting } from '@things-factory/setting-base'
14
13
 
15
14
  import { WORKSHEET_STATUS, WORKSHEET_TYPE } from '../../../constants'
16
15
  import { Worksheet as WorksheetEntity, WorksheetDetail as WorksheetDetailEntity } from '../../../entities'
17
16
 
17
+ // Simple in-memory cache for settings with TTL
18
+ const settingsCache = new Map<string, { value: Setting | null; expiry: number }>()
19
+ const SETTINGS_CACHE_TTL = 5 * 60 * 1000 // 5 minutes
20
+
21
+ /**
22
+ * Get setting with caching to avoid repeated database queries
23
+ */
24
+ async function getCachedSetting(
25
+ tx: EntityManager,
26
+ domain: Domain,
27
+ category: string,
28
+ name: string
29
+ ): Promise<Setting | null> {
30
+ const cacheKey = `${domain.id}:${category}:${name}`
31
+ const cached = settingsCache.get(cacheKey)
32
+
33
+ if (cached && cached.expiry > Date.now()) {
34
+ return cached.value
35
+ }
36
+
37
+ const setting = await tx.getRepository(Setting).findOne({
38
+ where: { domain, category, name }
39
+ })
40
+
41
+ settingsCache.set(cacheKey, { value: setting || null, expiry: Date.now() + SETTINGS_CACHE_TTL })
42
+ return setting || null
43
+ }
44
+
45
+ /**
46
+ * Find worksheet by release good name - returns task info if found
47
+ */
48
+ async function findWorksheetByReleaseGoodName(
49
+ tx: EntityManager,
50
+ domain: Domain,
51
+ taskNo: string
52
+ ): Promise<{ taskNo: string; selectedReleaseGood: string; status: string } | null> {
53
+ const result = await tx
54
+ .getRepository(WorksheetEntity)
55
+ .createQueryBuilder('ws')
56
+ .select('ws.task_no', 'taskNo')
57
+ .addSelect('ws.status', 'wsStatus')
58
+ .addSelect('rg.name', 'releaseGoodName')
59
+ .addSelect('rg.status', 'releaseGoodStatus')
60
+ .innerJoin('worksheet_details', 'wd', `ws.id = wd.worksheet_id`)
61
+ .innerJoin('order_inventories', 'oi', `wd.target_inventory_id = oi.id AND wd."type" = 'SORTING'`)
62
+ .innerJoin('release_goods', 'rg', `rg.id = oi.release_good_id`)
63
+ .where('rg.domain_id = :domainId', { domainId: domain.id })
64
+ .andWhere('rg.name = :name', { name: taskNo })
65
+ .andWhere('rg.status IN (:...statuses)', {
66
+ statuses: [ORDER_STATUS.READY_TO_SORT, ORDER_STATUS.SORTING, ORDER_STATUS.LOADING, ORDER_STATUS.DONE]
67
+ })
68
+ .andWhere('ws.type = :type', { type: WORKSHEET_TYPE.SORTING })
69
+ .getRawOne()
70
+
71
+ if (!result) return null
72
+
73
+ if (result.releaseGoodStatus === 'LOADING' || result.releaseGoodStatus === 'DONE') {
74
+ throw new Error(`Release Good already sorted`)
75
+ }
76
+
77
+ return {
78
+ taskNo: result.taskNo,
79
+ selectedReleaseGood: result.releaseGoodName,
80
+ status: result.wsStatus
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Find worksheet by taskNo directly - optimized to only load needed relations
86
+ */
87
+ async function findWorksheetByTaskNo(
88
+ tx: EntityManager,
89
+ domain: Domain,
90
+ taskNo: string,
91
+ loadWorksheetDetails: boolean = false
92
+ ): Promise<WorksheetEntity | null> {
93
+ const relations = loadWorksheetDetails ? ['bizplace', 'bizplace.domain', 'worksheetDetails'] : ['bizplace', 'bizplace.domain']
94
+
95
+ return tx.getRepository(WorksheetEntity).findOne({
96
+ where: { taskNo, type: WORKSHEET_TYPE.SORTING, domain },
97
+ relations
98
+ })
99
+ }
100
+
101
+ /**
102
+ * Find worksheet by bin location - combines location lookup and worksheet query
103
+ * Returns both taskNo and worksheet status in a single optimized query
104
+ */
105
+ async function findWorksheetByBinLocation(
106
+ tx: EntityManager,
107
+ domain: Domain,
108
+ binName: string
109
+ ): Promise<{ taskNo: string; worksheetId: string; status: string } | null> {
110
+ // Combined query: location -> order inventory -> worksheet in one go
111
+ const result = await tx
112
+ .getRepository(OrderInventoryEntity)
113
+ .createQueryBuilder('oi')
114
+ .select('ws2.task_no', 'taskNo')
115
+ .addSelect('ws2.id', 'worksheetId')
116
+ .addSelect('ws2.status', 'status')
117
+ .innerJoin('locations', 'loc', 'oi.bin_location_id = loc.id')
118
+ .innerJoin('worksheets', 'ws', `oi.ref_worksheet_id = ws.id AND ws.type = 'BATCH_PICKING'`)
119
+ .innerJoin('worksheets', 'ws2', `ws2.task_no = ws.task_no AND ws2.type = 'SORTING'`)
120
+ .innerJoin('release_goods', 'rg', 'rg.id = oi.release_good_id')
121
+ .where('oi.domain_id = :domainId', { domainId: domain.id })
122
+ .andWhere('loc.domain_id = :domainId', { domainId: domain.id })
123
+ .andWhere('loc.name = :binName', { binName })
124
+ .andWhere('oi.status IN (:...orderInventoryStatus)', {
125
+ orderInventoryStatus: [ORDER_INVENTORY_STATUS.READY_TO_SORT, ORDER_INVENTORY_STATUS.SORTING]
126
+ })
127
+ .andWhere('rg.status IN (:...statuses)', {
128
+ statuses: [ORDER_STATUS.READY_TO_SORT, ORDER_STATUS.SORTING]
129
+ })
130
+ .andWhere('ws2.status IN (:...worksheetStatuses)', {
131
+ worksheetStatuses: [WORKSHEET_STATUS.DEACTIVATED, WORKSHEET_STATUS.EXECUTING]
132
+ })
133
+ .getRawOne()
134
+
135
+ if (!result) {
136
+ throw new Error(`Bin do not have any batch picking order.`)
137
+ }
138
+
139
+ return {
140
+ taskNo: result.taskNo,
141
+ worksheetId: result.worksheetId,
142
+ status: result.status
143
+ }
144
+ }
145
+
146
+ /**
147
+ * Handle worksheet activation if needed
148
+ */
149
+ async function handleWorksheetActivation(
150
+ tx: EntityManager,
151
+ domain: Domain,
152
+ user: User,
153
+ task: WorksheetEntity
154
+ ): Promise<void> {
155
+ if (task.status !== 'DEACTIVATED') return
156
+
157
+ const sortingWSCtrl = new SortingWorksheetController(tx, domain, user)
158
+
159
+ // Use cached settings
160
+ const directActivateSetting = await getCachedSetting(
161
+ tx,
162
+ domain,
163
+ 'id-rule',
164
+ 'enable-direct-activate-sorting-worksheet'
165
+ )
166
+
167
+ if (!directActivateSetting || directActivateSetting.value?.toLowerCase() !== 'true') {
168
+ throw new Error('Kindly go to sorting worksheet page to activate the sorting worksheet')
169
+ }
170
+
171
+ // Only fetch partner setting if main setting is enabled
172
+ const partnerSetting: PartnerSetting | null = await tx.getRepository(PartnerSetting).findOne({
173
+ where: {
174
+ setting: directActivateSetting,
175
+ domain: domain,
176
+ partnerDomain: task.bizplace?.domain
177
+ }
178
+ })
179
+
180
+ // If partner setting exists and is false, don't activate
181
+ if (partnerSetting && (partnerSetting.value as string)?.toLowerCase() !== 'true') {
182
+ throw new Error('Kindly go to sorting worksheet page to activate the sorting worksheet')
183
+ }
184
+
185
+ // Load worksheet details only when needed for activation
186
+ if (!task.worksheetDetails) {
187
+ const taskWithDetails = await tx.getRepository(WorksheetEntity).findOne({
188
+ where: { id: task.id },
189
+ relations: ['worksheetDetails']
190
+ })
191
+ task.worksheetDetails = taskWithDetails?.worksheetDetails || []
192
+ }
193
+
194
+ await sortingWSCtrl.activateSorting(task.name, task.worksheetDetails)
195
+ }
196
+
197
+ /**
198
+ * Build and execute release goods query with item counts in a SINGLE query
199
+ * Optimizations:
200
+ * - Removed redundant Domain join (filter directly on ws.domain_id)
201
+ * - Combined release goods + counts into one query using aggregate functions
202
+ */
203
+ async function getReleaseGoodsWithCounts(
204
+ tx: EntityManager,
205
+ domain: Domain,
206
+ taskNo: string
207
+ ): Promise<ReleaseGoodEntity[]> {
208
+ // Single query that gets release goods with their counts using aggregation
209
+ const releaseGoods: any[] = await tx
210
+ .getRepository(WorksheetEntity)
211
+ .createQueryBuilder('ws')
212
+ .select('rg.id', 'id')
213
+ .addSelect('rg.name', 'name')
214
+ .addSelect('rg.refNo', 'refNo')
215
+ .addSelect('rg.refNo2', 'refNo2')
216
+ .addSelect('rg.status', 'status')
217
+ .addSelect('rg.district', 'district')
218
+ .addSelect('rg.attention_company', 'attentionCompany')
219
+ .addSelect('rg.delivery_address_1', 'deliveryAddress1')
220
+ .addSelect('rg.delivery_address_2', 'deliveryAddress2')
221
+ .addSelect('rg.delivery_address_3', 'deliveryAddress3')
222
+ .addSelect('rg.delivery_address_4', 'deliveryAddress4')
223
+ .addSelect('rg.delivery_address_5', 'deliveryAddress5')
224
+ .addSelect('rg.created_at', 'createdAt')
225
+ .addSelect('u.name', 'sortedByUser')
226
+ // Counts computed directly in the same query
227
+ .addSelect('COUNT(oi.id)', 'totalCount')
228
+ .addSelect('SUM(CASE WHEN oi.sorted_qty = oi.release_qty THEN 1 ELSE 0 END)', 'completedCount')
229
+ .innerJoin(WorksheetDetailEntity, 'wsd', 'ws.id = wsd.worksheet_id')
230
+ .innerJoin(OrderInventoryEntity, 'oi', 'oi.id = wsd.target_inventory_id')
231
+ .innerJoin(ReleaseGoodEntity, 'rg', 'rg.id = oi.release_good_id')
232
+ .leftJoin(User, 'u', 'rg.sorted_by_id = u.id')
233
+ // Filter directly on ws.domain_id - no need to join Domain table
234
+ .where('ws.domain_id = :domainId', { domainId: domain.id })
235
+ .andWhere('ws.taskNo = :taskNo', { taskNo })
236
+ .andWhere('ws.type = :worksheetType', { worksheetType: WORKSHEET_TYPE.SORTING })
237
+ .andWhere('ws.status = :worksheetStatus', { worksheetStatus: WORKSHEET_STATUS.EXECUTING })
238
+ .groupBy('rg.id')
239
+ .addGroupBy('rg.name')
240
+ .addGroupBy('rg.refNo')
241
+ .addGroupBy('rg.refNo2')
242
+ .addGroupBy('rg.status')
243
+ .addGroupBy('rg.district')
244
+ .addGroupBy('rg.attention_company')
245
+ .addGroupBy('rg.delivery_address_1')
246
+ .addGroupBy('rg.delivery_address_2')
247
+ .addGroupBy('rg.delivery_address_3')
248
+ .addGroupBy('rg.delivery_address_4')
249
+ .addGroupBy('rg.delivery_address_5')
250
+ .addGroupBy('rg.created_at')
251
+ .addGroupBy('u.name')
252
+ .orderBy('rg.created_at', 'ASC')
253
+ .getRawMany()
254
+
255
+ // Transform results to include itemCounts
256
+ return releaseGoods.map(rg => {
257
+ const total = parseInt(rg.totalCount) || 0
258
+ const completed = parseInt(rg.completedCount) || 0
259
+ return {
260
+ id: rg.id,
261
+ name: rg.name,
262
+ refNo: rg.refNo,
263
+ refNo2: rg.refNo2,
264
+ status: rg.status,
265
+ district: rg.district,
266
+ attentionCompany: rg.attentionCompany,
267
+ deliveryAddress1: rg.deliveryAddress1,
268
+ deliveryAddress2: rg.deliveryAddress2,
269
+ deliveryAddress3: rg.deliveryAddress3,
270
+ deliveryAddress4: rg.deliveryAddress4,
271
+ deliveryAddress5: rg.deliveryAddress5,
272
+ sortedByUser: rg.sortedByUser,
273
+ itemCounts: {
274
+ total,
275
+ pending: total - completed
276
+ }
277
+ }
278
+ }) as ReleaseGoodEntity[]
279
+ }
280
+
18
281
  export const findSortingReleaseOrdersByTaskNoResolver = {
19
282
  async findSortingReleaseOrdersByTaskNo(_: any, { taskNo }, context: any) {
283
+ const startTime = Date.now()
20
284
  const { domain, tx, user }: { domain: Domain; tx: EntityManager; user: User } = context.state
21
285
 
22
- let selectedReleaseGood = null
23
- let ws = await tx
24
- .getRepository(WorksheetEntity)
25
- .createQueryBuilder('ws')
26
- .addSelect('rg.name', 'release_good_name')
27
- .addSelect('rg.status', 'release_good_status')
28
- .innerJoin('worksheet_details', 'wd', `ws.id = wd.worksheet_id`)
29
- .innerJoin('order_inventories', 'oi', `wd.target_inventory_id = oi.id and wd."type" ='SORTING'`)
30
- .innerJoin('release_goods', 'rg', `rg.id = oi.release_good_id`)
31
- .where('rg.domain_id = :domainId', { domainId: domain.id })
32
- .andWhere('rg.name = :name', { name: taskNo })
33
- .andWhere('rg.status IN (:...statuses)', {
34
- statuses: [ORDER_STATUS.READY_TO_SORT, ORDER_STATUS.SORTING, ORDER_STATUS.LOADING, ORDER_STATUS.DONE]
35
- })
36
- .andWhere('ws.type = :type', { type: WORKSHEET_TYPE.SORTING })
37
- .getRawOne()
38
-
39
- if (ws) {
40
- if (ws.release_good_status == 'LOADING' || ws.release_good_status == 'DONE') {
41
- throw new Error(`Release Good already sorted`)
42
- }
286
+ let selectedReleaseGood: string | null = null
287
+ let task: WorksheetEntity | null = null
288
+ let resolvedTaskNo = taskNo
289
+
290
+ // Step 1: Try to find by release good name first (most common case)
291
+ const releaseGoodResult = await findWorksheetByReleaseGoodName(tx, domain, taskNo)
43
292
 
44
- selectedReleaseGood = ws.release_good_name
45
- taskNo = ws.ws_task_no
293
+ if (releaseGoodResult) {
294
+ selectedReleaseGood = releaseGoodResult.selectedReleaseGood
295
+ resolvedTaskNo = releaseGoodResult.taskNo
296
+
297
+ // Only load worksheetDetails if we need them for activation
298
+ const needsActivation = releaseGoodResult.status === 'DEACTIVATED'
299
+ task = await findWorksheetByTaskNo(tx, domain, resolvedTaskNo, needsActivation)
46
300
  }
47
301
 
48
- let task = await tx.getRepository(WorksheetEntity).findOne({
49
- where: { taskNo, type: WORKSHEET_TYPE.SORTING, domain },
50
- relations: ['bizplace', 'bizplace.domain', 'worksheetDetails']
51
- })
302
+ // Step 2: Try to find by worksheet taskNo directly
303
+ if (!task) {
304
+ task = await findWorksheetByTaskNo(tx, domain, taskNo, false)
305
+ }
52
306
 
53
- // Find Task based on Bin
307
+ // Step 3: Try to find by bin location
54
308
  if (!task) {
55
- const binLocation: Location = await tx.getRepository(Location).findOne({
56
- where: { domain, name: taskNo }
57
- })
58
-
59
- if (binLocation) {
60
- const qb: SelectQueryBuilder<OrderInventoryEntity> = tx
61
- .getRepository(OrderInventoryEntity)
62
- .createQueryBuilder('orderInventory')
63
-
64
- qb.innerJoinAndSelect('orderInventory.releaseGood', 'releaseGood')
65
- .innerJoinAndSelect(
66
- 'worksheets',
67
- 'ws',
68
- `orderInventory.ref_worksheet_id = ws.id AND ws.type = 'BATCH_PICKING'`
69
- )
70
- .innerJoinAndSelect('worksheets', 'ws2', `ws2.task_no = ws.task_no AND ws2.type = 'SORTING'`)
71
- .innerJoinAndSelect('releaseGood.bizplace', 'bizplace')
72
- .innerJoinAndSelect('bizplace.domain', 'domain')
73
- .where('orderInventory.domain_id = :domainId', { domainId: domain.id })
74
- .andWhere('orderInventory.status IN (:...orderInventoryStatus)', {
75
- orderInventoryStatus: [ORDER_INVENTORY_STATUS.READY_TO_SORT, ORDER_INVENTORY_STATUS.SORTING]
76
- })
77
- .andWhere('orderInventory.bin_location_id = :locationId', { locationId: binLocation.id })
78
- .andWhere('releaseGood.status IN (:...statuses)', {
79
- statuses: [ORDER_STATUS.READY_TO_SORT, ORDER_STATUS.SORTING]
80
- })
81
-
82
- const orderInventoryByBin = await qb.getRawOne()
83
- if (orderInventoryByBin?.releaseGood_id) {
84
- taskNo = orderInventoryByBin.ws_task_no
85
- task = await tx.getRepository(WorksheetEntity).findOne({
86
- where: {
87
- taskNo,
88
- status: In([WORKSHEET_STATUS.DEACTIVATED, WORKSHEET_STATUS.EXECUTING]),
89
- type: WORKSHEET_TYPE.SORTING,
90
- domain
91
- },
92
- relations: ['worksheetDetails']
93
- })
94
- } else {
95
- throw new Error(`Bin do not have any batch picking order.`)
96
- }
309
+ const binResult = await findWorksheetByBinLocation(tx, domain, taskNo)
310
+
311
+ if (binResult) {
312
+ resolvedTaskNo = binResult.taskNo
313
+ // Only load worksheetDetails if we need them for activation
314
+ const needsActivation = binResult.status === 'DEACTIVATED'
315
+ task = await findWorksheetByTaskNo(tx, domain, resolvedTaskNo, needsActivation)
97
316
  }
98
317
  }
99
318
 
100
- if (!task) throw new Error('Unable to find task no.')
101
-
102
- if (task.status === 'DEACTIVATED') {
103
- const sortingWSCtrl: SortingWorksheetController = new SortingWorksheetController(tx, domain, user)
104
-
105
- const directActivateSortingWorksheet: Setting = await tx.getRepository(Setting).findOne({
106
- where: { domain: domain, category: 'id-rule', name: 'enable-direct-activate-sorting-worksheet' }
107
- })
108
-
109
- const partnerDirectActivateSortingWorksheetSetting: PartnerSetting = await tx
110
- .getRepository(PartnerSetting)
111
- .findOne({
112
- where: {
113
- setting: directActivateSortingWorksheet,
114
- domain: domain,
115
- partnerDomain: task.bizplace?.domain
116
- }
117
- })
118
-
119
- if (directActivateSortingWorksheet != undefined && directActivateSortingWorksheet.value.toLowerCase() == 'true') {
120
- if (partnerDirectActivateSortingWorksheetSetting != undefined) {
121
- if (partnerDirectActivateSortingWorksheetSetting.value.toLowerCase() == 'true')
122
- await sortingWSCtrl.activateSorting(task.name, task.worksheetDetails)
123
- } else {
124
- await sortingWSCtrl.activateSorting(task.name, task.worksheetDetails)
125
- }
126
- } else {
127
- throw new Error('Kindly go to sorting worksheet page to activate the sorting worksheet')
128
- }
319
+ if (!task) {
320
+ throw new Error('Unable to find task no.')
129
321
  }
130
322
 
131
- const qb: SelectQueryBuilder<WorksheetEntity> = tx
132
- .getRepository(WorksheetEntity)
133
- .createQueryBuilder('ws')
134
- .select('rg.id as id')
135
- .addSelect('rg.name as name')
136
- .addSelect('rg.refNo as "refNo"')
137
- .addSelect('rg.refNo2 as "refNo2"')
138
- .addSelect('rg.status as status')
139
- .addSelect('rg.district as "district"')
140
- .addSelect('rg.attention_company as "attentionCompany"')
141
- .addSelect('rg.delivery_address_1 as "deliveryAddress1"')
142
- .addSelect('rg.delivery_address_2 as "deliveryAddress2"')
143
- .addSelect('rg.delivery_address_3 as "deliveryAddress3"')
144
- .addSelect('rg.delivery_address_4 as "deliveryAddress4"')
145
- .addSelect('rg.delivery_address_5 as "deliveryAddress5"')
146
- .addSelect('user.name as "sortedByUser"')
147
- .innerJoin(Domain, 'domain', 'ws.domain_id = domain.id')
148
- .innerJoin(WorksheetDetailEntity, 'wsd', 'ws.id = wsd.worksheet_id')
149
- .innerJoin(OrderInventoryEntity, 'oi', 'oi.id = wsd.target_inventory_id')
150
- .innerJoin(ReleaseGoodEntity, 'rg', 'rg.id = oi.release_good_id')
151
- .leftJoin(User, 'user', 'rg.sorted_by_id = user.id')
152
- .where('domain.id = :domainId', { domainId: domain.id })
153
- .andWhere('ws.taskNo = :taskNo', { taskNo: taskNo })
154
- .andWhere('ws.type = :worksheetType', { worksheetType: WORKSHEET_TYPE.SORTING })
155
- .andWhere('ws.status = :worksheetStatus', { worksheetStatus: WORKSHEET_STATUS.EXECUTING })
156
- .groupBy('rg.id')
157
- .addGroupBy('rg.name')
158
- .addGroupBy('rg.status')
159
- .addGroupBy('user.name')
160
- .orderBy('rg.createdAt', 'ASC')
161
-
162
- const releaseGoods: ReleaseGoodEntity[] = await qb.getRawMany()
163
-
164
- if (releaseGoods.length > 0) {
165
- // Get counts for all release goods in a single query (avoids N+1 problem)
166
- const releaseGoodIds = releaseGoods.map(rg => rg.id)
167
- const countsResult = await tx
168
- .getRepository(OrderInventoryEntity)
169
- .createQueryBuilder('orderInventory')
170
- .innerJoin(WorksheetDetailEntity, 'wsd', 'orderInventory.id = wsd.target_inventory_id')
171
- .innerJoin(WorksheetEntity, 'ws', 'wsd.worksheet_id = ws.id')
172
- .select('orderInventory.release_good_id', 'releaseGoodId')
173
- .addSelect('COUNT(*)', 'total')
174
- .addSelect(
175
- 'SUM(CASE WHEN orderInventory.sortedQty = orderInventory.releaseQty THEN 1 ELSE 0 END)',
176
- 'completed'
177
- )
178
- .where('orderInventory.release_good_id IN (:...releaseGoodIds)', { releaseGoodIds })
179
- .andWhere('orderInventory.domain_id = :domainId', { domainId: domain.id })
180
- .andWhere('ws.taskNo = :taskNo', { taskNo: taskNo })
181
- .andWhere('ws.type = :worksheetType', { worksheetType: WORKSHEET_TYPE.SORTING })
182
- .andWhere('ws.status = :worksheetStatus', { worksheetStatus: WORKSHEET_STATUS.EXECUTING })
183
- .groupBy('orderInventory.release_good_id')
184
- .getRawMany()
185
-
186
- // Build a map for quick lookup
187
- const countsById = new Map(
188
- countsResult.map(c => [
189
- c.releaseGoodId,
190
- { total: parseInt(c.total) || 0, completed: parseInt(c.completed) || 0 }
191
- ])
192
- )
193
-
194
- // Assign itemCounts to each release good
195
- for (const releaseGood of releaseGoods) {
196
- const counts = countsById.get(releaseGood.id) || { total: 0, completed: 0 }
197
- releaseGood['itemCounts'] = {
198
- total: counts.total,
199
- pending: counts.total - counts.completed
200
- }
201
- }
323
+ // Step 4: Handle activation if needed
324
+ await handleWorksheetActivation(tx, domain, user, task)
325
+
326
+ // Step 5: Get release goods with counts
327
+ const releaseGoods = await getReleaseGoodsWithCounts(tx, domain, resolvedTaskNo)
328
+
329
+ // Performance logging (only in development/debug mode)
330
+ const elapsed = Date.now() - startTime
331
+ if (elapsed > 1000) {
332
+ console.warn(`[PERF] findSortingReleaseOrdersByTaskNo took ${elapsed}ms for taskNo: ${taskNo}`)
202
333
  }
203
334
 
204
- return { releaseGoods, taskNo, selectedReleaseGood }
335
+ return { releaseGoods, taskNo: resolvedTaskNo, selectedReleaseGood }
205
336
  }
206
337
  }