feat: 产品模块
This commit is contained in:
parent
47b7015c16
commit
df8806a5fb
|
@ -49,5 +49,8 @@ export enum ErrorEnum {
|
||||||
|
|
||||||
// Storage相关
|
// Storage相关
|
||||||
STORAGE_NOT_FOUND = '1404:文件不存在,请重试',
|
STORAGE_NOT_FOUND = '1404:文件不存在,请重试',
|
||||||
STORAGE_REFRENCE_EXISTS = '1405:文件存在关联,无法删除,请先找到该文件关联的业务解除关联。'
|
STORAGE_REFRENCE_EXISTS = '1405:文件存在关联,无法删除,请先找到该文件关联的业务解除关联。',
|
||||||
|
|
||||||
|
// Product
|
||||||
|
PRODUCT_EXIST = '1406:产品已存在'
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,19 @@ export class CompanyUpdateDto extends PartialType(CompanyDto) {
|
||||||
fileIds: number[];
|
fileIds: number[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class ComapnyCreateDto extends PartialType(CompanyDto) {
|
||||||
|
@ApiProperty({ description: '附件' })
|
||||||
|
@IsOptional()
|
||||||
|
@IsArray()
|
||||||
|
fileIds: number[];
|
||||||
|
}
|
||||||
|
|
||||||
export class CompanyQueryDto extends IntersectionType(
|
export class CompanyQueryDto extends IntersectionType(
|
||||||
PagerDto<CompanyDto>,
|
PagerDto<CompanyDto>,
|
||||||
PartialType(CompanyDto)
|
PartialType(CompanyDto)
|
||||||
) {}
|
) {
|
||||||
|
@ApiProperty({ description: '公司名称' })
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import { ApiHideProperty, ApiProperty } from '@nestjs/swagger';
|
import { ApiHideProperty, ApiProperty } from '@nestjs/swagger';
|
||||||
import { Column, Entity, JoinTable, ManyToMany, Relation } from 'typeorm';
|
import { Column, Entity, JoinTable, ManyToMany, OneToMany, Relation } from 'typeorm';
|
||||||
import { CommonEntity } from '~/common/entity/common.entity';
|
import { CommonEntity } from '~/common/entity/common.entity';
|
||||||
import { Storage } from '../tools/storage/storage.entity';
|
import { Storage } from '../tools/storage/storage.entity';
|
||||||
|
import { ProductEntity } from '../product/product.entity';
|
||||||
|
|
||||||
@Entity({ name: 'company' })
|
@Entity({ name: 'company' })
|
||||||
export class CompanyEntity extends CommonEntity {
|
export class CompanyEntity extends CommonEntity {
|
||||||
|
@ -19,6 +20,10 @@ export class CompanyEntity extends CommonEntity {
|
||||||
@ApiProperty({ description: '删除状态:0未删除,1已删除' })
|
@ApiProperty({ description: '删除状态:0未删除,1已删除' })
|
||||||
isDelete: number;
|
isDelete: number;
|
||||||
|
|
||||||
|
@ApiHideProperty()
|
||||||
|
@OneToMany(() => ProductEntity, product => product.company)
|
||||||
|
products: Relation<ProductEntity[]>;
|
||||||
|
|
||||||
@ManyToMany(() => Storage, storage => storage.companys)
|
@ManyToMany(() => Storage, storage => storage.companys)
|
||||||
@JoinTable({
|
@JoinTable({
|
||||||
name: 'company_storage',
|
name: 'company_storage',
|
||||||
|
|
|
@ -16,46 +16,46 @@ export const permissions = definePermission('materials_inventory:history_in_out'
|
||||||
DELETE: 'delete'
|
DELETE: 'delete'
|
||||||
} as const);
|
} as const);
|
||||||
|
|
||||||
@ApiTags('Materials In Out History - 原材料出入库管理')
|
@ApiTags('Materials In Out History - 原材料出入库记录')
|
||||||
@ApiSecurityAuth()
|
@ApiSecurityAuth()
|
||||||
@Controller('materials-in-out')
|
@Controller('materials-in-out')
|
||||||
export class MaterialsInOutController {
|
export class MaterialsInOutController {
|
||||||
constructor(private miService: MaterialsInOutService) {}
|
constructor(private materialsInOutService: MaterialsInOutService) {}
|
||||||
@Get()
|
@Get()
|
||||||
@ApiOperation({ summary: '获取原材料盘点列表' })
|
@ApiOperation({ summary: '获取原材料出入库记录列表' })
|
||||||
@ApiResult({ type: [MaterialsInOutEntity], isPage: true })
|
@ApiResult({ type: [MaterialsInOutEntity], isPage: true })
|
||||||
@Perm(permissions.LIST)
|
@Perm(permissions.LIST)
|
||||||
async list(@Query() dto: MaterialsInOutQueryDto) {
|
async list(@Query() dto: MaterialsInOutQueryDto) {
|
||||||
return this.miService.findAll(dto);
|
return this.materialsInOutService.findAll(dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
@ApiOperation({ summary: '获取原材料盘点信息' })
|
@ApiOperation({ summary: '获取原材料出入库记录信息' })
|
||||||
@ApiResult({ type: MaterialsInOutDto })
|
@ApiResult({ type: MaterialsInOutDto })
|
||||||
@Perm(permissions.READ)
|
@Perm(permissions.READ)
|
||||||
async info(@IdParam() id: number) {
|
async info(@IdParam() id: number) {
|
||||||
return this.miService.info(id);
|
return this.materialsInOutService.info(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
@ApiOperation({ summary: '新增原材料盘点' })
|
@ApiOperation({ summary: '新增原材料出入库记录' })
|
||||||
@Perm(permissions.CREATE)
|
@Perm(permissions.CREATE)
|
||||||
async create(@Body() dto: MaterialsInOutDto): Promise<void> {
|
async create(@Body() dto: MaterialsInOutDto): Promise<void> {
|
||||||
await this.miService.create(dto);
|
await this.materialsInOutService.create(dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Put(':id')
|
@Put(':id')
|
||||||
@ApiOperation({ summary: '更新原材料盘点' })
|
@ApiOperation({ summary: '更新原材料出入库记录' })
|
||||||
@Perm(permissions.UPDATE)
|
@Perm(permissions.UPDATE)
|
||||||
async update(@IdParam() id: number, @Body() dto: MaterialsInOutUpdateDto): Promise<void> {
|
async update(@IdParam() id: number, @Body() dto: MaterialsInOutUpdateDto): Promise<void> {
|
||||||
await this.miService.update(id, dto);
|
await this.materialsInOutService.update(id, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Delete(':id')
|
@Delete(':id')
|
||||||
@ApiOperation({ summary: '删除原材料盘点' })
|
@ApiOperation({ summary: '删除原材料出入库记录' })
|
||||||
@Perm(permissions.DELETE)
|
@Perm(permissions.DELETE)
|
||||||
async delete(@IdParam() id: number): Promise<void> {
|
async delete(@IdParam() id: number): Promise<void> {
|
||||||
await this.miService.delete(id);
|
await this.materialsInOutService.delete(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Put('unlink-attachments/:id')
|
@Put('unlink-attachments/:id')
|
||||||
|
@ -65,6 +65,6 @@ export class MaterialsInOutController {
|
||||||
@IdParam() id: number,
|
@IdParam() id: number,
|
||||||
@Body() { fileIds }: MaterialsInOutUpdateDto
|
@Body() { fileIds }: MaterialsInOutUpdateDto
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await this.miService.unlinkAttachments(id, fileIds);
|
await this.materialsInOutService.unlinkAttachments(id, fileIds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,7 +83,7 @@ export class MaterialsInventoryEntity extends CommonEntity {
|
||||||
comment: '入库单价'
|
comment: '入库单价'
|
||||||
})
|
})
|
||||||
@ApiProperty({ description: '入库单价' })
|
@ApiProperty({ description: '入库单价' })
|
||||||
inventoryUnitPrice: number;
|
inventoryUnitPrice: number;
|
||||||
|
|
||||||
@Column({
|
@Column({
|
||||||
name: 'inventory_amount',
|
name: 'inventory_amount',
|
||||||
|
|
|
@ -4,10 +4,16 @@ import { MaterialsInventoryService } from './materials_inventory.service';
|
||||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
import { MaterialsInventoryEntity } from './materials_inventory.entity';
|
import { MaterialsInventoryEntity } from './materials_inventory.entity';
|
||||||
import { StorageModule } from '../tools/storage/storage.module';
|
import { StorageModule } from '../tools/storage/storage.module';
|
||||||
|
import { MaterialsInOutController } from './in_out/materials_in_out.controller';
|
||||||
|
import { MaterialsInOutService } from './in_out/materials_in_out.service';
|
||||||
|
import { MaterialsInOutEntity } from './in_out/materials_in_out.entity';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [TypeOrmModule.forFeature([MaterialsInventoryEntity]), StorageModule],
|
imports: [
|
||||||
controllers: [MaterialsInventoryController],
|
TypeOrmModule.forFeature([MaterialsInventoryEntity, MaterialsInOutEntity]),
|
||||||
providers: [MaterialsInventoryService]
|
StorageModule
|
||||||
|
],
|
||||||
|
controllers: [MaterialsInventoryController, MaterialsInOutController],
|
||||||
|
providers: [MaterialsInventoryService, MaterialsInOutService]
|
||||||
})
|
})
|
||||||
export class MaterialsInventoryModule {}
|
export class MaterialsInventoryModule {}
|
||||||
|
|
|
@ -18,10 +18,14 @@ import { ProductEntity } from './product.entity';
|
||||||
|
|
||||||
export class ProductDto {
|
export class ProductDto {
|
||||||
@ApiProperty({ description: '产品名称' })
|
@ApiProperty({ description: '产品名称' })
|
||||||
@IsUnique(ProductEntity, { message: '已存在同名产品' })
|
|
||||||
@IsString()
|
@IsString()
|
||||||
name: string;
|
name: string;
|
||||||
|
|
||||||
|
@ApiProperty({ description: '所属公司' })
|
||||||
|
@IsOptional()
|
||||||
|
@IsNumber()
|
||||||
|
companyId: number;
|
||||||
|
|
||||||
@ApiProperty({ description: '附件' })
|
@ApiProperty({ description: '附件' })
|
||||||
files: Storage[];
|
files: Storage[];
|
||||||
}
|
}
|
||||||
|
@ -36,4 +40,9 @@ export class ProductUpdateDto extends PartialType(ProductDto) {
|
||||||
export class ProductQueryDto extends IntersectionType(
|
export class ProductQueryDto extends IntersectionType(
|
||||||
PagerDto<ProductDto>,
|
PagerDto<ProductDto>,
|
||||||
PartialType(ProductDto)
|
PartialType(ProductDto)
|
||||||
) {}
|
) {
|
||||||
|
@ApiProperty({ description: '所属公司名称' })
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
company: string;
|
||||||
|
}
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import { ApiHideProperty, ApiProperty } from '@nestjs/swagger';
|
import { ApiHideProperty, ApiProperty } from '@nestjs/swagger';
|
||||||
import { Column, Entity, JoinTable, ManyToMany, Relation } from 'typeorm';
|
import { Column, Entity, JoinColumn, JoinTable, ManyToMany, ManyToOne, Relation } from 'typeorm';
|
||||||
import { CommonEntity } from '~/common/entity/common.entity';
|
import { CommonEntity } from '~/common/entity/common.entity';
|
||||||
import { Storage } from '../tools/storage/storage.entity';
|
import { Storage } from '../tools/storage/storage.entity';
|
||||||
|
import { CompanyEntity } from '../company/company.entity';
|
||||||
|
|
||||||
@Entity({ name: 'product' })
|
@Entity({ name: 'product' })
|
||||||
export class ProductEntity extends CommonEntity {
|
export class ProductEntity extends CommonEntity {
|
||||||
@Column({
|
@Column({
|
||||||
name: 'name',
|
name: 'name',
|
||||||
type: 'varchar',
|
type: 'varchar',
|
||||||
unique: true,
|
|
||||||
length: 255,
|
length: 255,
|
||||||
comment: '产品名称'
|
comment: '产品名称'
|
||||||
})
|
})
|
||||||
|
@ -19,6 +19,14 @@ export class ProductEntity extends CommonEntity {
|
||||||
@ApiProperty({ description: '删除状态:0未删除,1已删除' })
|
@ApiProperty({ description: '删除状态:0未删除,1已删除' })
|
||||||
isDelete: number;
|
isDelete: number;
|
||||||
|
|
||||||
|
@Column({ name: 'company_id', type: 'int', comment: '所属公司', nullable: true })
|
||||||
|
@ApiProperty({ description: '所属公司' })
|
||||||
|
companyId: number;
|
||||||
|
|
||||||
|
@ManyToOne(() => CompanyEntity /* , { onDelete: 'CASCADE' } */)
|
||||||
|
@JoinColumn({ name: 'company_id' })
|
||||||
|
company: CompanyEntity;
|
||||||
|
|
||||||
@ManyToMany(() => Storage, storage => storage.products)
|
@ManyToMany(() => Storage, storage => storage.products)
|
||||||
@JoinTable({
|
@JoinTable({
|
||||||
name: 'product_storage',
|
name: 'product_storage',
|
||||||
|
|
|
@ -28,14 +28,22 @@ export class ProductService {
|
||||||
pageSize,
|
pageSize,
|
||||||
...fields
|
...fields
|
||||||
}: ProductQueryDto): Promise<Pagination<ProductEntity>> {
|
}: ProductQueryDto): Promise<Pagination<ProductEntity>> {
|
||||||
const queryBuilder = this.productRepository
|
const { company: companyName,...ext } = fields;
|
||||||
|
const sqb = this.productRepository
|
||||||
.createQueryBuilder('product')
|
.createQueryBuilder('product')
|
||||||
.leftJoin('product.files', 'files')
|
.leftJoin('product.files', 'files')
|
||||||
.addSelect(['files.id', 'files.path'])
|
.leftJoin('product.company', 'company')
|
||||||
.where(fieldSearch(fields))
|
.addSelect(['files.id', 'files.path', 'company.name', 'company.id'])
|
||||||
.andWhere('product.isDelete = 0');
|
.where(fieldSearch(ext))
|
||||||
|
.where('product.isDelete = 0');
|
||||||
return paginate<ProductEntity>(queryBuilder, {
|
if (companyName) {
|
||||||
|
sqb.andWhere({
|
||||||
|
company: {
|
||||||
|
name: Like(`%${companyName}%`)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return paginate<ProductEntity>(sqb, {
|
||||||
page,
|
page,
|
||||||
pageSize
|
pageSize
|
||||||
});
|
});
|
||||||
|
@ -45,6 +53,13 @@ export class ProductService {
|
||||||
* 新增
|
* 新增
|
||||||
*/
|
*/
|
||||||
async create(dto: ProductDto): Promise<void> {
|
async create(dto: ProductDto): Promise<void> {
|
||||||
|
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(dto);
|
await this.productRepository.insert(dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,16 +98,17 @@ export class ProductService {
|
||||||
* 删除
|
* 删除
|
||||||
*/
|
*/
|
||||||
async delete(id: number): Promise<void> {
|
async delete(id: number): Promise<void> {
|
||||||
// 合同比较重要,做逻辑删除
|
|
||||||
await this.productRepository.update(id, { isDelete: 1 });
|
await this.productRepository.update(id, { isDelete: 1 });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取单个合同信息
|
* 获取单个产品信息
|
||||||
*/
|
*/
|
||||||
async info(id: number) {
|
async info(id: number) {
|
||||||
const info = await this.productRepository
|
const info = await this.productRepository
|
||||||
.createQueryBuilder('product')
|
.createQueryBuilder('product')
|
||||||
|
.leftJoin('product.company', 'company')
|
||||||
|
.addSelect(['company.name', 'company.id'])
|
||||||
.where({
|
.where({
|
||||||
id
|
id
|
||||||
})
|
})
|
||||||
|
@ -103,7 +119,7 @@ export class ProductService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解除附件关联
|
* 解除附件关联
|
||||||
* @param id 合同ID
|
* @param id 产品ID
|
||||||
* @param fileIds 附件ID
|
* @param fileIds 附件ID
|
||||||
*/
|
*/
|
||||||
async unlinkAttachments(id: number, fileIds: number[]) {
|
async unlinkAttachments(id: number, fileIds: number[]) {
|
||||||
|
|
Loading…
Reference in New Issue