Skip to main content

made_core/value_objects/ceremony/
succession_plan.rs

1use serde::{Deserialize, Serialize};
2use time::OffsetDateTime;
3
4use super::{
5    BudgetDisposition, CarriedEvidence, CeremonyId, ClaimDisposition, DefinitionPin,
6    IdempotencyKey, StepId,
7};
8use crate::value_objects::AuditActorId;
9
10/// The whole of a handoff, sealed in the predecessor before anything
11/// is opened.
12///
13/// It carries plan identity, the successor's derived id, the
14/// definition the successor runs, what the successor starts with, what
15/// happens to every outstanding claim and what the successor does
16/// about the ledger. One fact rather than several, because a partial
17/// handoff — a successor named with no dispositions, dispositions with
18/// no successor — is not a state this engine should be able to be in.
19#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
20pub struct SuccessionPlan {
21    plan_id: IdempotencyKey,
22    successor_id: CeremonyId,
23    successor_definition: DefinitionPin,
24    carried: Vec<CarriedEvidence>,
25    dispositions: Vec<ClaimDisposition>,
26    budget: BudgetDisposition,
27    planned_by: AuditActorId,
28    #[serde(with = "time::serde::rfc3339")]
29    planned_at: OffsetDateTime,
30}
31
32impl SuccessionPlan {
33    #[must_use]
34    pub const fn new(
35        plan_id: IdempotencyKey,
36        successor_id: CeremonyId,
37        successor_definition: DefinitionPin,
38        carried: Vec<CarriedEvidence>,
39        dispositions: Vec<ClaimDisposition>,
40        budget: BudgetDisposition,
41        planned_by: AuditActorId,
42        planned_at: OffsetDateTime,
43    ) -> Self {
44        Self {
45            plan_id,
46            successor_id,
47            successor_definition,
48            carried,
49            dispositions,
50            budget,
51            planned_by,
52            planned_at,
53        }
54    }
55
56    #[must_use]
57    pub const fn plan_id(&self) -> &IdempotencyKey {
58        &self.plan_id
59    }
60
61    #[must_use]
62    pub const fn successor_id(&self) -> &CeremonyId {
63        &self.successor_id
64    }
65
66    #[must_use]
67    pub const fn successor_definition(&self) -> &DefinitionPin {
68        &self.successor_definition
69    }
70
71    #[must_use]
72    pub fn carried(&self) -> &[CarriedEvidence] {
73        &self.carried
74    }
75
76    #[must_use]
77    pub fn dispositions(&self) -> &[ClaimDisposition] {
78        &self.dispositions
79    }
80
81    #[must_use]
82    pub const fn budget(&self) -> BudgetDisposition {
83        self.budget
84    }
85
86    #[must_use]
87    pub const fn planned_by(&self) -> &AuditActorId {
88        &self.planned_by
89    }
90
91    #[must_use]
92    pub const fn planned_at(&self) -> OffsetDateTime {
93        self.planned_at
94    }
95
96    /// The disposition this plan holds for one step, if it holds one.
97    #[must_use]
98    pub fn disposition_for(&self, step_id: &StepId) -> Option<&ClaimDisposition> {
99        self.dispositions
100            .iter()
101            .find(|disposition| disposition.step_id() == step_id)
102    }
103}