mirror of
https://github.com/HamzaSha1/zod-backend.git
synced 2025-11-26 00:24:54 +00:00
144 lines
5.3 KiB
TypeScript
144 lines
5.3 KiB
TypeScript
import { BadRequestException, Injectable, Logger } from '@nestjs/common';
|
|
import { FindOptionsWhere } from 'typeorm';
|
|
import { Transactional } from 'typeorm-transactional';
|
|
import { Roles } from '~/auth/enums';
|
|
import { PageOptionsRequestDto } from '~/core/dtos';
|
|
import { CustomerService } from '~/customer/services';
|
|
import { DocumentService, OciService } from '~/document/services';
|
|
import { User } from '~/user/entities';
|
|
import { UserType } from '~/user/enums';
|
|
import { UserService } from '~/user/services';
|
|
import { UserTokenService } from '~/user/services/user-token.service';
|
|
import { CreateJuniorRequestDto, SetThemeRequestDto } from '../dtos/request';
|
|
import { Junior } from '../entities';
|
|
import { JuniorRepository } from '../repositories';
|
|
import { QrcodeService } from './qrcode.service';
|
|
|
|
@Injectable()
|
|
export class JuniorService {
|
|
private readonly logger = new Logger(JuniorService.name);
|
|
constructor(
|
|
private readonly juniorRepository: JuniorRepository,
|
|
private readonly userService: UserService,
|
|
private readonly userTokenService: UserTokenService,
|
|
private readonly customerService: CustomerService,
|
|
private readonly documentService: DocumentService,
|
|
private readonly ociService: OciService,
|
|
private readonly qrCodeService: QrcodeService,
|
|
) {}
|
|
|
|
@Transactional()
|
|
async createJuniors(body: CreateJuniorRequestDto, guardianId: string) {
|
|
this.logger.log(`Creating junior for guardian ${guardianId}`);
|
|
|
|
const searchConditions: FindOptionsWhere<User>[] = [{ email: body.email }];
|
|
|
|
if (body.phoneNumber && body.countryCode) {
|
|
searchConditions.push({
|
|
phoneNumber: body.phoneNumber,
|
|
countryCode: body.countryCode,
|
|
});
|
|
}
|
|
|
|
const existingUser = await this.userService.findUser(searchConditions);
|
|
|
|
if (existingUser) {
|
|
this.logger.error(`User with email ${body.email} or phone number ${body.phoneNumber} already exists`);
|
|
throw new BadRequestException('USER.ALREADY_EXISTS');
|
|
}
|
|
|
|
const user = await this.userService.createUser({
|
|
email: body.email,
|
|
countryCode: body.countryCode,
|
|
phoneNumber: body.phoneNumber,
|
|
roles: [Roles.JUNIOR],
|
|
});
|
|
|
|
const customer = await this.customerService.createJuniorCustomer(guardianId, user.id, body);
|
|
|
|
await this.juniorRepository.createJunior(user.id, {
|
|
guardianId,
|
|
relationship: body.relationship,
|
|
customerId: customer.id,
|
|
});
|
|
|
|
this.logger.log(`Junior ${user.id} created successfully`);
|
|
|
|
return this.generateToken(user.id);
|
|
}
|
|
|
|
async findJuniorById(juniorId: string, withGuardianRelation = false, guardianId?: string) {
|
|
this.logger.log(`Finding junior ${juniorId}`);
|
|
const junior = await this.juniorRepository.findJuniorById(juniorId, withGuardianRelation, guardianId);
|
|
|
|
if (!junior) {
|
|
this.logger.error(`Junior ${juniorId} not found`);
|
|
throw new BadRequestException('JUNIOR.NOT_FOUND');
|
|
}
|
|
|
|
this.logger.log(`Junior ${juniorId} found successfully`);
|
|
return junior;
|
|
}
|
|
|
|
@Transactional()
|
|
async setTheme(body: SetThemeRequestDto, juniorId: string) {
|
|
this.logger.log(`Setting theme for junior ${juniorId}`);
|
|
const document = await this.documentService.findDocumentById(body.avatarId);
|
|
if (!document || document.createdById !== juniorId) {
|
|
this.logger.error(`Document ${body.avatarId} not found or not created by junior ${juniorId}`);
|
|
throw new BadRequestException('DOCUMENT.NOT_FOUND');
|
|
}
|
|
const junior = await this.findJuniorById(juniorId);
|
|
if (junior.theme) {
|
|
this.logger.log(`Removing existing theme for junior ${juniorId}`);
|
|
await this.juniorRepository.removeTheme(junior.theme);
|
|
}
|
|
|
|
await this.juniorRepository.setTheme(body, junior);
|
|
this.logger.log(`Theme set for junior ${juniorId}`);
|
|
return this.juniorRepository.findThemeForJunior(juniorId);
|
|
}
|
|
|
|
async findJuniorsByGuardianId(guardianId: string, pageOptions: PageOptionsRequestDto): Promise<[Junior[], number]> {
|
|
this.logger.log(`Finding juniors for guardian ${guardianId}`);
|
|
const [juniors, itemCount] = await this.juniorRepository.findJuniorsByGuardianId(guardianId, pageOptions);
|
|
this.logger.log(`Juniors found for guardian ${guardianId}`);
|
|
await this.prepareJuniorImages(juniors);
|
|
return [juniors, itemCount];
|
|
}
|
|
|
|
async validateToken(token: string) {
|
|
this.logger.log(`Validating token ${token}`);
|
|
const juniorId = await this.userTokenService.validateToken(token, UserType.JUNIOR);
|
|
return this.findJuniorById(juniorId!, true);
|
|
}
|
|
|
|
async generateToken(juniorId: string) {
|
|
this.logger.log(`Generating token for junior ${juniorId}`);
|
|
|
|
const token = await this.userTokenService.generateToken(juniorId);
|
|
|
|
return this.qrCodeService.generateQrCode(token);
|
|
}
|
|
|
|
async doesJuniorBelongToGuardian(guardianId: string, juniorId: string) {
|
|
this.logger.log(`Checking if junior ${juniorId} belongs to guardian ${guardianId}`);
|
|
const junior = await this.findJuniorById(juniorId, false, guardianId);
|
|
|
|
return !!junior;
|
|
}
|
|
|
|
private async prepareJuniorImages(juniors: Junior[]) {
|
|
this.logger.log(`Preparing junior images`);
|
|
await Promise.all(
|
|
juniors.map(async (junior) => {
|
|
const profilePicture = junior.customer.profilePicture;
|
|
|
|
if (profilePicture) {
|
|
profilePicture.url = await this.ociService.generatePreSignedUrl(profilePicture);
|
|
}
|
|
}),
|
|
);
|
|
}
|
|
}
|