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