use chrono::NaiveDate;
use rust_decimal::Decimal;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum GoingConcernIndicatorType {
RecurringOperatingLosses,
NegativeOperatingCashFlow,
WorkingCapitalDeficiency,
DebtCovenantBreach,
LossOfKeyCustomer,
RegulatoryAction,
LitigationExposure,
InabilityToObtainFinancing,
}
impl std::fmt::Display for GoingConcernIndicatorType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let s = match self {
Self::RecurringOperatingLosses => "Recurring Operating Losses",
Self::NegativeOperatingCashFlow => "Negative Operating Cash Flow",
Self::WorkingCapitalDeficiency => "Working Capital Deficiency",
Self::DebtCovenantBreach => "Debt Covenant Breach",
Self::LossOfKeyCustomer => "Loss of Key Customer",
Self::RegulatoryAction => "Regulatory Action",
Self::LitigationExposure => "Litigation Exposure",
Self::InabilityToObtainFinancing => "Inability to Obtain Financing",
};
write!(f, "{s}")
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum GoingConcernSeverity {
Low,
Medium,
High,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum GoingConcernConclusion {
#[default]
NoMaterialUncertainty,
MaterialUncertaintyExists,
GoingConcernDoubt,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GoingConcernIndicator {
pub indicator_type: GoingConcernIndicatorType,
pub severity: GoingConcernSeverity,
pub description: String,
#[serde(
with = "crate::serde_decimal::option",
skip_serializing_if = "Option::is_none",
default
)]
pub quantitative_measure: Option<Decimal>,
#[serde(
with = "crate::serde_decimal::option",
skip_serializing_if = "Option::is_none",
default
)]
pub threshold: Option<Decimal>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GoingConcernAssessment {
pub entity_code: String,
pub assessment_date: NaiveDate,
pub assessment_period: String,
pub indicators: Vec<GoingConcernIndicator>,
pub management_plans: Vec<String>,
pub auditor_conclusion: GoingConcernConclusion,
pub material_uncertainty_exists: bool,
}
impl GoingConcernAssessment {
pub fn conclude_from_indicators(mut self) -> Self {
let n = self.indicators.len();
self.auditor_conclusion = match n {
0 => GoingConcernConclusion::NoMaterialUncertainty,
1..=2 => GoingConcernConclusion::MaterialUncertaintyExists,
_ => GoingConcernConclusion::GoingConcernDoubt,
};
self.material_uncertainty_exists = n > 0;
self
}
}