52 std::set<std::string> affected_studies;
61 if (!study_uid.empty()) {
62 affected_studies.insert(study_uid);
68 result.
error_message =
"No instances found for patient ID: " +
84 audit.
timestamp = std::chrono::system_clock::now();
108 result.
error_message =
"Source and target patient IDs must be different";
113 std::set<std::string> affected_studies;
130 if (!study_uid.empty()) {
131 affected_studies.insert(study_uid);
137 result.
error_message =
"No instances found for source patient ID: " +
154 audit.
timestamp = std::chrono::system_clock::now();
162 const std::string& patient_id)
const {
164 std::vector<core::dicom_dataset> results;
167 results.push_back(instance);
178 std::set<std::string> ids;
185 return {ids.begin(), ids.end()};
188const std::vector<reconciliation_audit_record>&
193std::vector<reconciliation_audit_record>
195 const std::string& patient_id)
const {
197 std::vector<reconciliation_audit_record> results;
199 if (record.primary_patient_id == patient_id ||
200 (record.secondary_patient_id &&
201 record.secondary_patient_id.value() == patient_id)) {
202 results.push_back(record);
239 static std::mt19937_64 gen{std::random_device{}()};
240 static std::uniform_int_distribution<uint64_t> dist;
242 auto now = std::chrono::system_clock::now();
243 auto timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(
244 now.time_since_epoch()).count();
246 return "PIR-" + std::to_string(timestamp) +
"-" +
247 std::to_string(dist(gen) % 100000);
260 return "demographics_update";
void set_string(dicom_tag tag, encoding::vr_type vr, std::string_view value)
Set a string value for the given tag.
auto get_string(dicom_tag tag, std::string_view default_value="") const -> std::string
Get the string value of an element.
std::vector< core::dicom_dataset > find_instances(const std::string &patient_id) const
Find all instances for a given patient ID.
bool add_instance(const core::dicom_dataset &dataset)
Add a DICOM instance to the managed store.
size_t instance_count() const noexcept
Get the total number of managed instances.
std::vector< core::dicom_dataset > instances_
std::vector< std::string > get_patient_ids() const
Get distinct patient IDs in the store.
reconciliation_result merge_patients(const patient_merge_request &request)
Merge instances from source patient to target patient.
void apply_demographics(core::dicom_dataset &dataset, const patient_demographics &demographics) const
std::vector< reconciliation_audit_record > audit_records_
reconciliation_result update_demographics(const demographics_update_request &request)
Update patient demographics across all matching instances.
std::vector< reconciliation_audit_record > audit_trail_for_patient(const std::string &patient_id) const
Get audit records for a specific patient.
const std::vector< reconciliation_audit_record > & audit_trail() const noexcept
Get the audit trail of reconciliation operations.
std::string generate_record_id() const
Compile-time constants for commonly used DICOM tags.
constexpr std::string_view to_string(vr_type vr) noexcept
Converts a vr_type to its two-character string representation.
reconciliation_type
Type of patient reconciliation operation.
@ patient_link
ADT^A24: link related patients.
@ demographics_update
ADT^A08: update patient demographics.
@ patient_merge
ADT^A40: merge two patients.
IHE PIR (Patient Information Reconciliation) Service.
Request to update patient demographics.
std::optional< std::string > operator_name
Operator performing the update.
std::string target_patient_id
Patient ID to update.
patient_demographics updated_demographics
Updated demographics.
Updated patient demographics for a reconciliation operation.
std::optional< std::string > patient_name
Patient Name (0010,0010)
std::optional< std::string > patient_birth_date
Patient Birth Date (0010,0030)
std::optional< std::string > issuer_of_patient_id
Issuer of Patient ID (0010,0021)
std::optional< std::string > patient_id
Patient ID (0010,0020)
std::optional< std::string > patient_sex
Patient Sex (0010,0040)
Request to merge two patients.
std::string target_patient_id
Patient ID to merge into (target - will retain)
std::optional< patient_demographics > target_demographics
Optional updated demographics for the target.
std::optional< std::string > operator_name
Operator performing the merge.
std::string source_patient_id
Patient ID to merge from (source - will be removed)
Audit record of a reconciliation operation.
size_t instances_updated
Number of instances affected.
std::string operator_name
Operator who performed the action.
std::chrono::system_clock::time_point timestamp
Timestamp.
std::optional< std::string > secondary_patient_id
reconciliation_type type
Type of operation.
bool success
Whether operation succeeded.
std::string record_id
Unique identifier for this audit record.
std::string primary_patient_id
Patient ID(s) involved.
Result of a reconciliation operation.
size_t instances_updated
Number of instances affected.
std::string error_message
Error message (if failed)
size_t studies_affected
Number of studies affected.
reconciliation_type type
Type of operation performed.
bool success
Whether the operation succeeded.