Files
lcbp3/backend/src/modules/contract/contract.service.ts
T
admin 1aff83214f
CI / CD Pipeline / build (push) Failing after 17m29s
CI / CD Pipeline / deploy (push) Has been skipped
260326:1347 Fixing Refactor ADR-019 Naming convention uuid #01
2026-03-26 13:47:07 +07:00

129 lines
3.6 KiB
TypeScript

import {
Injectable,
NotFoundException,
ConflictException,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, Like, FindOptionsWhere, FindManyOptions } from 'typeorm';
import { Contract } from './entities/contract.entity';
import { CreateContractDto } from './dto/create-contract.dto.js';
import { UpdateContractDto } from './dto/update-contract.dto.js';
import { UuidResolverService } from '../../common/services/uuid-resolver.service';
@Injectable()
export class ContractService {
constructor(
@InjectRepository(Contract)
private readonly contractRepo: Repository<Contract>,
private readonly uuidResolver: UuidResolverService
) {}
async create(dto: CreateContractDto) {
const internalProjectId = await this.uuidResolver.resolveProjectId(
dto.projectId
);
const existing = await this.contractRepo.findOne({
where: { contractCode: dto.contractCode },
});
if (existing) {
throw new ConflictException(
`Contract Code "${dto.contractCode}" already exists`
);
}
const contract = this.contractRepo.create({
...dto,
projectId: internalProjectId,
});
return this.contractRepo.save(contract);
}
async findAll(params?: {
search?: string;
projectId?: number | string;
page?: number;
limit?: number;
}) {
const { search, projectId, page = 1, limit = 100 } = params || {};
const skip = (page - 1) * limit;
let internalProjectId: number | undefined = undefined;
if (projectId) {
internalProjectId = await this.uuidResolver.resolveProjectId(projectId);
}
const findOptions: FindManyOptions<Contract> = {
relations: ['project'],
order: { contractCode: 'ASC' },
skip,
take: limit,
};
const searchConditions: FindOptionsWhere<Contract>[] = [];
if (search) {
searchConditions.push({ contractCode: Like(`%${search}%`) });
searchConditions.push({ contractName: Like(`%${search}%`) });
}
if (internalProjectId) {
if (searchConditions.length > 0) {
findOptions.where = searchConditions.map((cond) => ({
...cond,
projectId: internalProjectId,
}));
} else {
findOptions.where = { projectId: internalProjectId };
}
} else if (searchConditions.length > 0) {
findOptions.where = searchConditions;
}
const [data, total] = await this.contractRepo.findAndCount(findOptions);
return {
data,
meta: {
total,
page,
limit,
totalPages: Math.ceil(total / limit),
},
};
}
async findOne(id: number) {
const contract = await this.contractRepo.findOne({
where: { id },
relations: ['project'],
});
if (!contract) throw new NotFoundException(`Contract ID ${id} not found`);
return contract;
}
async findOneByPublicId(publicId: string) {
const contract = await this.contractRepo.findOne({
where: { publicId },
relations: ['project'],
});
if (!contract)
throw new NotFoundException(
`Contract with publicId ${publicId} not found`
);
return contract;
}
async update(publicId: string, dto: UpdateContractDto) {
const contract = await this.findOneByPublicId(publicId);
if (dto.projectId) {
dto.projectId = await this.uuidResolver.resolveProjectId(dto.projectId);
}
Object.assign(contract, dto);
return this.contractRepo.save(contract);
}
async remove(publicId: string) {
const contract = await this.findOneByPublicId(publicId);
return this.contractRepo.remove(contract);
}
}