use chrono::NaiveDate;
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum OdsStatus {
Active,
Inactive,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum RecordClass {
Organisation,
Site,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum RecordUseType {
Full,
RefOnly,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum PeriodType {
Legal,
Operational,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct DatePeriod {
pub period_type: PeriodType,
pub start_date: Option<NaiveDate>,
pub end_date: Option<NaiveDate>,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct OrganizationRole {
pub unique_role_id: i64,
pub role_code: String,
pub role_name: Option<String>,
pub is_primary: bool,
pub status: OdsStatus,
pub periods: Vec<DatePeriod>,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct OrganizationRelationship {
pub unique_rel_id: i64,
pub relationship_type_code: String,
pub relationship_type_name: Option<String>,
pub status: OdsStatus,
pub target_ods_code: String,
pub target_primary_role_id: Option<String>,
pub periods: Vec<DatePeriod>,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum SuccessionType {
Predecessor,
Successor,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct OrganizationSuccession {
pub unique_succ_id: i64,
pub succession_type: SuccessionType,
pub target_ods_code: String,
pub target_primary_role_id: Option<String>,
pub legal_start_date: Option<NaiveDate>,
pub has_forward_succession: bool,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_ods_status_serialization() {
let statuses = vec![OdsStatus::Active, OdsStatus::Inactive];
for s in statuses {
let json = serde_json::to_string(&s).unwrap();
let deser: OdsStatus = serde_json::from_str(&json).unwrap();
assert_eq!(deser, s);
}
}
#[test]
fn test_record_class_serialization() {
let classes = vec![RecordClass::Organisation, RecordClass::Site];
for c in classes {
let json = serde_json::to_string(&c).unwrap();
let deser: RecordClass = serde_json::from_str(&json).unwrap();
assert_eq!(deser, c);
}
}
#[test]
fn test_period_type_serialization() {
let types = vec![PeriodType::Legal, PeriodType::Operational];
for t in types {
let json = serde_json::to_string(&t).unwrap();
let deser: PeriodType = serde_json::from_str(&json).unwrap();
assert_eq!(deser, t);
}
}
#[test]
fn test_date_period_construction() {
let period = DatePeriod {
period_type: PeriodType::Legal,
start_date: Some(chrono::NaiveDate::from_ymd_opt(2020, 1, 1).unwrap()),
end_date: None,
};
assert!(period.end_date.is_none());
assert_eq!(period.period_type, PeriodType::Legal);
}
#[test]
fn test_organization_role_construction() {
let role = OrganizationRole {
unique_role_id: 12345,
role_code: "RO197".to_string(),
role_name: Some("NHS Trust".to_string()),
is_primary: true,
status: OdsStatus::Active,
periods: vec![DatePeriod {
period_type: PeriodType::Legal,
start_date: Some(chrono::NaiveDate::from_ymd_opt(2000, 4, 1).unwrap()),
end_date: None,
}],
};
assert!(role.is_primary);
assert_eq!(role.role_code, "RO197");
}
#[test]
fn test_organization_relationship_construction() {
let rel = OrganizationRelationship {
unique_rel_id: 67890,
relationship_type_code: "RE4".to_string(),
relationship_type_name: Some("IS COMMISSIONED BY".to_string()),
status: OdsStatus::Active,
target_ods_code: "X26".to_string(),
target_primary_role_id: Some("RO209".to_string()),
periods: vec![],
};
assert_eq!(rel.relationship_type_code, "RE4");
assert_eq!(rel.target_ods_code, "X26");
}
#[test]
fn test_organization_succession_construction() {
let succ = OrganizationSuccession {
unique_succ_id: 11111,
succession_type: SuccessionType::Predecessor,
target_ods_code: "RAV".to_string(),
target_primary_role_id: Some("RO197".to_string()),
legal_start_date: Some(chrono::NaiveDate::from_ymd_opt(1993, 4, 1).unwrap()),
has_forward_succession: false,
};
assert_eq!(succ.succession_type, SuccessionType::Predecessor);
assert!(!succ.has_forward_succession);
}
#[test]
fn test_succession_type_serialization() {
let types = vec![SuccessionType::Predecessor, SuccessionType::Successor];
for t in types {
let json = serde_json::to_string(&t).unwrap();
let deser: SuccessionType = serde_json::from_str(&json).unwrap();
assert_eq!(deser, t);
}
}
#[test]
fn test_record_use_type_serialization() {
let types = vec![RecordUseType::Full, RecordUseType::RefOnly];
for t in types {
let json = serde_json::to_string(&t).unwrap();
let deser: RecordUseType = serde_json::from_str(&json).unwrap();
assert_eq!(deser, t);
}
}
}