feat: project filter

This commit is contained in:
louis 2024-03-29 14:41:54 +08:00
parent 59b77cdbc5
commit 072777b5e5
4 changed files with 102 additions and 94 deletions

View File

@ -9,7 +9,7 @@ export class LoginDto {
@ApiProperty({ description: '密码', example: 'a123456' }) @ApiProperty({ description: '密码', example: 'a123456' })
@IsString() @IsString()
@Matches(/^\S*(?=\S{6,})(?=\S*\d)(?=\S*[A-Za-z])\S*$/) @Matches(/^\S*(?=\S{6,})(?=\S*\d)(?=\S*[A-Za-z])\S*$/, { message: '密码错误' })
@MinLength(6) @MinLength(6)
password: string; password: string;

View File

@ -103,7 +103,7 @@ export class MaterialsInOutService {
position, position,
unitPrice, unitPrice,
quantity, quantity,
productId productId
} = dto; } = dto;
inventoryInOutNumber = await this.generateInventoryInOutNumber(inOrOut); inventoryInOutNumber = await this.generateInventoryInOutNumber(inOrOut);
let newRecordId; let newRecordId;
@ -130,84 +130,85 @@ export class MaterialsInOutService {
*/ */
async update(id: number, { fileIds, ...data }: Partial<MaterialsInOutUpdateDto>): Promise<void> { async update(id: number, { fileIds, ...data }: Partial<MaterialsInOutUpdateDto>): Promise<void> {
await this.entityManager.transaction(async manager => { await this.entityManager.transaction(async manager => {
const entity = await manager.findOne(MaterialsInOutEntity, { /* 暂时不允许更改金额和数量,以及不能影响库存变化, */
where: { // const entity = await manager.findOne(MaterialsInOutEntity, {
id // where: {
}, // id
lock: { mode: 'pessimistic_write' } // },
}); // lock: { mode: 'pessimistic_write' }
// });
//
// 修改入库记录的价格,会直接更改库存实际价格. // 修改入库记录的价格,会直接更改库存实际价格.
// 1.如果有了出库记录,不允许修改入库价格。 // 1.如果有了出库记录,不允许修改入库价格。
if ( // if (
Object.is(data.inOrOut, MaterialsInOrOutEnum.In) && // Object.is(data.inOrOut, MaterialsInOrOutEnum.In) &&
isDefined(data.unitPrice) && // isDefined(data.unitPrice) &&
Math.abs(Number(data.unitPrice) - Number(entity.unitPrice)) !== 0 // Math.abs(Number(data.unitPrice) - Number(entity.unitPrice)) !== 0
) { // ) {
const outEntity = await manager.findOne(MaterialsInOutEntity, { // const outEntity = await manager.findOne(MaterialsInOutEntity, {
where: { // where: {
unitPrice: entity.unitPrice, // unitPrice: entity.unitPrice,
inOrOut: MaterialsInOrOutEnum.Out, // inOrOut: MaterialsInOrOutEnum.Out,
projectId: entity.projectId, // projectId: entity.projectId,
productId: entity.productId // productId: entity.productId
} // }
}); // });
if (isDefined(outEntity)) { // if (isDefined(outEntity)) {
throw new BusinessException(ErrorEnum.MATERIALS_IN_OUT_UNIT_PRICE_CANNOT_BE_MODIFIED); // throw new BusinessException(ErrorEnum.MATERIALS_IN_OUT_UNIT_PRICE_CANNOT_BE_MODIFIED);
} // }
await ( // await (
Object.is(data.inOrOut, MaterialsInOrOutEnum.In) // Object.is(data.inOrOut, MaterialsInOrOutEnum.In)
? this.materialsInventoryService.inInventory.bind(this.materialsInventoryService) // ? this.materialsInventoryService.inInventory.bind(this.materialsInventoryService)
: this.materialsInventoryService.outInventory.bind(this.materialsInventoryService) // : this.materialsInventoryService.outInventory.bind(this.materialsInventoryService)
)( // )(
{ // {
productId: entity.productId, // productId: entity.productId,
quantity: 0, // quantity: 0,
unitPrice: entity.unitPrice, // unitPrice: entity.unitPrice,
projectId: entity.projectId, // projectId: entity.projectId,
changedUnitPrice: data.unitPrice // changedUnitPrice: data.unitPrice
}, // },
manager // manager
); // );
} // }
let changedQuantity = 0; // let changedQuantity = 0;
if (isDefined(data.quantity) && entity.quantity !== data.quantity) { // if (isDefined(data.quantity) && entity.quantity !== data.quantity) {
if (entity.inOrOut === MaterialsInOrOutEnum.In) { // if (entity.inOrOut === MaterialsInOrOutEnum.In) {
// 入库减少等于出库 // // 入库减少等于出库
if (data.quantity - entity.quantity < 0) { // if (data.quantity - entity.quantity < 0) {
data.inOrOut = MaterialsInOrOutEnum.Out; // data.inOrOut = MaterialsInOrOutEnum.Out;
} else { // } else {
// 入库增多等于入库 // // 入库增多等于入库
data.inOrOut = MaterialsInOrOutEnum.In; // data.inOrOut = MaterialsInOrOutEnum.In;
} // }
} else { // } else {
// 出库减少等于入库 // // 出库减少等于入库
if (data.quantity - entity.quantity < 0) { // if (data.quantity - entity.quantity < 0) {
data.inOrOut = MaterialsInOrOutEnum.In; // data.inOrOut = MaterialsInOrOutEnum.In;
} else { // } else {
// 出库增多等于出库 // // 出库增多等于出库
data.inOrOut = MaterialsInOrOutEnum.Out; // data.inOrOut = MaterialsInOrOutEnum.Out;
} // }
} // }
changedQuantity = Math.abs(data.quantity - entity.quantity); // changedQuantity = Math.abs(data.quantity - entity.quantity);
} // }
// 2.更新增减库存 // // 2.更新增减库存
if (changedQuantity !== 0) { // if (changedQuantity !== 0) {
await ( // await (
Object.is(data.inOrOut, MaterialsInOrOutEnum.In) // Object.is(data.inOrOut, MaterialsInOrOutEnum.In)
? this.materialsInventoryService.inInventory // ? this.materialsInventoryService.inInventory
: this.materialsInventoryService.outInventory // : this.materialsInventoryService.outInventory
)( // )(
{ // {
productId: entity.productId, // productId: entity.productId,
quantity: Math.abs(changedQuantity), // quantity: Math.abs(changedQuantity),
unitPrice: undefined, // unitPrice: undefined,
projectId: entity.projectId // projectId: entity.projectId
}, // },
manager // manager
); // );
} // }
// 完成所有业务逻辑后,更新出入库记录 // 完成所有业务逻辑后,更新出入库记录
await manager.update(MaterialsInOutEntity, id, { await manager.update(MaterialsInOutEntity, id, {
...data ...data
@ -254,10 +255,8 @@ export class MaterialsInOutService {
: this.materialsInventoryService.inInventory.bind(this.materialsInventoryService) : this.materialsInventoryService.inInventory.bind(this.materialsInventoryService)
)( )(
{ {
productId: entity.productId,
quantity: entity.quantity, quantity: entity.quantity,
unitPrice: entity.unitPrice, inventoryId: entity.inventoryId
projectId: entity.projectId
}, },
manager manager
); );

View File

@ -40,6 +40,11 @@ export class MaterialsInventoryQueryDto extends IntersectionType(
@IsOptional() @IsOptional()
@IsEnum(HasInventoryStatusEnum) @IsEnum(HasInventoryStatusEnum)
isHasInventory: HasInventoryStatusEnum; isHasInventory: HasInventoryStatusEnum;
@ApiProperty({ description: '项目Id' })
@IsOptional()
@IsNumber()
projectId: number;
} }
export class MaterialsInventoryExportDto { export class MaterialsInventoryExportDto {
@ApiProperty({ description: '项目' }) @ApiProperty({ description: '项目' })

View File

@ -318,6 +318,7 @@ export class MaterialsInventoryService {
pageSize, pageSize,
product, product,
keyword, keyword,
projectId,
isHasInventory isHasInventory
}: MaterialsInventoryQueryDto): Promise<Pagination<MaterialsInventoryEntity>> { }: MaterialsInventoryQueryDto): Promise<Pagination<MaterialsInventoryEntity>> {
const queryBuilder = this.materialsInventoryRepository const queryBuilder = this.materialsInventoryRepository
@ -342,6 +343,11 @@ export class MaterialsInventoryService {
if (product) { if (product) {
queryBuilder.andWhere('product.name like :product', { product: `%${product}%` }); queryBuilder.andWhere('product.name like :product', { product: `%${product}%` });
} }
if (projectId) {
queryBuilder.andWhere('project.id = :projectId', { projectId });
}
if (keyword) { if (keyword) {
queryBuilder.andWhere( queryBuilder.andWhere(
'(materialsInventory.inventoryNumber like :keyword or product.name like :keyword or product.productNumber like :keyword or product.productSpecification like :keyword)', '(materialsInventory.inventoryNumber like :keyword or product.name like :keyword or product.productNumber like :keyword or product.productSpecification like :keyword)',
@ -392,6 +398,7 @@ export class MaterialsInventoryService {
projectId: number; projectId: number;
productId: number; productId: number;
quantity: number; quantity: number;
inventoryId?: number;
unitPrice?: number; unitPrice?: number;
changedUnitPrice?: number; changedUnitPrice?: number;
}, },
@ -403,11 +410,17 @@ export class MaterialsInventoryService {
quantity: inQuantity, quantity: inQuantity,
unitPrice, unitPrice,
changedUnitPrice, changedUnitPrice,
position position,
inventoryId
} = data; } = data;
let searchPayload: any = {};
if (isDefined(inventoryId)) {
searchPayload = { id: inventoryId };
} else {
searchPayload = { projectId, productId, unitPrice };
}
const exsitedInventory = await manager.findOne(MaterialsInventoryEntity, { const exsitedInventory = await manager.findOne(MaterialsInventoryEntity, {
where: { projectId, productId, unitPrice }, // 根据项目,产品,价格查出之前的实时库存情况 where: searchPayload, // 根据项目,产品,价格查出之前的实时库存情况
lock: { mode: 'pessimistic_write' } // 开启悲观行锁,防止脏读和修改 lock: { mode: 'pessimistic_write' } // 开启悲观行锁,防止脏读和修改
}); });
@ -447,22 +460,13 @@ export class MaterialsInventoryService {
data: { data: {
quantity: number; quantity: number;
inventoryId?: number; inventoryId?: number;
productId: number;
unitPrice?: number;
}, },
manager: EntityManager manager: EntityManager
): Promise<MaterialsInventoryEntity> { ): Promise<MaterialsInventoryEntity> {
const { quantity: outQuantity, inventoryId, productId, unitPrice } = data; const { quantity: outQuantity, inventoryId } = data;
let searchPayload: any = {};
if (inventoryId) {
searchPayload.id = inventoryId;
} else {
// 删除出入库记录时需要根据产品ID和价格查找库存
searchPayload = { productId, unitPrice };
}
// 开启悲观行锁,防止脏读和修改 // 开启悲观行锁,防止脏读和修改
const inventory = await manager.findOne(MaterialsInventoryEntity, { const inventory = await manager.findOne(MaterialsInventoryEntity, {
where: searchPayload, where: { id: inventoryId },
lock: { mode: 'pessimistic_write' } lock: { mode: 'pessimistic_write' }
}); });
// 检查库存剩余 // 检查库存剩余