xpeditis2.0/apps/backend/src/domain/value-objects/volume.vo.ts
2025-10-24 16:01:09 +02:00

55 lines
1.7 KiB
TypeScript

/**
* Volume Value Object
* Represents shipping volume in CBM (Cubic Meters) and weight in KG
*
* Business Rule: Price is calculated using freight class rule:
* - Take the higher of: (volumeCBM * pricePerCBM) or (weightKG * pricePerKG)
*/
export class Volume {
constructor(
public readonly cbm: number,
public readonly weightKG: number,
) {
this.validate();
}
private validate(): void {
if (this.cbm < 0) {
throw new Error('Volume in CBM cannot be negative');
}
if (this.weightKG < 0) {
throw new Error('Weight in KG cannot be negative');
}
if (this.cbm === 0 && this.weightKG === 0) {
throw new Error('Either volume or weight must be greater than zero');
}
}
/**
* Check if this volume is within the specified range
*/
isWithinRange(minCBM: number, maxCBM: number, minKG: number, maxKG: number): boolean {
const cbmInRange = this.cbm >= minCBM && this.cbm <= maxCBM;
const weightInRange = this.weightKG >= minKG && this.weightKG <= maxKG;
return cbmInRange && weightInRange;
}
/**
* Calculate freight price using the freight class rule
* Returns the higher value between volume-based and weight-based pricing
*/
calculateFreightPrice(pricePerCBM: number, pricePerKG: number): number {
const volumePrice = this.cbm * pricePerCBM;
const weightPrice = this.weightKG * pricePerKG;
return Math.max(volumePrice, weightPrice);
}
equals(other: Volume): boolean {
return this.cbm === other.cbm && this.weightKG === other.weightKG;
}
toString(): string {
return `${this.cbm} CBM / ${this.weightKG} KG`;
}
}