use crate::domain::value_objects::medication_frequency::DoseFrequency;
use crate::domain::value_objects::{
dosage::Dosage, medication_id::MedicationId, medication_name::MedicationName,
scheduled_time::ScheduledTime,
};
#[derive(Debug, serde::Serialize, serde::Deserialize, Clone)]
pub struct Medication {
id: MedicationId,
name: MedicationName,
dosage: Dosage,
scheduled_time: Vec<ScheduledTime>,
dose_frequency: DoseFrequency,
}
impl Medication {
pub fn new(
id: MedicationId,
name: MedicationName,
dosage: Dosage,
scheduled_time: Vec<ScheduledTime>,
dose_frequency: DoseFrequency,
) -> Self {
Self {
id,
name,
dosage,
scheduled_time,
dose_frequency,
}
}
pub fn with_id(
id: MedicationId,
name: MedicationName,
dosage: Dosage,
scheduled_time: Vec<ScheduledTime>,
dose_frequency: DoseFrequency,
) -> Self {
Self {
id,
name,
dosage,
scheduled_time,
dose_frequency,
}
}
pub fn id(&self) -> &MedicationId {
&self.id
}
pub fn name(&self) -> &MedicationName {
&self.name
}
pub fn dosage(&self) -> &Dosage {
&self.dosage
}
pub fn scheduled_time(&self) -> &[ScheduledTime] {
&self.scheduled_time
}
pub fn dose_frequency(&self) -> &DoseFrequency {
&self.dose_frequency
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::domain::value_objects::{
dosage::Dosage, medication_name::MedicationName, scheduled_time::ScheduledTime,
};
fn make_medication() -> Medication {
Medication::new(
MedicationId::generate(),
MedicationName::new("Aspirin").unwrap(),
Dosage::new(500).unwrap(),
vec![
ScheduledTime::new(8, 0).unwrap(),
ScheduledTime::new(20, 0).unwrap(),
],
DoseFrequency::TwiceDaily,
)
}
#[test]
fn new_assigns_a_unique_id() {
let med_a = make_medication();
let med_b = make_medication();
assert_ne!(med_a.id(), med_b.id());
}
#[test]
fn name_returns_the_name_passed_to_constructor() {
let med = make_medication();
assert_eq!(med.name().value(), "Aspirin");
}
#[test]
fn dosage_returns_the_dosage_passed_to_constructor() {
let med = make_medication();
assert_eq!(med.dosage().amount_mg(), 500);
}
#[test]
fn scheduled_time_returns_all_times_passed_to_constructor() {
let med = make_medication();
assert_eq!(med.scheduled_time().len(), 2);
assert_eq!(med.scheduled_time()[0].to_string(), "08:00");
assert_eq!(med.scheduled_time()[1].to_string(), "20:00");
}
#[test]
fn new_with_no_scheduled_time_is_allowed() {
let med = Medication::new(
MedicationId::generate(),
MedicationName::new("Aspirin").unwrap(),
Dosage::new(500).unwrap(),
vec![],
DoseFrequency::OnceDaily,
);
assert!(med.scheduled_time().is_empty());
}
#[test]
fn with_id_constructs_medication_with_given_id() {
let id = MedicationId::generate();
let name = MedicationName::new("TestMed").unwrap();
let dosage = Dosage::new(250).unwrap();
let times = vec![ScheduledTime::new(8, 0).unwrap()];
let med = Medication::with_id(
id.clone(),
name.clone(),
dosage.clone(),
times.clone(),
DoseFrequency::Custom(times),
);
assert_eq!(med.id(), &id);
assert_eq!(med.name().value(), name.value());
assert_eq!(med.dosage().amount_mg(), dosage.amount_mg());
}
}