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}