Files
pcpuma_unam_api/src/multa/multa.service.ts
T
2023-03-14 13:08:52 -06:00

396 lines
13 KiB
TypeScript

import * as moment from 'moment';
import { ConflictException, Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import {
FindManyOptions,
FindOptionsWhere,
LessThanOrEqual,
Like,
Repository,
} from 'typeorm';
import { Modulo } from '../modulo/entity/modulo.entity';
import { Multa } from './entity/multa.entity';
import { Operador } from '../operador/entity/operador.entity';
import { Prestamo } from '../prestamo/entity/prestamo.entity';
import { Usuario } from '../usuario/entity/usuario.entity';
import { FullInformacionMultaView } from './entity/views/full-informacion-multa.view';
import { InformacionMultaView } from './entity/views/informacion-multa.view';
import { EquipoService } from '../equipo/equipo.service';
import { InstitucionInfraccionService } from '../institucion-infraccion/institucion-infraccion.service';
import { InstitucionUsuarioService } from '../institucion-usuario/institucion-usuario.service';
import { OperadorService } from '../operador/operador.service';
import { PrestamoService } from '../prestamo/prestamo.service';
import { UsuarioService } from '../usuario/usuario.service';
@Injectable()
export class MultaService {
constructor(
@InjectRepository(Multa) private repository: Repository<Multa>,
@InjectRepository(FullInformacionMultaView)
private fullInformacionMultaView: Repository<FullInformacionMultaView>,
@InjectRepository(InformacionMultaView)
private informacionMultaView: Repository<InformacionMultaView>,
private equipoService: EquipoService,
private institucionInfraccionService: InstitucionInfraccionService,
private institucionUsuarioService: InstitucionUsuarioService,
private operadorService: OperadorService,
private prestamoService: PrestamoService,
private usuarioService: UsuarioService,
) {}
async create(
operadorMulta: Operador,
modulo: Modulo,
prestamo: Prestamo,
descripcion: string,
semanasCastigo?: number,
id_institucion_infraccion?: number,
): Promise<{ message: string }> {
// Buscamos la infracción, si es que se mandó una, de lo contrario se asigna "Sin infracción" por default
const institucionInfraccion = id_institucion_infraccion
? await this.institucionInfraccionService.findById(
id_institucion_infraccion,
)
: await this.institucionInfraccionService.findSinInfraccion(
operadorMulta.institucion,
);
const existeMulta = await this.findByPrestamo(prestamo);
const fecha_fin = moment();
// Si ya existe una multa asignada a este préstamo significa que hubo un problema pero si se multo al usuario. Cortamos la función
if (existeMulta) return;
this.validacionMultaCancelacion(prestamo);
// Si hay semanasCastigo agregamos el tiempo de multa correspondiente a la institución
if (semanasCastigo)
fecha_fin.add(
semanasCastigo * modulo.institucion.dias_multa_retraso,
'd',
);
// Si la institucionInfraccion no es "Sin infracción"
if (institucionInfraccion.infraccion.id_infraccion != 1)
// Agregamos el tiempo de multa correspondiente de la infracción enviada
fecha_fin.add(institucionInfraccion.dias_multa, 'd');
// Creamos y guardamos un registro
return this.repository
.save(
this.repository.create({
descripcion,
fecha_fin: fecha_fin.toDate(),
fecha_inicio: moment().toDate(),
retraso: semanasCastigo ? true : false,
institucionInfraccion,
operadorMulta: id_institucion_infraccion
? operadorMulta
: this.operadorService.sistema(),
prestamo,
}),
)
.then((_) =>
// Multamos al usuario en todas las carreras a las que pertenece en esa institución
this.institucionUsuarioService.updateMulta(
operadorMulta.institucion,
prestamo.institucionUsuario.usuario,
true,
),
);
}
findAll(
operador: Operador,
filtros: {
nombre?: string;
pagina?: string;
usuario?: string;
},
): Promise<FullInformacionMultaView[] | [Multa[], number]> {
const busqueda: FindOptionsWhere<FullInformacionMultaView> = {
id_institucion: operador.institucion.id_institucion,
};
const options: FindManyOptions<FullInformacionMultaView> = {
order: {
institucion: 'ASC',
activo: 'DESC',
fecha_fin: 'ASC',
usuario: 'ASC',
},
};
if (filtros.nombre) busqueda.nombre = Like(`%${filtros.nombre}%`);
if (filtros.usuario) busqueda.usuario = Like(`%${filtros.usuario}%`);
options.where = busqueda;
if (filtros.pagina) {
options.skip = (parseInt(filtros.pagina) - 1) * 25;
options.take = 25;
return this.fullInformacionMultaView
.findAndCount(options)
.then((infoMultas) => {
const multas: Multa[] = [];
for (let i = 0; i < infoMultas[0].length; i++)
multas.push(
this.repository.create(this.fullViewToMulta(infoMultas[0][i])),
);
return [multas, infoMultas[1]];
});
} else return this.fullInformacionMultaView.find(options);
}
findAllActivasExpiradas(): Promise<Multa[]> {
return this.informacionMultaView
.find({
where: { activo: 1, fecha_fin: LessThanOrEqual(moment().toDate()) },
})
.then((infoMultas) => {
const multas: Multa[] = [];
for (let i = 0; i < infoMultas.length; i++)
multas.push(
this.repository.create({
id_multa: infoMultas[i].id_multa,
activo: infoMultas[i].activo === 1,
fecha_fin: infoMultas[i].fecha_fin,
retraso: infoMultas[i].retraso === 1,
institucionInfraccion: {
id_institucion_infraccion:
infoMultas[i].id_institucion_infraccion,
infraccion: { id_infraccion: infoMultas[i].id_infraccion },
institucion: { id_institucion: infoMultas[i].id_institucion },
},
operadorMulta: { id_operador: infoMultas[i].id_operador },
prestamo: {
id_prestamo: infoMultas[i].id_prestamo,
institucionUsuario: {
usuario: { id_usuario: infoMultas[i].id_usuario },
},
},
}),
);
return multas;
});
}
findAllByIdEquipo(
operador: Operador,
id_equipo: number,
pagina: number,
): Promise<[Multa[], number]> {
return this.equipoService.findById(id_equipo).then((equipo) =>
this.fullInformacionMultaView
.findAndCount({
where: {
id_equipo: equipo.id_equipo,
id_institucion: operador.institucion.id_institucion,
},
skip: (pagina - 1) * 25,
take: 25,
})
.then((infoMultas) => {
const multas: Multa[] = [];
for (let i = 0; i < infoMultas[0].length; i++)
multas.push(
this.repository.create(this.fullViewToMulta(infoMultas[0][i])),
);
return [multas, infoMultas[1]];
}),
);
}
findAllByIdUsuario(
operador: Operador,
id_usuario: number,
pagina: number,
): Promise<[Multa[], number]> {
return this.usuarioService.findById(id_usuario).then((usuario) =>
this.fullInformacionMultaView
.findAndCount({
where: {
id_usuario: usuario.id_usuario,
id_institucion: operador.institucion.id_institucion,
},
skip: (pagina - 1) * 25,
take: 25,
})
.then((infoMultas) => {
const multas: Multa[] = [];
for (let i = 0; i < infoMultas[0].length; i++)
multas.push(
this.repository.create(this.fullViewToMulta(infoMultas[0][i])),
);
return [multas, infoMultas[1]];
}),
);
}
findByPrestamo(prestamo: Prestamo): Promise<Multa> {
return this.repository.findOne({
select: ['id_multa'],
where: { prestamo },
});
}
findMultasActivasByUsuario(usuario: Usuario): Promise<Multa[]> {
return this.repository.find({
join: {
alias: 'mu',
innerJoin: {
p: 'mu.prestamo',
iu: 'p.institucionUsuario',
u: 'iu.usuario',
},
innerJoinAndSelect: {
ii: 'mu.institucionInfraccion',
i: 'ii.institucion',
},
},
where: { activo: true, prestamo: { institucionUsuario: { usuario } } },
});
}
private fullViewToMulta(infoMulta: FullInformacionMultaView): Multa {
return this.repository.create({
id_multa: infoMulta.id_multa,
activo: infoMulta.activo === 1,
descripcion: infoMulta.descripcion,
fecha_fin: infoMulta.fecha_fin,
fecha_inicio: infoMulta.fecha_inicio,
retraso: infoMulta.retraso === 1,
institucionInfraccion: {
id_institucion_infraccion: infoMulta.id_institucion_infraccion,
infraccion: {
id_infraccion: infoMulta.id_infraccion,
infraccion: infoMulta.infraccion,
},
},
operadorMulta: {
id_operador: infoMulta.id_operador,
operador: infoMulta.operador,
institucion: {
id_institucion: infoMulta.id_institucion,
institucion: infoMulta.institucion,
},
},
prestamo: {
id_prestamo: infoMulta.id_prestamo,
institucionUsuario: {
usuario: {
id_usuario: infoMulta.id_usuario,
usuario: infoMulta.usuario,
nombre: infoMulta.nombre,
},
},
},
});
}
async multaExtemporanea(
operador: Operador,
id_prestamo: number,
descripcion: string,
id_institucion_infraccion: number,
): Promise<{ message: string }> {
const prestamo = await this.prestamoService.findById(id_prestamo);
const institucionInfraccion =
await this.institucionInfraccionService.findById(
id_institucion_infraccion,
);
const fecha_fin = moment();
// Validamos que este préstamo le pertenezca al operador
if (
operador.institucion.id_institucion !=
prestamo.equipo.carrito.modulo.institucion.id_institucion
)
throw new ConflictException(
'Este préstamo no pertenece a tu institución.',
);
// Validamos que la infracción enviada no sea "Sin infracción"
if (institucionInfraccion.infraccion.id_infraccion === 1)
throw new ConflictException(
'No se puede asignar esta infracción manualmente.',
);
this.validacionMultaCancelacion(prestamo);
// Agregamos el tiempo de multa correspondiente de la infracción enviada
fecha_fin.add(institucionInfraccion.dias_multa, 'd');
return this.findByPrestamo(prestamo)
.then((existeMulta) => {
// Validamos que no exista una multa con este préstamo
if (existeMulta)
throw new ConflictException(
'Ya existe una multa asignada a este préstamo.',
);
// Creamos y guardamos un registro
return this.repository.save(
this.repository.create({
descripcion,
fecha_fin: fecha_fin.toDate(),
fecha_inicio: moment().toDate(),
institucionInfraccion,
operadorMulta: operador,
prestamo,
}),
);
})
.then((_) =>
// Multamos al usuario en todas las carreras a las que pertenece en esa institución
this.institucionUsuarioService.updateMulta(
operador.institucion,
prestamo.institucionUsuario.usuario,
true,
),
);
}
async quitarMulta(
admin: Operador,
id_institucion_usuario: number,
): Promise<{ message: string }> {
const institucionUsuario = await this.institucionUsuarioService.findById(
id_institucion_usuario,
);
const multa = await this.repository
.createQueryBuilder('mu')
.innerJoinAndSelect('mu.prestamo', 'p')
.innerJoin(
'p.institucionUsuario',
'iu',
'iu.id_institucion_usuario = :id_institucion_usuario',
{ id_institucion_usuario: institucionUsuario.id_institucion_usuario },
)
.where('mu.activo = 1')
.getOne();
// Validamos que este institucionUsuario le pertenezca al admin
if (
admin.institucion.id_institucion !=
institucionUsuario.institucionCarrera.institucion.id_institucion
)
throw new ConflictException(
'No puedes modificar la información este usuario porque no pertenece a tu institución.',
);
// Quitamos la multa a todas las carreras del usuario en la institución del admin
return this.institucionUsuarioService
.updateMulta(admin.institucion, institucionUsuario.usuario, false)
.then(async (_) => {
if (multa) {
multa.activo = false;
await this.repository.save(multa);
}
return { message: 'Se guardaron los cambios correctamente.' };
});
}
save(multa: Multa): Promise<Multa> {
return this.repository.save(multa);
}
private validacionMultaCancelacion(prestamo: Prestamo): void {
// Validamos que este présstamo no haya sido cancelado por el usuario u operador
if (prestamo.cancelado_operador || prestamo.cancelado_usuario)
throw new ConflictException(
'No se puede multar a un usuario con un préstamo que fue cancelado.',
);
}
}