defmodule CustomerService.Aggregates.QuickLead do defstruct [ :id, :name, :email, :phone, :company_name, :status, :priority, :source, :notes, :assigned_to, :estimated_value, :expected_close_date, :status_history ] alias __MODULE__ alias Commanded.Aggregates.Aggregate alias CustomerService.Commands alias CustomerService.Events @behaviour Aggregate @valid_statuses ~w(new contacted qualified proposal negotiation converted lost)a @impl Aggregate def execute(%QuickLead{id: nil}, %Commands.CreateQuickLead{} = cmd) do status = cmd.status || :new priority = cmd.priority || :medium source = cmd.source || :other %Events.QuickLeadCreated{ id: cmd.id, name: cmd.name, email: cmd.email, phone: cmd.phone, company_name: cmd.company_name, status: status, priority: priority, source: source, notes: cmd.notes, assigned_to: cmd.assigned_to, estimated_value: cmd.estimated_value, expected_close_date: cmd.expected_close_date } end @impl Aggregate def execute(%QuickLead{id: _id}, %Commands.UpdateQuickLead{} = cmd) do %Events.QuickLeadUpdated{ id: cmd.id, name: cmd.name, email: cmd.email, phone: cmd.phone, company_name: cmd.company_name, notes: cmd.notes, assigned_to: cmd.assigned_to, estimated_value: cmd.estimated_value, expected_close_date: cmd.expected_close_date } end @impl Aggregate def execute(%QuickLead{id: _id, status: current_status}, %Commands.UpdateLeadStatus{} = cmd) do new_status = cmd.status if valid_status_transition?(current_status, new_status) do %Events.LeadStatusUpdated{ id: cmd.id, status: new_status, previous_status: current_status, updated_at: DateTime.utc_now() } else {:error, :invalid_status_transition} end end @impl Aggregate def apply(%QuickLead{id: nil}, %Events.QuickLeadCreated{} = e) do %__MODULE__{ id: e.id, name: e.name, email: e.email, phone: e.phone, company_name: e.company_name, status: e.status, priority: e.priority, source: e.source, notes: e.notes, assigned_to: e.assigned_to, estimated_value: e.estimated_value, expected_close_date: e.expected_close_date, status_history: [ %{ status: e.status, updated_at: DateTime.utc_now(), notes: "Lead created" } ] } end @impl Aggregate def apply(%QuickLead{} = lead, %Events.QuickLeadUpdated{} = e) do %__MODULE__{ lead | name: e.name || lead.name, email: e.email || lead.email, phone: e.phone || lead.phone, company_name: e.company_name || lead.company_name, notes: e.notes || lead.notes, assigned_to: e.assigned_to || lead.assigned_to, estimated_value: e.estimated_value || lead.estimated_value, expected_close_date: e.expected_close_date || lead.expected_close_date } end @impl Aggregate def apply(%QuickLead{} = lead, %Events.LeadStatusUpdated{} = e) do %__MODULE__{ lead | status: e.status, status_history: [ %{ status: e.status, previous_status: e.previous_status, updated_at: e.updated_at } | lead.status_history ] } end defp valid_status_transition?(current_status, new_status) do current_status in @valid_statuses and new_status in @valid_statuses and current_status != new_status end end