zet-lib 1.3.41 → 1.3.42

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/zAppRouter.js CHANGED
@@ -1,1637 +1,1637 @@
1
- const express = require('express')
2
- const router = express.Router()
3
- const csrf = require('csurf')
4
- const csrfProtection = csrf({ cookie: true })
5
- const zRoute = require('./zRoute')
6
- const connection = require('./connection')
7
- const access = require('./access')
8
- const myCache = require('./cache')
9
- const Util = require('./Util')
10
- const moment = require('moment')
11
- const fs = require('fs-extra')
12
- const moduleLib = require('./moduleLib')
13
- var env = process.env.NODE_ENV || 'development'
14
- var ecosystem = require(`./../../../ecosystem.config.js`)
15
- const config = require('dotenv').config()
16
- const debug = require('./debug')
17
- const io = require('./io')
18
- const Mail = require('./Mail')
19
- const zCache = require('./zCache')
20
- const pm2 = require('pm2')
21
- const zFunction = require('./zFunction')
22
- const qs = require('qs')
23
- const zip = require('express-zip')
24
-
25
- /*
26
- ajax Post
27
- */
28
- router.post('/zajax', zRoute.ajax)
29
- router.get('/ztypeahead/:table/:field', zRoute.typeahead)
30
- router.post('/ztypeaheadpost/:table/:field', zRoute.typeaheadpost)
31
-
32
- //password
33
- router.post('/password-change', zRoute.changePassword)
34
- router.post('/reset-password/:forgot_password', zRoute.resetPassword)
35
- //logout
36
- router.get('/logout', zRoute.logout)
37
- /*
38
- function for build form for table type
39
- */
40
- router.post('/buildform', csrfProtection, zRoute.buildForm)
41
- /*
42
- function for tab access if any
43
- */
44
- router.post('/ztab-access', csrfProtection, zRoute.tabAccess)
45
-
46
- router.get('/profile', csrfProtection, access, async (req, res) => {
47
- const MYMODELS = myCache.get('MYMODELS')
48
- let MYMODEL = MYMODELS['zuser']
49
- let result = await connection.result({ table: 'zuser', where: { id: res.locals.userId } })
50
- let role = await connection.result({ table: 'zrole', where: { id: result.role_id } })
51
- let canEditCompany = false
52
- if (result.role_id == 1 || result.role_id == 2) {
53
- canEditCompany = true
54
- }
55
- let company = await connection.result({ table: 'zcompany', where: { id: res.locals.companyId } })
56
- let verify_signed = result.verify_signed ? '/uploads/zuser/' + result.verify_signed : '/img/user.png'
57
- res.render('layouts/' + layout, {
58
- menu: { menu: 'profile' },
59
- data: result,
60
- attributeData: MYMODEL,
61
- role: role,
62
- company: company,
63
- canEditCompany: canEditCompany,
64
- verify_signed: verify_signed,
65
- routeName: 'zuser',
66
- csrfToken: req.csrfToken(),
67
- renderHead: 'index/profile_head.ejs',
68
- renderBody: 'index/profile.ejs',
69
- renderEnd: 'index/profilejs.ejs',
70
- })
71
- })
72
-
73
- router.post('/profile', access, async (req, res) => {
74
- const MYMODELS = myCache.get('MYMODELS')
75
- let MYMODEL = MYMODELS['zuser']
76
- let json = Util.jsonSuccess(LANGUAGE['data_saved'])
77
- let userId = req.session.user.id
78
- let dataPost = zRoute.post(req, res, MYMODEL, 'zuser', req.body)
79
- let data = dataPost['zuser']
80
- if (req.body.company) {
81
- await connection.update({
82
- table: 'zcompany',
83
- data: { name: req.body.company },
84
- where: {
85
- id: res.locals.companyId,
86
- },
87
- })
88
- }
89
- await connection.update({
90
- table: 'zuser',
91
- data: data,
92
- where: {
93
- id: userId,
94
- },
95
- })
96
- for (var keys in data) {
97
- req.session.user[keys] = data[keys]
98
- }
99
- req.session.sessionFlash = json
100
- if (data.image) {
101
- json.image = Util.imageProfile(data.image)
102
- }
103
- res.json(json)
104
- })
105
-
106
- router.post('/profile-sign', access, async (req, res) => {
107
- const MYMODELS = myCache.get('MYMODELS')
108
- let MYMODEL = MYMODELS['zuser']
109
- let json = Util.jsonSuccess(LANGUAGE['data_saved'])
110
- let userId = res.locals.userId
111
- let image = req.body.image
112
- let ext = req.body.ext
113
- let base64Image = image.split(';base64,').pop()
114
- let filename = `${Util.generateUnique(10)}${res.locals.userId}.${ext}`
115
- await connection.update({
116
- table: 'zuser',
117
- where: {
118
- id: res.locals.userId,
119
- },
120
- data: {
121
- verify_signed: filename,
122
- },
123
- })
124
- fs.writeFile(dirRoot + '/public/uploads/zuser/' + filename, base64Image, { encoding: 'base64' }, function (err) {})
125
- res.json(json)
126
- })
127
-
128
- //check status user login in session
129
- router.put('/zuser-session', csrfProtection, async (req, res) => {
130
- let json = Util.flashError('err')
131
- if (USER_ID > 0) {
132
- json = Util.jsonSuccess('Success')
133
- }
134
- res.json(json)
135
- })
136
-
137
- router.get('/login', csrfProtection, async (req, res) => {
138
- if (res.locals.isLogin) {
139
- return res.redirect(process.env.APP_AFTER_LOGIN)
140
- } else {
141
- await zFunction('form_login', req, res)
142
- }
143
- const isError = req.query.err == 1 ? true : false
144
- if (isError) {
145
- res.locals.error = null
146
- }
147
- res.locals.menuApp = 'login'
148
- res.render('layouts/blank', {
149
- isError: isError,
150
- csrfToken: req.csrfToken(),
151
- renderHead: 'index/logincss.ejs',
152
- renderBody: 'index/login.ejs',
153
- })
154
- })
155
-
156
- router.post('/login', csrfProtection, async (req, res) => {
157
- await zRoute.login(req.body.username, req.body.password, req, res)
158
- })
159
-
160
- router.post('/login-ajax', csrfProtection, async (req, res) => {
161
- res.json(await zRoute.loginAjax(req.body.username, req.body.password, req, res))
162
- })
163
-
164
- router.get('/signup', csrfProtection, async (req, res) => {
165
- res.locals.menuApp = 'signup'
166
- if (res.locals.isLogin) {
167
- return res.redirect(CONFIG.app.afterLogin)
168
- } else {
169
- await zFunction('form_register', req, res)
170
- }
171
- res.render('layouts/blank', {
172
- renderBody: 'index/signup.ejs',
173
- })
174
- })
175
-
176
- router.post('/signup', async (req, res) => {
177
- let body = req.body
178
- let menuData = {}
179
- let userCompany = {}
180
- let user = {}
181
- let company = {}
182
- try {
183
- let validation = registrationValidation(body)
184
- if (validation.status == 0) {
185
- res.json(Util.flashError(validation.message))
186
- return false
187
- }
188
- let dataCompany = {
189
- code: Util.generateUnique(5),
190
- name: body.company,
191
- created_at: Util.now(),
192
- updated_at: Util.now(),
193
- created_by: 1,
194
- updated_by: 1,
195
- }
196
- company = await connection.insert({
197
- table: 'zcompany',
198
- data: dataCompany,
199
- })
200
- let dataCache = zCache.myCache.has(body.username)
201
- ? zCache.get(body.username)
202
- : {
203
- fullname: '',
204
- email: '',
205
- image: '',
206
- }
207
- let dataUser = {
208
- company_id: company.id,
209
- created_at: Util.now(),
210
- updated_at: Util.now(),
211
- created_by: 1,
212
- updated_by: 1,
213
- role_id: 2,
214
- token: Util.generateUnique(28),
215
- username: body.username,
216
- email: body.username,
217
- password: Util.hash(body.password),
218
- fullname: body.fullname,
219
- image: !dataCache.image ? '' : dataCache.image,
220
- active: 1,
221
- language: '1',
222
- }
223
- user = await connection.insert({
224
- table: 'zuser',
225
- data: dataUser,
226
- })
227
-
228
- //insert user company
229
- userCompany = await connection.insert({
230
- table: 'zuser_company',
231
- data: {
232
- role_id: 2,
233
- company_id: company.id,
234
- user_id: user.id,
235
- },
236
- })
237
-
238
- let menu = await connection.result({
239
- table: 'zmenu',
240
- where: {
241
- id: 1,
242
- },
243
- })
244
- //insert menu dari user yang sudah ada menu
245
- menuData = await connection.insert({
246
- table: 'zmenu',
247
- data: {
248
- company_id: company.id,
249
- created_at: Util.now(),
250
- updated_at: Util.now(),
251
- created_by: 1,
252
- updated_by: 1,
253
- name: menu.name,
254
- json: JSON.stringify(menu.json),
255
- active: 1,
256
- },
257
- })
258
- await zRoute.loginAjax(dataUser.username, body.password, req, res)
259
- //refresh cache
260
- await zCache.renew()
261
- res.json(Util.jsonSuccess(LANGUAGE.success))
262
- } catch (e) {
263
- if (menuData && menuData.id) {
264
- await connection.delete({
265
- table: 'zmenu',
266
- where: {
267
- id: menuData.id,
268
- },
269
- })
270
- }
271
- if (userCompany && userCompany.id) {
272
- await connection.delete({
273
- table: 'zuser_company',
274
- where: {
275
- id: userCompany.id,
276
- },
277
- })
278
- }
279
- if (user && user.id) {
280
- await connection.delete({
281
- table: 'zuser',
282
- where: {
283
- id: user.id,
284
- },
285
- })
286
- }
287
- if (company && company.id) {
288
- await connection.delete({
289
- table: 'zcompany',
290
- where: {
291
- id: company.id,
292
- },
293
- })
294
- }
295
- res.json(Util.flashError(e.toString()))
296
- }
297
- })
298
-
299
- const registrationValidation = (body) => {
300
- let json = {
301
- message: 'ok',
302
- status: 0,
303
- }
304
- if (!Util.validateEmail(body.username)) {
305
- json.message = 'Email format is wrong!!'
306
- }
307
- if (body.password != body.confirm_password) {
308
- json.message = 'Password not equal to confirm password'
309
- }
310
- if (body.password.length < 6) {
311
- json.message = 'Password must be at least 6 chars'
312
- }
313
- if (body.fullname.length < 3) {
314
- json.message = 'Fullname must be at least 3 chars'
315
- }
316
- if (body.company.length < 3) {
317
- json.message = 'Company Name must be at least 3 chars'
318
- }
319
- json.status = json.message == 'ok' ? 1 : 0
320
- return json
321
- }
322
-
323
- const registrationCUSTOMValidation = (body) => {
324
- var json = {
325
- message: 'ok',
326
- status: 0,
327
- }
328
- if (!Util.validateEmail(body.username)) {
329
- json.message = 'Format email salah'
330
- }
331
- if (body.password != body.confirm_password) {
332
- json.message = 'Password dan repasword tidak cocok'
333
- }
334
- if (body.password.length < 6) {
335
- json.message = 'Password kurang dari 6 '
336
- }
337
- if (body.fullname.length < 6) {
338
- json.message = 'Nama lengkap kurang lengkap'
339
- }
340
- if (body.phone.length < 6) {
341
- json.message = 'No telp kurang lengkap'
342
- }
343
- json.status = json.message == 'ok' ? 1 : 0
344
- return json
345
- }
346
-
347
- router.post('/signup-custom', async (req, res) => {
348
- var body = req.body
349
- try {
350
- var validation = registrationCUSTOMValidation(body)
351
- if (validation.status == 0) {
352
- res.json(Util.flashError(validation.message))
353
- return false
354
- }
355
-
356
- var dataUser = {
357
- company_id: 1,
358
- created_at: Util.now(),
359
- updated_at: Util.now(),
360
- created_by: 1,
361
- updated_by: 1,
362
- role_id: 4,
363
- token: Util.generateUnique(28),
364
- username: body.username,
365
- email: body.username,
366
- password: Util.hash(body.password),
367
- fullname: body.fullname,
368
- phone: body.phone,
369
- verify_signed: 'lizhn63iqA8CVDQeOw8.png',
370
- active: 0,
371
- language: '2',
372
- }
373
- var user = await connection.insert({
374
- table: 'zuser',
375
- data: dataUser,
376
- })
377
- var userCompany = await connection.insert({
378
- table: 'zuser_company',
379
- data: {
380
- role_id: 4,
381
- company_id: 1,
382
- user_id: user.id,
383
- },
384
- })
385
- /* await zRoute.loginAjax(dataUser.username, body.password, req, res);
386
- //refresh cache
387
- await zCache.renew();*/
388
-
389
- res.json(Util.jsonSuccess('Successfuly'))
390
- } catch (e) {
391
- res.json(Util.flashError(e.toString()))
392
- }
393
- })
394
-
395
- router.post('/gridprint', async (req, res) => {
396
- let html = ''
397
- let id = req.body.id
398
- let table = req.body.table
399
- if (id) {
400
- let results = await connection.results({
401
- table: 'zapprovals',
402
- where: {
403
- id_data: id,
404
- table: table,
405
- },
406
- })
407
- if (results.length) {
408
- let result = results[0]
409
- if (result.status == 3 || result.status == 4) {
410
- html += `<button class="btn btn-sm btn-info gridprint" data-token="${result.token}"><span class="fa fa-print"></span></button> `
411
- }
412
- }
413
- }
414
- res.json(html)
415
- })
416
-
417
- router.get('/failed', async function (req, res) {
418
- let template = 'fronts'
419
- res.render('layouts/' + template, {
420
- menu: 'failed',
421
- renderBody: 'index/failed.ejs',
422
- Util: Util,
423
- })
424
- })
425
-
426
- router.get('/forgot', csrfProtection, async (req, res) => {
427
- const MYMODELS = myCache.get('MYMODELS')
428
- let MYMODEL = MYMODELS['zuser']
429
- if (res.locals.isLogin) {
430
- return res.redirect('/dashboard')
431
- }
432
- let script = `submitForm('forgot-form',"","",function(data){if (data.status == 1) {
433
- toastrForm(data);spinner.hide();
434
- setTimeout(function () {location.href='/';},6000);
435
- }});`
436
- await moduleLib.custom(req, res, script)
437
-
438
- res.render('layouts/fronts', {
439
- csrfToken: req.csrfToken(),
440
- attributeData: MYMODEL,
441
- routeName: 'zuser',
442
- data: MYMODEL.datas,
443
- renderBody: 'index/forgot.ejs',
444
- })
445
- })
446
-
447
- router.post('/forgot', csrfProtection, async (req, res) => {
448
- let json = Util.jsonError('email', 'Email not found in our database')
449
- let routeName = 'user'
450
- const MYMODELS = myCache.get('MYMODELS')
451
- let MYMODEL = MYMODELS['zuser']
452
- let data = zRoute.post(req, res, MYMODEL)['zuser']
453
- var port = ecosystem.apps[0].env.PORT
454
- var url = env == 'production' ? process.env.APP_URL : 'http://localhost:' + port
455
- let email = data.email || ' '
456
- email = email.trim()
457
- if (email.length > 5) {
458
- let rows = await connection.results({
459
- table: 'zuser',
460
- where: {
461
- email: email,
462
- },
463
- })
464
- if (rows.length > 0) {
465
- let post = {
466
- forgot_password: Util.generateUnique(23),
467
- }
468
- await connection.update({
469
- table: 'zuser',
470
- where: {
471
- id: rows[0].id,
472
- },
473
- data: post,
474
- })
475
- let options = {
476
- to: email,
477
- subject: 'Forgot Password',
478
- }
479
- let datas = {
480
- config: {
481
- app: {
482
- url: url,
483
- },
484
- },
485
- url: url,
486
- link: url + '/reset-password/' + post.forgot_password,
487
- }
488
- Mail.forgotPassword(datas, options)
489
- json = Util.jsonSuccess('Please check your email to reset ')
490
- }
491
- }
492
-
493
- res.json(json)
494
- })
495
-
496
- router.get('/reset-password/:forgot_password', csrfProtection, async (req, res) => {
497
- let forgot_password = req.params.forgot_password || ''
498
- let activated = false
499
- if (forgot_password != '') {
500
- let results = await connection.results({
501
- table: 'zuser',
502
- where: {
503
- forgot_password: forgot_password,
504
- },
505
- })
506
- if (results.length > 0) {
507
- activated = true
508
- }
509
- }
510
- var script = `submitForm('form-group','','',function(data){
511
- if(data.status==1){
512
- location.href = '/login'
513
- }
514
- });`
515
- await moduleLib.custom(req, res, script)
516
- res.render('layouts/fronts', {
517
- activated: activated,
518
- csrfToken: req.csrfToken(),
519
- forgot_password: forgot_password,
520
- renderBody: 'index/reset-password.ejs',
521
- })
522
- })
523
-
524
- router.get('/no-access', async (req, res) => {
525
- let myview = 'fronts'
526
- if (req.session.user) {
527
- myview = 'main'
528
- }
529
- res.render('layouts/' + myview, {
530
- data: { table: 'error' },
531
- menu: 'error',
532
- renderBody: 'index/no-access.ejs',
533
- })
534
- })
535
-
536
- router.get('/page_not_found', async (req, res) => {
537
- res.render('layouts/page_not_found', {
538
- data: { table: 'error' },
539
- menu: 'error',
540
- //renderBody: "index/no-found.ejs",
541
- })
542
- })
543
-
544
- // for change company session
545
- router.get('/session/:id', access, async (req, res) => {
546
- let companies = res.locals.zcompanies
547
- let user = await connection.result({
548
- table: 'zuser',
549
- where: {
550
- id: res.locals.userId,
551
- },
552
- })
553
- for (let i = 0; i < companies.length; i++) {
554
- if (companies[i].id == req.params.id) {
555
- user.company_id = req.params.id
556
- await zRoute.handleSession(req, user)
557
- var post = {
558
- company_id: companies[i].id,
559
- role_id: companies[i].role_id,
560
- }
561
- await connection.update({
562
- table: 'zuser',
563
- data: post,
564
- where: {
565
- id: res.locals.userId,
566
- },
567
- })
568
- }
569
- }
570
- var backURL = req.header('Referer') || '/'
571
- // do your thang
572
- res.redirect(backURL)
573
- })
574
-
575
- //RESTART
576
- router.get('/restart', access, async (req, res) => {
577
- var room = res.locals.user.token
578
- if (env == 'production') {
579
- pm2.connect(function (err) {
580
- if (err) {
581
- io.to(room).emit('error', err.toString())
582
- }
583
- pm2.restart(process.env.PM2_NAME, (err, proc) => {
584
- io.to(room).emit('message', 'Restart done')
585
- })
586
- })
587
- } else {
588
- io.to(room).emit('message', 'Restart done')
589
- }
590
- res.json('ok')
591
- })
592
-
593
- //ERROR UI
594
- router.get('/error', async (err, req, res, next) => {
595
- res.locals.message = err.message
596
- res.locals.error = req.app.get('env') === 'development' ? err : err
597
- // render the error page
598
- res.status(err.status || 500)
599
- debug(req, res, err)
600
- res.render('layouts/' + layout, {
601
- renderBody: 'index/error.ejs',
602
- })
603
- })
604
-
605
- //APPROVAL SYSTEMS
606
- router.post('/zzapproval', async (req, res) => {
607
- let json = Util.jsonSuccess(LANGUAGE['data_saved'])
608
- const MYMODELS = myCache.get('MYMODELS')
609
- let MYMODEL = MYMODELS['zapprovals']
610
- const port = ecosystem.apps[0].env.PORT
611
- let users = Util.arrayToObject(await connection.results({ table: 'zuser' }), 'id')
612
- try {
613
- let userId = res.locals.userId
614
- let data = zRoute.post(req, res, MYMODEL)[MYMODEL.table]
615
- let validator = zRoute.validator(data, MYMODEL)
616
- if (validator.status == 0) return res.json(validator.message)
617
- if (data.status == 2) {
618
- if (!data.approvers) {
619
- return res.json(Util.flashError('Approvers empty'))
620
- }
621
- if (data.title == '') {
622
- return res.json(Util.flashError('Title empty', 'title'))
623
- }
624
- }
625
- //update template for newst
626
- var row = await connection.result({ table: 'zfields', where: { table: data.table } })
627
- var jsonApproval = row.approval_json || {}
628
- data.template = jsonApproval.content || {}
629
- var approvers = []
630
- if (typeof data.approvers == 'string') {
631
- data.approvers = JSON.parse(data.approvers)
632
- }
633
- approvers = data.approvers || []
634
- if (approvers.length > 1) {
635
- approvers = approvers.filter(Util.arrayUnique)
636
- }
637
- data.approvers = JSON.stringify(approvers)
638
- let knowings = []
639
- if (typeof data.knowings == 'string') {
640
- data.knowings = JSON.parse(data.knowings)
641
- }
642
- knowings = data.knowings || []
643
- if (knowings.length > 1) {
644
- knowings = knowings.filter(Util.arrayUnique)
645
- }
646
- data.knowings = JSON.stringify(knowings)
647
- let allUsers = [...approvers, ...knowings]
648
-
649
- let statusApprovers = approvers.reduce((result, item) => {
650
- return [...result, { user: item, status: 2 }]
651
- }, [])
652
- data.approved_stats = JSON.stringify({
653
- stats: `0/${approvers.length}`,
654
- status: statusApprovers,
655
- })
656
- let knowingStatus = knowings.reduce((result, item) => {
657
- return [...result, { user: item, status: 7 }]
658
- }, [])
659
-
660
- data.knowing_stats = JSON.stringify({
661
- stats: `0/${knowings.length}`,
662
- status: knowingStatus,
663
- })
664
- let results = await connection.results({
665
- table: MYMODEL.table,
666
- where: { table: data.table, id_data: data.id_data },
667
- })
668
- if (results.length) {
669
- let query = await zRoute.updateSQL(req, res, MYMODEL.table, data, { id: results[0].id })
670
- data.id = results[0].id
671
- } else {
672
- var query = await zRoute.insertSQL(req, res, MYMODEL.table, data)
673
- data.id = query.id
674
- }
675
- if (data.status == 2) {
676
- //send activity
677
- /* await zRoute.insertSQL(req, res, "zactivity", {
678
- user_id: res.locals.userId,
679
- table: MYMODEL.table,
680
- id_data: data.id,
681
- status: data.status,
682
- status_label: MYMODEL.widgets.status.fields[data.status],
683
- title: MYMODEL.widgets.status.fields[data.status],
684
- description: users[res.locals.userId].fname + " " +users[res.locals.userId].lname ,
685
- data: JSON.stringify(data)
686
- });*/
687
- //if serial
688
- if (data.type == 2) {
689
- approvers = [approvers[0]]
690
- }
691
- let sectionsAprrovers = approvers.reduce((temp, item, index) => {
692
- return [
693
- ...temp,
694
- {
695
- title: users[item].fullname,
696
- description: '@' + users[item].fullname,
697
- rowId: 'row' + index,
698
- },
699
- ]
700
- }, [])
701
- let sectionsKnowings = knowings.reduce((temp, item, index) => {
702
- return [
703
- ...temp,
704
- {
705
- title: users[item].fullname,
706
- description: '@' + users[item].fullname,
707
- rowId: 'row' + index,
708
- },
709
- ]
710
- }, [])
711
- let sections = []
712
- sections.push({ title: 'Approvers', rows: sectionsAprrovers })
713
- if (sectionsKnowings) {
714
- sections.push({ title: 'Knowings', rows: sectionsKnowings })
715
- }
716
- approvers.forEach(async (item, num) => {
717
- let post = {
718
- title_id: data.id,
719
- user_id: item,
720
- status: 7,
721
- type: 1,
722
- token: Util.uuid(),
723
- }
724
- await zRoute.insertSQL(req, res, 'zapprovals_details', post)
725
- let link = env == 'production' ? process.env.APP_URL + '/za/' + post.token : `http://localhost:${port}/za/${post.token}`
726
- let email = users[post.user_id].email
727
-
728
- post.subject = `Need Approve ${data.title}`
729
- post.buttonTitle = `Approve Now`
730
- post.title = `NEED APPROVE DOCUMENT`
731
- post.link = link
732
- post.url = CONFIG.app.url
733
- post.description = `Hai ${users[post.user_id].fullname} <br>
734
-
735
-
736
- We have some document for you.<br>
737
- Please click the link above to view the document.`
738
-
739
- post.note = `If you click the link, it's will be automatically acknowledged`
740
- Mail.gmail(req, res, post, email)
741
-
742
- //send to whatsapp
743
- let phone = Util.phoneWA(users[post.user_id].phone)
744
- if (phone) {
745
- var textWa = ''
746
- textWa += `*NEED APPROVE DOCUMENT* \r\n_${data.title}_\r\nHai ${users[post.user_id].fullname} \r\n \r\n`
747
- textWa += 'We have some document for you.\r\n'
748
- textWa += `Please click the link above to view the document.\r\n${link}`
749
-
750
- /* await whatsapp({
751
- to: phone,
752
- text: textWa,
753
- sections: JSON.stringify(sections),
754
- buttonText: "Click me for details"
755
- });*/
756
- }
757
-
758
- //send notification
759
- /* await zRoute.insertSQL(req, res, "znotification", {
760
- user_id: item,
761
- table: MYMODEL.table,
762
- id_data: data.id,
763
- status: 1,
764
- link: "/za/" + post.token,
765
- status_label: MYMODEL.widgets.status.fields[1],
766
- title: `Need Approve`,
767
- description: data.title,
768
- token: post.token
769
- });*/
770
-
771
- //send todolist
772
- /* await zRoute.insertSQL(req, res, "ztodolist", {
773
- user_id: item,
774
- table: MYMODEL.table,
775
- id_data: data.id,
776
- status: 1,
777
- link: "/za/" + post.token,
778
- status_label: MYMODEL.widgets.status.fields[1],
779
- title: `Need Approve`,
780
- description: data.title,
781
- users: JSON.stringify(allUsers)
782
- });*/
783
-
784
- //send toastr using socket.io
785
- io.to(users[item].token).emit('message', 'Need Approve ' + data.title)
786
- })
787
-
788
- knowings.map(async (item) => {
789
- let post = {
790
- title_id: data.id,
791
- user_id: item,
792
- status: 7,
793
- type: 2,
794
- token: Util.uuid(),
795
- }
796
- await zRoute.insertSQL(req, res, 'zapprovals_details', post)
797
- let link = env == 'production' ? process.env.APP_URL + '/za/' + post.token : `http://localhost:${port}/za/${post.token}`
798
- let email = users[post.user_id].email
799
-
800
- post.subject = `Need acknowledge ${data.title}`
801
- post.buttonTitle = `Acknowledge Now`
802
- post.title = `NEED ACKNOWLEDGE DOCUMENT`
803
-
804
- post.link = link
805
- post.url = CONFIG.app.url
806
- post.description = `Hai ${users[post.user_id].fullname} <br>
807
-
808
-
809
- We have some document for you.<br>
810
- Please click the link above to view the document.`
811
-
812
- post.note = `If you click the link, it's will be automatically acknowledged`
813
- Mail.gmail(req, res, post, email)
814
-
815
- //send to whatsapp
816
- let phone = Util.phoneWA(users[post.user_id].phone)
817
- if (phone) {
818
- var textWa = ''
819
- textWa += `*NEED ACKNOWLEDGE DOCUMENT* \r\n_${data.title}_\r\nHai ${users[post.user_id].fullname} \r\n \r\n`
820
- textWa += 'We have some document for you.\r\n'
821
- textWa += `Please click the link above to view the document.\r\n${link}`
822
- /* await whatsapp({
823
- to: phone,
824
- text: textWa,
825
- sections: JSON.stringify(sections),
826
- buttonText: "Click me for details"
827
- });*/
828
- }
829
-
830
- //send activity
831
- /* await cRoute.insertSQL(req, res, "zactivity",{
832
- user_id:item,
833
- table:MYMODEL.table,
834
- id_data:data.id,
835
- status:7,
836
- status_label: MYMODEL.widgets.status.fields[7],
837
- title : MYMODEL.widgets.status.fields[7],
838
- description: data.title,
839
- data:JSON.stringify(data)
840
- });*/
841
-
842
- //send notification
843
- /* await zRoute.insertSQL(req, res, "znotification", {
844
- user_id: item,
845
- table: MYMODEL.table,
846
- id_data: data.id,
847
- status: 1,
848
- link: "/za/" + post.token,
849
- status_label: MYMODEL.widgets.status.fields[1],
850
- title: `Need Acknowledge`,
851
- description: data.title,
852
- token: post.token
853
- });
854
-
855
- //send todolist
856
- await zRoute.insertSQL(req, res, "ztodolist", {
857
- user_id: item,
858
- table: MYMODEL.table,
859
- id_data: data.id,
860
- status: 1,
861
- link: "/za/" + post.token,
862
- status_label: MYMODEL.widgets.status.fields[1],
863
- title: `Need Acknowledge`,
864
- description: data.title,
865
- users: JSON.stringify(allUsers)
866
- });*/
867
- io.to(users[item].token).emit('message', 'Need Acknowledge ' + data.title)
868
- })
869
- }
870
- } catch (err) {
871
- if (Object.prototype.hasOwnProperty.call(err, 'sqlMessage')) {
872
- json = Util.flashError(err.sqlMessage)
873
- } else {
874
- json = Util.flashError(err.toString())
875
- }
876
- debug(req, res, err)
877
- }
878
- res.json(json)
879
- })
880
-
881
- router.get('/za/:token', csrfProtection, async (req, res) => {
882
- let token = req.params.token
883
- let data = {},
884
- data2 = {}
885
- let template = ''
886
- let result
887
- let isClosed = false
888
- let footers = ''
889
- let details = []
890
- let routeName = env == 'production' ? process.env.APP_URL : `http://localhost:${port}`
891
- let statusLabel = ''
892
- let knowings = []
893
- const MYMODELS = myCache.get('MYMODELS')
894
- let MYMODEL = MYMODELS['zapprovals']
895
- let users = Util.arrayToObject(await connection.results({ table: 'zuser' }), 'id')
896
- try {
897
- result = await connection.result({
898
- select: '*, zapprovals.id as ide, zapprovals_details.token as usertoken, zapprovals.status as statuse, zapprovals_details.status as mystatus, zapprovals_details.type as user_type, zapprovals_details.updated_at',
899
- table: 'zapprovals_details',
900
- joins: ['LEFT JOIN zapprovals ON (zapprovals_details.title_id = zapprovals.id)', 'LEFT JOIN employee ON (zapprovals_details.user_id = employee.id)'],
901
- where: { 'zapprovals_details.token': token },
902
- })
903
- let approvers = result.approvers
904
- knowings = result.knowings ? result.knowings : []
905
-
906
- statusLabel = MYMODEL.widgets.status.fields[result.statuse]
907
- routeName = routeName + '/' + result.table + '/view/' + result.id_data
908
- if (result.statuse == 3 || result.statuse == 4 || result.mystatus == 3 || result.mystatus == 4) {
909
- isClosed = true
910
- }
911
- details = await connection.results({ table: 'zapprovals_details', where: { title_id: result.ide } })
912
- if (result.user_type == 2) {
913
- isClosed = true
914
- var post = {
915
- status: 6, //read
916
- }
917
- await connection.update({ table: 'zapprovals_details', data: post, where: { token: token } })
918
-
919
- //set stats
920
- //{"stats":"0/1","status":[{"user":"12","status":0}]}
921
- let knowing_stats = result.knowing_stats || {}
922
- let statuses = knowing_stats.status
923
- let stats = knowing_stats.stats
924
- let explode = stats.split('/')
925
- let count = parseInt(explode[0])
926
- let newStatus = []
927
- knowings = result.knowings || []
928
- statuses.map((item) => {
929
- if (item.user == result.user_id && result.mystatus != 3) {
930
- item.status = 3
931
- if (count < knowings.length) {
932
- count = count + 1
933
- }
934
- newStatus.push(item)
935
- } else {
936
- newStatus.push(item)
937
- }
938
- })
939
- if (result.mystatus != 3) {
940
- post = {
941
- knowing_stats: JSON.stringify({ stats: count + '/' + explode[1], status: newStatus }),
942
- }
943
- await connection.update({ table: 'zapprovals', data: post, where: { id: result.ide } })
944
- //var users = await zRoute.getUsers();
945
- var message = users[result.user_id].fullname + ' has readed document ' + result.title
946
- details.forEach(function (item) {
947
- io.to(users[item.user_id].token).emit('message', message)
948
- })
949
- }
950
- }
951
-
952
- MYMODEL = MYMODELS[result.table]
953
- let row = await connection.result({ table: MYMODEL.table, where: { id: result.id_data } })
954
- data = await zRoute.viewTable(req, res, MYMODEL, row)
955
- template = result.template
956
- for (var key in data) {
957
- template = Util.replaceAll(template, '{{' + key + '}}', data[key])
958
- }
959
-
960
- footers = await zRoute.approversFooter(details)
961
-
962
- //send activity
963
- if (result.mystatus == 7) {
964
- MYMODEL = MYMODELS['zapprovals']
965
- /* await connection.insert({
966
- table: "zactivity",
967
- data: {
968
- company_id: result.company_id,
969
- created_at: Util.now(),
970
- created_by: result.user_id,
971
- updated_by: result.user_id,
972
- user_id: result.user_id,
973
- table: MYMODEL.table,
974
- id_data: result.ide,
975
- status: 6,
976
- status_label: MYMODEL.widgets.status.fields[6],
977
- title: `${MYMODEL.widgets.status.fields[6]}`,
978
- description: `Ok `,
979
- data: JSON.stringify(data)
980
- }
981
- });
982
- */
983
-
984
- await connection.update({
985
- table: 'zapprovals_details',
986
- where: {
987
- token: token,
988
- },
989
- data: { status: 6 },
990
- })
991
- }
992
- } catch (err) {
993
- debug(req, res, err)
994
- res.send('Not Found')
995
- }
996
- res.render('layouts/blank', {
997
- routeName: routeName,
998
- Util: Util,
999
- data: data,
1000
- statusLabel: statusLabel,
1001
- template: template,
1002
- result: result,
1003
- statusLabel: statusLabel,
1004
- isClosed: isClosed,
1005
- footers: footers,
1006
- csrfToken: req.csrfToken(),
1007
- token: result.usertoken,
1008
- tokendoc: token,
1009
- renderHead: 'index/zacss.ejs',
1010
- renderBody: 'index/za.ejs',
1011
- renderEnd: 'index/zajs.ejs',
1012
- })
1013
- })
1014
-
1015
- router.post('/za/:token', csrfProtection, async (req, res) => {
1016
- let token = req.params.token
1017
- let comments = req.body.comments
1018
- let status = req.body.status
1019
- let json = Util.jsonSuccess('Success')
1020
- let data = {},
1021
- data2 = {}
1022
- let template = ''
1023
- let approvers = [],
1024
- knowings = []
1025
- let users = Util.arrayToObject(await connection.results({ table: 'zuser' }), 'id')
1026
- let employee_user = users
1027
- const MYMODELS = myCache.get('MYMODELS')
1028
- let MYMODEL = MYMODELS['zapprovals']
1029
- let post = {}
1030
- try {
1031
- var results = await connection.results({
1032
- select: '*,zapprovals_details.status as approvers_status, zapprovals.created_by as submiter, zapprovals.type as typee, zapprovals.status as statuse, zapprovals_details.id as detaild_id, zapprovals.id as ide, zapprovals.approvers as approvers ',
1033
- table: 'zapprovals_details',
1034
- joins: ['LEFT JOIN zapprovals ON (zapprovals_details.title_id = zapprovals.id)'],
1035
- where: { 'zapprovals_details.token': token },
1036
- })
1037
- if (!results.length) {
1038
- return res.json(Util.jsonError('Data not found!'))
1039
- }
1040
-
1041
- var result = results[0]
1042
- if (result.approvers_status == 3 || result.approvers_status == 4) {
1043
- return res.json(Util.jsonError('You have submited.'))
1044
- }
1045
- post = {
1046
- status: status,
1047
- comments: comments,
1048
- updated_at: Util.now(),
1049
- }
1050
- let update = await connection.update({ table: 'zapprovals_details', data: post, where: { id: result.detaild_id } })
1051
- let details = await connection.results({ table: 'zapprovals_details', where: { title_id: result.ide } })
1052
- approvers = result.approvers
1053
- knowings = result.knowings || []
1054
- let stats = 0
1055
- let status_stats = []
1056
- let approversSigned = []
1057
- //{"stats":"0/2","status":[{"user":"12","status":2},{"user":"35","status":2}]}
1058
- let last_status
1059
- details.map((item) => {
1060
- if (item.type == 1) {
1061
- if (item.status == 4 || item.status == 3) {
1062
- stats++
1063
- approversSigned.push(item.user_id + '')
1064
- }
1065
- status_stats.push({
1066
- user: item.user_id,
1067
- status: item.status,
1068
- })
1069
- last_status = item.status
1070
- }
1071
- })
1072
-
1073
- post.approved_stats = JSON.stringify({
1074
- stats: stats + '/' + approvers.length,
1075
- status: status_stats,
1076
- })
1077
- if (stats == approvers.length) {
1078
- post.status = last_status
1079
- } else {
1080
- post.status = 5
1081
- }
1082
- if (status == 4) {
1083
- post.status = 4
1084
- }
1085
- await connection.update({ table: 'zapprovals', data: post, where: { id: result.ide } })
1086
-
1087
- //send activity
1088
- await connection.insert({
1089
- table: 'zactivity',
1090
- data: {
1091
- company_id: result.company_id,
1092
- created_at: Util.now(),
1093
- created_by: result.user_id,
1094
- updated_by: result.user_id,
1095
- user_id: result.user_id,
1096
- table: MYMODEL.table,
1097
- id_data: result.ide,
1098
- status: status,
1099
- status_label: MYMODEL.widgets.status.fields[status],
1100
- title: MYMODEL.widgets.status.fields[status],
1101
- description: comments,
1102
- data: JSON.stringify(post),
1103
- },
1104
- })
1105
-
1106
- //send notification
1107
- if (status == 3 || status == 4) {
1108
- let message = `Document ${result.title} has ${MYMODEL.widgets.status[status]};`
1109
- approvers.forEach(function (item) {
1110
- io.to(users[item].token).emit('message', message)
1111
- })
1112
- if (status == 3) {
1113
- // if type is serial is step by step
1114
- //send notification and generate email
1115
- //approversSigned
1116
- if (result.typee == 2) {
1117
- //get approvers has already sign
1118
-
1119
- approversSigned.push(result.user_id)
1120
- var newApprovers = approvers.filter((item) => {
1121
- return !approversSigned.includes(item)
1122
- })
1123
- var item = newApprovers.length ? newApprovers[0] : ''
1124
- if (item) {
1125
- post = {
1126
- title_id: result.ide,
1127
- user_id: employee_user[item].user_id,
1128
- status: 7,
1129
- type: 1,
1130
- comments: comments,
1131
- token: Util.uuid(),
1132
- company_id: result.company_id,
1133
- created_at: Util.now(),
1134
- updated_at: Util.now(),
1135
- created_by: employee_user[item].user_id,
1136
- updated_by: employee_user[item].user_id,
1137
- }
1138
- await connection.insert({
1139
- table: 'zapprovals_details',
1140
- data: post,
1141
- })
1142
- let link = CONFIG.app.url + '/za/' + post.token
1143
- let email = users[item].username
1144
-
1145
- post.subject = `Need Approve ${result.title}`
1146
- post.buttonTitle = `Approve Now`
1147
- post.title = `NEED APPROVE DOCUMENT`
1148
- post.link = link
1149
- post.url = CONFIG.app.url
1150
- post.description = `Hai ${users[item].fullname} <br>
1151
-
1152
-
1153
- We have some document for you.<br>
1154
- Please click the link above to view the document.`
1155
-
1156
- post.note = `If you click the link, it's will be automatically acknowledged`
1157
- Mail.gmail(req, res, post, email)
1158
-
1159
- //send to whatsapp
1160
- let sectionsAprrovers = approvers.reduce((temp, item, index) => {
1161
- return [
1162
- ...temp,
1163
- {
1164
- title: users[item].fullname + ' ' + users[item].position,
1165
- description: '@' + users[item].fullname + ' ' + users[item].position,
1166
- rowId: 'roe' + index,
1167
- },
1168
- ]
1169
- }, [])
1170
- let sectionsKnowings = knowings.reduce((temp, item, index) => {
1171
- return [
1172
- ...temp,
1173
- {
1174
- title: users[item].fullname + ' ' + users[item].position,
1175
- description: '@' + users[item].fullname + ' ' + users[item].position,
1176
- rowId: 'roe' + index,
1177
- },
1178
- ]
1179
- }, [])
1180
- let sections = []
1181
- sections.push({ title: 'Approvers', rows: sectionsAprrovers })
1182
- if (sectionsKnowings) {
1183
- sections.push({ title: 'Knowings', rows: sectionsKnowings })
1184
- }
1185
- //send notification
1186
- await connection.insert({
1187
- table: 'znotification',
1188
- data: {
1189
- company_id: result.company_id,
1190
- created_at: Util.now(),
1191
- created_by: employee_user[result.user_id].user_id,
1192
- updated_by: employee_user[result.user_id].user_id,
1193
- user_id: item,
1194
- table: MYMODEL.table,
1195
- id_data: data.id,
1196
- status: 1,
1197
- link: '/za/' + post.token,
1198
- status_label: 'Unread',
1199
- title: `Need Approve`,
1200
- description: data.title,
1201
- token: post.token,
1202
- },
1203
- })
1204
-
1205
- //send todolist
1206
- await connection.insert({
1207
- table: 'ztodolist',
1208
- data: {
1209
- company_id: result.company_id,
1210
- created_at: Util.now(),
1211
- created_by: employee_user[result.user_id].user_id,
1212
- updated_by: employee_user[result.user_id].user_id,
1213
- user_id: item,
1214
- table: MYMODEL.table,
1215
- id_data: result.ide,
1216
- status: 1,
1217
- link: '/za/' + post.token,
1218
- status_label: 'Unread',
1219
- title: `Need Approve`,
1220
- description: result.title,
1221
- users: JSON.stringify(approvers),
1222
- },
1223
- })
1224
-
1225
- //send toastr using socket.io
1226
- io.to(users[item].token).emit('message', 'Need Approve for document : ' + result.title)
1227
- }
1228
- }
1229
- }
1230
- }
1231
- } catch (err) {
1232
- debug(req, res, err)
1233
- json = Util.flashError(err.toString())
1234
- }
1235
-
1236
- res.json(json)
1237
- })
1238
-
1239
- router.get('/zdownload/zgenerator/:table', async (req, res) => {
1240
- var table = req.params.table
1241
- var path = `${dirRoot}/public/uploads/zgenerator/${table}.json`
1242
- res.download(path, function (err) {
1243
- if (err) {
1244
- //console.log(err);
1245
- }
1246
- })
1247
- })
1248
-
1249
- router.post('/zlock-unlock/:table', async (req, res) => {
1250
- let json = Util.jsonSuccess('Success')
1251
- let table = req.params.table
1252
- let cacheRoles = myCache.get('ROLES')
1253
- let roleId = res.locals.roleId
1254
- let myrole = cacheRoles[roleId]
1255
- let tableRole = myrole.params[table] || []
1256
- let hasAccess = tableRole.includes('lock') ? true : false
1257
- if (hasAccess) {
1258
- let type = req.body.type
1259
- let datas = req.body.datas || []
1260
- if (datas.length > 0) {
1261
- for (const data of datas) {
1262
- let id = data.name.replace('ck[', '').replace(']', '')
1263
- await connection.update({
1264
- table: table,
1265
- data: {
1266
- lock: type,
1267
- },
1268
- where: {
1269
- id: id,
1270
- },
1271
- })
1272
- }
1273
- } else {
1274
- json = Util.flashError('No Data')
1275
- }
1276
- } else {
1277
- json = Util.flashError('No Access')
1278
- }
1279
-
1280
- res.json(json)
1281
- })
1282
-
1283
- router.post('/zdeleted-selected/:table', async (req, res) => {
1284
- let json = Util.jsonSuccess('Success')
1285
- let table = req.params.table
1286
- let cacheRoles = myCache.get('ROLES')
1287
- let roleId = res.locals.roleId
1288
- let myrole = cacheRoles[roleId]
1289
- let tableRole = myrole.params[table] || []
1290
- let hasAccess = tableRole.includes('lock') ? true : false
1291
- if (hasAccess) {
1292
- let type = req.body.type
1293
- let datas = req.body.datas || []
1294
- if (datas.length > 0) {
1295
- for (const data of datas) {
1296
- let id = data.name.replace('ck[', '').replace(']', '')
1297
- try {
1298
- await connection.delete({
1299
- table: table,
1300
- where: {
1301
- id: id,
1302
- },
1303
- })
1304
- } catch (e) {
1305
- io.emit('error', e + '')
1306
- }
1307
- }
1308
- } else {
1309
- json = Util.flashError('No Data')
1310
- }
1311
- } else {
1312
- json = Util.flashError('No Access')
1313
- }
1314
-
1315
- res.json(json)
1316
- })
1317
-
1318
- router.post('/zapproval-update/:table', async (req, res) => {
1319
- let json = Util.jsonSuccess('Success')
1320
- let table = req.params.table
1321
- let value = req.body.value
1322
- let text = req.body.text
1323
- let datas = req.body.datas || []
1324
- let roles = myCache.get('ROLES')[res.locals.roleId] || {}
1325
- let myaccess = roles.approvals[table]
1326
- let hasAccess = myaccess.hasOwnProperty(value) ? true : false
1327
- let canUpdate = true
1328
- let dataStatus = []
1329
- if (text == '') {
1330
- res.json(Util.flashError('please type a message'))
1331
- return false
1332
- }
1333
- if (hasAccess) {
1334
- if (datas.length > 0) {
1335
- for (const data of datas) {
1336
- let id = data.name.replace('ck[', '').replace(']', '')
1337
- let result = await connection.result({
1338
- select: 'id,approval_status,approval_history',
1339
- table: table,
1340
- where: {
1341
- id: id,
1342
- },
1343
- })
1344
- let approval_status = result.approval_status || null
1345
- let approval_history = result.approval_history || []
1346
- if (approval_status == null) {
1347
- canUpdate = true
1348
- } else if (approval_status == 22) {
1349
- canUpdate = true
1350
- } else {
1351
- if (+value > +approval_status) {
1352
- canUpdate = true
1353
- } else {
1354
- canUpdate = false
1355
- }
1356
- }
1357
- if (canUpdate) {
1358
- approval_history.push({
1359
- status: value,
1360
- user_id: res.locals.userId,
1361
- created_at: Util.now(),
1362
- text: text,
1363
- })
1364
- let mydata = {
1365
- approval_status: value,
1366
- approval_history: Util.array_to_jsonb(approval_history),
1367
- }
1368
- if (+value > 1 && +value < 22) {
1369
- mydata.lock = 1
1370
- }
1371
- if (+value === 22) {
1372
- mydata.lock = 0
1373
- }
1374
- await connection.update({
1375
- table: table,
1376
- where: {
1377
- id: id,
1378
- },
1379
- data: mydata,
1380
- })
1381
- } else {
1382
- dataStatus.push(`${id} -> Status has been delivered`)
1383
- }
1384
- }
1385
- } else {
1386
- json = Util.flashError('No Data')
1387
- }
1388
- } else {
1389
- json = Util.flashError('No Access')
1390
- }
1391
- json.dataStatus = dataStatus
1392
- res.json(json)
1393
- })
1394
-
1395
- router.get('/addlock-fields', async (req, res) => {
1396
- let tables = await connection.query(connection.showTables)
1397
- for (const table of tables) {
1398
- let tablename = table.tablename
1399
- let sql = `ALTER TABLE ${tablename} ADD COLUMN "lock" smallint DEFAULT 0 `
1400
- try {
1401
- await connection.query(sql)
1402
- } catch (e) {
1403
- console.log(e)
1404
- }
1405
- }
1406
- res.send(tables)
1407
- })
1408
-
1409
- router.get('/addlock-models', async (req, res) => {
1410
- let text = ''
1411
- let results = await connection.results({
1412
- table: 'zfields',
1413
- })
1414
- for (const result of results) {
1415
- let labels = result.labels
1416
- let arr = Object.keys(labels)
1417
- if (!Util.in_array('lock', arr)) {
1418
- text += result.id + ' tidak ada'
1419
- labels.lock = 'Lock/Unlock'
1420
- try {
1421
- await connection.update({
1422
- table: 'zfields',
1423
- data: {
1424
- labels: JSON.stringify(labels),
1425
- },
1426
- where: {
1427
- id: result.id,
1428
- },
1429
- })
1430
- } catch (err) {
1431
- console.log(err)
1432
- }
1433
- }
1434
- }
1435
-
1436
- res.send(text)
1437
- })
1438
-
1439
- router.get('/addapprovals-data', async (req, res) => {
1440
- let tables = await connection.query(connection.showTables)
1441
- for (const table of tables) {
1442
- let tablename = table.tablename
1443
- let sql = `ALTER TABLE ${tablename} ADD COLUMN "approval_status" smallint DEFAULT NULL`
1444
- let sql2 = `ALTER TABLE ${tablename} ADD COLUMN "approval_history" jsonb[] DEFAULT NULL `
1445
- try {
1446
- await connection.query(sql)
1447
- } catch (e) {
1448
- console.log(e)
1449
- }
1450
- try {
1451
- await connection.query(sql2)
1452
- } catch (e) {
1453
- console.log(e)
1454
- }
1455
- }
1456
- res.send(tables)
1457
- })
1458
-
1459
- router.get('/addapproval-models', async (req, res) => {
1460
- let text = ''
1461
- let results = await connection.results({
1462
- table: 'zfields',
1463
- })
1464
- for (const result of results) {
1465
- let labels = result.labels
1466
- let arr = Object.keys(labels)
1467
- if (!Util.in_array('approval_status', arr)) {
1468
- text += result.id + ' tidak ada'
1469
- //approval_status_id : "Approval Status",
1470
- labels.approval_status = 'Approval Status'
1471
- labels.approval_history = 'Approval History'
1472
- try {
1473
- await connection.update({
1474
- table: 'zfields',
1475
- data: {
1476
- labels: JSON.stringify(labels),
1477
- },
1478
- where: {
1479
- id: result.id,
1480
- },
1481
- })
1482
- } catch (err) {
1483
- console.log(err)
1484
- }
1485
- }
1486
- }
1487
-
1488
- res.send(text)
1489
- })
1490
-
1491
- //post dropzone widget
1492
- router.post('/zdropzone', async (req, res) => {
1493
- try {
1494
- let userId = res.locals.userId
1495
- if (userId) {
1496
- let dir = `${dirRoot}/public/zdropzone/${userId}`
1497
- if (!fs.existsSync(dir)) {
1498
- fs.mkdirSync(dir, { recursive: true })
1499
- }
1500
- let filename = req.files.file.name
1501
- req.files.file.mv(dir + '/' + filename, function (err) {
1502
- if (err) {
1503
- return res.status(500).send(err + '')
1504
- }
1505
- })
1506
- }
1507
- res.json('ok')
1508
- } catch (e) {
1509
- console.log(e)
1510
- res.status(500)
1511
- res.send(e + '')
1512
- }
1513
- })
1514
-
1515
- router.post('/zdropzone-remove', async (req, res) => {
1516
- try {
1517
- let userId = res.locals.userId
1518
- let cacheName = req.body.cname.replace('ZUSER___ID', userId)
1519
- let dir = `${dirRoot}/public/zdropzone/${userId}`
1520
- if (!fs.existsSync(dir)) {
1521
- fs.mkdirSync(dir, { recursive: true })
1522
- }
1523
- let filename = `${dirRoot}/public/zdropzone/${userId}/${req.body.file}`
1524
- if (Util.fileExist(filename)) {
1525
- await fs.unlink(filename)
1526
- if (myCache.has(cacheName)) {
1527
- arr = myCache.get(name)
1528
- }
1529
- arr = Util.arrayDelete(arr, body.file)
1530
- myCache.set(name, arr)
1531
- }
1532
- res.json('ok')
1533
- } catch (e) {
1534
- console.log(e)
1535
- res.status(500).send(e + '')
1536
- }
1537
- })
1538
- router.post('/zdropzone-attributes', async (req, res) => {
1539
- try {
1540
- let userId = res.locals.userId
1541
- let dir = `${dirRoot}/public/zdropzone/${userId}`
1542
- if (!fs.existsSync(dir)) {
1543
- fs.mkdirSync(dir, { recursive: true })
1544
- }
1545
- let body = req.body
1546
- let category = body.category
1547
- let name = `dropzone__${userId}__${body.table}__${body.field}__${body.type}`
1548
- //dropzone__${res.locals.userId}__${table}__${key}__create
1549
- let arr = []
1550
- if (category === 'add') {
1551
- if (myCache.has(name)) {
1552
- arr = myCache.get(name)
1553
- }
1554
- arr.push(body.file)
1555
- } else {
1556
- name = `dropzone__${userId}__${body.table}__${body.field}__${body.type}`
1557
- if (myCache.has(name)) {
1558
- arr = myCache.get(name)
1559
- }
1560
- arr = Util.arrayDelete(arr, body.file)
1561
- }
1562
- myCache.set(name, arr)
1563
- res.json('ok')
1564
- } catch (e) {
1565
- console.log(e)
1566
- res.status(500).send(e + '')
1567
- }
1568
- })
1569
-
1570
- router.post('/zhistory-data', async (req, res) => {
1571
- let html = ''
1572
- try {
1573
- let id = req.body.id
1574
- let table = req.body.table
1575
- const relations = await zRoute.relations(req, res, table)
1576
- const MYMODELS = zRoute.MYMODELS()
1577
- const MYMODEL = MYMODELS[table]
1578
- let results = await connection.results({
1579
- table: 'zhistory',
1580
- where: {
1581
- module: table,
1582
- module_id: id,
1583
- },
1584
- order_by: ['id asc'],
1585
- })
1586
- if (results.length > 0) {
1587
- let users = {}
1588
- if (myCache.has('users')) {
1589
- users = myCache.get('users')
1590
- } else {
1591
- users = Util.arrayToObject(
1592
- await connection.results({
1593
- table: 'zuser',
1594
- }),
1595
- 'id'
1596
- )
1597
- myCache.set('users', users)
1598
- }
1599
- html = await zRoute.history(req, res, relations, id, MYMODEL, users, results)
1600
- }
1601
- res.json(html)
1602
- } catch (e) {
1603
- console.log(e)
1604
- res.json(e + '')
1605
- }
1606
- })
1607
-
1608
- router.get('/zdownloads-dropzone/:table/:field/:id', async (req, res) => {
1609
- try {
1610
- let table = req.params.table
1611
- let field = req.params.field
1612
- let id = req.params.id
1613
- const room = res.locals.token
1614
- let result = await connection.result({
1615
- table: table,
1616
- where: {
1617
- id: id,
1618
- },
1619
- })
1620
- let dir = `${dirRoot}/public/uploads/${table}/${field}/`
1621
- let arr = []
1622
- let files = result[field]
1623
- for (const file of files) {
1624
- if (Util.fileExist(dir + file)) {
1625
- let filename = file.substring(13)
1626
- arr.push({ path: dir + file, name: filename })
1627
- io.to(room).emit('info', `Zip file ${filename}`)
1628
- }
1629
- }
1630
- io.to(room).emit('info', `Zip file completed...`)
1631
- res.zip(arr, `${field}_${table}_${id}.zip`)
1632
- } catch (e) {
1633
- console.log(e)
1634
- res.json(e + '')
1635
- }
1636
- })
1637
- module.exports = router
1
+ const express = require('express')
2
+ const router = express.Router()
3
+ const csrf = require('csurf')
4
+ const csrfProtection = csrf({ cookie: true })
5
+ const zRoute = require('./zRoute')
6
+ const connection = require('./connection')
7
+ const access = require('./access')
8
+ const myCache = require('./cache')
9
+ const Util = require('./Util')
10
+ const moment = require('moment')
11
+ const fs = require('fs-extra')
12
+ const moduleLib = require('./moduleLib')
13
+ var env = process.env.NODE_ENV || 'development'
14
+ var ecosystem = require(`./../../../ecosystem.config.js`)
15
+ const config = require('dotenv').config()
16
+ const debug = require('./debug')
17
+ const io = require('./io')
18
+ const Mail = require('./Mail')
19
+ const zCache = require('./zCache')
20
+ const pm2 = require('pm2')
21
+ const zFunction = require('./zFunction')
22
+ const qs = require('qs')
23
+ const zip = require('express-zip')
24
+
25
+ /*
26
+ ajax Post
27
+ */
28
+ router.post('/zajax', zRoute.ajax)
29
+ router.get('/ztypeahead/:table/:field', zRoute.typeahead)
30
+ router.post('/ztypeaheadpost/:table/:field', zRoute.typeaheadpost)
31
+
32
+ //password
33
+ router.post('/password-change', zRoute.changePassword)
34
+ router.post('/reset-password/:forgot_password', zRoute.resetPassword)
35
+ //logout
36
+ router.get('/logout', zRoute.logout)
37
+ /*
38
+ function for build form for table type
39
+ */
40
+ router.post('/buildform', csrfProtection, zRoute.buildForm)
41
+ /*
42
+ function for tab access if any
43
+ */
44
+ router.post('/ztab-access', csrfProtection, zRoute.tabAccess)
45
+
46
+ router.get('/profile', csrfProtection, access, async (req, res) => {
47
+ const MYMODELS = myCache.get('MYMODELS')
48
+ let MYMODEL = MYMODELS['zuser']
49
+ let result = await connection.result({ table: 'zuser', where: { id: res.locals.userId } })
50
+ let role = await connection.result({ table: 'zrole', where: { id: result.role_id } })
51
+ let canEditCompany = false
52
+ if (result.role_id == 1 || result.role_id == 2) {
53
+ canEditCompany = true
54
+ }
55
+ let company = await connection.result({ table: 'zcompany', where: { id: res.locals.companyId } })
56
+ let verify_signed = result.verify_signed ? '/uploads/zuser/' + result.verify_signed : '/img/user.png'
57
+ res.render('layouts/' + layout, {
58
+ menu: { menu: 'profile' },
59
+ data: result,
60
+ attributeData: MYMODEL,
61
+ role: role,
62
+ company: company,
63
+ canEditCompany: canEditCompany,
64
+ verify_signed: verify_signed,
65
+ routeName: 'zuser',
66
+ csrfToken: req.csrfToken(),
67
+ renderHead: 'index/profile_head.ejs',
68
+ renderBody: 'index/profile.ejs',
69
+ renderEnd: 'index/profilejs.ejs',
70
+ })
71
+ })
72
+
73
+ router.post('/profile', access, async (req, res) => {
74
+ const MYMODELS = myCache.get('MYMODELS')
75
+ let MYMODEL = MYMODELS['zuser']
76
+ let json = Util.jsonSuccess(LANGUAGE['data_saved'])
77
+ let userId = req.session.user.id
78
+ let dataPost = zRoute.post(req, res, MYMODEL, 'zuser', req.body)
79
+ let data = dataPost['zuser']
80
+ if (req.body.company) {
81
+ await connection.update({
82
+ table: 'zcompany',
83
+ data: { name: req.body.company },
84
+ where: {
85
+ id: res.locals.companyId,
86
+ },
87
+ })
88
+ }
89
+ await connection.update({
90
+ table: 'zuser',
91
+ data: data,
92
+ where: {
93
+ id: userId,
94
+ },
95
+ })
96
+ for (var keys in data) {
97
+ req.session.user[keys] = data[keys]
98
+ }
99
+ req.session.sessionFlash = json
100
+ if (data.image) {
101
+ json.image = Util.imageProfile(data.image)
102
+ }
103
+ res.json(json)
104
+ })
105
+
106
+ router.post('/profile-sign', access, async (req, res) => {
107
+ const MYMODELS = myCache.get('MYMODELS')
108
+ let MYMODEL = MYMODELS['zuser']
109
+ let json = Util.jsonSuccess(LANGUAGE['data_saved'])
110
+ let userId = res.locals.userId
111
+ let image = req.body.image
112
+ let ext = req.body.ext
113
+ let base64Image = image.split(';base64,').pop()
114
+ let filename = `${Util.generateUnique(10)}${res.locals.userId}.${ext}`
115
+ await connection.update({
116
+ table: 'zuser',
117
+ where: {
118
+ id: res.locals.userId,
119
+ },
120
+ data: {
121
+ verify_signed: filename,
122
+ },
123
+ })
124
+ fs.writeFile(dirRoot + '/public/uploads/zuser/' + filename, base64Image, { encoding: 'base64' }, function (err) {})
125
+ res.json(json)
126
+ })
127
+
128
+ //check status user login in session
129
+ router.put('/zuser-session', csrfProtection, async (req, res) => {
130
+ let json = Util.flashError('err')
131
+ if (USER_ID > 0) {
132
+ json = Util.jsonSuccess('Success')
133
+ }
134
+ res.json(json)
135
+ })
136
+
137
+ router.get('/login', csrfProtection, async (req, res) => {
138
+ if (res.locals.isLogin) {
139
+ return res.redirect(process.env.APP_AFTER_LOGIN)
140
+ } else {
141
+ await zFunction('form_login', req, res)
142
+ }
143
+ const isError = req.query.err == 1 ? true : false
144
+ if (isError) {
145
+ res.locals.error = null
146
+ }
147
+ res.locals.menuApp = 'login'
148
+ res.render('layouts/blank', {
149
+ isError: isError,
150
+ csrfToken: req.csrfToken(),
151
+ renderHead: 'index/logincss.ejs',
152
+ renderBody: 'index/login.ejs',
153
+ })
154
+ })
155
+
156
+ router.post('/login', csrfProtection, async (req, res) => {
157
+ await zRoute.login(req.body.username, req.body.password, req, res)
158
+ })
159
+
160
+ router.post('/login-ajax', csrfProtection, async (req, res) => {
161
+ res.json(await zRoute.loginAjax(req.body.username, req.body.password, req, res))
162
+ })
163
+
164
+ router.get('/signup', csrfProtection, async (req, res) => {
165
+ res.locals.menuApp = 'signup'
166
+ if (res.locals.isLogin) {
167
+ return res.redirect(CONFIG.app.afterLogin)
168
+ } else {
169
+ await zFunction('form_register', req, res)
170
+ }
171
+ res.render('layouts/blank', {
172
+ renderBody: 'index/signup.ejs',
173
+ })
174
+ })
175
+
176
+ router.post('/signup', async (req, res) => {
177
+ let body = req.body
178
+ let menuData = {}
179
+ let userCompany = {}
180
+ let user = {}
181
+ let company = {}
182
+ try {
183
+ let validation = registrationValidation(body)
184
+ if (validation.status == 0) {
185
+ res.json(Util.flashError(validation.message))
186
+ return false
187
+ }
188
+ let dataCompany = {
189
+ code: Util.generateUnique(5),
190
+ name: body.company,
191
+ created_at: Util.now(),
192
+ updated_at: Util.now(),
193
+ created_by: 1,
194
+ updated_by: 1,
195
+ }
196
+ company = await connection.insert({
197
+ table: 'zcompany',
198
+ data: dataCompany,
199
+ })
200
+ let dataCache = zCache.myCache.has(body.username)
201
+ ? zCache.get(body.username)
202
+ : {
203
+ fullname: '',
204
+ email: '',
205
+ image: '',
206
+ }
207
+ let dataUser = {
208
+ company_id: company.id,
209
+ created_at: Util.now(),
210
+ updated_at: Util.now(),
211
+ created_by: 1,
212
+ updated_by: 1,
213
+ role_id: 2,
214
+ token: Util.generateUnique(28),
215
+ username: body.username,
216
+ email: body.username,
217
+ password: Util.hash(body.password),
218
+ fullname: body.fullname,
219
+ image: !dataCache.image ? '' : dataCache.image,
220
+ active: 1,
221
+ language: '1',
222
+ }
223
+ user = await connection.insert({
224
+ table: 'zuser',
225
+ data: dataUser,
226
+ })
227
+
228
+ //insert user company
229
+ userCompany = await connection.insert({
230
+ table: 'zuser_company',
231
+ data: {
232
+ role_id: 2,
233
+ company_id: company.id,
234
+ user_id: user.id,
235
+ },
236
+ })
237
+
238
+ let menu = await connection.result({
239
+ table: 'zmenu',
240
+ where: {
241
+ id: 1,
242
+ },
243
+ })
244
+ //insert menu dari user yang sudah ada menu
245
+ menuData = await connection.insert({
246
+ table: 'zmenu',
247
+ data: {
248
+ company_id: company.id,
249
+ created_at: Util.now(),
250
+ updated_at: Util.now(),
251
+ created_by: 1,
252
+ updated_by: 1,
253
+ name: menu.name,
254
+ json: JSON.stringify(menu.json),
255
+ active: 1,
256
+ },
257
+ })
258
+ await zRoute.loginAjax(dataUser.username, body.password, req, res)
259
+ //refresh cache
260
+ await zCache.renew()
261
+ res.json(Util.jsonSuccess(LANGUAGE.success))
262
+ } catch (e) {
263
+ if (menuData && menuData.id) {
264
+ await connection.delete({
265
+ table: 'zmenu',
266
+ where: {
267
+ id: menuData.id,
268
+ },
269
+ })
270
+ }
271
+ if (userCompany && userCompany.id) {
272
+ await connection.delete({
273
+ table: 'zuser_company',
274
+ where: {
275
+ id: userCompany.id,
276
+ },
277
+ })
278
+ }
279
+ if (user && user.id) {
280
+ await connection.delete({
281
+ table: 'zuser',
282
+ where: {
283
+ id: user.id,
284
+ },
285
+ })
286
+ }
287
+ if (company && company.id) {
288
+ await connection.delete({
289
+ table: 'zcompany',
290
+ where: {
291
+ id: company.id,
292
+ },
293
+ })
294
+ }
295
+ res.json(Util.flashError(e.toString()))
296
+ }
297
+ })
298
+
299
+ const registrationValidation = (body) => {
300
+ let json = {
301
+ message: 'ok',
302
+ status: 0,
303
+ }
304
+ if (!Util.validateEmail(body.username)) {
305
+ json.message = 'Email format is wrong!!'
306
+ }
307
+ if (body.password != body.confirm_password) {
308
+ json.message = 'Password not equal to confirm password'
309
+ }
310
+ if (body.password.length < 6) {
311
+ json.message = 'Password must be at least 6 chars'
312
+ }
313
+ if (body.fullname.length < 3) {
314
+ json.message = 'Fullname must be at least 3 chars'
315
+ }
316
+ if (body.company.length < 3) {
317
+ json.message = 'Company Name must be at least 3 chars'
318
+ }
319
+ json.status = json.message == 'ok' ? 1 : 0
320
+ return json
321
+ }
322
+
323
+ const registrationCUSTOMValidation = (body) => {
324
+ var json = {
325
+ message: 'ok',
326
+ status: 0,
327
+ }
328
+ if (!Util.validateEmail(body.username)) {
329
+ json.message = 'Format email salah'
330
+ }
331
+ if (body.password != body.confirm_password) {
332
+ json.message = 'Password dan repasword tidak cocok'
333
+ }
334
+ if (body.password.length < 6) {
335
+ json.message = 'Password kurang dari 6 '
336
+ }
337
+ if (body.fullname.length < 6) {
338
+ json.message = 'Nama lengkap kurang lengkap'
339
+ }
340
+ if (body.phone.length < 6) {
341
+ json.message = 'No telp kurang lengkap'
342
+ }
343
+ json.status = json.message == 'ok' ? 1 : 0
344
+ return json
345
+ }
346
+
347
+ router.post('/signup-custom', async (req, res) => {
348
+ var body = req.body
349
+ try {
350
+ var validation = registrationCUSTOMValidation(body)
351
+ if (validation.status == 0) {
352
+ res.json(Util.flashError(validation.message))
353
+ return false
354
+ }
355
+
356
+ var dataUser = {
357
+ company_id: 1,
358
+ created_at: Util.now(),
359
+ updated_at: Util.now(),
360
+ created_by: 1,
361
+ updated_by: 1,
362
+ role_id: 4,
363
+ token: Util.generateUnique(28),
364
+ username: body.username,
365
+ email: body.username,
366
+ password: Util.hash(body.password),
367
+ fullname: body.fullname,
368
+ phone: body.phone,
369
+ verify_signed: 'lizhn63iqA8CVDQeOw8.png',
370
+ active: 0,
371
+ language: '2',
372
+ }
373
+ var user = await connection.insert({
374
+ table: 'zuser',
375
+ data: dataUser,
376
+ })
377
+ var userCompany = await connection.insert({
378
+ table: 'zuser_company',
379
+ data: {
380
+ role_id: 4,
381
+ company_id: 1,
382
+ user_id: user.id,
383
+ },
384
+ })
385
+ /* await zRoute.loginAjax(dataUser.username, body.password, req, res);
386
+ //refresh cache
387
+ await zCache.renew();*/
388
+
389
+ res.json(Util.jsonSuccess('Successfuly'))
390
+ } catch (e) {
391
+ res.json(Util.flashError(e.toString()))
392
+ }
393
+ })
394
+
395
+ router.post('/gridprint', async (req, res) => {
396
+ let html = ''
397
+ let id = req.body.id
398
+ let table = req.body.table
399
+ if (id) {
400
+ let results = await connection.results({
401
+ table: 'zapprovals',
402
+ where: {
403
+ id_data: id,
404
+ table: table,
405
+ },
406
+ })
407
+ if (results.length) {
408
+ let result = results[0]
409
+ if (result.status == 3 || result.status == 4) {
410
+ html += `<button class="btn btn-sm btn-info gridprint" data-token="${result.token}"><span class="fa fa-print"></span></button> `
411
+ }
412
+ }
413
+ }
414
+ res.json(html)
415
+ })
416
+
417
+ router.get('/failed', async function (req, res) {
418
+ let template = 'fronts'
419
+ res.render('layouts/' + template, {
420
+ menu: 'failed',
421
+ renderBody: 'index/failed.ejs',
422
+ Util: Util,
423
+ })
424
+ })
425
+
426
+ router.get('/forgot', csrfProtection, async (req, res) => {
427
+ const MYMODELS = myCache.get('MYMODELS')
428
+ let MYMODEL = MYMODELS['zuser']
429
+ if (res.locals.isLogin) {
430
+ return res.redirect('/dashboard')
431
+ }
432
+ let script = `submitForm('forgot-form',"","",function(data){if (data.status == 1) {
433
+ toastrForm(data);spinner.hide();
434
+ setTimeout(function () {location.href='/';},6000);
435
+ }});`
436
+ await moduleLib.custom(req, res, script)
437
+
438
+ res.render('layouts/fronts', {
439
+ csrfToken: req.csrfToken(),
440
+ attributeData: MYMODEL,
441
+ routeName: 'zuser',
442
+ data: MYMODEL.datas,
443
+ renderBody: 'index/forgot.ejs',
444
+ })
445
+ })
446
+
447
+ router.post('/forgot', csrfProtection, async (req, res) => {
448
+ let json = Util.jsonError('email', 'Email not found in our database')
449
+ let routeName = 'user'
450
+ const MYMODELS = myCache.get('MYMODELS')
451
+ let MYMODEL = MYMODELS['zuser']
452
+ let data = zRoute.post(req, res, MYMODEL)['zuser']
453
+ var port = ecosystem.apps[0].env.PORT
454
+ var url = env == 'production' ? process.env.APP_URL : 'http://localhost:' + port
455
+ let email = data.email || ' '
456
+ email = email.trim()
457
+ if (email.length > 5) {
458
+ let rows = await connection.results({
459
+ table: 'zuser',
460
+ where: {
461
+ email: email,
462
+ },
463
+ })
464
+ if (rows.length > 0) {
465
+ let post = {
466
+ forgot_password: Util.generateUnique(23),
467
+ }
468
+ await connection.update({
469
+ table: 'zuser',
470
+ where: {
471
+ id: rows[0].id,
472
+ },
473
+ data: post,
474
+ })
475
+ let options = {
476
+ to: email,
477
+ subject: 'Forgot Password',
478
+ }
479
+ let datas = {
480
+ config: {
481
+ app: {
482
+ url: url,
483
+ },
484
+ },
485
+ url: url,
486
+ link: url + '/reset-password/' + post.forgot_password,
487
+ }
488
+ Mail.forgotPassword(datas, options)
489
+ json = Util.jsonSuccess('Please check your email to reset ')
490
+ }
491
+ }
492
+
493
+ res.json(json)
494
+ })
495
+
496
+ router.get('/reset-password/:forgot_password', csrfProtection, async (req, res) => {
497
+ let forgot_password = req.params.forgot_password || ''
498
+ let activated = false
499
+ if (forgot_password != '') {
500
+ let results = await connection.results({
501
+ table: 'zuser',
502
+ where: {
503
+ forgot_password: forgot_password,
504
+ },
505
+ })
506
+ if (results.length > 0) {
507
+ activated = true
508
+ }
509
+ }
510
+ var script = `submitForm('form-group','','',function(data){
511
+ if(data.status==1){
512
+ location.href = '/login'
513
+ }
514
+ });`
515
+ await moduleLib.custom(req, res, script)
516
+ res.render('layouts/fronts', {
517
+ activated: activated,
518
+ csrfToken: req.csrfToken(),
519
+ forgot_password: forgot_password,
520
+ renderBody: 'index/reset-password.ejs',
521
+ })
522
+ })
523
+
524
+ router.get('/no-access', async (req, res) => {
525
+ let myview = 'fronts'
526
+ if (req.session.user) {
527
+ myview = 'main'
528
+ }
529
+ res.render('layouts/' + myview, {
530
+ data: { table: 'error' },
531
+ menu: 'error',
532
+ renderBody: 'index/no-access.ejs',
533
+ })
534
+ })
535
+
536
+ router.get('/page_not_found', async (req, res) => {
537
+ res.render('layouts/page_not_found', {
538
+ data: { table: 'error' },
539
+ menu: 'error',
540
+ //renderBody: "index/no-found.ejs",
541
+ })
542
+ })
543
+
544
+ // for change company session
545
+ router.get('/session/:id', access, async (req, res) => {
546
+ let companies = res.locals.zcompanies
547
+ let user = await connection.result({
548
+ table: 'zuser',
549
+ where: {
550
+ id: res.locals.userId,
551
+ },
552
+ })
553
+ for (let i = 0; i < companies.length; i++) {
554
+ if (companies[i].id == req.params.id) {
555
+ user.company_id = req.params.id
556
+ await zRoute.handleSession(req, user)
557
+ var post = {
558
+ company_id: companies[i].id,
559
+ role_id: companies[i].role_id,
560
+ }
561
+ await connection.update({
562
+ table: 'zuser',
563
+ data: post,
564
+ where: {
565
+ id: res.locals.userId,
566
+ },
567
+ })
568
+ }
569
+ }
570
+ var backURL = req.header('Referer') || '/'
571
+ // do your thang
572
+ res.redirect(backURL)
573
+ })
574
+
575
+ //RESTART
576
+ router.get('/restart', access, async (req, res) => {
577
+ var room = res.locals.user.token
578
+ if (env == 'production') {
579
+ pm2.connect(function (err) {
580
+ if (err) {
581
+ io.to(room).emit('error', err.toString())
582
+ }
583
+ pm2.restart(process.env.PM2_NAME, (err, proc) => {
584
+ io.to(room).emit('message', 'Restart done')
585
+ })
586
+ })
587
+ } else {
588
+ io.to(room).emit('message', 'Restart done')
589
+ }
590
+ res.json('ok')
591
+ })
592
+
593
+ //ERROR UI
594
+ router.get('/error', async (err, req, res, next) => {
595
+ res.locals.message = err.message
596
+ res.locals.error = req.app.get('env') === 'development' ? err : err
597
+ // render the error page
598
+ res.status(err.status || 500)
599
+ debug(req, res, err)
600
+ res.render('layouts/' + layout, {
601
+ renderBody: 'index/error.ejs',
602
+ })
603
+ })
604
+
605
+ //APPROVAL SYSTEMS
606
+ router.post('/zzapproval', async (req, res) => {
607
+ let json = Util.jsonSuccess(LANGUAGE['data_saved'])
608
+ const MYMODELS = myCache.get('MYMODELS')
609
+ let MYMODEL = MYMODELS['zapprovals']
610
+ const port = ecosystem.apps[0].env.PORT
611
+ let users = Util.arrayToObject(await connection.results({ table: 'zuser' }), 'id')
612
+ try {
613
+ let userId = res.locals.userId
614
+ let data = zRoute.post(req, res, MYMODEL)[MYMODEL.table]
615
+ let validator = zRoute.validator(data, MYMODEL)
616
+ if (validator.status == 0) return res.json(validator.message)
617
+ if (data.status == 2) {
618
+ if (!data.approvers) {
619
+ return res.json(Util.flashError('Approvers empty'))
620
+ }
621
+ if (data.title == '') {
622
+ return res.json(Util.flashError('Title empty', 'title'))
623
+ }
624
+ }
625
+ //update template for newst
626
+ var row = await connection.result({ table: 'zfields', where: { table: data.table } })
627
+ var jsonApproval = row.approval_json || {}
628
+ data.template = jsonApproval.content || {}
629
+ var approvers = []
630
+ if (typeof data.approvers == 'string') {
631
+ data.approvers = JSON.parse(data.approvers)
632
+ }
633
+ approvers = data.approvers || []
634
+ if (approvers.length > 1) {
635
+ approvers = approvers.filter(Util.arrayUnique)
636
+ }
637
+ data.approvers = JSON.stringify(approvers)
638
+ let knowings = []
639
+ if (typeof data.knowings == 'string') {
640
+ data.knowings = JSON.parse(data.knowings)
641
+ }
642
+ knowings = data.knowings || []
643
+ if (knowings.length > 1) {
644
+ knowings = knowings.filter(Util.arrayUnique)
645
+ }
646
+ data.knowings = JSON.stringify(knowings)
647
+ let allUsers = [...approvers, ...knowings]
648
+
649
+ let statusApprovers = approvers.reduce((result, item) => {
650
+ return [...result, { user: item, status: 2 }]
651
+ }, [])
652
+ data.approved_stats = JSON.stringify({
653
+ stats: `0/${approvers.length}`,
654
+ status: statusApprovers,
655
+ })
656
+ let knowingStatus = knowings.reduce((result, item) => {
657
+ return [...result, { user: item, status: 7 }]
658
+ }, [])
659
+
660
+ data.knowing_stats = JSON.stringify({
661
+ stats: `0/${knowings.length}`,
662
+ status: knowingStatus,
663
+ })
664
+ let results = await connection.results({
665
+ table: MYMODEL.table,
666
+ where: { table: data.table, id_data: data.id_data },
667
+ })
668
+ if (results.length) {
669
+ let query = await zRoute.updateSQL(req, res, MYMODEL.table, data, { id: results[0].id })
670
+ data.id = results[0].id
671
+ } else {
672
+ var query = await zRoute.insertSQL(req, res, MYMODEL.table, data)
673
+ data.id = query.id
674
+ }
675
+ if (data.status == 2) {
676
+ //send activity
677
+ /* await zRoute.insertSQL(req, res, "zactivity", {
678
+ user_id: res.locals.userId,
679
+ table: MYMODEL.table,
680
+ id_data: data.id,
681
+ status: data.status,
682
+ status_label: MYMODEL.widgets.status.fields[data.status],
683
+ title: MYMODEL.widgets.status.fields[data.status],
684
+ description: users[res.locals.userId].fname + " " +users[res.locals.userId].lname ,
685
+ data: JSON.stringify(data)
686
+ });*/
687
+ //if serial
688
+ if (data.type == 2) {
689
+ approvers = [approvers[0]]
690
+ }
691
+ let sectionsAprrovers = approvers.reduce((temp, item, index) => {
692
+ return [
693
+ ...temp,
694
+ {
695
+ title: users[item].fullname,
696
+ description: '@' + users[item].fullname,
697
+ rowId: 'row' + index,
698
+ },
699
+ ]
700
+ }, [])
701
+ let sectionsKnowings = knowings.reduce((temp, item, index) => {
702
+ return [
703
+ ...temp,
704
+ {
705
+ title: users[item].fullname,
706
+ description: '@' + users[item].fullname,
707
+ rowId: 'row' + index,
708
+ },
709
+ ]
710
+ }, [])
711
+ let sections = []
712
+ sections.push({ title: 'Approvers', rows: sectionsAprrovers })
713
+ if (sectionsKnowings) {
714
+ sections.push({ title: 'Knowings', rows: sectionsKnowings })
715
+ }
716
+ approvers.forEach(async (item, num) => {
717
+ let post = {
718
+ title_id: data.id,
719
+ user_id: item,
720
+ status: 7,
721
+ type: 1,
722
+ token: Util.uuid(),
723
+ }
724
+ await zRoute.insertSQL(req, res, 'zapprovals_details', post)
725
+ let link = env == 'production' ? process.env.APP_URL + '/za/' + post.token : `http://localhost:${port}/za/${post.token}`
726
+ let email = users[post.user_id].email
727
+
728
+ post.subject = `Need Approve ${data.title}`
729
+ post.buttonTitle = `Approve Now`
730
+ post.title = `NEED APPROVE DOCUMENT`
731
+ post.link = link
732
+ post.url = CONFIG.app.url
733
+ post.description = `Hai ${users[post.user_id].fullname} <br>
734
+
735
+
736
+ We have some document for you.<br>
737
+ Please click the link above to view the document.`
738
+
739
+ post.note = `If you click the link, it's will be automatically acknowledged`
740
+ Mail.gmail(req, res, post, email)
741
+
742
+ //send to whatsapp
743
+ let phone = Util.phoneWA(users[post.user_id].phone)
744
+ if (phone) {
745
+ var textWa = ''
746
+ textWa += `*NEED APPROVE DOCUMENT* \r\n_${data.title}_\r\nHai ${users[post.user_id].fullname} \r\n \r\n`
747
+ textWa += 'We have some document for you.\r\n'
748
+ textWa += `Please click the link above to view the document.\r\n${link}`
749
+
750
+ /* await whatsapp({
751
+ to: phone,
752
+ text: textWa,
753
+ sections: JSON.stringify(sections),
754
+ buttonText: "Click me for details"
755
+ });*/
756
+ }
757
+
758
+ //send notification
759
+ /* await zRoute.insertSQL(req, res, "znotification", {
760
+ user_id: item,
761
+ table: MYMODEL.table,
762
+ id_data: data.id,
763
+ status: 1,
764
+ link: "/za/" + post.token,
765
+ status_label: MYMODEL.widgets.status.fields[1],
766
+ title: `Need Approve`,
767
+ description: data.title,
768
+ token: post.token
769
+ });*/
770
+
771
+ //send todolist
772
+ /* await zRoute.insertSQL(req, res, "ztodolist", {
773
+ user_id: item,
774
+ table: MYMODEL.table,
775
+ id_data: data.id,
776
+ status: 1,
777
+ link: "/za/" + post.token,
778
+ status_label: MYMODEL.widgets.status.fields[1],
779
+ title: `Need Approve`,
780
+ description: data.title,
781
+ users: JSON.stringify(allUsers)
782
+ });*/
783
+
784
+ //send toastr using socket.io
785
+ io.to(users[item].token).emit('message', 'Need Approve ' + data.title)
786
+ })
787
+
788
+ knowings.map(async (item) => {
789
+ let post = {
790
+ title_id: data.id,
791
+ user_id: item,
792
+ status: 7,
793
+ type: 2,
794
+ token: Util.uuid(),
795
+ }
796
+ await zRoute.insertSQL(req, res, 'zapprovals_details', post)
797
+ let link = env == 'production' ? process.env.APP_URL + '/za/' + post.token : `http://localhost:${port}/za/${post.token}`
798
+ let email = users[post.user_id].email
799
+
800
+ post.subject = `Need acknowledge ${data.title}`
801
+ post.buttonTitle = `Acknowledge Now`
802
+ post.title = `NEED ACKNOWLEDGE DOCUMENT`
803
+
804
+ post.link = link
805
+ post.url = CONFIG.app.url
806
+ post.description = `Hai ${users[post.user_id].fullname} <br>
807
+
808
+
809
+ We have some document for you.<br>
810
+ Please click the link above to view the document.`
811
+
812
+ post.note = `If you click the link, it's will be automatically acknowledged`
813
+ Mail.gmail(req, res, post, email)
814
+
815
+ //send to whatsapp
816
+ let phone = Util.phoneWA(users[post.user_id].phone)
817
+ if (phone) {
818
+ var textWa = ''
819
+ textWa += `*NEED ACKNOWLEDGE DOCUMENT* \r\n_${data.title}_\r\nHai ${users[post.user_id].fullname} \r\n \r\n`
820
+ textWa += 'We have some document for you.\r\n'
821
+ textWa += `Please click the link above to view the document.\r\n${link}`
822
+ /* await whatsapp({
823
+ to: phone,
824
+ text: textWa,
825
+ sections: JSON.stringify(sections),
826
+ buttonText: "Click me for details"
827
+ });*/
828
+ }
829
+
830
+ //send activity
831
+ /* await cRoute.insertSQL(req, res, "zactivity",{
832
+ user_id:item,
833
+ table:MYMODEL.table,
834
+ id_data:data.id,
835
+ status:7,
836
+ status_label: MYMODEL.widgets.status.fields[7],
837
+ title : MYMODEL.widgets.status.fields[7],
838
+ description: data.title,
839
+ data:JSON.stringify(data)
840
+ });*/
841
+
842
+ //send notification
843
+ /* await zRoute.insertSQL(req, res, "znotification", {
844
+ user_id: item,
845
+ table: MYMODEL.table,
846
+ id_data: data.id,
847
+ status: 1,
848
+ link: "/za/" + post.token,
849
+ status_label: MYMODEL.widgets.status.fields[1],
850
+ title: `Need Acknowledge`,
851
+ description: data.title,
852
+ token: post.token
853
+ });
854
+
855
+ //send todolist
856
+ await zRoute.insertSQL(req, res, "ztodolist", {
857
+ user_id: item,
858
+ table: MYMODEL.table,
859
+ id_data: data.id,
860
+ status: 1,
861
+ link: "/za/" + post.token,
862
+ status_label: MYMODEL.widgets.status.fields[1],
863
+ title: `Need Acknowledge`,
864
+ description: data.title,
865
+ users: JSON.stringify(allUsers)
866
+ });*/
867
+ io.to(users[item].token).emit('message', 'Need Acknowledge ' + data.title)
868
+ })
869
+ }
870
+ } catch (err) {
871
+ if (Object.prototype.hasOwnProperty.call(err, 'sqlMessage')) {
872
+ json = Util.flashError(err.sqlMessage)
873
+ } else {
874
+ json = Util.flashError(err.toString())
875
+ }
876
+ debug(req, res, err)
877
+ }
878
+ res.json(json)
879
+ })
880
+
881
+ router.get('/za/:token', csrfProtection, async (req, res) => {
882
+ let token = req.params.token
883
+ let data = {},
884
+ data2 = {}
885
+ let template = ''
886
+ let result
887
+ let isClosed = false
888
+ let footers = ''
889
+ let details = []
890
+ let routeName = env == 'production' ? process.env.APP_URL : `http://localhost:${port}`
891
+ let statusLabel = ''
892
+ let knowings = []
893
+ const MYMODELS = myCache.get('MYMODELS')
894
+ let MYMODEL = MYMODELS['zapprovals']
895
+ let users = Util.arrayToObject(await connection.results({ table: 'zuser' }), 'id')
896
+ try {
897
+ result = await connection.result({
898
+ select: '*, zapprovals.id as ide, zapprovals_details.token as usertoken, zapprovals.status as statuse, zapprovals_details.status as mystatus, zapprovals_details.type as user_type, zapprovals_details.updated_at',
899
+ table: 'zapprovals_details',
900
+ joins: ['LEFT JOIN zapprovals ON (zapprovals_details.title_id = zapprovals.id)', 'LEFT JOIN employee ON (zapprovals_details.user_id = employee.id)'],
901
+ where: { 'zapprovals_details.token': token },
902
+ })
903
+ let approvers = result.approvers
904
+ knowings = result.knowings ? result.knowings : []
905
+
906
+ statusLabel = MYMODEL.widgets.status.fields[result.statuse]
907
+ routeName = routeName + '/' + result.table + '/view/' + result.id_data
908
+ if (result.statuse == 3 || result.statuse == 4 || result.mystatus == 3 || result.mystatus == 4) {
909
+ isClosed = true
910
+ }
911
+ details = await connection.results({ table: 'zapprovals_details', where: { title_id: result.ide } })
912
+ if (result.user_type == 2) {
913
+ isClosed = true
914
+ var post = {
915
+ status: 6, //read
916
+ }
917
+ await connection.update({ table: 'zapprovals_details', data: post, where: { token: token } })
918
+
919
+ //set stats
920
+ //{"stats":"0/1","status":[{"user":"12","status":0}]}
921
+ let knowing_stats = result.knowing_stats || {}
922
+ let statuses = knowing_stats.status
923
+ let stats = knowing_stats.stats
924
+ let explode = stats.split('/')
925
+ let count = parseInt(explode[0])
926
+ let newStatus = []
927
+ knowings = result.knowings || []
928
+ statuses.map((item) => {
929
+ if (item.user == result.user_id && result.mystatus != 3) {
930
+ item.status = 3
931
+ if (count < knowings.length) {
932
+ count = count + 1
933
+ }
934
+ newStatus.push(item)
935
+ } else {
936
+ newStatus.push(item)
937
+ }
938
+ })
939
+ if (result.mystatus != 3) {
940
+ post = {
941
+ knowing_stats: JSON.stringify({ stats: count + '/' + explode[1], status: newStatus }),
942
+ }
943
+ await connection.update({ table: 'zapprovals', data: post, where: { id: result.ide } })
944
+ //var users = await zRoute.getUsers();
945
+ var message = users[result.user_id].fullname + ' has readed document ' + result.title
946
+ details.forEach(function (item) {
947
+ io.to(users[item.user_id].token).emit('message', message)
948
+ })
949
+ }
950
+ }
951
+
952
+ MYMODEL = MYMODELS[result.table]
953
+ let row = await connection.result({ table: MYMODEL.table, where: { id: result.id_data } })
954
+ data = await zRoute.viewTable(req, res, MYMODEL, row)
955
+ template = result.template
956
+ for (var key in data) {
957
+ template = Util.replaceAll(template, '{{' + key + '}}', data[key])
958
+ }
959
+
960
+ footers = await zRoute.approversFooter(details)
961
+
962
+ //send activity
963
+ if (result.mystatus == 7) {
964
+ MYMODEL = MYMODELS['zapprovals']
965
+ /* await connection.insert({
966
+ table: "zactivity",
967
+ data: {
968
+ company_id: result.company_id,
969
+ created_at: Util.now(),
970
+ created_by: result.user_id,
971
+ updated_by: result.user_id,
972
+ user_id: result.user_id,
973
+ table: MYMODEL.table,
974
+ id_data: result.ide,
975
+ status: 6,
976
+ status_label: MYMODEL.widgets.status.fields[6],
977
+ title: `${MYMODEL.widgets.status.fields[6]}`,
978
+ description: `Ok `,
979
+ data: JSON.stringify(data)
980
+ }
981
+ });
982
+ */
983
+
984
+ await connection.update({
985
+ table: 'zapprovals_details',
986
+ where: {
987
+ token: token,
988
+ },
989
+ data: { status: 6 },
990
+ })
991
+ }
992
+ } catch (err) {
993
+ debug(req, res, err)
994
+ res.send('Not Found')
995
+ }
996
+ res.render('layouts/blank', {
997
+ routeName: routeName,
998
+ Util: Util,
999
+ data: data,
1000
+ statusLabel: statusLabel,
1001
+ template: template,
1002
+ result: result,
1003
+ statusLabel: statusLabel,
1004
+ isClosed: isClosed,
1005
+ footers: footers,
1006
+ csrfToken: req.csrfToken(),
1007
+ token: result.usertoken,
1008
+ tokendoc: token,
1009
+ renderHead: 'index/zacss.ejs',
1010
+ renderBody: 'index/za.ejs',
1011
+ renderEnd: 'index/zajs.ejs',
1012
+ })
1013
+ })
1014
+
1015
+ router.post('/za/:token', csrfProtection, async (req, res) => {
1016
+ let token = req.params.token
1017
+ let comments = req.body.comments
1018
+ let status = req.body.status
1019
+ let json = Util.jsonSuccess('Success')
1020
+ let data = {},
1021
+ data2 = {}
1022
+ let template = ''
1023
+ let approvers = [],
1024
+ knowings = []
1025
+ let users = Util.arrayToObject(await connection.results({ table: 'zuser' }), 'id')
1026
+ let employee_user = users
1027
+ const MYMODELS = myCache.get('MYMODELS')
1028
+ let MYMODEL = MYMODELS['zapprovals']
1029
+ let post = {}
1030
+ try {
1031
+ var results = await connection.results({
1032
+ select: '*,zapprovals_details.status as approvers_status, zapprovals.created_by as submiter, zapprovals.type as typee, zapprovals.status as statuse, zapprovals_details.id as detaild_id, zapprovals.id as ide, zapprovals.approvers as approvers ',
1033
+ table: 'zapprovals_details',
1034
+ joins: ['LEFT JOIN zapprovals ON (zapprovals_details.title_id = zapprovals.id)'],
1035
+ where: { 'zapprovals_details.token': token },
1036
+ })
1037
+ if (!results.length) {
1038
+ return res.json(Util.jsonError('Data not found!'))
1039
+ }
1040
+
1041
+ var result = results[0]
1042
+ if (result.approvers_status == 3 || result.approvers_status == 4) {
1043
+ return res.json(Util.jsonError('You have submited.'))
1044
+ }
1045
+ post = {
1046
+ status: status,
1047
+ comments: comments,
1048
+ updated_at: Util.now(),
1049
+ }
1050
+ let update = await connection.update({ table: 'zapprovals_details', data: post, where: { id: result.detaild_id } })
1051
+ let details = await connection.results({ table: 'zapprovals_details', where: { title_id: result.ide } })
1052
+ approvers = result.approvers
1053
+ knowings = result.knowings || []
1054
+ let stats = 0
1055
+ let status_stats = []
1056
+ let approversSigned = []
1057
+ //{"stats":"0/2","status":[{"user":"12","status":2},{"user":"35","status":2}]}
1058
+ let last_status
1059
+ details.map((item) => {
1060
+ if (item.type == 1) {
1061
+ if (item.status == 4 || item.status == 3) {
1062
+ stats++
1063
+ approversSigned.push(item.user_id + '')
1064
+ }
1065
+ status_stats.push({
1066
+ user: item.user_id,
1067
+ status: item.status,
1068
+ })
1069
+ last_status = item.status
1070
+ }
1071
+ })
1072
+
1073
+ post.approved_stats = JSON.stringify({
1074
+ stats: stats + '/' + approvers.length,
1075
+ status: status_stats,
1076
+ })
1077
+ if (stats == approvers.length) {
1078
+ post.status = last_status
1079
+ } else {
1080
+ post.status = 5
1081
+ }
1082
+ if (status == 4) {
1083
+ post.status = 4
1084
+ }
1085
+ await connection.update({ table: 'zapprovals', data: post, where: { id: result.ide } })
1086
+
1087
+ //send activity
1088
+ await connection.insert({
1089
+ table: 'zactivity',
1090
+ data: {
1091
+ company_id: result.company_id,
1092
+ created_at: Util.now(),
1093
+ created_by: result.user_id,
1094
+ updated_by: result.user_id,
1095
+ user_id: result.user_id,
1096
+ table: MYMODEL.table,
1097
+ id_data: result.ide,
1098
+ status: status,
1099
+ status_label: MYMODEL.widgets.status.fields[status],
1100
+ title: MYMODEL.widgets.status.fields[status],
1101
+ description: comments,
1102
+ data: JSON.stringify(post),
1103
+ },
1104
+ })
1105
+
1106
+ //send notification
1107
+ if (status == 3 || status == 4) {
1108
+ let message = `Document ${result.title} has ${MYMODEL.widgets.status[status]};`
1109
+ approvers.forEach(function (item) {
1110
+ io.to(users[item].token).emit('message', message)
1111
+ })
1112
+ if (status == 3) {
1113
+ // if type is serial is step by step
1114
+ //send notification and generate email
1115
+ //approversSigned
1116
+ if (result.typee == 2) {
1117
+ //get approvers has already sign
1118
+
1119
+ approversSigned.push(result.user_id)
1120
+ var newApprovers = approvers.filter((item) => {
1121
+ return !approversSigned.includes(item)
1122
+ })
1123
+ var item = newApprovers.length ? newApprovers[0] : ''
1124
+ if (item) {
1125
+ post = {
1126
+ title_id: result.ide,
1127
+ user_id: employee_user[item].user_id,
1128
+ status: 7,
1129
+ type: 1,
1130
+ comments: comments,
1131
+ token: Util.uuid(),
1132
+ company_id: result.company_id,
1133
+ created_at: Util.now(),
1134
+ updated_at: Util.now(),
1135
+ created_by: employee_user[item].user_id,
1136
+ updated_by: employee_user[item].user_id,
1137
+ }
1138
+ await connection.insert({
1139
+ table: 'zapprovals_details',
1140
+ data: post,
1141
+ })
1142
+ let link = CONFIG.app.url + '/za/' + post.token
1143
+ let email = users[item].username
1144
+
1145
+ post.subject = `Need Approve ${result.title}`
1146
+ post.buttonTitle = `Approve Now`
1147
+ post.title = `NEED APPROVE DOCUMENT`
1148
+ post.link = link
1149
+ post.url = CONFIG.app.url
1150
+ post.description = `Hai ${users[item].fullname} <br>
1151
+
1152
+
1153
+ We have some document for you.<br>
1154
+ Please click the link above to view the document.`
1155
+
1156
+ post.note = `If you click the link, it's will be automatically acknowledged`
1157
+ Mail.gmail(req, res, post, email)
1158
+
1159
+ //send to whatsapp
1160
+ let sectionsAprrovers = approvers.reduce((temp, item, index) => {
1161
+ return [
1162
+ ...temp,
1163
+ {
1164
+ title: users[item].fullname + ' ' + users[item].position,
1165
+ description: '@' + users[item].fullname + ' ' + users[item].position,
1166
+ rowId: 'roe' + index,
1167
+ },
1168
+ ]
1169
+ }, [])
1170
+ let sectionsKnowings = knowings.reduce((temp, item, index) => {
1171
+ return [
1172
+ ...temp,
1173
+ {
1174
+ title: users[item].fullname + ' ' + users[item].position,
1175
+ description: '@' + users[item].fullname + ' ' + users[item].position,
1176
+ rowId: 'roe' + index,
1177
+ },
1178
+ ]
1179
+ }, [])
1180
+ let sections = []
1181
+ sections.push({ title: 'Approvers', rows: sectionsAprrovers })
1182
+ if (sectionsKnowings) {
1183
+ sections.push({ title: 'Knowings', rows: sectionsKnowings })
1184
+ }
1185
+ //send notification
1186
+ await connection.insert({
1187
+ table: 'znotification',
1188
+ data: {
1189
+ company_id: result.company_id,
1190
+ created_at: Util.now(),
1191
+ created_by: employee_user[result.user_id].user_id,
1192
+ updated_by: employee_user[result.user_id].user_id,
1193
+ user_id: item,
1194
+ table: MYMODEL.table,
1195
+ id_data: data.id,
1196
+ status: 1,
1197
+ link: '/za/' + post.token,
1198
+ status_label: 'Unread',
1199
+ title: `Need Approve`,
1200
+ description: data.title,
1201
+ token: post.token,
1202
+ },
1203
+ })
1204
+
1205
+ //send todolist
1206
+ await connection.insert({
1207
+ table: 'ztodolist',
1208
+ data: {
1209
+ company_id: result.company_id,
1210
+ created_at: Util.now(),
1211
+ created_by: employee_user[result.user_id].user_id,
1212
+ updated_by: employee_user[result.user_id].user_id,
1213
+ user_id: item,
1214
+ table: MYMODEL.table,
1215
+ id_data: result.ide,
1216
+ status: 1,
1217
+ link: '/za/' + post.token,
1218
+ status_label: 'Unread',
1219
+ title: `Need Approve`,
1220
+ description: result.title,
1221
+ users: JSON.stringify(approvers),
1222
+ },
1223
+ })
1224
+
1225
+ //send toastr using socket.io
1226
+ io.to(users[item].token).emit('message', 'Need Approve for document : ' + result.title)
1227
+ }
1228
+ }
1229
+ }
1230
+ }
1231
+ } catch (err) {
1232
+ debug(req, res, err)
1233
+ json = Util.flashError(err.toString())
1234
+ }
1235
+
1236
+ res.json(json)
1237
+ })
1238
+
1239
+ router.get('/zdownload/zgenerator/:table', async (req, res) => {
1240
+ var table = req.params.table
1241
+ var path = `${dirRoot}/public/uploads/zgenerator/${table}.json`
1242
+ res.download(path, function (err) {
1243
+ if (err) {
1244
+ //console.log(err);
1245
+ }
1246
+ })
1247
+ })
1248
+
1249
+ router.post('/zlock-unlock/:table', async (req, res) => {
1250
+ let json = Util.jsonSuccess('Success')
1251
+ let table = req.params.table
1252
+ let cacheRoles = myCache.get('ROLES')
1253
+ let roleId = res.locals.roleId
1254
+ let myrole = cacheRoles[roleId]
1255
+ let tableRole = myrole.params[table] || []
1256
+ let hasAccess = tableRole.includes('lock') ? true : false
1257
+ if (hasAccess) {
1258
+ let type = req.body.type
1259
+ let datas = req.body.datas || []
1260
+ if (datas.length > 0) {
1261
+ for (const data of datas) {
1262
+ let id = data.name.replace('ck[', '').replace(']', '')
1263
+ await connection.update({
1264
+ table: table,
1265
+ data: {
1266
+ lock: type,
1267
+ },
1268
+ where: {
1269
+ id: id,
1270
+ },
1271
+ })
1272
+ }
1273
+ } else {
1274
+ json = Util.flashError('No Data')
1275
+ }
1276
+ } else {
1277
+ json = Util.flashError('No Access')
1278
+ }
1279
+
1280
+ res.json(json)
1281
+ })
1282
+
1283
+ router.post('/zdeleted-selected/:table', async (req, res) => {
1284
+ let json = Util.jsonSuccess('Success')
1285
+ let table = req.params.table
1286
+ let cacheRoles = myCache.get('ROLES')
1287
+ let roleId = res.locals.roleId
1288
+ let myrole = cacheRoles[roleId]
1289
+ let tableRole = myrole.params[table] || []
1290
+ let hasAccess = tableRole.includes('lock') ? true : false
1291
+ if (hasAccess) {
1292
+ let type = req.body.type
1293
+ let datas = req.body.datas || []
1294
+ if (datas.length > 0) {
1295
+ for (const data of datas) {
1296
+ let id = data.name.replace('ck[', '').replace(']', '')
1297
+ try {
1298
+ await connection.delete({
1299
+ table: table,
1300
+ where: {
1301
+ id: id,
1302
+ },
1303
+ })
1304
+ } catch (e) {
1305
+ io.emit('error', e + '')
1306
+ }
1307
+ }
1308
+ } else {
1309
+ json = Util.flashError('No Data')
1310
+ }
1311
+ } else {
1312
+ json = Util.flashError('No Access')
1313
+ }
1314
+
1315
+ res.json(json)
1316
+ })
1317
+
1318
+ router.post('/zapproval-update/:table', async (req, res) => {
1319
+ let json = Util.jsonSuccess('Success')
1320
+ let table = req.params.table
1321
+ let value = req.body.value
1322
+ let text = req.body.text
1323
+ let datas = req.body.datas || []
1324
+ let roles = myCache.get('ROLES')[res.locals.roleId] || {}
1325
+ let myaccess = roles.approvals[table]
1326
+ let hasAccess = myaccess.hasOwnProperty(value) ? true : false
1327
+ let canUpdate = true
1328
+ let dataStatus = []
1329
+ if (text == '') {
1330
+ res.json(Util.flashError('please type a message'))
1331
+ return false
1332
+ }
1333
+ if (hasAccess) {
1334
+ if (datas.length > 0) {
1335
+ for (const data of datas) {
1336
+ let id = data.name.replace('ck[', '').replace(']', '')
1337
+ let result = await connection.result({
1338
+ select: 'id,approval_status,approval_history',
1339
+ table: table,
1340
+ where: {
1341
+ id: id,
1342
+ },
1343
+ })
1344
+ let approval_status = result.approval_status || null
1345
+ let approval_history = result.approval_history || []
1346
+ if (approval_status == null) {
1347
+ canUpdate = true
1348
+ } else if (approval_status == 22) {
1349
+ canUpdate = true
1350
+ } else {
1351
+ if (+value > +approval_status) {
1352
+ canUpdate = true
1353
+ } else {
1354
+ canUpdate = false
1355
+ }
1356
+ }
1357
+ if (canUpdate) {
1358
+ approval_history.push({
1359
+ status: value,
1360
+ user_id: res.locals.userId,
1361
+ created_at: Util.now(),
1362
+ text: text,
1363
+ })
1364
+ let mydata = {
1365
+ approval_status: value,
1366
+ approval_history: Util.array_to_jsonb(approval_history),
1367
+ }
1368
+ if (+value > 1 && +value < 22) {
1369
+ mydata.lock = 1
1370
+ }
1371
+ if (+value === 22) {
1372
+ mydata.lock = 0
1373
+ }
1374
+ await connection.update({
1375
+ table: table,
1376
+ where: {
1377
+ id: id,
1378
+ },
1379
+ data: mydata,
1380
+ })
1381
+ } else {
1382
+ dataStatus.push(`${id} -> Status has been delivered`)
1383
+ }
1384
+ }
1385
+ } else {
1386
+ json = Util.flashError('No Data')
1387
+ }
1388
+ } else {
1389
+ json = Util.flashError('No Access')
1390
+ }
1391
+ json.dataStatus = dataStatus
1392
+ res.json(json)
1393
+ })
1394
+
1395
+ router.get('/addlock-fields', async (req, res) => {
1396
+ let tables = await connection.query(connection.showTables)
1397
+ for (const table of tables) {
1398
+ let tablename = table.tablename
1399
+ let sql = `ALTER TABLE ${tablename} ADD COLUMN "lock" smallint DEFAULT 0 `
1400
+ try {
1401
+ await connection.query(sql)
1402
+ } catch (e) {
1403
+ console.log(e)
1404
+ }
1405
+ }
1406
+ res.send(tables)
1407
+ })
1408
+
1409
+ router.get('/addlock-models', async (req, res) => {
1410
+ let text = ''
1411
+ let results = await connection.results({
1412
+ table: 'zfields',
1413
+ })
1414
+ for (const result of results) {
1415
+ let labels = result.labels
1416
+ let arr = Object.keys(labels)
1417
+ if (!Util.in_array('lock', arr)) {
1418
+ text += result.id + ' tidak ada'
1419
+ labels.lock = 'Lock/Unlock'
1420
+ try {
1421
+ await connection.update({
1422
+ table: 'zfields',
1423
+ data: {
1424
+ labels: JSON.stringify(labels),
1425
+ },
1426
+ where: {
1427
+ id: result.id,
1428
+ },
1429
+ })
1430
+ } catch (err) {
1431
+ console.log(err)
1432
+ }
1433
+ }
1434
+ }
1435
+
1436
+ res.send(text)
1437
+ })
1438
+
1439
+ router.get('/addapprovals-data', async (req, res) => {
1440
+ let tables = await connection.query(connection.showTables)
1441
+ for (const table of tables) {
1442
+ let tablename = table.tablename
1443
+ let sql = `ALTER TABLE ${tablename} ADD COLUMN "approval_status" smallint DEFAULT NULL`
1444
+ let sql2 = `ALTER TABLE ${tablename} ADD COLUMN "approval_history" jsonb[] DEFAULT NULL `
1445
+ try {
1446
+ await connection.query(sql)
1447
+ } catch (e) {
1448
+ console.log(e)
1449
+ }
1450
+ try {
1451
+ await connection.query(sql2)
1452
+ } catch (e) {
1453
+ console.log(e)
1454
+ }
1455
+ }
1456
+ res.send(tables)
1457
+ })
1458
+
1459
+ router.get('/addapproval-models', async (req, res) => {
1460
+ let text = ''
1461
+ let results = await connection.results({
1462
+ table: 'zfields',
1463
+ })
1464
+ for (const result of results) {
1465
+ let labels = result.labels
1466
+ let arr = Object.keys(labels)
1467
+ if (!Util.in_array('approval_status', arr)) {
1468
+ text += result.id + ' tidak ada'
1469
+ //approval_status_id : "Approval Status",
1470
+ labels.approval_status = 'Approval Status'
1471
+ labels.approval_history = 'Approval History'
1472
+ try {
1473
+ await connection.update({
1474
+ table: 'zfields',
1475
+ data: {
1476
+ labels: JSON.stringify(labels),
1477
+ },
1478
+ where: {
1479
+ id: result.id,
1480
+ },
1481
+ })
1482
+ } catch (err) {
1483
+ console.log(err)
1484
+ }
1485
+ }
1486
+ }
1487
+
1488
+ res.send(text)
1489
+ })
1490
+
1491
+ //post dropzone widget
1492
+ router.post('/zdropzone', async (req, res) => {
1493
+ try {
1494
+ let userId = res.locals.userId
1495
+ if (userId) {
1496
+ let dir = `${dirRoot}/public/zdropzone/${userId}`
1497
+ if (!fs.existsSync(dir)) {
1498
+ fs.mkdirSync(dir, { recursive: true })
1499
+ }
1500
+ let filename = req.files.file.name
1501
+ req.files.file.mv(dir + '/' + filename, function (err) {
1502
+ if (err) {
1503
+ return res.status(500).send(err + '')
1504
+ }
1505
+ })
1506
+ }
1507
+ res.json('ok')
1508
+ } catch (e) {
1509
+ console.log(e)
1510
+ res.status(500)
1511
+ res.send(e + '')
1512
+ }
1513
+ })
1514
+
1515
+ router.post('/zdropzone-remove', async (req, res) => {
1516
+ try {
1517
+ let userId = res.locals.userId
1518
+ let cacheName = req.body.cname.replace('ZUSER___ID', userId)
1519
+ let dir = `${dirRoot}/public/zdropzone/${userId}`
1520
+ if (!fs.existsSync(dir)) {
1521
+ fs.mkdirSync(dir, { recursive: true })
1522
+ }
1523
+ let filename = `${dirRoot}/public/zdropzone/${userId}/${req.body.file}`
1524
+ if (Util.fileExist(filename)) {
1525
+ await fs.unlink(filename)
1526
+ if (myCache.has(cacheName)) {
1527
+ arr = myCache.get(name)
1528
+ }
1529
+ arr = Util.arrayDelete(arr, body.file)
1530
+ myCache.set(name, arr)
1531
+ }
1532
+ res.json('ok')
1533
+ } catch (e) {
1534
+ console.log(e)
1535
+ res.status(500).send(e + '')
1536
+ }
1537
+ })
1538
+ router.post('/zdropzone-attributes', async (req, res) => {
1539
+ try {
1540
+ let userId = res.locals.userId
1541
+ let dir = `${dirRoot}/public/zdropzone/${userId}`
1542
+ if (!fs.existsSync(dir)) {
1543
+ fs.mkdirSync(dir, { recursive: true })
1544
+ }
1545
+ let body = req.body
1546
+ let category = body.category
1547
+ let name = `dropzone__${userId}__${body.table}__${body.field}__${body.type}`
1548
+ //dropzone__${res.locals.userId}__${table}__${key}__create
1549
+ let arr = []
1550
+ if (category === 'add') {
1551
+ if (myCache.has(name)) {
1552
+ arr = myCache.get(name)
1553
+ }
1554
+ arr.push(body.file)
1555
+ } else {
1556
+ name = `dropzone__${userId}__${body.table}__${body.field}__${body.type}`
1557
+ if (myCache.has(name)) {
1558
+ arr = myCache.get(name)
1559
+ }
1560
+ arr = Util.arrayDelete(arr, body.file)
1561
+ }
1562
+ myCache.set(name, arr)
1563
+ res.json('ok')
1564
+ } catch (e) {
1565
+ console.log(e)
1566
+ res.status(500).send(e + '')
1567
+ }
1568
+ })
1569
+
1570
+ router.post('/zhistory-data', async (req, res) => {
1571
+ let html = ''
1572
+ try {
1573
+ let id = req.body.id
1574
+ let table = req.body.table
1575
+ const relations = await zRoute.relations(req, res, table)
1576
+ const MYMODELS = zRoute.MYMODELS()
1577
+ const MYMODEL = MYMODELS[table]
1578
+ let results = await connection.results({
1579
+ table: 'zhistory',
1580
+ where: {
1581
+ module: table,
1582
+ module_id: id,
1583
+ },
1584
+ order_by: ['id asc'],
1585
+ })
1586
+ if (results.length > 0) {
1587
+ let users = {}
1588
+ if (myCache.has('users')) {
1589
+ users = myCache.get('users')
1590
+ } else {
1591
+ users = Util.arrayToObject(
1592
+ await connection.results({
1593
+ table: 'zuser',
1594
+ }),
1595
+ 'id'
1596
+ )
1597
+ myCache.set('users', users)
1598
+ }
1599
+ html = await zRoute.history(req, res, relations, id, MYMODEL, users, results)
1600
+ }
1601
+ res.json(html)
1602
+ } catch (e) {
1603
+ console.log(e)
1604
+ res.json(e + '')
1605
+ }
1606
+ })
1607
+
1608
+ router.get('/zdownloads-dropzone/:table/:field/:id', async (req, res) => {
1609
+ try {
1610
+ let table = req.params.table
1611
+ let field = req.params.field
1612
+ let id = req.params.id
1613
+ const room = res.locals.token
1614
+ let result = await connection.result({
1615
+ table: table,
1616
+ where: {
1617
+ id: id,
1618
+ },
1619
+ })
1620
+ let dir = `${dirRoot}/public/uploads/${table}/${field}/`
1621
+ let arr = []
1622
+ let files = result[field]
1623
+ for (const file of files) {
1624
+ if (Util.fileExist(dir + file)) {
1625
+ let filename = file.substring(13)
1626
+ arr.push({ path: dir + file, name: filename })
1627
+ io.to(room).emit('info', `Zip file ${filename}`)
1628
+ }
1629
+ }
1630
+ io.to(room).emit('info', `Zip file completed...`)
1631
+ res.zip(arr, `${field}_${table}_${id}.zip`)
1632
+ } catch (e) {
1633
+ console.log(e)
1634
+ res.json(e + '')
1635
+ }
1636
+ })
1637
+ module.exports = router