diff --git a/src/Controllers/AuditorController.ts b/src/Controllers/AuditorController.ts index a060e8ade79b8308be9c611e34d74f834f6762a8..280ec472c5bc8599b7ca0520daf2ba7df312d591 100644 --- a/src/Controllers/AuditorController.ts +++ b/src/Controllers/AuditorController.ts @@ -1,7 +1,7 @@ import { Request, Response, Router, } from 'express'; -import Auditor from '../Services/Auditor'; +import Auditor from '../Services/AuditorService'; import { logAndRespond } from './Utils'; const router = Router(); @@ -17,6 +17,18 @@ const auditGet = async (req: Request, res: Response) => { } }; +const calculationAuditGet = async (req: Request, res: Response) => { + try { + const audits = await + Auditor.getCalculationsAudit(req.body.userIds, req.body.dateFrom, req.body.dateTo); + return logAndRespond(res, 200, 'send', audits, 'info', null, null); + } catch (error) { + const e = error as Error; + return logAndRespond(res, 400, 'json', { error: e.message }, 'info', null, null); + } +}; + router.get('/', auditGet); +router.post('/calculations', calculationAuditGet); export default router; diff --git a/src/Controllers/CalculatorController.ts b/src/Controllers/CalculatorController.ts index e5c3b6c6dd4fecc8a1ba27cb39866b59e0749019..5a0eae49eaaf33d56b31207d13bac7f78fb1f423 100644 --- a/src/Controllers/CalculatorController.ts +++ b/src/Controllers/CalculatorController.ts @@ -4,9 +4,8 @@ import { import { Validator } from 'express-json-validator-middleware'; import CalculatorService from '../Services/CalculatorService'; import CalculatorResponse from '../DTOs/CalculatorResponseDTO'; -import logger from '../Logger/logger'; import getRepBody from '../Schemas/getRepBody'; -import { audit } from '../Services/Auditor'; +import { calculationAudit } from '../Services/AuditorService'; import { logAndRespond } from './Utils'; const router = Router(); @@ -14,11 +13,11 @@ const router = Router(); const { validate } = new Validator({}); const getREP: Handler = async (req: Request, res: Response) => { - const { groups, extraData } = req.body; + const { groups, extraData, isTemplateUsed } = req.body; try { const EnergyReq: CalculatorResponse = await CalculatorService .calculateEnergeticRequirement(groups, extraData); - audit(req, 'Calculó el REP'); + calculationAudit(req, isTemplateUsed); return logAndRespond(res, 200, 'send', EnergyReq, 'info', null, null); } catch (error) { const e = error as Error; diff --git a/src/Controllers/ParameterController.ts b/src/Controllers/ParameterController.ts index 9bf421395bcc905ce89c7e3f5df8d8e3003cb516..dad57365c1346ad186df17a4fa9ca14da3de286a 100644 --- a/src/Controllers/ParameterController.ts +++ b/src/Controllers/ParameterController.ts @@ -5,7 +5,7 @@ import { Validator } from 'express-json-validator-middleware'; import ParameterType from '../Enum/ParameterType'; import logger from '../Logger/logger'; import updateParameterValueBody from '../Schemas/updateParameterValueBody'; -import { audit } from '../Services/Auditor'; +import { audit } from '../Services/AuditorService'; import ParameterService from '../Services/ParameterService'; import { logAndRespond } from './Utils'; diff --git a/src/Controllers/SheetController.ts b/src/Controllers/SheetController.ts index f9c99ed99f770f128c35565c73da06748819789a..965b5354ae67399d0110100a4a1da689b03bb1c9 100644 --- a/src/Controllers/SheetController.ts +++ b/src/Controllers/SheetController.ts @@ -2,9 +2,8 @@ import { Handler, Request, Response, Router, } from 'express'; import SheetService from '../Services/SheetService'; -import logger from '../Logger/logger'; import AgeGroupJSON from '../DTOs/AgeGroupJSON'; -import { audit } from '../Services/Auditor'; +import { audit } from '../Services/AuditorService'; import { logAndRespond } from './Utils'; const router = Router(); diff --git a/src/Loaders/ParameterDataBaseLoader.ts b/src/Loaders/ParameterDataBaseLoader.ts index ec44b292f62defe04b8d62a87369c9bb47aac7b1..15989a857d3ffb4761a034f9ecfda1c1aab79f55 100644 --- a/src/Loaders/ParameterDataBaseLoader.ts +++ b/src/Loaders/ParameterDataBaseLoader.ts @@ -5,6 +5,7 @@ import DefaultExtraDataDTO from '../DTOs/DefaultExtraDataDTO'; import DefaultWeightDTO from '../DTOs/DefaultWeightDTO'; import EquationConstantDTO from '../DTOs/EquationConstantDTO'; import Auditor from '../Models/Auditor'; +import CalculationAuditor from '../Models/CalculationAuditor'; import DefaultExtraData from '../Models/DefaultExtraData'; import DefaultWeight from '../Models/DefaultWeight'; import EquationConstant from '../Models/EquationConstant'; @@ -53,6 +54,7 @@ async function initParameterDataBase(): Promise<void> { }); FAQ.sync({ force: true }); Auditor.sync({ force: false }); + CalculationAuditor.sync({ force: false }); } export default { initParameterDataBase }; diff --git a/src/Models/CalculationAuditor.ts b/src/Models/CalculationAuditor.ts new file mode 100644 index 0000000000000000000000000000000000000000..64b643442859819a3f71d651c6d370117ffd038d --- /dev/null +++ b/src/Models/CalculationAuditor.ts @@ -0,0 +1,30 @@ +import { DataTypes, Model } from 'sequelize'; +import sequelize from '../Loaders/ParameterDataBase'; + +class CalculationAuditor extends Model { + id!: number; + + user_id!: number; + + isTemplateUsed!: boolean; + + createdAt!: string; +} + +CalculationAuditor.init({ + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + }, + user_id: DataTypes.INTEGER, + isTemplateUsed: DataTypes.TINYINT, +}, +{ + sequelize, + modelName: 'CalculationAuditor', + timestamps: true, +}); + +// BD: ID // USER ID // IS TEMPLATE USED // CREATED AT +export default CalculationAuditor; diff --git a/src/Services/Auditor.ts b/src/Services/AuditorService.ts similarity index 56% rename from src/Services/Auditor.ts rename to src/Services/AuditorService.ts index 7d5134e14511145484afd86138bf1094cc3845b3..9762a7bcc1a2f6ee1f8102148cc30bc135682344 100644 --- a/src/Services/Auditor.ts +++ b/src/Services/AuditorService.ts @@ -1,84 +1,148 @@ -import AuditDTO from '../DTOs/AuditDTO'; -import Paginator from '../interfaces/paginator.interface'; -import Auditor from '../Models/Auditor'; -import UserAPI from './UserAPI'; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export const audit = (request: any, action: string): void => { - const userId = request.user_id; - Auditor.create({ user_id: userId, action }); -}; - -const listAudits = async (limit: number, offset: number): Promise<Paginator<Auditor>> => { - let options = {}; - if (limit >= 1 && offset >= 0) { - options = { - limit, - offset, - }; - } - const res = await Auditor.findAndCountAll({ - attributes: [ - 'id', 'user_id', 'action', 'createdAt', - ], - ...options, - }); - return res; -}; - -const getAudit = async (cant: number, page: number, token: any) => { - const offset = cant * (page - 1); - const audits: Paginator<Auditor> = await listAudits(cant, offset); - const ids: number[] = []; - audits.rows.forEach((auditor: Auditor) => { - if (!ids.includes(auditor.user_id)) { - ids.push(auditor.user_id); - } - }); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const users = await UserAPI.listUsersById({ userIds: ids }, token) as any[]; - const usersMap: Map<number, any> = new Map(); - users.forEach((user) => { - usersMap.set(user.id, user); - }); - const userAudits: AuditDTO[] = []; - audits.rows.forEach((auditor) => { - const user = usersMap.get(auditor.user_id); - const userAudit: AuditDTO = { - id: auditor.id, - email: user.email, - user_name: user.name, - organization_name: user.organization, - date: auditor.createdAt, - action: auditor.action, - }; - userAudits.push(userAudit); - }); - return { - count: audits.count, - list: userAudits, - }; -}; - -// { -// count:number, -// list:[{id,user_name,full_name, organization_name, date, action}] -// } - -// export const getAudit = (cant: number, page: number) => { -// const init = (cant * page) - cant; -// const end = cant * page; -// Auditor.findAll({ -// where: { -// ageRange: ageBracket as string, -// sex: sex as string, -// }, -// order: [['order', 'ASC']], -// }) -// }; - -// BD: UUID // USER ID // ACTION // TIME - -export default { - getAudit, -}; +// TODO: Get rid of all the 'any' mentions +/* eslint-disable @typescript-eslint/no-explicit-any */ + +import { Op } from 'sequelize'; +import AuditDTO from '../DTOs/AuditDTO'; +import Paginator from '../interfaces/paginator.interface'; +import Auditor from '../Models/Auditor'; +import CalculationAuditor from '../Models/CalculationAuditor'; +import UserAPI from './UserAPI'; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export const audit = (request: any, action: string): void => { + const userId = request.user_id; + Auditor.create({ user_id: userId, action }); +}; + +export const calculationAudit = (request: any, templateUsed: boolean): void => { + const userId = request.user_id; + CalculationAuditor.create({ user_id: userId, isTemplateUsed: templateUsed }); +}; + +const listAudits = async (limit: number, offset: number): Promise<Paginator<Auditor>> => { + let options = {}; + if (limit >= 1 && offset >= 0) { + options = { + limit, + offset, + }; + } + const res = await Auditor.findAndCountAll({ + attributes: [ + 'id', 'user_id', 'action', 'createdAt', + ], + ...options, + }); + return res; +}; + +const calculationAudits = async (userIds: number[], dateFrom: string, + dateTo: string, isTemplateUsed: boolean) => { + const whereStatement: any = {}; + + if (userIds.length > 0) { + whereStatement.user_id = userIds; + } + + if (dateFrom !== '' && dateTo !== '') { + try { + const from = new Date(dateFrom); + const to = new Date(dateTo); + whereStatement.createdAt = { [Op.between]: [from, to] }; + } catch (error) { + const e = error as Error; + throw e; + } + } + + whereStatement.isTemplateUsed = isTemplateUsed; + + const res = await CalculationAuditor.count({ + attributes: [ + 'id', 'user_id', 'isTemplateUsed', 'createdAt', + ], + where: whereStatement, + }); + + return res; +}; + +const getAudit = async (cant: number, page: number, token: any) => { + const offset = cant * (page - 1); + const audits: Paginator<Auditor> = await listAudits(cant, offset); + const ids: number[] = []; + audits.rows.forEach((auditor: Auditor) => { + if (!ids.includes(auditor.user_id)) { + ids.push(auditor.user_id); + } + }); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const users = await UserAPI.listUsersById({ userIds: ids }, token) as any[]; + const usersMap: Map<number, any> = new Map(); + users.forEach((user) => { + usersMap.set(user.id, user); + }); + const userAudits: AuditDTO[] = []; + audits.rows.forEach((auditor) => { + const user = usersMap.get(auditor.user_id); + const userAudit: AuditDTO = { + id: auditor.id, + email: user.email, + user_name: user.name, + organization_name: user.organization, + date: auditor.createdAt, + action: auditor.action, + }; + userAudits.push(userAudit); + }); + return { + count: audits.count, + list: userAudits, + }; +}; + +const getCalculationsAudit = async (userIds: number[], dateFrom: string, dateTo: string) => { + const calculationsByHand: number = await calculationAudits(userIds, dateFrom, dateTo, false); + const calculationsWithTemplate: number = await calculationAudits(userIds, dateFrom, dateTo, true); + + return [ + { + name: 'Cálculos a mano', + value: calculationsByHand, + extra: { + code: 'cam', + }, + }, + { + name: 'Cálculos usando plantilla', + value: calculationsWithTemplate, + extra: { + code: 'cup', + }, + }, + ]; +}; + +// { +// count:number, +// list:[{id,user_name,full_name, organization_name, date, action}] +// } + +// export const getAudit = (cant: number, page: number) => { +// const init = (cant * page) - cant; +// const end = cant * page; +// Auditor.findAll({ +// where: { +// ageRange: ageBracket as string, +// sex: sex as string, +// }, +// order: [['order', 'ASC']], +// }) +// }; + +// BD: UUID // USER ID // ACTION // TIME + +export default { + getAudit, + getCalculationsAudit, +};