flexbiz-server 12.5.6 → 12.5.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "flexbiz-server",
3
3
  "main": "./server/app.js",
4
4
  "description": "Flexible Server",
5
- "version": "12.5.6",
5
+ "version": "12.5.8",
6
6
  "author": {
7
7
  "name": "Van Truong Pham",
8
8
  "email": "invncur@gmail.com"
@@ -1,30 +1,357 @@
1
- const _=require("lodash"),crypto=require("crypto"),numeral=require("numeral"),Moment=require("moment-timezone"),moment=$time$$=>Moment.tz($time$$,configs.timezone||"Asia/Ho_Chi_Minh"),reportinfo=global.getModel("reportinfo"),{evalute,getParameterData}=require("../libs/utils"),utils=require("../libs/utils"),handlers=require("./handlers"),{getCurrentSession,getCurrentStore}=require("../libs/sessionContext");
2
- class controllerRPT{constructor($router$$,$rptId$$,$fecthData$$,$options$$={}){this.module=this.name=$rptId$$;this.router=$router$$;this.options=$options$$;this.fecthDataFunc=$fecthData$$;global.report_controllers[$rptId$$.toUpperCase()]=this;this.base_path=$options$$.require_id_app===!1?"/":"/:id_app/";this.getData=this.getData.bind(this);this.createRoute=this.createRoute.bind(this);this.notNeedRight=async($user$$,$_options$$={})=>{let $nnr$$=$options$$.notNeedRight;_.isFunction($nnr$$)&&($nnr$$=
3
- $nnr$$($user$$,$_options$$));return $nnr$$};this.handleResult=async($req$$,$data_response$$,$callback$$)=>{if($data_response$$.error)return $callback$$($data_response$$.error);$data_response$$=$data_response$$.result;var $func_string_rptInfo$$=await reportinfo.findOne({code:($req$$.query.report_info_code||$rptId$$).toLowerCase()}).lean();if($func_string_rptInfo$$&&$func_string_rptInfo$$.handle_data_expression_server){if($func_string_rptInfo$$.handle_data_expression_server.indexOf("async ")>=0)return $callback$$("async function is not allow");
4
- $func_string_rptInfo$$=`return (async ()=>{
1
+ const _ = require("lodash");
2
+ const crypto = require("crypto");
3
+ const numeral = require('numeral');
4
+ const Moment = require("moment-timezone");
5
+ const moment = (time)=>{
6
+ return Moment.tz(time,configs.timezone|| 'Asia/Ho_Chi_Minh');
7
+ }
8
+ const reportinfo = global.getModel('reportinfo');
9
+ const {evalute,getParameterData} = require("../libs/utils");
10
+ const utils = require("../libs/utils");
11
+ const handlers = require("./handlers")
12
+ const {getCurrentSession,getCurrentStore} = require("../libs/sessionContext")
13
+
14
+ class controllerRPT {
15
+ constructor(router, rptId, fecthData, options = {}) {
16
+ this.name = rptId;
17
+ this.module = rptId;
18
+ this.router = router;
19
+ this.options = options;
20
+ this.fecthDataFunc = fecthData;
21
+ global.report_controllers[rptId.toUpperCase()] = this;
22
+ //tạo base route
23
+ if (options.require_id_app === false) {
24
+ this.base_path = '/';
25
+ } else {
26
+ this.base_path = '/:id_app/';
27
+ }
28
+ //binding function
29
+ this.getData = this.getData.bind(this);
30
+ this.createRoute = this.createRoute.bind(this);
31
+ //Báo cáo có cần kiểm tra quyền truy cập hay không
32
+ this.notNeedRight = async (user,_options={})=>{
33
+ let nnr = options.notNeedRight;
34
+ if(_.isFunction(nnr)){
35
+ nnr = nnr(user,_options)
36
+ }
37
+ return nnr;
38
+ }
39
+ //xử lý kết quả báo cáo trước khi trả về cho user
40
+ this.handleResult = async (req,response,callback)=>{
41
+ if (response.error) {
42
+ return callback(response.error);
43
+ }else{
44
+ let data = response.result;
45
+ let rptInfo = await reportinfo.findOne({code:(req.query.report_info_code || rptId).toLowerCase()}).lean();
46
+ //console.log("dynamic hanlde data for",req.query.report_info_code || rptId,(rptInfo||{}).handle_data_expression_server);
47
+ if(rptInfo && rptInfo.handle_data_expression_server){
48
+ if(rptInfo.handle_data_expression_server.indexOf("async ")>=0) return callback("async function is not allow");
49
+ let func_string = `return (async ()=>{
5
50
  try{
6
- ${$func_string_rptInfo$$.handle_data_expression_server}
51
+ ${rptInfo.handle_data_expression_server}
7
52
  }catch(e){
8
53
  return {error:e}
9
54
  }
10
55
 
11
- })`;try{let $rs$$=await evalute($func_string_rptInfo$$,{data:$data_response$$,moment,numeral,condition:$req$$.query,user:$req$$.user,_,utils,getData:getParameterData})();if($rs$$){if($rs$$.error)return console.error("handle_data_expression_server",$rs$$.error,$func_string_rptInfo$$,$rptId$$),$callback$$($rs$$.error.message||$rs$$.error);$data_response$$=$rs$$}}catch($e$$){return console.error("handle_data_expression_server",$e$$,$func_string_rptInfo$$,$rptId$$),$callback$$($e$$.message||
12
- $e$$)}}$callback$$(null,$data_response$$)};this.getDataFunc=()=>{const $currentStore$$=getCurrentStore();console.log(`\u2705 [rptHanlder] [getDataFunc], storeId=${$currentStore$$?.storeId||"none"},sessionID=${getCurrentSession()?._debugId}`);return $options$$.stream?$fecthData$$:async($req$$,$callback$$)=>{console.log(`\u2705 [rptHanlder] Ch\u1ea1y b\u00e1o c\u00e1o ${$rptId$$}, sessionID=${getCurrentSession()?._debugId}`);try{await $fecthData$$($req$$,($e$$,$data$$)=>{this.handleResult($req$$,{error:$e$$,
13
- result:$data$$},($e$$,$rs$$)=>{$callback$$($e$$,$rs$$)})})}catch($e$$){$callback$$($e$$)}}};const $mainRoute$$=async($req$$,$res$$)=>{if($options$$.stream)handlers.rptHandler(this,$req$$,($e$$,$rs$$)=>{if($options$$.resHandler)return $options$$.resHandler($req$$,{error:$e$$,data:$rs$$},$res$$);if($e$$)return $e$$.error?$res$$.status(500).send($e$$):$res$$.status(500).send({error:$e$$.message||$e$$});$rs$$=="__end_stream__"?console.log("[controllerRPT] end stream...",$rptId$$):$res$$.send($rs$$)},
14
- $res$$);else{const {query:$query$$,body:$body$$,user:$user$$,params:$params$$,files:$files$$}=$req$$;var $_req_user_agent$$=$req$$.header("user-agent");const $ip$$=$req$$.ip||$req$$.headers["x-forwarded-for"]||$req$$.connection.remoteAddress;try{if($_req_user_agent$$={handler:"rptHandler",query:$query$$,body:$body$$,user:$user$$,params:$params$$,user_agent:$_req_user_agent$$,ip:$ip$$,files:$files$$},global.reportMainPool&&!global.reportMainPool.fullQueue()&&$options$$.queue!=0){const $id_task$$=`report-${crypto.randomBytes(20).toString("hex")}`;
15
- if($options$$.waiting_message){const $status_task$$=`${configs.api_url||configs.domain}/task-status/${$id_task$$}`;$res$$.status(202).send([{message:$options$$.waiting_message,status_task:$status_task$$}])}global.reportMainPool.exec({id_task:$id_task$$,req:$_req_user_agent$$,module:$rptId$$.toUpperCase(),configs:JSON.stringify(configs)},$response$$=>{setImmediate(()=>{if(!$options$$.waiting_message){if($options$$.resHandler)return $options$$.resHandler($req$$,{error:$response$$.error,data:$response$$.result},
16
- $res$$);if($response$$.error)return $res$$.status(400).send($response$$.error);$res$$.send($response$$.result)}})})}else $options$$.waiting_message&&$res$$.status(202).send([{message:$options$$.waiting_message}]),handlers.rptHandler(this,$_req_user_agent$$,($e$$,$returnvalue$$)=>{if(!$options$$.waiting_message){if($options$$.resHandler)return $options$$.resHandler($req$$,{error:$e$$,data:$returnvalue$$},$res$$);if($e$$)return $res$$.status(400).send($e$$);$res$$.send($returnvalue$$)}})}catch($e$$){console.error("L\u1ed7i t\u1ea1o job cho b\u00e1o c\u00e1o",
17
- $rptId$$,$e$$),$res$$.status(400).send($e$$)}}},$excelRoute$$=async($ip$jscomp$1_req$$,$res$$)=>{const {query:$query$$,body:$body$$,user:$user$$,params:$params$$,files:$files$$}=$ip$jscomp$1_req$$;var $_req$jscomp$1_user_agent$$=$ip$jscomp$1_req$$.header("user-agent");$ip$jscomp$1_req$$=$ip$jscomp$1_req$$.ip||$ip$jscomp$1_req$$.headers["x-forwarded-for"]||$ip$jscomp$1_req$$.connection.remoteAddress;try{if($_req$jscomp$1_user_agent$$={handler:"rptExcelHandler",query:$query$$,body:$body$$,user:$user$$,
18
- params:$params$$,user_agent:$_req$jscomp$1_user_agent$$,ip:$ip$jscomp$1_req$$,files:$files$$},global.reportMainPool&&!global.reportMainPool.fullQueue()&&$options$$.queue!=0){const $id_task$$=`report-export-${crypto.randomBytes(20).toString("hex")}`;global.reportMainPool.exec({id_task:$id_task$$,req:$_req$jscomp$1_user_agent$$,module:$rptId$$.toUpperCase(),configs:JSON.stringify(configs)},$data$jscomp$2_data$jscomp$3_response$jscomp$3_returnvalue$$=>{if($data$jscomp$2_data$jscomp$3_response$jscomp$3_returnvalue$$.error)return $res$$.status(400).send($data$jscomp$2_data$jscomp$3_response$jscomp$3_returnvalue$$.error);
19
- $data$jscomp$2_data$jscomp$3_response$jscomp$3_returnvalue$$=$data$jscomp$2_data$jscomp$3_response$jscomp$3_returnvalue$$.result;const $result$$=$data$jscomp$2_data$jscomp$3_response$jscomp$3_returnvalue$$.data;switch($data$jscomp$2_data$jscomp$3_response$jscomp$3_returnvalue$$.type){case "xlsx":$res$$.setHeader("Content-Type","application/vnd.openxmlformats");$res$$.setHeader("Content-Disposition","attachment; filename="+$rptId$$+".xlsx");$data$jscomp$2_data$jscomp$3_response$jscomp$3_returnvalue$$=
20
- $result$$;$data$jscomp$2_data$jscomp$3_response$jscomp$3_returnvalue$$?.type=="Buffer"&&$data$jscomp$2_data$jscomp$3_response$jscomp$3_returnvalue$$?.data&&($data$jscomp$2_data$jscomp$3_response$jscomp$3_returnvalue$$=Buffer.from($data$jscomp$2_data$jscomp$3_response$jscomp$3_returnvalue$$.data));$res$$.send($data$jscomp$2_data$jscomp$3_response$jscomp$3_returnvalue$$);break;case "docx":$res$$.setHeader("Content-Type","application/vnd.openxmlformats-officedocument.wordprocessingml.document");$res$$.setHeader("Content-Disposition",
21
- "attachment; filename="+$rptId$$+".docx");$data$jscomp$2_data$jscomp$3_response$jscomp$3_returnvalue$$=$result$$;$data$jscomp$2_data$jscomp$3_response$jscomp$3_returnvalue$$?.type=="Buffer"&&$data$jscomp$2_data$jscomp$3_response$jscomp$3_returnvalue$$?.data&&($data$jscomp$2_data$jscomp$3_response$jscomp$3_returnvalue$$=Buffer.from($data$jscomp$2_data$jscomp$3_response$jscomp$3_returnvalue$$.data));$res$$.send($data$jscomp$2_data$jscomp$3_response$jscomp$3_returnvalue$$);break;default:$res$$.send($result$$)}})}else handlers.rptExcelHandler(this,
22
- $_req$jscomp$1_user_agent$$,($e$jscomp$7_result$$,$data$jscomp$4_data$jscomp$5_returnvalue$$)=>{if($e$jscomp$7_result$$)return $res$$.status(400).send($e$jscomp$7_result$$);$e$jscomp$7_result$$=$data$jscomp$4_data$jscomp$5_returnvalue$$.data;switch($data$jscomp$4_data$jscomp$5_returnvalue$$.type){case "xlsx":$res$$.setHeader("Content-Type","application/vnd.openxmlformats");$res$$.setHeader("Content-Disposition","attachment; filename="+$rptId$$+".xlsx");$data$jscomp$4_data$jscomp$5_returnvalue$$=$e$jscomp$7_result$$;
23
- $data$jscomp$4_data$jscomp$5_returnvalue$$?.type=="Buffer"&&$data$jscomp$4_data$jscomp$5_returnvalue$$?.data&&($data$jscomp$4_data$jscomp$5_returnvalue$$=Buffer.from($data$jscomp$4_data$jscomp$5_returnvalue$$.data));$res$$.send($data$jscomp$4_data$jscomp$5_returnvalue$$);break;case "docx":$res$$.setHeader("Content-Type","application/vnd.openxmlformats-officedocument.wordprocessingml.document");$res$$.setHeader("Content-Disposition","attachment; filename="+$rptId$$+".docx");$data$jscomp$4_data$jscomp$5_returnvalue$$=
24
- $e$jscomp$7_result$$;$data$jscomp$4_data$jscomp$5_returnvalue$$?.type=="Buffer"&&$data$jscomp$4_data$jscomp$5_returnvalue$$?.data&&($data$jscomp$4_data$jscomp$5_returnvalue$$=Buffer.from($data$jscomp$4_data$jscomp$5_returnvalue$$.data));$res$$.send($data$jscomp$4_data$jscomp$5_returnvalue$$);break;default:$res$$.send($e$jscomp$7_result$$)}})}catch($e$$){$res$$.status(400).send($e$$)}};$router$$.route(`${this.base_path+this.module}`).get($mainRoute$$);$router$$.route(`${this.base_path+this.module}`).post($mainRoute$$);
25
- $router$$.route(`${this.base_path+this.module}/excel`).get($excelRoute$$);$router$$.route(`${this.base_path+this.module}/excel`).post($excelRoute$$)}getData($req$$,$callback$$){const $ctrl$$=this;let $callback_run$$=!1;setImmediate(()=>{try{$ctrl$$.fecthDataFunc($req$$,($err$$,$data$$,$event$$)=>{if($ctrl$$.options?.stream){if($err$$)return $callback$$($err$$);$event$$!="data"||$callback_run$$||($callback_run$$=!0,this.handleResult($req$$,{error:$err$$,result:$data$$},($e$$,$rs$$)=>{$callback$$($e$$,
26
- $rs$$)}))}else $callback_run$$=!0,this.handleResult($req$$,{error:$err$$,result:$data$$},($e$$,$rs$$)=>{$callback$$($e$$,$rs$$)})})}catch($e$$){console.error("[report controller] [getData]",$e$$),$callback$$($e$$.message)}})}createRoute($routeName$$,$callbackRoute_handler$$,$_options$$={method:"GET",not_use_worker:!1}){const $self$$=this;$_options$$.method=$_options$$.method?$_options$$.method.toUpperCase():"GET";const $route_action_key$$=`rpt_route_action_${$self$$.module}_${$routeName$$}_${$_options$$.method}`;
27
- $self$$[$route_action_key$$]=$callbackRoute_handler$$;$callbackRoute_handler$$=async function($ip$jscomp$2_req$$,$res$$){const {query:$query$$,body:$body$$,user:$user$$,params:$params$$,files:$files$$}=$ip$jscomp$2_req$$;var $_req$jscomp$2_user_agent$$=$ip$jscomp$2_req$$.header("user-agent");$ip$jscomp$2_req$$=$ip$jscomp$2_req$$.ip||$ip$jscomp$2_req$$.headers["x-forwarded-for"]||$ip$jscomp$2_req$$.connection.remoteAddress;try{if($_req$jscomp$2_user_agent$$={handler:"rptCreateRouteHandler",routeName:$routeName$$,
28
- _options:$_options$$,route_action_key:$route_action_key$$,query:$query$$,body:$body$$,user:$user$$,params:$params$$,user_agent:$_req$jscomp$2_user_agent$$,ip:$ip$jscomp$2_req$$,files:$files$$},!global.reportMainPool||global.reportMainPool.fullQueue()||$_options$$.not_use_worker)handlers.rptCreateRouteHandler(this,$_req$jscomp$2_user_agent$$,($e$$,$returnvalue$$)=>{if($e$$)return $res$$.status(400).send($e$$);$res$$.send($returnvalue$$)});else{const $id_task$$=`report-create-route-${crypto.randomBytes(20).toString("hex")}`;
29
- global.reportMainPool.exec({id_task:$id_task$$,req:$_req$jscomp$2_user_agent$$,module:$self$$.module.toUpperCase(),configs:JSON.stringify(configs)},$response$jscomp$6_result$$=>{if($response$jscomp$6_result$$.error)return $res$$.status(400).send($response$jscomp$6_result$$.error);({result:$response$jscomp$6_result$$}=$response$jscomp$6_result$$);$res$$.send($response$jscomp$6_result$$)})}}catch($e$$){$res$$.status(400).send($e$$)}};$_options$$.method=="DELETE"?this.router.route(`${this.base_path+
30
- this.module}/${$routeName$$}`).delete($callbackRoute_handler$$):$_options$$.method=="POST"?this.router.route(`${this.base_path+this.module}/${$routeName$$}`).post($callbackRoute_handler$$):$_options$$.method=="PUT"?this.router.route(`${this.base_path+this.module}/${$routeName$$}`).put($callbackRoute_handler$$):this.router.route(`${this.base_path+this.module}/${$routeName$$}`).get($callbackRoute_handler$$)}}module.exports=controllerRPT;
56
+ })`;
57
+ try{
58
+ let rs = await evalute(func_string,{data,moment,numeral,condition:req.query,user:req.user,_,utils,getData:getParameterData})();
59
+ if(rs){
60
+ if(rs.error){
61
+ console.error("handle_data_expression_server",rs.error,func_string,rptId);
62
+ return callback(rs.error.message || rs.error);
63
+ }
64
+ data = rs;
65
+ }
66
+ }catch(e){
67
+ console.error("handle_data_expression_server",e,func_string,rptId);
68
+ return callback(e.message || e);
69
+ }
70
+ }
71
+ callback(null,data)
72
+ }
73
+ }
74
+ //Hàm tạo function chạy báo cáo
75
+ this.getDataFunc = ()=>{
76
+ const currentStore = getCurrentStore(); // lấy context tại thời điểm tạo hàm
77
+ console.log(`✅ [rptHanlder] [getDataFunc], storeId=${currentStore?.storeId || "none"},sessionID=${getCurrentSession()?._debugId}`);
78
+ if(options.stream ) return fecthData;
79
+ return async (req,callback)=>{
80
+ //chạy báo cáo
81
+ console.log(`✅ [rptHanlder] Chạy báo cáo ${rptId}, sessionID=${getCurrentSession()?._debugId}`);
82
+ try{
83
+ await fecthData(req,(e,data)=>{
84
+ const response={
85
+ error:e,
86
+ result:data
87
+ }
88
+ this.handleResult(req,response,(e,rs)=>{
89
+ callback(e,rs)
90
+ })
91
+ })
92
+ }catch(e){
93
+ callback(e)
94
+ }
95
+ }
96
+ }
97
+ //route chạy báo cáo trả về dự liệu là json
98
+ const mainRoute =async (req,res)=>{
99
+ if(options.stream){
100
+ handlers.rptHandler(this,req,(e,rs)=>{
101
+ //có function xử lý kế quả
102
+ if(options.resHandler){
103
+ return options.resHandler(req,{error:e,data:rs},res);
104
+ }
105
+ //xử lý kết quả mặc định
106
+ if(e){
107
+ if(e.error){
108
+ return res.status(500).send(e);
109
+ }
110
+ return res.status(500).send({error:e.message || e});
111
+ }
112
+ if(rs=="__end_stream__"){
113
+ console.log("[controllerRPT] end stream...",rptId)
114
+ }else{
115
+ res.send(rs);
116
+ }
117
+ },res)
118
+ }else{
119
+ const {query,body,user,params,files} = req;
120
+ const user_agent = req.header('user-agent');
121
+ const ip = req.ip || req.headers['x-forwarded-for']||req.connection.remoteAddress;
122
+ try{
123
+ const _req = {handler:"rptHandler",query,body,user,params,user_agent,ip,files}
124
+ if(global.reportMainPool && !global.reportMainPool.fullQueue() && options.queue!=false ){
125
+ const id_task = `report-${crypto.randomBytes(20).toString('hex')}`;
126
+ //Nếu có thông báo phải chờ, thì gửi thông báo cho client
127
+ if(options.waiting_message){
128
+ const status_task = `${configs.api_url || configs.domain}/task-status/${id_task}`;
129
+ res.status(202).send([{message:options.waiting_message,status_task}])
130
+ }
131
+ global.reportMainPool.exec({
132
+ id_task,
133
+ req:_req,
134
+ module:rptId.toUpperCase(),
135
+ configs: JSON.stringify(configs)
136
+ },(response)=>{
137
+ setImmediate(()=>{
138
+ if(!options.waiting_message){
139
+ //có function xử lý kế quả
140
+ if(options.resHandler){
141
+ return options.resHandler(req,{error:response.error,data:response.result},res);
142
+ }
143
+ //xử lý kết quả mặc định
144
+ if(response.error) return res.status(400).send(response.error);
145
+ res.send(response.result);
146
+ }
147
+ })
148
+ })
149
+ }else{
150
+ if(options.waiting_message){
151
+ res.status(202).send([{message:options.waiting_message}])
152
+ }
153
+ handlers.rptHandler(this,_req,(e,returnvalue)=>{
154
+ if(!options.waiting_message){
155
+ //có function xử lý kế quả
156
+ if(options.resHandler){
157
+ return options.resHandler(req,{error:e,data:returnvalue},res);
158
+ }
159
+ //xử lý kết quả mặc định
160
+ if(e) return res.status(400).send(e);
161
+ res.send(returnvalue);
162
+ }
163
+ })
164
+ }
165
+
166
+ }catch(e){
167
+ console.error("Lỗi tạo job cho báo cáo",rptId,e);
168
+ res.status(400).send(e);
169
+ }
170
+ }
171
+ }
172
+ //Route chạy báo cáo trả về dữ liệu theo template (html,excel, docx hay json)
173
+ const excelRoute = async(req, res) => {
174
+ const {query,body,user,params,files} = req;
175
+ const user_agent = req.header('user-agent');
176
+ const ip = req.ip || req.headers['x-forwarded-for']||req.connection.remoteAddress;
177
+ try{
178
+ const _req = {handler:"rptExcelHandler",query,body,user,params,user_agent,ip,files}
179
+ if(global.reportMainPool && !global.reportMainPool.fullQueue() && options.queue!=false ){
180
+ const id_task = `report-export-${crypto.randomBytes(20).toString('hex')}`;
181
+ global.reportMainPool.exec({
182
+ id_task,
183
+ req:_req,
184
+ module:rptId.toUpperCase(),
185
+ configs: JSON.stringify(configs)
186
+ },(response)=>{
187
+ if(response.error) return res.status(400).send(response.error);
188
+ let returnvalue = response.result;
189
+ let ext = returnvalue.type;
190
+ const result = returnvalue.data;
191
+ switch(ext){
192
+ case "xlsx":{
193
+ console.log("[controllerRPT] send xls file from worker...");
194
+ res.setHeader('Content-Type', 'application/vnd.openxmlformats');
195
+ res.setHeader('Content-Disposition', 'attachment; filename=' + rptId + '.xlsx');
196
+ //convert sang buffer nếu data là một object có type ==Buffer
197
+ let data = result;
198
+ if(data?.type == "Buffer" && data?.data){
199
+ data = Buffer.from(data.data);
200
+ }
201
+ res.send(data);
202
+ break;
203
+ }
204
+ case "docx":{
205
+ res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document');
206
+ res.setHeader('Content-Disposition', 'attachment; filename=' + rptId + '.docx');
207
+ //convert sang buffer nếu data là một object có type ==Buffer
208
+ let data = result;
209
+ if(data?.type == "Buffer" && data?.data){
210
+ data = Buffer.from(data.data);
211
+ }
212
+ res.send(data);
213
+ break;
214
+ }
215
+ default:
216
+ res.send(result);
217
+ }
218
+ })
219
+ }else{
220
+ handlers.rptExcelHandler(this,_req,(e,returnvalue)=>{
221
+ if(e) return res.status(400).send(e);
222
+ let ext = returnvalue.type;
223
+ const result = returnvalue.data;
224
+ switch(ext){
225
+ case "xlsx":{
226
+ console.log("[controllerRPT] send xls file...");
227
+ res.setHeader('Content-Type', 'application/vnd.openxmlformats');
228
+ res.setHeader('Content-Disposition', 'attachment; filename=' + rptId + '.xlsx');
229
+ //convert sang buffer nếu data là một object có type ==Buffer
230
+ let data = result;
231
+ if(data?.type == "Buffer" && data?.data){
232
+ data = Buffer.from(data.data);
233
+ }
234
+ res.send(data);
235
+ break;
236
+ }
237
+ case "docx":{
238
+ res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document');
239
+ res.setHeader('Content-Disposition', 'attachment; filename=' + rptId + '.docx');
240
+ //convert sang buffer nếu data là một object có type ==Buffer
241
+ let data = result;
242
+ if(data?.type == "Buffer" && data?.data){
243
+ data = Buffer.from(data.data);
244
+ }
245
+ res.send(data);
246
+ break;
247
+ }
248
+ default:
249
+ res.send(result);
250
+ }
251
+ })
252
+ }
253
+ }catch(e){
254
+ res.status(400).send(e);
255
+ }
256
+ };
257
+
258
+ router.route(`${this.base_path + this.module}`).get(mainRoute);
259
+ router.route(`${this.base_path + this.module}`).post(mainRoute);
260
+
261
+ router.route(`${this.base_path + this.module}/excel`).get(excelRoute);
262
+ router.route(`${this.base_path + this.module}/excel`).post(excelRoute);
263
+ }
264
+ //Hàm này sẽ chạy báo cáo trả về dữ liệu là json. Nếu báo cáo là dạng stream thì chỉ lấy kết quả cuối cùng
265
+ getData(req,callback){
266
+ const ctrl = this;
267
+ let callback_run = false;
268
+ setImmediate(()=>{
269
+ try{
270
+ ctrl.fecthDataFunc(req,(err,data,event)=>{
271
+ if(ctrl.options?.stream){
272
+ if(err) return callback(err);
273
+ //Chỉ gọi callback một lần khi event là data
274
+ if(event=="data" && !callback_run){
275
+ callback_run = true;
276
+ //Xử lý kết quả báo cáo
277
+ const response={
278
+ error:err,
279
+ result:data
280
+ }
281
+ this.handleResult(req,response,(e,rs)=>{
282
+ callback(e,rs)
283
+ })
284
+ }
285
+ }else{
286
+ callback_run = true;
287
+ //Xử lý kết quả báo cáo
288
+ const response={
289
+ error:err,
290
+ result:data
291
+ }
292
+ this.handleResult(req,response,(e,rs)=>{
293
+ callback(e,rs)
294
+ })
295
+ }
296
+ });
297
+ }catch(e){
298
+ console.error("[report controller] [getData]",e);
299
+ callback(e.message);
300
+ }
301
+ })
302
+ }
303
+ //tạo custom route
304
+ createRoute(routeName, callbackRoute, _options = {method: 'GET',not_use_worker:false}) {
305
+ const self = this;
306
+ if (!_options.method) {
307
+ _options.method = 'GET';
308
+ } else {
309
+ _options.method = _options.method.toUpperCase();
310
+ }
311
+ const route_action_key = `rpt_route_action_${self.module}_${routeName}_${_options.method}`
312
+ self[route_action_key] = callbackRoute;
313
+ const handler = async function(req, res) {
314
+ const {query,body,user,params,files} = req;
315
+ const user_agent = req.header('user-agent');
316
+ const ip = req.ip || req.headers['x-forwarded-for']||req.connection.remoteAddress;
317
+ try{
318
+ const _req = {handler:"rptCreateRouteHandler",routeName,_options,route_action_key,query,body,user,params,user_agent,ip,files}
319
+ if(global.reportMainPool && !global.reportMainPool.fullQueue() && !_options.not_use_worker ){
320
+ const id_task = `report-create-route-${crypto.randomBytes(20).toString('hex')}`;
321
+ global.reportMainPool.exec({
322
+ id_task,
323
+ req:_req,
324
+ module:self.module.toUpperCase(),
325
+ configs: JSON.stringify(configs)
326
+ },(response)=>{
327
+ if(response.error) return res.status(400).send(response.error);
328
+ let {result} = response;
329
+ res.send(result);
330
+ })
331
+ }else{
332
+ handlers.rptCreateRouteHandler(this,_req,(e,returnvalue)=>{
333
+ if(e) return res.status(400).send(e);
334
+ res.send(returnvalue);
335
+ })
336
+ }
337
+ }catch(e){
338
+ res.status(400).send(e);
339
+ }
340
+ };
341
+ if (_options.method == 'DELETE') {
342
+ this.router.route(`${this.base_path + this.module}/${routeName}`).delete(handler);
343
+ } else {
344
+ if (_options.method == 'POST') {
345
+ this.router.route(`${this.base_path + this.module}/${routeName}`).post(handler);
346
+ } else {
347
+ if (_options.method == 'PUT') {
348
+ this.router.route(`${this.base_path + this.module}/${routeName}`).put(handler);
349
+ } else {
350
+ this.router.route(`${this.base_path + this.module}/${routeName}`).get(handler);
351
+ }
352
+ }
353
+ }
354
+
355
+ }
356
+ }
357
+ module.exports = controllerRPT;