@things-factory/operato-hub 4.3.820 → 4.3.821

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.
@@ -0,0 +1,207 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.efmxStockDetailReport = void 0;
4
+ const biz_base_1 = require("@things-factory/biz-base");
5
+ exports.efmxStockDetailReport = {
6
+ async efmxStockDetailReport(_, params, context) {
7
+ try {
8
+ const { tx, domain } = context.state;
9
+ let bizplaceFilter = params.filters.find(data => data.name === 'bizplace');
10
+ let asOfDate = params.filters.find(data => data.name === 'asOfDate');
11
+ let timezoneOffsetFilter = params.filters.find(data => data.name === 'timezoneOffset');
12
+ let timezoneOffset = ((timezoneOffsetFilter === null || timezoneOffsetFilter === void 0 ? void 0 : timezoneOffsetFilter.value) || 0) + ' minutes';
13
+ if (!bizplaceFilter || !asOfDate)
14
+ throw 'Invalid input';
15
+ const bizplace = await tx.getRepository(biz_base_1.Bizplace).findOne({ id: bizplaceFilter.value });
16
+ if (!bizplace)
17
+ throw 'Invalid bizplace';
18
+ await tx.query(`
19
+ CREATE TEMP TABLE tmp_bizfilter ON COMMIT DROP AS (
20
+ SELECT bizplace_id::uuid FROM (VALUES ('${bizplace.id}')) AS bizFilter(bizplace_id)
21
+ )
22
+ `);
23
+ await tx.query(`
24
+ CREATE TEMP TABLE tmp_src ON COMMIT DROP AS (
25
+ SELECT domain_id, pallet_id, carton_id, seq,
26
+ TRUNC(qty::numeric, 3) AS qty,
27
+ TRUNC(uom_value::numeric, 3) AS uom_value,
28
+ packing_type, batch_id, batch_id_ref, created_at, status, unit_cost,
29
+ product_id::uuid AS product_id, bizplace_id::uuid AS bizplace_id, location_id::uuid AS location_id
30
+ FROM reduced_inventory_histories rih
31
+ WHERE domain_id = $1
32
+ AND created_at < $2::timestamp + $3::INTERVAL + '1 day'::INTERVAL
33
+ AND bizplace_id = $4
34
+ )
35
+ `, [domain.id, asOfDate.value, timezoneOffset, bizplace.id]);
36
+ await tx.query(`
37
+ CREATE TEMP TABLE tmp_src_group ON COMMIT DROP AS (
38
+ SELECT ih.domain_id, ih.pallet_id,
39
+ TRUNC(SUM(ih.qty)::numeric, 3) AS qty,
40
+ TRUNC(SUM(ih.uom_value)::numeric, 3) AS uom_value,
41
+ MAX(ih.seq) AS last_seq,
42
+ MAX(ih.created_at) AS created_at,
43
+ MIN(ih.created_at) AS initial_inbound_at
44
+ FROM tmp_src ih
45
+ GROUP BY ih.domain_id, ih.pallet_id
46
+ )
47
+ `);
48
+ await tx.query(`
49
+ CREATE TEMP TABLE tmp_data ON COMMIT DROP AS (
50
+ SELECT dt.*, rih.carton_id, rih.batch_id, rih.batch_id_ref, rih.product_id, rih.packing_type,
51
+ rih.bizplace_id, rih.location_id, rih.unit_cost,
52
+ iv.id AS inventory_id, iv.uom,
53
+ iv.expiration_date, iv.manufacture_date, iv.remark,
54
+ iv.locked_qty, iv.locked_uom_value, iv.condition_of_goods
55
+ FROM (
56
+ SELECT ih.*, ih2.status FROM tmp_src_group ih
57
+ INNER JOIN inventory_histories ih2
58
+ ON ih.domain_id = ih2.domain_id
59
+ AND ih.pallet_id = ih2.pallet_id
60
+ AND ih.last_seq = ih2.seq
61
+ ) dt
62
+ INNER JOIN tmp_src rih
63
+ ON dt.domain_id = rih.domain_id
64
+ AND dt.pallet_id = rih.pallet_id
65
+ AND dt.last_seq = rih.seq
66
+ AND rih.status <> 'TERMINATED'
67
+ INNER JOIN inventories iv
68
+ ON iv.domain_id = dt.domain_id
69
+ AND iv.pallet_id = dt.pallet_id
70
+ AND iv.status <> 'MISSING'
71
+ WHERE EXISTS (
72
+ SELECT * FROM tmp_bizfilter bizFilter WHERE bizFilter.bizplace_id = rih.bizplace_id
73
+ )
74
+ )
75
+ `);
76
+ const total = await tx.query(`SELECT COUNT(*) FROM tmp_data WHERE qty > 0`);
77
+ const result = await tx.query(`
78
+ SELECT
79
+ rih.pallet_id AS "palletId",
80
+ rih.carton_id AS "cartonId",
81
+ rih.batch_id AS "batchId",
82
+ rih.batch_id_ref AS "batchIdRef",
83
+ rih.initial_inbound_at AS "initialInboundAt",
84
+ TRUNC(rih.qty::numeric, 3) AS "qty",
85
+ TRUNC(rih.uom_value::numeric, 3) AS "uomValue",
86
+ rih.uom,
87
+ rih.packing_type AS "packingType",
88
+ rih.locked_qty AS "allocatedQty",
89
+ TRUNC((rih.qty - rih.locked_qty)::numeric, 3) AS "availableQty",
90
+ rih.unit_cost AS "unitCost",
91
+ rih.expiration_date AS "expirationDate",
92
+ rih.manufacture_date AS "manufactureDate",
93
+ rih.condition_of_goods AS "conditionOfGoods",
94
+ rih.remark,
95
+ prd.id AS product_id,
96
+ prd.name AS product_name,
97
+ prd.sku AS product_sku,
98
+ prd.brand AS product_brand,
99
+ prd.description AS product_description,
100
+ prd.volume AS product_volume,
101
+ prd.outbound_alert AS product_outbound_alert,
102
+ prd.min_outbound_shelf_life AS product_min_outbound_shelf_life,
103
+ bz.name AS bizplace_name,
104
+ loc.name AS location_name,
105
+ loc.type AS location_type,
106
+ loc.zone AS location_zone,
107
+ wh.name AS warehouse_name,
108
+ CASE
109
+ WHEN rih.expiration_date < NOW() THEN 'Expired'
110
+ WHEN (rih.expiration_date - (prd.min_outbound_shelf_life || ' days')::INTERVAL) < NOW() THEN 'Expiring'
111
+ WHEN (rih.expiration_date - (prd.outbound_alert || ' days')::INTERVAL) < NOW() THEN 'Risky'
112
+ ELSE 'Normal'
113
+ END AS expiry,
114
+ TRUNC(COALESCE((
115
+ SELECT SUM(oi1.release_qty) FROM order_inventories oi1
116
+ INNER JOIN release_goods rg1 ON rg1.id = oi1.release_good_id
117
+ WHERE rg1.status IN ('PICKING', 'LOADING')
118
+ AND oi1.inventory_id = rih.inventory_id
119
+ AND oi1.status IN ('PICKED', 'LOADING')
120
+ AND rg1.domain_id = '${domain.id}'
121
+ GROUP BY oi1.inventory_id
122
+ ), 0)::numeric, 3) AS "nonLoadedQty",
123
+ TRUNC(COALESCE((
124
+ SELECT SUM(oi1.release_uom_value) FROM order_inventories oi1
125
+ INNER JOIN release_goods rg1 ON rg1.id = oi1.release_good_id
126
+ WHERE rg1.status IN ('PICKING', 'LOADING')
127
+ AND oi1.inventory_id = rih.inventory_id
128
+ AND oi1.status IN ('PICKED', 'LOADING')
129
+ AND rg1.domain_id = '${domain.id}'
130
+ GROUP BY oi1.inventory_id
131
+ ), 0)::numeric, 3) AS "nonLoadedUomValue"
132
+ FROM tmp_data rih
133
+ INNER JOIN products prd ON prd.id = rih.product_id
134
+ INNER JOIN bizplaces bz ON bz.id = rih.bizplace_id
135
+ INNER JOIN locations loc ON loc.id = rih.location_id
136
+ INNER JOIN warehouses wh ON wh.id = loc.warehouse_id
137
+ WHERE rih.qty > 0
138
+ ORDER BY bz.name, rih.batch_id, rih.initial_inbound_at
139
+ OFFSET ${(params.pagination.page - 1) * params.pagination.limit} LIMIT ${params.pagination.limit}
140
+ `);
141
+ const getCondition = (locationType) => {
142
+ return ({
143
+ BIN: 'New',
144
+ BUFFER: 'New',
145
+ FLOOR: 'New',
146
+ SHELF: 'New',
147
+ STORAGE: 'New',
148
+ RESERVE: 'Reserve',
149
+ DAMAGE: 'Damage',
150
+ QUARANTINE: 'Quarantine'
151
+ }[locationType] || 'Unknown');
152
+ };
153
+ const calculateDaysUntilExpiry = (expirationDate) => {
154
+ if (!expirationDate)
155
+ return null;
156
+ const expiry = new Date(expirationDate);
157
+ const today = new Date();
158
+ return Math.ceil((expiry.getTime() - today.getTime()) / (1000 * 60 * 60 * 24));
159
+ };
160
+ const items = result.map(itm => ({
161
+ palletId: itm.palletId,
162
+ cartonId: itm.cartonId,
163
+ batchId: itm.batchId,
164
+ batchIdRef: itm.batchIdRef,
165
+ initialInboundAt: itm.initialInboundAt,
166
+ bizplace: {
167
+ name: itm.bizplace_name
168
+ },
169
+ product: {
170
+ id: itm.product_id,
171
+ sku: itm.product_sku,
172
+ name: itm.product_name,
173
+ description: itm.product_description,
174
+ brand: itm.product_brand,
175
+ volume: itm.product_volume
176
+ },
177
+ packingType: itm.packingType,
178
+ qty: itm.qty,
179
+ uomValue: itm.uomValue,
180
+ allocatedQty: itm.allocatedQty,
181
+ availableQty: itm.availableQty,
182
+ nonLoadedQty: itm.nonLoadedQty,
183
+ nonLoadedUomValue: itm.nonLoadedUomValue,
184
+ uom: itm.uom,
185
+ location: {
186
+ name: itm.location_name,
187
+ type: itm.location_type,
188
+ zone: itm.location_zone
189
+ },
190
+ warehouseName: itm.warehouse_name,
191
+ expirationDate: itm.expirationDate,
192
+ daysUntilExpiry: calculateDaysUntilExpiry(itm.expirationDate),
193
+ expiryStatus: itm.expiry,
194
+ manufactureDate: itm.manufactureDate,
195
+ unitCost: itm.unitCost,
196
+ condition: itm.location_type ? getCondition(itm.location_type) : 'Unknown',
197
+ conditionOfGoods: itm.conditionOfGoods,
198
+ remark: itm.remark
199
+ }));
200
+ return { items, total: total[0].count };
201
+ }
202
+ catch (error) {
203
+ throw error;
204
+ }
205
+ }
206
+ };
207
+ //# sourceMappingURL=efmx-stock-detail-report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"efmx-stock-detail-report.js","sourceRoot":"","sources":["../../../../../../server/graphql/resolvers/reports/custom/efmx/efmx-stock-detail-report.ts"],"names":[],"mappings":"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"}
@@ -13,5 +13,6 @@ const receiving_report_1 = require("./receiving-report");
13
13
  const export_report_1 = require("./custom/elccl/export-report");
