111 lines
2.5 KiB
TypeScript
111 lines
2.5 KiB
TypeScript
/**
|
|
* BookingStatus Value Object
|
|
*
|
|
* Represents the current status of a booking
|
|
*/
|
|
|
|
import { InvalidBookingStatusException } from '../exceptions/invalid-booking-status.exception';
|
|
|
|
export type BookingStatusValue =
|
|
| 'draft'
|
|
| 'pending_confirmation'
|
|
| 'confirmed'
|
|
| 'in_transit'
|
|
| 'delivered'
|
|
| 'cancelled';
|
|
|
|
export class BookingStatus {
|
|
private static readonly VALID_STATUSES: BookingStatusValue[] = [
|
|
'draft',
|
|
'pending_confirmation',
|
|
'confirmed',
|
|
'in_transit',
|
|
'delivered',
|
|
'cancelled',
|
|
];
|
|
|
|
private static readonly STATUS_TRANSITIONS: Record<BookingStatusValue, BookingStatusValue[]> = {
|
|
draft: ['pending_confirmation', 'cancelled'],
|
|
pending_confirmation: ['confirmed', 'cancelled'],
|
|
confirmed: ['in_transit', 'cancelled'],
|
|
in_transit: ['delivered', 'cancelled'],
|
|
delivered: [],
|
|
cancelled: [],
|
|
};
|
|
|
|
private readonly _value: BookingStatusValue;
|
|
|
|
private constructor(value: BookingStatusValue) {
|
|
this._value = value;
|
|
}
|
|
|
|
get value(): BookingStatusValue {
|
|
return this._value;
|
|
}
|
|
|
|
/**
|
|
* Create BookingStatus from string
|
|
*/
|
|
static create(value: string): BookingStatus {
|
|
if (!BookingStatus.isValid(value)) {
|
|
throw new InvalidBookingStatusException(value);
|
|
}
|
|
return new BookingStatus(value as BookingStatusValue);
|
|
}
|
|
|
|
/**
|
|
* Validate status value
|
|
*/
|
|
static isValid(value: string): boolean {
|
|
return BookingStatus.VALID_STATUSES.includes(value as BookingStatusValue);
|
|
}
|
|
|
|
/**
|
|
* Check if transition to another status is allowed
|
|
*/
|
|
canTransitionTo(newStatus: BookingStatus): boolean {
|
|
const allowedTransitions = BookingStatus.STATUS_TRANSITIONS[this._value];
|
|
return allowedTransitions.includes(newStatus._value);
|
|
}
|
|
|
|
/**
|
|
* Transition to new status
|
|
*/
|
|
transitionTo(newStatus: BookingStatus): BookingStatus {
|
|
if (!this.canTransitionTo(newStatus)) {
|
|
throw new Error(
|
|
`Invalid status transition from ${this._value} to ${newStatus._value}`
|
|
);
|
|
}
|
|
return newStatus;
|
|
}
|
|
|
|
/**
|
|
* Check if booking is in a final state
|
|
*/
|
|
isFinal(): boolean {
|
|
return this._value === 'delivered' || this._value === 'cancelled';
|
|
}
|
|
|
|
/**
|
|
* Check if booking can be modified
|
|
*/
|
|
canBeModified(): boolean {
|
|
return this._value === 'draft' || this._value === 'pending_confirmation';
|
|
}
|
|
|
|
/**
|
|
* Equality check
|
|
*/
|
|
equals(other: BookingStatus): boolean {
|
|
return this._value === other._value;
|
|
}
|
|
|
|
/**
|
|
* String representation
|
|
*/
|
|
toString(): string {
|
|
return this._value;
|
|
}
|
|
}
|