fix issue

This commit is contained in:
Marshal
2026-08-20 18:10:29 +00:00
183 changed files with 14241 additions and 1265 deletions

View File

@@ -94,6 +94,16 @@ export class CreateCargoTypeDto {
@IsBoolean()
isActive?: boolean;
@ApiPropertyOptional({
description:
'Wagons in a full trainset of this cargo (37 vehicles, 22 sand). Blank uses the default.',
example: 37,
})
@IsOptional()
@IsInt()
@Min(1)
fullTrainsetWagons?: number;
@ApiPropertyOptional({ default: 1 })
@IsOptional()
@IsInt()

View File

@@ -1,6 +1,6 @@
import { ApiProperty } from '@nestjs/swagger';
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
import { IsNumber, IsUUID, Min } from 'class-validator';
import { IsNumber, IsOptional, IsUUID, Min } from 'class-validator';
const toNumber = ({ value }: { value: unknown }) =>
value === '' || value == null ? value : Number(value);
@@ -19,4 +19,15 @@ export class CreateYardDistanceDto {
@IsNumber()
@Min(0.01)
distanceKm!: number;
@ApiPropertyOptional({
description:
'Standard running time for this leg in hours. Blank uses the default leg standard.',
example: 21,
})
@IsOptional()
@Transform(toNumber)
@IsNumber()
@Min(0.01)
standardHours?: number;
}

View File

@@ -71,6 +71,15 @@ export class CargoType extends BaseEntity {
@Column({ name: 'tons_per_wagon_map', type: 'jsonb', nullable: true })
tonsPerWagonMap?: Record<string, number> | null;
/**
* Wagons in a full trainset of this cargo — 37 for vehicles, 22 for sand.
* The trainset report divides wagons actually loaded by this figure, so a
* train carrying 30 of a 50-wagon set reports 0.6 trainsets. Null falls back
* to `operations_standards.default_full_trainset_wagons`.
*/
@Column({ name: 'full_trainset_wagons', type: 'int', nullable: true })
fullTrainsetWagons?: number | null;
@Column({ name: 'requires_director_approval', type: 'boolean', default: false })
requiresDirectorApproval!: boolean;

View File

@@ -32,4 +32,15 @@ export class YardDistance extends BaseEntity {
@Column({ name: 'distance_km', type: 'decimal', precision: 10, scale: 2 })
distanceKm!: string; // decimal columns come back as string in typeorm/pg — keep consistent with RouteMilestone.distanceKm
/**
* Standard running time for this leg, in hours — Negad→GMP 21, →Adama 20,
* →Modjo 20.5, →Sebeta 22. The delay report flags a leg that takes longer
* than this plus the tolerance. Null falls back to
* `operations_standards.default_leg_standard_hours`.
*
* Symmetric like the distance itself: an A→B row governs B→A too.
*/
@Column({ name: 'standard_hours', type: 'decimal', precision: 6, scale: 2, nullable: true })
standardHours?: string | null;
}

View File

@@ -204,6 +204,7 @@ export class CargoTypesService {
itemsPerWagonMap: dto.itemsPerWagonMap,
}),
tonsPerWagonMap,
fullTrainsetWagons: dto.fullTrainsetWagons ?? null,
displayOrder,
});
}

View File

@@ -61,6 +61,7 @@ export class YardDistancesService {
fromYardId: dto.fromYardId,
toYardId: dto.toYardId,
distanceKm: dto.distanceKm.toFixed(2),
standardHours: dto.standardHours != null ? dto.standardHours.toFixed(2) : null,
});
return toRow(created);
}
@@ -78,6 +79,9 @@ export class YardDistancesService {
fromYardId,
toYardId,
...(dto.distanceKm != null ? { distanceKm: dto.distanceKm.toFixed(2) } : {}),
...(dto.standardHours !== undefined
? { standardHours: dto.standardHours != null ? dto.standardHours.toFixed(2) : null }
: {}),
});
if (!updated) throw new NotFoundException(`Yard distance ${id} not found`);
return toRow(updated);