14
14
  const custom_posmy_aging_report_1 = require("./custom/posmy/custom-posmy-aging-report");
15
15
  const custom_yltc_inventory_report_1 = require("./custom/yltc/custom-yltc-inventory-report");
16
- exports.Query = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, inbound_order_details_report_1.inboundOrderDetailsReport), outbound_order_details_report_1.outboundOrderDetailsReport), shortage_report_1.shortageReport), custom_elccl_fn_dispatch_report_1.customElcclDispatchReport), custom_elccl_fn_monthly_dispatch_report_1.customElcclMonthlyDispatchReport), aging_report_1.agingReport), asn_report_1.asnReport), admiral_asn_report_1.admiralAsnReport), custom_elccl_fn_dispatch_report_1.customElcclDispatchReport), custom_elccl_fn_monthly_dispatch_report_1.customElcclMonthlyDispatchReport), receiving_report_1.receivingReport), export_report_1.exportReport), custom_posmy_aging_report_1.customPosmyAgingReport), custom_yltc_inventory_report_1.customYltcInventoryReport);
16
+ const efmx_stock_detail_report_1 = require("./custom/efmx/efmx-stock-detail-report");
17
+ exports.Query = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, inbound_order_details_report_1.inboundOrderDetailsReport), outbound_order_details_report_1.outboundOrderDetailsReport), shortage_report_1.shortageReport), custom_elccl_fn_dispatch_report_1.customElcclDispatchReport), custom_elccl_fn_monthly_dispatch_report_1.customElcclMonthlyDispatchReport), aging_report_1.agingReport), asn_report_1.asnReport), admiral_asn_report_1.admiralAsnReport), custom_elccl_fn_dispatch_report_1.customElcclDispatchReport), custom_elccl_fn_monthly_dispatch_report_1.customElcclMonthlyDispatchReport), receiving_report_1.receivingReport), export_report_1.exportReport), custom_posmy_aging_report_1.customPosmyAgingReport), custom_yltc_inventory_report_1.customYltcInventoryReport), efmx_stock_detail_report_1.efmxStockDetailReport);
17
18
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../server/graphql/resolvers/reports/index.ts"],"names":[],"mappings":";;;AAAA,iFAA0E;AAC1E,mFAA4E;AAC5E,uDAAkD;AAClD,oGAA0F;AAC1F,oHAAyG;AACzG,8DAAyD;AACzD,6CAAwC;AACxC,6DAAuD;AACvD,yDAAoD;AACpD,gEAA2D;AAC3D,wFAAiF;AACjF,6FAAsF;AAEzE,QAAA,KAAK,2MACb,wDAAyB,GACzB,0DAA0B,GAC1B,gCAAc,GACd,2DAAyB,GACzB,0EAAgC,GAChC,0BAAW,GACX,sBAAS,GACT,qCAAgB,GAChB,2DAAyB,GACzB,0EAAgC,GAChC,kCAAe,GACf,4BAAY,GACZ,kDAAsB,GACtB,wDAAyB,EAC7B"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../server/graphql/resolvers/reports/index.ts"],"names":[],"mappings":";;;AAAA,iFAA0E;AAC1E,mFAA4E;AAC5E,uDAAkD;AAClD,oGAA0F;AAC1F,oHAAyG;AACzG,8DAAyD;AACzD,6CAAwC;AACxC,6DAAuD;AACvD,yDAAoD;AACpD,gEAA2D;AAC3D,wFAAiF;AACjF,6FAAsF;AACtF,qFAA8E;AAEjE,QAAA,KAAK,yNACb,wDAAyB,GACzB,0DAA0B,GAC1B,gCAAc,GACd,2DAAyB,GACzB,0EAAgC,GAChC,0BAAW,GACX,sBAAS,GACT,qCAAgB,GAChB,2DAAyB,GACzB,0EAAgC,GAChC,kCAAe,GACf,4BAAY,GACZ,kDAAsB,GACtB,wDAAyB,GACzB,gDAAqB,EACzB"}
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.EfmxStockDetailReportList = void 0;
7
+ const graphql_tag_1 = __importDefault(require("graphql-tag"));
8
+ exports.EfmxStockDetailReportList = (0, graphql_tag_1.default) `
9
+ type EfmxStockDetailReportList {
10
+ items: [EfmxStockDetailReport]
11
+ total: Int
12
+ }
13
+ `;
14
+ //# sourceMappingURL=efmx-stock-detail-report-list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"efmx-stock-detail-report-list.js","sourceRoot":"","sources":["../../../../../../server/graphql/types/reports/custom/efmx/efmx-stock-detail-report-list.ts"],"names":[],"mappings":";;;;;;AAAA,8DAA6B;AAEhB,QAAA,yBAAyB,GAAG,IAAA,qBAAG,EAAA;;;;;CAK3C,CAAA"}
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.EfmxStockDetailReport = void 0;
7
+ const graphql_tag_1 = __importDefault(require("graphql-tag"));
8
+ exports.EfmxStockDetailReport = (0, graphql_tag_1.default) `
9
+ type EfmxStockDetailReport {
10
+ palletId: String
11
+ cartonId: String
12
+ batchId: String
13
+ batchIdRef: String
14
+ initialInboundAt: String
15
+ bizplace: Bizplace
16
+ product: Product
17
+ packingType: String
18
+ qty: Float
19
+ uomValue: Float
20
+ allocatedQty: Float
21
+ availableQty: Float
22
+ nonLoadedQty: Float
23
+ nonLoadedUomValue: Float
24
+ uom: String
25
+ location: Location
26
+ warehouseName: String
27
+ expirationDate: String
28
+ daysUntilExpiry: Int
29
+ expiryStatus: String
30
+ manufactureDate: String
31
+ unitCost: Float
32
+ condition: String
33
+ conditionOfGoods: String
34
+ remark: String
35
+ }
36
+ `;
37
+ //# sourceMappingURL=efmx-stock-detail-report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"efmx-stock-detail-report.js","sourceRoot":"","sources":["../../../../../../server/graphql/types/reports/custom/efmx/efmx-stock-detail-report.ts"],"names":[],"mappings":";;;;;;AAAA,8DAA6B;AAEhB,QAAA,qBAAqB,GAAG,IAAA,qBAAG,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4BvC,CAAA"}
@@ -22,6 +22,8 @@ const export_report_list_1 = require("./custom/elccl/exportreport/export-report-
22
22
  const custom_posmy_aging_report_1 = require("./custom/posmy/custom-posmy-aging-report");
23
23
  const custom_posmy_aging_report_list_1 = require("./custom/posmy/custom-posmy-aging-report-list");
24
24
  const custom_yltc_inventory_report_1 = require("./custom/yltc/custom-yltc-inventory-report");
25
+ const efmx_stock_detail_report_1 = require("./custom/efmx/efmx-stock-detail-report");
26
+ const efmx_stock_detail_report_list_1 = require("./custom/efmx/efmx-stock-detail-report-list");
25
27
  exports.Query = `
26
28
  inboundOrderDetailsReport(filters: [Filter!], pagination: Pagination, sortings: [Sorting!]): InboundOrderDetailsReportList @transaction
27
29
  outboundOrderDetailsReport(filters: [Filter!], pagination: Pagination, sortings: [Sorting!]): OutboundOrderDetailsReportList @transaction
@@ -36,6 +38,7 @@ exports.Query = `
36
38
  customPosmyAgingReport(filters: [Filter!], pagination: Pagination, sortings: [Sorting!]): CustomPosmyAgingReportList @transaction
37
39
  customYltcInventoryReport(domainId: String!, bizplaceIds: [String!]!, platform: String!): Boolean @transaction
38
40
  customYltcInventoryReportData(domainId: String!, bizplaceIds: [String!]!, platform: String!): [CustomYltcInventoryReport]! @transaction
41
+ efmxStockDetailReport(filters: [Filter], pagination: Pagination, sortings: [Sorting]): EfmxStockDetailReportList @transaction
39
42
  `;
40
43
  exports.Types = [
41
44
  inbound_order_details_report_1.InboundOrderDetailsReport,
@@ -58,6 +61,8 @@ exports.Types = [
58
61
  export_report_list_1.ExportReportList,
59
62
  custom_posmy_aging_report_1.CustomPosmyAgingReport,
60
63
  custom_posmy_aging_report_list_1.CustomPosmyAgingReportList,
61
- custom_yltc_inventory_report_1.CustomYltcInventoryReport
64
+ custom_yltc_inventory_report_1.CustomYltcInventoryReport,
65
+ efmx_stock_detail_report_1.EfmxStockDetailReport,
66
+ efmx_stock_detail_report_list_1.EfmxStockDetailReportList
62
67
  ];
63
68
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../server/graphql/types/reports/index.ts"],"names":[],"mappings":";;;AAAA,iFAA0E;AAC1E,2FAAmF;AACnF,mFAA4E;AAC5E,6FAAqF;AACrF,iEAA2D;AAC3D,iEAAuD;AACvD,mHAAyG;AACzG,6HAAkH;AAClH,0EAAqE;AACrE,oFAA8E;AAC9E,6CAAwC;AACxC,uDAAiD;AACjD,6DAAuD;AACvD,uEAAgE;AAChE,yDAAoD;AACpD,mEAA6D;AAC7D,6EAAwE;AACxE,uFAAiF;AACjF,wFAAiF;AACjF,kGAA0F;AAC1F,6FAAsF;AAEzE,QAAA,KAAK,GAAG;;;;;;;;;;;;;;CAcpB,CAAA;AAEY,QAAA,KAAK,GAAG;IACnB,wDAAyB;IACzB,iEAA6B;IAC7B,0DAA0B;IAC1B,mEAA8B;IAC9B,qCAAc;IACd,yCAAkB;IAClB,2DAAyB;IACzB,oEAA6B;IAC7B,kCAAe;IACf,2CAAmB;IACnB,0BAAW;IACX,mCAAe;IACf,sBAAS;IACT,+BAAa;IACb,qCAAgB;IAChB,8CAAoB;IACpB,4BAAY;IACZ,qCAAgB;IAChB,kDAAsB;IACtB,2DAA0B;IAC1B,wDAAyB;CAC1B,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../server/graphql/types/reports/index.ts"],"names":[],"mappings":";;;AAAA,iFAA0E;AAC1E,2FAAmF;AACnF,mFAA4E;AAC5E,6FAAqF;AACrF,iEAA2D;AAC3D,iEAAuD;AACvD,mHAAyG;AACzG,6HAAkH;AAClH,0EAAqE;AACrE,oFAA8E;AAC9E,6CAAwC;AACxC,uDAAiD;AACjD,6DAAuD;AACvD,uEAAgE;AAChE,yDAAoD;AACpD,mEAA6D;AAC7D,6EAAwE;AACxE,uFAAiF;AACjF,wFAAiF;AACjF,kGAA0F;AAC1F,6FAAsF;AACtF,qFAA8E;AAC9E,+FAAuF;AAE1E,QAAA,KAAK,GAAG;;;;;;;;;;;;;;;CAepB,CAAA;AAEY,QAAA,KAAK,GAAG;IACnB,wDAAyB;IACzB,iEAA6B;IAC7B,0DAA0B;IAC1B,mEAA8B;IAC9B,qCAAc;IACd,yCAAkB;IAClB,2DAAyB;IACzB,oEAA6B;IAC7B,kCAAe;IACf,2CAAmB;IACnB,0BAAW;IACX,mCAAe;IACf,sBAAS;IACT,+BAAa;IACb,qCAAgB;IAChB,8CAAoB;IACpB,4BAAY;IACZ,qCAAgB;IAChB,kDAAsB;IACtB,2DAA0B;IAC1B,wDAAyB;IACzB,gDAAqB;IACrB,yDAAyB;CAC1B,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@things-factory/operato-hub",
3
- "version": "4.3.820",
3
+ "version": "4.3.821",
4
4
  "main": "dist-server/index.js",
5
5
  "browser": "client/index.js",
6
6
  "things-factory": true,
@@ -123,5 +123,5 @@
123
123
  "resolutions": {
124
124
  "core-js": "^3.16.0"
125
125
  },
126
- "gitHead": "50ff67176b1c57306867ee735081facd63a14d3b"
126
+ "gitHead": "09e56022878a6715239bbf61669a73f56a7577dd"
127
127
  }
@@ -0,0 +1,220 @@
1
+ import { EntityManager } from 'typeorm'
2
+ import { Bizplace } from '@things-factory/biz-base'
3
+ import { ListParam } from '@things-factory/shell'
4
+
5
+ export const efmxStockDetailReport = {
6
+ async efmxStockDetailReport(_: any, params: ListParam, context: any) {
7
+ try {
8
+ const { tx, domain } = context.state
9
+
10
+ let bizplaceFilter = params.filters.find(data => data.name === 'bizplace')
11
+ let asOfDate = params.filters.find(data => data.name === 'asOfDate')
12
+ let timezoneOffsetFilter = params.filters.find(data => data.name === 'timezoneOffset')
13
+ let timezoneOffset = (timezoneOffsetFilter?.value || 0) + ' minutes'
14
+
15
+ if (!bizplaceFilter || !asOfDate) throw 'Invalid input'
16
+
17
+ const bizplace: Bizplace = await tx.getRepository(Bizplace).findOne({ id: bizplaceFilter.value })
18
+ if (!bizplace) throw 'Invalid bizplace'
19
+
20
+ await tx.query(`
21
+ CREATE TEMP TABLE tmp_bizfilter ON COMMIT DROP AS (
22
+ SELECT bizplace_id::uuid FROM (VALUES ('${bizplace.id}')) AS bizFilter(bizplace_id)
23
+ )
24
+ `)
25
+
26
+ await tx.query(
27
+ `
28
+ CREATE TEMP TABLE tmp_src ON COMMIT DROP AS (
29
+ SELECT domain_id, pallet_id, carton_id, seq,
30
+ TRUNC(qty::numeric, 3) AS qty,
31
+ TRUNC(uom_value::numeric, 3) AS uom_value,
32
+ packing_type, batch_id, batch_id_ref, created_at, status, unit_cost,
33
+ product_id::uuid AS product_id, bizplace_id::uuid AS bizplace_id, location_id::uuid AS location_id
34
+ FROM reduced_inventory_histories rih
35
+ WHERE domain_id = $1
36
+ AND created_at < $2::timestamp + $3::INTERVAL + '1 day'::INTERVAL
37
+ AND bizplace_id = $4
38
+ )
39
+ `,
40
+ [domain.id, asOfDate.value, timezoneOffset, bizplace.id]
41
+ )
42
+
43
+ await tx.query(`
44
+ CREATE TEMP TABLE tmp_src_group ON COMMIT DROP AS (
45
+ SELECT ih.domain_id, ih.pallet_id,
46
+ TRUNC(SUM(ih.qty)::numeric, 3) AS qty,
47
+ TRUNC(SUM(ih.uom_value)::numeric, 3) AS uom_value,
48
+ MAX(ih.seq) AS last_seq,
49
+ MAX(ih.created_at) AS created_at,
50
+ MIN(ih.created_at) AS initial_inbound_at
51
+ FROM tmp_src ih
52
+ GROUP BY ih.domain_id, ih.pallet_id
53
+ )
54
+ `)
55
+
56
+ await tx.query(`
57
+ CREATE TEMP TABLE tmp_data ON COMMIT DROP AS (
58
+ SELECT dt.*, rih.carton_id, rih.batch_id, rih.batch_id_ref, rih.product_id, rih.packing_type,
59
+ rih.bizplace_id, rih.location_id, rih.unit_cost,
60
+ iv.id AS inventory_id, iv.uom,
61
+ iv.expiration_date, iv.manufacture_date, iv.remark,
62
+ iv.locked_qty, iv.locked_uom_value, iv.condition_of_goods
63
+ FROM (
64
+ SELECT ih.*, ih2.status FROM tmp_src_group ih
65
+ INNER JOIN inventory_histories ih2
66
+ ON ih.domain_id = ih2.domain_id
67
+ AND ih.pallet_id = ih2.pallet_id
68
+ AND ih.last_seq = ih2.seq
69
+ ) dt
70
+ INNER JOIN tmp_src rih
71
+ ON dt.domain_id = rih.domain_id
72
+ AND dt.pallet_id = rih.pallet_id
73
+ AND dt.last_seq = rih.seq
74
+ AND rih.status <> 'TERMINATED'
75
+ INNER JOIN inventories iv
76
+ ON iv.domain_id = dt.domain_id
77
+ AND iv.pallet_id = dt.pallet_id
78
+ AND iv.status <> 'MISSING'
79
+ WHERE EXISTS (
80
+ SELECT * FROM tmp_bizfilter bizFilter WHERE bizFilter.bizplace_id = rih.bizplace_id
81
+ )
82
+ )
83
+ `)
84
+
85
+ const total: any = await tx.query(`SELECT COUNT(*) FROM tmp_data WHERE qty > 0`)
86
+
87
+ const result: any = await tx.query(`
88
+ SELECT
89
+ rih.pallet_id AS "palletId",
90
+ rih.carton_id AS "cartonId",
91
+ rih.batch_id AS "batchId",
92
+ rih.batch_id_ref AS "batchIdRef",
93
+ rih.initial_inbound_at AS "initialInboundAt",
94
+ TRUNC(rih.qty::numeric, 3) AS "qty",
95
+ TRUNC(rih.uom_value::numeric, 3) AS "uomValue",
96
+ rih.uom,
97
+ rih.packing_type AS "packingType",
98
+ rih.locked_qty AS "allocatedQty",
99
+ TRUNC((rih.qty - rih.locked_qty)::numeric, 3) AS "availableQty",
100
+ rih.unit_cost AS "unitCost",
101
+ rih.expiration_date AS "expirationDate",
102
+ rih.manufacture_date AS "manufactureDate",
103
+ rih.condition_of_goods AS "conditionOfGoods",
104
+ rih.remark,
105
+ prd.id AS product_id,
106
+ prd.name AS product_name,
107
+ prd.sku AS product_sku,
108
+ prd.brand AS product_brand,
109
+ prd.description AS product_description,
110
+ prd.volume AS product_volume,
111
+ prd.outbound_alert AS product_outbound_alert,
112
+ prd.min_outbound_shelf_life AS product_min_outbound_shelf_life,
113
+ bz.name AS bizplace_name,
114
+ loc.name AS location_name,
115
+ loc.type AS location_type,
116
+ loc.zone AS location_zone,
117
+ wh.name AS warehouse_name,
118
+ CASE
119
+ WHEN rih.expiration_date < NOW() THEN 'Expired'
120
+ WHEN (rih.expiration_date - (prd.min_outbound_shelf_life || ' days')::INTERVAL) < NOW() THEN 'Expiring'
121
+ WHEN (rih.expiration_date - (prd.outbound_alert || ' days')::INTERVAL) < NOW() THEN 'Risky'
122
+ ELSE 'Normal'
123
+ END AS expiry,
124
+ TRUNC(COALESCE((
125
+ SELECT SUM(oi1.release_qty) FROM order_inventories oi1
126
+ INNER JOIN release_goods rg1 ON rg1.id = oi1.release_good_id
127
+ WHERE rg1.status IN ('PICKING', 'LOADING')
128
+ AND oi1.inventory_id = rih.inventory_id
129
+ AND oi1.status IN ('PICKED', 'LOADING')
130
+ AND rg1.domain_id = '${domain.id}'
131
+ GROUP BY oi1.inventory_id
132
+ ), 0)::numeric, 3) AS "nonLoadedQty",
133
+ TRUNC(COALESCE((
134
+ SELECT SUM(oi1.release_uom_value) FROM order_inventories oi1
135
+ INNER JOIN release_goods rg1 ON rg1.id = oi1.release_good_id
136
+ WHERE rg1.status IN ('PICKING', 'LOADING')
137
+ AND oi1.inventory_id = rih.inventory_id
138
+ AND oi1.status IN ('PICKED', 'LOADING')
139
+ AND rg1.domain_id = '${domain.id}'
140
+ GROUP BY oi1.inventory_id
141
+ ), 0)::numeric, 3) AS "nonLoadedUomValue"
142
+ FROM tmp_data rih
143
+ INNER JOIN products prd ON prd.id = rih.product_id
144
+ INNER JOIN bizplaces bz ON bz.id = rih.bizplace_id
145
+ INNER JOIN locations loc ON loc.id = rih.location_id
146
+ INNER JOIN warehouses wh ON wh.id = loc.warehouse_id
147
+ WHERE rih.qty > 0
148
+ ORDER BY bz.name, rih.batch_id, rih.initial_inbound_at
149
+ OFFSET ${(params.pagination.page - 1) * params.pagination.limit} LIMIT ${params.pagination.limit}
150
+ `)
151
+
152
+ const getCondition = (locationType: string) => {
153
+ return (
154
+ {
155
+ BIN: 'New',
156
+ BUFFER: 'New',
157
+ FLOOR: 'New',
158
+ SHELF: 'New',
159
+ STORAGE: 'New',
160
+ RESERVE: 'Reserve',
161
+ DAMAGE: 'Damage',
162
+ QUARANTINE: 'Quarantine'
163
+ }[locationType] || 'Unknown'
164
+ )
165
+ }
166
+
167
+ const calculateDaysUntilExpiry = (expirationDate: string | null): number | null => {
168
+ if (!expirationDate) return null
169
+ const expiry = new Date(expirationDate)
170
+ const today = new Date()
171
+ return Math.ceil((expiry.getTime() - today.getTime()) / (1000 * 60 * 60 * 24))
172
+ }
173
+
174
+ const items = result.map(itm => ({
175
+ palletId: itm.palletId,
176
+ cartonId: itm.cartonId,
177
+ batchId: itm.batchId,
178
+ batchIdRef: itm.batchIdRef,
179
+ initialInboundAt: itm.initialInboundAt,
180
+ bizplace: {
181
+ name: itm.bizplace_name
182
+ },
183
+ product: {
184
+ id: itm.product_id,
185
+ sku: itm.product_sku,
186
+ name: itm.product_name,
187
+ description: itm.product_description,
188
+ brand: itm.product_brand,
189
+ volume: itm.product_volume
190
+ },
191
+ packingType: itm.packingType,
192
+ qty: itm.qty,
193
+ uomValue: itm.uomValue,
194
+ allocatedQty: itm.allocatedQty,
195
+ availableQty: itm.availableQty,
196
+ nonLoadedQty: itm.nonLoadedQty,
197
+ nonLoadedUomValue: itm.nonLoadedUomValue,
198
+ uom: itm.uom,
199
+ location: {
200
+ name: itm.location_name,
201
+ type: itm.location_type,
202
+ zone: itm.location_zone
203
+ },
204
+ warehouseName: itm.warehouse_name,
205
+ expirationDate: itm.expirationDate,
206
+ daysUntilExpiry: calculateDaysUntilExpiry(itm.expirationDate),
207
+ expiryStatus: itm.expiry,
208
+ manufactureDate: itm.manufactureDate,
209
+ unitCost: itm.unitCost,
210
+ condition: itm.location_type ? getCondition(itm.location_type) : 'Unknown',
211
+ conditionOfGoods: itm.conditionOfGoods,
212
+ remark: itm.remark
213
+ }))
214
+
215
+ return { items, total: total[0].count }
216
+ } catch (error) {
217
+ throw error
218
+ }
219
+ }
220
+ }
@@ -10,6 +10,7 @@ import { receivingReport } from './receiving-report'
10
10
  import { exportReport } from './custom/elccl/export-report'
11
11
  import { customPosmyAgingReport } from './custom/posmy/custom-posmy-aging-report'
12
12
  import { customYltcInventoryReport } from './custom/yltc/custom-yltc-inventory-report'
13
+ import { efmxStockDetailReport } from './custom/efmx/efmx-stock-detail-report'
13
14
 
14
15
  export const Query = {
15
16
  ...inboundOrderDetailsReport,
@@ -25,5 +26,6 @@ export const Query = {
25
26
  ...receivingReport,
26
27
  ...exportReport,
27
28
  ...customPosmyAgingReport,
28
- ...customYltcInventoryReport
29
+ ...customYltcInventoryReport,
30
+ ...efmxStockDetailReport
29
31
  }
@@ -0,0 +1,8 @@
1
+ import gql from 'graphql-tag'
2
+
3
+ export const EfmxStockDetailReportList = gql`
4
+ type EfmxStockDetailReportList {
5
+ items: [EfmxStockDetailReport]
6
+ total: Int
7
+ }
8
+ `
@@ -0,0 +1,31 @@
1
+ import gql from 'graphql-tag'
2
+
3
+ export const EfmxStockDetailReport = gql`
4
+ type EfmxStockDetailReport {
5
+ palletId: String
6
+ cartonId: String
7
+ batchId: String
8
+ batchIdRef: String
9
+ initialInboundAt: String
10
+ bizplace: Bizplace
11
+ product: Product
12
+ packingType: String
13
+ qty: Float
14
+ uomValue: Float
15
+ allocatedQty: Float
16
+ availableQty: Float
17
+ nonLoadedQty: Float
18
+ nonLoadedUomValue: Float
19
+ uom: String
20
+ location: Location
21
+ warehouseName: String
22
+ expirationDate: String
23
+ daysUntilExpiry: Int
24
+ expiryStatus: String
25
+ manufactureDate: String
26
+ unitCost: Float
27
+ condition: String
28
+ conditionOfGoods: String
29
+ remark: String
30
+ }
31
+ `
@@ -19,6 +19,8 @@ import { ExportReportList } from './custom/elccl/exportreport/export-report-list
19
19
  import { CustomPosmyAgingReport } from './custom/posmy/custom-posmy-aging-report'
20
20
  import { CustomPosmyAgingReportList } from './custom/posmy/custom-posmy-aging-report-list'
21
21
  import { CustomYltcInventoryReport } from './custom/yltc/custom-yltc-inventory-report'
22
+ import { EfmxStockDetailReport } from './custom/efmx/efmx-stock-detail-report'
23
+ import { EfmxStockDetailReportList } from './custom/efmx/efmx-stock-detail-report-list'
22
24
 
23
25
  export const Query = `
24
26
  inboundOrderDetailsReport(filters: [Filter!], pagination: Pagination, sortings: [Sorting!]): InboundOrderDetailsReportList @transaction
@@ -34,6 +36,7 @@ export const Query = `
34
36
  customPosmyAgingReport(filters: [Filter!], pagination: Pagination, sortings: [Sorting!]): CustomPosmyAgingReportList @transaction
35
37
  customYltcInventoryReport(domainId: String!, bizplaceIds: [String!]!, platform: String!): Boolean @transaction
36
38
  customYltcInventoryReportData(domainId: String!, bizplaceIds: [String!]!, platform: String!): [CustomYltcInventoryReport]! @transaction
39
+ efmxStockDetailReport(filters: [Filter], pagination: Pagination, sortings: [Sorting]): EfmxStockDetailReportList @transaction
37
40
  `
38
41
 
39
42
  export const Types = [
@@ -57,5 +60,7 @@ export const Types = [
57
60
  ExportReportList,
58
61
  CustomPosmyAgingReport,
59
62
  CustomPosmyAgingReportList,
60
- CustomYltcInventoryReport
63
+ CustomYltcInventoryReport,
64
+ EfmxStockDetailReport,
65
+ EfmxStockDetailReportList
61
66
  ]