because I got bored of customising my CV for every job
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

refactor(server): update job experience entities and services

+271 -163
+1 -1
apps/server/src/modules/job-experience/company/company.entity.ts
··· 1 - import { BaseEntity } from "../../base/base.entity"; 1 + import { BaseEntity } from "@/modules/base/base.entity"; 2 2 3 3 export class Company extends BaseEntity { 4 4 name: string;
+2 -2
apps/server/src/modules/job-experience/company/company.mapper.ts
··· 1 1 import { Injectable } from "@nestjs/common"; 2 2 import type { Company as PrismaCompany } from "@prisma/client"; 3 - import type { BaseMapper } from "../../base/mapper.interface"; 4 - import { Company } from "./company.entity"; 3 + import type { BaseMapper } from "@/modules/base/mapper.interface"; 4 + import { Company } from "@/modules/job-experience/company/company.entity"; 5 5 6 6 /** 7 7 * Mapper service for converting between Prisma Company entities and domain Company entities
+5 -4
apps/server/src/modules/job-experience/company/company.module.ts
··· 1 1 import { Module } from "@nestjs/common"; 2 - import { DatabaseModule } from "../../database/database.module"; 2 + import { BaseModule } from "@/modules/base/base.module"; 3 + import { DatabaseModule } from "@/modules/database/database.module"; 4 + import { CompanyService } from "@/modules/job-experience/company/company.service"; 3 5 import { CompanyMapper } from "./company.mapper"; 4 - import { CompanyResolver } from "./company.resolver"; 5 - import { CompanyService } from "./company.service"; 6 + import { CompanyResolver } from "./graphql/company.resolver"; 6 7 7 8 @Module({ 8 - imports: [DatabaseModule], 9 + imports: [DatabaseModule, BaseModule], 9 10 providers: [CompanyService, CompanyResolver, CompanyMapper], 10 11 exports: [CompanyService, CompanyMapper], 11 12 })
+34 -23
apps/server/src/modules/job-experience/company/company.service.ts
··· 1 - import { Injectable, NotFoundException } from "@nestjs/common"; 2 - import { PrismaService } from "../../database/prisma.service"; 1 + import { Injectable } from "@nestjs/common"; 2 + import { notFound } from "@/modules/base/not-found.util"; 3 + import { PrismaService } from "@/modules/database/prisma.service"; 4 + import { Company } from "@/modules/job-experience/company/company.entity"; 3 5 import type { CreateCompanyDto, UpdateCompanyDto } from "./company.dto"; 4 - import { Company } from "./company.entity"; 5 6 import { CompanyMapper } from "./company.mapper"; 7 + 8 + type CompanyFilters = { 9 + searchTerm?: string | undefined; 10 + }; 6 11 7 12 @Injectable() 8 13 export class CompanyService { ··· 18 23 return this.companyMapper.toDomain(prismaCompany); 19 24 } 20 25 21 - async findAll(): Promise<Company[]> { 26 + async findMany(filters: CompanyFilters = {}): Promise<Company[]> { 27 + const where = filters.searchTerm 28 + ? { 29 + name: { 30 + contains: filters.searchTerm, 31 + mode: "insensitive" as const, 32 + }, 33 + } 34 + : {}; 35 + 22 36 const prismaCompanies = await this.prisma.company.findMany({ 37 + where, 23 38 orderBy: { name: "asc" }, 24 39 }); 40 + 25 41 return this.companyMapper.mapToDomain(prismaCompanies); 26 42 } 27 43 44 + async count(filters: CompanyFilters = {}): Promise<number> { 45 + const where = filters.searchTerm 46 + ? { 47 + name: { 48 + contains: filters.searchTerm, 49 + mode: "insensitive" as const, 50 + }, 51 + } 52 + : {}; 53 + 54 + return this.prisma.company.count({ where }); 55 + } 56 + 28 57 async findById(id: string): Promise<Company | null> { 29 58 const prismaCompany = await this.prisma.company.findUnique({ 30 59 where: { id }, ··· 34 63 35 64 async findByIdOrFail(id: string): Promise<Company> { 36 65 const company = await this.findById(id); 37 - if (!company) { 38 - throw new NotFoundException(`Company with id ${id} not found`); 39 - } 40 - return company; 41 - } 42 - 43 - async findByName(name: string): Promise<Company | null> { 44 - const prismaCompany = await this.prisma.company.findUnique({ 45 - where: { name }, 46 - }); 47 - return this.companyMapper.toDomain(prismaCompany); 48 - } 49 - 50 - async findByNameOrFail(name: string): Promise<Company> { 51 - const company = await this.findByName(name); 52 - if (!company) { 53 - throw new NotFoundException(`Company with name ${name} not found`); 54 - } 55 - return company; 66 + return company ?? notFound("Company", "id", id); 56 67 } 57 68 58 69 async update(
+11 -7
apps/server/src/modules/job-experience/employment/employment.module.ts
··· 1 1 import { Module } from "@nestjs/common"; 2 - import { DatabaseModule } from "../../database/database.module"; 3 - import { CompanyModule } from "../company/company.module"; 4 - import { LevelModule } from "../level/level.module"; 5 - import { RoleModule } from "../role/role.module"; 6 - import { SkillModule } from "../skill/skill.module"; 7 - import { EmploymentResolver } from "./employment.resolver"; 8 - import { UserFieldResolver } from "./user-field.resolver"; 2 + import { AuthModule } from "@/modules/auth/auth.module"; 3 + import { BaseModule } from "@/modules/base/base.module"; 4 + import { DatabaseModule } from "@/modules/database/database.module"; 5 + import { CompanyModule } from "@/modules/job-experience/company/company.module"; 6 + import { LevelModule } from "@/modules/job-experience/level/level.module"; 7 + import { RoleModule } from "@/modules/job-experience/role/role.module"; 8 + import { SkillModule } from "@/modules/job-experience/skill/skill.module"; 9 + import { EmploymentResolver } from "./graphql/employment.resolver"; 10 + import { UserFieldResolver } from "./graphql/user-field.resolver"; 9 11 import { UserJobExperienceMapper } from "./user-job-experience.mapper"; 10 12 import { UserJobExperienceService } from "./user-job-experience.service"; 11 13 12 14 @Module({ 13 15 imports: [ 14 16 DatabaseModule, 17 + BaseModule, 18 + AuthModule, 15 19 CompanyModule, 16 20 RoleModule, 17 21 LevelModule,
+4 -4
apps/server/src/modules/job-experience/employment/user-job-experience.dto.ts
··· 1 - import type { Company } from "../company/company.entity"; 2 - import type { Level } from "../level/level.entity"; 3 - import type { Role } from "../role/role.entity"; 4 - import type { Skill } from "../skill/skill.entity"; 1 + import type { Company } from "@/modules/job-experience/company/company.entity"; 2 + import type { Level } from "@/modules/job-experience/level/level.entity"; 3 + import type { Role } from "@/modules/job-experience/role/role.entity"; 4 + import type { Skill } from "@/modules/job-experience/skill/skill.entity"; 5 5 6 6 export interface CreateUserJobExperienceDto { 7 7 user: { id: string }; // Only need user ID for the relation
+5 -5
apps/server/src/modules/job-experience/employment/user-job-experience.entity.ts
··· 1 - import { BaseEntity } from "../../base/base.entity"; 2 - import type { Company } from "../company/company.entity"; 3 - import type { Level } from "../level/level.entity"; 4 - import type { Role } from "../role/role.entity"; 5 - import type { Skill } from "../skill/skill.entity"; 1 + import { BaseEntity } from "@/modules/base/base.entity"; 2 + import type { Company } from "@/modules/job-experience/company/company.entity"; 3 + import type { Level } from "@/modules/job-experience/level/level.entity"; 4 + import type { Role } from "@/modules/job-experience/role/role.entity"; 5 + import type { Skill } from "@/modules/job-experience/skill/skill.entity"; 6 6 7 7 export class UserJobExperience extends BaseEntity { 8 8 startDate: Date;
+5 -5
apps/server/src/modules/job-experience/employment/user-job-experience.mapper.ts
··· 6 6 Skill as PrismaSkill, 7 7 UserJobExperience as PrismaUserJobExperience, 8 8 } from "@prisma/client"; 9 - import type { BaseMapper } from "../../base/mapper.interface"; 10 - import { CompanyMapper } from "../company/company.mapper"; 11 - import { LevelMapper } from "../level/level.mapper"; 12 - import { RoleMapper } from "../role/role.mapper"; 13 - import { SkillMapper } from "../skill/skill.mapper"; 9 + import type { BaseMapper } from "@/modules/base/mapper.interface"; 10 + import { CompanyMapper } from "@/modules/job-experience/company/company.mapper"; 11 + import { LevelMapper } from "@/modules/job-experience/level/level.mapper"; 12 + import { RoleMapper } from "@/modules/job-experience/role/role.mapper"; 13 + import { SkillMapper } from "@/modules/job-experience/skill/skill.mapper"; 14 14 import { UserJobExperience } from "./user-job-experience.entity"; 15 15 16 16 /**
+52 -17
apps/server/src/modules/job-experience/employment/user-job-experience.service.ts
··· 1 - import { Injectable, NotFoundException } from "@nestjs/common"; 2 - import { PrismaService } from "../../database/prisma.service"; 1 + import { Injectable } from "@nestjs/common"; 2 + import type { Prisma } from "@prisma/client"; 3 + import { notFound } from "@/modules/base/not-found.util"; 4 + import { PaginationService } from "@/modules/base/pagination.service"; 5 + import type { 6 + PaginationOptions, 7 + PaginationResult, 8 + } from "@/modules/base/pagination.types"; 9 + import { PrismaService } from "@/modules/database/prisma.service"; 3 10 import type { 4 11 CreateUserJobExperienceDto, 5 12 UpdateUserJobExperienceDto, ··· 38 45 constructor( 39 46 private prisma: PrismaService, 40 47 private userJobExperienceMapper: UserJobExperienceMapper, 48 + private paginationService: PaginationService, 41 49 ) {} 42 50 43 51 async create( ··· 77 85 return this.userJobExperienceMapper.toDomain(prismaExperience); 78 86 } 79 87 88 + async findMany( 89 + userId?: string, 90 + options: PaginationOptions = {}, 91 + ): Promise<PaginationResult<UserJobExperience>> { 92 + const where: Prisma.UserJobExperienceWhereInput = userId ? { userId } : {}; 93 + const queryOptions = this.paginationService.buildQueryOptions( 94 + where, 95 + { startDate: "desc" }, 96 + options, 97 + ); 98 + 99 + const [items, totalCount] = await Promise.all([ 100 + this.prisma.userJobExperience.findMany({ 101 + ...queryOptions, 102 + include: { 103 + company: true, 104 + role: true, 105 + level: true, 106 + skills: true, 107 + }, 108 + }), 109 + this.prisma.userJobExperience.count({ where }), 110 + ]); 111 + 112 + const domainExperiences = this.userJobExperienceMapper.mapToDomain(items); 113 + return this.paginationService.buildPaginationResult( 114 + domainExperiences, 115 + totalCount, 116 + options, 117 + ); 118 + } 119 + 80 120 async findForUser(user: { id: string }): Promise<UserJobExperience[]> { 81 - const prismaExperiences = await this.prisma.userJobExperience.findMany({ 82 - where: { userId: user.id }, 83 - include: { 84 - company: true, 85 - role: true, 86 - level: true, 87 - skills: true, 88 - }, 89 - orderBy: { startDate: "desc" }, 90 - }); 91 - return this.userJobExperienceMapper.mapToDomain(prismaExperiences); 121 + const result = await this.findMany(user.id); 122 + return result.edges.map((edge) => edge.node); 123 + } 124 + 125 + async findManyForUser( 126 + userId: string, 127 + options: PaginationOptions = {}, 128 + ): Promise<PaginationResult<UserJobExperience>> { 129 + return this.findMany(userId, options); 92 130 } 93 131 94 132 async findById(id: string): Promise<UserJobExperience | null> { ··· 106 144 107 145 async findByIdOrFail(id: string): Promise<UserJobExperience> { 108 146 const experience = await this.findById(id); 109 - if (!experience) { 110 - throw new NotFoundException(`Job experience with id ${id} not found`); 111 - } 112 - return experience; 147 + return experience ?? notFound("Job experience", "id", id); 113 148 } 114 149 115 150 async update(
+1 -1
apps/server/src/modules/job-experience/level/level.entity.ts
··· 1 - import { BaseEntity } from "../../base/base.entity"; 1 + import { BaseEntity } from "@/modules/base/base.entity"; 2 2 3 3 export class Level extends BaseEntity { 4 4 name: string;
+2 -2
apps/server/src/modules/job-experience/level/level.mapper.ts
··· 1 1 import { Injectable } from "@nestjs/common"; 2 2 import type { Level as PrismaLevel } from "@prisma/client"; 3 - import type { BaseMapper } from "../../base/mapper.interface"; 4 - import { Level } from "./level.entity"; 3 + import type { BaseMapper } from "@/modules/base/mapper.interface"; 4 + import { Level } from "@/modules/job-experience/level/level.entity"; 5 5 6 6 /** 7 7 * Mapper service for converting between Prisma Level entities and domain Level entities
+5 -4
apps/server/src/modules/job-experience/level/level.module.ts
··· 1 1 import { Module } from "@nestjs/common"; 2 - import { DatabaseModule } from "../../database/database.module"; 2 + import { BaseModule } from "@/modules/base/base.module"; 3 + import { DatabaseModule } from "@/modules/database/database.module"; 4 + import { LevelService } from "@/modules/job-experience/level/level.service"; 5 + import { LevelResolver } from "./graphql/level.resolver"; 3 6 import { LevelMapper } from "./level.mapper"; 4 - import { LevelResolver } from "./level.resolver"; 5 - import { LevelService } from "./level.service"; 6 7 7 8 @Module({ 8 - imports: [DatabaseModule], 9 + imports: [DatabaseModule, BaseModule], 9 10 providers: [LevelService, LevelResolver, LevelMapper], 10 11 exports: [LevelService, LevelMapper], 11 12 })
+34 -23
apps/server/src/modules/job-experience/level/level.service.ts
··· 1 - import { Injectable, NotFoundException } from "@nestjs/common"; 2 - import { PrismaService } from "../../database/prisma.service"; 1 + import { Injectable } from "@nestjs/common"; 2 + import { notFound } from "@/modules/base/not-found.util"; 3 + import { PrismaService } from "@/modules/database/prisma.service"; 4 + import { Level } from "@/modules/job-experience/level/level.entity"; 3 5 import type { CreateLevelDto, UpdateLevelDto } from "./level.dto"; 4 - import { Level } from "./level.entity"; 5 6 import { LevelMapper } from "./level.mapper"; 7 + 8 + type LevelFilters = { 9 + searchTerm?: string | undefined; 10 + }; 6 11 7 12 @Injectable() 8 13 export class LevelService { ··· 18 23 return this.levelMapper.toDomain(prismaLevel); 19 24 } 20 25 21 - async findAll(): Promise<Level[]> { 26 + async findMany(filters: LevelFilters = {}): Promise<Level[]> { 27 + const where = filters.searchTerm 28 + ? { 29 + name: { 30 + contains: filters.searchTerm, 31 + mode: "insensitive" as const, 32 + }, 33 + } 34 + : {}; 35 + 22 36 const prismaLevels = await this.prisma.level.findMany({ 37 + where, 23 38 orderBy: { name: "asc" }, 24 39 }); 40 + 25 41 return this.levelMapper.mapToDomain(prismaLevels); 26 42 } 27 43 44 + async count(filters: LevelFilters = {}): Promise<number> { 45 + const where = filters.searchTerm 46 + ? { 47 + name: { 48 + contains: filters.searchTerm, 49 + mode: "insensitive" as const, 50 + }, 51 + } 52 + : {}; 53 + 54 + return this.prisma.level.count({ where }); 55 + } 56 + 28 57 async findById(id: string): Promise<Level | null> { 29 58 const prismaLevel = await this.prisma.level.findUnique({ 30 59 where: { id }, ··· 34 63 35 64 async findByIdOrFail(id: string): Promise<Level> { 36 65 const level = await this.findById(id); 37 - if (!level) { 38 - throw new NotFoundException(`Level with id ${id} not found`); 39 - } 40 - return level; 41 - } 42 - 43 - async findByName(name: string): Promise<Level | null> { 44 - const prismaLevel = await this.prisma.level.findUnique({ 45 - where: { name }, 46 - }); 47 - return this.levelMapper.toDomain(prismaLevel); 48 - } 49 - 50 - async findByNameOrFail(name: string): Promise<Level> { 51 - const level = await this.findByName(name); 52 - if (!level) { 53 - throw new NotFoundException(`Level with name ${name} not found`); 54 - } 55 - return level; 66 + return level ?? notFound("Level", "id", id); 56 67 } 57 68 58 69 async update(id: string, updateLevelDto: UpdateLevelDto): Promise<Level> {
+1 -1
apps/server/src/modules/job-experience/role/role.entity.ts
··· 1 - import { BaseEntity } from "../../base/base.entity"; 1 + import { BaseEntity } from "@/modules/base/base.entity"; 2 2 3 3 export class Role extends BaseEntity { 4 4 name: string;
+2 -2
apps/server/src/modules/job-experience/role/role.mapper.ts
··· 1 1 import { Injectable } from "@nestjs/common"; 2 2 import type { Role as PrismaRole } from "@prisma/client"; 3 - import type { BaseMapper } from "../../base/mapper.interface"; 4 - import { Role } from "./role.entity"; 3 + import type { BaseMapper } from "@/modules/base/mapper.interface"; 4 + import { Role } from "@/modules/job-experience/role/role.entity"; 5 5 6 6 /** 7 7 * Mapper service for converting between Prisma Role entities and domain Role entities
+5 -4
apps/server/src/modules/job-experience/role/role.module.ts
··· 1 1 import { Module } from "@nestjs/common"; 2 - import { DatabaseModule } from "../../database/database.module"; 2 + import { BaseModule } from "@/modules/base/base.module"; 3 + import { DatabaseModule } from "@/modules/database/database.module"; 4 + import { RoleService } from "@/modules/job-experience/role/role.service"; 5 + import { RoleResolver } from "./graphql/role.resolver"; 3 6 import { RoleMapper } from "./role.mapper"; 4 - import { RoleResolver } from "./role.resolver"; 5 - import { RoleService } from "./role.service"; 6 7 7 8 @Module({ 8 - imports: [DatabaseModule], 9 + imports: [DatabaseModule, BaseModule], 9 10 providers: [RoleService, RoleResolver, RoleMapper], 10 11 exports: [RoleService, RoleMapper], 11 12 })
+34 -23
apps/server/src/modules/job-experience/role/role.service.ts
··· 1 - import { Injectable, NotFoundException } from "@nestjs/common"; 2 - import { PrismaService } from "../../database/prisma.service"; 1 + import { Injectable } from "@nestjs/common"; 2 + import { notFound } from "@/modules/base/not-found.util"; 3 + import { PrismaService } from "@/modules/database/prisma.service"; 4 + import { Role } from "@/modules/job-experience/role/role.entity"; 3 5 import type { CreateRoleDto, UpdateRoleDto } from "./role.dto"; 4 - import { Role } from "./role.entity"; 5 6 import { RoleMapper } from "./role.mapper"; 7 + 8 + type RoleFilters = { 9 + searchTerm?: string | undefined; 10 + }; 6 11 7 12 @Injectable() 8 13 export class RoleService { ··· 18 23 return this.roleMapper.toDomain(prismaRole); 19 24 } 20 25 21 - async findAll(): Promise<Role[]> { 26 + async findMany(filters: RoleFilters = {}): Promise<Role[]> { 27 + const where = filters.searchTerm 28 + ? { 29 + name: { 30 + contains: filters.searchTerm, 31 + mode: "insensitive" as const, 32 + }, 33 + } 34 + : {}; 35 + 22 36 const prismaRoles = await this.prisma.role.findMany({ 37 + where, 23 38 orderBy: { name: "asc" }, 24 39 }); 40 + 25 41 return this.roleMapper.mapToDomain(prismaRoles); 26 42 } 27 43 44 + async count(filters: RoleFilters = {}): Promise<number> { 45 + const where = filters.searchTerm 46 + ? { 47 + name: { 48 + contains: filters.searchTerm, 49 + mode: "insensitive" as const, 50 + }, 51 + } 52 + : {}; 53 + 54 + return this.prisma.role.count({ where }); 55 + } 56 + 28 57 async findById(id: string): Promise<Role | null> { 29 58 const prismaRole = await this.prisma.role.findUnique({ 30 59 where: { id }, ··· 34 63 35 64 async findByIdOrFail(id: string): Promise<Role> { 36 65 const role = await this.findById(id); 37 - if (!role) { 38 - throw new NotFoundException(`Role with id ${id} not found`); 39 - } 40 - return role; 41 - } 42 - 43 - async findByName(name: string): Promise<Role | null> { 44 - const prismaRole = await this.prisma.role.findUnique({ 45 - where: { name }, 46 - }); 47 - return this.roleMapper.toDomain(prismaRole); 48 - } 49 - 50 - async findByNameOrFail(name: string): Promise<Role> { 51 - const role = await this.findByName(name); 52 - if (!role) { 53 - throw new NotFoundException(`Role with name ${name} not found`); 54 - } 55 - return role; 66 + return role ?? notFound("Role", "id", id); 56 67 } 57 68 58 69 async update(id: string, updateRoleDto: UpdateRoleDto): Promise<Role> {
+1 -1
apps/server/src/modules/job-experience/skill/skill.entity.ts
··· 1 - import { BaseEntity } from "../../base/base.entity"; 1 + import { BaseEntity } from "@/modules/base/base.entity"; 2 2 3 3 export class Skill extends BaseEntity { 4 4 name: string;
+2 -2
apps/server/src/modules/job-experience/skill/skill.mapper.ts
··· 1 1 import { Injectable } from "@nestjs/common"; 2 2 import type { Skill as PrismaSkill } from "@prisma/client"; 3 - import type { BaseMapper } from "../../base/mapper.interface"; 4 - import { Skill } from "./skill.entity"; 3 + import type { BaseMapper } from "@/modules/base/mapper.interface"; 4 + import { Skill } from "@/modules/job-experience/skill/skill.entity"; 5 5 6 6 /** 7 7 * Mapper service for converting between Prisma Skill entities and domain Skill entities
+14 -5
apps/server/src/modules/job-experience/skill/skill.module.ts
··· 1 1 import { Module } from "@nestjs/common"; 2 - import { DatabaseModule } from "../../database/database.module"; 2 + import { BaseModule } from "@/modules/base/base.module"; 3 + import { DatabaseModule } from "@/modules/database/database.module"; 4 + import { SkillService } from "@/modules/job-experience/skill/skill.service"; 5 + import { JobExperienceSeedService } from "../seed/job-experience.seed"; 6 + import { ReferenceDataSeedService } from "../seed/reference-data.seed"; 7 + import { SkillResolver } from "./graphql/skill.resolver"; 3 8 import { SkillMapper } from "./skill.mapper"; 4 - import { SkillResolver } from "./skill.resolver"; 5 - import { SkillService } from "./skill.service"; 6 9 7 10 @Module({ 8 - imports: [DatabaseModule], 9 - providers: [SkillService, SkillResolver, SkillMapper], 11 + imports: [DatabaseModule, BaseModule], 12 + providers: [ 13 + SkillService, 14 + SkillResolver, 15 + SkillMapper, 16 + ReferenceDataSeedService, 17 + JobExperienceSeedService, 18 + ], 10 19 exports: [SkillService, SkillMapper], 11 20 }) 12 21 export class SkillModule {}
+51 -27
apps/server/src/modules/job-experience/skill/skill.service.ts
··· 1 - import { Injectable, NotFoundException } from "@nestjs/common"; 2 - import { PrismaService } from "../../database/prisma.service"; 1 + import { Injectable } from "@nestjs/common"; 2 + import { notFound } from "@/modules/base/not-found.util"; 3 + import { PrismaService } from "@/modules/database/prisma.service"; 4 + import { Skill } from "@/modules/job-experience/skill/skill.entity"; 3 5 import type { CreateSkillDto, UpdateSkillDto } from "./skill.dto"; 4 - import { Skill } from "./skill.entity"; 5 6 import { SkillMapper } from "./skill.mapper"; 6 7 8 + type SkillFilters = { 9 + searchTerm?: string | undefined; 10 + }; 11 + 7 12 @Injectable() 8 13 export class SkillService { 9 14 constructor( ··· 12 17 ) {} 13 18 14 19 async create(createSkillDto: CreateSkillDto): Promise<Skill> { 15 - const prismaSkill = await this.prisma.skill.create({ 20 + const prismaSkill = await this.prisma["skill"].create({ 16 21 data: createSkillDto, 17 22 }); 18 23 return this.skillMapper.toDomain(prismaSkill); 19 24 } 20 25 21 - async findAll(): Promise<Skill[]> { 22 - const prismaSkills = await this.prisma.skill.findMany({ 26 + async findMany(filters: SkillFilters = {}): Promise<Skill[]> { 27 + const where = filters.searchTerm 28 + ? { 29 + name: { 30 + contains: filters.searchTerm, 31 + mode: "insensitive" as const, 32 + }, 33 + } 34 + : {}; 35 + 36 + const prismaSkills = await this.prisma["skill"].findMany({ 37 + where, 23 38 orderBy: { name: "asc" }, 24 39 }); 40 + 25 41 return this.skillMapper.mapToDomain(prismaSkills); 26 42 } 27 43 44 + async count(filters: SkillFilters = {}): Promise<number> { 45 + const where = filters.searchTerm 46 + ? { 47 + name: { 48 + contains: filters.searchTerm, 49 + mode: "insensitive" as const, 50 + }, 51 + } 52 + : {}; 53 + 54 + return this.prisma["skill"].count({ where }); 55 + } 56 + 28 57 async findById(id: string): Promise<Skill | null> { 29 - const prismaSkill = await this.prisma.skill.findUnique({ 58 + const prismaSkill = await this.prisma["skill"].findUnique({ 30 59 where: { id }, 31 60 }); 32 61 return this.skillMapper.toDomain(prismaSkill); 33 62 } 34 63 35 - async findByIdOrFail(id: string): Promise<Skill> { 36 - const skill = await this.findById(id); 37 - if (!skill) { 38 - throw new NotFoundException(`Skill with id ${id} not found`); 39 - } 40 - return skill; 41 - } 42 - 43 - async findByName(name: string): Promise<Skill | null> { 44 - const prismaSkill = await this.prisma.skill.findUnique({ 45 - where: { name }, 64 + async findByVacancyId(vacancyId: string): Promise<Skill[]> { 65 + const prismaSkills = await this.prisma["skill"].findMany({ 66 + where: { 67 + vacancies: { 68 + some: { 69 + id: vacancyId, 70 + }, 71 + }, 72 + }, 46 73 }); 47 - return this.skillMapper.toDomain(prismaSkill); 74 + return this.skillMapper.mapToDomain(prismaSkills); 48 75 } 49 76 50 - async findByNameOrFail(name: string): Promise<Skill> { 51 - const skill = await this.findByName(name); 52 - if (!skill) { 53 - throw new NotFoundException(`Skill with name ${name} not found`); 54 - } 55 - return skill; 77 + async findByIdOrFail(id: string): Promise<Skill> { 78 + const skill = await this.findById(id); 79 + return skill ?? notFound("Skill", "id", id); 56 80 } 57 81 58 82 async update(id: string, updateSkillDto: UpdateSkillDto): Promise<Skill> { 59 - const prismaSkill = await this.prisma.skill.update({ 83 + const prismaSkill = await this.prisma["skill"].update({ 60 84 where: { id }, 61 85 data: updateSkillDto, 62 86 }); ··· 64 88 } 65 89 66 90 async delete(id: string): Promise<void> { 67 - await this.prisma.skill.delete({ 91 + await this.prisma["skill"].delete({ 68 92 where: { id }, 69 93 }); 70 94 }