[BE] Add controller for migrating from old registroGIEschema to new

master
Fernando 2023-05-23 17:36:42 -05:00
parent a527f4e33e
commit 7bf1c764aa
6 changed files with 179 additions and 15 deletions

View File

@ -10,6 +10,7 @@ import { PersonService } from "./controller/person/person.service";
import { SubjectController } from "./controller/subject/subject.controller"; import { SubjectController } from "./controller/subject/subject.controller";
import { SubjectService } from "./controller/subject/subject.service"; import { SubjectService } from "./controller/subject/subject.service";
import * as dotenv from "dotenv"; import * as dotenv from "dotenv";
import { MigratorController } from "./controller/migrator/migrator.controller";
// Must be done before initializing DB. // Must be done before initializing DB.
console.log(dotenv.config()); console.log(dotenv.config());
@ -31,7 +32,7 @@ console.log(dotenv.config());
synchronize: false, synchronize: false,
}), }),
], ],
controllers: [CertificateController, PersonController, SubjectController], controllers: [CertificateController, PersonController, SubjectController, MigratorController],
providers: [CertificateService, PersonService, SubjectService], providers: [CertificateService, PersonService, SubjectService],
}) })
export class AppModule {} export class AppModule {}

View File

@ -1,4 +1,4 @@
import { Body, Controller, Delete, Get, InternalServerErrorException, Param, Post, Res, StreamableFile } from "@nestjs/common"; import { Body, Controller, Delete, Get, InternalServerErrorException, Param, Post, Res } from "@nestjs/common";
import { renderToString } from "solid-js/web"; import { renderToString } from "solid-js/web";
import { Certs } from "../../views/Certs"; import { Certs } from "../../views/Certs";
import { template } from "./certificate.template"; import { template } from "./certificate.template";
@ -19,7 +19,7 @@ export class CertificateController {
} }
@Get(":dni") @Get(":dni")
getByDni(@Param() param: {dni: string}) { getByDni(@Param() param: { dni: string }) {
return this.certificateService.getByDni(param.dni); return this.certificateService.getByDni(param.dni);
} }
@ -30,7 +30,7 @@ export class CertificateController {
} }
@Post("generate/:id") @Post("generate/:id")
async generate(@Param() param: {id: string}, @Res({ passthrough: true }) res: Response) { async generate(@Param() param: { id: string }, @Res({ passthrough: true }) res: Response) {
const [stream, filename] = await this.certificateService.generate(parseInt(param.id, 10)); const [stream, filename] = await this.certificateService.generate(parseInt(param.id, 10));
const str = res.writeHead(201, { const str = res.writeHead(201, {
@ -42,7 +42,7 @@ export class CertificateController {
} }
@Delete(":id") @Delete(":id")
async delete(@Param() param: {id: number}) { async delete(@Param() param: { id: number }) {
console.log(param); console.log(param);
const result = await this.certificateService.deleteById(param.id); const result = await this.certificateService.deleteById(param.id);
if (!result) { if (!result) {

View File

@ -0,0 +1,162 @@
import { Controller, Get } from "@nestjs/common";
import { CursoGIE } from "src/model/CursoGIE/cursoGIE.entity";
import { Persona } from "src/model/Persona/persona.entity";
import { RegistroGIE } from "src/model/RegistroGIE/registroGIE.entity";
import { DataSource, Repository } from "typeorm";
import { PersonService } from "../person/person.service";
@Controller("migrator")
export class MigratorController {
registroGIERepository: Repository<RegistroGIE>;
personGIERepository: Repository<Persona>;
subjectRepo: Repository<CursoGIE>;
constructor(dataSource: DataSource, private personService: PersonService) {
this.registroGIERepository = dataSource.getRepository(RegistroGIE);
this.personGIERepository = dataSource.getRepository(Persona);
this.subjectRepo = dataSource.getRepository(CursoGIE);
}
@Get()
async migrate() {
const registers = await this.registroGIERepository.find({
// @ts-ignore
select: {
cursoGIE: null,
persona: null,
},
});
// Try to create Persons for each user
for (const register of registers) {
const {curso, persona, cursoGIE, dni} = register;
// If this register doesn't link to a Person
if (!persona) {
// Try to get the person by DNI
try {
await this.personService.getByDni(dni);
// Update this register
register.persona = (await this.personGIERepository.findOneBy({dni}))!;
} catch (e) {
// Return creation form to the user
return `
<html>
<body>
<div class="p-2">
<h2 class="my-2 font-medium text-xl">1.1 Registrar persona manualmente</h2>
<h3>${register.nombre}</h3>
<form id="form" class="px-4">
<label for="add-person-dni">DNI</label>
<br/>
<label for="add-person-nombres">Nombres</label>
<br/>
<input
id="add-person-nombres"
name="add-person-nombres"
class="bg-c-background text-c-on-background border-c-outline border-2 rounded px-2 py-1
invalid:border-c-error invalid:text-c-error
focus:border-c-primary outline-none
disabled:opacity-50 disabled:cursor-not-allowed"
type="text"
placeholder="Nombres"
required="true"
/>
<br/>
<br/>
<div class="grid grid-cols-2 w-1/2">
<div>
<label for="add-person-apellido-paterno">Apellido Paterno</label>
<br/>
<input
id="add-person-apellido-paterno"
class="bg-c-background text-c-on-background border-c-outline border-2 rounded px-2 py-1
invalid:border-c-error invalid:text-c-error
focus:border-c-primary outline-none
disabled:opacity-50 disabled:cursor-not-allowed"
type="text"
placeholder="Apellido paterno"
/>
</div>
<div>
<label for="add-person-apellido-paterno">Apellido Materno</label>
<br/>
<input
id="add-person-apellido-materno"
class="bg-c-background text-c-on-background border-c-outline border-2 rounded px-2 py-1
invalid:border-c-error invalid:text-c-error
focus:border-c-primary outline-none
disabled:opacity-50 disabled:cursor-not-allowed"
type="text"
placeholder="Apellido materno"
/>
</div>
</div>
<br/>
<input
class="bg-c-primary text-c-on-primary px-4 py-2 rounded-md cursor-pointer
disabled:opacity-50 disabled:cursor-not-allowed"
type="submit"
value="Registrar persona"
/>
</form>
<br/>
<script>
const form = document.getElementById("form");
form.addEventListener("submit", async (ev) => {
ev.preventDefault();
const response = await fetch("/person", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
dni: "${dni}",
apellidoPaterno: document.getElementById("add-person-apellido-paterno").value.toUpperCase().trim(),
apellidoMaterno: document.getElementById("add-person-apellido-materno").value.toUpperCase().trim(),
nombres: document.getElementById("add-person-nombres").value.toUpperCase().trim(),
}),
});
if (response.ok) {
alert("OK");
window.location.reload();
} else {
alert("Error creating");
}
});
</script>
</div>
</body>
</html>
`;
return `NOT FOUND IN DB NOR SUNAT: ${JSON.stringify(register)}`;
}
}
// If this register doesn't link to a Curso
if (!cursoGIE) {
// Get Curso and update
const cursoGIE = await this.subjectRepo.findOneBy({id: curso});
register.cursoGIE = cursoGIE!;
}
// Save person
if (!persona || !cursoGIE) {
await this.registroGIERepository.save(register);
}
}
return "All registers updated (?) :D";
}
}

View File

@ -15,7 +15,7 @@ interface SunatPerson {
export class PersonService { export class PersonService {
personaRepository: Repository<Persona>; personaRepository: Repository<Persona>;
constructor(private dataSource: DataSource) { constructor(dataSource: DataSource) {
this.personaRepository = dataSource.getRepository(Persona); this.personaRepository = dataSource.getRepository(Persona);
} }

View File

@ -36,9 +36,9 @@ export class RegistroGIE {
/* New fields */ /* New fields */
@ManyToOne(() => Persona, (persona) => persona.registros) @ManyToOne(() => Persona,(persona) => persona.registros, {nullable: true})
persona: Persona; persona: Persona;
@ManyToOne(() => CursoGIE) @ManyToOne(() => CursoGIE, {nullable: true})
cursoGIE: CursoGIE; cursoGIE: CursoGIE;
} }

View File

@ -41,7 +41,7 @@ export function Registers(props: { person: Person | null, lastUpdate: number })
<div class="px-4"> <div class="px-4">
<Show when={props.person !== null}> <Show when={props.person !== null}>
<span>Nombres y Apellidos</span> <span>Nombres y Apellidos</span>
<br/> <br />
<input <input
type="text" type="text"
disabled disabled
@ -84,14 +84,14 @@ export function Registers(props: { person: Person | null, lastUpdate: number })
); );
} }
function Register(props: {cert: RegisterReturn, onUpdate: () => void}) { function Register(props: { cert: RegisterReturn, onUpdate: () => void }) {
const [deleteConfirmation, setDeleteConfirmation] = createSignal(false); const [deleteConfirmation, setDeleteConfirmation] = createSignal(false);
const [deleteText, setDeleteText] = createSignal("Eliminar"); const [deleteText, setDeleteText] = createSignal("Eliminar");
const deleteRegister = async() => { const deleteRegister = async() => {
if (deleteConfirmation()) { if (deleteConfirmation()) {
// Actually delete from DB // Actually delete from DB
const response = await fetch(`/certificate/${props.cert.id}`,{ const response = await fetch(`/certificate/${props.cert.id}`, {
method: "DELETE", method: "DELETE",
}); });
@ -113,7 +113,7 @@ function Register(props: {cert: RegisterReturn, onUpdate: () => void}) {
}; };
const getCertificate = async() => { const getCertificate = async() => {
const response = await fetch(`/certificate/generate/${props.cert.id}`,{ const response = await fetch(`/certificate/generate/${props.cert.id}`, {
method: "POST", method: "POST",
}); });
@ -145,7 +145,8 @@ function Register(props: {cert: RegisterReturn, onUpdate: () => void}) {
return; return;
} else { } else {
alert("Error downloading..."); const json = await response.json();
alert(json);
} }
}; };
@ -158,7 +159,7 @@ function Register(props: {cert: RegisterReturn, onUpdate: () => void}) {
<Show when={props.cert.generatable}> <Show when={props.cert.generatable}>
<button <button
class="rounded-full py-1 px-2 shadow" class="rounded-full py-1 px-2 shadow"
style={{"background-color": "#0055d5", "color": "#ffffff"}} style={{ "background-color": "#0055d5", "color": "#ffffff" }}
onclick={getCertificate} onclick={getCertificate}
> >
DOCX DOCX