fixing
This commit is contained in:
505
src/controllers/event.ts
Normal file
505
src/controllers/event.ts
Normal file
@ -0,0 +1,505 @@
|
||||
import config from "config";
|
||||
// import { LogHikvision } from "entity";
|
||||
import { NextFunction, Response } from "express";
|
||||
import { Request } from 'express-jwt';
|
||||
import moment from "moment";
|
||||
import { ILogObj, Logger } from "tslog";
|
||||
import { ReturnHelper } from "../helpers/express/return";
|
||||
import { OrmHelper } from "../helpers/orm";
|
||||
// import Thirdparty from "../helpers/thirdparty";
|
||||
import { Language } from "../langs/lang";
|
||||
import { Between, Or } from "typeorm";
|
||||
import { AttendanceDoorInfo, AttendanceDoorLog } from "entity";
|
||||
import Joi from "joi";
|
||||
import { Employee } from "entity";
|
||||
|
||||
const log: Logger<ILogObj> = new Logger({ name: '[EventController]', type: 'pretty' });
|
||||
|
||||
export class EventController {
|
||||
static async indexold(req: Request, res: Response, next: NextFunction): Promise<Response> {
|
||||
/*
|
||||
#swagger.tags = ['Event']
|
||||
*/
|
||||
|
||||
try {
|
||||
|
||||
let param: any = req.body
|
||||
let dtPost: any = {}
|
||||
let data: any = null;
|
||||
const attendancedoorlogrepo = OrmHelper.DB.getRepository(AttendanceDoorLog);
|
||||
// console.log('Request : ', req)
|
||||
// console.log('param : ', param)
|
||||
let eventLog: any = {};
|
||||
let dateTime: any = null;
|
||||
let originalTimezone: string = null;
|
||||
let originalDate: string = null;
|
||||
let originalTime: string = null;
|
||||
if (param.event_log) {
|
||||
eventLog = JSON.parse(param.event_log)
|
||||
// console.log('eventLog:', eventLog)
|
||||
let employeeId = eventLog.AccessControllerEvent.employeeNoString
|
||||
if (!employeeId) throw { message: 'NO_EMPLOYEE_NO_STRING_ON_EVENT' }
|
||||
|
||||
|
||||
// 0|svc-hcmbridge | eventLog: {
|
||||
// 0|svc-hcmbridge | ipAddress: '172.16.110.242',
|
||||
// 0|svc-hcmbridge | ipv6Address: 'fe80::603:12ff:fe2e:4f8d',
|
||||
// 0|svc-hcmbridge | portNo: 3000,
|
||||
// 0|svc-hcmbridge | protocol: 'HTTP',
|
||||
// 0|svc-hcmbridge | macAddress: '04:03:12:2e:4f:8d',
|
||||
// 0|svc-hcmbridge | channelID: 1,
|
||||
// 0|svc-hcmbridge | dateTime: '2025-05-29T09:22:40+08:00',
|
||||
// 0|svc-hcmbridge | activePostCount: 1,
|
||||
// 0|svc-hcmbridge | eventType: 'AccessControllerEvent',
|
||||
// 0|svc-hcmbridge | eventState: 'active',
|
||||
// 0|svc-hcmbridge | eventDescription: 'Access Controller Event',
|
||||
// 0|svc-hcmbridge | AccessControllerEvent: {
|
||||
// 0|svc-hcmbridge | deviceName: 'DeviceOut',
|
||||
// 0|svc-hcmbridge | majorEventType: 5,
|
||||
// 0|svc-hcmbridge | subEventType: 22,
|
||||
// 0|svc-hcmbridge | cardReaderKind: 1,
|
||||
// 0|svc-hcmbridge | doorNo: 1,
|
||||
// 0|svc-hcmbridge | serialNo: 21403,
|
||||
// 0|svc-hcmbridge | currentVerifyMode: 'invalid',
|
||||
// 0|svc-hcmbridge | frontSerialNo: 21402,
|
||||
// 0|svc-hcmbridge | attendanceStatus: 'undefined',
|
||||
// 0|svc-hcmbridge | label: '',
|
||||
// 0|svc-hcmbridge | statusValue: 0,
|
||||
// 0|svc-hcmbridge | mask: 'unknown',
|
||||
// 0|svc-hcmbridge | purePwdVerifyEnable: true
|
||||
// 0|svc-hcmbridge | }
|
||||
dateTime = moment.parseZone(eventLog.dateTime);
|
||||
originalDate = dateTime.format("YYYY-MM-DD"); // Extract the date
|
||||
originalTime = dateTime.format("HH:mm:ss"); // Extract the time
|
||||
originalTimezone = dateTime.format("Z"); // Extract the timezone
|
||||
|
||||
dtPost = {
|
||||
"accessdoorid": employeeId,
|
||||
"datelogs": originalDate + ' ' + originalTime,
|
||||
"ipaddress": eventLog.ipAddress,
|
||||
"macaddress": eventLog.macAddress,
|
||||
"devicename": eventLog.AccessControllerEvent.deviceName,
|
||||
"doornumber": eventLog.AccessControllerEvent.doorNo,
|
||||
"iby": 'system',
|
||||
"idt": new Date()
|
||||
}
|
||||
// log.info('dtpost:', JSON.stringify(dtPost))
|
||||
// let url = config.get('service.hrms') + 'api/sync-attendance'
|
||||
// // log.info(url)
|
||||
// let result = await Thirdparty.PostData(url, dtPost)
|
||||
// // log.info('result:', JSON.stringify(result))
|
||||
|
||||
// const data = new LogHikvision()
|
||||
// data.incoming = JSON.stringify(param.event_log)
|
||||
// data.request = JSON.stringify(dtPost)
|
||||
// data.url = url
|
||||
// data.response = JSON.stringify(result)
|
||||
// await OrmHelper.DB.manager.save(data);
|
||||
|
||||
}
|
||||
const startOfToday = new Date();
|
||||
startOfToday.setHours(0, 0, 0, 0);
|
||||
|
||||
const endOfToday = new Date();
|
||||
endOfToday.setHours(23, 59, 59, 999);
|
||||
|
||||
// console.log('dtPost:', JSON.stringify(dtPost))
|
||||
if (eventLog?.AccessControllerEvent?.deviceName === 'DeviceOut') {
|
||||
const datalogsbefore = await attendancedoorlogrepo.findOne({
|
||||
where: {
|
||||
accessdoorid: dtPost.accessdoorid,
|
||||
devicename: "DeviceIn",
|
||||
datelogs: Between(startOfToday, endOfToday),
|
||||
},
|
||||
order: { datelogs: "DESC" },
|
||||
});
|
||||
// const datalogsbefore = await attendancedoorlogrepo
|
||||
// .createQueryBuilder("log")
|
||||
// .where("log.accessdoorid = :accessdoorid", { accessdoorid: dtPost.accessdoorid })
|
||||
// .andWhere("log.devicename = :devicename", { devicename: "DeviceOut" })
|
||||
// .andWhere("DATE(log.datelogs) = CURDATE()")
|
||||
// .orderBy("log._idx", "DESC")
|
||||
// .getOne();
|
||||
if (datalogsbefore != null && datalogsbefore !== undefined) {
|
||||
|
||||
// data = await attendancedoorlogrepo.save(dtPost);
|
||||
const previousDate = new Date(datalogsbefore.datelogs);
|
||||
const timezone = new Date(originalDate + ' ' + originalTime);
|
||||
const timeDiffSeconds = Math.floor((timezone.getTime() - previousDate.getTime()) / 1000);
|
||||
|
||||
|
||||
|
||||
// if(timeDiffSeconds<=50){
|
||||
if ((timeDiffSeconds <= 50)) {
|
||||
if (dtPost.accessdoorid == 34) {
|
||||
if (dtPost.ipaddress == '172.16.110.245') {
|
||||
console.log('datalogsbefore OUT:', datalogsbefore);
|
||||
console.log("Interval (OUT) in seconds:", timeDiffSeconds);
|
||||
}
|
||||
|
||||
}
|
||||
return ReturnHelper.successResponseAny(res, 500, "Internal server error", {});
|
||||
}
|
||||
// data = await attendancedoorlogrepo.update({ idx: datalogsbefore.idx }, { datelogs: originalDate + ' ' + originalTime });
|
||||
// }
|
||||
// else {
|
||||
// data = await attendancedoorlogrepo.save(dtPost);
|
||||
}
|
||||
|
||||
}
|
||||
// else {
|
||||
// // const datalogsbefore = await attendancedoorlogrepo.findOne({
|
||||
// // where: {
|
||||
// // accessdoorid: dtPost.accessdoorid,
|
||||
// // devicename: "DeviceOut",
|
||||
// // datelogs : new Date(),
|
||||
// // },
|
||||
// // order: { idx: "DESC" },
|
||||
// // });
|
||||
// // const datalogsbefore = await attendancedoorlogrepo
|
||||
// // .createQueryBuilder("log")
|
||||
// // .where("log.accessdoorid = :accessdoorid", { accessdoorid: dtPost.accessdoorid })
|
||||
// // .andWhere("log.devicename = :devicename", { devicename: "DeviceIn" })
|
||||
// // .andWhere("DATE(log.datelogs) = CURDATE()")
|
||||
// // .orderBy("log._idx", "DESC")
|
||||
// // .getOne();
|
||||
// const datalogsbefore = await attendancedoorlogrepo.findOne({
|
||||
// where: {
|
||||
// accessdoorid: dtPost.accessdoorid,
|
||||
// // devicename: "DeviceOut",
|
||||
// datelogs: Between(startOfToday, endOfToday),
|
||||
// },
|
||||
// order: { datelogs: "DESC" },
|
||||
// });
|
||||
// if (datalogsbefore != null && datalogsbefore !== undefined) {
|
||||
// const previousDate = new Date(datalogsbefore.datelogs);
|
||||
// const timezone = new Date(originalDate + ' ' + originalTime);
|
||||
// const timeDiffSeconds = Math.floor((timezone.getTime() - previousDate.getTime()) / 1000);
|
||||
// // if(timeDiffSeconds>=0 && timeDiffSeconds<=10){
|
||||
// // if(timeDiffSeconds<=50){
|
||||
// if ((datalogsbefore.devicename === 'DeviceOut' && timeDiffSeconds <= 50) || datalogsbefore.devicename === 'DeviceIn') {
|
||||
// console.log("Interval (IN) in seconds:", timeDiffSeconds);
|
||||
// return ReturnHelper.successResponseAny(res, 500, "Internal server error", {});
|
||||
// }
|
||||
// // console.log('datalogsbefore IN : ', datalogsbefore)
|
||||
// // data = await attendancedoorlogrepo.update({ idx: datalogsbefore.idx }, { datelogs: originalDate + ' ' + originalTime });
|
||||
// // }
|
||||
// // else {
|
||||
// // data = await attendancedoorlogrepo.save(dtPost);
|
||||
// }
|
||||
// // data = await attendancedoorlogrepo.save(dtPost);
|
||||
// }
|
||||
data = (dtPost ? await attendancedoorlogrepo.save(dtPost) : {});
|
||||
return ReturnHelper.successResponseAny(res, 200, Language.lang.success, data);
|
||||
|
||||
} catch (e: unknown) {
|
||||
log.error(e);
|
||||
const err = e as Error;
|
||||
|
||||
return ReturnHelper.successResponseAny(res, 200, Language.lang.failed, err.message);
|
||||
}
|
||||
}
|
||||
|
||||
static async index(req: Request, res: Response, next: NextFunction): Promise<Response> {
|
||||
/*
|
||||
#swagger.tags = ['Event']
|
||||
*/
|
||||
|
||||
try {
|
||||
|
||||
let param: any = req.body
|
||||
let dtPost: any = {}
|
||||
let data: any = null;
|
||||
// console.log('Request : ', req)
|
||||
// console.log('param : ', param.event_log)
|
||||
|
||||
const attendancedoorlogrepo = OrmHelper.DB.getRepository(AttendanceDoorLog);
|
||||
let eventLog: any = {};
|
||||
let dateTime: any = null;
|
||||
let originalTimezone: string = null;
|
||||
let originalDate: string = null;
|
||||
let originalTime: string = null;
|
||||
let employeeId: string = null;
|
||||
let formattedDuration = "00:00:00";
|
||||
// const today = moment().format('YYYY-MM-DD');
|
||||
let datalog = new AttendanceDoorLog();
|
||||
|
||||
// console.log(param);
|
||||
if (param.event_log) {
|
||||
eventLog = JSON.parse(param.event_log)
|
||||
console.log('eventLog:', eventLog)
|
||||
employeeId = eventLog.AccessControllerEvent.employeeNoString
|
||||
if (!employeeId) throw { message: 'NO_EMPLOYEE_NO_STRING_ON_EVENT' }
|
||||
|
||||
|
||||
// 0|svc-hcmbridge | eventLog: {
|
||||
// 0|svc-hcmbridge | ipAddress: '172.16.110.242',
|
||||
// 0|svc-hcmbridge | ipv6Address: 'fe80::603:12ff:fe2e:4f8d',
|
||||
// 0|svc-hcmbridge | portNo: 3000,
|
||||
// 0|svc-hcmbridge | protocol: 'HTTP',
|
||||
// 0|svc-hcmbridge | macAddress: '04:03:12:2e:4f:8d',
|
||||
// 0|svc-hcmbridge | channelID: 1,
|
||||
// 0|svc-hcmbridge | dateTime: '2025-05-29T09:22:40+08:00',
|
||||
// 0|svc-hcmbridge | activePostCount: 1,
|
||||
// 0|svc-hcmbridge | eventType: 'AccessControllerEvent',
|
||||
// 0|svc-hcmbridge | eventState: 'active',
|
||||
// 0|svc-hcmbridge | eventDescription: 'Access Controller Event',
|
||||
// 0|svc-hcmbridge | AccessControllerEvent: {
|
||||
// 0|svc-hcmbridge | deviceName: 'DeviceOut',
|
||||
// 0|svc-hcmbridge | majorEventType: 5,
|
||||
// 0|svc-hcmbridge | subEventType: 22,
|
||||
// 0|svc-hcmbridge | cardReaderKind: 1,
|
||||
// 0|svc-hcmbridge | doorNo: 1,
|
||||
// 0|svc-hcmbridge | serialNo: 21403,
|
||||
// 0|svc-hcmbridge | currentVerifyMode: 'invalid',
|
||||
// 0|svc-hcmbridge | frontSerialNo: 21402,
|
||||
// 0|svc-hcmbridge | attendanceStatus: 'undefined',
|
||||
// 0|svc-hcmbridge | label: '',
|
||||
// 0|svc-hcmbridge | statusValue: 0,
|
||||
// 0|svc-hcmbridge | mask: 'unknown',
|
||||
// 0|svc-hcmbridge | purePwdVerifyEnable: true
|
||||
// 0|svc-hcmbridge | }
|
||||
dateTime = moment.parseZone(eventLog.dateTime);
|
||||
originalDate = dateTime.format("YYYY-MM-DD"); // Extract the date
|
||||
originalTime = dateTime.format("HH:mm:ss"); // Extract the time
|
||||
originalTimezone = dateTime.format("Z"); // Extract the timezone
|
||||
// dtPost = {
|
||||
// "accessdoorid": employeeId,
|
||||
// "datelogs": originalDate + ' ' + originalTime,
|
||||
// "ipaddress": eventLog.ipAddress,
|
||||
// "macaddress": eventLog.macAddress,
|
||||
// "devicename": eventLog.AccessControllerEvent.deviceName,
|
||||
// "doornumber": eventLog.AccessControllerEvent.doorNo,
|
||||
// "duration" : formattedDuration,
|
||||
// "iby": 'system',
|
||||
// "idt": new Date()
|
||||
// }
|
||||
datalog.accessdoorid = parseInt(employeeId);
|
||||
datalog.datelogs = moment.parseZone(eventLog.dateTime).toDate();
|
||||
datalog.ipaddress = eventLog.ipAddress;
|
||||
datalog.macaddress = eventLog.macAddress;
|
||||
datalog.devicename = eventLog.AccessControllerEvent.deviceName;
|
||||
datalog.doornumber = eventLog.AccessControllerEvent.doorNo;
|
||||
datalog.duration = formattedDuration;
|
||||
datalog.iby = 'system';
|
||||
datalog.idt = new Date();
|
||||
// datalog.dura
|
||||
// log.info('dtpost:', JSON.stringify(dtPost))
|
||||
// let url = config.get('service.hrms') + 'api/sync-attendance'
|
||||
// // log.info(url)
|
||||
// let result = await Thirdparty.PostData(url, dtPost)
|
||||
// // log.info('result:', JSON.stringify(result))
|
||||
|
||||
// const data = new LogHikvision()
|
||||
// data.incoming = JSON.stringify(param.event_log)
|
||||
// data.request = JSON.stringify(dtPost)
|
||||
// data.url = url
|
||||
// data.response = JSON.stringify(result)
|
||||
// await OrmHelper.DB.manager.save(data);
|
||||
|
||||
}
|
||||
const startOfToday = new Date();
|
||||
startOfToday.setHours(0, 0, 0, 0);
|
||||
|
||||
const endOfToday = new Date();
|
||||
endOfToday.setHours(23, 59, 59, 999);
|
||||
|
||||
// console.log(dtPost);
|
||||
if (employeeId == '34') {
|
||||
console.log('dtPost: ', JSON.stringify(dtPost))
|
||||
}
|
||||
|
||||
if (eventLog?.AccessControllerEvent?.deviceName === 'DeviceIn') {
|
||||
const datalogsbefore = await attendancedoorlogrepo
|
||||
.createQueryBuilder("log")
|
||||
.where("log.accessdoorid = :accessdoorid", { accessdoorid: datalog.accessdoorid })
|
||||
.andWhere("log.devicename = :devicename", { devicename: "DeviceOut" })
|
||||
.andWhere("DATE(log.datelogs) = CURDATE()")
|
||||
.orderBy("log._idx", "DESC")
|
||||
.getOne();
|
||||
if (datalogsbefore != null && datalogsbefore !== undefined) {
|
||||
let dateTimeIn = moment.parseZone(eventLog.dateTime);
|
||||
let dateTimeOut = moment(datalogsbefore.datelogs);
|
||||
|
||||
let duration = moment.duration(dateTimeIn.diff(dateTimeOut));
|
||||
formattedDuration = moment.utc(duration.asMilliseconds()).format("HH:mm:ss");
|
||||
datalog.duration = formattedDuration;
|
||||
}
|
||||
}
|
||||
// if (eventLog?.AccessControllerEvent?.deviceName === 'DeviceOut') {
|
||||
// // console.log("line 300 : ",dtPost);
|
||||
// // const datalogsbefore = await attendancedoorlogrepo.findOne({
|
||||
// // where: {
|
||||
// // accessdoorid: dtPost.accessdoorid,
|
||||
// // devicename: "DeviceIn",
|
||||
// // datelogs: Between(startOfToday, endOfToday),
|
||||
// // },
|
||||
// // order: { datelogs: "DESC" },
|
||||
// // });
|
||||
// const datalogsbefore = await attendancedoorlogrepo.createQueryBuilder("tbl_attendancedoorlogs")
|
||||
// .where("DATE_FORMAT(tbl_attendancedoorlogs.datelogs, '%Y-%m-%d')= :d", { d: today.toString() })
|
||||
// .andWhere("accessdoorid= :a", { a: employeeId })
|
||||
// .andWhere("devicename= :b", { b: "DeviceIn" })
|
||||
// .orderBy("tbl_attendancedoorlogs.datelogs", "DESC")
|
||||
// .getOne()
|
||||
// // const datalogsbefore = await attendancedoorlogrepo
|
||||
// // .createQueryBuilder("log")
|
||||
// // .where("log.accessdoorid = :accessdoorid", { accessdoorid: dtPost.accessdoorid })
|
||||
// // .andWhere("log.devicename = :devicename", { devicename: "DeviceOut" })
|
||||
// // .andWhere("DATE(log.datelogs) = CURDATE()")
|
||||
// // .orderBy("log._idx", "DESC")
|
||||
// // .getOne();
|
||||
// if (datalogsbefore != null && datalogsbefore !== undefined) {
|
||||
|
||||
// // data = await attendancedoorlogrepo.save(dtPost);
|
||||
// const previousDate = new Date(datalogsbefore.datelogs);
|
||||
// const timezone = new Date(originalDate + ' ' + originalTime);
|
||||
// const timeDiffSeconds = Math.floor((timezone.getTime() - previousDate.getTime()) / 1000);
|
||||
|
||||
// if(employeeId==="34"){
|
||||
// console.log('Accessdoor Id : ',employeeId,' ',datalogsbefore.devicename,' Prev Time : ',previousDate,' TimeDoor : ',timezone,' ===> Time Diff : ', timeDiffSeconds);
|
||||
// }
|
||||
// // if(timeDiffSeconds<=50){
|
||||
// // if ((timeDiffSeconds <= 50)) {
|
||||
|
||||
// if (datalogsbefore.devicename == 'DeviceIn'&&(timeDiffSeconds>50)) {
|
||||
// // console.log("Accessdoorid : ", employeeId, ", dates : ", timezone, ", dates checkin before : ", previousDate, ", diff second : ", timeDiffSeconds)
|
||||
// // const datetimelogs = new Date(`${originalDate}T${originalTime}`);
|
||||
// // data = await attendancedoorlogrepo.save(dtPost);
|
||||
// // return ReturnHelper.successResponseAny(res, 200, Language.lang.success, data);
|
||||
// }
|
||||
// else{
|
||||
// // console.log("interval : ",timeDiffSeconds);
|
||||
// // if ((timeDiffSeconds >= 0 && timeDiffSeconds <= 7)){
|
||||
// // return ReturnHelper.successResponseAny(res, 500, "Internal server error", {});
|
||||
// // }
|
||||
// }
|
||||
// }
|
||||
|
||||
// }
|
||||
// console.log(datalog);
|
||||
data = (datalog ? await attendancedoorlogrepo.save(datalog) : {});
|
||||
console.log(data);
|
||||
return ReturnHelper.successResponseAny(res, 200, Language.lang.success, data);
|
||||
|
||||
} catch (e: unknown) {
|
||||
log.error(e);
|
||||
const err = e as Error;
|
||||
|
||||
return ReturnHelper.successResponseAny(res, 200, Language.lang.failed, err.message);
|
||||
}
|
||||
}
|
||||
|
||||
static async logrekon(req: Request, res: Response, next: NextFunction): Promise<Response> {
|
||||
/*
|
||||
#swagger.tags = ['Event']
|
||||
#swagger.parameters['datelogs'] = {
|
||||
description: 'Entry Date Logs',
|
||||
in: 'query',
|
||||
type: 'string'
|
||||
}
|
||||
*/
|
||||
|
||||
try {
|
||||
// let data: any = null;
|
||||
const schema = Joi.object().keys({
|
||||
datelogs: Joi.string().required().label('Date Logs'),
|
||||
});
|
||||
const param = await schema.validateAsync(req.query);
|
||||
const employeerepo = OrmHelper.DB.getRepository(Employee);
|
||||
const attendancedoorinfo = OrmHelper.DB.getRepository(AttendanceDoorInfo);
|
||||
const data = await employeerepo.createQueryBuilder("tbl_employee")
|
||||
.innerJoin(
|
||||
"tbl_attendancedoorlogs",
|
||||
"attlog",
|
||||
"tbl_employee.accessdoorid = attlog.accessdoorid"
|
||||
)
|
||||
.select("attlog.accessdoorid", "accessdoorid")
|
||||
.addSelect("tbl_employee.nik", "nik")
|
||||
.addSelect("tbl_employee.employeename", "employeename")
|
||||
.addSelect("DATE_FORMAT(attlog.datelogs, '%Y-%m-%d')", "logdate")
|
||||
.addSelect(`COUNT(CASE WHEN attlog.devicename = 'DeviceIn' THEN 1 END)`, "total_in")
|
||||
.addSelect(`COUNT(CASE WHEN attlog.devicename = 'DeviceOut' THEN 1 END)`, "total_out")
|
||||
|
||||
// .select([
|
||||
// "tbl_employee._idx AS idx",
|
||||
// "tbl_employee.accessdoorid AS accessdoorid",
|
||||
// "tbl_employee.nik AS nik",
|
||||
// "tbl_employee.employeename AS employeename",
|
||||
// "DATE_FORMAT(attlog.datelogs, '%Y-%m-%d') AS log_date",
|
||||
// "attlog.devicename AS deviceevent",
|
||||
// "COUNT(attlog.devicename) AS total_event"
|
||||
// ])
|
||||
.where("DATE_FORMAT(attlog.datelogs, '%Y-%m-%d') = :d", { d: param.datelogs })
|
||||
// .andWhere("tbl_employee.accessdoorid = :e", { e: "219" })
|
||||
.groupBy("tbl_employee.accessdoorid")
|
||||
.addGroupBy("tbl_employee.nik")
|
||||
.addGroupBy("tbl_employee.employeename")
|
||||
.addGroupBy("DATE_FORMAT(attlog.datelogs, '%Y-%m-%d')")
|
||||
.orderBy("accessdoorid", "ASC")
|
||||
.getRawMany();
|
||||
|
||||
// console.log(data);
|
||||
for (const row of data) {
|
||||
const doorinfo = await attendancedoorinfo.createQueryBuilder("tbl_attendancedoorinfo")
|
||||
.where("DATE_FORMAT(tbl_attendancedoorinfo.datelogs, '%Y-%m-%d')= :d", { d: param.datelogs })
|
||||
.andWhere("accessdoorid= :a", { a: row.accessdoorid })
|
||||
.getOne()
|
||||
let datadoorinfo: any = {};
|
||||
// console.log(doorinfo);
|
||||
if (doorinfo == null) {
|
||||
datadoorinfo = {
|
||||
"accessdoorid": row.accessdoorid,
|
||||
"nik": row.nik,
|
||||
"employeename": row.employeename,
|
||||
"datelogs": param.datelogs,
|
||||
"totalin": row.total_in,
|
||||
"totalout": row.total_out,
|
||||
"iby": 'sys',
|
||||
"idt": new Date()
|
||||
}
|
||||
await attendancedoorinfo.save(datadoorinfo);
|
||||
}
|
||||
else {
|
||||
datadoorinfo = {
|
||||
"accessdoorid": row.accessdoorid,
|
||||
"nik": row.nik,
|
||||
"employeename": row.employeename,
|
||||
"datelogs": param.datelogs,
|
||||
"totalin": row.total_in,
|
||||
"totalout": row.total_out,
|
||||
"uby": "sys",
|
||||
"udt": new Date()
|
||||
}
|
||||
// console.log("update ; ", datadoorinfo);
|
||||
// console.log("doorinfo ; ", doorinfo);
|
||||
await attendancedoorinfo.update({ idx: doorinfo.idx }, datadoorinfo)
|
||||
// if (row.deviceevent == 'deviceIn') {
|
||||
// data['totalin'] = row.total_event + doorinfo.totalin;
|
||||
// }
|
||||
// else {
|
||||
// data['totalout'] = row.total_event + ;
|
||||
// }
|
||||
}
|
||||
// console.log("Access Door ID:", row.accessdoorid);
|
||||
// console.log("Employee Name:", row.employeename);
|
||||
// console.log("Log Date:", row.log_date);
|
||||
// console.log("Device Event:", row.deviceevent);
|
||||
// console.log("Total Events:", row.total_event);
|
||||
// console.log("-----");
|
||||
}
|
||||
// data.map(row => ({
|
||||
// ...row,
|
||||
// log_date: (row.log_date).toISOString().split('T')[0],
|
||||
// }));
|
||||
|
||||
return ReturnHelper.successResponseAny(res, 200, Language.lang.success, data);
|
||||
|
||||
} catch (e: unknown) {
|
||||
log.error(e);
|
||||
const err = e as Error;
|
||||
|
||||
return ReturnHelper.successResponseAny(res, 200, Language.lang.failed, err.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
514
src/controllers/eventold.ts
Normal file
514
src/controllers/eventold.ts
Normal file
@ -0,0 +1,514 @@
|
||||
import config from "config";
|
||||
// import { LogHikvision } from "entity";
|
||||
import { NextFunction, Response } from "express";
|
||||
import { Request } from 'express-jwt';
|
||||
import moment from "moment";
|
||||
import { ILogObj, Logger } from "tslog";
|
||||
import { ReturnHelper } from "../helpers/express/return";
|
||||
import { OrmHelper } from "../helpers/orm";
|
||||
// import Thirdparty from "../helpers/thirdparty";
|
||||
import { Language } from "../langs/lang";
|
||||
import { Between, Or } from "typeorm";
|
||||
import { AttendanceDoorInfo, AttendanceDoorLog } from "entity";
|
||||
import Joi from "joi";
|
||||
import { Employee } from "entity";
|
||||
|
||||
const log: Logger<ILogObj> = new Logger({ name: '[EventController]', type: 'pretty' });
|
||||
|
||||
export class EventController {
|
||||
static async indexold(req: Request, res: Response, next: NextFunction): Promise<Response> {
|
||||
/*
|
||||
#swagger.tags = ['Event']
|
||||
*/
|
||||
|
||||
try {
|
||||
|
||||
let param: any = req.body
|
||||
let dtPost: any = {}
|
||||
let data: any = null;
|
||||
const attendancedoorlogrepo = OrmHelper.DB.getRepository(AttendanceDoorLog);
|
||||
// console.log('Request : ', req)
|
||||
// console.log('param : ', param)
|
||||
let eventLog: any = {};
|
||||
let dateTime: any = null;
|
||||
let originalTimezone: string = null;
|
||||
let originalDate: string = null;
|
||||
let originalTime: string = null;
|
||||
if (param.event_log) {
|
||||
eventLog = JSON.parse(param.event_log)
|
||||
// console.log('eventLog:', eventLog)
|
||||
let employeeId = eventLog.AccessControllerEvent.employeeNoString
|
||||
if (!employeeId) throw { message: 'NO_EMPLOYEE_NO_STRING_ON_EVENT' }
|
||||
|
||||
|
||||
// 0|svc-hcmbridge | eventLog: {
|
||||
// 0|svc-hcmbridge | ipAddress: '172.16.110.242',
|
||||
// 0|svc-hcmbridge | ipv6Address: 'fe80::603:12ff:fe2e:4f8d',
|
||||
// 0|svc-hcmbridge | portNo: 3000,
|
||||
// 0|svc-hcmbridge | protocol: 'HTTP',
|
||||
// 0|svc-hcmbridge | macAddress: '04:03:12:2e:4f:8d',
|
||||
// 0|svc-hcmbridge | channelID: 1,
|
||||
// 0|svc-hcmbridge | dateTime: '2025-05-29T09:22:40+08:00',
|
||||
// 0|svc-hcmbridge | activePostCount: 1,
|
||||
// 0|svc-hcmbridge | eventType: 'AccessControllerEvent',
|
||||
// 0|svc-hcmbridge | eventState: 'active',
|
||||
// 0|svc-hcmbridge | eventDescription: 'Access Controller Event',
|
||||
// 0|svc-hcmbridge | AccessControllerEvent: {
|
||||
// 0|svc-hcmbridge | deviceName: 'DeviceOut',
|
||||
// 0|svc-hcmbridge | majorEventType: 5,
|
||||
// 0|svc-hcmbridge | subEventType: 22,
|
||||
// 0|svc-hcmbridge | cardReaderKind: 1,
|
||||
// 0|svc-hcmbridge | doorNo: 1,
|
||||
// 0|svc-hcmbridge | serialNo: 21403,
|
||||
// 0|svc-hcmbridge | currentVerifyMode: 'invalid',
|
||||
// 0|svc-hcmbridge | frontSerialNo: 21402,
|
||||
// 0|svc-hcmbridge | attendanceStatus: 'undefined',
|
||||
// 0|svc-hcmbridge | label: '',
|
||||
// 0|svc-hcmbridge | statusValue: 0,
|
||||
// 0|svc-hcmbridge | mask: 'unknown',
|
||||
// 0|svc-hcmbridge | purePwdVerifyEnable: true
|
||||
// 0|svc-hcmbridge | }
|
||||
dateTime = moment.parseZone(eventLog.dateTime);
|
||||
originalDate = dateTime.format("YYYY-MM-DD"); // Extract the date
|
||||
originalTime = dateTime.format("HH:mm:ss"); // Extract the time
|
||||
originalTimezone = dateTime.format("Z"); // Extract the timezone
|
||||
|
||||
dtPost = {
|
||||
"accessdoorid": employeeId,
|
||||
"datelogs": originalDate + ' ' + originalTime,
|
||||
"ipaddress": eventLog.ipAddress,
|
||||
"macaddress": eventLog.macAddress,
|
||||
"devicename": eventLog.AccessControllerEvent.deviceName,
|
||||
"doornumber": eventLog.AccessControllerEvent.doorNo,
|
||||
"iby": 'system',
|
||||
"idt": new Date()
|
||||
}
|
||||
// log.info('dtpost:', JSON.stringify(dtPost))
|
||||
// let url = config.get('service.hrms') + 'api/sync-attendance'
|
||||
// // log.info(url)
|
||||
// let result = await Thirdparty.PostData(url, dtPost)
|
||||
// // log.info('result:', JSON.stringify(result))
|
||||
|
||||
// const data = new LogHikvision()
|
||||
// data.incoming = JSON.stringify(param.event_log)
|
||||
// data.request = JSON.stringify(dtPost)
|
||||
// data.url = url
|
||||
// data.response = JSON.stringify(result)
|
||||
// await OrmHelper.DB.manager.save(data);
|
||||
|
||||
}
|
||||
const startOfToday = new Date();
|
||||
startOfToday.setHours(0, 0, 0, 0);
|
||||
|
||||
const endOfToday = new Date();
|
||||
endOfToday.setHours(23, 59, 59, 999);
|
||||
|
||||
// console.log('dtPost:', JSON.stringify(dtPost))
|
||||
if (eventLog?.AccessControllerEvent?.deviceName === 'DeviceOut') {
|
||||
const datalogsbefore = await attendancedoorlogrepo.findOne({
|
||||
where: {
|
||||
accessdoorid: dtPost.accessdoorid,
|
||||
devicename: "DeviceIn",
|
||||
datelogs: Between(startOfToday, endOfToday),
|
||||
},
|
||||
order: { datelogs: "DESC" },
|
||||
});
|
||||
// const datalogsbefore = await attendancedoorlogrepo
|
||||
// .createQueryBuilder("log")
|
||||
// .where("log.accessdoorid = :accessdoorid", { accessdoorid: dtPost.accessdoorid })
|
||||
// .andWhere("log.devicename = :devicename", { devicename: "DeviceOut" })
|
||||
// .andWhere("DATE(log.datelogs) = CURDATE()")
|
||||
// .orderBy("log._idx", "DESC")
|
||||
// .getOne();
|
||||
if (datalogsbefore != null && datalogsbefore !== undefined) {
|
||||
|
||||
// data = await attendancedoorlogrepo.save(dtPost);
|
||||
const previousDate = new Date(datalogsbefore.datelogs);
|
||||
const timezone = new Date(originalDate + ' ' + originalTime);
|
||||
const timeDiffSeconds = Math.floor((timezone.getTime() - previousDate.getTime()) / 1000);
|
||||
|
||||
|
||||
|
||||
// if(timeDiffSeconds<=50){
|
||||
if ((timeDiffSeconds <= 50)) {
|
||||
if (dtPost.accessdoorid == 34) {
|
||||
if (dtPost.ipaddress == '172.16.110.245') {
|
||||
console.log('datalogsbefore OUT:', datalogsbefore);
|
||||
console.log("Interval (OUT) in seconds:", timeDiffSeconds);
|
||||
}
|
||||
|
||||
}
|
||||
return ReturnHelper.successResponseAny(res, 500, "Internal server error", {});
|
||||
}
|
||||
// data = await attendancedoorlogrepo.update({ idx: datalogsbefore.idx }, { datelogs: originalDate + ' ' + originalTime });
|
||||
// }
|
||||
// else {
|
||||
// data = await attendancedoorlogrepo.save(dtPost);
|
||||
}
|
||||
|
||||
}
|
||||
// else {
|
||||
// // const datalogsbefore = await attendancedoorlogrepo.findOne({
|
||||
// // where: {
|
||||
// // accessdoorid: dtPost.accessdoorid,
|
||||
// // devicename: "DeviceOut",
|
||||
// // datelogs : new Date(),
|
||||
// // },
|
||||
// // order: { idx: "DESC" },
|
||||
// // });
|
||||
// // const datalogsbefore = await attendancedoorlogrepo
|
||||
// // .createQueryBuilder("log")
|
||||
// // .where("log.accessdoorid = :accessdoorid", { accessdoorid: dtPost.accessdoorid })
|
||||
// // .andWhere("log.devicename = :devicename", { devicename: "DeviceIn" })
|
||||
// // .andWhere("DATE(log.datelogs) = CURDATE()")
|
||||
// // .orderBy("log._idx", "DESC")
|
||||
// // .getOne();
|
||||
// const datalogsbefore = await attendancedoorlogrepo.findOne({
|
||||
// where: {
|
||||
// accessdoorid: dtPost.accessdoorid,
|
||||
// // devicename: "DeviceOut",
|
||||
// datelogs: Between(startOfToday, endOfToday),
|
||||
// },
|
||||
// order: { datelogs: "DESC" },
|
||||
// });
|
||||
// if (datalogsbefore != null && datalogsbefore !== undefined) {
|
||||
// const previousDate = new Date(datalogsbefore.datelogs);
|
||||
// const timezone = new Date(originalDate + ' ' + originalTime);
|
||||
// const timeDiffSeconds = Math.floor((timezone.getTime() - previousDate.getTime()) / 1000);
|
||||
// // if(timeDiffSeconds>=0 && timeDiffSeconds<=10){
|
||||
// // if(timeDiffSeconds<=50){
|
||||
// if ((datalogsbefore.devicename === 'DeviceOut' && timeDiffSeconds <= 50) || datalogsbefore.devicename === 'DeviceIn') {
|
||||
// console.log("Interval (IN) in seconds:", timeDiffSeconds);
|
||||
// return ReturnHelper.successResponseAny(res, 500, "Internal server error", {});
|
||||
// }
|
||||
// // console.log('datalogsbefore IN : ', datalogsbefore)
|
||||
// // data = await attendancedoorlogrepo.update({ idx: datalogsbefore.idx }, { datelogs: originalDate + ' ' + originalTime });
|
||||
// // }
|
||||
// // else {
|
||||
// // data = await attendancedoorlogrepo.save(dtPost);
|
||||
// }
|
||||
// // data = await attendancedoorlogrepo.save(dtPost);
|
||||
// }
|
||||
data = (dtPost ? await attendancedoorlogrepo.save(dtPost) : {});
|
||||
return ReturnHelper.successResponseAny(res, 200, Language.lang.success, data);
|
||||
|
||||
} catch (e: unknown) {
|
||||
log.error(e);
|
||||
const err = e as Error;
|
||||
|
||||
return ReturnHelper.successResponseAny(res, 200, Language.lang.failed, err.message);
|
||||
}
|
||||
}
|
||||
|
||||
static async index(req: Request, res: Response, next: NextFunction): Promise<Response> {
|
||||
/*
|
||||
#swagger.tags = ['Event']
|
||||
*/
|
||||
|
||||
try {
|
||||
|
||||
let param: any = req.body
|
||||
let dtPost: any = {}
|
||||
let data: any = null;
|
||||
// console.log('Request : ', req)
|
||||
// console.log('param : ', param.event_log)
|
||||
|
||||
const attendancedoorlogrepo = OrmHelper.DB.getRepository(AttendanceDoorLog);
|
||||
let eventLog: any = {};
|
||||
let dateTime: any = null;
|
||||
let originalTimezone: string = null;
|
||||
let originalDate: string = null;
|
||||
let originalTime: string = null;
|
||||
let employeeId: string = null;
|
||||
const today = moment().format('YYYY-MM-DD');
|
||||
// console.log(param);
|
||||
if (param.event_log) {
|
||||
eventLog = JSON.parse(param.event_log)
|
||||
// console.log('eventLog:', eventLog)
|
||||
employeeId = eventLog.AccessControllerEvent.employeeNoString
|
||||
if (!employeeId) throw { message: 'NO_EMPLOYEE_NO_STRING_ON_EVENT' }
|
||||
|
||||
|
||||
// 0|svc-hcmbridge | eventLog: {
|
||||
// 0|svc-hcmbridge | ipAddress: '172.16.110.242',
|
||||
// 0|svc-hcmbridge | ipv6Address: 'fe80::603:12ff:fe2e:4f8d',
|
||||
// 0|svc-hcmbridge | portNo: 3000,
|
||||
// 0|svc-hcmbridge | protocol: 'HTTP',
|
||||
// 0|svc-hcmbridge | macAddress: '04:03:12:2e:4f:8d',
|
||||
// 0|svc-hcmbridge | channelID: 1,
|
||||
// 0|svc-hcmbridge | dateTime: '2025-05-29T09:22:40+08:00',
|
||||
// 0|svc-hcmbridge | activePostCount: 1,
|
||||
// 0|svc-hcmbridge | eventType: 'AccessControllerEvent',
|
||||
// 0|svc-hcmbridge | eventState: 'active',
|
||||
// 0|svc-hcmbridge | eventDescription: 'Access Controller Event',
|
||||
// 0|svc-hcmbridge | AccessControllerEvent: {
|
||||
// 0|svc-hcmbridge | deviceName: 'DeviceOut',
|
||||
// 0|svc-hcmbridge | majorEventType: 5,
|
||||
// 0|svc-hcmbridge | subEventType: 22,
|
||||
// 0|svc-hcmbridge | cardReaderKind: 1,
|
||||
// 0|svc-hcmbridge | doorNo: 1,
|
||||
// 0|svc-hcmbridge | serialNo: 21403,
|
||||
// 0|svc-hcmbridge | currentVerifyMode: 'invalid',
|
||||
// 0|svc-hcmbridge | frontSerialNo: 21402,
|
||||
// 0|svc-hcmbridge | attendanceStatus: 'undefined',
|
||||
// 0|svc-hcmbridge | label: '',
|
||||
// 0|svc-hcmbridge | statusValue: 0,
|
||||
// 0|svc-hcmbridge | mask: 'unknown',
|
||||
// 0|svc-hcmbridge | purePwdVerifyEnable: true
|
||||
// 0|svc-hcmbridge | }
|
||||
dateTime = moment.parseZone(eventLog.dateTime);
|
||||
originalDate = dateTime.format("YYYY-MM-DD"); // Extract the date
|
||||
originalTime = dateTime.format("HH:mm:ss"); // Extract the time
|
||||
originalTimezone = dateTime.format("Z"); // Extract the timezone
|
||||
|
||||
dtPost = {
|
||||
"accessdoorid": employeeId,
|
||||
"datelogs": originalDate + ' ' + originalTime,
|
||||
"ipaddress": eventLog.ipAddress,
|
||||
"macaddress": eventLog.macAddress,
|
||||
"devicename": eventLog.AccessControllerEvent.deviceName,
|
||||
"doornumber": eventLog.AccessControllerEvent.doorNo,
|
||||
"iby": 'system',
|
||||
"idt": new Date()
|
||||
}
|
||||
// log.info('dtpost:', JSON.stringify(dtPost))
|
||||
// let url = config.get('service.hrms') + 'api/sync-attendance'
|
||||
// // log.info(url)
|
||||
// let result = await Thirdparty.PostData(url, dtPost)
|
||||
// // log.info('result:', JSON.stringify(result))
|
||||
|
||||
// const data = new LogHikvision()
|
||||
// data.incoming = JSON.stringify(param.event_log)
|
||||
// data.request = JSON.stringify(dtPost)
|
||||
// data.url = url
|
||||
// data.response = JSON.stringify(result)
|
||||
// await OrmHelper.DB.manager.save(data);
|
||||
|
||||
}
|
||||
const startOfToday = new Date();
|
||||
startOfToday.setHours(0, 0, 0, 0);
|
||||
|
||||
const endOfToday = new Date();
|
||||
endOfToday.setHours(23, 59, 59, 999);
|
||||
|
||||
// console.log(dtPost);
|
||||
// if (eventLog.ipAddress == '172.16.110.245' && employeeId == '34') {
|
||||
// console.log('dtPost: ', JSON.stringify(dtPost))
|
||||
// }
|
||||
|
||||
if (eventLog?.AccessControllerEvent?.deviceName === 'DeviceOut') {
|
||||
// console.log(dtPost);
|
||||
// const datalogsbefore = await attendancedoorlogrepo.findOne({
|
||||
// where: {
|
||||
// accessdoorid: dtPost.accessdoorid,
|
||||
// devicename: "DeviceIn",
|
||||
// datelogs: Between(startOfToday, endOfToday),
|
||||
// },
|
||||
// order: { datelogs: "DESC" },
|
||||
// });
|
||||
const datalogsbefore = await attendancedoorlogrepo.createQueryBuilder("tbl_attendancedoorlogs")
|
||||
.where("DATE_FORMAT(tbl_attendancedoorlogs.datelogs, '%Y-%m-%d')= :d", { d: today })
|
||||
.andWhere("accessdoorid= :a", { a: employeeId })
|
||||
.andWhere("devicename= :b", { b: "DeviceIn" })
|
||||
.orderBy("tbl_attendancedoorlogs.datelogs", "DESC")
|
||||
.getOne()
|
||||
// const datalogsbefore = await attendancedoorlogrepo
|
||||
// .createQueryBuilder("log")
|
||||
// .where("log.accessdoorid = :accessdoorid", { accessdoorid: dtPost.accessdoorid })
|
||||
// .andWhere("log.devicename = :devicename", { devicename: "DeviceOut" })
|
||||
// .andWhere("DATE(log.datelogs) = CURDATE()")
|
||||
// .orderBy("log._idx", "DESC")
|
||||
// .getOne();
|
||||
if (datalogsbefore != null && datalogsbefore !== undefined) {
|
||||
|
||||
// data = await attendancedoorlogrepo.save(dtPost);
|
||||
const previousDate = new Date(datalogsbefore.datelogs);
|
||||
const timezone = new Date(originalDate + ' ' + originalTime);
|
||||
const timeDiffSeconds = Math.floor((timezone.getTime() - previousDate.getTime()) / 1000);
|
||||
|
||||
// if(timeDiffSeconds<=50){
|
||||
if ((timeDiffSeconds <= 50)) {
|
||||
console.log("Accessdoorid : ", employeeId, ", dates : ", timezone, ", dates checkin before : ", previousDate, ", diff second : ", timeDiffSeconds)
|
||||
|
||||
// if (dtPost.accessdoorid == 34) {
|
||||
// if (dtPost.ipaddress == '172.16.110.245') {
|
||||
// console.log('datalogsbefore OUT:', datalogsbefore);
|
||||
// console.log("Interval (OUT) in seconds:", timeDiffSeconds);
|
||||
// }
|
||||
|
||||
// }
|
||||
return ReturnHelper.successResponseAny(res, 500, "Internal server error", {});
|
||||
}
|
||||
// data = await attendancedoorlogrepo.update({ idx: datalogsbefore.idx }, { datelogs: originalDate + ' ' + originalTime });
|
||||
// }
|
||||
// else {
|
||||
// data = await attendancedoorlogrepo.save(dtPost);
|
||||
}
|
||||
|
||||
}
|
||||
// else {
|
||||
// // const datalogsbefore = await attendancedoorlogrepo.findOne({
|
||||
// // where: {
|
||||
// // accessdoorid: dtPost.accessdoorid,
|
||||
// // devicename: "DeviceOut",
|
||||
// // datelogs : new Date(),
|
||||
// // },
|
||||
// // order: { idx: "DESC" },
|
||||
// // });
|
||||
// // const datalogsbefore = await attendancedoorlogrepo
|
||||
// // .createQueryBuilder("log")
|
||||
// // .where("log.accessdoorid = :accessdoorid", { accessdoorid: dtPost.accessdoorid })
|
||||
// // .andWhere("log.devicename = :devicename", { devicename: "DeviceIn" })
|
||||
// // .andWhere("DATE(log.datelogs) = CURDATE()")
|
||||
// // .orderBy("log._idx", "DESC")
|
||||
// // .getOne();
|
||||
// const datalogsbefore = await attendancedoorlogrepo.findOne({
|
||||
// where: {
|
||||
// accessdoorid: dtPost.accessdoorid,
|
||||
// // devicename: "DeviceOut",
|
||||
// datelogs: Between(startOfToday, endOfToday),
|
||||
// },
|
||||
// order: { datelogs: "DESC" },
|
||||
// });
|
||||
// if (datalogsbefore != null && datalogsbefore !== undefined) {
|
||||
// const previousDate = new Date(datalogsbefore.datelogs);
|
||||
// const timezone = new Date(originalDate + ' ' + originalTime);
|
||||
// const timeDiffSeconds = Math.floor((timezone.getTime() - previousDate.getTime()) / 1000);
|
||||
// // if(timeDiffSeconds>=0 && timeDiffSeconds<=10){
|
||||
// // if(timeDiffSeconds<=50){
|
||||
// if ((datalogsbefore.devicename === 'DeviceOut' && timeDiffSeconds <= 50) || datalogsbefore.devicename === 'DeviceIn') {
|
||||
// console.log("Interval (IN) in seconds:", timeDiffSeconds);
|
||||
// return ReturnHelper.successResponseAny(res, 500, "Internal server error", {});
|
||||
// }
|
||||
// // console.log('datalogsbefore IN : ', datalogsbefore)
|
||||
// // data = await attendancedoorlogrepo.update({ idx: datalogsbefore.idx }, { datelogs: originalDate + ' ' + originalTime });
|
||||
// // }
|
||||
// // else {
|
||||
// // data = await attendancedoorlogrepo.save(dtPost);
|
||||
// }
|
||||
// // data = await attendancedoorlogrepo.save(dtPost);
|
||||
// }
|
||||
data = (dtPost ? await attendancedoorlogrepo.save(dtPost) : {});
|
||||
return ReturnHelper.successResponseAny(res, 200, Language.lang.success, data);
|
||||
|
||||
} catch (e: unknown) {
|
||||
log.error(e);
|
||||
const err = e as Error;
|
||||
|
||||
return ReturnHelper.successResponseAny(res, 200, Language.lang.failed, err.message);
|
||||
}
|
||||
}
|
||||
|
||||
static async logrekon(req: Request, res: Response, next: NextFunction): Promise<Response> {
|
||||
/*
|
||||
#swagger.tags = ['Event']
|
||||
#swagger.parameters['datelogs'] = {
|
||||
description: 'Entry Date Logs',
|
||||
in: 'query',
|
||||
type: 'string'
|
||||
}
|
||||
*/
|
||||
|
||||
try {
|
||||
// let data: any = null;
|
||||
const schema = Joi.object().keys({
|
||||
datelogs: Joi.string().required().label('Date Logs'),
|
||||
});
|
||||
const param = await schema.validateAsync(req.query);
|
||||
const employeerepo = OrmHelper.DB.getRepository(Employee);
|
||||
const attendancedoorinfo = OrmHelper.DB.getRepository(AttendanceDoorInfo);
|
||||
const data = await employeerepo.createQueryBuilder("tbl_employee")
|
||||
.innerJoin(
|
||||
"tbl_attendancedoorlogs",
|
||||
"attlog",
|
||||
"tbl_employee.accessdoorid = attlog.accessdoorid"
|
||||
)
|
||||
.select("attlog.accessdoorid", "accessdoorid")
|
||||
.addSelect("tbl_employee.nik", "nik")
|
||||
.addSelect("tbl_employee.employeename", "employeename")
|
||||
.addSelect("DATE_FORMAT(attlog.datelogs, '%Y-%m-%d')", "logdate")
|
||||
.addSelect(`COUNT(CASE WHEN attlog.devicename = 'DeviceIn' THEN 1 END)`, "total_in")
|
||||
.addSelect(`COUNT(CASE WHEN attlog.devicename = 'DeviceOut' THEN 1 END)`, "total_out")
|
||||
|
||||
// .select([
|
||||
// "tbl_employee._idx AS idx",
|
||||
// "tbl_employee.accessdoorid AS accessdoorid",
|
||||
// "tbl_employee.nik AS nik",
|
||||
// "tbl_employee.employeename AS employeename",
|
||||
// "DATE_FORMAT(attlog.datelogs, '%Y-%m-%d') AS log_date",
|
||||
// "attlog.devicename AS deviceevent",
|
||||
// "COUNT(attlog.devicename) AS total_event"
|
||||
// ])
|
||||
.where("DATE_FORMAT(attlog.datelogs, '%Y-%m-%d') = :d", { d: param.datelogs })
|
||||
// .andWhere("tbl_employee.accessdoorid = :e", { e: "219" })
|
||||
.groupBy("tbl_employee.accessdoorid")
|
||||
.addGroupBy("tbl_employee.nik")
|
||||
.addGroupBy("tbl_employee.employeename")
|
||||
.addGroupBy("DATE_FORMAT(attlog.datelogs, '%Y-%m-%d')")
|
||||
.orderBy("accessdoorid", "ASC")
|
||||
.getRawMany();
|
||||
|
||||
// console.log(data);
|
||||
for (const row of data) {
|
||||
const doorinfo = await attendancedoorinfo.createQueryBuilder("tbl_attendancedoorinfo")
|
||||
.where("DATE_FORMAT(tbl_attendancedoorinfo.datelogs, '%Y-%m-%d')= :d", { d: param.datelogs })
|
||||
.andWhere("accessdoorid= :a", { a: row.accessdoorid })
|
||||
.getOne()
|
||||
let datadoorinfo: any = {};
|
||||
// console.log(doorinfo);
|
||||
if (doorinfo == null) {
|
||||
datadoorinfo = {
|
||||
"accessdoorid": row.accessdoorid,
|
||||
"nik": row.nik,
|
||||
"employeename": row.employeename,
|
||||
"datelogs": param.datelogs,
|
||||
"totalin": row.total_in,
|
||||
"totalout": row.total_out,
|
||||
"iby": 'sys',
|
||||
"idt": new Date()
|
||||
}
|
||||
await attendancedoorinfo.save(datadoorinfo);
|
||||
}
|
||||
else {
|
||||
datadoorinfo = {
|
||||
"accessdoorid": row.accessdoorid,
|
||||
"nik": row.nik,
|
||||
"employeename": row.employeename,
|
||||
"datelogs": param.datelogs,
|
||||
"totalin": row.total_in,
|
||||
"totalout": row.total_out,
|
||||
"uby": "sys",
|
||||
"udt": new Date()
|
||||
}
|
||||
// console.log("update ; ", datadoorinfo);
|
||||
// console.log("doorinfo ; ", doorinfo);
|
||||
await attendancedoorinfo.update({ idx: doorinfo.idx }, datadoorinfo)
|
||||
// if (row.deviceevent == 'deviceIn') {
|
||||
// data['totalin'] = row.total_event + doorinfo.totalin;
|
||||
// }
|
||||
// else {
|
||||
// data['totalout'] = row.total_event + ;
|
||||
// }
|
||||
}
|
||||
// console.log("Access Door ID:", row.accessdoorid);
|
||||
// console.log("Employee Name:", row.employeename);
|
||||
// console.log("Log Date:", row.log_date);
|
||||
// console.log("Device Event:", row.deviceevent);
|
||||
// console.log("Total Events:", row.total_event);
|
||||
// console.log("-----");
|
||||
}
|
||||
// data.map(row => ({
|
||||
// ...row,
|
||||
// log_date: (row.log_date).toISOString().split('T')[0],
|
||||
// }));
|
||||
|
||||
return ReturnHelper.successResponseAny(res, 200, Language.lang.success, data);
|
||||
|
||||
} catch (e: unknown) {
|
||||
log.error(e);
|
||||
const err = e as Error;
|
||||
|
||||
return ReturnHelper.successResponseAny(res, 200, Language.lang.failed, err.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
37
src/cron-task.ts
Normal file
37
src/cron-task.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import cron from 'node-cron';
|
||||
import { AxiosApi } from "./helpers/express/axiosapi";
|
||||
import config, { util } from "config";
|
||||
import moment from 'moment-timezone';
|
||||
let isRunning = false;
|
||||
|
||||
export function startCronJob() {
|
||||
const job = cron.schedule('0 */1 * * * *', async () => {
|
||||
if (isRunning) {
|
||||
console.log('crlogrekon is still running. Skipping this schedule.');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Running scheduled task at :', new Date().toLocaleString());
|
||||
isRunning = true;
|
||||
|
||||
try {
|
||||
await crlogrekon();
|
||||
} catch (error) {
|
||||
console.error('crlogrekon failed:', error);
|
||||
} finally {
|
||||
isRunning = false;
|
||||
}
|
||||
});
|
||||
|
||||
// job.stop();
|
||||
console.log('Cron task initialized');
|
||||
}
|
||||
|
||||
export async function crlogrekon() {
|
||||
const today = moment().tz('Asia/Dili').format('YYYY-MM-DD');
|
||||
console.log(today);
|
||||
// let res = await AxiosApi.get("http://" + config.get("server.host") + ":" + config.get("server.port") + "/api/dooraccess/logrekon?datelogs=" + today, '');
|
||||
await AxiosApi.get("http://" + config.get("server.host") + ":" + config.get("server.port") + "/api/dooraccess/logrekon?datelogs=" + today, '');
|
||||
console.log('Process done At :', new Date().toLocaleString());
|
||||
// return res;
|
||||
}
|
||||
225
src/helpers/common.ts
Normal file
225
src/helpers/common.ts
Normal file
@ -0,0 +1,225 @@
|
||||
import { Logger, ILogObj } from 'tslog';
|
||||
import { validate } from 'uuid';
|
||||
|
||||
const log: Logger<ILogObj> = new Logger({ name: '[CommonHelper]', type: 'pretty' });
|
||||
|
||||
export default class CommonHelper {
|
||||
static randomInteger(min: number, max: number): number | null {
|
||||
if (min > 0 && max > 0) {
|
||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||
} else {
|
||||
log.error(new Error('Min & Max must be > 0'));
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
static inArray(array: string[], keyword: string): boolean {
|
||||
for (let val of array) {
|
||||
if (val === keyword) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static async sleep(seconds: number): Promise<void> {
|
||||
if (seconds > 0) {
|
||||
return new Promise((resolve) => setTimeout(resolve, seconds * 1000));
|
||||
} else {
|
||||
log.error(new Error('Second must be > 0'));
|
||||
}
|
||||
}
|
||||
|
||||
static convertArrayToObject(object: any, key: string, val = ''): any {
|
||||
const ret: any = {};
|
||||
|
||||
for (let i in object) {
|
||||
const d = object[i];
|
||||
|
||||
if (val) {
|
||||
ret[d[key]] = d[val];
|
||||
} else {
|
||||
ret[d[key]] = d;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static objectFlip(obj: any): any {
|
||||
const ret = {};
|
||||
|
||||
Object.keys(obj).forEach(key => {
|
||||
ret[obj[key]] = key;
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static countObject(obj: any): number {
|
||||
let c = 0;
|
||||
|
||||
for (let s in obj) {
|
||||
c++;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static capitalizeFirstLetter(str: string): string {
|
||||
if (str) {
|
||||
return str.charAt(0).toUpperCase() + str.slice(1);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
static getKeyEnum(obj: any, key: any): any {
|
||||
try {
|
||||
return Object.values(obj)[Object.keys(obj)[key]]
|
||||
} catch (e: any) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
static generateTemplate(template: string, pairMap: any): string {
|
||||
for (let p in pairMap) {
|
||||
let v = pairMap[p];
|
||||
|
||||
template = template.split('{' + p + '}').join(v);
|
||||
}
|
||||
|
||||
return template
|
||||
}
|
||||
|
||||
static handleFilter(param: { filter: any, col_any_eq: string[], col_any_like: string[], additional_where?: string }): any {
|
||||
const whereAttrPre = [];
|
||||
const whereVal: any = {};
|
||||
|
||||
if (param.filter) {
|
||||
try {
|
||||
param.filter = JSON.parse(param.filter);
|
||||
|
||||
let filter_any = false;
|
||||
let filter_any_val = '';
|
||||
|
||||
for (let p in param.filter) {
|
||||
let f = String(param.filter[p])
|
||||
let fr = param.filter[p]
|
||||
|
||||
if (p != 'any') {
|
||||
if (!validate(f)) {
|
||||
let found = false;
|
||||
if (fr['from']) {
|
||||
whereAttrPre.push(p + " >= :" + p + '_from');
|
||||
whereVal[p + '_from'] = fr['from'];
|
||||
found = true;
|
||||
}
|
||||
if (fr['to']) {
|
||||
whereAttrPre.push(p + " <= :" + p + '_to');
|
||||
whereVal[p + '_to'] = fr['to'];
|
||||
found = true;
|
||||
}
|
||||
if (fr['in']) {
|
||||
whereAttrPre.push(p + " in (:..." + p + '_in)');
|
||||
whereVal[p + '_in'] = fr['in'];
|
||||
found = true;
|
||||
}
|
||||
if (fr['like']) {
|
||||
whereAttrPre.push('LOWER(' + p + ') like :' + p + '_like');
|
||||
whereVal[p + '_like'] = '%' + fr['like'].toLowerCase() + '%';;
|
||||
found = true;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
whereAttrPre.push("LOWER(" + p + ") = :" + p);
|
||||
f = f.toLowerCase();
|
||||
|
||||
whereVal[p] = f;
|
||||
}
|
||||
} else {//uuid only
|
||||
whereAttrPre.push(p + " = :" + p);
|
||||
whereVal[p] = f;
|
||||
}
|
||||
} else {
|
||||
filter_any = true;
|
||||
filter_any_val = f;
|
||||
}
|
||||
}
|
||||
|
||||
if (filter_any) {
|
||||
let wtp = []
|
||||
if (param.col_any_eq.length > 0) {
|
||||
const eqr = [];
|
||||
for (let c of param.col_any_eq) {
|
||||
eqr.push('LOWER(' + c + ') = :filter_eq');
|
||||
}
|
||||
const eq = '(' + eqr.join(' or ') + ')';
|
||||
|
||||
wtp.push(eq);
|
||||
}
|
||||
if (param.col_any_like.length > 0) {
|
||||
const liker = [];
|
||||
for (let c of param.col_any_like) {
|
||||
liker.push('LOWER(' + c + ') like :filter_like');
|
||||
}
|
||||
|
||||
const like = '(' + liker.join(' or ') + ')';
|
||||
|
||||
wtp.push(like);
|
||||
}
|
||||
|
||||
if (wtp.length > 0) {
|
||||
whereAttrPre.push('(' + wtp.join(' or ') + ')');
|
||||
}
|
||||
|
||||
if (param.col_any_eq.length > 0) {
|
||||
whereVal['filter_eq'] = filter_any_val;
|
||||
}
|
||||
if (param.col_any_like.length > 0) {
|
||||
whereVal['filter_like'] = '%' + filter_any_val + '%';
|
||||
}
|
||||
}
|
||||
} catch (e: any) {
|
||||
let wtp = []
|
||||
if (param.col_any_eq.length > 0) {
|
||||
const eqr = [];
|
||||
for (let c of param.col_any_eq) {
|
||||
eqr.push('LOWER(' + c + ') = :filter_eq');
|
||||
}
|
||||
const eq = '(' + eqr.join(' or ') + ')';
|
||||
|
||||
wtp.push(eq);
|
||||
}
|
||||
if (param.col_any_like.length > 0) {
|
||||
const liker = [];
|
||||
for (let c of param.col_any_like) {
|
||||
liker.push(c + ' like :filter_like');
|
||||
}
|
||||
|
||||
const like = '(' + liker.join(' or ') + ')';
|
||||
|
||||
wtp.push(like);
|
||||
}
|
||||
|
||||
if (wtp.length > 0) {
|
||||
whereAttrPre.push('(' + wtp.join(' or ') + ')');
|
||||
}
|
||||
|
||||
|
||||
if (param.col_any_eq.length > 0) {
|
||||
whereVal['filter_eq'] = param.filter.toLowerCase();
|
||||
}
|
||||
if (param.col_any_like.length > 0) {
|
||||
whereVal['filter_like'] = '%' + param.filter + '%';
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
const whereAttr = whereAttrPre.join(' and ') + (whereAttrPre.length > 0 && param.additional_where && param.additional_where != '' ? ' and ' : '') + (param.additional_where ?? '');
|
||||
|
||||
return { whereAttr, whereVal };
|
||||
}
|
||||
}
|
||||
72
src/helpers/express/axiosapi.ts
Normal file
72
src/helpers/express/axiosapi.ts
Normal file
@ -0,0 +1,72 @@
|
||||
import axios from 'axios';
|
||||
|
||||
let header = {
|
||||
'accept': '*/*',
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
|
||||
export class AxiosApi {
|
||||
static async get(url: string, token: any): Promise<any> {
|
||||
try {
|
||||
if (token) header['Authorization'] = `Bearer ${token}`;
|
||||
header['Content-Type'] = 'application/json';
|
||||
|
||||
return await axios.get(url, {
|
||||
headers: header
|
||||
})
|
||||
.then(response => {
|
||||
// console.log('Response sms:', response.data);
|
||||
return response.data;
|
||||
})
|
||||
.catch(error => {
|
||||
// console.error('Error:', error);
|
||||
throw error;
|
||||
});
|
||||
} catch (e: unknown) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static async post(url: string, data: any, token: any): Promise<any> {
|
||||
try {
|
||||
// console.log(token);
|
||||
if (token) header['Authorization'] = `Bearer ${token}`;
|
||||
header['Content-Type'] = 'application/json';
|
||||
return await axios.post(url, data, {
|
||||
headers: header
|
||||
})
|
||||
.then(response => {
|
||||
// console.log('Response sms:', response.data);
|
||||
return response.data;
|
||||
})
|
||||
.catch(error => {
|
||||
// console.error('Error:', error);
|
||||
throw error;
|
||||
});
|
||||
} catch (e: unknown) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
async postparams(url: string, data: any): Promise<any> {
|
||||
try {
|
||||
return await axios.post(url, new URLSearchParams(data).toString(), {
|
||||
headers: {
|
||||
'accept': '*/*',
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
}
|
||||
})
|
||||
.then(response => {
|
||||
// console.log('Response sms:', response.data);
|
||||
return response.data;
|
||||
})
|
||||
.catch(error => {
|
||||
// console.error('Error:', error);
|
||||
throw error;
|
||||
});
|
||||
} catch (e: unknown) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
14
src/helpers/express/compression.ts
Normal file
14
src/helpers/express/compression.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import cors from 'cors';
|
||||
import express from 'express';
|
||||
import compression from 'compression';
|
||||
|
||||
export class CompressionHelper {
|
||||
static setup(app: express.Application) {
|
||||
const compressionOptions: compression.CompressionOptions = {
|
||||
level: 6,
|
||||
memLevel: 8
|
||||
};
|
||||
|
||||
app.use(compression(compressionOptions));
|
||||
}
|
||||
}
|
||||
16
src/helpers/express/cors.ts
Normal file
16
src/helpers/express/cors.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import config from 'config';
|
||||
import cors from 'cors';
|
||||
import express from 'express';
|
||||
|
||||
export class CorsHelper {
|
||||
static setup(app: express.Application) {
|
||||
const corsOptions: cors.CorsOptions = {
|
||||
origin: config.get('server.cors'),
|
||||
methods: 'GET,POST,PUT,DELETE,OPTIONS',
|
||||
allowedHeaders: ['Content-Type', 'Authorization'],
|
||||
optionsSuccessStatus: 200,
|
||||
};
|
||||
|
||||
app.use(cors(corsOptions));
|
||||
}
|
||||
}
|
||||
124
src/helpers/express/encryption_pin.ts
Normal file
124
src/helpers/express/encryption_pin.ts
Normal file
@ -0,0 +1,124 @@
|
||||
import crypto from 'crypto';
|
||||
|
||||
export default class EncryptionPINHelper {
|
||||
static alphaNum = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
static defaultEncKey = [
|
||||
's'.charCodeAt(0) << 1, 't'.charCodeAt(0) << 2, '9'.charCodeAt(0) << 3, '4'.charCodeAt(0) << 4,
|
||||
'v'.charCodeAt(0) << 1, '1'.charCodeAt(0) << 2, 'b'.charCodeAt(0) << 3, '0'.charCodeAt(0) << 4,
|
||||
'a'.charCodeAt(0) << 1, 'b'.charCodeAt(0) << 2, 'C'.charCodeAt(0) << 3, 'F'.charCodeAt(0) << 4,
|
||||
'x'.charCodeAt(0) << 1, 'u'.charCodeAt(0) << 2, 'T'.charCodeAt(0) << 3, 'z'.charCodeAt(0) << 4
|
||||
];
|
||||
|
||||
static getDefaultEncryptionKey() {
|
||||
const key = new Uint8Array(EncryptionPINHelper.defaultEncKey.length);
|
||||
for (let i = 0; i < key.length; i++) {
|
||||
key[i] = EncryptionPINHelper.defaultEncKey[i] >> (i % 4) + 1;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
static Generate128BitsKey() {
|
||||
return EncryptionPINHelper.GetRandomSecureBytes(16);
|
||||
}
|
||||
|
||||
static AES128EncryptToBase64(key, plainText) {
|
||||
const ivSeed = EncryptionPINHelper.GenerateIVSeed();
|
||||
const iv = EncryptionPINHelper.GenerateIV(ivSeed);
|
||||
|
||||
const cipher = crypto.createCipheriv('aes-128-cbc', Buffer.from(key), Buffer.from(iv));
|
||||
cipher.setAutoPadding(true); // PKCS7 is default
|
||||
|
||||
let cipherText = cipher.update(plainText);
|
||||
cipherText = Buffer.concat([cipherText, cipher.final()]);
|
||||
|
||||
const base64CipherText = cipherText.toString('base64');
|
||||
return base64CipherText + ivSeed;
|
||||
}
|
||||
|
||||
static AES128DecryptFromBase64(key, base64CipherText) {
|
||||
const ivSeed = base64CipherText.slice(-2);
|
||||
base64CipherText = base64CipherText.slice(0, -2);
|
||||
const cipherText = Buffer.from(base64CipherText, 'base64');
|
||||
const iv = EncryptionPINHelper.GenerateIV(ivSeed);
|
||||
|
||||
const decipher = crypto.createDecipheriv('aes-128-cbc', Buffer.from(key), Buffer.from(iv));
|
||||
decipher.setAutoPadding(true);
|
||||
|
||||
let plainText = decipher.update(cipherText);
|
||||
plainText = Buffer.concat([plainText, decipher.final()]);
|
||||
|
||||
return plainText;
|
||||
}
|
||||
|
||||
static Decrypt_with_shared_key(msg) {
|
||||
try {
|
||||
const decrypted = EncryptionPINHelper.AES128DecryptFromBase64(EncryptionPINHelper.getDefaultEncryptionKey(), msg);
|
||||
return decrypted.toString('utf8');
|
||||
} catch (error) {
|
||||
console.error("Decryption error:", error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static Encrypt_with_shared_key(msg) {
|
||||
try {
|
||||
return EncryptionPINHelper.AES128EncryptToBase64(EncryptionPINHelper.getDefaultEncryptionKey(), Buffer.from(msg, 'utf8'));
|
||||
} catch (error) {
|
||||
console.error("Encryption error:", error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static GenerateIVSeed() {
|
||||
var length = 2;
|
||||
let result = "";
|
||||
for (let i = 0; i < length; i++) {
|
||||
const randomIndex = Math.floor(Math.random() * EncryptionPINHelper.alphaNum.length);
|
||||
result += EncryptionPINHelper.alphaNum.charAt(randomIndex);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static GenerateIV(seed) {
|
||||
const ivSeed = Buffer.from(seed, 'utf8');
|
||||
return new Uint8Array([
|
||||
ivSeed[0], ivSeed[1], 1, 2, ivSeed[0], ivSeed[1], 3, 4, ivSeed[0], ivSeed[1], 5, 6, ivSeed[0], ivSeed[1], 7, 8
|
||||
]);
|
||||
}
|
||||
|
||||
static GetRandomSecureBytes(size: number) {
|
||||
return crypto.randomBytes(size);
|
||||
}
|
||||
|
||||
|
||||
// static encryptDefaultUTF8(texto) {
|
||||
// try {
|
||||
// let encrypted = EncryptionPINHelper.AES128EncryptToBase64(EncryptionPINHelper.getDefaultEncryptionKey(), Buffer.from(texto, 'utf8'));
|
||||
// return (encrypted);
|
||||
// } catch (error) {
|
||||
// console.error("Encryption error:", error);
|
||||
// return null; // Or handle the error as needed
|
||||
// }
|
||||
// }
|
||||
// static Decrypt_with_key(msg, keyEncriptedWithSeven) {
|
||||
// try {
|
||||
// const key = EncryptionPINHelper.AES128DecryptFromBase64(EncryptionPINHelper.getDefaultEncryptionKey(), keyEncriptedWithSeven);
|
||||
// const decrypted = EncryptionPINHelper.AES128DecryptFromBase64(key, msg);
|
||||
// return decrypted.toString('utf8');
|
||||
// } catch (error) {
|
||||
// console.error("Decryption error:", error);
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
|
||||
// static Encrypt_with_key(msg, keyEncriptedWithSeven) {
|
||||
// try {
|
||||
// const key = EncryptionPINHelper.AES128DecryptFromBase64(EncryptionPINHelper.getDefaultEncryptionKey(), keyEncriptedWithSeven);
|
||||
// return EncryptionPINHelper.AES128EncryptToBase64(key, Buffer.from(msg, 'utf8'));
|
||||
// } catch (error) {
|
||||
// console.error("Encryption error:", error);
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
12
src/helpers/express/json.ts
Normal file
12
src/helpers/express/json.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import config from 'config';
|
||||
import express from 'express';
|
||||
|
||||
export class JsonHelper {
|
||||
static setup(app: express.Application) {
|
||||
app.use(
|
||||
express.json({
|
||||
limit: config.get('server.max_body'),
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
15
src/helpers/express/morgan.ts
Normal file
15
src/helpers/express/morgan.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import config from 'config';
|
||||
import morgan from 'morgan';
|
||||
import express from 'express';
|
||||
|
||||
export class MorganHelper {
|
||||
static setup(app: express.Application) {
|
||||
if (process.env.NODE_ENV == 'prod') {
|
||||
app.use(morgan(config.get('server.morgan'), {
|
||||
skip: function (req, res) { return res.statusCode < 400 }
|
||||
}));
|
||||
} else {
|
||||
app.use(morgan(config.get('server.morgan')));
|
||||
}
|
||||
}
|
||||
}
|
||||
58
src/helpers/express/return.ts
Normal file
58
src/helpers/express/return.ts
Normal file
@ -0,0 +1,58 @@
|
||||
import { Response } from 'express';
|
||||
import { ErrorType, ErrorValidation } from 'entity';
|
||||
|
||||
export class ReturnHelper {
|
||||
static successResponseAny(
|
||||
res: Response,
|
||||
status_code: number,
|
||||
message: string,
|
||||
data: any = null
|
||||
): Response {
|
||||
|
||||
return res.status(status_code || 200).json({
|
||||
status: true,
|
||||
code: status_code || 200,
|
||||
message: message || "success",
|
||||
data: data || {},
|
||||
});
|
||||
};
|
||||
|
||||
static successResponselist(
|
||||
res: Response,
|
||||
status_code: number,
|
||||
message: string,
|
||||
count_data: number = 0,
|
||||
current_page: number = 0,
|
||||
total_count_data: number = 0,
|
||||
list_data: any = null
|
||||
): Response {
|
||||
|
||||
return res.status(status_code || 200).json({
|
||||
status: true,
|
||||
code: status_code || 200,
|
||||
message: message || "success",
|
||||
data: {
|
||||
count: count_data,
|
||||
page: current_page,
|
||||
total_count: total_count_data,
|
||||
list: list_data
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
static errorResponse(
|
||||
res: Response,
|
||||
status_code: number,
|
||||
error_code: number,
|
||||
message: string,
|
||||
error: any = null
|
||||
): Response {
|
||||
|
||||
return res.status(status_code || 200).json({
|
||||
status: false,
|
||||
error_code: error_code || 400,
|
||||
message: message || "failed",
|
||||
error: error,
|
||||
});
|
||||
};
|
||||
}
|
||||
14
src/helpers/express/swagger.ts
Normal file
14
src/helpers/express/swagger.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import config from 'config';
|
||||
import express from 'express';
|
||||
import swaggerUi from 'swagger-ui-express';
|
||||
import swaggerDocument from '../../swagger/swagger.json';
|
||||
|
||||
export class SwaggerHelper {
|
||||
static setup(app: express.Application) {
|
||||
var options = {
|
||||
explorer: false
|
||||
};
|
||||
|
||||
app.use('/api/docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument, options));
|
||||
}
|
||||
}
|
||||
7
src/helpers/express/trust_proxy.ts
Normal file
7
src/helpers/express/trust_proxy.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import express from 'express';
|
||||
|
||||
export class TrustProxyHelper {
|
||||
static setup(app: express.Application) {
|
||||
app.set('trust proxy', true);
|
||||
}
|
||||
}
|
||||
13
src/helpers/express/urlencoded.ts
Normal file
13
src/helpers/express/urlencoded.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import config from 'config';
|
||||
import express from 'express';
|
||||
|
||||
export class UrlencodedHelper {
|
||||
static setup(app: express.Application) {
|
||||
app.use(
|
||||
express.urlencoded({
|
||||
extended: true,
|
||||
limit: config.get('server.max_body'),
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
103
src/helpers/express/utility.ts
Normal file
103
src/helpers/express/utility.ts
Normal file
@ -0,0 +1,103 @@
|
||||
import moment from 'moment-timezone';
|
||||
import crypto from 'crypto';
|
||||
import config from "config";
|
||||
import { AxiosApi } from "../../helpers/express/axiosapi";
|
||||
|
||||
const algorithm = config.get("auth.algorithm").toString();
|
||||
const keyString = config.get("auth.keystring").toString(); // Must be 32 characters for AES-256
|
||||
const iv = crypto.randomBytes(16); // Secure random IV
|
||||
const axiosapi = new AxiosApi();
|
||||
|
||||
export enum TimeLocation {
|
||||
"local" = "L",
|
||||
"GMT" = "G"
|
||||
}
|
||||
export class Utility {
|
||||
static isMobile(): boolean {
|
||||
try {
|
||||
const userAgent = navigator.userAgent.toLowerCase();
|
||||
|
||||
// List of mobile device keywords
|
||||
const mobileDevices = [
|
||||
'iphone', 'ipod', 'ipad', 'android', 'blackberry', 'windows phone', 'mobile'
|
||||
];
|
||||
|
||||
// Check if the userAgent matches any mobile device keyword
|
||||
return mobileDevices.some(device => userAgent.includes(device));
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static getTimeStamp(d: string): Date {
|
||||
var dobj = moment.tz(d, "YYYY-MM-DD HH:mm:ss", 'Asia/Jakarta').toDate();
|
||||
return new Date(dobj.getFullYear() + '-' + (dobj.getMonth() + 1) + '-' + dobj.getDate() + ' ' + dobj.getHours() + ':' + dobj.getMinutes() + ':' + dobj.getSeconds());
|
||||
}
|
||||
|
||||
static hashData(data: string, salt: string): string {
|
||||
const hash = crypto.createHmac("sha256", salt).update(data).digest("hex");
|
||||
return hash;
|
||||
}
|
||||
|
||||
static generateSalt(length: number = 16): string {
|
||||
return crypto.randomBytes(length).toString("hex");
|
||||
}
|
||||
|
||||
static encrypt(text: string): string {
|
||||
const key = Buffer.from(keyString, 'utf8');
|
||||
const cipher = crypto.createCipheriv(algorithm, key, iv);
|
||||
const encrypted = Buffer.concat([cipher.update(text), cipher.final()]);
|
||||
return `${iv.toString('hex')}:${encrypted.toString('hex')}`;
|
||||
}
|
||||
|
||||
static decrypt(encryptedData: string): string {
|
||||
const [ivHex, encryptedHex] = encryptedData.split(':');
|
||||
const ivBuffer = Buffer.from(ivHex, 'hex');
|
||||
const key = Buffer.from(keyString, 'utf8');
|
||||
const encryptedBuffer = Buffer.from(encryptedHex, 'hex');
|
||||
|
||||
const decipher = crypto.createDecipheriv(algorithm, key, ivBuffer);
|
||||
const decrypted = Buffer.concat([decipher.update(encryptedBuffer), decipher.final()]);
|
||||
return decrypted.toString();
|
||||
}
|
||||
|
||||
static expired_at(location: TimeLocation): any {
|
||||
return location === TimeLocation.GMT
|
||||
? moment.tz("Asia/Jakarta").add(config.get("auth.expired_otp"), "minute").add(7, "hours").toDate()
|
||||
: moment.tz("Asia/Jakarta").add(config.get("auth.expired_otp"), "minute").toDate();
|
||||
}
|
||||
|
||||
static expired_attoken(location: TimeLocation): any {
|
||||
return location === TimeLocation.GMT
|
||||
? moment.tz("Asia/Jakarta").add(24 * parseInt(config.get("auth.refresh_token_lifetime_day")), "hours").toDate()
|
||||
: moment.tz("Asia/Jakarta").add(config.get("auth.refresh_token_lifetime_day"), "days").toDate();
|
||||
}
|
||||
|
||||
// static expired_atdb() : any{
|
||||
// return moment.tz("Asia/Jakarta").add(config.get("auth.expired_otp"), "minute").toDate();
|
||||
// }
|
||||
|
||||
static suspend_until(location: TimeLocation): any {
|
||||
return location === TimeLocation.GMT
|
||||
? moment.tz("Asia/Jakarta").add(config.get("auth.suspend_otp"), "minute").add(7, "hours").toDate()
|
||||
: moment.tz("Asia/Jakarta").add(config.get("auth.suspend_otp"), "minute").toDate();
|
||||
// return moment.tz("Asia/Jakarta").add(config.get("auth.suspend_otp"), "minute").toDate();
|
||||
}
|
||||
|
||||
// static suspend_untildb() : any{
|
||||
// return moment.tz("Asia/Jakarta").add(config.get("auth.suspend_otp"), "minute").toDate();
|
||||
// }
|
||||
|
||||
static async getwording(code: string, lang: string): Promise<any> {
|
||||
try {
|
||||
const respwording = await axiosapi.postparams(
|
||||
config.get("service.wording"), { code: code }
|
||||
);
|
||||
let getcontentmsg = respwording.data[0].name[lang];
|
||||
return getcontentmsg;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
50
src/helpers/jwt.ts
Normal file
50
src/helpers/jwt.ts
Normal file
@ -0,0 +1,50 @@
|
||||
import { NextFunction, Response } from 'express';
|
||||
import { Logger, ILogObj } from 'tslog';
|
||||
import { Request, expressjwt } from "express-jwt";
|
||||
import fs from 'fs';
|
||||
import { Language } from '../langs/lang';
|
||||
import { ReturnHelper } from './express/return';
|
||||
import express from 'express';
|
||||
import { Utility } from './express/utility';
|
||||
|
||||
const log: Logger<ILogObj> = new Logger({ name: '[JwtHelper]', type: 'pretty' });
|
||||
|
||||
export default class JwtHelper {
|
||||
static secure = (app: express.Application) => {
|
||||
|
||||
var publicKey = fs.readFileSync("src/helpers/key/public.key");
|
||||
|
||||
app.use(
|
||||
expressjwt({
|
||||
secret: publicKey, algorithms: ["RS256"],
|
||||
getToken: function fromHeaderOrQuerystring(req): any {
|
||||
// log.info(req.query);
|
||||
if (req.headers.authorization && req.headers.authorization.split(' ')[0] === 'Bearer') {
|
||||
return req.headers.authorization.split(' ')[1];
|
||||
} else if (req.query && req.query.token) {
|
||||
return req.query.token;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
}).unless({ path: ["/token"] }),
|
||||
function (req: Request, res: Response, next: NextFunction) {
|
||||
// log.info(req.auth.data);
|
||||
req.auth.data.id = Utility.decrypt(req.auth.data.id);
|
||||
if (!req.auth?.data.id) {
|
||||
return ReturnHelper.errorResponse(res, 403, 666, Language.lang.failed_access);
|
||||
}
|
||||
|
||||
return next();
|
||||
}
|
||||
)
|
||||
|
||||
app.use(function (err: any, req: Request, res: Response, next: NextFunction) {
|
||||
if (err.name === 'UnauthorizedError') {
|
||||
return ReturnHelper.errorResponse(res, 403, 666, Language.lang.failed_access);
|
||||
}
|
||||
|
||||
return next();
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
28
src/helpers/key/private.key
Normal file
28
src/helpers/key/private.key
Normal file
@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC0sdcneY7W32xE
|
||||
8hbjFPR4/AZFdtQqwQ3lEsuUFcsYh2KR0wP0umqtIMGLle3603lhQ/AMXDlKBBJt
|
||||
IAP1SJNvGYY6fUdm+AZ0NFmst3CCiFsw7N5F+KXKEW1g/vUO9OKJ2Hg9lXuOkYAh
|
||||
DYv+d0R5nsHu5l7WAesHtrcuNwezmENeAwjgWNezlwJmf54soNrV+EE7zPxTyye1
|
||||
se3b8LjMgB/zDTF2UkdrvrVulpshG0JMvDy1n7QG/+K3u3BcGakRws5GZu7LZug4
|
||||
ZNdURajL0oqN9bxPQRWR5+7jVqm1gYNRGQfPJuBXUiqd/AXa+ap0M0RPBFWfomjf
|
||||
xn21QpdVAgMBAAECggEAKUMRHCEMhrG3YhkcM9fFqdj3P6aOdYLnPt+nYFYHrj7A
|
||||
OgeDOD/Xe1hnCg5/LQ9cgOMILnJi3K2IXaX5cWoUzMJ53eJcyz0pECEiNygeh5hG
|
||||
pqn4aecJSNbo8MTXxgYSsyKc9ocrk1dTeHjE9qNaniEsLPcrQdhnSLgnJWUIm7Bv
|
||||
HqFFhgINdbZmE3Wx0a1Y71jGePcm3Zqx0a5sZDmZN2Vh7fNs1X8y2rnNvsKOBG5T
|
||||
RmB8zlnj5SkjtD9RKkis0gGDVGjtkfskClY6wARUgSajfJnBAwpbdqrR0bmOox5k
|
||||
T39aL6dxcPBQc8L0HX1sYW4yCIba1snxOUXtLEjdkQKBgQDwepPKv09waBlp7Q5W
|
||||
c7Fn5dLBJ8ungbeDf83jZbIUs2I0wJ0v/UJiUegVP/h005kpEyY9NjFhcN5GXnTo
|
||||
Ru1jmZ2w0UC+iOa7+JplXsS7kZfieaPIWHcmg0IkQpWHXRjoeWrd2dA+unc+6BGf
|
||||
ZvUlb9XPZBATShARnjHu1z5CiQKBgQDAW3PBjLwgrT7NlRkpjuLMEvzimso1yTKa
|
||||
yYdTNhJYkz5YnlPeu197seqqeGQPuRuR9KlMjfe7IQOvo0AGNB7VMxCxfF0Obyb9
|
||||
hBT5fFci5dweKqgN3bR/+ppj/bpLS0veMwYNKzhaHsMrwRQzaxrRypRkri2rT7dx
|
||||
jZAI0ilrbQKBgGmk//5m80gng1qkmNLj+oDxVxgiGnbZJryvTczjZUtwzujr4WIu
|
||||
uZYl83Y6ZzUzrCp+TiNABouPISb64hMU7b7+wmbmVrIdxHe5rGJyMq1QNdB5rbkb
|
||||
HCUgLtNtKPGRtZqTlJ4nzTNxiWdqXiuP+IxcyCpXBDTlKZAD1l3d0205AoGBAJTk
|
||||
NO2UKeqBLyOiTR/F4fdkmyor9mk7m1gEtiLKr9iv4IpnwzOchYQRazsYhRtGhPit
|
||||
EH6ZRTArldbV3jDvFw6fwEQhp0YM83k4S6PxguEYWxFeo0ZYXebR67+KHjE5zzfm
|
||||
9sAqvCvFs/yiLyi9try8ubBUwjTgN3ZFxT+OrVDhAoGAUhFkd/Fy0FCsMROPKK5l
|
||||
uadRukj5zKLMw+JJegXO+0AntV2vWPam73x2ulvVig9TqrJLqtOfqYNNX789Fzri
|
||||
PBcqDaMJKfMc6ac7YgZTNP6vk7avjqWUpoJqlj1g8y3suAYkm/xfLd1HvAqQh0p8
|
||||
i3/cmSzkc1MCE2YxYop0gpc=
|
||||
-----END PRIVATE KEY-----
|
||||
9
src/helpers/key/public.key
Normal file
9
src/helpers/key/public.key
Normal file
@ -0,0 +1,9 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtLHXJ3mO1t9sRPIW4xT0
|
||||
ePwGRXbUKsEN5RLLlBXLGIdikdMD9LpqrSDBi5Xt+tN5YUPwDFw5SgQSbSAD9UiT
|
||||
bxmGOn1HZvgGdDRZrLdwgohbMOzeRfilyhFtYP71DvTiidh4PZV7jpGAIQ2L/ndE
|
||||
eZ7B7uZe1gHrB7a3LjcHs5hDXgMI4FjXs5cCZn+eLKDa1fhBO8z8U8sntbHt2/C4
|
||||
zIAf8w0xdlJHa761bpabIRtCTLw8tZ+0Bv/it7twXBmpEcLORmbuy2boOGTXVEWo
|
||||
y9KKjfW8T0EVkefu41aptYGDURkHzybgV1IqnfwF2vmqdDNETwRVn6Jo38Z9tUKX
|
||||
VQIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
44
src/helpers/orm.ts
Normal file
44
src/helpers/orm.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import config from "config";
|
||||
import { DataSource } from "typeorm";
|
||||
import { entities } from "entity";
|
||||
import { ILogObj, Logger } from "tslog";
|
||||
|
||||
export class OrmHelper {
|
||||
static DB: DataSource = null;
|
||||
|
||||
static setup() {
|
||||
const log: Logger<ILogObj> = new Logger({
|
||||
name: "[OrmHelper]",
|
||||
type: "pretty",
|
||||
});
|
||||
log.settings.prettyLogTimeZone = "local";
|
||||
|
||||
const engine: "mysql" = config.get("database.hcm.engine");
|
||||
|
||||
OrmHelper.DB = new DataSource({
|
||||
type: engine,
|
||||
host: config.get("database.hcm.host"),
|
||||
port: Number(config.get("database.hcm.port")),
|
||||
username: String(config.get("database.hcm.username")),
|
||||
password: String(config.get("database.hcm.password")),
|
||||
database: String(config.get("database.hcm.database")),
|
||||
synchronize: config.get("database.hcm.sync"),
|
||||
logging: config.get("database.hcm.logging"),
|
||||
entities: entities,
|
||||
subscribers: [],
|
||||
migrations: [],
|
||||
extra: {
|
||||
// Set the timezone for the session
|
||||
query: "SET TIMEZONE='Asia/Jakarta';",
|
||||
},
|
||||
});
|
||||
|
||||
OrmHelper.DB.initialize()
|
||||
.then(async () => {
|
||||
// await OrmHelper.DB.query("SET TIMEZONE='Asia/Jakarta';");
|
||||
log.info("Database initialized successfully and created default data");
|
||||
// here you can start to work with your database
|
||||
})
|
||||
.catch((error: any) => log.error(error));
|
||||
}
|
||||
}
|
||||
150
src/helpers/thirdparty.ts
Normal file
150
src/helpers/thirdparty.ts
Normal file
@ -0,0 +1,150 @@
|
||||
import axios from "axios";
|
||||
import { ILogObj, Logger } from "tslog"
|
||||
const log: Logger<ILogObj> = new Logger({
|
||||
name: "[AppliactionFileController]",
|
||||
type: "pretty",
|
||||
})
|
||||
|
||||
export default class Thirdparty {
|
||||
static async GetData(url: string, field: any, token?: string) {
|
||||
try {
|
||||
const headers: Record<string, string> = {};
|
||||
if (token) {
|
||||
headers.Authorization = `Bearer ${token}`;
|
||||
}
|
||||
|
||||
const response = await axios.get(url, { params: field, headers });
|
||||
|
||||
const result = response.data;
|
||||
|
||||
if (!result.status) throw response
|
||||
return result
|
||||
} catch (error: any) {
|
||||
const { response } = error;
|
||||
throw {
|
||||
status: false,
|
||||
message: response?.data?.error ?? response?.data?.message ?? 'Unknown error',
|
||||
error: error
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
static async PostData(url: string, field: any, token?: string) {
|
||||
try {
|
||||
const headers: Record<string, string> = {};
|
||||
if (token) {
|
||||
headers.Authorization = `Bearer ${token}`;
|
||||
}
|
||||
const response = await axios.post(url, field, { headers });
|
||||
|
||||
const result = response.data;
|
||||
|
||||
// if (!result.status) throw response
|
||||
return result
|
||||
} catch (error: any) {
|
||||
const { response } = error;
|
||||
throw {
|
||||
status: false,
|
||||
message: response?.data.message || 'Unknown error',
|
||||
data: null
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
static async PutDate(url: string, field: any, token?: string) {
|
||||
try {
|
||||
const headers: Record<string, string> = {};
|
||||
if (token) {
|
||||
headers.Authorization = `Bearer ${token}`;
|
||||
}
|
||||
const response = await axios.put(url, field, { headers });
|
||||
// log.info(response.data || response)
|
||||
|
||||
const result = response.data;
|
||||
|
||||
if (!result.status) throw response
|
||||
return result
|
||||
} catch (error: any) {
|
||||
const { response } = error;
|
||||
throw {
|
||||
status: false,
|
||||
message: response?.data?.error ?? response?.data?.message ?? 'Unknown error',
|
||||
data: null
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
static async UploadFile(url: string, field: any, token?: string) {
|
||||
try {
|
||||
const headers: Record<string, string> = {};
|
||||
if (token) {
|
||||
headers.Authorization = `Bearer ${token}`;
|
||||
}
|
||||
|
||||
const formData = new FormData();
|
||||
|
||||
// Append the file and other fields to FormData
|
||||
for (const key in field) {
|
||||
if (field.hasOwnProperty(key)) {
|
||||
const value = field[key];
|
||||
|
||||
if (value instanceof Object && value.data && value.mimetype) {
|
||||
// Convert file-like object to a Blob
|
||||
const blob = new Blob([value.data], { type: value.mimetype });
|
||||
formData.append(key, blob, value.name); // Use name as filename
|
||||
} else {
|
||||
formData.append(key, value); // Append non-file fields
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// console.log('formData :', formData);
|
||||
|
||||
const response = await axios.post(url, formData, {
|
||||
headers: { ...headers, "Content-Type": "multipart/form-data" }
|
||||
});
|
||||
// log.info(response.data || response)
|
||||
|
||||
const result = response.data;
|
||||
|
||||
if (!result.status) throw response
|
||||
return result
|
||||
} catch (error: any) {
|
||||
log.error(error)
|
||||
const { response } = error;
|
||||
|
||||
throw {
|
||||
status: false,
|
||||
message: response?.data?.error ?? response?.data?.message ?? 'Unknown error',
|
||||
data: null
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
static async DownloadFile(url: string, field: any, token?: string) {
|
||||
try {
|
||||
const headers: Record<string, string> = {};
|
||||
if (token) {
|
||||
headers.Authorization = `Bearer ${token}`;
|
||||
}
|
||||
|
||||
const response = await axios.get(url, { params: field, headers, responseType: 'arraybuffer' });
|
||||
// log.info(response.data || response)
|
||||
const result = response.data;
|
||||
|
||||
return Buffer.from(result)
|
||||
} catch (error: any) {
|
||||
log.error(error)
|
||||
const { response } = error;
|
||||
|
||||
throw {
|
||||
status: false,
|
||||
message: response?.data?.error ?? response?.data?.message ?? 'Unknown error',
|
||||
data: null
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
44
src/index.ts
Normal file
44
src/index.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import { Logger, ILogObj } from "tslog";
|
||||
import { app } from "./server";
|
||||
import config from 'config'
|
||||
import https from 'https';
|
||||
import fs from 'fs';
|
||||
import moment from 'moment-timezone';
|
||||
import { startCronJob } from './cron-task';
|
||||
|
||||
// Set a global timezone for all dates
|
||||
moment.tz.setDefault('Asia/Dili');
|
||||
|
||||
const log: Logger<ILogObj> = new Logger({ name: '[Index]', type: 'pretty' });
|
||||
log.settings.prettyLogTimeZone = 'local';
|
||||
|
||||
const HOST = config.get('server.host')
|
||||
const PORT = Number(config.get('server.port'))
|
||||
|
||||
|
||||
const server = app.listen(config.get('server.ssl.enable') ? PORT + 1000 : PORT, String(HOST), () => {
|
||||
log.info(`Server ${config.get('app.name')} running on port http://${HOST}:${PORT}`);
|
||||
// === Start cron
|
||||
startCronJob();
|
||||
});
|
||||
|
||||
if (config.get('server.ssl.enable')) {
|
||||
const options = {
|
||||
cert: fs.readFileSync(config.get('server.ssl.cert')),
|
||||
key: fs.readFileSync(config.get('server.ssl.key'))
|
||||
};
|
||||
|
||||
https.createServer(options, app).listen(PORT);
|
||||
}
|
||||
|
||||
const onCloseSignal = () => {
|
||||
log.info("sigint received, shutting down");
|
||||
server.close(() => {
|
||||
log.info("server closed");
|
||||
process.exit();
|
||||
});
|
||||
setTimeout(() => process.exit(1), 10000).unref(); // Force shutdown after 10s
|
||||
};
|
||||
|
||||
process.on("SIGINT", onCloseSignal);
|
||||
process.on("SIGTERM", onCloseSignal);
|
||||
45
src/langs/json/en.json
Normal file
45
src/langs/json/en.json
Normal file
@ -0,0 +1,45 @@
|
||||
{
|
||||
"success_insert": "Data has been successfully inserted",
|
||||
"success_update": "Data has been successfully updated",
|
||||
"success_delete": "Data has been successfully deleted",
|
||||
"success_restore": "Data has been successfully restored",
|
||||
"success_view": "Data has been successfully fetched",
|
||||
"success": "Operation has been success",
|
||||
"success_userexists": "User Exists",
|
||||
"otp_success_login": "OTP Has been Verified, Login Successfully",
|
||||
"pin_success_login": "PIN Has been Verified, Login Successfully",
|
||||
"success_valid_otp": "Operation has been success, valid for 1 minutes",
|
||||
"success_logout": "Logout has been success",
|
||||
"failed": "Operation has been failed",
|
||||
"failed_access": "You're not allowed to access",
|
||||
"failed_access_otp": "Please provide valid OTP code",
|
||||
"failed_expired_otp": "Your OTP has been expired, Please provide valid OTP code",
|
||||
"failed_access_pin": "Please provide valid PIN code",
|
||||
"failed_try_pin": "Maximum try has been reached, please re-login MyTelkomcel",
|
||||
"failed_insert": "Data has been NOT successfully inserted",
|
||||
"failed_update": "Data has been NOT successfully updated",
|
||||
"failed_delete": "Data has been NOT successfully deleted",
|
||||
"failed_restore": "Data has been NOT successfully restored",
|
||||
"failed_save": "Data has been NOT successfully saved",
|
||||
"failed_view": "Data has been NOT successfully fetched",
|
||||
"failed_empty": "Data empty",
|
||||
"failed_data": "Please provide valid data",
|
||||
"failed_duplicate": "Duplicate data, please provide valid data",
|
||||
"failed_not_found": "Data not found, please provide valid data",
|
||||
"failed_usernot_found": "Username not found, please provide valid username",
|
||||
"failed_usernotorotp_found": "Username not found or wrong OTP, please provide valid username",
|
||||
"failed_otpfailedattempt_found": "OTP 3 Failed attempt, please try again",
|
||||
"failed_userorpin_notfound": "Username not found or wrong PIN, please provide valid username",
|
||||
"failed_forgotpin_notfound": "Username, Mother Full name, birth of date do not match",
|
||||
"failed_pinfailedattempt_found": "Pin 3 Failed attempts, Your account will be suspend",
|
||||
"failed_userorpasswordnot_found": "Username not found or wrong password, please provide valid username",
|
||||
"success_login": "Login Successfully",
|
||||
"failed_password": "Please provide valid password",
|
||||
"failed_limit_otp": "Please send OTP 1 minutes later",
|
||||
"failed_limit_link_code": "Please send verification link 1 minutes later",
|
||||
"failed_expired_token": "Token has been expired",
|
||||
"failed_token": "Your session has been expired, please re-login",
|
||||
"failed_add_point": "Add point failed, please try again later",
|
||||
"failed_logout": "Logout has been failed, please try again later",
|
||||
"failed_related": "Data has been NOT successfully saved, please check related data"
|
||||
}
|
||||
79
src/langs/lang.ts
Normal file
79
src/langs/lang.ts
Normal file
@ -0,0 +1,79 @@
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import { NextFunction, Request, Response } from 'express';
|
||||
|
||||
interface LanguageValue {
|
||||
success_insert?: string;
|
||||
success_update?: string;
|
||||
success_delete?: string;
|
||||
success_restore?: string;
|
||||
success_view?: string;
|
||||
success?: string;
|
||||
success_valid_otp?: string;
|
||||
success_logout?: string;
|
||||
pin_success_login?: string;
|
||||
|
||||
failed?: string;
|
||||
failed_access?: string;
|
||||
failed_access_otp?: string;
|
||||
failed_expired_otp?: string;
|
||||
failed_access_pin?: string;
|
||||
failed_try_pin?: string;
|
||||
failed_insert?: string;
|
||||
failed_update?: string;
|
||||
failed_delete?: string;
|
||||
failed_restore?: string;
|
||||
failed_save?: string;
|
||||
failed_view?: string;
|
||||
failed_empty?: string;
|
||||
failed_data?: string;
|
||||
failed_duplicate?: string;
|
||||
failed_not_found?: string;
|
||||
failed_usernot_found?: string;
|
||||
failed_forgotpin_notfound?: string;
|
||||
failed_pinfailedattempt_found?: string;
|
||||
failed_usernotorotp_found?: string;
|
||||
failed_otpfailedattempt_found?: string;
|
||||
failed_userorpin_notfound?: string;
|
||||
failed_userorpasswordnot_found?: string;
|
||||
failed_limit_otp?: string;
|
||||
failed_limit_link_code?: string;
|
||||
failed_expired_token?: string;
|
||||
failed_token?: string;
|
||||
failed_add_point?: string;
|
||||
failed_logout?: string;
|
||||
failed_related?: string;
|
||||
|
||||
//login
|
||||
otp_success_login?: string;
|
||||
success_login?: string;
|
||||
success_userexists?: string;
|
||||
failed_password?: string;
|
||||
}
|
||||
|
||||
export class Language {
|
||||
static lang_init: LanguageValue = {};
|
||||
static lang: LanguageValue = {};
|
||||
|
||||
static setup() {
|
||||
const fileLang: any = fs.readFileSync(
|
||||
path.join(__dirname, '../langs/json/en.json')
|
||||
);
|
||||
Language.lang_init['en'] = JSON.parse(fileLang.toString('utf8'));
|
||||
}
|
||||
|
||||
static apply = (req: Request, res: Response, next: NextFunction) => {
|
||||
const acceptLanguageHeader = req.get('Accept-Language') as string | null;
|
||||
if (!acceptLanguageHeader) {
|
||||
//default
|
||||
req.params.language = 'en';
|
||||
} else {
|
||||
req.params.language = 'en';
|
||||
// req.params.language = acceptLanguageHeader.substring(0, 2).toLowerCase();
|
||||
}
|
||||
|
||||
Language.lang = Language.lang_init[req.params.language];
|
||||
|
||||
return next();
|
||||
}
|
||||
}
|
||||
25
src/routes/private.ts
Normal file
25
src/routes/private.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import express from 'express';
|
||||
import { Language } from '../langs/lang';
|
||||
import JwtHelper from '../helpers/jwt';
|
||||
// import { EventController } from '../controllers/event';
|
||||
|
||||
export class RoutePrivate {
|
||||
static setup(app: express.Application) {
|
||||
|
||||
app.use(Language.apply)
|
||||
|
||||
JwtHelper.secure(app);
|
||||
|
||||
// app.get('/api/auth/getprofile', AuthController.getprofile)
|
||||
// app.get('/api/reguler/list', RegulersController.list)
|
||||
// app.get('/api/reguler/export', RegulersController.export)
|
||||
// app.post('/api/reguler/create', RegulersController.create)
|
||||
// // app.put('/api/reguler/update/:id', RegulersController.update)
|
||||
// app.put('/api/reguler/update_profile', RegulersController.updateProfile)
|
||||
// app.put('/api/reguler/update_password', RegulersController.updatePassword)
|
||||
// app.get('/api/reguler/detail/:id', RegulersController.detail)
|
||||
// app.delete('/api/reguler/delete/:id/:hard', RegulersController.delete)
|
||||
// app.put('/api/reguler/restore/:id', RegulersController.restore)
|
||||
|
||||
}
|
||||
}
|
||||
19
src/routes/public.ts
Normal file
19
src/routes/public.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import express from 'express';
|
||||
|
||||
import { EventController } from '../controllers/event';
|
||||
import { Language } from '../langs/lang';
|
||||
import multer from 'multer';
|
||||
|
||||
const upload = multer({ storage: multer.memoryStorage() });
|
||||
|
||||
export class RoutePublic {
|
||||
static setup(app: express.Application) {
|
||||
|
||||
|
||||
app.use(Language.apply);
|
||||
|
||||
app.post('/api/dooraccess/logs', upload.any(), EventController.index)
|
||||
app.get('/api/dooraccess/logrekon', EventController.logrekon)
|
||||
|
||||
}
|
||||
}
|
||||
29
src/server.ts
Normal file
29
src/server.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import express from 'express';
|
||||
import { CorsHelper } from './helpers/express/cors';
|
||||
import { CompressionHelper } from './helpers/express/compression';
|
||||
import { MorganHelper } from './helpers/express/morgan';
|
||||
import { JsonHelper } from './helpers/express/json';
|
||||
import { UrlencodedHelper } from './helpers/express/urlencoded';
|
||||
import { OrmHelper } from './helpers/orm';
|
||||
import { RoutePrivate } from './routes/private';
|
||||
import { RoutePublic } from './routes/public';
|
||||
import { Language } from './langs/lang';
|
||||
import { SwaggerHelper } from './helpers/express/swagger';
|
||||
import { TrustProxyHelper } from './helpers/express/trust_proxy';
|
||||
|
||||
|
||||
const app = express();
|
||||
|
||||
CorsHelper.setup(app);
|
||||
CompressionHelper.setup(app);
|
||||
MorganHelper.setup(app);
|
||||
JsonHelper.setup(app);
|
||||
UrlencodedHelper.setup(app);
|
||||
OrmHelper.setup();
|
||||
Language.setup();
|
||||
TrustProxyHelper.setup(app);
|
||||
SwaggerHelper.setup(app);
|
||||
RoutePublic.setup(app);
|
||||
RoutePrivate.setup(app);
|
||||
|
||||
export { app };
|
||||
78
src/swagger/builder.js
Normal file
78
src/swagger/builder.js
Normal file
@ -0,0 +1,78 @@
|
||||
const swaggerAutogen = require('swagger-autogen')({ openapi: '3.0.0' });
|
||||
const config = require('config');
|
||||
const { verify } = require('jsonwebtoken');
|
||||
|
||||
const doc = {
|
||||
info: {
|
||||
title: config.get('app.name'),
|
||||
description: config.get('app.description'),
|
||||
version: config.get('app.version')
|
||||
},
|
||||
servers: [
|
||||
{
|
||||
url: config.get('server.host_swagger'),
|
||||
description: 'Environtment ' + config.get('app.env')
|
||||
},
|
||||
],
|
||||
schemas: ['http', 'https'],
|
||||
components: {
|
||||
schemas: {
|
||||
username: {
|
||||
$username: "Users"
|
||||
},
|
||||
loginagent: {
|
||||
$username: "67075666667",
|
||||
$password: "87654321"
|
||||
},
|
||||
loginreguler: {
|
||||
$msisdn: "67075666666",
|
||||
$otp: "12345"
|
||||
},
|
||||
verifyotp: {
|
||||
$msisdn: "67074254072",
|
||||
$otp: "12345",
|
||||
$code: "d8ecef150ab78ccf1823a399b12b55264369164b45eb87e4eec6a5b94405f699"
|
||||
},
|
||||
verifypin: {
|
||||
$customerid: "d8ecef150ab78ccf1823a399b12b55264369164b45eb87e4eec6a5b94405f699",
|
||||
$fcmtoken: "d8ecef150ab78ccf1823a399b12b55264369164b45eb87e4eec6a5b94405f699",
|
||||
$lng: "20.470202",
|
||||
$lat: "11.867351",
|
||||
$os: "Android",
|
||||
$uniqueid: "d8ecef150ab78ccf1823a399b12b55264369164b45eb87e4eec6a5b94405f699",
|
||||
$pin: "123456"
|
||||
},
|
||||
changepin: {
|
||||
$customerid: "d8ecef150ab78ccf1823a399b12b55264369164b45eb87e4eec6a5b94405f699",
|
||||
$pin: "123456"
|
||||
},
|
||||
forgotpin: {
|
||||
$fullname: "Fatih",
|
||||
$mother_fullname: "Yana",
|
||||
$date_birth: "2000-01-01",
|
||||
$msisdn: "67074254072"
|
||||
}
|
||||
},
|
||||
parameters: {
|
||||
|
||||
},
|
||||
securitySchemes: {
|
||||
bearerAuth: {
|
||||
type: 'http',
|
||||
scheme: 'bearer',
|
||||
format: 'JWT'
|
||||
},
|
||||
}
|
||||
},
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const outputFile = './swagger.json';
|
||||
const routes = ['../routes/private.ts', '../routes/public.ts'];
|
||||
|
||||
swaggerAutogen(outputFile, routes, doc);
|
||||
|
||||
Reference in New Issue
Block a user