@things-factory/operato-wms 4.3.752 → 4.3.755

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/client/pages/inbound/unload-product.js +30 -33
  2. package/client/pages/outbound/loading-product.js +2 -3
  3. package/client/pages/outbound/loading-v2/loading-execution-base.js +568 -56
  4. package/client/pages/outbound/loading-v2/loading-execution.js +258 -8
  5. package/client/pages/outbound/loading-v2/loading.js +82 -12
  6. package/client/pages/outbound/picking-product.js +11 -6
  7. package/client/pages/outbound/picking-v2/picking-execution-base.js +8 -8
  8. package/client/pages/outbound/picking-v2/picking-execution.js +75 -0
  9. package/client/pages/outbound/route-label-history-dialog.js +253 -0
  10. package/client/pages/outbound/route-label-popup.js +637 -131
  11. package/client/pages/outbound/show-ro-list-popup.js +8 -4
  12. package/client/pages/outbound/single-outbound-worksheet.js +55 -6
  13. package/client/pages/outbound/sorting-product.js +71 -25
  14. package/client/pages/outbound/zone-worksheet.js +62 -3
  15. package/dist-server/entities/index.js +9 -0
  16. package/dist-server/entities/index.js.map +1 -0
  17. package/dist-server/entities/route-label-sequence-counter.js +75 -0
  18. package/dist-server/entities/route-label-sequence-counter.js.map +1 -0
  19. package/dist-server/entities/route-label-sequence-log.js +74 -0
  20. package/dist-server/entities/route-label-sequence-log.js.map +1 -0
  21. package/dist-server/graphql/resolvers/index.js +3 -0
  22. package/dist-server/graphql/resolvers/index.js.map +1 -1
  23. package/dist-server/graphql/resolvers/outbound/complete-load.js +40 -3
  24. package/dist-server/graphql/resolvers/outbound/complete-load.js.map +1 -1
  25. package/dist-server/graphql/resolvers/outbound/find-loadable-release-good-by-bin.js +50 -11
  26. package/dist-server/graphql/resolvers/outbound/find-loadable-release-good-by-bin.js.map +1 -1
  27. package/dist-server/graphql/resolvers/outbound/find-loadable-release-good.js +90 -48
  28. package/dist-server/graphql/resolvers/outbound/find-loadable-release-good.js.map +1 -1
  29. package/dist-server/graphql/resolvers/outbound/loading-worksheet-v2.js +15 -7
  30. package/dist-server/graphql/resolvers/outbound/loading-worksheet-v2.js.map +1 -1
  31. package/dist-server/graphql/resolvers/outbound/sort-item.js +95 -16
  32. package/dist-server/graphql/resolvers/outbound/sort-item.js.map +1 -1
  33. package/dist-server/graphql/resolvers/route-label/index.js +7 -0
  34. package/dist-server/graphql/resolvers/route-label/index.js.map +1 -0
  35. package/dist-server/graphql/resolvers/route-label/route-label.js +220 -0
  36. package/dist-server/graphql/resolvers/route-label/route-label.js.map +1 -0
  37. package/dist-server/graphql/resolvers/zone-worksheet/index.js.map +1 -1
  38. package/dist-server/graphql/resolvers/zone-worksheet/zone-picking.js +123 -27
  39. package/dist-server/graphql/resolvers/zone-worksheet/zone-picking.js.map +1 -1
  40. package/dist-server/graphql/resolvers/zone-worksheet/zone-worksheet.js.map +1 -1
  41. package/dist-server/graphql/types/index.js +4 -0
  42. package/dist-server/graphql/types/index.js.map +1 -1
  43. package/dist-server/graphql/types/outbound/index.js +7 -1
  44. package/dist-server/graphql/types/outbound/index.js.map +1 -1
  45. package/dist-server/graphql/types/route-label/index.js +14 -0
  46. package/dist-server/graphql/types/route-label/index.js.map +1 -0
  47. package/dist-server/graphql/types/route-label/route-label-sequence.js +53 -0
  48. package/dist-server/graphql/types/route-label/route-label-sequence.js.map +1 -0
  49. package/dist-server/index.js +5 -0
  50. package/dist-server/index.js.map +1 -1
  51. package/dist-server/validators/setting-validators.js +519 -0
  52. package/dist-server/validators/setting-validators.js.map +1 -0
  53. package/helps/operato-wms/outbound/picking-product.en.md +156 -158
  54. package/package.json +50 -50
  55. package/server/entities/index.ts +6 -0
  56. package/server/entities/route-label-sequence-counter.ts +56 -0
  57. package/server/entities/route-label-sequence-log.ts +47 -0
  58. package/server/graphql/resolvers/index.ts +3 -0
  59. package/server/graphql/resolvers/outbound/complete-load.ts +42 -1
  60. package/server/graphql/resolvers/outbound/find-loadable-release-good-by-bin.ts +56 -13
  61. package/server/graphql/resolvers/outbound/find-loadable-release-good.ts +120 -57
  62. package/server/graphql/resolvers/outbound/loading-worksheet-v2.ts +9 -2
  63. package/server/graphql/resolvers/outbound/sort-item.ts +125 -21
  64. package/server/graphql/resolvers/route-label/index.ts +16 -0
  65. package/server/graphql/resolvers/route-label/route-label.ts +264 -0
  66. package/server/graphql/resolvers/zone-worksheet/index.ts +2 -2
  67. package/server/graphql/resolvers/zone-worksheet/zone-picking.ts +156 -39
  68. package/server/graphql/resolvers/zone-worksheet/zone-worksheet.ts +1 -2
  69. package/server/graphql/types/index.ts +4 -0
  70. package/server/graphql/types/outbound/index.ts +7 -1
  71. package/server/graphql/types/route-label/index.ts +18 -0
  72. package/server/graphql/types/route-label/route-label-sequence.ts +50 -0
  73. package/server/index.ts +7 -1
  74. package/server/validators/setting-validators.ts +668 -0
  75. package/translations/en.json +280 -252
  76. package/translations/ko.json +29 -1
  77. package/translations/ms.json +28 -0
  78. package/translations/zh.json +28 -0
