2024-03-04 17:31:28 +08:00
|
|
|
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<ProductEntity>,
|
|
|
|
@InjectRepository(Storage)
|
|
|
|
private storageRepository: Repository<Storage>
|
|
|
|
) {}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 查询所有产品
|
|
|
|
*/
|
|
|
|
async findAll({
|
|
|
|
page,
|
|
|
|
pageSize,
|
|
|
|
...fields
|
|
|
|
}: ProductQueryDto): Promise<Pagination<ProductEntity>> {
|
2024-03-05 22:27:01 +08:00
|
|
|
const { company: companyName, ...ext } = fields;
|
2024-03-05 13:57:03 +08:00
|
|
|
const sqb = this.productRepository
|
2024-03-04 17:31:28 +08:00
|
|
|
.createQueryBuilder('product')
|
|
|
|
.leftJoin('product.files', 'files')
|
2024-03-05 13:57:03 +08:00
|
|
|
.leftJoin('product.company', 'company')
|
|
|
|
.addSelect(['files.id', 'files.path', 'company.name', 'company.id'])
|
|
|
|
.where(fieldSearch(ext))
|
2024-03-05 22:27:01 +08:00
|
|
|
.andWhere('product.isDelete = 0')
|
|
|
|
.addOrderBy('product.namePinyin', 'ASC');
|
2024-03-05 13:57:03 +08:00
|
|
|
if (companyName) {
|
|
|
|
sqb.andWhere({
|
|
|
|
company: {
|
|
|
|
name: Like(`%${companyName}%`)
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return paginate<ProductEntity>(sqb, {
|
2024-03-04 17:31:28 +08:00
|
|
|
page,
|
|
|
|
pageSize
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 新增
|
|
|
|
*/
|
|
|
|
async create(dto: ProductDto): Promise<void> {
|
2024-03-05 13:57:03 +08:00
|
|
|
const { name, companyId } = dto;
|
|
|
|
const isExsit = await this.productRepository.findOne({
|
|
|
|
where: { name, company: { id: companyId } }
|
|
|
|
});
|
|
|
|
if (isExsit) {
|
|
|
|
throw new BusinessException(ErrorEnum.PRODUCT_EXIST);
|
|
|
|
}
|
2024-03-05 22:27:01 +08:00
|
|
|
await this.productRepository.insert(this.productRepository.create(dto));
|
2024-03-04 17:31:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 更新
|
|
|
|
*/
|
|
|
|
async update(id: number, { fileIds, ...data }: Partial<ProductUpdateDto>): Promise<void> {
|
|
|
|
await this.entityManager.transaction(async manager => {
|
2024-03-05 22:27:01 +08:00
|
|
|
await manager.update(
|
|
|
|
ProductEntity,
|
|
|
|
id,
|
|
|
|
this.productRepository.create({
|
|
|
|
...data
|
|
|
|
})
|
|
|
|
);
|
2024-03-04 17:31:28 +08:00
|
|
|
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<void> {
|
|
|
|
await this.productRepository.update(id, { isDelete: 1 });
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2024-03-05 13:57:03 +08:00
|
|
|
* 获取单个产品信息
|
2024-03-04 17:31:28 +08:00
|
|
|
*/
|
|
|
|
async info(id: number) {
|
|
|
|
const info = await this.productRepository
|
|
|
|
.createQueryBuilder('product')
|
2024-03-05 13:57:03 +08:00
|
|
|
.leftJoin('product.company', 'company')
|
|
|
|
.addSelect(['company.name', 'company.id'])
|
2024-03-04 17:31:28 +08:00
|
|
|
.where({
|
|
|
|
id
|
|
|
|
})
|
|
|
|
.andWhere('product.isDelete = 0')
|
|
|
|
.getOne();
|
|
|
|
return info;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 解除附件关联
|
2024-03-05 13:57:03 +08:00
|
|
|
* @param id 产品ID
|
2024-03-04 17:31:28 +08:00
|
|
|
* @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);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|