183 lines
4.0 KiB
TypeScript
183 lines
4.0 KiB
TypeScript
/**
|
|
* Carrier Entity
|
|
*
|
|
* Represents a shipping carrier (e.g., Maersk, MSC, CMA CGM)
|
|
*
|
|
* Business Rules:
|
|
* - Carrier code must be unique
|
|
* - SCAC code must be valid (4 uppercase letters)
|
|
* - API configuration is optional (for carriers with API integration)
|
|
*/
|
|
|
|
export interface CarrierApiConfig {
|
|
baseUrl: string;
|
|
apiKey?: string;
|
|
clientId?: string;
|
|
clientSecret?: string;
|
|
timeout: number; // in milliseconds
|
|
retryAttempts: number;
|
|
circuitBreakerThreshold: number;
|
|
}
|
|
|
|
export interface CarrierProps {
|
|
id: string;
|
|
name: string;
|
|
code: string; // Unique carrier code (e.g., 'MAERSK', 'MSC')
|
|
scac: string; // Standard Carrier Alpha Code
|
|
logoUrl?: string;
|
|
website?: string;
|
|
apiConfig?: CarrierApiConfig;
|
|
isActive: boolean;
|
|
supportsApi: boolean; // True if carrier has API integration
|
|
createdAt: Date;
|
|
updatedAt: Date;
|
|
}
|
|
|
|
export class Carrier {
|
|
private readonly props: CarrierProps;
|
|
|
|
private constructor(props: CarrierProps) {
|
|
this.props = props;
|
|
}
|
|
|
|
/**
|
|
* Factory method to create a new Carrier
|
|
*/
|
|
static create(props: Omit<CarrierProps, 'createdAt' | 'updatedAt'>): Carrier {
|
|
const now = new Date();
|
|
|
|
// Validate SCAC code
|
|
if (!Carrier.isValidSCAC(props.scac)) {
|
|
throw new Error('Invalid SCAC code format. Must be 4 uppercase letters.');
|
|
}
|
|
|
|
// Validate carrier code
|
|
if (!Carrier.isValidCarrierCode(props.code)) {
|
|
throw new Error('Invalid carrier code format. Must be uppercase letters and underscores only.');
|
|
}
|
|
|
|
// Validate API config if carrier supports API
|
|
if (props.supportsApi && !props.apiConfig) {
|
|
throw new Error('Carriers with API support must have API configuration.');
|
|
}
|
|
|
|
return new Carrier({
|
|
...props,
|
|
createdAt: now,
|
|
updatedAt: now,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Factory method to reconstitute from persistence
|
|
*/
|
|
static fromPersistence(props: CarrierProps): Carrier {
|
|
return new Carrier(props);
|
|
}
|
|
|
|
/**
|
|
* Validate SCAC code format
|
|
*/
|
|
private static isValidSCAC(scac: string): boolean {
|
|
const scacPattern = /^[A-Z]{4}$/;
|
|
return scacPattern.test(scac);
|
|
}
|
|
|
|
/**
|
|
* Validate carrier code format
|
|
*/
|
|
private static isValidCarrierCode(code: string): boolean {
|
|
const codePattern = /^[A-Z_]+$/;
|
|
return codePattern.test(code);
|
|
}
|
|
|
|
// Getters
|
|
get id(): string {
|
|
return this.props.id;
|
|
}
|
|
|
|
get name(): string {
|
|
return this.props.name;
|
|
}
|
|
|
|
get code(): string {
|
|
return this.props.code;
|
|
}
|
|
|
|
get scac(): string {
|
|
return this.props.scac;
|
|
}
|
|
|
|
get logoUrl(): string | undefined {
|
|
return this.props.logoUrl;
|
|
}
|
|
|
|
get website(): string | undefined {
|
|
return this.props.website;
|
|
}
|
|
|
|
get apiConfig(): CarrierApiConfig | undefined {
|
|
return this.props.apiConfig ? { ...this.props.apiConfig } : undefined;
|
|
}
|
|
|
|
get isActive(): boolean {
|
|
return this.props.isActive;
|
|
}
|
|
|
|
get supportsApi(): boolean {
|
|
return this.props.supportsApi;
|
|
}
|
|
|
|
get createdAt(): Date {
|
|
return this.props.createdAt;
|
|
}
|
|
|
|
get updatedAt(): Date {
|
|
return this.props.updatedAt;
|
|
}
|
|
|
|
// Business methods
|
|
hasApiIntegration(): boolean {
|
|
return this.props.supportsApi && !!this.props.apiConfig;
|
|
}
|
|
|
|
updateApiConfig(apiConfig: CarrierApiConfig): void {
|
|
if (!this.props.supportsApi) {
|
|
throw new Error('Cannot update API config for carrier without API support.');
|
|
}
|
|
|
|
this.props.apiConfig = { ...apiConfig };
|
|
this.props.updatedAt = new Date();
|
|
}
|
|
|
|
updateLogoUrl(logoUrl: string): void {
|
|
this.props.logoUrl = logoUrl;
|
|
this.props.updatedAt = new Date();
|
|
}
|
|
|
|
updateWebsite(website: string): void {
|
|
this.props.website = website;
|
|
this.props.updatedAt = new Date();
|
|
}
|
|
|
|
deactivate(): void {
|
|
this.props.isActive = false;
|
|
this.props.updatedAt = new Date();
|
|
}
|
|
|
|
activate(): void {
|
|
this.props.isActive = true;
|
|
this.props.updatedAt = new Date();
|
|
}
|
|
|
|
/**
|
|
* Convert to plain object for persistence
|
|
*/
|
|
toObject(): CarrierProps {
|
|
return {
|
|
...this.props,
|
|
apiConfig: this.props.apiConfig ? { ...this.props.apiConfig } : undefined,
|
|
};
|
|
}
|
|
}
|