use chrono::NaiveDate;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct RulesetId(pub String);
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct RulesetVersion(pub String);
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct EffectiveDateBound {
pub from: NaiveDate,
pub until: Option<NaiveDate>,
}
impl EffectiveDateBound {
pub fn open(from: NaiveDate) -> Self {
Self { from, until: None }
}
pub fn is_active_on(&self, date: NaiveDate) -> bool {
date >= self.from && self.until.is_none_or(|u| date <= u)
}
pub fn ensure_active_on(
&self,
id: &RulesetId,
date: NaiveDate,
) -> Result<(), crate::error::CalcError> {
if date < self.from {
return Err(crate::error::CalcError::RulesetNotYetEffective {
id: id.0.clone(),
from: self.from.to_string(),
});
}
if let Some(until) = self.until
&& date > until
{
return Err(crate::error::CalcError::RulesetExpired {
id: id.0.clone(),
until: until.to_string(),
});
}
Ok(())
}
}
#[derive(Debug, Clone, Serialize)]
pub struct RegulatoryBasis {
pub regulation: &'static str,
pub article: &'static str,
pub standard: Option<&'static str>,
pub technical_study: Option<&'static str>,
pub source_url: Option<&'static str>,
pub superseded_by: Option<&'static str>,
}
pub trait Ruleset {
fn id(&self) -> &RulesetId;
fn version(&self) -> &RulesetVersion;
fn effective_dates(&self) -> &EffectiveDateBound;
fn regulatory_basis(&self) -> &RegulatoryBasis;
}