import { AggregateRoot, ValidationException } from '@modules/shared'; import { LeadCreatedEvent } from '../events/lead-created.event'; import { LeadStatusChangedEvent } from '../events/lead-status-changed.event'; import { type LeadScore } from '../value-objects/lead-score.vo'; export type LeadStatus = 'NEW' | 'CONTACTED' | 'QUALIFIED' | 'NEGOTIATING' | 'CONVERTED' | 'LOST'; const VALID_TRANSITIONS: Record = { NEW: ['CONTACTED', 'LOST'], CONTACTED: ['QUALIFIED', 'LOST'], QUALIFIED: ['NEGOTIATING', 'LOST'], NEGOTIATING: ['CONVERTED', 'LOST'], CONVERTED: [], LOST: [], }; export interface LeadProps { agentId: string; name: string; phone: string; email: string | null; source: string; score: LeadScore | null; notes: unknown; status: LeadStatus; } export class LeadEntity extends AggregateRoot { private _agentId: string; private _name: string; private _phone: string; private _email: string | null; private _source: string; private _score: LeadScore | null; private _notes: unknown; private _status: LeadStatus; constructor(id: string, props: LeadProps, createdAt?: Date, updatedAt?: Date) { super(id, createdAt); if (updatedAt) this.updatedAt = updatedAt; this._agentId = props.agentId; this._name = props.name; this._phone = props.phone; this._email = props.email; this._source = props.source; this._score = props.score; this._notes = props.notes; this._status = props.status; } get agentId(): string { return this._agentId; } get name(): string { return this._name; } get phone(): string { return this._phone; } get email(): string | null { return this._email; } get source(): string { return this._source; } get score(): LeadScore | null { return this._score; } get notes(): unknown { return this._notes; } get status(): LeadStatus { return this._status; } static createNew( id: string, agentId: string, name: string, phone: string, email: string | null, source: string, score: LeadScore | null, notes: unknown, ): LeadEntity { const lead = new LeadEntity(id, { agentId, name, phone, email, source, score, notes, status: 'NEW', }); lead.addDomainEvent(new LeadCreatedEvent(id, agentId)); return lead; } updateStatus(newStatus: LeadStatus): void { const allowed = VALID_TRANSITIONS[this._status]; if (!allowed.includes(newStatus)) { throw new ValidationException( `Không thể chuyển trạng thái từ ${this._status} sang ${newStatus}`, ); } const oldStatus = this._status; this._status = newStatus; this.updatedAt = new Date(); this.addDomainEvent( new LeadStatusChangedEvent(this.id, this._agentId, oldStatus, newStatus), ); } }