Something went wrong. Try again.
because I got bored of customising my CV for every job
Something went wrong. Try again.
3.9 kB · 142 lines
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143import { notFound } from "@cv/core";import { type EntityService, PrismaService } from "@cv/core";import { Injectable } from "@nestjs/common";import { Prisma } from "@prisma/client";import { Application } from "./application.entity";import { DuplicateApplicationError } from "./application.error";import { ApplicationMapper } from "./application.mapper";
type ApplicationFilters = { userId?: string; id?: string | string[];};
type ApplicationWhereInput = { userId?: string; id?: { in: string[] } | string;};
@Injectable()export class ApplicationService implements EntityService<Application, ApplicationFilters>{ readonly applicationInclude = { user: true, vacancy: { include: { company: true, role: true, level: true, jobType: true, skills: true, }, }, status: true, cv: { include: { template: true, }, }, } satisfies Prisma.ApplicationInclude;
constructor( private readonly prisma: PrismaService, private readonly applicationMapper: ApplicationMapper, ) {}
async findById(id: string): Promise<Application | null> { const application = await this.prisma.application.findUnique({ where: { id }, include: this.applicationInclude, });
return application ? this.applicationMapper.toDomain(application) : null; }
async findByIdOrFail(id: string): Promise<Application> { const application = await this.findById(id); return application ?? notFound("Application", "id", id); }
private buildWhere(filters: ApplicationFilters = {}): ApplicationWhereInput { const where: ApplicationWhereInput = {}; if (filters.userId) { where.userId = filters.userId; } if (filters.id !== undefined) { where.id = Array.isArray(filters.id) ? { in: filters.id } : filters.id; } return where; }
async findMany(filters: ApplicationFilters = {}): Promise<Application[]> { const applications = await this.prisma.application.findMany({ where: this.buildWhere(filters), include: this.applicationInclude, orderBy: { appliedAt: "desc" }, });
return this.applicationMapper.mapToDomainWithRelations(applications); }
async count(filters: ApplicationFilters = {}): Promise<number> { return this.prisma.application.count({ where: this.buildWhere(filters) }); }
private buildPrismaData(entity: Application): { statusId: string; cvId: string | null; coverLetter: string | null; } { return { statusId: entity.statusId, cvId: entity.cv?.id ?? null, coverLetter: entity.coverLetter ?? null, }; }
async save(entity: Application): Promise<Application> { const data = this.buildPrismaData(entity);
try { const application = await this.prisma.application.upsert({ where: { id: entity.id }, create: { id: entity.id, userId: entity.userId, profileId: entity.profileId, vacancyId: entity.vacancy.id, ...data, }, update: data, include: this.applicationInclude, });
const domain = this.applicationMapper.toDomain(application); if (!domain) { throw new Error("Failed to map application to domain"); } return domain; } catch (error: unknown) { if ( error instanceof Prisma.PrismaClientKnownRequestError && error.code === "P2002" && error.meta && typeof error.meta === "object" && "target" in error.meta && Array.isArray(error.meta["target"]) && error.meta["target"].includes("userId") && error.meta["target"].includes("vacancyId") ) { throw new DuplicateApplicationError(); } throw error; } }
async destroy(entity: Application): Promise<void> { await this.prisma.application.delete({ where: { id: entity.id }, }); }}