@@ -3,8 +3,49 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.sortItem = void 0;
4
4
  const typeorm_1 = require("typeorm");
5
5
  const sales_base_1 = require("@things-factory/sales-base");
6
+ const warehouse_base_1 = require("@things-factory/warehouse-base");
7
+ /**
8
+ * Calculates the available quantity that can still be sorted for an order inventory
9
+ */
10
+ function getAvailableQty(oi) {
11
+ const available = Math.min(oi.releaseQty, oi.pickedQty) - oi.sortedQty;
12
+ return available > 0 ? available : 0;
13
+ }
14
+ /**
15
+ * Creates or updates an order tote item with the given quantity
16
+ */
17
+ async function upsertOrderToteItem(tx, domain, user, orderTote, orderInventory, qtyToAdd) {
18
+ var _a;
19
+ const orderToteItemRepo = tx.getRepository(sales_base_1.OrderToteItem);
20
+ const existingItem = (await orderToteItemRepo.findOne({
21
+ where: {
22
+ domain,
23
+ orderTote,
24
+ orderInventory,
25
+ orderProduct: orderInventory.orderProduct
26
+ }
27
+ }));
28
+ if (!existingItem) {
29
+ await orderToteItemRepo.save({
30
+ domain,
31
+ name: sales_base_1.OrderNoGenerator.orderToteItem(),
32
+ orderTote,
33
+ orderInventory,
34
+ orderProduct: orderInventory.orderProduct,
35
+ qty: qtyToAdd,
36
+ updater: user
37
+ });
38
+ }
39
+ else {
40
+ await orderToteItemRepo.update(existingItem.id, {
41
+ qty: Number((_a = existingItem.qty) !== null && _a !== void 0 ? _a : 0) + qtyToAdd,
42
+ updater: user,
43
+ updatedAt: new Date()
44
+ });
45
+ }
46
+ }
6
47
  exports.sortItem = {
7
- async sortItem(_, { releaseGoodNo, productBarcode, qty, worksheetDetails }, context) {
48
+ async sortItem(_, { releaseGoodNo, productBarcode, qty, worksheetDetails, toteNo }, context) {
8
49
  const { domain, user, tx } = context.state;
9
50
  // Single query to get order inventories based on either releaseGood name or binLocation
10
51
  const orderInventories = await tx
@@ -12,20 +53,17 @@ exports.sortItem = {
12
53
  .createQueryBuilder('orderInventory')
13
54
  .innerJoinAndSelect('orderInventory.productDetail', 'productDetail')
14
55
  .innerJoinAndSelect('productDetail.productBarcodes', 'productBarcode')
56
+ .leftJoinAndSelect('orderInventory.orderProduct', 'orderProduct')
15
57
  .leftJoinAndSelect('orderInventory.releaseGood', 'releaseGood')
58
+ .leftJoinAndSelect('releaseGood.bizplace', 'bizplace')
16
59
  .leftJoinAndSelect('orderInventory.binLocation', 'binLocation')
17
60
  .where('orderInventory.domain_id = :domainId', { domainId: domain.id })
18
61
  .andWhere('orderInventory.status IN (:...statuses)', {
19
- statuses: [
20
- sales_base_1.ORDER_INVENTORY_STATUS.SORTING,
21
- sales_base_1.ORDER_INVENTORY_STATUS.LOADING
22
- ]
62
+ statuses: [sales_base_1.ORDER_INVENTORY_STATUS.SORTING, sales_base_1.ORDER_INVENTORY_STATUS.LOADING]
23
63
  })
24
64
  .andWhere('productBarcode.gtin = :gtin', { gtin: productBarcode })
25
65
  .andWhere(new typeorm_1.Brackets(qb => {
26
- qb
27
- .where('orderInventory.sortedQty < orderInventory.pickedQty')
28
- .andWhere('orderInventory.sortedQty < orderInventory.releaseQty');
66
+ qb.where('orderInventory.sortedQty < orderInventory.pickedQty').andWhere('orderInventory.sortedQty < orderInventory.releaseQty');
29
67
  }))
30
68
  .andWhere(new typeorm_1.Brackets(qb => {
31
69
  qb.where('releaseGood.name = :releaseGoodNo', { releaseGoodNo }).orWhere('binLocation.name = :releaseGoodNo', { releaseGoodNo });
@@ -33,11 +71,49 @@ exports.sortItem = {
33
71
  .getMany();
34
72
  if (!orderInventories.length)
35
73
  throw new Error('No matching product barcode found');
36
- // Calculate total available quantity (minimum of releaseQty and pickedQty for each order inventory)
37
- const totalAvailableQty = orderInventories.reduce((sum, oi) => {
38
- const availableQty = Math.min(oi.releaseQty, oi.pickedQty) - oi.sortedQty;
39
- return sum + (availableQty > 0 ? availableQty : 0);
40
- }, 0);
74
+ let resolvedReleaseGood = null;
75
+ let resolvedOrderTote = null;
76
+ if (toteNo) {
77
+ // Ensure we can identify a single release order when scanning by BIN
78
+ const uniqueReleaseGoodIds = [...new Set(orderInventories.map(oi => oi.releaseGoodId).filter(Boolean))];
79
+ if (uniqueReleaseGoodIds.length > 1) {
80
+ throw new Error('Multiple release orders detected. Please select a release order before tote scanning.');
81
+ }
82
+ resolvedReleaseGood = await tx.getRepository(sales_base_1.ReleaseGood).findOne({
83
+ where: { domain, id: uniqueReleaseGoodIds[0] },
84
+ relations: ['bizplace']
85
+ });
86
+ if (!resolvedReleaseGood) {
87
+ throw new Error('Release good not found for tote scanning');
88
+ }
89
+ resolvedOrderTote = await tx.getRepository(sales_base_1.OrderTote).findOne({
90
+ where: { domain, name: toteNo, releaseGood: resolvedReleaseGood }
91
+ });
92
+ if (!resolvedOrderTote) {
93
+ // Query for valid totes (NOT dispatched or damaged)
94
+ const foundTote = await tx.getRepository(warehouse_base_1.Tote).findOne({
95
+ where: {
96
+ bizplace: resolvedReleaseGood.bizplace,
97
+ name: toteNo,
98
+ deletedAt: (0, typeorm_1.IsNull)(),
99
+ status: (0, typeorm_1.Not)((0, typeorm_1.In)([warehouse_base_1.TOTE_STATUS.DISPATCHED, warehouse_base_1.TOTE_STATUS.DAMAGED]))
100
+ }
101
+ });
102
+ resolvedOrderTote = await tx.getRepository(sales_base_1.OrderTote).save({
103
+ name: toteNo,
104
+ domain,
105
+ releaseGood: resolvedReleaseGood,
106
+ tote: foundTote !== null && foundTote !== void 0 ? foundTote : null,
107
+ creator: user,
108
+ updater: user
109
+ });
110
+ }
111
+ else if (resolvedOrderTote.closedDate) {
112
+ throw new Error('Tote has been sealed, please try another tote!');
113
+ }
114
+ }
115
+ // Calculate total available quantity using helper function
116
+ const totalAvailableQty = orderInventories.reduce((sum, oi) => sum + getAvailableQty(oi), 0);
41
117
  if (qty > totalAvailableQty) {
42
118
  throw new Error(`Sort qty (${qty}) exceeds total available quantity (${totalAvailableQty})`);
43
119
  }
@@ -46,18 +122,21 @@ exports.sortItem = {
46
122
  for (const orderInventory of orderInventories) {
47
123
  if (remainingQty <= 0)
48
124
  break;
49
- const availableQty = Math.min(orderInventory.releaseQty, orderInventory.pickedQty) - orderInventory.sortedQty;
125
+ const availableQty = getAvailableQty(orderInventory);
50
126
  if (availableQty <= 0)
51
127
  continue;
52
128
  const qtyToAdd = Math.min(remainingQty, availableQty);
53
- const newSortQty = orderInventory.sortedQty + qtyToAdd;
54
129
  // Update the order inventory
55
130
  await tx.getRepository(sales_base_1.OrderInventory).update(orderInventory.id, {
56
- sortedQty: newSortQty,
131
+ sortedQty: orderInventory.sortedQty + qtyToAdd,
57
132
  status: sales_base_1.ORDER_INVENTORY_STATUS.LOADING,
58
133
  updatedAt: new Date(),
59
134
  updater: user
60
135
  });
136
+ // Create / update order tote items to reflect tote allocation during QC
137
+ if (resolvedOrderTote) {
138
+ await upsertOrderToteItem(tx, domain, user, resolvedOrderTote, orderInventory, qtyToAdd);
139
+ }
61
140
  remainingQty -= qtyToAdd;
62
141
  }
63
142
  return true;
@@ -1 +1 @@
1
- {"version":3,"file":"sort-item.js","sourceRoot":"","sources":["../../../../server/graphql/resolvers/outbound/sort-item.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sort-item.js","sourceRoot":"","sources":["../../../../server/graphql/resolvers/outbound/sort-item.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Mutation = exports.Query = void 0;
4
+ const route_label_1 = require("./route-label");
5
+ exports.Query = Object.assign(Object.assign(Object.assign({}, route_label_1.routeLabelReleaseGoodsInExecutingWorksheet), route_label_1.routeLabelSequenceStatuses), route_label_1.routeLabelSequenceLogs);
6
+ exports.Mutation = Object.assign({}, route_label_1.reserveRouteLabelSequence);
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../server/graphql/resolvers/route-label/index.ts"],"names":[],"mappings":";;;AAAA,+CAKsB;AAET,QAAA,KAAK,iDACb,wDAA0C,GAC1C,wCAA0B,GAC1B,oCAAsB,EAC1B;AAEY,QAAA,QAAQ,qBAChB,uCAAyB,EAC7B"}
@@ -0,0 +1,220 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.routeLabelSequenceLogs = exports.reserveRouteLabelSequence = exports.routeLabelSequenceStatuses = exports.routeLabelReleaseGoodsInExecutingWorksheet = void 0;
4
+ const typeorm_1 = require("typeorm");
5
+ const worksheet_base_1 = require("@things-factory/worksheet-base");
6
+ const route_label_sequence_counter_1 = require("../../../entities/route-label-sequence-counter");
7
+ const route_label_sequence_log_1 = require("../../../entities/route-label-sequence-log");
8
+ function ensureSeqField(field) {
9
+ if (!['refNo', 'refNo2', 'refNo3'].includes(field)) {
10
+ throw new Error('Invalid sequence field. Allowed: refNo, refNo2, refNo3');
11
+ }
12
+ }
13
+ function parseNonNegativeInt(value) {
14
+ const n = parseInt(value !== null && value !== void 0 ? value : '0', 10);
15
+ return Number.isFinite(n) ? Math.max(0, n) : 0;
16
+ }
17
+ exports.routeLabelReleaseGoodsInExecutingWorksheet = {
18
+ async routeLabelReleaseGoodsInExecutingWorksheet(_, { partnerId, refNo, worksheetType, seqField }, context) {
19
+ const { domain, tx } = context.state;
20
+ let filterRefNo = '';
21
+ if (refNo) {
22
+ const removeSymbol = refNo
23
+ .split('')
24
+ .filter(res => res !== '%')
25
+ .join('');
26
+ const filterInfos = removeSymbol
27
+ .toLowerCase()
28
+ .split(',')
29
+ .map(value => "'%" + value.trim().replace(/'/g, "''") + "%'")
30
+ .join(',');
31
+ filterRefNo = ` and (
32
+ lower(rg.ref_no) like any(array[${filterInfos}])
33
+ or lower(rg.ref_no_2) like any(array[${filterInfos}])
34
+ or lower(rg.ref_no_3) like any(array[${filterInfos}])
35
+ )`;
36
+ }
37
+ const rows = await tx.query(`
38
+ select distinct
39
+ rg.id as "id",
40
+ rg.name as "name",
41
+ rg.ref_no as "refNo",
42
+ rg.ref_no_2 as "refNo2",
43
+ rg.ref_no_3 as "refNo3",
44
+ rg.route_id as "routeId",
45
+ rg.store_id as "storeId",
46
+ rg.store_name as "storeName",
47
+ rg.stop_id as "stopId",
48
+ rg.created_at as "createdAt"
49
+ from worksheets ws
50
+ inner join worksheet_details wsd on wsd.worksheet_id = ws.id
51
+ inner join order_inventories oi on oi.id = wsd.target_inventory_id
52
+ inner join release_goods rg on rg.id = oi.release_good_id
53
+ where ws.domain_id = $1
54
+ and ws.type = $2
55
+ and ws.status = $3
56
+ and rg.domain_id = $1
57
+ and rg.bizplace_id = $4
58
+ ${filterRefNo}
59
+ order by rg.created_at desc
60
+ `, [domain.id, worksheetType, worksheet_base_1.WORKSHEET_STATUS.EXECUTING, partnerId]);
61
+ const releaseGoods = rows || [];
62
+ // If seqField is provided, fetch and merge sequence data
63
+ if (seqField && ['refNo', 'refNo2', 'refNo3'].includes(seqField) && releaseGoods.length > 0) {
64
+ const releaseGoodIds = releaseGoods.map((rg) => rg.id);
65
+ // Fetch lastSeq from counters
66
+ const lastSeqById = new Map();
67
+ const counterRepo = tx.getRepository(route_label_sequence_counter_1.RouteLabelSequenceCounter);
68
+ const counters = await counterRepo.find({
69
+ where: { domain, releaseGoodId: (0, typeorm_1.In)(releaseGoodIds), field: seqField }
70
+ });
71
+ for (const c of counters) {
72
+ lastSeqById.set(c.releaseGoodId, parseNonNegativeInt(c.lastSeq));
73
+ }
74
+ // Fetch lastPrintedBy from logs (most recent per releaseGood)
75
+ const lastPrintedById = new Map();
76
+ const logRepo = tx.getRepository(route_label_sequence_log_1.RouteLabelSequenceLog);
77
+ const logs = await logRepo.find({
78
+ where: { domain, releaseGoodId: (0, typeorm_1.In)(releaseGoodIds), field: seqField },
79
+ relations: ['creator'],
80
+ order: { createdAt: 'DESC' },
81
+ take: 500
82
+ });
83
+ for (const log of logs) {
84
+ if (!lastPrintedById.has(log.releaseGoodId) && log.creator) {
85
+ lastPrintedById.set(log.releaseGoodId, log.creator.name || '');
86
+ }
87
+ }
88
+ // Merge sequence data into release goods
89
+ return releaseGoods.map((rg) => (Object.assign(Object.assign({}, rg), { lastSeq: lastSeqById.get(rg.id) || 0, lastPrintedBy: lastPrintedById.get(rg.id) || null })));
90
+ }
91
+ return releaseGoods;
92
+ }
93
+ };
94
+ exports.routeLabelSequenceStatuses = {
95
+ async routeLabelSequenceStatuses(_, { releaseGoodIds, field }, context) {
96
+ const { domain, tx } = context.state;
97
+ ensureSeqField(field);
98
+ const lastSeqById = new Map();
99
+ const counterRepo = tx.getRepository(route_label_sequence_counter_1.RouteLabelSequenceCounter);
100
+ const counters = await counterRepo.find({
101
+ where: { domain, releaseGoodId: (0, typeorm_1.In)(releaseGoodIds), field }
102
+ });
103
+ for (const c of counters) {
104
+ lastSeqById.set(c.releaseGoodId, parseNonNegativeInt(c.lastSeq));
105
+ }
106
+ const histById = new Map();
107
+ const lastPrintedById = new Map();
108
+ const logRepo = tx.getRepository(route_label_sequence_log_1.RouteLabelSequenceLog);
109
+ const logs = await logRepo.find({
110
+ where: { domain, releaseGoodId: (0, typeorm_1.In)(releaseGoodIds), field },
111
+ relations: ['creator'],
112
+ order: { createdAt: 'DESC' },
113
+ take: 500
114
+ });
115
+ for (const log of logs) {
116
+ const list = histById.get(log.releaseGoodId) || [];
117
+ if (list.length >= 5)
118
+ continue;
119
+ list.push(`${log.from}-${log.to}`);
120
+ histById.set(log.releaseGoodId, list);
121
+ // Store the creator name from the most recent log entry (first one due to DESC order)
122
+ if (!lastPrintedById.has(log.releaseGoodId) && log.creator) {
123
+ lastPrintedById.set(log.releaseGoodId, log.creator.name || '');
124
+ }
125
+ }
126
+ return releaseGoodIds.map((releaseGoodId) => {
127
+ return {
128
+ releaseGoodId,
129
+ field,
130
+ lastSeq: lastSeqById.get(releaseGoodId) || 0,
131
+ history: histById.get(releaseGoodId) || [],
132
+ lastPrintedBy: lastPrintedById.get(releaseGoodId) || null
133
+ };
134
+ });
135
+ }
136
+ };
137
+ exports.reserveRouteLabelSequence = {
138
+ async reserveRouteLabelSequence(_, { releaseGoodId, field, qty }, context) {
139
+ const { domain, tx, user } = context.state;
140
+ ensureSeqField(field);
141
+ const q = parseNonNegativeInt(qty);
142
+ if (q <= 0) {
143
+ throw new Error('Print qty must be greater than 0');
144
+ }
145
+ const counterRepo = tx.getRepository(route_label_sequence_counter_1.RouteLabelSequenceCounter);
146
+ const logRepo = tx.getRepository(route_label_sequence_log_1.RouteLabelSequenceLog);
147
+ // Lock counter row to avoid duplicated sequences under concurrent prints.
148
+ let counter = await counterRepo
149
+ .createQueryBuilder('c')
150
+ .setLock('pessimistic_write')
151
+ .where('c.domain = :domainId and c.releaseGoodId = :releaseGoodId and c.field = :field', {
152
+ domainId: domain.id,
153
+ releaseGoodId,
154
+ field
155
+ })
156
+ .getOne();
157
+ if (!counter) {
158
+ try {
159
+ await counterRepo.save({
160
+ domain,
161
+ releaseGoodId,
162
+ field,
163
+ lastSeq: 0,
164
+ creator: user,
165
+ updater: user
166
+ });
167
+ }
168
+ catch (e) {
169
+ // ignore: concurrent insert can violate unique index
170
+ }
171
+ counter = await counterRepo
172
+ .createQueryBuilder('c')
173
+ .setLock('pessimistic_write')
174
+ .where('c.domain = :domainId and c.releaseGoodId = :releaseGoodId and c.field = :field', {
175
+ domainId: domain.id,
176
+ releaseGoodId,
177
+ field
178
+ })
179
+ .getOne();
180
+ }
181
+ if (!counter) {
182
+ throw new Error('Failed to initialize route label sequence counter');
183
+ }
184
+ const last = parseNonNegativeInt(counter.lastSeq);
185
+ const from = last + 1;
186
+ const to = last + q;
187
+ await counterRepo.update(counter.id, { lastSeq: to, updater: user, updatedAt: new Date() });
188
+ await logRepo.save({ domain, releaseGoodId, field, from, to, qty: q, creator: user });
189
+ return { releaseGoodId, field, from, to };
190
+ }
191
+ };
192
+ exports.routeLabelSequenceLogs = {
193
+ async routeLabelSequenceLogs(_, { releaseGoodId, field }, context) {
194
+ const { domain, tx } = context.state;
195
+ ensureSeqField(field);
196
+ const rows = (await tx.query(`
197
+ select
198
+ l.id as "id",
199
+ l.release_good_id as "releaseGoodId",
200
+ l.field as "field",
201
+ l."from" as "from",
202
+ l."to" as "to",
203
+ l.qty as "qty",
204
+ l.created_at as "createdAt",
205
+ u.name as "creatorName"
206
+ from route_label_sequence_logs l
207
+ left join users u on u.id = l.creator_id
208
+ where l.domain_id = $1
209
+ and l.release_good_id = $2
210
+ and l.field = $3
211
+ order by l.created_at desc
212
+ limit 200
213
+ `, [domain.id, releaseGoodId, field])) || [];
214
+ return rows.map((row) => {
215
+ const createdAt = row.createdAt ? new Date(row.createdAt) : null;
216
+ return Object.assign(Object.assign({}, row), { createdAt: createdAt ? createdAt.toISOString() : null });
217
+ });
218
+ }
219
+ };
220
+ //# sourceMappingURL=route-label.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-label.js","sourceRoot":"","sources":["../../../../server/graphql/resolvers/route-label/route-label.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../server/graphql/resolvers/zone-worksheet/index.ts"],"names":[],"mappings":";;;AAAA,qDAA8E;AAC9E,uEAAyE;AACzE,uEAA0G;AAC1G,iDAA4C;AAC5C,mDAA8C;AAC9C,mEAA4D;AAE/C,QAAA,KAAK,mCACb,sCAAqB,GACrB,qCAAoB,EACxB;AAEY,QAAA,QAAQ,2FAChB,sDAA4B,GAC5B,sDAA4B,GAC5B,0DAAgC,GAChC,0BAAW,GACX,4BAAY,GACZ,0CAAkB,EACtB"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../server/graphql/resolvers/zone-worksheet/index.ts"],"names":[],"mappings":";;;AAAA,qDAA8E;AAC9E,uEAAwE;AACxE,uEAA0G;AAC1G,iDAA4C;AAC5C,mDAA8C;AAC9C,mEAA4D;AAE/C,QAAA,KAAK,mCACb,sCAAqB,GACrB,qCAAoB,EACxB;AAEY,QAAA,QAAQ,2FAChB,sDAA4B,GAC5B,sDAA4B,GAC5B,0DAAgC,GAChC,0BAAW,GACX,4BAAY,GACZ,0CAAkB,EACtB"}
@@ -6,6 +6,7 @@ const worksheet_base_1 = require("@things-factory/worksheet-base");
6
6
  const sales_base_1 = require("@things-factory/sales-base");
7
7
  const warehouse_base_1 = require("@things-factory/warehouse-base");
8
8
  const product_base_1 = require("@things-factory/product-base");
9
+ const setting_base_1 = require("@things-factory/setting-base");
9
10
  const uuid_1 = require("uuid");
10
11
  exports.zonePicking = {
11
12
  async scanProductZonePicking(_, { worksheetId, cartonId, productBarcode, binNo, pickingQty }, context) {
@@ -244,11 +245,51 @@ async function completeZonePicking(worksheetId, context, isPartial) {
244
245
  });
245
246
  }
246
247
  else if (!isPartial) {
247
- await tx.getRepository(sales_base_1.ReleaseGood).update({ id: (0, typeorm_1.In)(roIds), status: sales_base_1.ORDER_STATUS.PARTIAL_PROCESSING }, {
248
- status: sales_base_1.ORDER_STATUS.PROCESSING,
249
- updater: user,
250
- updatedAt: new Date()
248
+ // When completing fully, check if all OrderInventories for each ReleaseGood are actually completed
249
+ // Only update from PARTIAL_PROCESSING to PROCESSING if all OrderInventories are completed
250
+ const releaseGoods = await tx.getRepository(sales_base_1.ReleaseGood).find({
251
+ where: { id: (0, typeorm_1.In)(roIds) },
252
+ relations: ['orderInventories']
251
253
  });
254
+ const completedRoIds = [];
255
+ const incompleteRoIds = [];
256
+ for (const rg of releaseGoods) {
257
+ // Check if all OrderInventories are in a completed state (not PROCESSING)
258
+ const completedStatuses = [
259
+ sales_base_1.ORDER_INVENTORY_STATUS.PICKED,
260
+ sales_base_1.ORDER_INVENTORY_STATUS.SORTING,
261
+ sales_base_1.ORDER_INVENTORY_STATUS.LOADING,
262
+ sales_base_1.ORDER_INVENTORY_STATUS.LOADED,
263
+ sales_base_1.ORDER_INVENTORY_STATUS.TERMINATED,
264
+ sales_base_1.ORDER_INVENTORY_STATUS.MISSING,
265
+ sales_base_1.ORDER_INVENTORY_STATUS.CANCELLED
266
+ ];
267
+ const allCompleted = rg.orderInventories.every(oi => completedStatuses.includes(oi.status));
268
+ if (allCompleted) {
269
+ completedRoIds.push(rg.id);
270
+ }
271
+ else {
272
+ incompleteRoIds.push(rg.id);
273
+ }
274
+ }
275
+ // Update ReleaseGoods that are fully completed from PARTIAL_PROCESSING to PROCESSING
276
+ if (completedRoIds.length > 0) {
277
+ await tx.getRepository(sales_base_1.ReleaseGood).update({ id: (0, typeorm_1.In)(completedRoIds), status: sales_base_1.ORDER_STATUS.PARTIAL_PROCESSING }, {
278
+ status: sales_base_1.ORDER_STATUS.PROCESSING,
279
+ updater: user,
280
+ updatedAt: new Date()
281
+ });
282
+ }
283
+ // For ReleaseGoods that still have incomplete OrderInventories:
284
+ // - If they're in PROCESSING, update to PARTIAL_PROCESSING
285
+ // - If they're already in PARTIAL_PROCESSING, leave them as is
286
+ if (incompleteRoIds.length > 0) {
287
+ await tx.getRepository(sales_base_1.ReleaseGood).update({ id: (0, typeorm_1.In)(incompleteRoIds), status: sales_base_1.ORDER_STATUS.PROCESSING }, {
288
+ status: sales_base_1.ORDER_STATUS.PARTIAL_PROCESSING,
289
+ updater: user,
290
+ updatedAt: new Date()
291
+ });
292
+ }
252
293
  }
253
294
  //find exist loading worksheet
254
295
  const existLoadingWorksheet = await tx
@@ -261,31 +302,67 @@ async function completeZonePicking(worksheetId, context, isPartial) {
261
302
  .getMany();
262
303
  let roWithoutLoadingWorksheet = roIds.filter(roId => !existLoadingWorksheet.some(ws => ws.releaseGood.id === roId));
263
304
  let roWithLoadingWorksheet = roIds.filter(roId => existLoadingWorksheet.some(ws => ws.releaseGood.id === roId));
305
+ // Get disable-QC-in-loading setting
306
+ const disableQcSetting = await tx.getRepository(setting_base_1.Setting).findOne({
307
+ where: {
308
+ domain,
309
+ name: 'disable-QC-in-loading'
310
+ }
311
+ });
312
+ const disableQc = (disableQcSetting === null || disableQcSetting === void 0 ? void 0 : disableQcSetting.value) === 'true';
264
313
  if (roWithoutLoadingWorksheet.length > 0) {
265
- await generateLoadingWorksheets(tx, domain, user, roWithoutLoadingWorksheet);
314
+ await generateLoadingWorksheets(tx, domain, user, roWithoutLoadingWorksheet, disableQc);
266
315
  }
267
316
  if (roWithLoadingWorksheet.length > 0) {
268
- //update picked oi to loading
269
- await tx.getRepository(sales_base_1.OrderInventory).update({ releaseGood: (0, typeorm_1.In)(roWithLoadingWorksheet), status: sales_base_1.ORDER_INVENTORY_STATUS.PICKED }, {
270
- status: sales_base_1.ORDER_INVENTORY_STATUS.SORTING,
271
- updater: user,
272
- updatedAt: new Date()
273
- });
274
- const loadingOrderInventories = await tx.getRepository(sales_base_1.OrderInventory).find({
275
- where: { releaseGood: (0, typeorm_1.In)(roWithLoadingWorksheet), status: sales_base_1.ORDER_INVENTORY_STATUS.SORTING }
276
- });
277
- //update loading wsd deactivated to executing
278
- await tx.getRepository(worksheet_base_1.WorksheetDetail).update({
279
- targetInventory: (0, typeorm_1.In)(loadingOrderInventories.map(oi => oi.id)),
280
- type: worksheet_base_1.WORKSHEET_TYPE.LOADING,
281
- status: worksheet_base_1.WORKSHEET_STATUS.DEACTIVATED
282
- }, { status: worksheet_base_1.WORKSHEET_STATUS.EXECUTING, updatedAt: new Date(), updater: user });
317
+ if (disableQc) {
318
+ // When QC is disabled: update PICKED to LOADING status and set sortedQty = pickedQty automatically
319
+ // Use query builder with raw SQL to set sortedQty = pickedQty in a single update
320
+ await tx
321
+ .getRepository(sales_base_1.OrderInventory)
322
+ .createQueryBuilder()
323
+ .update(sales_base_1.OrderInventory)
324
+ .set({
325
+ status: sales_base_1.ORDER_INVENTORY_STATUS.LOADING,
326
+ sortedQty: () => '"picked_qty"',
327
+ updater: user,
328
+ updatedAt: new Date()
329
+ })
330
+ .where('release_good_id IN (:...roIds)', { roIds: roWithLoadingWorksheet })
331
+ .andWhere('status = :status', { status: sales_base_1.ORDER_INVENTORY_STATUS.PICKED })
332
+ .execute();
333
+ const loadingOrderInventories = await tx.getRepository(sales_base_1.OrderInventory).find({
334
+ where: { releaseGood: (0, typeorm_1.In)(roWithLoadingWorksheet), status: sales_base_1.ORDER_INVENTORY_STATUS.LOADING }
335
+ });
336
+ //update loading wsd deactivated to executing
337
+ await tx.getRepository(worksheet_base_1.WorksheetDetail).update({
338
+ targetInventory: (0, typeorm_1.In)(loadingOrderInventories.map(oi => oi.id)),
339
+ type: worksheet_base_1.WORKSHEET_TYPE.LOADING,
340
+ status: worksheet_base_1.WORKSHEET_STATUS.DEACTIVATED
341
+ }, { status: worksheet_base_1.WORKSHEET_STATUS.EXECUTING, updatedAt: new Date(), updater: user });
342
+ }
343
+ else {
344
+ // When QC is enabled: update PICKED to SORTING status (existing behavior)
345
+ await tx.getRepository(sales_base_1.OrderInventory).update({ releaseGood: (0, typeorm_1.In)(roWithLoadingWorksheet), status: sales_base_1.ORDER_INVENTORY_STATUS.PICKED }, {
346
+ status: sales_base_1.ORDER_INVENTORY_STATUS.SORTING,
347
+ updater: user,
348
+ updatedAt: new Date()
349
+ });
350
+ const loadingOrderInventories = await tx.getRepository(sales_base_1.OrderInventory).find({
351
+ where: { releaseGood: (0, typeorm_1.In)(roWithLoadingWorksheet), status: sales_base_1.ORDER_INVENTORY_STATUS.SORTING }
352
+ });
353
+ //update loading wsd deactivated to executing
354
+ await tx.getRepository(worksheet_base_1.WorksheetDetail).update({
355
+ targetInventory: (0, typeorm_1.In)(loadingOrderInventories.map(oi => oi.id)),
356
+ type: worksheet_base_1.WORKSHEET_TYPE.LOADING,
357
+ status: worksheet_base_1.WORKSHEET_STATUS.DEACTIVATED
358
+ }, { status: worksheet_base_1.WORKSHEET_STATUS.EXECUTING, updatedAt: new Date(), updater: user });
359
+ }
283
360
  }
284
361
  const wsStatus = isPartial ? worksheet_base_1.WORKSHEET_STATUS.PARTIAL_EXECUTING : worksheet_base_1.WORKSHEET_STATUS.DONE;
285
362
  await updateWorksheetsAndDetails(tx, worksheet, worksheetDetails, wsStatus, user);
286
363
  return true;
287
364
  }
288
- async function generateLoadingWorksheets(tx, domain, user, roWithoutLoadingWorksheet) {
365
+ async function generateLoadingWorksheets(tx, domain, user, roWithoutLoadingWorksheet, disableQc) {
289
366
  const releaseGoods = await tx.getRepository(sales_base_1.ReleaseGood).find({
290
367
  where: { id: (0, typeorm_1.In)(roWithoutLoadingWorksheet), status: (0, typeorm_1.Not)((0, typeorm_1.In)(sales_base_1.ORDER_STATUS.OBSOLETE)) },
291
368
  relations: ['orderInventories', 'sortedBy']
@@ -320,12 +397,31 @@ async function generateLoadingWorksheets(tx, domain, user, roWithoutLoadingWorks
320
397
  };
321
398
  });
322
399
  await tx.getRepository(worksheet_base_1.WorksheetDetail).insert(loadingWorksheetDetails);
323
- //update picked oi to loading
324
- await tx.getRepository(sales_base_1.OrderInventory).update({ id: (0, typeorm_1.In)(orderInventories.map(oi => oi.id)), status: sales_base_1.ORDER_INVENTORY_STATUS.PICKED }, {
325
- status: sales_base_1.ORDER_INVENTORY_STATUS.SORTING,
326
- updater: user,
327
- updatedAt: new Date()
328
- });
400
+ // Update picked OrderInventories based on disableQc setting
401
+ if (disableQc) {
402
+ // When QC is disabled: update PICKED to LOADING status and set sortedQty = pickedQty automatically
403
+ await tx
404
+ .getRepository(sales_base_1.OrderInventory)
405
+ .createQueryBuilder()
406
+ .update(sales_base_1.OrderInventory)
407
+ .set({
408
+ status: sales_base_1.ORDER_INVENTORY_STATUS.LOADING,
409
+ sortedQty: () => '"picked_qty"',
410
+ updater: user,
411
+ updatedAt: new Date()
412
+ })
413
+ .where('id IN (:...oiIds)', { oiIds: orderInventories.map(oi => oi.id) })
414
+ .andWhere('status = :status', { status: sales_base_1.ORDER_INVENTORY_STATUS.PICKED })
415
+ .execute();
416
+ }
417
+ else {
418
+ // When QC is enabled: update PICKED to SORTING status (existing behavior)
419
+ await tx.getRepository(sales_base_1.OrderInventory).update({ id: (0, typeorm_1.In)(orderInventories.map(oi => oi.id)), status: sales_base_1.ORDER_INVENTORY_STATUS.PICKED }, {
420
+ status: sales_base_1.ORDER_INVENTORY_STATUS.SORTING,
421
+ updater: user,
422
+ updatedAt: new Date()
423
+ });
424
+ }
329
425
  }
330
426
  }
331
427
  async function updateWorksheetsAndDetails(tx, worksheet, worksheetDetails, status, updater) {