made-core 0.8.0

Domain core of MADE: entities, value objects, events, ports. No IO.
Documentation
use crate::entities::ceremony_commands::StartStep;
use crate::entities::CeremonyInstance;
use crate::error::DomainError;
use crate::value_objects::{
    BudgetOperationId, BudgetReservationId, ExecutionOperationId, StepExecutionRecord, StepId,
};

impl CeremonyInstance {
    pub(super) fn require_budget_reservation(
        &self,
        step_id: &StepId,
        record: &StepExecutionRecord,
        command: &StartStep,
    ) -> Result<(), DomainError> {
        match (&self.budget_account_id, &command.budget_reservation_id) {
            (None, None) => Ok(()),
            (Some(account), Some(reservation)) => {
                let operation = ExecutionOperationId::for_step(
                    self.id(),
                    step_id,
                    self.current_state_visit,
                    self.current_state_iteration,
                    record.iteration(),
                );
                let budget_operation = BudgetOperationId::for_execution(&operation);
                let expected = BudgetReservationId::for_operation(account, &budget_operation);
                if reservation == &expected {
                    Ok(())
                } else {
                    Err(DomainError::InvariantViolated {
                        reason:
                            "step claim budget reservation does not match its execution identity",
                    })
                }
            }
            (Some(_), None) => Err(DomainError::InvariantViolated {
                reason: "budgeted ceremony steps require an admitted reservation",
            }),
            (None, Some(_)) => Err(DomainError::InvariantViolated {
                reason: "unbudgeted ceremony steps cannot name a budget reservation",
            }),
        }
    }
}