import { Money } from './money.vo'; /** * Surcharge Type Enumeration * Common maritime shipping surcharges */ export enum SurchargeType { BAF = 'BAF', // Bunker Adjustment Factor CAF = 'CAF', // Currency Adjustment Factor PSS = 'PSS', // Peak Season Surcharge THC = 'THC', // Terminal Handling Charge OTHER = 'OTHER', } /** * Surcharge Value Object * Represents additional fees applied to base freight rates */ export class Surcharge { constructor( public readonly type: SurchargeType, public readonly amount: Money, public readonly description?: string ) { this.validate(); } private validate(): void { if (!Object.values(SurchargeType).includes(this.type)) { throw new Error(`Invalid surcharge type: ${this.type}`); } } /** * Get human-readable surcharge label */ getLabel(): string { const labels: Record = { [SurchargeType.BAF]: 'Bunker Adjustment Factor', [SurchargeType.CAF]: 'Currency Adjustment Factor', [SurchargeType.PSS]: 'Peak Season Surcharge', [SurchargeType.THC]: 'Terminal Handling Charge', [SurchargeType.OTHER]: 'Other Surcharge', }; return labels[this.type]; } equals(other: Surcharge): boolean { return this.type === other.type && this.amount.isEqualTo(other.amount); } toString(): string { const label = this.description || this.getLabel(); return `${label}: ${this.amount.toString()}`; } } /** * Collection of surcharges with utility methods */ export class SurchargeCollection { constructor(public readonly surcharges: Surcharge[]) {} /** * Calculate total surcharge amount in a specific currency * Note: This assumes all surcharges are in the same currency * In production, currency conversion would be needed */ getTotalAmount(currency: string): Money { const relevantSurcharges = this.surcharges.filter(s => s.amount.getCurrency() === currency); if (relevantSurcharges.length === 0) { return Money.zero(currency); } return relevantSurcharges.reduce( (total, surcharge) => total.add(surcharge.amount), Money.zero(currency) ); } /** * Check if collection has any surcharges */ isEmpty(): boolean { return this.surcharges.length === 0; } /** * Get surcharges by type */ getByType(type: SurchargeType): Surcharge[] { return this.surcharges.filter(s => s.type === type); } /** * Get formatted surcharge details for display */ getDetails(): string { if (this.isEmpty()) { return 'All-in price (no separate surcharges)'; } return this.surcharges.map(s => s.toString()).join(', '); } }