78 lines
1.8 KiB
TypeScript
78 lines
1.8 KiB
TypeScript
/**
|
|
* BookingNumber Value Object
|
|
*
|
|
* Represents a unique booking reference number
|
|
* Format: WCM-YYYY-XXXXXX (e.g., WCM-2025-ABC123)
|
|
* - WCM: WebCargo Maritime prefix
|
|
* - YYYY: Current year
|
|
* - XXXXXX: 6 alphanumeric characters
|
|
*/
|
|
|
|
import { InvalidBookingNumberException } from '../exceptions/invalid-booking-number.exception';
|
|
|
|
export class BookingNumber {
|
|
private readonly _value: string;
|
|
|
|
private constructor(value: string) {
|
|
this._value = value;
|
|
}
|
|
|
|
get value(): string {
|
|
return this._value;
|
|
}
|
|
|
|
/**
|
|
* Generate a new booking number
|
|
*/
|
|
static generate(): BookingNumber {
|
|
const year = new Date().getFullYear();
|
|
const random = BookingNumber.generateRandomString(6);
|
|
const value = `WCM-${year}-${random}`;
|
|
return new BookingNumber(value);
|
|
}
|
|
|
|
/**
|
|
* Create BookingNumber from string
|
|
*/
|
|
static fromString(value: string): BookingNumber {
|
|
if (!BookingNumber.isValid(value)) {
|
|
throw new InvalidBookingNumberException(value);
|
|
}
|
|
return new BookingNumber(value);
|
|
}
|
|
|
|
/**
|
|
* Validate booking number format
|
|
*/
|
|
static isValid(value: string): boolean {
|
|
const pattern = /^WCM-\d{4}-[A-Z0-9]{6}$/;
|
|
return pattern.test(value);
|
|
}
|
|
|
|
/**
|
|
* Generate random alphanumeric string
|
|
*/
|
|
private static generateRandomString(length: number): string {
|
|
const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'; // Exclude ambiguous chars: 0,O,1,I
|
|
let result = '';
|
|
for (let i = 0; i < length; i++) {
|
|
result += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Equality check
|
|
*/
|
|
equals(other: BookingNumber): boolean {
|
|
return this._value === other._value;
|
|
}
|
|
|
|
/**
|
|
* String representation
|
|
*/
|
|
toString(): string {
|
|
return this._value;
|
|
}
|
|
}
|