mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-27 16:40:56 +00:00
188 lines
5.6 KiB
TypeScript
188 lines
5.6 KiB
TypeScript
import { Inject, Injectable } from "@nestjs/common";
|
|
import { In, Not } from "typeorm";
|
|
|
|
import { CargoType } from "../rule-engine/entities/cargo-type.entity";
|
|
import { ContainerType } from "../rule-engine/entities/container-type.entity";
|
|
import {
|
|
CARGO_TYPES_REPOSITORY,
|
|
ICargoTypesRepository,
|
|
} from "../rule-engine/interfaces/cargo-types.repository.interface";
|
|
import {
|
|
CONTAINER_TYPES_REPOSITORY,
|
|
IContainerTypesRepository,
|
|
} from "../rule-engine/interfaces/container-types.repository.interface";
|
|
import {
|
|
IServiceTypesRepository,
|
|
SERVICE_TYPES_REPOSITORY,
|
|
} from "../rule-engine/interfaces/service-types.repository.interface";
|
|
import {
|
|
IShippingLinesRepository,
|
|
SHIPPING_LINES_REPOSITORY,
|
|
} from "../rule-engine/interfaces/shipping-lines.repository.interface";
|
|
import {
|
|
IYardsRepository,
|
|
YARDS_REPOSITORY,
|
|
} from "../rule-engine/interfaces/yards.repository.interface";
|
|
import {
|
|
BookingReferenceCargoTypeChildDto,
|
|
BookingReferenceCargoTypeGroupDto,
|
|
BookingReferenceContainerSizeGroupDto,
|
|
BookingReferenceContainerTypeDto,
|
|
BookingReferenceDataDto,
|
|
BookingReferenceServiceDto,
|
|
BookingReferenceShippingLineDto,
|
|
BookingReferenceYardDto,
|
|
} from "./dto/booking-reference-data.dto";
|
|
|
|
const LEGACY_YARD_CODES = ["LEGACY_ORIGIN", "LEGACY_DEST"] as const;
|
|
|
|
export function buildCargoTypeTree(
|
|
rows: CargoType[],
|
|
): BookingReferenceCargoTypeGroupDto[] {
|
|
const active = rows.filter((r) => r.isActive);
|
|
const parents = active
|
|
.filter((r) => !r.parentGroupId)
|
|
.sort(
|
|
(a, b) => a.displayOrder - b.displayOrder || a.code.localeCompare(b.code),
|
|
);
|
|
|
|
return parents.map((parent) => {
|
|
const children = active
|
|
.filter((r) => r.parentGroupId === parent.id)
|
|
.sort(
|
|
(a, b) =>
|
|
a.displayOrder - b.displayOrder || a.code.localeCompare(b.code),
|
|
)
|
|
.map(
|
|
(child): BookingReferenceCargoTypeChildDto => ({
|
|
id: child.id,
|
|
name: child.cargoTypeName,
|
|
code: child.code,
|
|
unit_of_measure: child.unitOfMeasure ?? null,
|
|
}),
|
|
);
|
|
|
|
const group: BookingReferenceCargoTypeGroupDto = {
|
|
id: parent.id,
|
|
name: parent.cargoTypeName,
|
|
code: parent.code,
|
|
};
|
|
if (children.length > 0) {
|
|
group.children = children;
|
|
}
|
|
return group;
|
|
});
|
|
}
|
|
|
|
export function groupContainersBySize(
|
|
rows: ContainerType[],
|
|
): BookingReferenceContainerSizeGroupDto[] {
|
|
const active = rows.filter((r) => r.isActive);
|
|
const bySize = new Map<string, ContainerType[]>();
|
|
|
|
for (const ct of active) {
|
|
const sizeKey =
|
|
ct.sizeFt != null && ct.sizeFt > 0 ? `${ct.sizeFt}ft` : "other";
|
|
const list = bySize.get(sizeKey) ?? [];
|
|
list.push(ct);
|
|
bySize.set(sizeKey, list);
|
|
}
|
|
|
|
const sortSizeKey = (key: string): number => {
|
|
if (key === "other") return Number.MAX_SAFE_INTEGER;
|
|
const n = parseInt(key, 10);
|
|
return Number.isNaN(n) ? Number.MAX_SAFE_INTEGER - 1 : n;
|
|
};
|
|
|
|
return [...bySize.entries()]
|
|
.sort(([a], [b]) => sortSizeKey(a) - sortSizeKey(b))
|
|
.map(([size, types]) => ({
|
|
size,
|
|
types: types
|
|
.sort(
|
|
(a, b) =>
|
|
(a.displayOrder ?? 0) - (b.displayOrder ?? 0) ||
|
|
a.code.localeCompare(b.code),
|
|
)
|
|
.map(
|
|
(ct): BookingReferenceContainerTypeDto => ({
|
|
id: ct.id,
|
|
name: ct.label?.trim() ? ct.label : ct.code,
|
|
code: ct.code,
|
|
is_reefer: ct.isReefer ?? false,
|
|
}),
|
|
),
|
|
}));
|
|
}
|
|
|
|
@Injectable()
|
|
export class BookingReferenceDataService {
|
|
constructor(
|
|
@Inject(YARDS_REPOSITORY)
|
|
private readonly yardsRepository: IYardsRepository,
|
|
@Inject(CONTAINER_TYPES_REPOSITORY)
|
|
private readonly containerTypesRepository: IContainerTypesRepository,
|
|
@Inject(SERVICE_TYPES_REPOSITORY)
|
|
private readonly serviceTypesRepository: IServiceTypesRepository,
|
|
@Inject(SHIPPING_LINES_REPOSITORY)
|
|
private readonly shippingLinesRepository: IShippingLinesRepository,
|
|
@Inject(CARGO_TYPES_REPOSITORY)
|
|
private readonly cargoTypesRepository: ICargoTypesRepository,
|
|
) { }
|
|
|
|
async getReferenceData(): Promise<BookingReferenceDataDto> {
|
|
const [yards, containerTypes, serviceTypes, shippingLines, cargoTypes] =
|
|
await Promise.all([
|
|
this.yardsRepository.findAll({
|
|
where: {
|
|
isActive: true,
|
|
code: Not(In([...LEGACY_YARD_CODES])),
|
|
},
|
|
order: { displayOrder: "ASC", code: "ASC" },
|
|
}),
|
|
this.containerTypesRepository.findAll({
|
|
where: { isActive: true },
|
|
order: { displayOrder: "ASC", code: "ASC" },
|
|
}),
|
|
this.serviceTypesRepository.findAll({
|
|
where: { isActive: true },
|
|
order: { displayOrder: "ASC", code: "ASC" },
|
|
}),
|
|
this.shippingLinesRepository.findAll({
|
|
where: { isActive: true },
|
|
order: { label: "ASC", code: "ASC" },
|
|
}),
|
|
this.cargoTypesRepository.findAll({
|
|
where: { isActive: true },
|
|
order: { displayOrder: "ASC", code: "ASC" },
|
|
}),
|
|
]);
|
|
|
|
return {
|
|
yard: yards.map(
|
|
(y): BookingReferenceYardDto => ({
|
|
id: y.id,
|
|
name: y.label,
|
|
code: y.code,
|
|
country: y.country,
|
|
}),
|
|
),
|
|
containers: groupContainersBySize(containerTypes),
|
|
service: serviceTypes.map(
|
|
(s): BookingReferenceServiceDto => ({
|
|
name: s.serviceName,
|
|
...s,
|
|
}),
|
|
),
|
|
shipping_line: shippingLines.map(
|
|
(sl): BookingReferenceShippingLineDto => ({
|
|
id: sl.id,
|
|
name: sl.label,
|
|
code: sl.code,
|
|
}),
|
|
),
|
|
cargo_type: buildCargoTypeTree(cargoTypes),
|
|
};
|
|
}
|
|
}
|