This commit is contained in:
Marshal
2026-07-07 12:28:47 +00:00
parent 1c18fdbd52
commit f300600bfa
63 changed files with 2587 additions and 428 deletions

View File

@@ -1,4 +1,4 @@
import { WagonStatus } from '@edr/types';
import { WagonMovementKind, WagonStatus } from '@edr/types';
import { Injectable, NotFoundException, ConflictException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, DataSource, FindOptionsOrder, FindOptionsWhere, ILike } from 'typeorm';
@@ -8,6 +8,7 @@ import { UpdateWagonDto } from './dto/update-wagon.dto';
import { AssignWagonToTrainDto } from './dto/assign-wagon-to-train.dto';
import { ReorderWagonsDto } from './dto/reorder-wagons.dto';
import { Wagon } from './entities/wagon.entity';
import { WagonMovement } from './entities/wagon-movement.entity';
import { Train } from '../trains/entities/train.entity';
@Injectable()
@@ -74,8 +75,9 @@ export class WagonsService {
return wagon;
}
async update(id: string, dto: UpdateWagonDto): Promise<Wagon> {
async update(id: string, dto: UpdateWagonDto, userId?: string | null): Promise<Wagon> {
const wagon = await this.findById(id);
const previousYardId = wagon.currentYardId ?? null;
Object.assign(wagon, dto);
// `findById` eager-loads `currentYard`; when the DTO changes the scalar FK
// TypeORM otherwise re-derives `current_yard_id` from the STALE relation
@@ -85,11 +87,40 @@ export class WagonsService {
wagon.currentYard = null;
}
await this.wagonRepo.save(wagon);
// Staff manually relocated the wagon — write the movement ledger row so the
// wagon's yard history stays auditable (who moved it, from where, when).
if (
dto.currentYardId !== undefined &&
dto.currentYardId !== null &&
dto.currentYardId !== previousYardId
) {
const movementRepo = this.dataSource.getRepository(WagonMovement);
await movementRepo.save(
movementRepo.create({
wagonId: id,
fromYardId: previousYardId,
toYardId: dto.currentYardId,
kind: WagonMovementKind.Manual,
movedByUserId: userId ?? null,
occurredAt: new Date(),
}),
);
}
// Re-read with the relation so the response reflects the new yard label
// instead of the stale relation object loaded before the assign.
return this.findById(id);
}
/** Movement ledger for one wagon, newest first (loaded legs, repositions, manual moves). */
async listMovements(wagonId: string): Promise<WagonMovement[]> {
await this.findById(wagonId); // 404 on unknown wagon
return this.dataSource.getRepository(WagonMovement).find({
where: { wagonId },
relations: { fromYard: true, toYard: true },
order: { occurredAt: 'DESC', createdAt: 'DESC' },
});
}
async remove(id: string): Promise<void> {
const wagon = await this.findById(id);
await this.wagonRepo.remove(wagon);