import { Injectable, UnauthorizedException, NotAcceptableException } from '@nestjs/common'; import { userSelectValidator } from '@/src/auth/select/dtoValidator'; import { RedisHandlers } from '@/src/utils/store/redisHandlers'; import { EmployeeTokenSchema, OccupantTokenSchema, UserType } from '@/src/types/auth/token'; import { PrismaService } from '@/src/prisma.service'; import { MongoService } from '@/src/database/mongo/mongo.service'; import { EventsService } from '@/src/navigator/events/events.service'; @Injectable() export class SelectService { constructor( private readonly redis: RedisHandlers, private readonly prisma: PrismaService, private readonly mongoService: MongoService, private readonly eventService: EventsService ) { } 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: { uu_id: employee.staff_uu_id }, select: { uu_id: true, staff_code: true, user_type_id: true, duties_id: true, staff_name: true, staff_description: true, duties_uu_id: true, created_credentials_token: true, updated_credentials_token: true, confirmed_credentials_token: true, is_confirmed: true, deleted: true, active: true, is_notification_send: true, is_email_send: true, expiry_starts: true, expiry_ends: true, created_at: true, updated_at: true, ref_int: true, user_types: { select: { token: true, type_token: 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 staffUserType = staff.user_type_id ? await this.prisma.user_types.findFirst({ where: { id: staff.user_type_id }, select: { token: true, type_token: true } }) : null; const employeeToken = EmployeeTokenSchema.parse({ uuid: dto.uuid, company: company, department: department, duty: duty, employee: employee, staff: staff, menu: null, pages: null, events: null, selection: await this.prisma.employees.findFirstOrThrow({ where: { uu_id: dto.uuid }, select: { uu_id: true, staff: { select: { uu_id: true, staff_code: true, user_types: { select: { uu_id: true, token: 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, }, }, }, }, }, }, }, }, }, }, }, }), typeToken: staffUserType?.type_token, functionsRetriever: staffUserType?.token, kind: UserType.employee, }); // Render page and menu // const collection = this.mongoService.getDb(`Events/${company.uu_id}`) const events = "" 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 }, select: { uu_id: true, build_parts_uu_id: true, occupant_type_uu_id: true } }); const occupantType = await this.prisma.occupant_types.findFirstOrThrow({ where: { uu_id: livingSpace.occupant_type_uu_id } }); const userTypeInfo = occupantType.user_type_uu_id ? await this.prisma.user_types.findFirst({ where: { uu_id: occupantType.user_type_uu_id }, select: { uu_id: true, type: true, description: true, type_token: true, token: true } }) : null; const part = await this.prisma.build_parts.findFirstOrThrow({ where: { uu_id: livingSpace.build_parts_uu_id }, select: { uu_id: true, part_code: true, part_no: true, part_level: true, human_livable: true, build_uu_id: true, api_enum_dropdown_build_parts_part_type_idToapi_enum_dropdown: { select: { uu_id: true, enum_class: true, value: true } } } }); const build = await this.prisma.build.findFirstOrThrow({ where: { uu_id: part.build_uu_id }, select: { uu_id: true, build_name: true } }); const company = await this.prisma.companies.findFirstOrThrow({ where: { uu_id: accessObject.value.users.related_company }, select: { uu_id: true, is_confirmed: true, deleted: true, active: true, created_at: true, updated_at: true, ref_int: true } }); const occupantToken = OccupantTokenSchema.parse({ uuid: dto.uuid, livingSpace: livingSpace, occupant: occupantType, build: build, part: part, company: company, menu: null, pages: null, events: null, selection: { occupant_types: { uu_id: occupantType.uu_id, occupant_code: occupantType.occupant_code, occupant_type: occupantType.occupant_type }, build_parts: { uu_id: part.uu_id, part_code: part.part_code, part_no: part.part_no, part_level: part.part_level, human_livable: part.human_livable, api_enum_dropdown_build_parts_part_type_idToapi_enum_dropdown: { uu_id: part.api_enum_dropdown_build_parts_part_type_idToapi_enum_dropdown.uu_id, enum_class: part.api_enum_dropdown_build_parts_part_type_idToapi_enum_dropdown.enum_class, value: part.api_enum_dropdown_build_parts_part_type_idToapi_enum_dropdown.value }, build: { uu_id: build.uu_id, build_name: build.build_name } } }, typeToken: userTypeInfo?.type_token, functionsRetriever: userTypeInfo?.token, kind: UserType.occupant }); // Render page and menu const eventsObject = await this.eventService.getEventsOccupants(livingSpace.uu_id) eventsObject && (occupantToken.events = eventsObject) 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'); } } }