use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum FacilityType {
Hospital,
AmbulatorySurgery,
PhysicianPractice,
SkilledNursing,
HomeHealth,
Dme,
Laboratory,
ImagingCenter,
}
impl FacilityType {
pub fn provider_type_code(&self) -> &'static str {
match self {
FacilityType::Hospital => "01",
FacilityType::AmbulatorySurgery => "21",
FacilityType::PhysicianPractice => "11",
FacilityType::SkilledNursing => "31",
FacilityType::HomeHealth => "34",
FacilityType::Dme => "09",
FacilityType::Laboratory => "81",
FacilityType::ImagingCenter => "22",
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HealthcareSettings {
pub facility_type: FacilityType,
pub payer_mix: HashMap<String, f64>,
pub coding_systems: CodingSystemSettings,
pub compliance: HealthcareCompliance,
pub avg_daily_encounters: u32,
pub avg_charges_per_encounter: u32,
pub denial_rate: f64,
pub bad_debt_rate: f64,
pub charity_care_rate: f64,
#[serde(default)]
pub anomaly_rates: HealthcareAnomalyRates,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CodingSystemSettings {
pub icd10: bool,
pub cpt: bool,
pub drg: bool,
pub hcpcs: bool,
pub revenue_codes: bool,
}
impl Default for CodingSystemSettings {
fn default() -> Self {
Self {
icd10: true,
cpt: true,
drg: true,
hcpcs: true,
revenue_codes: true,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HealthcareCompliance {
pub hipaa: bool,
pub stark_law: bool,
pub anti_kickback: bool,
pub false_claims_act: bool,
pub emtala: bool,
}
impl Default for HealthcareCompliance {
fn default() -> Self {
Self {
hipaa: true,
stark_law: true,
anti_kickback: true,
false_claims_act: true,
emtala: true,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HealthcareAnomalyRates {
pub upcoding: f64,
pub unbundling: f64,
pub phantom_billing: f64,
pub kickbacks: f64,
pub duplicate_billing: f64,
pub medical_necessity_abuse: f64,
}
impl Default for HealthcareAnomalyRates {
fn default() -> Self {
Self {
upcoding: 0.02,
unbundling: 0.015,
phantom_billing: 0.005,
kickbacks: 0.003,
duplicate_billing: 0.008,
medical_necessity_abuse: 0.01,
}
}
}
impl Default for HealthcareSettings {
fn default() -> Self {
let mut payer_mix = HashMap::new();
payer_mix.insert("medicare".to_string(), 0.40);
payer_mix.insert("medicaid".to_string(), 0.20);
payer_mix.insert("commercial".to_string(), 0.30);
payer_mix.insert("self_pay".to_string(), 0.10);
Self {
facility_type: FacilityType::Hospital,
payer_mix,
coding_systems: CodingSystemSettings::default(),
compliance: HealthcareCompliance::default(),
avg_daily_encounters: 150,
avg_charges_per_encounter: 8,
denial_rate: 0.05,
bad_debt_rate: 0.03,
charity_care_rate: 0.02,
anomaly_rates: HealthcareAnomalyRates::default(),
}
}
}
impl HealthcareSettings {
pub fn for_facility(facility_type: FacilityType) -> Self {
let (avg_daily_encounters, avg_charges_per_encounter) = match facility_type {
FacilityType::PhysicianPractice => (30, 3),
FacilityType::AmbulatorySurgery => (20, 15),
FacilityType::SkilledNursing => (100, 5),
_ => {
let defaults = Self::default();
(
defaults.avg_daily_encounters,
defaults.avg_charges_per_encounter,
)
}
};
Self {
facility_type,
avg_daily_encounters,
avg_charges_per_encounter,
..Self::default()
}
}
}
#[cfg(test)]
#[allow(clippy::unwrap_used)]
mod tests {
use super::*;
#[test]
fn test_facility_type() {
let hospital = FacilityType::Hospital;
assert_eq!(hospital.provider_type_code(), "01");
let physician = FacilityType::PhysicianPractice;
assert_eq!(physician.provider_type_code(), "11");
}
#[test]
fn test_healthcare_settings() {
let settings = HealthcareSettings::default();
assert_eq!(settings.facility_type, FacilityType::Hospital);
assert!(settings.payer_mix.len() >= 4);
assert!(settings.compliance.hipaa);
}
#[test]
fn test_facility_specific_settings() {
let settings = HealthcareSettings::for_facility(FacilityType::PhysicianPractice);
assert_eq!(settings.avg_daily_encounters, 30);
assert_eq!(settings.avg_charges_per_encounter, 3);
}
}