mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
71 lines
2.2 KiB
TypeScript
71 lines
2.2 KiB
TypeScript
import { Injectable } from "@nestjs/common";
|
|
import { InjectRepository } from "@nestjs/typeorm";
|
|
import { BaseRepository } from "@edr/api-common";
|
|
import { Repository } from "typeorm";
|
|
|
|
import { JobTitle } from "./entities/job-title.entity";
|
|
|
|
@Injectable()
|
|
export class JobTitlesRepository extends BaseRepository<JobTitle> {
|
|
constructor(
|
|
@InjectRepository(JobTitle) repository: Repository<JobTitle>,
|
|
) {
|
|
super(repository);
|
|
}
|
|
|
|
findByCode(organizationId: string, code: string): Promise<JobTitle | null> {
|
|
return this.repository.findOne({ where: { organizationId, code } });
|
|
}
|
|
|
|
async findPage(
|
|
organizationId: string | null,
|
|
filters: {
|
|
search?: string;
|
|
isActive?: boolean;
|
|
page?: number;
|
|
limit?: number;
|
|
sortOrder?: "ASC" | "DESC";
|
|
},
|
|
): Promise<[JobTitle[], number]> {
|
|
const page = filters.page ?? 1;
|
|
const limit = filters.limit ?? 25;
|
|
|
|
const qb = this.repository.createQueryBuilder("title").where("1 = 1");
|
|
|
|
// `null` = every organization (super admin).
|
|
if (organizationId) {
|
|
qb.andWhere("title.organization_id = :organizationId", { organizationId });
|
|
}
|
|
|
|
if (filters.isActive !== undefined) {
|
|
qb.andWhere("title.is_active = :isActive", { isActive: filters.isActive });
|
|
}
|
|
if (filters.search) {
|
|
// Both locales of the jsonb name, plus the code.
|
|
qb.andWhere(
|
|
`(title.code ILIKE :search OR title.name->>'en' ILIKE :search OR title.name->>'am' ILIKE :search)`,
|
|
{ search: `%${filters.search}%` },
|
|
);
|
|
}
|
|
|
|
return qb
|
|
.orderBy("title.gradeLevel", filters.sortOrder ?? "ASC")
|
|
.addOrderBy("title.code", "ASC")
|
|
.skip((page - 1) * limit)
|
|
.take(limit)
|
|
.getManyAndCount();
|
|
}
|
|
|
|
/** How many profiles reference this title — the guard against deleting a
|
|
* title that salary structures and employees still point at. */
|
|
async countEmployeesUsing(jobTitleId: string): Promise<number> {
|
|
const row = await this.repository.manager.query<{ count: string }[]>(
|
|
`SELECT COUNT(*)::text AS count
|
|
FROM hr.employee_profiles
|
|
WHERE job_title_id = $1 AND deleted_at IS NULL`,
|
|
[jobTitleId],
|
|
);
|
|
return parseInt(row[0]?.count ?? "0", 10);
|
|
}
|
|
}
|