From 466c3ca384ef7bf1efc9e1c53d1f1a7d20851a42 Mon Sep 17 00:00:00 2001 From: louis <869322496@qq.com> Date: Wed, 6 Mar 2024 17:13:14 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=87=BA=E5=85=A5=E5=BA=93=E8=AE=B0?= =?UTF-8?q?=E5=BD=95=E6=A8=A1=E5=9D=97=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/constants/enum/index.ts | 5 ++ .../in_out/materials_in_out.dto.ts | 51 +++++++++++--- .../in_out/materials_in_out.entity.ts | 32 +++++---- .../in_out/materials_in_out.service.ts | 67 ++++++++++++++++--- .../materials_inventory.module.ts | 2 + 5 files changed, 126 insertions(+), 31 deletions(-) diff --git a/src/constants/enum/index.ts b/src/constants/enum/index.ts index 0fd9687..1d18590 100644 --- a/src/constants/enum/index.ts +++ b/src/constants/enum/index.ts @@ -18,3 +18,8 @@ export enum MaterialsInOrOutEnum { In, Out } + +// 系统参数key +export enum ParamConfigEnum { + MaterialsInOutPrefix = 'materials_in_out_prefix' +} diff --git a/src/modules/materials_inventory/in_out/materials_in_out.dto.ts b/src/modules/materials_inventory/in_out/materials_in_out.dto.ts index 8f999b1..8ca15c1 100644 --- a/src/modules/materials_inventory/in_out/materials_in_out.dto.ts +++ b/src/modules/materials_inventory/in_out/materials_in_out.dto.ts @@ -2,6 +2,7 @@ import { ApiProperty, IntersectionType, PartialType } from '@nestjs/swagger'; import { Transform } from 'class-transformer'; import { IsArray, + IsBoolean, IsDate, IsDateString, IsEnum, @@ -11,7 +12,8 @@ import { IsOptional, IsString, Matches, - MinLength + MinLength, + ValidateIf } from 'class-validator'; import dayjs from 'dayjs'; import { PagerDto } from '~/common/dto/pager.dto'; @@ -21,9 +23,15 @@ import { formatToDate } from '~/utils'; export class MaterialsInOutDto { @ApiProperty({ description: '产品' }) + @ValidateIf(o => !o.inventoryNumber) @IsNumber() productId: number; + @ApiProperty({ description: '原材料库存编号' }) + @IsOptional() + @IsString() + inventoryNumber: string; + @ApiProperty({ description: '单位(字典)' }) @IsNumber() @IsOptional() @@ -68,10 +76,6 @@ export class MaterialsInOutDto { @IsString() @ApiProperty({ description: '项目' }) project: string; - - // @ApiProperty({ description: '附件' }) - // @IsOptional() - // files: Storage[]; } export class MaterialsInOutUpdateDto extends PartialType(MaterialsInOutDto) { @@ -80,7 +84,7 @@ export class MaterialsInOutUpdateDto extends PartialType(MaterialsInOutDto) { @IsArray() fileIds: number[]; } -export class MaterialsInOutQueryDto extends PagerDto { +export class MaterialsInOutQueryDto extends PagerDto { @ApiProperty({ description: '出入库时间YYYY-MM-DD' }) @IsOptional() // @IsString() @@ -97,10 +101,41 @@ export class MaterialsInOutQueryDto extends PagerDto { @ApiProperty({ description: '入库或出库 0:入库 1:出库' }) @IsOptional() @IsEnum(MaterialsInOrOutEnum) - inOrOut: MaterialsInOrOutEnum; + inOrOut?: MaterialsInOrOutEnum; @ApiProperty({ description: '产品名称' }) @IsOptional() @IsString() - product: string; + product?: string; + + @ApiProperty({ description: '经办人' }) + @IsOptional() + @IsString() + agent?: string; + + @ApiProperty({ description: '领料单号' }) + @IsOptional() + @IsString() + issuanceNumber?: string; + + @ApiProperty({ description: '原材料库存编号' }) + @IsOptional() + @IsString() + inventoryNumber?: string; + + + @IsOptional() + @IsString() + @ApiProperty({ description: '备注' }) + remark?: string; + + @IsOptional() + @IsString() + @ApiProperty({ description: '项目' }) + project?: string; + + @IsOptional() + @IsBoolean() + @ApiProperty({ description: '是否是用于创建出库记录' }) + isCreateOut?: boolean; } diff --git a/src/modules/materials_inventory/in_out/materials_in_out.entity.ts b/src/modules/materials_inventory/in_out/materials_in_out.entity.ts index d3b2cae..5197eb1 100644 --- a/src/modules/materials_inventory/in_out/materials_in_out.entity.ts +++ b/src/modules/materials_inventory/in_out/materials_in_out.entity.ts @@ -1,23 +1,34 @@ import { ApiHideProperty, ApiProperty } from '@nestjs/swagger'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Expose } from 'class-transformer'; +import pinyin from 'pinyin'; import { + BeforeInsert, Column, Entity, JoinColumn, JoinTable, ManyToMany, ManyToOne, - OneToMany, Relation, - VirtualColumn + Repository } from 'typeorm'; import { CommonEntity } from '~/common/entity/common.entity'; -import { MaterialsInOrOutEnum } from '~/constants/enum'; +import { MaterialsInOrOutEnum, ParamConfigEnum } from '~/constants/enum'; import { ProductEntity } from '~/modules/product/product.entity'; -import { DictItemEntity } from '~/modules/system/dict-item/dict-item.entity'; +import { ParamConfigEntity } from '~/modules/system/param-config/param-config.entity'; import { Storage } from '~/modules/tools/storage/storage.entity'; - @Entity({ name: 'materials_in_out' }) export class MaterialsInOutEntity extends CommonEntity { + @Column({ + name: 'inventory_number', + type: 'varchar', + length: 50, + comment: '原材料库存编号' + }) + @ApiProperty({ description: '原材料库存编号' }) + inventoryNumber: string; + @Column({ name: 'product_id', type: 'int', @@ -55,9 +66,9 @@ export class MaterialsInOutEntity extends CommonEntity { @Column({ name: 'unit_price', type: 'decimal', - precision: 10, + precision: 15, default: 0, - scale: 2, + scale: 10, comment: '单价' }) @ApiProperty({ description: '单价' }) @@ -66,9 +77,9 @@ export class MaterialsInOutEntity extends CommonEntity { @Column({ name: 'amount', type: 'decimal', - precision: 10, + precision: 15, default: 0, - scale: 2, + scale: 10, comment: '金额' }) @ApiProperty({ description: '金额' }) @@ -104,9 +115,6 @@ export class MaterialsInOutEntity extends CommonEntity { @JoinColumn({ name: 'product_id' }) product: ProductEntity; - @ApiHideProperty() - unit: DictItemEntity; - @ManyToMany(() => Storage, storage => storage.materialsInOut) @JoinTable({ name: 'materials_in_out_storage', diff --git a/src/modules/materials_inventory/in_out/materials_in_out.service.ts b/src/modules/materials_inventory/in_out/materials_in_out.service.ts index 5e17ee4..3c8b0c1 100644 --- a/src/modules/materials_inventory/in_out/materials_in_out.service.ts +++ b/src/modules/materials_inventory/in_out/materials_in_out.service.ts @@ -14,6 +14,8 @@ import { } from './materials_in_out.dto'; import { MaterialsInOutEntity } from './materials_in_out.entity'; import { fieldSearch } from '~/shared/database/field-search'; +import { ParamConfigEntity } from '~/modules/system/param-config/param-config.entity'; +import { MaterialsInOrOutEnum, ParamConfigEnum } from '~/constants/enum'; @Injectable() export class MaterialsInOutService { @@ -22,7 +24,9 @@ export class MaterialsInOutService { @InjectRepository(MaterialsInOutEntity) private materialsInOutRepository: Repository, @InjectRepository(Storage) - private storageRepository: Repository + private storageRepository: Repository, + @InjectRepository(ParamConfigEntity) + private paramConfigRepository: Repository ) {} /** * 查询所有出入库记录 @@ -31,6 +35,7 @@ export class MaterialsInOutService { page, pageSize, product: productName, + isCreateOut, ...ext }: MaterialsInOutQueryDto): Promise> { const sqb = this.materialsInOutRepository @@ -38,23 +43,21 @@ export class MaterialsInOutService { .leftJoin('materialsInOut.files', 'files') .leftJoin('materialsInOut.product', 'product') .leftJoin('product.unit', 'unit') - .addSelect(['files.id', 'files.path', 'product.id', 'product.name', 'unit.id', 'unit.label']) + .leftJoin('product.company', 'company') + .addSelect(['files.path', 'product.name', 'unit.label', 'company.name']) .where(fieldSearch(ext)) .andWhere('materialsInOut.isDelete = 0') - .addOrderBy('materialsInOut.time', 'DESC'); + .addOrderBy('materialsInOut.createdAt', 'DESC'); if (productName) { sqb.andWhere('product.name like :productName', { productName: `%${productName}%` }); } - let pageData = await paginate(sqb, { + if (isCreateOut) { + sqb.andWhere('materialsInOut.inOrOut = 0'); + } + const pageData = await paginate(sqb, { page, pageSize }); - // 产品表中的单位字段需要单独处理 - pageData.items = pageData.items.map(materialsInOut => { - materialsInOut.unit = materialsInOut.product.unit; - delete materialsInOut.product.unit; - return materialsInOut; - }); return pageData; } @@ -62,7 +65,22 @@ export class MaterialsInOutService { * 新增 */ async create(dto: MaterialsInOutDto): Promise { - await this.materialsInOutRepository.insert(dto); + let { inOrOut, inventoryNumber } = dto; + if (inOrOut === MaterialsInOrOutEnum.In) { + inventoryNumber = await this.generateInventoryNumber(); + } else { + const inRecord = await this.materialsInOutRepository.findOne({ + where: { + inventoryNumber + } + }); + const { productId } = inRecord; + dto.productId = productId; + } + await this.materialsInOutRepository.insert({ + ...this.materialsInOutRepository.create(dto), + inventoryNumber + }); } /** @@ -141,4 +159,31 @@ export class MaterialsInOutService { .addAndRemove(linkedFiles, materialsInOut.files); }); } + + /** + * 生成库存单号 + * @returns 库存单号 + */ + async generateInventoryNumber() { + const prefix = + ( + await this.paramConfigRepository.findOne({ + where: { + key: ParamConfigEnum.MaterialsInOutPrefix + } + }) + )?.value || ''; + const lastMaterial = await this.materialsInOutRepository + .createQueryBuilder('materialsInOut') + .select( + `MAX(CAST(REPLACE(materialsInOut.inventoryNumber, '${prefix}', '') AS UNSIGNED))`, + 'maxInventoryNumber' + ) + .getRawOne(); + const lastNumber = lastMaterial.maxInventoryNumber + ? parseInt(lastMaterial.maxInventoryNumber.replace(prefix, '')) + : 0; + const newNumber = lastNumber + 1 < 1000 ? 1000 : lastNumber + 1; + return `${prefix}${newNumber}`; + } } diff --git a/src/modules/materials_inventory/materials_inventory.module.ts b/src/modules/materials_inventory/materials_inventory.module.ts index a834aa5..f3b42ea 100644 --- a/src/modules/materials_inventory/materials_inventory.module.ts +++ b/src/modules/materials_inventory/materials_inventory.module.ts @@ -7,10 +7,12 @@ 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'; +import { ParamConfigModule } from '../system/param-config/param-config.module'; @Module({ imports: [ TypeOrmModule.forFeature([MaterialsInventoryEntity, MaterialsInOutEntity]), + ParamConfigModule, StorageModule ], controllers: [MaterialsInventoryController, MaterialsInOutController],