mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 12:18:11 +00:00
95 lines
3.1 KiB
TypeScript
95 lines
3.1 KiB
TypeScript
import { BaseRepository } from "@edr/api-common";
|
|
import { Injectable } from "@nestjs/common";
|
|
import { InjectRepository } from "@nestjs/typeorm";
|
|
import { In, IsNull, Not, Repository } from "typeorm";
|
|
|
|
import { Booking } from "./entities/booking.entity";
|
|
import { FileRecord } from "../files/entities/file.entity";
|
|
|
|
@Injectable()
|
|
export class BookingsRepository extends BaseRepository<Booking> {
|
|
constructor(
|
|
@InjectRepository(Booking)
|
|
repository: Repository<Booking>,
|
|
) {
|
|
super(repository);
|
|
}
|
|
|
|
/** Find a booking by its human-readable reference number. */
|
|
findByReference(reference: string): Promise<Booking | null> {
|
|
return this.repository.findOne({ where: { reference } });
|
|
}
|
|
|
|
/** Find a booking by reference with associated files (polymorphic join). */
|
|
async findByReferenceWithFiles(reference: string): Promise<Booking | null> {
|
|
const booking = await this.repository
|
|
.createQueryBuilder("booking")
|
|
.where("booking.reference = :reference", { reference })
|
|
.leftJoinAndMapMany(
|
|
"booking.files",
|
|
FileRecord,
|
|
"file",
|
|
"file.resource_id = booking.id AND file.resource = 'bookings'"
|
|
)
|
|
.getOne();
|
|
return booking ?? null;
|
|
}
|
|
|
|
/** Find a booking by ID with associated files (polymorphic join). */
|
|
async findByIdWithFiles(id: string): Promise<Booking | null> {
|
|
const booking = await this.repository
|
|
.createQueryBuilder("booking")
|
|
.where("booking.id = :id", { id })
|
|
.leftJoinAndMapMany(
|
|
"booking.files",
|
|
FileRecord,
|
|
"file",
|
|
"file.resource_id = booking.id AND file.resource = 'bookings'"
|
|
)
|
|
.getOne();
|
|
return booking ?? null;
|
|
}
|
|
|
|
/** Find a compatible consolidation partner for the given booking. */
|
|
async findConsolidationPartner(booking: Booking): Promise<Booking | null> {
|
|
return this.repository.findOne({
|
|
where: {
|
|
allowConsolidation: true,
|
|
// Check if containers JSONB contains at least one 20FT entry with odd qty
|
|
containers: Not(IsNull()),
|
|
originStation: booking.originStation,
|
|
destinationStation: booking.destinationStation,
|
|
tradeDirection: booking.tradeDirection,
|
|
consolidationPartnerId: IsNull(),
|
|
status: In(["DRAFT", "PENDING_CONSOLIDATION"]),
|
|
id: Not(booking.id),
|
|
},
|
|
order: { createdAt: "ASC" },
|
|
});
|
|
}
|
|
|
|
/** Pair two bookings for consolidation. */
|
|
async pairConsolidation(bookingId: string, partnerId: string): Promise<void> {
|
|
await this.repository.update(bookingId, {
|
|
consolidationPartnerId: partnerId,
|
|
status: "CONSOLIDATED",
|
|
} as never);
|
|
await this.repository.update(partnerId, {
|
|
consolidationPartnerId: bookingId,
|
|
status: "CONSOLIDATED",
|
|
} as never);
|
|
}
|
|
|
|
/** Un-pair a consolidation. Returns both booking IDs. */
|
|
async unpairConsolidation(bookingId: string, partnerId: string): Promise<void> {
|
|
await this.repository.update(bookingId, {
|
|
consolidationPartnerId: null,
|
|
status: "PENDING_CONSOLIDATION",
|
|
} as never);
|
|
await this.repository.update(partnerId, {
|
|
consolidationPartnerId: null,
|
|
status: "PENDING_CONSOLIDATION",
|
|
} as never);
|
|
}
|
|
}
|