add bot wsp

This commit is contained in:
Valentin Romero
2026-06-30 22:04:56 -03:00
parent 6859b89262
commit 25d4ba6cc0
166 changed files with 29830 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
export class CreateRfidDto {}
+4
View File
@@ -0,0 +1,4 @@
import { PartialType } from '@nestjs/mapped-types';
import { CreateRfidDto } from './create-rfid.dto';
export class UpdateRfidDto extends PartialType(CreateRfidDto) {}
+1
View File
@@ -0,0 +1 @@
export class Rfid {}
+20
View File
@@ -0,0 +1,20 @@
import { Test, TestingModule } from '@nestjs/testing';
import { RfidController } from './rfid.controller';
import { RfidService } from './rfid.service';
describe('RfidController', () => {
let controller: RfidController;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [RfidController],
providers: [RfidService],
}).compile();
controller = module.get<RfidController>(RfidController);
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
});
+19
View File
@@ -0,0 +1,19 @@
import { Body, Controller, Header, HttpCode, Post } from '@nestjs/common';
import { RfidService } from './rfid.service';
@Controller('rfid')
// TODO ponerle un token estatico a los lectores RFID ?
// @UseGuards(AuthTokenGuard)
export class RfidController {
constructor(private readonly rfidService: RfidService) { }
@Post('ping')
@HttpCode(200)
@Header('Content-Type', 'text/plain')
async ping(@Body('id') uid: string): Promise<string> {
console.log(`RFID ping recibido con id=${uid}`);
await this.rfidService.ping(uid);
return 'ok'
}
}
+15
View File
@@ -0,0 +1,15 @@
import { Module } from '@nestjs/common';
import { InvoicesModule } from '../invoices/invoices.module';
import { AttendanceModule } from '../attendance/attendance.module';
import { UserModule } from '../user/user.module';
import { WhatsappModule } from '../whatsapp/whatsapp.module';
import { RfidController } from './rfid.controller';
import { RfidService } from './rfid.service';
import { AuthModule } from '~/auth/auth.module';
@Module({
controllers: [RfidController],
providers: [RfidService],
imports: [UserModule,AttendanceModule,WhatsappModule,AttendanceModule,InvoicesModule,AuthModule]
})
export class RfidModule { }
+18
View File
@@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { RfidService } from './rfid.service';
describe('RfidService', () => {
let service: RfidService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [RfidService],
}).compile();
service = module.get<RfidService>(RfidService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});
+96
View File
@@ -0,0 +1,96 @@
import { Injectable, Logger } from '@nestjs/common';
import { LogDirection } from '@prisma/client';
import dayjs from 'dayjs';
import { AuthService, TokenRedirectURL } from '~/auth/auth.service';
import { AttendanceService } from '../attendance/attendance.service';
import { InvoicesService } from '../invoices/invoices.service';
import { UserService } from '../user/user.service';
import { WhatsappService } from '../whatsapp/whatsapp.service';
@Injectable()
export class RfidService {
private logger = new Logger(RfidService.name);
constructor(
private readonly userService: UserService,
private readonly whatsappService: WhatsappService,
private readonly attendanceService: AttendanceService,
private readonly invoicesService: InvoicesService,
private readonly authService: AuthService,
) { }
async ping(uid: string): Promise<void> {
try {
const usuario = await this.userService.findByRfid(uid);
const admin = await this.userService.getUserAdmin();
if (usuario) {
if (!usuario.phone) {
this.logger.debug(`El usuario ${usuario.name} no tiene un número de teléfono registrado.`);
const number = admin?.phone ? `549${admin.phone}` : '5493435077510'
this.logger.log({
action: 'RFID ping',
message: `El usuario ${usuario.name} con ID ${usuario.id} no tiene un número de teléfono registrado.`,
uid: uid,
userId: usuario.id,
})
await this.whatsappService.sendText(
number,
`El usuario ${usuario.name} con ID ${usuario.id} no tiene un número de teléfono registrado. Por favor, actualiza su información.`);
} else {
this.logger.log(`RFID ping recibido con id=${uid} del usuario ${usuario.name}`);
const log = await this.attendanceService.logAccess(usuario.id);
const tipo = log.direction === LogDirection.INGRESS ? 'ingreso' : 'egreso';
const hora = dayjs(log.timestamp).format('HH:mm');
// ---- Construir un único mensaje ----
let message = `Hola ${usuario.name} ! \n`;
if (log.direction === LogDirection.INGRESS) {
this.logger.log(`Registro de ingreso para el usuario ${usuario.name} a las ${hora}`);
message += `Registramos tu ${tipo} a las ${hora}. \n`;
// Verificar factura pagada
const unpaidInvoice = await this.invoicesService.hasUnpaidInvoiceThisMonth(usuario.id);
if (unpaidInvoice) {
this.logger.warn(`El usuario ${usuario.name} tiene facturas no pagadas este mes.`);
message += `⚠️ Notamos que tienes facturas no pagadas este mes. Por favor, regulariza tu situación.`;
}
} else {
// Si es egreso, solo avisamos el registro
message += `Registramos tu ${tipo} a las ${hora}.`;
}
// Enviar el mensaje único
await this.whatsappService.sendText('549' + usuario.phone, message);
}
return;
} else {
//NOTE mando al admin que se esta registrando un un nuevo usuario
this.logger.error({
action: 'RFID ping',
message: `RFID ping recibido con id=${uid} pero no se encontró el usuario`,
uid: uid,
})
const newUser = await this.userService.createUserTemporary(uid);
this.logger.debug(`Usuario temporal creado: ${newUser.name} con ID ${newUser.id}`);
if (!admin) {
this.logger.error(`No se encontró un usuario administrador para notificar sobre el nuevo usuario con RFID ${uid}.`);
return;
}
const token = await this.authService.generarToken(admin.id, TokenRedirectURL.USER);
await this.whatsappService.sendText('549' + admin?.phone,
`🆕 Se registro un *nuevo usuario* a travez de un nuevo *llavero*.\n
🤔 Nombre: *${newUser.name}*\n
Porfavor actualiza su información ingresando al link 🙏\n
${process.env.URL_FRONT}?t=${token}
`);
return;
}
}
catch (error: any) {
this.logger.error(`Error al procesar el ping RFID: ${error}`);
}
}
}