import { Injectable } from '@nestjs/common'; import { InjectEntityManager, InjectRepository } from '@nestjs/typeorm'; import { ProductEntity } from './product.entity'; import { EntityManager, Like, Repository } from 'typeorm'; import { ProductDto, ProductQueryDto, ProductUpdateDto } from './product.dto'; import { Pagination } from '~/helper/paginate/pagination'; 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'; import { fieldSearch } from '~/shared/database/field-search'; @Injectable() export class ProductService { constructor( @InjectEntityManager() private entityManager: EntityManager, @InjectRepository(ProductEntity) private productRepository: Repository, @InjectRepository(Storage) private storageRepository: Repository ) {} /** * 查询所有产品 */ async findAll({ page, pageSize, ...fields }: ProductQueryDto): Promise> { const { company: companyName, ...ext } = fields; const sqb = this.productRepository .createQueryBuilder('product') .leftJoin('product.files', 'files') .leftJoin('product.company', 'company') .addSelect(['files.id', 'files.path', 'company.name', 'company.id']) .where(fieldSearch(ext)) .andWhere('product.isDelete = 0') .addOrderBy('product.namePinyin', 'ASC'); if (companyName) { sqb.andWhere({ company: { name: Like(`%${companyName}%`) } }); } return paginate(sqb, { page, pageSize }); } /** * 新增 */ async create(dto: ProductDto): Promise { const { name, companyId } = dto; const isExsit = await this.productRepository.findOne({ where: { name, company: { id: companyId } } }); if (isExsit) { throw new BusinessException(ErrorEnum.PRODUCT_EXIST); } await this.productRepository.insert(this.productRepository.create(dto)); } /** * 更新 */ async update(id: number, { fileIds, ...data }: Partial): Promise { await this.entityManager.transaction(async manager => { await manager.update( ProductEntity, id, this.productRepository.create({ ...data }) ); const product = await this.productRepository .createQueryBuilder('product') .leftJoinAndSelect('product.files', 'files') .where('product.id = :id', { id }) .getOne(); if (fileIds?.length) { 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(ProductEntity, 'files') .of(id) .addAndRemove(fileIds, product.files); } }); } /** * 删除 */ async delete(id: number): Promise { await this.productRepository.update(id, { isDelete: 1 }); } /** * 获取单个产品信息 */ async info(id: number) { const info = await this.productRepository .createQueryBuilder('product') .leftJoin('product.company', 'company') .addSelect(['company.name', 'company.id']) .where({ id }) .andWhere('product.isDelete = 0') .getOne(); return info; } /** * 解除附件关联 * @param id 产品ID * @param fileIds 附件ID */ async unlinkAttachments(id: number, fileIds: number[]) { await this.entityManager.transaction(async manager => { const product = await this.productRepository .createQueryBuilder('product') .leftJoinAndSelect('product.files', 'files') .where('product.id = :id', { id }) .getOne(); const linkedFiles = product.files .map(item => item.id) .filter(item => !fileIds.includes(item)); // 附件要批量更新 await manager .createQueryBuilder() .relation(ProductEntity, 'files') .of(id) .addAndRemove(linkedFiles, product.files); }); } }