diff --git a/src/controller/certificate/certificate.controller.ts b/src/controller/certificate/certificate.controller.ts index 0515cef..2736fa3 100644 --- a/src/controller/certificate/certificate.controller.ts +++ b/src/controller/certificate/certificate.controller.ts @@ -1,8 +1,9 @@ -import { Controller, Delete, Get, InternalServerErrorException, Param } from "@nestjs/common"; +import { Body, Controller, Delete, Get, InternalServerErrorException, Param, Post } from "@nestjs/common"; import { renderToString } from "solid-js/web"; import { Certs } from "../../views/Certs"; import { template } from "./certificate.template"; import { CertificateService } from "./certificate.service"; +import { CertificateDto } from "./certificate.dto"; @Controller("certificate") export class CertificateController { @@ -21,6 +22,12 @@ export class CertificateController { } + @Post() + async create(@Body() subjectDto: CertificateDto) { + await this.certificateService.create(subjectDto); + } + + @Delete(":id") async delete(@Param() param: {id: number}) { console.log(param); diff --git a/src/controller/certificate/certificate.dto.ts b/src/controller/certificate/certificate.dto.ts new file mode 100644 index 0000000..cade18d --- /dev/null +++ b/src/controller/certificate/certificate.dto.ts @@ -0,0 +1,5 @@ +export class CertificateDto { + personId: number; + subjectId: number; + date: string; +} diff --git a/src/controller/certificate/certificate.service.ts b/src/controller/certificate/certificate.service.ts index e34ca3b..da754a4 100644 --- a/src/controller/certificate/certificate.service.ts +++ b/src/controller/certificate/certificate.service.ts @@ -1,15 +1,23 @@ -import { Injectable } from "@nestjs/common"; +import { BadRequestException, Injectable, InternalServerErrorException } from "@nestjs/common"; import { DataSource, Repository } from "typeorm"; import { RegistroGIE } from "../../model/RegistroGIE/registroGIE.entity"; import { RegisterReturn } from "../../types/RegisterReturn"; +import { CertificateDto } from "./certificate.dto"; +import { Persona } from "../../model/Persona/persona.entity"; +import { CursoGIE } from "../../model/CursoGIE/cursoGIE.entity"; +import { data } from "autoprefixer"; @Injectable() export class CertificateService { registroGIERepository: Repository; + personGIERepository: Repository; + subjectRepo: Repository; constructor(private dataSource: DataSource) { this.registroGIERepository = dataSource.getRepository(RegistroGIE); + this.personGIERepository = dataSource.getRepository(Persona); + this.subjectRepo = dataSource.getRepository(CursoGIE); } async getByDni(dni: string): Promise> { @@ -31,6 +39,70 @@ export class CertificateService { })); } + async create(data: CertificateDto) { + const certificate = new RegistroGIE(); + + // Get data for legacy fields + const person = await this.personGIERepository.findOneBy({id: data.personId}); + const subject = await this.subjectRepo.findOneBy({id: data.subjectId}); + + if (person === null) { + throw new BadRequestException("personId es invalido"); + } + if (subject === null) { + throw new BadRequestException("subjectId es invalido"); + } + + certificate.dni = person.dni; + // For some reason this is `last names` `names` + certificate.nombre = `${person.apellidoPaterno} ${person.apellidoMaterno} ${person.nombres}`; + certificate.curso = data.subjectId; + certificate.codigo = await this.getNextRegisterCode(data.subjectId); + certificate.fecha_actual = new Date(); + certificate.fecha_inscripcion = new Date(data.date); + certificate.curso_nombre = subject.nombre; + + certificate.persona = person; + certificate.cursoGIE = subject; + + try { + await this.registroGIERepository.save(certificate); + } catch (e) { + throw new InternalServerErrorException("Error creando registro"); + } + } + + async getNextRegisterCode(subjectId: number): Promise { + + // Matpel 1, 2 & 3 share codes + // TODO: Get actual ids from db instead of hard coding them? + if (subjectId === 10 || subjectId === 11 || subjectId === 12) { + const res = await this.registroGIERepository + .createQueryBuilder("registro") + .select("MAX(registro.codigo)") + .where("registro.curso = :m1", {m1: 10}) + .orWhere("registro.curso = :m2", {m2: 11}) + .orWhere("registro.curso = :m3", {m3: 12}) + .getRawOne(); + + const {"MAX(`registro`.`codigo`)": nextRegisterCode} = res; + + // TODO?: Make atomic to avoid race conditions? + return nextRegisterCode + 1; + } else { + const res = await this.registroGIERepository + .createQueryBuilder("registro") + .select("MAX(registro.codigo)") + .where("registro.curso = :subjectId", {subjectId}) + .getRawOne(); + + const {"MAX(`registro`.`codigo`)": nextRegisterCode} = res; + + // TODO?: Make atomic to avoid race conditions? + return nextRegisterCode + 1; + } + } + async deleteById(id: number) { // TODO: Should do logical deletion const certificate = await this.registroGIERepository.findOneBy({ diff --git a/src/controller/subject/subject.controller.ts b/src/controller/subject/subject.controller.ts index 5a10f96..0b746c8 100644 --- a/src/controller/subject/subject.controller.ts +++ b/src/controller/subject/subject.controller.ts @@ -1,5 +1,6 @@ -import { Controller, Get } from "@nestjs/common"; +import { Body, Controller, Get, Param, Post } from "@nestjs/common"; import { SubjectService } from "./subject.service"; +import { CertificateDto } from "../certificate/certificate.dto"; @Controller("subject") export class SubjectController { @@ -10,4 +11,5 @@ export class SubjectController { async getAll() { return this.subjectService.getAll(); } + } diff --git a/src/views/Certs.tsx b/src/views/Certs.tsx index 6fbcb57..a56110f 100644 --- a/src/views/Certs.tsx +++ b/src/views/Certs.tsx @@ -15,7 +15,7 @@ export function Certs() { - + ); } diff --git a/src/views/components/NewRegister.tsx b/src/views/components/NewRegister.tsx index b5915e8..c348c07 100644 --- a/src/views/components/NewRegister.tsx +++ b/src/views/components/NewRegister.tsx @@ -1,4 +1,4 @@ -import { createSignal, onMount } from "solid-js"; +import { createSignal, onMount, Show } from "solid-js"; import type { CursoGIE } from "../../model/CursoGIE/cursoGIE.entity"; import { SearchableSelect } from "./NewRegister/SearchableSelect"; import { JSX } from "solid-js/jsx-runtime"; @@ -9,7 +9,7 @@ type HTMLEventFn = JSX.EventHandlerUnion = JSON.parse("[{\"id\":1,\"nombre\":\"Manejo Defensivo\",\"codigo\":302,\"otro\":\"\"},{\"id\":2,\"nombre\":\"Mecanica Basica\",\"codigo\":100,\"otro\":\"\"},{\"id\":3,\"nombre\":\"4x4\",\"codigo\":82,\"otro\":\"\"},{\"id\":4,\"nombre\":\"Cargador Frontal\",\"codigo\":32,\"otro\":\"\"},{\"id\":5,\"nombre\":\"Excavadora\",\"codigo\":7,\"otro\":\"\"},{\"id\":6,\"nombre\":\"Retroexcavadora\",\"codigo\":14,\"otro\":\"\"},{\"id\":7,\"nombre\":\"Volquete\",\"codigo\":63,\"otro\":\"\"},{\"id\":8,\"nombre\":\"Minicargador\",\"codigo\":5,\"otro\":\"\"},{\"id\":9,\"nombre\":\"Montacargas\",\"codigo\":6,\"otro\":\"\"},{\"id\":10,\"nombre\":\"Matpel I\",\"codigo\":616,\"otro\":\"\"},{\"id\":11,\"nombre\":\"Matpel II\",\"codigo\":1,\"otro\":\"\"},{\"id\":12,\"nombre\":\"Matpel III\",\"codigo\":1,\"otro\":\"\"},{\"id\":13,\"nombre\":\"Matpel IV\",\"codigo\":1,\"otro\":\"\"},{\"id\":14,\"nombre\":\"Supervisor Escolta\",\"codigo\":41,\"otro\":\"\"},{\"id\":15,\"nombre\":\"Herramientas de Gestion\",\"codigo\":86,\"otro\":\"\"},{\"id\":16,\"nombre\":\"Primeros Auxilios\",\"codigo\":249,\"otro\":\"\"},{\"id\":17,\"nombre\":\"Lucha contra Incendios\",\"codigo\":69,\"otro\":\"\"},{\"id\":18,\"nombre\":\"Seguridad Minera\",\"codigo\":17,\"otro\":\"\"},{\"id\":19,\"nombre\":\"SBComportamiento\",\"codigo\":5,\"otro\":\"\"},{\"id\":20,\"nombre\":\"Primer Respondedor\",\"codigo\":132,\"otro\":\"\"},{\"id\":21,\"nombre\":\"Operador Multiple\",\"codigo\":15,\"otro\":\"\"},{\"id\":22,\"nombre\":\"IPERC\",\"codigo\":66,\"otro\":\"\"},{\"id\":23,\"nombre\":\"RITRA\",\"codigo\":6,\"otro\":\"\"},{\"id\":24,\"nombre\":\"Rodillo\",\"codigo\":11,\"otro\":\"\"},{\"id\":25,\"nombre\":\"Fatiga y Somnolencia\",\"codigo\":63,\"otro\":\"\"},{\"id\":26,\"nombre\":\"Bioseguridad y la Salud Ocupacional\",\"codigo\":17,\"otro\":\"\"},{\"id\":27,\"nombre\":\"Seguridad y Salud en Mineria\",\"codigo\":26,\"otro\":\"\"},{\"id\":28,\"nombre\":\"Espacios Confinados\",\"codigo\":23,\"otro\":\"\"},{\"id\":29,\"nombre\":\"Manipulación de productos químicos\",\"codigo\":201,\"otro\":\"\"},{\"id\":30,\"nombre\":\"Interpretación del Reglamento Interno de Transito\",\"codigo\":16,\"otro\":\"\"},{\"id\":31,\"nombre\":\"DERRAMES DE HIDROCARBUROS\",\"codigo\":20,\"otro\":\"\"},{\"id\":32,\"nombre\":\"PREVENCIÓN Y CONTROL DE COVID-19\",\"codigo\":18,\"otro\":\"\"},{\"id\":33,\"nombre\":\"BIOSEGURIDAD EN EL TRABAJO\",\"codigo\":18,\"otro\":\"\"},{\"id\":34,\"nombre\":\"Seguridad en la Operación\",\"codigo\":16,\"otro\":\"\"},{\"id\":35,\"nombre\":\"IMPLEMENTACIÓN DE PLAN DE VIGILANCIA \",\"codigo\":121,\"otro\":\"\"},{\"id\":36,\"nombre\":\"ESPECIALIZACION PERFORACION Y VOLADURA\",\"codigo\":102,\"otro\":\"\"},{\"id\":37,\"nombre\":\"SEGURIDAD Y SALUD EN EL TRABAJO frente al COVID-19\",\"codigo\":81,\"otro\":\"\"},{\"id\":38,\"nombre\":\"Telehandler\",\"codigo\":51,\"otro\":\"\"},{\"id\":39,\"nombre\":\"CAMIÓN GRÚA\",\"codigo\":86,\"otro\":\"\"},{\"id\":40,\"nombre\":\"Supervisor de trabajos en alto riesgo\",\"codigo\":51,\"otro\":\"\"},{\"id\":41,\"nombre\":\"Técnicas preventivas en la operación de maquinaria\",\"codigo\":26,\"otro\":\"\"},{\"id\":42,\"nombre\":\"Prevención y protección contra incendios\",\"codigo\":48,\"otro\":\"\"},{\"id\":44,\"nombre\":\"Salud ocupacional y primeros auxilios\",\"codigo\":30,\"otro\":\"\"},{\"id\":43,\"nombre\":\"Manejo defensivo y transporte personal\",\"codigo\":30,\"otro\":\"\"},{\"id\":45,\"nombre\":\"Seguridad con materiales peligrosos\",\"codigo\":51,\"otro\":\"\"},{\"id\":46,\"nombre\":\"Operador CAT\",\"codigo\":25,\"otro\":\"\"},{\"id\":47,\"nombre\":\"Brigada de emergencia\",\"codigo\":25,\"otro\":\"\"},{\"id\":48,\"nombre\":\"Seguridad en trabajos de alto riesgo\",\"codigo\":25,\"otro\":\"\"},{\"id\":49,\"nombre\":\"Supervisor de seguridad minera e industrial\",\"codigo\":50,\"otro\":\"\"},{\"id\":50,\"nombre\":\"Logística, transporte, almacenaje y manutención\",\"codigo\":25,\"otro\":\"\"},{\"id\":51,\"nombre\":\"Operación segura de montacargas\",\"codigo\":25,\"otro\":\"\"},{\"id\":52,\"nombre\":\"PRIMEROS AUXILIOS (BIOSEGURIDAD) frente al COVID -\",\"codigo\":25,\"otro\":\"\"},{\"id\":53,\"nombre\":\"SEGURIDAD Y SALUD EN EL TRABAJO, bajo normativas a\",\"codigo\":25,\"otro\":\"\"},{\"id\":54,\"nombre\":\"Tractor Oruga\",\"codigo\":25,\"otro\":\"\"},{\"id\":55,\"nombre\":\"Operador SCOOPTRAMS\",\"codigo\":50,\"otro\":\"\"},{\"id\":56,\"nombre\":\"Especialización operador de puente grúa\",\"codigo\":25,\"otro\":\"\"},{\"id\":57,\"nombre\":\"Caja Fuller\",\"codigo\":25,\"otro\":\"\"},{\"id\":58,\"nombre\":\"Especialización Cargador Frontal\",\"codigo\":25,\"otro\":\"\"},{\"id\":59,\"nombre\":\"Operador Jumbo\",\"codigo\":25,\"otro\":\"\"},{\"id\":60,\"nombre\":\"Rescatista Industrial\",\"codigo\":25,\"otro\":\"\"},{\"id\":66,\"nombre\":\"Camión Minero 797F CAT\",\"codigo\":25,\"otro\":\"\"},{\"id\":61,\"nombre\":\"Investigación de accidentes e incidentes\",\"codigo\":25,\"otro\":\"\"},{\"id\":62,\"nombre\":\"Uso y Manejo de Extintores\",\"codigo\":32,\"otro\":\"\"},{\"id\":65,\"nombre\":\"Motoniveladora\",\"codigo\":25,\"otro\":\"\"},{\"id\":67,\"nombre\":\"Sistema de Comando de Incidentes SCI\",\"codigo\":25,\"otro\":\"\"},{\"id\":68,\"nombre\":\"Seguridad en la Operación de Camión Minero de Alto\",\"codigo\":25,\"otro\":\"\"},{\"id\":69,\"nombre\":\"Seguridad Minera frente al Covid-19\",\"codigo\":28,\"otro\":\"\"},{\"id\":70,\"nombre\":\"Operador de Camión Lubricador\",\"codigo\":25,\"otro\":\"\"},{\"id\":71,\"nombre\":\"RIGGER O Auxiliar de Operador Grua\",\"codigo\":28,\"otro\":\"\"},{\"id\":72,\"nombre\":\"Seguridad en la Operacion de Maquinaria Pesada\",\"codigo\":61,\"otro\":\"\"},{\"id\":73,\"nombre\":\"Operador de Elevador de Tijera\",\"codigo\":70,\"otro\":\"\"},{\"id\":74,\"nombre\":\"Trabajos en Caliente\",\"codigo\":24,\"otro\":\"\"},{\"id\":75,\"nombre\":\"Operador Grua Articulada ANSI/ASME\",\"codigo\":26,\"otro\":\"\"},{\"id\":76,\"nombre\":\"Operador Calificado KOMATSU\",\"codigo\":26,\"otro\":\"\"},{\"id\":77,\"nombre\":\"Cuidado del Medio AMbiente\",\"codigo\":26,\"otro\":\"\"},{\"id\":78,\"nombre\":\"Campaña \\\"No al exceso de velocidad\\\"\",\"codigo\":26,\"otro\":\"\"},{\"id\":79,\"nombre\":\"INCENDIO EN VEHÍCULOS\",\"codigo\":26,\"otro\":\"\"},{\"id\":80,\"nombre\":\"Sensibilización Primeros Auxilios\",\"codigo\":26,\"otro\":\"\"},{\"id\":81,\"nombre\":\"Inspecciones de Seguridad\",\"codigo\":27,\"otro\":\"\"},{\"id\":82,\"nombre\":\"Transporte de Personal Industrial\",\"codigo\":30,\"otro\":\"\"},{\"id\":83,\"nombre\":\"BIOSEGURIDAD EN INDUSTRIA Y MINERIA EN COVID-19\",\"codigo\":25,\"otro\":\"\"},{\"id\":84,\"nombre\":\"CAMPAÑA DE NO ALCOHOL\",\"codigo\":10,\"otro\":\"\"},{\"id\":102,\"nombre\":\"OPERACIÓN, LOGÍSTICA Y ALMACENES\",\"codigo\":35,\"otro\":\"\"},{\"id\":87,\"nombre\":\"Trabajos en Altura \",\"codigo\":21,\"otro\":\"\"},{\"id\":88,\"nombre\":\"PERFORACIÓN Y VOLADURA\",\"codigo\":0,\"otro\":\"\"},{\"id\":90,\"nombre\":\"SEGURIDAD Y SALUD EN EL TRABAJO\",\"codigo\":35,\"otro\":\"\"},{\"id\":92,\"nombre\":\"PREVENCIÓN DE RIESGOS LABORALES\",\"codigo\":25,\"otro\":\"\"},{\"id\":94,\"nombre\":\"MANEJO DEFENSIVO 4X4\",\"codigo\":0,\"otro\":\"\"},{\"id\":95,\"nombre\":\"MANEJO DEFENSIVO Y TRANSPORTE PERSONAL\",\"codigo\":35,\"otro\":\"\"},{\"id\":96,\"nombre\":\"CONDUCCIÓN SEGURA\",\"codigo\":35,\"otro\":\"\"},{\"id\":97,\"nombre\":\"MANEJO Y MANTENIMIENTO OPERADOR DE SEMITRAILER\",\"codigo\":25,\"otro\":\"\"},{\"id\":98,\"nombre\":\"OPERADOR CAMION CISTERNA\",\"codigo\":25,\"otro\":\"\"},{\"id\":99,\"nombre\":\"SEMITRAILER INTERNATIONAL\",\"codigo\":25,\"otro\":\"\"},{\"id\":100,\"nombre\":\"Procedimientos de carga y descarga de combustibles\",\"codigo\":50,\"otro\":\"\"},{\"id\":101,\"nombre\":\"Transporte seguro de materiales y residuos peligro\",\"codigo\":50,\"otro\":\"\"},{\"id\":103,\"nombre\":\"GESTIÓN DE ALMACENES EN GENERAL\",\"codigo\":35,\"otro\":\"\"},{\"id\":104,\"nombre\":\"Operación Segura para Transporte de Hidrocarburos \",\"codigo\":35,\"otro\":\"\"},{\"id\":105,\"nombre\":\"COMO EVITAR ACTOS SUBESTANDAR DURANTE LA OPERACIÓN\",\"codigo\":35,\"otro\":\"\"},{\"id\":106,\"nombre\":\"MANIOBRAS TEMERARIAS\",\"codigo\":35,\"otro\":\"\"},{\"id\":107,\"nombre\":\"MANIOBRAS EN PARQUEOS Y ZONAS CERCA A PERSONAL QUE\",\"codigo\":35,\"otro\":\"\"},{\"id\":108,\"nombre\":\"LÍMITES DE VELOCIDAD\",\"codigo\":35,\"otro\":\"\"},{\"id\":109,\"nombre\":\"Cargador Frontal 950M CAT\",\"codigo\":50,\"otro\":\"\"},{\"id\":110,\"nombre\":\"CAMPAÑA DE NO ALCOHOL Y DROGAS\",\"codigo\":50,\"otro\":\"\"},{\"id\":112,\"nombre\":\"GESTIÓN DE RESIDUOS SOLIDOS\",\"codigo\":50,\"otro\":\"\"},{\"id\":113,\"nombre\":\"Tractor de Ruedas\",\"codigo\":50,\"otro\":\"\"},{\"id\":114,\"nombre\":\"Manlift\",\"codigo\":50,\"otro\":\"\"},{\"id\":115,\"nombre\":\"ASPECTOS E IMPACTO AMBIENTAL\",\"codigo\":50,\"otro\":\"\"},{\"id\":116,\"nombre\":\"INVESTIGACIÓN DE ACCIDENTES\",\"codigo\":50,\"otro\":\"\"},{\"id\":117,\"nombre\":\"MANEJO DE RESIDUOS\",\"codigo\":50,\"otro\":\"\"},{\"id\":119,\"nombre\":\"OPERADOR DE SCOOPTRANS R1600H\",\"codigo\":50,\"otro\":\"\"}]"); -export function NewRegister() { +export function NewRegister(props: {personId: number}) { const [subjects, setSubjects] = createSignal>([]); const [error, setError] = createSignal(""); const [loading, setLoading] = createSignal(false); @@ -62,46 +62,60 @@ export function NewRegister() { } setLoading(true); + + const response = await fetch("/certificate", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + personId: props.personId, + subjectId: subject, + date, + }), + }); }; return (

3. Crear nuevos registros

-

- {error()}  -

+ +

+ {error()}  +

-
-
- -
- -
-
- -
- {datePicker} -
-
-
-
- +
+ +
+ +
+
+ +
+ {datePicker} +
+
+
+
+ -
- + type="submit" + value="Registrar" + disabled={loading()} + /> +
+ +
); }