use crate::infra::serde_support::{RawEvent, RawEventAction};
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) enum EnrichWarning {
StatusJournalMismatch {
frontmatter: String,
terminal: String,
},
}
pub(crate) fn enrich_event_action(
raw: RawEventAction,
) -> Option<crate::domain::model::event::EventAction> {
use crate::domain::model::event::{EventAction, State};
match raw {
RawEventAction::Created { status } => {
let state = State::new(&status).unwrap_or_else(|_| State::unknown());
Some(EventAction::Created { state })
}
RawEventAction::StatusChanged { from, to } => {
let from_state = State::new(&from).unwrap_or_else(|_| State::unknown());
let to_state = State::new(&to).unwrap_or_else(|_| State::unknown());
Some(EventAction::StatusChanged {
from: from_state,
to: to_state,
})
}
RawEventAction::Other(_) => None,
}
}
pub(crate) fn enrich_record(
status: &mut crate::domain::model::status::Status,
events: &mut crate::domain::model::event::EventLog,
raw_events: Vec<RawEvent>,
statuses: &crate::domain::model::status::StatusesConfig,
) -> Vec<EnrichWarning> {
let fm_status_name = status.name.clone();
if let Ok(s) = statuses.resolve(&fm_status_name) {
*status = s;
}
for raw in raw_events {
if let Some(action) = enrich_event_action(raw.action) {
events.push(crate::domain::model::event::Event {
timestamp: raw.timestamp,
action,
});
}
}
if let Some(latest) = events.latest_state() {
*status = statuses
.resolve(latest.as_str())
.unwrap_or_else(|_| crate::domain::model::status::Status::unresolved(latest.as_str()));
}
let mut warnings = Vec::new();
if status.as_str() != fm_status_name {
warnings.push(EnrichWarning::StatusJournalMismatch {
frontmatter: fm_status_name,
terminal: status.as_str().to_string(),
});
}
warnings
}
pub(crate) fn enrich_dr_record(
status: &mut crate::domain::model::decision_record::DrStatus,
events: &mut crate::domain::model::event::EventLog,
raw_events: Vec<RawEvent>,
) -> Vec<EnrichWarning> {
use std::str::FromStr;
let fm_status = *status;
for raw in raw_events {
if let Some(action) = enrich_event_action(raw.action) {
events.push(crate::domain::model::event::Event {
timestamp: raw.timestamp,
action,
});
}
}
if let Some(latest) = events.latest_state() {
if let Ok(projected) =
crate::domain::model::decision_record::DrStatus::from_str(latest.as_str())
{
*status = projected;
}
}
let mut warnings = Vec::new();
if *status != fm_status {
warnings.push(EnrichWarning::StatusJournalMismatch {
frontmatter: fm_status.to_string(),
terminal: status.to_string(),
});
}
warnings
}