use chrono::NaiveDateTime;
use crate::domain::value_objects::{
dosage::Dosage, medication_id::MedicationId, medication_refill_id::MedicationRefillId,
};
#[derive(Debug, serde::Serialize, serde::Deserialize, Clone)]
pub struct MedicationRefill {
id: MedicationRefillId,
medication_id: MedicationId,
pill_strength: Dosage,
pills_per_package: u16,
packages_purchased: u16,
purchased_at: NaiveDateTime,
}
impl MedicationRefill {
pub fn new(
medication_id: MedicationId,
pill_strength: Dosage,
pills_per_package: u16,
packages_purchased: u16,
purchased_at: NaiveDateTime,
) -> Self {
Self {
id: MedicationRefillId::generate(),
medication_id,
pill_strength,
pills_per_package,
packages_purchased,
purchased_at,
}
}
pub fn with_id(
id: MedicationRefillId,
medication_id: MedicationId,
pill_strength: Dosage,
pills_per_package: u16,
packages_purchased: u16,
purchased_at: NaiveDateTime,
) -> Self {
Self {
id,
medication_id,
pill_strength,
pills_per_package,
packages_purchased,
purchased_at,
}
}
pub fn id(&self) -> &MedicationRefillId {
&self.id
}
pub fn medication_id(&self) -> &MedicationId {
&self.medication_id
}
pub fn pill_strength(&self) -> &Dosage {
&self.pill_strength
}
pub fn pills_per_package(&self) -> u16 {
self.pills_per_package
}
pub fn packages_purchased(&self) -> u16 {
self.packages_purchased
}
pub fn purchased_at(&self) -> NaiveDateTime {
self.purchased_at
}
}
#[cfg(test)]
mod tests {
use super::*;
use chrono::NaiveDate;
fn make_datetime() -> NaiveDateTime {
NaiveDate::from_ymd_opt(2025, 1, 1)
.unwrap()
.and_hms_opt(10, 0, 0)
.unwrap()
}
fn make_refill() -> MedicationRefill {
MedicationRefill::new(
MedicationId::generate(),
Dosage::new(500).unwrap(),
30,
1,
make_datetime(),
)
}
#[test]
fn new_assigns_a_unique_id() {
let a = make_refill();
let b = make_refill();
assert_ne!(a.id(), b.id());
}
#[test]
fn new_stores_medication_id() {
let med_id = MedicationId::generate();
let refill = MedicationRefill::new(
med_id.clone(),
Dosage::new(500).unwrap(),
30,
1,
make_datetime(),
);
assert_eq!(refill.medication_id(), &med_id);
}
#[test]
fn new_stores_pill_strength() {
let refill = MedicationRefill::new(
MedicationId::generate(),
Dosage::new(250).unwrap(),
30,
1,
make_datetime(),
);
assert_eq!(refill.pill_strength().amount_mg(), 250);
}
#[test]
fn new_stores_pills_per_package() {
let refill = MedicationRefill::new(
MedicationId::generate(),
Dosage::new(500).unwrap(),
60,
1,
make_datetime(),
);
assert_eq!(refill.pills_per_package(), 60);
}
#[test]
fn new_stores_packages_purchased() {
let refill = MedicationRefill::new(
MedicationId::generate(),
Dosage::new(500).unwrap(),
30,
3,
make_datetime(),
);
assert_eq!(refill.packages_purchased(), 3);
}
#[test]
fn new_stores_purchased_at() {
let purchased_at = make_datetime();
let refill = MedicationRefill::new(
MedicationId::generate(),
Dosage::new(500).unwrap(),
30,
1,
purchased_at,
);
assert_eq!(refill.purchased_at(), purchased_at);
}
#[test]
fn with_id_uses_the_supplied_id() {
let id = MedicationRefillId::generate();
let med_id = MedicationId::generate();
let refill = MedicationRefill::with_id(
id.clone(),
med_id,
Dosage::new(100).unwrap(),
28,
2,
make_datetime(),
);
assert_eq!(refill.id(), &id);
}
}