mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-27 22:30:55 +00:00
Merge branch 'freight_feature/profile' of github.com:Tria-plc/edr-platform into freight_feature/profile
This commit is contained in:
@@ -285,6 +285,7 @@ export class CompaniesService {
|
||||
async findCompanyById(id: string): Promise<Company> {
|
||||
const company = await this.companiesRepo.findById(id);
|
||||
if (!company) throw new NotFoundException(`Company ${id} not found`);
|
||||
company.companyProfiles = await this.companyProfilesRepo.findByCompanyId(id);
|
||||
return company;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ export class CreateFirstMileDto {
|
||||
nullable: true,
|
||||
})
|
||||
@IsOptional()
|
||||
@Transform(({ value }) => (value === '' ? undefined : value))
|
||||
@IsUUID()
|
||||
vehicleId?: string | null;
|
||||
}
|
||||
|
||||
@@ -55,6 +55,13 @@ export class FirstMileController {
|
||||
return this.firstMileService.findById(id);
|
||||
}
|
||||
|
||||
@Post('accept/:reference')
|
||||
@TrainSchedulingManage()
|
||||
@ApiOperation({ summary: 'Accept a paid booking and create a first-mile leg' })
|
||||
acceptBooking(@Param('reference') reference: string) {
|
||||
return this.firstMileService.acceptBooking(reference);
|
||||
}
|
||||
|
||||
@Post()
|
||||
@TrainSchedulingManage()
|
||||
@ApiOperation({ summary: 'Create a first-mile leg' })
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { BookingsModule } from '../bookings/bookings.module';
|
||||
import { FirstMile } from './entities/first-mile.entity';
|
||||
import { FirstMileController } from './first-mile.controller';
|
||||
import { FirstMileRepository } from './first-mile.repository';
|
||||
import { FirstMileService } from './first-mile.service';
|
||||
|
||||
@Module({
|
||||
imports: [TypeOrmModule.forFeature([FirstMile])],
|
||||
imports: [TypeOrmModule.forFeature([FirstMile]), BookingsModule],
|
||||
controllers: [FirstMileController],
|
||||
providers: [FirstMileRepository, FirstMileService],
|
||||
exports: [FirstMileRepository, FirstMileService],
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Injectable, NotFoundException } from '@nestjs/common';
|
||||
import { FindOptionsWhere } from 'typeorm';
|
||||
|
||||
import { BookingsRepository } from '../bookings/bookings.repository';
|
||||
import { CreateFirstMileDto } from './dto/create-first-mile.dto';
|
||||
import { UpdateFirstMileDto } from './dto/update-first-mile.dto';
|
||||
import { FirstMile, FirstMileStatus } from './entities/first-mile.entity';
|
||||
@@ -25,7 +26,32 @@ const SORTABLE_FIELDS: (keyof FirstMile)[] = [
|
||||
|
||||
@Injectable()
|
||||
export class FirstMileService {
|
||||
constructor(private readonly firstMileRepository: FirstMileRepository) {}
|
||||
constructor(
|
||||
private readonly firstMileRepository: FirstMileRepository,
|
||||
private readonly bookingsRepository: BookingsRepository,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Look up a booking by its human-readable reference and confirm it has been
|
||||
* paid before any first-mile work proceeds. Throws if the reference is
|
||||
* unknown or the booking has not reached PAID status.
|
||||
*/
|
||||
async acceptBooking(bookingReference: string): Promise<FirstMile | null> {
|
||||
const booking = await this.bookingsRepository.findByReference(bookingReference);
|
||||
|
||||
if (!booking) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (booking.paymentStatus !== 'PAID') {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.create({
|
||||
bookingId: booking.id,
|
||||
advancedPayment: 0,
|
||||
});
|
||||
}
|
||||
|
||||
async findAll(filter: FirstMileListFilter = {}): Promise<{
|
||||
data: FirstMile[];
|
||||
@@ -45,7 +71,10 @@ export class FirstMileService {
|
||||
|
||||
const [data, total] = await this.firstMileRepository.findAndCount({
|
||||
where,
|
||||
relations: { booking: true, vehicle: true },
|
||||
relations: {
|
||||
booking: { company: true, serviceType: true, originYard: true, destinationYard: true, cargoType: true },
|
||||
vehicle: true,
|
||||
},
|
||||
order: { [sortBy]: sortOrder },
|
||||
skip: (page - 1) * pageSize,
|
||||
take: pageSize,
|
||||
@@ -64,7 +93,10 @@ export class FirstMileService {
|
||||
|
||||
async findById(id: string): Promise<FirstMile> {
|
||||
const record = await this.firstMileRepository.findById(id, {
|
||||
relations: { booking: true, vehicle: true },
|
||||
relations: {
|
||||
booking: { company: true, serviceType: true, originYard: true, destinationYard: true, cargoType: true },
|
||||
vehicle: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!record) {
|
||||
|
||||
@@ -55,6 +55,7 @@ export class CreateLastMileDto {
|
||||
nullable: true,
|
||||
})
|
||||
@IsOptional()
|
||||
@Transform(({ value }) => (value === '' ? undefined : value))
|
||||
@IsUUID()
|
||||
vehicleId?: string | null;
|
||||
}
|
||||
|
||||
@@ -55,6 +55,13 @@ export class LastMileController {
|
||||
return this.lastMileService.findById(id);
|
||||
}
|
||||
|
||||
@Post('accept/:reference')
|
||||
@TrainSchedulingManage()
|
||||
@ApiOperation({ summary: 'Accept a paid booking and create a last-mile leg' })
|
||||
acceptBooking(@Param('reference') reference: string) {
|
||||
return this.lastMileService.acceptBooking(reference);
|
||||
}
|
||||
|
||||
@Post()
|
||||
@TrainSchedulingManage()
|
||||
@ApiOperation({ summary: 'Create a last-mile leg' })
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { BookingsModule } from '../bookings/bookings.module';
|
||||
import { LastMile } from './entities/last-mile.entity';
|
||||
import { LastMileController } from './last-mile.controller';
|
||||
import { LastMileRepository } from './last-mile.repository';
|
||||
import { LastMileService } from './last-mile.service';
|
||||
|
||||
@Module({
|
||||
imports: [TypeOrmModule.forFeature([LastMile])],
|
||||
imports: [TypeOrmModule.forFeature([LastMile]), BookingsModule],
|
||||
controllers: [LastMileController],
|
||||
providers: [LastMileRepository, LastMileService],
|
||||
exports: [LastMileRepository, LastMileService],
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Injectable, NotFoundException } from '@nestjs/common';
|
||||
import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common';
|
||||
import { FindOptionsWhere } from 'typeorm';
|
||||
|
||||
import { BookingsRepository } from '../bookings/bookings.repository';
|
||||
import { CreateLastMileDto } from './dto/create-last-mile.dto';
|
||||
import { UpdateLastMileDto } from './dto/update-last-mile.dto';
|
||||
import { LastMile, LastMileStatus } from './entities/last-mile.entity';
|
||||
@@ -25,7 +26,29 @@ const SORTABLE_FIELDS: (keyof LastMile)[] = [
|
||||
|
||||
@Injectable()
|
||||
export class LastMileService {
|
||||
constructor(private readonly lastMileRepository: LastMileRepository) {}
|
||||
constructor(
|
||||
private readonly lastMileRepository: LastMileRepository,
|
||||
private readonly bookingsRepository: BookingsRepository,
|
||||
) {}
|
||||
|
||||
async acceptBooking(bookingReference: string): Promise<LastMile> {
|
||||
const booking = await this.bookingsRepository.findByReference(bookingReference);
|
||||
|
||||
if (!booking) {
|
||||
throw new NotFoundException(`Booking ${bookingReference} not found`);
|
||||
}
|
||||
|
||||
if (booking.paymentStatus !== 'PAID') {
|
||||
throw new BadRequestException(
|
||||
`Booking ${bookingReference} is not paid (payment status: ${booking.paymentStatus})`,
|
||||
);
|
||||
}
|
||||
|
||||
return this.create({
|
||||
bookingId: booking.id,
|
||||
advancedPayment: booking.totalAmount,
|
||||
});
|
||||
}
|
||||
|
||||
async findAll(filter: LastMileListFilter = {}): Promise<{
|
||||
data: LastMile[];
|
||||
@@ -45,7 +68,10 @@ export class LastMileService {
|
||||
|
||||
const [data, total] = await this.lastMileRepository.findAndCount({
|
||||
where,
|
||||
relations: { booking: true, vehicle: true },
|
||||
relations: {
|
||||
booking: { company: true, serviceType: true, originYard: true, destinationYard: true, cargoType: true },
|
||||
vehicle: true,
|
||||
},
|
||||
order: { [sortBy]: sortOrder },
|
||||
skip: (page - 1) * pageSize,
|
||||
take: pageSize,
|
||||
@@ -64,7 +90,10 @@ export class LastMileService {
|
||||
|
||||
async findById(id: string): Promise<LastMile> {
|
||||
const record = await this.lastMileRepository.findById(id, {
|
||||
relations: { booking: true, vehicle: true },
|
||||
relations: {
|
||||
booking: { company: true, serviceType: true, originYard: true, destinationYard: true, cargoType: true },
|
||||
vehicle: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!record) {
|
||||
|
||||
@@ -35,6 +35,7 @@ import {
|
||||
} from "./payments.dto";
|
||||
import { BookingBatchService } from "../train-scheduling/booking-batch.service";
|
||||
import { DropdownSettingsService } from "../dropdown-settings/dropdown-settings.service";
|
||||
import { FirstMileService } from "../first-mile/first-mile.service";
|
||||
|
||||
/** Setting code holding the global ordering window (months) for general contracts. */
|
||||
const CONTRACT_PERIOD_SETTING_CODE = "general_contract_period";
|
||||
@@ -60,6 +61,7 @@ export class PaymentService {
|
||||
@Inject(forwardRef(() => BookingBatchService))
|
||||
private readonly bookingBatchService: BookingBatchService,
|
||||
private readonly dropdownSettings: DropdownSettingsService,
|
||||
private readonly firstMileService: FirstMileService,
|
||||
) { }
|
||||
|
||||
/** Configured general-contract ordering window in months (defaults to 3). */
|
||||
@@ -342,6 +344,8 @@ export class PaymentService {
|
||||
? { paymentStatus: "PAID", status: "CONTRACT_ACTIVE", expiresAt: contractExpiresAt }
|
||||
: { paymentStatus: "PAID", status: "PAID" },
|
||||
);
|
||||
await this.firstMileService.acceptBooking(input.bookingId);
|
||||
|
||||
});
|
||||
|
||||
if (isGeneralContract) {
|
||||
|
||||
@@ -2272,6 +2272,7 @@ export class TrainSchedulingService {
|
||||
weightTons: roundTons(Number(sb.booking?.cargoTotalWeightVgm ?? 0)),
|
||||
status: sb.booking?.status ?? null,
|
||||
schedulingStatus: sb.booking?.schedulingStatus ?? null,
|
||||
freightType: sb.booking?.freightType ?? null,
|
||||
})) ?? [],
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user