55 lines
1.6 KiB
TypeScript
55 lines
1.6 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`;
|
|
}
|
|
}
|