zet-lib 1.3.39 → 1.3.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +15 -15
- package/lib/ErrorWithCode.js +6 -6
- package/lib/Form.js +1020 -1019
- package/lib/Mail.js +68 -68
- package/lib/Modal.js +95 -95
- package/lib/Pool.js +437 -437
- package/lib/UI.js +7 -7
- package/lib/Util.js +1384 -1384
- package/lib/access.js +6 -6
- package/lib/cache.js +3 -3
- package/lib/connection.js +409 -409
- package/lib/debug.js +22 -22
- package/lib/index.js +36 -36
- package/lib/io.js +44 -44
- package/lib/languages/lang_en.js +125 -125
- package/lib/languages/lang_fr.js +125 -125
- package/lib/languages/lang_id.js +126 -126
- package/lib/languages/lang_jp.js +125 -125
- package/lib/moduleLib.js +661 -661
- package/lib/tableForm.js +10 -10
- package/lib/views/generator.ejs +598 -598
- package/lib/views/generator_layout.ejs +224 -224
- package/lib/views/generatorjs.ejs +927 -927
- package/lib/zAppRouter.js +1637 -1637
- package/lib/zCache.js +301 -301
- package/lib/zComponent.js +27 -27
- package/lib/zFn.js +58 -58
- package/lib/zFunction.js +20 -20
- package/lib/zGeneratorRouter.js +1641 -1641
- package/lib/zMenuRouter.js +556 -556
- package/lib/zPage.js +188 -188
- package/lib/zReport.js +982 -982
- package/lib/zRole.js +256 -256
- package/lib/zRoleRouter.js +609 -609
- package/lib/zRoute.js +5025 -5024
- package/lib/zTester.js +93 -93
- package/lib/zapp.js +65 -65
- package/lib/zdataTable.js +330 -330
- package/package.json +56 -56
package/lib/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
|