feat(procurement): validate acquisition lease fields and enforce bulk-receive capacity

Reject lease start/end and monthly payment on PURCHASE acquisitions (create and
update, validated against the resulting record). Add asset_acquisitions.item_name
column + migration. Enforce warehouse/yard/zone capacity on bulk receive and apply
capacity-counter deltas on save. Adds acquisition-guard spec.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Hagernesh
2026-07-22 11:59:37 +00:00
parent 59f06a9bd1
commit 8dc4dd585e
8 changed files with 201 additions and 42 deletions

View File

@@ -1,7 +1,7 @@
import { Injectable } from '@nestjs/common';
import { BadRequestException, Injectable } from '@nestjs/common';
import { ProcurementRepository } from './procurement.repository';
import { Vendor } from './entities/vendor.entity';
import { AssetAcquisition } from './entities/asset-acquisition.entity';
import { AcquisitionType, AssetAcquisition } from './entities/asset-acquisition.entity';
import { AssetDisposal } from './entities/asset-disposal.entity';
import {
CreateVendorDto,
@@ -51,7 +51,23 @@ export class ProcurementService {
}
// ---- Acquisitions ----
/** Lease terms only make sense on LEASE / RENTAL — a PURCHASE must not carry them. */
private assertLeaseFieldsValid(dto: {
acquisitionType?: string;
leaseStart?: string;
leaseEnd?: string;
monthlyPayment?: number;
}): void {
if (dto.acquisitionType !== AcquisitionType.PURCHASE) return;
if (dto.leaseStart || dto.leaseEnd || dto.monthlyPayment != null) {
throw new BadRequestException(
'Lease start/end and monthly payment are not valid for a PURCHASE acquisition',
);
}
}
async createAcquisition(dto: CreateAcquisitionDto): Promise<AssetAcquisition> {
this.assertLeaseFieldsValid(dto);
return this.procurementRepository.createAcquisition(dto);
}
@@ -64,6 +80,20 @@ export class ProcurementService {
}
async updateAcquisition(id: string, dto: UpdateAcquisitionDto): Promise<AssetAcquisition | null> {
// Validate against the resulting record, not just the patch — switching an
// acquisition to PURCHASE must also shed any stored lease terms.
const existing = await this.procurementRepository.findAcquisitionById(id);
if (existing) {
const next = { ...existing, ...dto };
if (next.acquisitionType === AcquisitionType.PURCHASE) {
this.assertLeaseFieldsValid({
acquisitionType: next.acquisitionType,
leaseStart: dto.leaseStart,
leaseEnd: dto.leaseEnd,
monthlyPayment: dto.monthlyPayment,
});
}
}
return this.procurementRepository.updateAcquisition(id, dto);
}