mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-08 11:18:17 +00:00
feat: add contract extension request functionality
- Implemented method in to allow customers to request an extension for expired contracts. - Added component in for users to initiate extension requests. - Updated to include logic for handling extension requests for expired contracts. - Enhanced to display extension request options and status. - Created migration to add and columns to the contracts table. - Added unit tests for contract extension request and handling in . - Defined DTOs for request and extension in . - Updated types in to include new fields related to contract extensions.
This commit is contained in:
@@ -20,12 +20,17 @@ export type TrainLimitConfig = {
|
||||
maxWeightTons?: number;
|
||||
maxLengthMeters?: number;
|
||||
maxWagonsPerTrain?: number;
|
||||
max20ftContainerWeightTons?: number;
|
||||
max20ftPairWeightDiffTons?: number;
|
||||
};
|
||||
|
||||
export type ContainerPlacementRules = {
|
||||
max20ftContainerWeightTons?: number;
|
||||
/**
|
||||
* Hard per-box weight ceiling keyed by booking container LINE id, resolved
|
||||
* from the rule engine's weight limit rule (`max_capacity_tons`) for the
|
||||
* line's container type and the booking's trade direction. A line with no
|
||||
* entry has no ceiling — the rule's capacity is optional.
|
||||
*/
|
||||
maxContainerWeightTonsByLineId?: Record<string, number>;
|
||||
max20ftPairWeightDiffTons?: number;
|
||||
};
|
||||
|
||||
@@ -820,15 +825,21 @@ export function perEdgeConsistUsage(
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Per-box weight rules for a container plan:
|
||||
* - every unit is checked against its line's weight-limit-rule capacity
|
||||
* ceiling (`maxContainerWeightTonsByLineId`, any size);
|
||||
* - 20ft pairs sharing a wagon are checked for weight imbalance.
|
||||
*/
|
||||
export function validate20ftContainerRules(
|
||||
units: ContainerUnitRow[],
|
||||
placements: ContainerPlacementInput[],
|
||||
rules?: ContainerPlacementRules,
|
||||
): string[] {
|
||||
const violations: string[] = [];
|
||||
const maxEach = rules?.max20ftContainerWeightTons;
|
||||
const capacityByLine = rules?.maxContainerWeightTonsByLineId;
|
||||
const maxDiff = rules?.max20ftPairWeightDiffTons;
|
||||
if (maxEach == null && maxDiff == null) return violations;
|
||||
if (capacityByLine == null && maxDiff == null) return violations;
|
||||
|
||||
const placementByUnit = new Map(
|
||||
placements.map((p) => [`${p.bookingContainerId}:${p.unitIndex}`, p]),
|
||||
@@ -837,15 +848,16 @@ export function validate20ftContainerRules(
|
||||
const weightsBySlot = new Map<number, number[]>();
|
||||
|
||||
for (const unit of units) {
|
||||
const sizeFt = unit.sizeFt ?? (unit.containerTypeCode.includes('40') ? 40 : 20);
|
||||
if (sizeFt >= 40) continue;
|
||||
|
||||
const maxEach = capacityByLine?.[unit.bookingContainerId];
|
||||
if (maxEach != null && unit.grossWeightTons > maxEach) {
|
||||
violations.push(
|
||||
`${unit.label} weight ${unit.grossWeightTons}T exceeds max ${maxEach}T for 20ft containers`,
|
||||
`${unit.label} weight ${unit.grossWeightTons}T exceeds the weight limit rule capacity of ${maxEach}T for ${unit.containerTypeCode} containers`,
|
||||
);
|
||||
}
|
||||
|
||||
const sizeFt = unit.sizeFt ?? (unit.containerTypeCode.includes('40') ? 40 : 20);
|
||||
if (sizeFt >= 40) continue;
|
||||
|
||||
const placement = placementByUnit.get(`${unit.bookingContainerId}:${unit.unitIndex}`);
|
||||
if (!placement?.sequenceNo) continue;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user