vpr_core/
patient.rs

1//! Patient service and related types.
2//!
3//! This module provides the main service for patient operations,
4//! including initialising full patient records.
5
6use crate::{
7    author::Author, error::PatientResult, repositories::clinical::ClinicalService,
8    repositories::coordination::CoordinationService,
9    repositories::demographics::DemographicsService, NonEmptyText, ShardableUuid,
10};
11use chrono::NaiveDate;
12
13/// Represents a complete patient record with both demographics and clinical components.
14#[derive(Debug)]
15pub struct FullRecord {
16    /// The UUID of the demographics record.
17    pub demographics_uuid: ShardableUuid,
18    /// The UUID of the clinical record.
19    pub clinical_uuid: ShardableUuid,
20    /// The UUID of the coordination record.
21    pub coordination_uuid: ShardableUuid,
22}
23
24/// Pure patient data operations - no API concerns
25#[derive(Clone)]
26pub struct PatientService {
27    cfg: std::sync::Arc<crate::CoreConfig>,
28}
29
30impl PatientService {
31    /// Creates a new instance of PatientService.
32    ///
33    /// # Returns
34    /// A new `PatientService` instance ready to handle patient operations.
35    pub fn new(cfg: std::sync::Arc<crate::CoreConfig>) -> Self {
36        Self { cfg }
37    }
38
39    /// Initialises a complete patient record with demographics and clinical components.
40    ///
41    /// This function creates both a demographics repository and a clinical repository,
42    /// links them together, and populates the demographics with the provided patient information.
43    ///
44    /// # Arguments
45    ///
46    /// * `author` - The author information for Git commits.
47    /// * `given_names` - A vector of the patient's given names.
48    /// * `last_name` - The patient's family/last name.
49    /// * `birth_date` - The patient's date of birth.
50    /// * `namespace` - Optional namespace for the clinical-demographics link.
51    ///
52    /// # Returns
53    ///
54    /// Returns a `FullRecord` containing both UUIDs on success.
55    ///
56    /// # Errors
57    ///
58    /// Returns a `PatientError` if:
59    /// - demographics initialisation or update fails,
60    /// - clinical initialisation fails,
61    /// - linking clinical to demographics fails.
62    pub fn initialise_full_record(
63        &self,
64        author: Author,
65        care_location: NonEmptyText,
66        given_names: Vec<NonEmptyText>,
67        last_name: NonEmptyText,
68        birth_date: NaiveDate,
69        namespace: Option<NonEmptyText>,
70    ) -> PatientResult<FullRecord> {
71        let demographics_service = DemographicsService::new(self.cfg.clone());
72        // Initialise demographics
73        let demographics_service =
74            demographics_service.initialise(author.clone(), care_location.clone())?;
75
76        // Get the UUID for later use
77        let demographics_uuid = demographics_service.demographics_id().to_string();
78
79        // Update demographics with patient information
80        demographics_service.update(given_names, last_name.as_str(), &birth_date.to_string())?;
81
82        // Initialise clinical
83        let clinical_service = ClinicalService::new(self.cfg.clone());
84        let clinical_service =
85            clinical_service.initialise(author.clone(), care_location.clone())?;
86        let clinical_uuid = clinical_service.clinical_id();
87
88        // Link clinical to demographics
89        clinical_service.link_to_demographics(
90            &author,
91            care_location.clone(),
92            &demographics_uuid,
93            namespace,
94        )?;
95
96        // Initialise coordination record linked to clinical
97        let coordination_service = CoordinationService::new(self.cfg.clone());
98        let coordination_service =
99            coordination_service.initialise(author, care_location, clinical_uuid)?;
100        let coordination_uuid = coordination_service.coordination_id();
101
102        Ok(FullRecord {
103            demographics_uuid: ShardableUuid::parse(&demographics_uuid)?,
104            clinical_uuid: ShardableUuid::parse(&clinical_uuid.simple().to_string())?,
105            coordination_uuid: coordination_uuid.clone(),
106        })
107    }
108}