mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-28 23:00:57 +00:00
feat(contracts): per-cargo bulk contract templates
This commit is contained in:
@@ -70,6 +70,16 @@ export class CreateCargoTypeDto {
|
||||
@IsBoolean()
|
||||
hasLashing?: boolean;
|
||||
|
||||
@ApiPropertyOptional({
|
||||
default: false,
|
||||
description:
|
||||
'Allow staff to write bulk contract templates for this cargo type. ' +
|
||||
'Mutually exclusive with the parent group / children having it.',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
hasContractTemplate?: boolean;
|
||||
|
||||
@ApiPropertyOptional({ default: true })
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
|
||||
@@ -82,6 +82,14 @@ export class CargoType extends BaseEntity {
|
||||
@Column({ name: 'has_lashing', type: 'boolean', default: false })
|
||||
hasLashing!: boolean;
|
||||
|
||||
/**
|
||||
* Whether staff may write bulk contract templates against this cargo type.
|
||||
* Mutually exclusive between a parent group and its children: if the parent
|
||||
* provides the template, no child may, and vice versa.
|
||||
*/
|
||||
@Column({ name: 'has_contract_template', type: 'boolean', default: false })
|
||||
hasContractTemplate!: boolean;
|
||||
|
||||
@Column({ name: 'is_active', type: 'boolean', default: true })
|
||||
isActive!: boolean;
|
||||
|
||||
|
||||
@@ -135,6 +135,35 @@ export class CargoTypesService {
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* A cargo type and its parent group may not BOTH offer a contract template —
|
||||
* the template would be ambiguous for bookings of the child. To enable the
|
||||
* child, the parent must be turned off first (and vice versa).
|
||||
*/
|
||||
private async assertContractTemplateExclusive(input: {
|
||||
id?: string;
|
||||
parentGroupId?: string | null;
|
||||
}): Promise<void> {
|
||||
if (input.parentGroupId) {
|
||||
const parent = await this.repository.findById(input.parentGroupId);
|
||||
if (parent?.hasContractTemplate) {
|
||||
throw new BadRequestException(
|
||||
`Parent group "${parent.cargoTypeName}" already has a contract template — turn it off there first`,
|
||||
);
|
||||
}
|
||||
}
|
||||
if (input.id) {
|
||||
const children = await this.repository.findAll({
|
||||
where: { parentGroupId: input.id, hasContractTemplate: true },
|
||||
});
|
||||
if (children.length) {
|
||||
throw new BadRequestException(
|
||||
`Child cargo type(s) ${children.map((c) => `"${c.cargoTypeName}"`).join(', ')} already have their own contract template — turn those off first`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Create a new cargo type. */
|
||||
async create(dto: CreateCargoTypeDto): Promise<CargoType> {
|
||||
const code = generateCode(dto.cargoTypeName);
|
||||
@@ -144,6 +173,9 @@ export class CargoTypesService {
|
||||
const parent = await this.repository.findById(dto.parentGroupId);
|
||||
if (!parent) throw new NotFoundException(`Parent cargo type ${dto.parentGroupId} not found`);
|
||||
}
|
||||
if (dto.hasContractTemplate) {
|
||||
await this.assertContractTemplateExclusive({ parentGroupId: dto.parentGroupId });
|
||||
}
|
||||
|
||||
const displayOrder = await this.displayOrder.resolveCreateOrder(CargoType, 'displayOrder', {
|
||||
explicitOrder: dto.displayOrder,
|
||||
@@ -160,6 +192,7 @@ export class CargoTypesService {
|
||||
code,
|
||||
cargoTypeName: dto.cargoTypeName,
|
||||
parentGroupId: dto.parentGroupId ?? null,
|
||||
hasContractTemplate: dto.hasContractTemplate ?? false,
|
||||
requiresDirectorApproval: dto.requiresDirectorApproval ?? false,
|
||||
isActive: dto.isActive ?? true,
|
||||
unitOfMeasure: dto.unitOfMeasure ?? null,
|
||||
@@ -183,6 +216,18 @@ export class CargoTypesService {
|
||||
const parent = await this.repository.findById(dto.parentGroupId);
|
||||
if (!parent) throw new NotFoundException(`Parent cargo type ${dto.parentGroupId} not found`);
|
||||
}
|
||||
// Re-check the parent/child template exclusivity whenever the flag or the
|
||||
// parent moves and the row ends up flagged.
|
||||
const willHaveTemplate = dto.hasContractTemplate ?? existing.hasContractTemplate;
|
||||
if (
|
||||
willHaveTemplate &&
|
||||
(dto.hasContractTemplate !== undefined || dto.parentGroupId !== undefined)
|
||||
) {
|
||||
await this.assertContractTemplateExclusive({
|
||||
id,
|
||||
parentGroupId: dto.parentGroupId ?? existing.parentGroupId,
|
||||
});
|
||||
}
|
||||
const {
|
||||
wagonTypeIds,
|
||||
itemsPerWagonMap,
|
||||
|
||||
Reference in New Issue
Block a user