feat: complete train scheduling integration

This commit is contained in:
hagiye
2026-06-06 05:52:47 +03:00
parent 29247d4140
commit 788de5381e
56 changed files with 1191 additions and 141 deletions

View File

@@ -2,13 +2,14 @@ import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Cargo } from './entities/cargoes.entity';
import { Container } from '../container-management/entities/container.entity';
import { CargoType } from '../rule-engine/entities/cargo-type.entity';
import { CargoesController } from './cargoes.controller';
import { CargoesService } from './cargoes.service';
@Module({
imports: [TypeOrmModule.forFeature([Cargo, Container])],
imports: [TypeOrmModule.forFeature([Cargo, Container, CargoType])],
controllers: [CargoesController],
providers: [CargoesService],
exports: [CargoesService],
})
export class CargoesModule {}
export class CargoesModule {}

View File

@@ -7,6 +7,7 @@ import { LoadCargoDto } from './dto/load-cargo.dto';
import { DeliverCargoDto } from './dto/deliver-cargo.dto';
import { Cargo } from './entities/cargoes.entity';
import { Container } from '../container-management/entities/container.entity';
import { CargoType } from '../rule-engine/entities/cargo-type.entity';
@Injectable()
export class CargoesService {
@@ -15,9 +16,30 @@ export class CargoesService {
private readonly cargoRepo: Repository<Cargo>,
@InjectRepository(Container)
private readonly containerRepo: Repository<Container>,
@InjectRepository(CargoType)
private readonly cargoTypeRepo: Repository<CargoType>,
) {}
async create(dto: CreateCargoDto): Promise<Cargo> {
const existing = await this.cargoRepo.findOne({
where: { cargoReference: dto.cargoReference },
});
if (existing) {
throw new ConflictException(`Cargo reference "${dto.cargoReference}" already exists`);
}
const container = await this.containerRepo.findOne({ where: { id: dto.containerId } });
if (!container) {
throw new NotFoundException(`Container ${dto.containerId} not found`);
}
if (dto.cargoTypeId) {
const cargoType = await this.cargoTypeRepo.findOne({
where: { id: dto.cargoTypeId, isActive: true },
});
if (!cargoType) throw new NotFoundException(`Cargo type ${dto.cargoTypeId} not found`);
}
const cargo = this.cargoRepo.create(dto);
return this.cargoRepo.save(cargo);
}
@@ -62,6 +84,24 @@ export class CargoesService {
async update(id: string, dto: UpdateCargoDto): Promise<Cargo> {
const cargo = await this.findById(id);
if (dto.cargoReference && dto.cargoReference !== cargo.cargoReference) {
const existing = await this.cargoRepo.findOne({
where: { cargoReference: dto.cargoReference },
});
if (existing) {
throw new ConflictException(`Cargo reference "${dto.cargoReference}" already exists`);
}
}
if (dto.containerId) {
const container = await this.containerRepo.findOne({ where: { id: dto.containerId } });
if (!container) throw new NotFoundException(`Container ${dto.containerId} not found`);
}
if (dto.cargoTypeId) {
const cargoType = await this.cargoTypeRepo.findOne({
where: { id: dto.cargoTypeId, isActive: true },
});
if (!cargoType) throw new NotFoundException(`Cargo type ${dto.cargoTypeId} not found`);
}
Object.assign(cargo, dto);
return this.cargoRepo.save(cargo);
}

View File

@@ -3,12 +3,13 @@ import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Container } from './entities/container.entity';
import { Wagon } from '../wagons/entities/wagon.entity';
import { ContainerType } from '../rule-engine/entities/container-type.entity';
import { ContainersController } from './containers.controller';
import { ContainersService } from './containers.service';
@Module({
imports: [TypeOrmModule.forFeature([Container, Wagon])], // ✅ add Wagon
imports: [TypeOrmModule.forFeature([Container, Wagon, ContainerType])],
controllers: [ContainersController],
providers: [ContainersService],
})
export class ContainersModule {}
export class ContainersModule {}

View File

@@ -7,6 +7,7 @@ import { UpdateContainerDto } from './dto/update-container.dto';
import { AssignContainerToWagonDto } from './dto/assign-container-to-wagon.dto';
import { Container } from './entities/container.entity';
import { Wagon } from '../wagons/entities/wagon.entity';
import { ContainerType } from '../rule-engine/entities/container-type.entity';
@Injectable()
export class ContainersService {
@@ -15,9 +16,30 @@ export class ContainersService {
private readonly containerRepo: Repository<Container>,
@InjectRepository(Wagon)
private readonly wagonRepo: Repository<Wagon>, // ✅ use raw repository
@InjectRepository(ContainerType)
private readonly containerTypeRepo: Repository<ContainerType>,
) {}
async create(dto: CreateContainerDto): Promise<Container> {
const existing = await this.containerRepo.findOne({
where: { containerNumber: dto.containerNumber },
});
if (existing) {
throw new ConflictException(`Container number "${dto.containerNumber}" already exists`);
}
const containerType = await this.containerTypeRepo.findOne({
where: { id: dto.containerTypeId, isActive: true },
});
if (!containerType) {
throw new NotFoundException(`Container type ${dto.containerTypeId} not found`);
}
if (dto.wagonId) {
const wagon = await this.wagonRepo.findOne({ where: { id: dto.wagonId } });
if (!wagon) throw new NotFoundException(`Wagon ${dto.wagonId} not found`);
}
const container = this.containerRepo.create(dto);
if (dto.wagonId === undefined) container.wagonId = null;
if (dto.position === undefined) container.position = null;
@@ -59,6 +81,26 @@ export class ContainersService {
async update(id: string, dto: UpdateContainerDto): Promise<Container> {
const container = await this.findById(id);
if (dto.containerNumber && dto.containerNumber !== container.containerNumber) {
const existing = await this.containerRepo.findOne({
where: { containerNumber: dto.containerNumber },
});
if (existing) {
throw new ConflictException(`Container number "${dto.containerNumber}" already exists`);
}
}
if (dto.containerTypeId) {
const containerType = await this.containerTypeRepo.findOne({
where: { id: dto.containerTypeId, isActive: true },
});
if (!containerType) {
throw new NotFoundException(`Container type ${dto.containerTypeId} not found`);
}
}
if (dto.wagonId) {
const wagon = await this.wagonRepo.findOne({ where: { id: dto.wagonId } });
if (!wagon) throw new NotFoundException(`Wagon ${dto.wagonId} not found`);
}
Object.assign(container, dto);
return this.containerRepo.save(container);
}

View File

@@ -4,11 +4,6 @@ import { Public } from "@edr/api-common";
import { randomUUID } from "crypto";
import { Response } from "express"
import * as fs from 'fs';
import * as path from 'path';
import Handlebars from 'handlebars';
@Public()
@Controller("payments")
export class PaymentController {
@@ -86,4 +81,4 @@ export class PaymentController {
}
}

View File

@@ -118,9 +118,11 @@ export class TrainSchedulingService {
);
}
queryBuilder.andWhere("booking.status = :status", {
status: query.status ?? "PAID",
});
if (query.status) {
queryBuilder.andWhere("booking.status = :status", {
status: query.status,
});
}
const bookings = await queryBuilder
.orderBy("booking.scheduled_date", "ASC")

View File

@@ -0,0 +1,16 @@
import { Controller, Get } from '@nestjs/common';
import { ApiTags, ApiOperation } from '@nestjs/swagger';
import { WagonTypesService } from './wagon-types.service';
import { WagonType } from './entities/wagon-type.entity';
@ApiTags('Wagon Types')
@Controller('wagon-types')
export class WagonTypesController {
constructor(private readonly wagonTypesService: WagonTypesService) {}
@Get()
@ApiOperation({ summary: 'Get all active wagon types' })
async findAll(): Promise<WagonType[]> {
return this.wagonTypesService.findAll();
}
}

View File

@@ -2,11 +2,13 @@ import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { WagonType } from './entities/wagon-type.entity';
import { WagonTypesController } from './wagon-types.controller';
import { WagonTypesRepository } from './wagon-types.repository';
import { WagonTypesService } from './wagon-types.service';
@Module({
imports: [TypeOrmModule.forFeature([WagonType])],
controllers: [WagonTypesController],
providers: [WagonTypesRepository, WagonTypesService],
exports: [WagonTypesRepository, WagonTypesService],
})

View File

@@ -7,6 +7,13 @@ import { WagonTypesRepository } from './wagon-types.repository';
export class WagonTypesService {
constructor(private readonly wagonTypesRepository: WagonTypesRepository) {}
async findAll(): Promise<WagonType[]> {
return this.wagonTypesRepository.findAll({
where: { isActive: true },
order: { code: 'ASC' },
});
}
async findByCode(code: string): Promise<WagonType> {
const [wagonType] = await this.wagonTypesRepository.findAll({ where: { code } });