diff --git a/src/passcode/dto/input/devolucion.dto.ts b/src/passcode/dto/input/devolucion.dto.ts new file mode 100644 index 0000000..5fbf23c --- /dev/null +++ b/src/passcode/dto/input/devolucion.dto.ts @@ -0,0 +1,6 @@ +import { IsInt } from 'class-validator'; + +export class DevolucionDto { + @IsInt() + passcode: number; +} diff --git a/src/passcode/dto/input/notificacion.dto.ts b/src/passcode/dto/input/notificacion.dto.ts new file mode 100644 index 0000000..b758b22 --- /dev/null +++ b/src/passcode/dto/input/notificacion.dto.ts @@ -0,0 +1,9 @@ +import { IsInt } from 'class-validator'; + +export class NotificacionDto { + @IsInt() + passcode: number; + + @IsInt() + estatus: number; +} diff --git a/src/passcode/dto/input/prestamo.dto.ts b/src/passcode/dto/input/prestamo.dto.ts new file mode 100644 index 0000000..b7fdc8a --- /dev/null +++ b/src/passcode/dto/input/prestamo.dto.ts @@ -0,0 +1,9 @@ +import { IsString } from 'class-validator'; + +export class PrestamoDto { + @IsString() + passcode: string; + + @IsString() + id_locker: string; +} diff --git a/src/passcode/dto/output/devolucion.dto.ts b/src/passcode/dto/output/devolucion.dto.ts new file mode 100644 index 0000000..f43d3c3 --- /dev/null +++ b/src/passcode/dto/output/devolucion.dto.ts @@ -0,0 +1,6 @@ +import { Expose } from 'class-transformer'; + +export class DevolucionOutputDto { + @Expose() + code; +} diff --git a/src/passcode/dto/output/notificacion.dto.ts b/src/passcode/dto/output/notificacion.dto.ts new file mode 100644 index 0000000..7488eea --- /dev/null +++ b/src/passcode/dto/output/notificacion.dto.ts @@ -0,0 +1,6 @@ +import { Expose } from 'class-transformer'; + +export class NotificacionOutputDto { + @Expose() + code; +} diff --git a/src/passcode/dto/output/passcode.dto.ts b/src/passcode/dto/output/passcode.dto.ts new file mode 100644 index 0000000..4b6e658 --- /dev/null +++ b/src/passcode/dto/output/passcode.dto.ts @@ -0,0 +1,15 @@ +import { Expose } from 'class-transformer'; + +export class PasscodeOutputDto { + @Expose() + code; + + @Expose() + passcode; + + @Expose() + id_locker; + + @Expose() + door; +} diff --git a/src/passcode/entity/passcode.entity.ts b/src/passcode/entity/passcode.entity.ts new file mode 100644 index 0000000..7056beb --- /dev/null +++ b/src/passcode/entity/passcode.entity.ts @@ -0,0 +1,26 @@ +import { + Column, + Entity, + JoinColumn, + OneToOne, + PrimaryGeneratedColumn, +} from 'typeorm'; +import { Prestamo } from '../../prestamo/entity/prestamo.entity'; + +@Entity() +export class Passcode { + @PrimaryGeneratedColumn() + id_passcode: number; + + @Column({ type: String, nullable: false }) + passcode: string; + + @Column({ type: Boolean, nullable: true, default: false }) + abrio: boolean; + + @OneToOne(() => Prestamo, (Prestamo) => Prestamo.id_prestamo, { + eager: true, + }) + @JoinColumn({ name: 'id_prestamo' }) + prestamo: Prestamo; +} diff --git a/src/passcode/passcode.controller.spec.ts b/src/passcode/passcode.controller.spec.ts new file mode 100644 index 0000000..9a58392 --- /dev/null +++ b/src/passcode/passcode.controller.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { PasscodeController } from './passcode.controller'; + +describe('PasscodeController', () => { + let controller: PasscodeController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [PasscodeController], + }).compile(); + + controller = module.get(PasscodeController); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/src/passcode/passcode.controller.ts b/src/passcode/passcode.controller.ts new file mode 100644 index 0000000..9f8d987 --- /dev/null +++ b/src/passcode/passcode.controller.ts @@ -0,0 +1,109 @@ +import { + Body, + Controller, + Get, + Put, + Query, + Request, + UseGuards, +} from '@nestjs/common'; +import { + ApiBearerAuth, + ApiBody, + ApiOperation, + ApiQuery, + ApiTags, +} from '@nestjs/swagger'; +import { AuthGuard } from '@nestjs/passport'; +import { Serealize } from '../interceptors/serialize.interceptor'; +import { ValidarUsuarioService } from '../validar-usuario/validar-usuario.service'; +import { DevolucionDto } from './dto/input/devolucion.dto'; +import { DevolucionOutputDto } from './dto/output/devolucion.dto'; +import { PasscodeService } from './passcode.service'; +import { NotificacionDto } from './dto/input/notificacion.dto'; +import { NotificacionOutputDto } from './dto/output/notificacion.dto'; +import { Operador } from '../operador/entity/operador.entity'; +import { PrestamoDto } from './dto/input/prestamo.dto'; +import { PasscodeOutputDto } from './dto/output/passcode.dto'; + +@Controller('passcode') +@ApiTags('passcode') +export class PasscodeController { + constructor( + private passcodeService: PasscodeService, + private validarUsuarioService: ValidarUsuarioService, + ) {} + + @Serealize(PasscodeOutputDto) + @Get('prestamo') + @UseGuards(AuthGuard('jwt')) + @ApiOperation({ + description: 'Endpoint que verifica la existencia y validez del passcode.', + }) + @ApiBearerAuth('jwt') + @ApiQuery({ + description: 'Passcode del préstamo', + name: 'passcode', + type: 'string', + }) + @ApiQuery({ + description: 'id_locker, un locker hace referencia a un carrito.', + name: 'id_locker', + type: 'string', + }) + prestamo(@Request() req, @Query() query: PrestamoDto) { + const operador: Operador = req.user.operador; + + this.validarUsuarioService.validarAdminOperador(operador); + return this.passcodeService.findByPasscode( + query.passcode, + false, + query.id_locker, + ); + } + + @Serealize(NotificacionOutputDto) + @Put('notificacion') + @UseGuards(AuthGuard('jwt')) + @ApiOperation({ + description: + 'Endpoint que actualiza el status del equipo a "En uso" por medio del autoprestamo.', + }) + @ApiBearerAuth('jwt') + @ApiBody({ + description: 'Ambas variables son obligatorias.', + examples: { ejemplo: { value: { passcode: 123456789012, estatus: 1 } } }, + }) + autoprestamo(@Request() req, @Body() body: NotificacionDto) { + const operador: Operador = req.user.operador; + this.validarUsuarioService.validarAdminOperador(operador); + + return this.passcodeService.entregarEquipo( + body.passcode, + body.estatus, + operador, + ); + } + + @Serealize(DevolucionOutputDto) + @Put('devolucion') + @UseGuards(AuthGuard('jwt')) + @ApiOperation({ description: 'Endpoint que da por terminado un préstamo.' }) + @ApiBearerAuth('jwt') + @ApiBody({ + description: 'Solo necesitamos el passcode.', + examples: { + ejemplo: { + value: { + passcode: 123456789012, + }, + }, + }, + }) + devolucion(@Request() req, @Body() body: DevolucionDto) { + const operador: Operador = req.user.operador; + + this.validarUsuarioService.validarAdminOperador(operador); + return this.passcodeService.devolverEquipo(body.passcode, operador); + } +} diff --git a/src/passcode/passcode.module.ts b/src/passcode/passcode.module.ts new file mode 100644 index 0000000..6a3f4de --- /dev/null +++ b/src/passcode/passcode.module.ts @@ -0,0 +1,19 @@ +import { forwardRef, Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { PasscodeController } from './passcode.controller'; +import { PasscodeService } from './passcode.service'; +import { Passcode } from './entity/passcode.entity'; +import { PrestamoModule } from '../prestamo/prestamo.module'; +import { ValidarUsuarioModule } from '../validar-usuario/validar-usuario.module'; + +@Module({ + imports: [ + forwardRef(() => PrestamoModule), + TypeOrmModule.forFeature([Passcode]), + ValidarUsuarioModule, + ], + controllers: [PasscodeController], + providers: [PasscodeService], + exports: [PasscodeService], +}) +export class PasscodeModule {} diff --git a/src/passcode/passcode.service.spec.ts b/src/passcode/passcode.service.spec.ts new file mode 100644 index 0000000..89747df --- /dev/null +++ b/src/passcode/passcode.service.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { PasscodeService } from './passcode.service'; + +describe('PasscodeService', () => { + let service: PasscodeService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [PasscodeService], + }).compile(); + + service = module.get(PasscodeService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/src/passcode/passcode.service.ts b/src/passcode/passcode.service.ts new file mode 100644 index 0000000..1d41818 --- /dev/null +++ b/src/passcode/passcode.service.ts @@ -0,0 +1,111 @@ +import { + BadRequestException, + forwardRef, + Inject, + Injectable, +} from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { Passcode } from './entity/passcode.entity'; +import { PrestamoService } from '../prestamo/prestamo.service'; + +@Injectable() +export class PasscodeService { + constructor( + @InjectRepository(Passcode) private repository: Repository, + @Inject(forwardRef(() => PrestamoService)) + private prestamoService: PrestamoService, + ) {} + + crearPasscode(id_carrito, id_prestamo) { + const prestamo = { + 1: '00000', + 2: '0000', + 3: '000', + 4: '00', + 5: '0', + }; + const passcode = + id_carrito + + prestamo[id_prestamo.length] + + id_prestamo + + Math.floor(Math.random() * 99999 + 10000).toString(); + + this.repository.save( + this.repository.create({ + passcode, + prestamo: { id_prestamo }, + }), + ); + return passcode; + } + + async devolverEquipo(passcode, operador) { + const passcodeInterno = await this.findByPasscode(passcode, true); + + // return this.prestamoService + // .regresarIdPrestamo( + // operador.id_operador, + // passcodeInterno.prestamo.id_prestamo, + // ) + // .then((_) => { + // return { code: 1 }; + // }); + } + + async entregarEquipo(passcode, estatus, operador) { + const passcodeInterno = await this.findByPasscode(passcode, false); + if (estatus) { + if (passcodeInterno.abrio != estatus) + passcodeInterno.abrio = estatus === 1 ? true : false; + // return this.prestamoService + // .entregar(passcodeInterno.prestamo.id_prestamo, operador.id_operador) + // .then((_) => { + // return this.repository.save(passcodeInterno).then((_) => { + // return { code: 1 }; + // }); + // }); + } + } + + findByPasscode(passcode: string, abrio?: boolean, id_locker?: string) { + let door = ''; + + return this.repository + .findOne({ where: { passcode, abrio } }) + .then(async (passcode) => { + if (!passcode) + throw new BadRequestException({ + message: `Este passcode no existe`, + code: 6, + }); + if (id_locker) { + await this.prestamoService + .findById(passcode.prestamo.id_prestamo) + .then((prestamo) => { + if (prestamo.equipo.carrito.id_carrito != parseInt(id_locker)) + throw new BadRequestException({ + message: `El id_locker no corresponde`, + code: 4, + }); + door = prestamo.equipo.equipo.substring(1, 3); + }); + return { ...passcode, code: 1, id_locker, door: parseInt(door) }; + } + return passcode; + }); + } + + findPasscode(id_prestamo: number) { + return this.repository + .findOne({ where: { prestamo: { id_prestamo } } }) + .then(async (passcode) => { + if (!passcode) + throw new BadRequestException({ + message: `Este passcode no existe`, + code: 6, + }); + return passcode.passcode; + }); + } +}