pcpuma_unam_api/src/operador/operador.service.ts
2022-09-05 06:53:59 -05:00

281 lines
9.0 KiB
TypeScript

import {
ConflictException,
Injectable,
NotFoundException,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Between, Repository } from 'typeorm';
import { Institucion } from '../institucion/entity/institucion.entity';
import { Operador } from './entity/operador.entity';
import { InformacionOperadorView } from './entity/views/informacion-operador.view';
import { BcryptService } from '../bcrypt/bcrypt.service';
import { InstitucionService } from '../institucion/institucion.service';
import { NodemailerService } from '../nodemailer/nodemailer.service';
import { TipoUsuarioService } from '../tipo-usuario/tipo-usuario.service';
@Injectable()
export class OperadorService {
constructor(
@InjectRepository(Operador) private repository: Repository<Operador>,
@InjectRepository(InformacionOperadorView)
private informacionOperadorView: Repository<InformacionOperadorView>,
private bcryptService: BcryptService,
private institucionService: InstitucionService,
private nodemailerService: NodemailerService,
private tipoUsuarioService: TipoUsuarioService,
) {}
async create(
id_institucion: number | Institucion,
id_tipo_usuario: number,
operador: string,
nombre: string,
correo: string,
password?: string,
) {
const institucion =
typeof id_institucion === 'number'
? await this.institucionService.findById(id_institucion)
: id_institucion;
const tipoUsuario = await this.tipoUsuarioService.findById(id_tipo_usuario);
if (tipoUsuario.id_tipo_usuario < 3 || tipoUsuario.id_tipo_usuario > 4)
throw new ConflictException(
'No se puede asignar un tipo de usuario distinto a admin y operador',
);
return this.findAdmin(operador, false)
.then((existeAdmin) => {
if (existeAdmin)
throw new ConflictException(
'Ya existe un admin con ese nombre, intenta de nuevo con otro.',
);
return this.findByOperador(institucion, operador, false);
})
.then(async (existeOperador) => {
if (existeOperador)
throw new ConflictException(
'Ya existe un operador en esta institución con ese nombre, intenta de nuevo con otro.',
);
if (!password) password = this.bcryptService.generarPassword();
return this.repository.save(
this.repository.create({
correo,
institucion,
nombre,
operador,
password: this.bcryptService.encriptar(password),
tipoUsuario,
}),
);
})
.then((operador) =>
this.nodemailerService.sendEmail({
email: operador.correo,
subject: 'Credenciales Pc Puma',
html:
tipoUsuario.id_tipo_usuario === 3
? this.nodemailerService.correoPasswordAdmin(
operador.operador,
password,
)
: this.nodemailerService.correoPasswordOperador(
operador.operador,
password,
),
}),
)
.then((_) => ({
message: `Se creó correctamente un nuevo ${tipoUsuario.tipo_usuario.toLowerCase()}.`,
}));
}
findAdmin(admin: string, validarNoExiste = true) {
return this.repository
.findOne({
where: {
operador: admin,
tipoUsuario: { id_tipo_usuario: Between(2, 3) },
},
})
.then((admin) => {
if (validarNoExiste && !admin)
throw new NotFoundException('No existe este admin.');
return admin;
});
}
async findAll(filtros: {
pagina: string;
id_institucion?: string;
id_tipo_usuario?: string;
operador?: string;
}) {
const institucion = filtros.id_institucion
? await this.institucionService.findById(parseInt(filtros.id_institucion))
: null;
const tipoUsuario = filtros.id_tipo_usuario
? await this.tipoUsuarioService.findById(
parseInt(filtros.id_tipo_usuario),
)
: null;
const query = this.repository
.createQueryBuilder('o')
.innerJoinAndSelect('o.institucion', 'i')
.innerJoinAndSelect('o.tipoUsuario', 'tu')
.where('id_operador != 1 AND id_operador != 2')
.orderBy('i.institucion')
.addOrderBy('tu.tipo_usuario')
.addOrderBy('o.operador')
.take(25)
.skip((parseInt(filtros.pagina) - 1) * 25);
if (filtros.operador)
query.andWhere('operador LIKE :operador', {
operador: `${filtros.operador}%`,
});
if (institucion)
query.andWhere('i.id_institucion = :id_institucion', {
id_institucion: institucion.id_institucion,
});
if (tipoUsuario)
query.andWhere('tu.id_tipo_usuario = :id_tipo_usuario', {
id_tipo_usuario: tipoUsuario.id_tipo_usuario,
});
return query.getManyAndCount();
}
findById(id_operador: number) {
return this.repository
.findOne({ where: { id_operador } })
.then((operador) => {
if (!operador)
throw new NotFoundException('No existe este id operador.');
return operador;
});
}
async findByOperador(
id_institucion: number | Institucion,
operador: string,
validarNoExiste = true,
) {
const institucion =
typeof id_institucion === 'number'
? await this.institucionService.findById(id_institucion)
: id_institucion;
return this.repository
.findOne({ where: { institucion, operador } })
.then((operador) => {
if (validarNoExiste && !operador)
throw new NotFoundException('No existe este operador.');
return operador;
});
}
informacionAdmin(admin: string) {
return this.informacionOperadorView
.findOne({
where: {
operador: admin,
id_tipo_usuario: Between(2, 3),
},
})
.then((admin) => {
if (!admin) return { operador: null, activo: null, password: null };
return {
operador: {
id_operador: admin.id_operador,
nombre: admin.nombre,
operador: admin.operador,
institucion: admin.id_institucion
? { id_institucion: admin.id_institucion }
: null,
tipoUsuario: { id_tipo_usuario: admin.id_tipo_usuario },
},
activo: admin.activo,
password: admin.password,
};
});
}
informacionOperador(institucion: Institucion, operador: string) {
return this.informacionOperadorView
.findOne({
where: { operador, id_institucion: institucion.id_institucion },
})
.then((operador) => {
if (!operador) return { operador: null, activo: null, password: null };
return {
operador: {
id_operador: operador.id_operador,
nombre: operador.nombre,
operador: operador.operador,
institucion: { id_institucion: operador.id_institucion },
tipoUsuario: { id_tipo_usuario: operador.id_tipo_usuario },
},
activo: operador.activo,
password: operador.password,
};
});
}
passwordReset(admin: Operador, id_operador: number, password?: string) {
return this.findById(id_operador)
.then((operador) => {
this.validarUpdate(admin, operador);
if (!password) password = this.bcryptService.generarPassword();
operador.password = this.bcryptService.encriptar(password);
return this.repository.save(operador);
})
.then((operador) =>
this.nodemailerService.sendEmail({
email: operador.correo,
subject: 'Credenciales PC Puma',
html:
operador.tipoUsuario.id_tipo_usuario === 3
? this.nodemailerService.correoPasswordAdmin(
operador.operador,
password,
)
: this.nodemailerService.correoPasswordOperador(
operador.operador,
password,
),
}),
)
.then((_) => ({
message: 'Se cambió correctamente la constraseña.',
}));
}
update(admin: Operador, attrs: Partial<Operador>) {
return this.findById(attrs.id_operador)
.then((operador) => {
this.validarUpdate(admin, operador);
Object.assign(operador, attrs);
return this.repository.save(operador);
})
.then((_) => ({
message: 'Se guardaron los cambios correctamente.',
}));
}
validarUpdate(admin: Operador, operador: Operador) {
if (
admin.tipoUsuario.id_tipo_usuario === 2 &&
operador.tipoUsuario.id_tipo_usuario != 3
)
throw new ConflictException(
`El super admin solo puede modificar la infomración de los admins.`,
);
if (
admin.tipoUsuario.id_tipo_usuario === 3 &&
admin.institucion.id_institucion != operador.institucion.id_institucion
)
throw new ConflictException(
`No puedes actualizar la información de este ${operador.tipoUsuario.tipo_usuario.toLowerCase()} porque no pertenece a tu institución.`,
);
}
}