made_core/entities/ceremony_instance/
transitions.rs1use super::{
2 CeremonyDefinition, CeremonyInstance, CeremonyTransitionRecord, DomainError, OffsetDateTime,
3 RoleAction, RoleId, StateId, TransitionTrigger,
4};
5
6impl CeremonyInstance {
7 pub fn apply_transition_as(
8 &mut self,
9 definition: &CeremonyDefinition,
10 role_id: &RoleId,
11 trigger: &TransitionTrigger,
12 now: OffsetDateTime,
13 ) -> Result<StateId, DomainError> {
14 self.require_role(
15 definition,
16 role_id,
17 &RoleAction::transition(trigger.clone()),
18 )?;
19 self.move_on(definition, trigger, Some(role_id.clone()), now)
20 }
21
22 pub fn apply_transition(
23 &mut self,
24 definition: &CeremonyDefinition,
25 trigger: &TransitionTrigger,
26 now: OffsetDateTime,
27 ) -> Result<StateId, DomainError> {
28 self.move_on(definition, trigger, None, now)
29 }
30
31 fn move_on(
36 &mut self,
37 definition: &CeremonyDefinition,
38 trigger: &TransitionTrigger,
39 applied_by: Option<RoleId>,
40 now: OffsetDateTime,
41 ) -> Result<StateId, DomainError> {
42 self.require_definition(definition)?;
43 if self.is_terminal(definition) {
44 return Err(DomainError::InvariantViolated {
45 reason: "terminal ceremony instances cannot transition",
46 });
47 }
48
49 let transition = definition
50 .transition_for_trigger(&self.current_state, trigger)
51 .ok_or(DomainError::InvalidTransition {
52 from: "ceremony_instance.current_state",
53 to: "transition_trigger",
54 })?;
55 if !definition.repeat_requirements_are_satisfied(&self.current_state, &self.step_records) {
56 return Err(DomainError::InvariantViolated {
57 reason: "ceremony step repeat condition is not satisfied",
58 });
59 }
60 if !definition.guards_are_satisfied(transition, &self.step_records, &self.context) {
61 return Err(DomainError::InvariantViolated {
62 reason: "ceremony transition guards are not satisfied",
63 });
64 }
65
66 let from_state = self.current_state.clone();
67 self.current_state = transition.to().clone();
68 self.transitions.push(CeremonyTransitionRecord::record(
69 trigger.clone(),
70 from_state,
71 self.current_state.clone(),
72 applied_by,
73 now,
74 ));
75 self.updated_at = now;
76 if definition.is_terminal_state(&self.current_state) {
77 self.completed_at = Some(now);
78 }
79 Ok(self.current_state.clone())
80 }
81}