import { Injectable } from '@nestjs/common'; import { InjectEntityManager, InjectRepository } from '@nestjs/typeorm'; import { ContractEntity } from './contract.entity'; import { EntityManager, Like, Repository } from 'typeorm'; import { ContractDto, ContractQueryDto, ContractUpdateDto } from './contract.dto'; import { Pagination } from '~/helper/paginate/pagination'; import { isNumber } from 'lodash'; import { paginate } from '~/helper/paginate'; import { Storage } from '../tools/storage/storage.entity'; import { BusinessException } from '~/common/exceptions/biz.exception'; import { ErrorEnum } from '~/constants/error-code.constant'; @Injectable() export class ContractService { constructor( @InjectEntityManager() private entityManager: EntityManager, @InjectRepository(ContractEntity) private contractRepository: Repository, @InjectRepository(Storage) private storageRepository: Repository ) {} /** * 列举所有角色:除去超级管理员 */ async findAll({ page, pageSize, contractNumber, title, type, status }: ContractQueryDto): Promise> { const queryBuilder = this.contractRepository .createQueryBuilder('contract') .leftJoin('contract.files', 'files') .addSelect(['files.id', 'files.path']) .where({ ...(contractNumber ? { contractNumber: Like(`%${contractNumber}%`) } : null), ...(title ? { title: Like(`%${title}%`) } : null), ...(isNumber(type) ? { type } : null), ...(isNumber(status) ? { status } : null) }) .andWhere('contract.isDelete = 0'); return paginate(queryBuilder, { page, pageSize }); } /** * 新增 */ async create(dto: ContractDto): Promise { await this.contractRepository.insert(dto); } /** * 更新 */ async update(id: number, { fileIds, ...data }: Partial): Promise { await this.entityManager.transaction(async manager => { await manager.update(ContractEntity, id, { ...data }); const contract = await this.contractRepository .createQueryBuilder('contract') .leftJoinAndSelect('contract.files', 'files') .where('contract.id = :id', { id }) .getOne(); const count = await this.storageRepository .createQueryBuilder('storage') .where('storage.id in(:fileIds)', { fileIds }) .getCount(); if (count !== fileIds?.length) { throw new BusinessException(ErrorEnum.STORAGE_NOT_FOUND); } // 附件要批量更新 await manager .createQueryBuilder() .relation(ContractEntity, 'files') .of(id) .addAndRemove(fileIds, contract.files); }); } /** * 删除 */ async delete(id: number): Promise { // 合同比较重要,做逻辑删除 await this.contractRepository.update(id, { isDelete: 1 }); } /** * 获取单个合同信息 */ async info(id: number) { const info = await this.contractRepository .createQueryBuilder('contract') .where({ id }) .andWhere('contract.isDelete = 0') .getOne(); return info; } /** * 解除附件关联 * @param id 合同ID * @param fileIds 附件ID */ async unlinkAttachments(id: number, fileIds: number[]) { await this.entityManager.transaction(async manager => { const contract = await this.contractRepository .createQueryBuilder('contract') .leftJoinAndSelect('contract.files', 'files') .where('contract.id = :id', { id }) .getOne(); const linkedFiles = contract.files .map(item => item.id) .filter(item => !fileIds.includes(item)); // 附件要批量更新 await manager .createQueryBuilder() .relation(ContractEntity, 'files') .of(id) .addAndRemove(linkedFiles, contract.files); }); } }