use chrono::NaiveDate;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ServiceOrganization {
pub id: String,
pub name: String,
pub service_type: ServiceType,
pub entities_served: Vec<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
#[serde(rename_all = "snake_case")]
pub enum ServiceType {
#[default]
PayrollProcessor,
CloudHosting,
PaymentProcessor,
ItManagedServices,
DataCentre,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SocReport {
pub id: String,
pub service_org_id: String,
pub report_type: SocReportType,
pub report_period_start: NaiveDate,
pub report_period_end: NaiveDate,
pub opinion_type: SocOpinionType,
pub control_objectives: Vec<ControlObjective>,
pub exceptions_noted: Vec<SocException>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
#[serde(rename_all = "snake_case")]
pub enum SocReportType {
Soc1Type1,
#[default]
Soc1Type2,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
#[serde(rename_all = "snake_case")]
pub enum SocOpinionType {
#[default]
Unmodified,
Qualified,
Adverse,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ControlObjective {
pub id: String,
pub description: String,
pub controls_tested: u32,
pub controls_effective: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SocException {
pub control_objective_id: String,
pub description: String,
pub management_response: String,
pub user_entity_impact: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserEntityControl {
pub id: String,
pub soc_report_id: String,
pub description: String,
pub mapped_objective: String,
pub implemented: bool,
pub operating_effectiveness: ControlEffectiveness,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
#[serde(rename_all = "snake_case")]
pub enum ControlEffectiveness {
#[default]
Effective,
EffectiveWithExceptions,
Ineffective,
NotTested,
}
impl ServiceOrganization {
pub fn new(
name: impl Into<String>,
service_type: ServiceType,
entities_served: Vec<String>,
) -> Self {
Self {
id: Uuid::new_v4().to_string(),
name: name.into(),
service_type,
entities_served,
}
}
}
impl SocReport {
pub fn new(
service_org_id: impl Into<String>,
report_type: SocReportType,
report_period_start: NaiveDate,
report_period_end: NaiveDate,
opinion_type: SocOpinionType,
) -> Self {
Self {
id: Uuid::new_v4().to_string(),
service_org_id: service_org_id.into(),
report_type,
report_period_start,
report_period_end,
opinion_type,
control_objectives: Vec::new(),
exceptions_noted: Vec::new(),
}
}
}
impl ControlObjective {
pub fn new(
description: impl Into<String>,
controls_tested: u32,
controls_effective: bool,
) -> Self {
Self {
id: Uuid::new_v4().to_string(),
description: description.into(),
controls_tested,
controls_effective,
}
}
}
impl UserEntityControl {
pub fn new(
soc_report_id: impl Into<String>,
description: impl Into<String>,
mapped_objective: impl Into<String>,
implemented: bool,
operating_effectiveness: ControlEffectiveness,
) -> Self {
Self {
id: Uuid::new_v4().to_string(),
soc_report_id: soc_report_id.into(),
description: description.into(),
mapped_objective: mapped_objective.into(),
implemented,
operating_effectiveness,
}
}
}