import { Injectable, BadRequestException, UnauthorizedException, NotAcceptableException, } from '@nestjs/common'; import { userSelectValidator } from '@/src/auth/select/dtoValidator'; import { RedisHandlers } from '@/src/utils/auth/redis_handlers'; import { EmployeeTokenSchema, OccupantTokenSchema, TokenDictInterface, UserType, } from '@/src/types/auth/token'; import { PrismaService } from '@/src/prisma.service'; @Injectable() export class SelectService { constructor( private readonly redis: RedisHandlers, private readonly prisma: PrismaService, ) {} async run(dto: userSelectValidator, req: Request) { const accessObject = await this.redis.getLoginFromRedis(req); if (!accessObject) { throw new UnauthorizedException( 'Authorization failed. Please login to continue', ); } const accessToken = accessObject.key.split(':')[1]; const existingSelectToken = await this.redis.callExistingSelectToken( accessObject.value.users.uu_id, dto.uuid, ); if (existingSelectToken) { return { message: 'Select successful', token: existingSelectToken, }; } const userType = accessObject.value.users.user_type; if (userType === 'employee') { const employee = await this.prisma.employees.findFirstOrThrow({ where: { uu_id: dto.uuid }, omit: { id: true, }, }); const staff = await this.prisma.staff.findFirstOrThrow({ where: { id: employee.staff_id }, omit: { id: true, }, }); const duties = await this.prisma.duties.findFirstOrThrow({ where: { id: staff.duties_id }, omit: { id: true, }, }); const department = await this.prisma.departments.findFirstOrThrow({ where: { id: duties.department_id }, omit: { id: true, }, }); const duty = await this.prisma.duty.findFirstOrThrow({ where: { id: duties.duties_id }, omit: { id: true, }, }); const company = await this.prisma.companies.findFirstOrThrow({ where: { id: duties.company_id }, omit: { id: true, }, }); const employeeToken = EmployeeTokenSchema.parse({ company: company, department: department, duty: duty, employee: employee, staff: staff, menu: null, pages: null, selection: await this.prisma.employees.findFirstOrThrow({ where: { uu_id: dto.uuid }, select: { uu_id: true, staff: { select: { uu_id: true, staff_code: true, function_retriever: true, duties: { select: { uu_id: true, departments: { select: { uu_id: true, department_code: true, department_name: true, companies: { select: { uu_id: true, formal_name: true, public_name: true, addresses: { select: { comment_address: true, }, }, }, }, }, }, }, }, }, }, }, }), functionsRetriever: staff.function_retriever, kind: UserType.employee, }); const tokenSelect = await this.redis.setSelectToRedis( accessToken, employeeToken, accessObject.value.users.uu_id, dto.uuid, ); return { message: 'Select successful', token: tokenSelect, }; } else if (userType === 'occupant') { const livingSpace = await this.prisma.build_living_space.findFirstOrThrow( { where: { uu_id: dto.uuid }, omit: { id: true, person_id: true, build_parts_id: true, occupant_type_id: true, ref_id: true, replication_id: true, cryp_uu_id: true, }, }, ); const occupantType = await this.prisma.occupant_types.findFirstOrThrow({ where: { uu_id: livingSpace.occupant_type_uu_id }, omit: { id: true, cryp_uu_id: true, ref_id: true, replication_id: true, }, }); const part = await this.prisma.build_parts.findFirstOrThrow({ where: { uu_id: livingSpace.build_parts_uu_id }, omit: { id: true, cryp_uu_id: true, ref_id: true, replication_id: true, }, }); const build = await this.prisma.build.findFirstOrThrow({ where: { uu_id: part.build_uu_id }, omit: { id: true, cryp_uu_id: true, ref_id: true, replication_id: true, }, }); const company = await this.prisma.companies.findFirstOrThrow({ where: { uu_id: accessObject.value.users.related_company }, omit: { id: true, cryp_uu_id: true, ref_id: true, replication_id: true, }, }); const occupantToken = OccupantTokenSchema.parse({ livingSpace: livingSpace, occupant: occupantType, build: build, part: part, company: company, menu: null, pages: null, config: null, caches: null, selection: await this.prisma.build_living_space.findFirstOrThrow({ where: { uu_id: dto.uuid }, select: { uu_id: true, occupant_types: { select: { uu_id: true, occupant_code: true, occupant_type: true, function_retriever: true, }, }, build_parts: { select: { uu_id: true, part_code: true, part_no: true, part_level: true, human_livable: true, api_enum_dropdown_build_parts_part_type_idToapi_enum_dropdown: { select: { uu_id: true, enum_class: true, value: true, }, }, build: { select: { uu_id: true, build_name: true, }, }, }, }, }, }), functionsRetriever: occupantType.function_retriever, kind: UserType.occupant, }); const tokenSelect = await this.redis.setSelectToRedis( accessToken, occupantToken, accessObject.value.users.uu_id, dto.uuid, ); return { message: 'Select successful', token: tokenSelect, }; } else { throw new NotAcceptableException('Invalid user type'); } } }