zet-lib 1.0.0

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/lib/zReport.js ADDED
@@ -0,0 +1,930 @@
1
+ const axios = require('axios');
2
+ const fs = require('fs-extra');
3
+ const nodemailer = require('nodemailer');
4
+ const qs = require('qs');
5
+ const moment = require('moment');
6
+ const XLSX = require('xlsx');
7
+ const Excel = require('exceljs');
8
+ const debug = require("./debug");
9
+ const zRoute = require("./zRoute");
10
+ const Util = require('./Util');
11
+ const connection = require('./connection');
12
+ const io = require('./io');
13
+ const config = require('dotenv').config();
14
+ const dirRoot = process.env.dirRoot;
15
+ const zReport = {};
16
+
17
+
18
+ /*
19
+ Custom Reports
20
+ Report Generator
21
+ */
22
+
23
+
24
+ /*
25
+ UI For edit excel File
26
+ */
27
+ zReport.reportData = (filename, data, sessions = {}) => {
28
+ console.log(filename);
29
+ const workbook = XLSX.readFile(filename);
30
+ const Sheets = workbook.Sheets;
31
+ let sheet = Sheets[Object.keys(Sheets)[0]];
32
+ let excel = Util.excelSequence();
33
+ let ref = sheet["!ref"];
34
+ let explode = ref.split(":");
35
+ let lastchar = explode[1];
36
+ let stringPattern = /[A-Z]+/i;
37
+ let digitPattern = /[0-9]+/i;
38
+ let stringColumn = lastchar.match(stringPattern)[0];
39
+ let maxColumn = excel.indexOf(stringColumn);
40
+
41
+ let maxRow = lastchar.match(digitPattern)[0];
42
+ //add 5 row for input cells
43
+ maxRow = parseInt(maxRow) + 5;
44
+ let excelData = {};
45
+ let excelValue = {};
46
+ let tableModel = {};
47
+ let dataForExcel = data.excel;
48
+ let dataCallback = data.callback || [];
49
+ let callback = {};
50
+ let objQuery = {};
51
+ let results = [];
52
+
53
+ //set callback as object
54
+ dataCallback.map((m) => {
55
+ callback[m.name] = m.value;
56
+ });
57
+
58
+ //console.log(JSON.stringify(sessions));
59
+
60
+ //create UI Button in excel cell
61
+ if (dataForExcel) {
62
+ dataForExcel.forEach((datafor, index) => {
63
+ let button = "",
64
+ name = datafor.name,
65
+ callback = datafor.callback || "",
66
+ value = datafor.value || "";
67
+ let split = value.split(".");
68
+ let len = split.length;
69
+ let MYMODEL = {};
70
+ let table = "", tableKey = "";
71
+ if (len == 4) {
72
+ table = split[2];
73
+ tableKey = split[3];
74
+ } else {
75
+ table = split[0];
76
+ tableKey = split[1];
77
+ }
78
+
79
+ const MYMODELS = zRoute.MYMODELS() || {};
80
+ MYMODEL = tableModel.hasOwnProperty(table) ? tableModel[table] : MYMODELS[table];
81
+ if (!objQuery[table]) {
82
+ objQuery[table] = [];
83
+ }
84
+ objQuery[table].push(value);
85
+ if (!excelValue) {
86
+ excelValue[name] = "";
87
+ } else {
88
+ button = excelValue[name] || "";
89
+ }
90
+
91
+ let labels = value.indexOf("_SESSIONS_") > -1 ? value.replace("_SESSIONS_.", "") : tableKey;
92
+ button += `<li class="dragged"> <button class="btn btn-info btn-excel" type="button" title="${name.replace('[', '').replace(']', '')} : ${value}">${MYMODEL.labels[labels]}
93
+ <input type="hidden" class="EXCEL" name="${name}" value='${value}_CALLBACK_SEPARATOR_${callback}'> <i class="fa fa-code call-me"></i> <i class="fa fa-trash trash-me"></i></button></li>`;
94
+ excelValue[name] = button;
95
+ });
96
+ }
97
+ //end UI
98
+
99
+ let table = `<table class="table table-striped table-bordered" >`;
100
+ for (var x = 1; x < maxRow; x++) {
101
+ table += `<tr>`;
102
+ let arr = [];
103
+ for (var i = 0; i <= maxColumn; i++) {
104
+ let str = excel[i] + x;
105
+ let strkey = excel[i] + "[" + x + "]";
106
+ let defaultValue = Object.prototype.hasOwnProperty.call(sheet, str) ? sheet[str].v : "";
107
+ let value = excelValue[strkey] || defaultValue;
108
+ table += `<td width="80px" id="${str}" title="${str}" class="mydragable" data-col="${excel[i]}" data-row="${x}">${value}</td>`;
109
+ arr.push(value)
110
+ }
111
+ table += `</tr>`;
112
+ results.push(arr);
113
+ }
114
+ table += `</table>`;
115
+ return {
116
+ table: table,
117
+ excelData: excelData,
118
+ results: results,
119
+ max: maxRow,
120
+ objQuery: objQuery
121
+ }
122
+ };
123
+
124
+
125
+ //Save reports Setup
126
+ zReport.reportPostData = async(req, res) => {
127
+ let data_status = Util.jsonSuccess("Success");
128
+ try {
129
+ let body = req.body;
130
+ ///console.log(body)
131
+ let post = zRoute.postData(body);
132
+ let ex = post.excel;
133
+ delete post.excel;
134
+ let id = body.id;
135
+ let CALLBACK_SEPARATOR = "_CALLBACK_SEPARATOR_";
136
+
137
+ //remove CALLBACK in query
138
+ //sometimes bug in query callback separator in javascript
139
+ let query = body.query;
140
+ query = Util.replaceAll(query, CALLBACK_SEPARATOR, "");
141
+ let callback = [], excel = [];
142
+ ex.map((e) => {
143
+ let name = e.name || "";
144
+ let value = e.value || "";
145
+ //console.log(value);
146
+ if (value.indexOf(CALLBACK_SEPARATOR) > -1) {
147
+ let split = value.split(CALLBACK_SEPARATOR);
148
+ excel.push({
149
+ name: name,
150
+ title: name.replace("[", "").replace("]", ""),
151
+ value: split[0],
152
+ callback: Util.replaceAll(split[1], "'", '"')
153
+ });
154
+ }
155
+ });
156
+ post.excel = excel || "";
157
+ post.query = query || "";
158
+ await connection.update({
159
+ table : "zreport",
160
+ data : {json: JSON.stringify(post)},
161
+ where : {
162
+ id : id
163
+ }
164
+ });
165
+ } catch (err) {
166
+ debug(req, res, err);
167
+ data_status = Util.flashError(err.toString());
168
+ }
169
+ res.json(data_status);
170
+ };
171
+
172
+
173
+ //SUBMIT REPORT ROUTE FOR REPORT GENERATOR
174
+ zReport.submitReport = async(req, res) => {
175
+ let company_id = res.locals.companyId;
176
+ let body = req.body;
177
+ console.log("BODYYYYYY");
178
+ console.log(body);
179
+ delete body._csrf;
180
+ const MYMODELS = zRoute.MYMODELS() || {};
181
+ //delete key where null
182
+ for (let keys in body) {
183
+ if (body[keys] == "") {
184
+ delete body[keys];
185
+ }
186
+ if (body[keys] == "undefined") {
187
+ delete body[keys];
188
+ }
189
+ }
190
+ //console.log(body);
191
+ let $session = req.session.user;
192
+ try {
193
+ let reportId = body.zreport_name;
194
+ let row = await connection.result({
195
+ table: "zreport",
196
+ where: {
197
+ id: reportId
198
+ }
199
+ });
200
+ let json = row.json ? row.json : {};
201
+ console.log(json);
202
+ let query = json.query || "";
203
+ let table = json.tables[0] || "";
204
+ if (!table) {
205
+ return res.json("error not configure!");
206
+ }
207
+ let title = row.title;
208
+ let jsonExcels = json.excel || [];
209
+ let excelObj = {};
210
+ let callback = {};
211
+ jsonExcels.map((jsonExcel) => {
212
+ if (!excelObj[jsonExcel.name])
213
+ excelObj[jsonExcel.name] = [];
214
+
215
+ let jsonvalue = Util.replaceAll(jsonExcel.value, ".", "___");
216
+ let nameCallback = jsonExcel.title + "___" + jsonvalue;
217
+
218
+ jsonExcel.callbackName = nameCallback;
219
+
220
+ let split = jsonvalue.split("___");
221
+ if (split.length == 2) {
222
+ jsonExcel.data = jsonvalue;
223
+ } else if (split.length == 3) {
224
+ jsonExcel.data = split[0] + "___" + split[1];
225
+ } else {
226
+ jsonExcel.data = jsonvalue;
227
+ }
228
+
229
+ if (jsonExcel.callback)
230
+ callback[nameCallback] = jsonExcel.callback;
231
+
232
+ excelObj[jsonExcel.name].push(jsonExcel);
233
+ });
234
+
235
+ delete body.zreports_name;
236
+
237
+ //console.log(filterWhere);
238
+ //excel instance
239
+ var workbook = new Excel.Workbook();
240
+ let filename = `${dirRoot}/public/uploads/zreport/${row.excel}`;
241
+ await workbook.xlsx.readFile(filename);
242
+ var worksheet = workbook.worksheets[0]; //the first one;
243
+ let images = []; // store images
244
+ // Force workbook calculation on load
245
+ //workbook.calcProperties.fullCalcOnLoad = true;
246
+
247
+ //set images
248
+ var setExcelImages = (script, data, r, c) => {
249
+ let excelsq = Util.excelSequence();
250
+ //A1 = col=0 row=0
251
+ //convert column to integer
252
+ c = excelsq.indexOf(c);
253
+ r = r - 1;
254
+ script = script || "";
255
+ if (script == "") {
256
+ return "";
257
+ }
258
+ data = data || "";
259
+ if (data == "") {
260
+ return "";
261
+ }
262
+
263
+ let str = script.replace("hasImages(", "").replace(")", "");
264
+ let explode = str.split(",");
265
+ let table = explode[0].trim() || "";
266
+ let width = parseInt(explode[1]) || 200;
267
+ let height = parseInt(explode[2]) || 200;
268
+ let photoName = `${dirRoot}/public/uploads/${table}/${data}`;
269
+ if (!fs.existsSync(photoName)) {
270
+ return "";
271
+ }
272
+ let image = workbook.addImage({
273
+ filename: photoName,
274
+ extension: data.split(".").pop()
275
+ });
276
+ images.push({
277
+ image: image,
278
+ width: width,
279
+ height: height,
280
+ c: c,
281
+ r: r,
282
+ });
283
+
284
+ return "";
285
+ };
286
+ //end set images
287
+
288
+ //query where sql;
289
+ //query executes
290
+ console.log("query")
291
+ console.log(JSON.stringify(query))
292
+ console.log("query")
293
+
294
+ let datas = [];
295
+ if (query) {
296
+ var wheres = [];
297
+ var whereArr = [];
298
+ var where = "";
299
+ //TODO if has order by limit
300
+ var sql = json.query;
301
+ console.log("sql");
302
+ console.log(sql);
303
+ console.log("sql");
304
+
305
+ var num = 1;
306
+ for (var key in json.filter) {
307
+ if (body[key]) {
308
+ wheres.push( Util.replaceAll(json.filter[key],"?",`$${num}`));
309
+ if (json.filter[key].includes("LIKE")) {
310
+ whereArr.push(`%${body[key]}%`)
311
+ } else {
312
+ whereArr.push(body[key])
313
+ }
314
+ num++;
315
+ }
316
+ }
317
+
318
+ //row.wheres from database
319
+ var rowWheres = row.wheres || [];
320
+ rowWheres.forEach(function (item) {
321
+ wheres.push(item);
322
+ });
323
+
324
+ if (wheres.length) {
325
+ where += " WHERE ";
326
+ where += wheres.join(" AND ");
327
+ }
328
+ var orderby = "";
329
+ if (row.orderby) {
330
+ orderby = ` ORDER BY ${row.orderby} `;
331
+ }
332
+ sql = sql + where + orderby;
333
+ console.log("sql")
334
+ console.log(sql)
335
+ console.log("sql")
336
+
337
+ console.log("whereArr")
338
+ console.log(JSON.stringify(whereArr))
339
+ console.log("whereArr")
340
+ datas = await connection.query(sql, whereArr);
341
+ }
342
+
343
+ let excelMap = {};
344
+ let beginLooping = 0
345
+ for (let keys in excelObj) {
346
+ let split = keys.split("[");
347
+ let column = split[0];
348
+ let idx = parseInt(split[1]);
349
+
350
+ if (!excelMap[keys]) excelMap[keys] = {}
351
+
352
+ excelMap[keys].column = column;
353
+ excelMap[keys].row = idx;
354
+ excelMap[keys].rowColumn = column + idx;
355
+ if (beginLooping == 0)
356
+ beginLooping = idx;
357
+ }
358
+
359
+ console.log("datas")
360
+ console.log(JSON.stringify(datas))
361
+ console.log("datas")
362
+
363
+ if (datas.length > 1) {
364
+ try {
365
+ for (var i = 0; i < (datas.length - 1); i++) {
366
+ let r = i + beginLooping;
367
+ worksheet.spliceRows(r + 1, 1, true);
368
+ worksheet.duplicateRow(r, 1, true);
369
+ }
370
+ } catch (e) {
371
+ console.log("no style");
372
+ }
373
+ }
374
+
375
+ var ioroom = function (err) {
376
+ io.to(res.locals.user.token).emit("error", err.toString());
377
+ };
378
+
379
+ datas.forEach((data, index) => {
380
+ for (let keys in excelObj) {
381
+ let columnIndex = excelMap[keys].column;
382
+ let rowIndex = parseInt(excelMap[keys].row) + index;
383
+ let rowColumn = columnIndex + rowIndex;
384
+ let value = excelObj[keys].map((m) => {
385
+ //console.log(m)
386
+ return callback.hasOwnProperty(m.callbackName) ? callback[m.callbackName].indexOf("hasImages") > -1 ? setExcelImages(callback[m.callbackName], data[m.data], rowIndex, columnIndex) : zReport.callbackReport(callback[m.callbackName], data[m.data], rowIndex, columnIndex, null, data, ioroom, res) : data[m.data]
387
+ }).join(" ");
388
+
389
+ worksheet.getCell(rowColumn).value = Util.isNumeric(value) ? parseFloat(value) : value;
390
+ }
391
+ });
392
+ //build images if any
393
+ images.map((m)=> {
394
+ worksheet.addImage(m.image, {
395
+ tl: {col: m.c, row: m.r},
396
+ ext: {width: m.width, height: m.height}
397
+ });
398
+ });
399
+
400
+ var fileName = title + '.xlsx';
401
+ if (row.scripts) {
402
+ return zReport.additionalScripts(req,res,row.scripts, fileName, datas, moment, Util, dirRoot, ioroom, connection, worksheet,workbook,debug)
403
+ } else {
404
+ res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
405
+ res.setHeader('Content-Disposition', 'attachment; filename=' + fileName);
406
+ await workbook.xlsx.write(res);
407
+ res.end();
408
+ }
409
+ } catch (e) {
410
+ console.log(e)
411
+ debug(req, res, e);
412
+ res.json(e.toString())
413
+ }
414
+ }
415
+
416
+ zReport.additionalScripts = (req,res,script, fileName, datas, moment, Util, dirRoot, ioroom, connection, worksheet, workbook) => {
417
+ script = script.trim() || "";
418
+ let CALL = {
419
+ Util: Util,
420
+ moment: moment,
421
+ datas: datas,
422
+ dirRoot: dirRoot,
423
+ ioroom: ioroom,
424
+ res: res,
425
+ req:req,
426
+ fileName: fileName,
427
+ connection: connection,
428
+ worksheet: worksheet,
429
+ workbook : workbook,
430
+ };
431
+ let STRINGS_VARIABLE = "";
432
+ Object.keys(CALL).forEach(function (item) {
433
+ STRINGS_VARIABLE += ` var ${item} = this.${item}; `;
434
+ });
435
+ return Function(`
436
+ var runcode = async() => {
437
+ ${STRINGS_VARIABLE}
438
+ try {
439
+ ${script};
440
+ res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
441
+ res.setHeader('Content-Disposition', 'attachment; filename=' + fileName);
442
+ await workbook.xlsx.write(res);
443
+ res.end();
444
+ } catch(e) {
445
+ console.log(e.toString());
446
+ res.json(e.toString());
447
+ }
448
+ };
449
+ runcode();
450
+
451
+ `).call(CALL);
452
+ };
453
+
454
+ zReport.callbackReport = (script, data, row, column, selectFromTable, obj, ioroom, res) => {
455
+ script = script.trim() || "";
456
+ let results = {}
457
+ for (var key in obj) {
458
+ let name = key.split("___");
459
+ if (name.length > 0) {
460
+ results[name[1]] = obj[key];
461
+ }
462
+ }
463
+
464
+ let first = script.charAt(0);
465
+ let CALL = {
466
+ Util: Util,
467
+ obj: obj,
468
+ moment: moment,
469
+ data: data,
470
+ dirRoot: dirRoot,
471
+ selectFromTable: selectFromTable,
472
+ row: row,
473
+ col: column,
474
+ results: results,
475
+ ioroom,
476
+ res: res
477
+ };
478
+ let STRINGS_VARIABLE = "";
479
+ Object.keys(CALL).forEach(function (item) {
480
+ STRINGS_VARIABLE += ` var ${item} = this.${item}; `;
481
+ });
482
+ return Function(`
483
+ ${STRINGS_VARIABLE}
484
+ try {
485
+ ${script};
486
+ } catch(e) {
487
+ console.log(e);
488
+ ioroom("CELLS : " + col+row+ " " +e.toString());
489
+ }
490
+ `).call(CALL);
491
+
492
+ };
493
+
494
+ zReport.staticDataReport = (data, filter) => {
495
+ delete data.id;
496
+ delete data.password;
497
+ delete data.token;
498
+ let session_obj = {};
499
+ let session_obj_fields = {}
500
+
501
+ filter.map((m) => {
502
+ let keyName = m.name;
503
+ session_obj[keyName] = m.label;
504
+ session_obj_fields[keyName] = {
505
+ name: keyName,
506
+ title: m.label,
507
+ type: "text",
508
+ category: "text",
509
+ length: "undefined",
510
+ required: false,
511
+ search: "LIKE",
512
+ key: "",
513
+ placeholder: m.label
514
+ }
515
+ });
516
+
517
+ for (var key in data) {
518
+ let keyName = "$session." + key;
519
+ session_obj[keyName] = key;
520
+ session_obj_fields[keyName] = {
521
+ name: keyName,
522
+ title: key,
523
+ type: "text",
524
+ category: "text",
525
+ length: "undefined",
526
+ required: false,
527
+ search: "LIKE",
528
+ key: "",
529
+ placeholder: key
530
+ }
531
+
532
+ if (key == "company") {
533
+ for (var k in data[key]) {
534
+ let keyName2 = "$session.company." + k;
535
+ session_obj[keyName2] = k;
536
+ session_obj_fields[keyName2] = {
537
+ name: keyName2,
538
+ title: key + " " + k,
539
+ type: "text",
540
+ category: "text",
541
+ length: "undefined",
542
+ required: false,
543
+ search: "LIKE",
544
+ key: "",
545
+ placeholder: key + " " + k,
546
+ }
547
+ }
548
+ }
549
+ }
550
+
551
+ return {
552
+ table: '_SESSIONS_',
553
+ routeName: "_SESSIONS_",
554
+ keys: Object.keys(session_obj),
555
+ labels: session_obj,
556
+ fields: session_obj_fields,
557
+ relations: {},
558
+ dropdowns: {},
559
+ modules: {}
560
+ }
561
+ }
562
+
563
+ zReport.listReports = async(data) => {
564
+ let html = "";
565
+ let rows = await connection.query("select * from zreport where parent_id = ?", [data.id]);
566
+ rows.forEach((obj, index) => {
567
+ let action = "";
568
+ if (obj.excel) {
569
+ action += `<a href="/zreport/setup/${obj.id}" class="btn btn-default"> <i class="fa fa-gear" title="Setup Report"></i> </a>`;
570
+ }
571
+ action += `<a href="/zreport/update/${obj.id}" class="btn btn-default"><i class="fa fa-pencil" title="Edit Data"></i> </a>`;
572
+ action += `<a href="#" class="btn btn-default reportdelete" data-id="${obj.id}"><i class="fa fa-trash " title="Delete Report"></i></a>`;
573
+ html += `<tr><td>${index + 1}. </td><td>${obj.title}</td><td><a href="/uploads/zreport/${obj.excel}">Excel File</a></td><td>${action}</td></tr>`;
574
+ });
575
+
576
+ return `<div class="form-group divReportList">
577
+ <div class="panel panel-default">
578
+ <div class="panel-heading">Report List</div>
579
+ <div class="panel-body">
580
+ <table class="table table-hover">
581
+ <thead>
582
+ <tr>
583
+ <th width="3%">#</th>
584
+ <th width="50%">Name</th>
585
+ <th>File</th>
586
+ <th class="pull-right"><a href="/zreport/create?id=${data.id}" class="btn btn-default" title="Add" id="addReportList"><i class="fa fa-plus"></i></a></th>
587
+ </tr>
588
+ </thead>
589
+ <tbody class="body-reportList" data-value="">${html}</tbody>
590
+ </table>
591
+ </div>
592
+ </div>
593
+ </div>`;
594
+ }
595
+
596
+
597
+ zReport.filterReport = async(req, res) => {
598
+ let id = req.params.id || "";
599
+ let companyId = res.locals.companyId;
600
+ let data = [], rows = [];
601
+ if (id == "") {
602
+ rows = await connection.query("select * from zreport where company_id = ? and parent_id IS NULL", [companyId])
603
+ } else {
604
+ rows = await connection.results({table: "zreport", where: {id: id, company_id: companyId}})
605
+ }
606
+
607
+ console.log(rows)
608
+ for (var i = 0; i < rows.length; i++) {
609
+
610
+ var row = rows[i];
611
+ //rows.forEach(async function (row) {
612
+ let reportsRow = await connection.results({table: "zreport", where: {parent_id: row.id}});
613
+ console.log(reportsRow)
614
+ let filterHtml = reportsRow.length > 0 ? `<form method="post" action="/zreport" >` : '';
615
+ let filters = JSON.parse(row.filter) || [];
616
+ console.log("filters :")
617
+ console.log(filters)
618
+ row.listReports = await zReport.listReports(row);
619
+ for (var x = 0; x < filters.length; x++) {
620
+ let filter = filters[x];
621
+ let options = `<option value="">Please Select</option>`;
622
+ let html = '';
623
+ if (filter.type == 1) {
624
+ html = `<input type="text" class="datepicker form-control" name="${filter.name}" >`;
625
+
626
+ } else if (filter.type == 2) {
627
+ let values = JSON.parse(filter.value) || [];
628
+ values.map(function (e) {
629
+ options += `<option value="${e.key}">${e.label}</option>`;
630
+ });
631
+ html = `<select class="form-control form-select" name="${filter.name}">${options}</select>`;
632
+
633
+ } else if (filter.type == 3) {
634
+ let values = filter.value || "";
635
+ let explode = values.split(".");
636
+ let table = explode[0];
637
+ if (table && fs.existsSync(dirRoot + "/models/" + table + ".js")) {
638
+ let keycolumn = explode[1];
639
+ let labelcolumn = explode[2];
640
+ let MYMODEL = require('./../models/' + table);
641
+ let fields = MYMODEL.keys;
642
+ let where = '';
643
+ if (fields.indexOf("company_id") > -1) {
644
+ where = ` where company_id = ${company_id} `;
645
+ }
646
+ let results = await connection.query("select * from `" + table + "` " + where + " order by " + labelcolumn + " ASC");
647
+ results.map(async(result) => {
648
+ options += `<option value="${result[keycolumn]}">${result[labelcolumn]}</option>`;
649
+ });
650
+ html = `<select class="form-control form-select" name="${filter.name}">${options}</select>`;
651
+ }
652
+ }
653
+ filterHtml += `<div class="row"><div class="form-group"><label class="control-label col-md-2">${filter.label}</label><div class="col-md-10">${html}</div></div></div><br>`;
654
+ row.filterHtml = filterHtml;
655
+ }
656
+
657
+ //drop down report name
658
+ let reportList = "";
659
+ if (reportsRow.length > 0) {
660
+ let reportOptions = "";
661
+ reportsRow.map((obj) => {
662
+ reportOptions += `<option value="${obj.id}">${obj.title}</option>`
663
+ });
664
+ reportList += `<div class="row"><div class="form-group"><label class="control-label col-md-2">Report Name</label><div class="col-md-10"><select class="form-control" id="zreports_name" name="zreports_name">${reportOptions}</select></div></div></div>`;
665
+ reportList += `<br><button type="submit" class="btn btn-block btn-success">Submit </button> `;
666
+ reportList += `</form>`;
667
+ }
668
+ row.reportList = reportList;
669
+
670
+ data.push(row);
671
+ }
672
+
673
+ return data;
674
+ }
675
+
676
+ /*
677
+ One line
678
+ */
679
+ zReport.filters2 = async(arr, companyId) => {
680
+ var html = '';
681
+
682
+ for (var i = 0; i < arr.length; i++) {
683
+ var filter = arr[i];
684
+
685
+ html += ` <div class="mb-3 row">
686
+ <label for="${filter.name}"class="col-sm-4 col-form-label">${filter.label}</label>
687
+ <div class="col-sm-8">`;
688
+
689
+ if (filter.type == 1) {
690
+ html += `<input type="text" class="datepicker form-control" name="${filter.name}" >`;
691
+
692
+ } else if (filter.type == 2) {
693
+ let values = filter.value ? JSON.parse(filter.value) : [];
694
+ let options = `<option value="">Please Select</option>`;
695
+ if (values.length) {
696
+ values.map(function (e) {
697
+ options += `<option value="${e.key}">${e.label}</option>`;
698
+ });
699
+ html += `<select class="form-control form-select" name="${filter.name}">${options}</select>`;
700
+ }
701
+
702
+
703
+ } else if (filter.type == 3) {
704
+ let values = filter.value || "";
705
+ let explode = values.split(".");
706
+ let table = explode[0];
707
+ let options = `<option value="">Please Select</option>`;
708
+ if (table && fs.existsSync(dirRoot + "/models/" + table + ".js")) {
709
+ let keycolumn = explode[1];
710
+ let labelcolumn = explode[2];
711
+ let MYMODEL = require('./../models/' + table);
712
+ let fields = MYMODEL.keys;
713
+ let where = '';
714
+ if (fields.indexOf("company_id") > -1) {
715
+ where = ` where company_id = ${companyId} `;
716
+ }
717
+ let results = await connection.results({
718
+ table : table,
719
+ where : {
720
+ company_id : companyId
721
+ },
722
+ orderby : [labelcolumn, "ASC"]
723
+ })
724
+ if(results.length) {
725
+ results.map(async(result) => {
726
+ options += `<option value="${result[keycolumn]}">${result[labelcolumn]}</option>`;
727
+ });
728
+ }
729
+ html += `<select class="form-control form-select" name="${filter.name}">${options}</select>`;
730
+ }
731
+ }
732
+
733
+ html += `</div>
734
+ </div>`;
735
+
736
+ }
737
+
738
+ return html;
739
+ }
740
+
741
+
742
+ zReport.filters = async(arr, companyId) => {
743
+ var html = '';
744
+
745
+ for (var i = 0; i < arr.length; i++) {
746
+ var filter = arr[i];
747
+
748
+ html += `<div class="mb-3"><label for="${filter.name}" class="form-label">${filter.label}</label>`;
749
+ if (filter.type == 1) {
750
+ html += `<input type="text" class="datepicker form-control" name="${filter.name}" >`;
751
+
752
+ } else if (filter.type == 2) {
753
+ let values = filter.value ? JSON.parse(filter.value) : [];
754
+ let options = '';
755
+ if (values.length) {
756
+ values.map(function (e) {
757
+ options += `<option value="${e.key}">${e.label}</option>`;
758
+ });
759
+ html += `<select class="form-control form-select" name="${filter.name}">${options}</select>`;
760
+ }
761
+
762
+
763
+ } else if (filter.type == 3) {
764
+ let values = filter.value || "";
765
+ let explode = values.split(".");
766
+ let table = explode[0];
767
+ let options = '';
768
+ if (table && fs.existsSync(dirRoot + "/models/" + table + ".js")) {
769
+ let keycolumn = explode[1];
770
+ let labelcolumn = explode[2];
771
+ let MYMODEL = require('./../models/' + table);
772
+ let fields = MYMODEL.keys;
773
+ let where = '';
774
+ if (fields.indexOf("company_id") > -1) {
775
+ where = ` where company_id = ${companyId} `;
776
+ }
777
+ let results = await connection.query("select * from `" + table + "` " + where + " order by " + labelcolumn + " ASC");
778
+ results.map(async(result) => {
779
+ options += `<option value="${result[keycolumn]}">${result[labelcolumn]}</option>`;
780
+ });
781
+ html += `<select class="form-control form-select" name="${filter.name}">${options}</select>`;
782
+ }
783
+ }
784
+
785
+ html += `</div>`;
786
+
787
+ }
788
+
789
+ return html;
790
+ }
791
+
792
+ zReport.showAll = async(req, res) => {
793
+ var html = '';
794
+ var companyId = res.locals.companyId;
795
+ var rows = await connection.query("select * from zreport where company_id = ? and parent_id IS NULL", [companyId]);
796
+ for (var i = 0; i < rows.length; i++) {
797
+ var isEnd = false;
798
+
799
+ if (i == 0) html += `<div class="row">`;
800
+
801
+ if (i > 1) {
802
+ if (i % 2 == 0) {
803
+ html += `<div class="row">`;
804
+ isEnd = true;
805
+ }
806
+
807
+ if (i == (rows.length - 1)) {
808
+ isEnd = true;
809
+ }
810
+ }
811
+
812
+ var content = await zReport.show(rows[i].id, companyId);
813
+ html += `<div class="col">${content}</div>`
814
+
815
+ if (i == 1) html += `</div>`;
816
+
817
+
818
+ if (i > 1) {
819
+ if (isEnd) {
820
+ html += `</div>`;
821
+ isEnd = false;
822
+ }
823
+ }
824
+ }
825
+
826
+ return html;
827
+
828
+ }
829
+
830
+ zReport.show = async(id, companyId, csrfToken, isHideLink = false) => {
831
+ var html = '';
832
+ var result = await connection.result({
833
+ table: "zreport",
834
+ where: {
835
+ id: id
836
+ }
837
+ })
838
+ if (result.id) {
839
+ if (result.parent_id) {
840
+ result = await connection.result({
841
+ table: "zreport",
842
+ where: {
843
+ id: result.parent_id
844
+ }
845
+ })
846
+ }
847
+
848
+ var arr = [];
849
+ arr.push({id: result.id, label: result.title});
850
+ var rows = await connection.results({
851
+ table: "zreport",
852
+ where: {
853
+ parent_id: result.id
854
+ }
855
+ })
856
+ rows.forEach(function (item) {
857
+ arr.push({id: item.id, label: item.title});
858
+ })
859
+
860
+ var reports = `<div class="mb-3 row"><label for="reporttype" class="col-sm-4 form-label">Report Name</label><div class="col-sm-8"><select class="form-control form-select" id="zreport_name" name="zreport_name">`;
861
+ arr.forEach(function (item) {
862
+ reports += `<option value="${item.id}">${item.label}</option>`
863
+ })
864
+ reports += `</select></div></div>`;
865
+
866
+ var link = '';
867
+ if (!isHideLink) {
868
+ link = `<div class="card-footer">
869
+ <i class="fa fa-copy copy-link" title="copy link" data-url="${CONFIG.app.url}/zreport/show/${result.id}/${result.title}"></i>
870
+ <a href="${CONFIG.app.url}/zreport/show/${result.id}/${result.title}" class="card-link">${CONFIG.app.url}/zreport/show/${result.id}/${result.title}</a>
871
+ </div>`
872
+ }
873
+ //one line filters2
874
+ var filter = await zReport.filters2(result.filters || [], companyId);
875
+ html += `<form class="form" method="post" action="/zreport/report" >`;
876
+ html += `<input type="hidden" name="_csrf" value="${csrfToken}">`;
877
+ html += `<div class="card boxy">
878
+ <div class="card-body">
879
+ <h2 class="card-title">${result.title}</h2>
880
+ <p class="card-text">${result.description}</p><br>
881
+
882
+ ${reports}
883
+ ${filter}
884
+ </div>
885
+
886
+ <div class="card-body">
887
+ <button type="submit" class="btn btn-success"><i class="fa fa-paper-plane"></i> Submit</button>
888
+ </div>
889
+
890
+ ${link}
891
+
892
+ </div></form>`;
893
+ }
894
+
895
+ return html;
896
+ }
897
+
898
+ zReport.updateQuery = async(req, res) => {
899
+ var body = req.body;
900
+ var orderby = body.orderby || "";
901
+ var wheres = body.wheres || "";
902
+ var scripts = body.scripts || "";
903
+ var id = body.id;
904
+ console.log(req.body);
905
+ var json = Util.jsonSuccess("Successfully save");
906
+ var data = {}
907
+ if(body.hasOwnProperty("orderby")) {
908
+ data.orderby = orderby;
909
+ }
910
+ if(body.hasOwnProperty("scripts")) {
911
+ data.scripts = scripts;
912
+ }
913
+ if(body.hasOwnProperty("wheres")) {
914
+ data.wheres = wheres ? JSON.stringify(wheres) : null;
915
+ }
916
+ try {
917
+ await connection.update({
918
+ table: "zreport",
919
+ data: data,
920
+ where: {
921
+ id: id
922
+ }
923
+ });
924
+ } catch (err) {
925
+ json = Util.flashError("Error " + err.toString());
926
+ }
927
+ res.json(json);
928
+ }
929
+
930
+ module.exports = zReport;