use jiff::Timestamp;
use secrecy::SecretString;
use url::Url;
use super::error::PdqmError;
use ihe_atna::balp::{
Coded, DESTINATION_ROLE, Direction, Entity, EventKind, Exchange, Outcome, Peer, REST, SEARCH,
SOURCE_ROLE,
};
use ihe_atna::user::OnBehalfOf;
pub const ITI_78: Coded = Coded::fixed(
ihe_atna::balp::IHE_TRANSACTIONS,
"ITI-78",
"Mobile Patient Demographics Query",
);
pub const ITI_119: Coded = Coded::fixed(
ihe_atna::balp::IHE_TRANSACTIONS,
"ITI-119",
"Patient Demographics Match",
);
#[must_use]
pub fn query_consumer() -> EventKind {
EventKind {
profile: "https://profiles.ihe.net/ITI/PDQm/StructureDefinition/IHE.PDQm.Query.Audit.Consumer",
event_type: REST,
subtypes: vec![ITI_78, SEARCH],
action: "E",
client: SOURCE_ROLE,
server: DESTINATION_ROLE,
}
}
#[must_use]
pub fn match_consumer() -> EventKind {
EventKind {
profile: "https://profiles.ihe.net/ITI/PDQm/StructureDefinition/IHE.PDQm.Match.Audit.Consumer",
event_type: REST,
subtypes: vec![ITI_119, SEARCH],
action: "E",
client: SOURCE_ROLE,
server: DESTINATION_ROLE,
}
}
pub(super) fn exchange<T>(
base: &Url,
request: SecretString,
on_behalf: &OnBehalfOf,
result: &Result<T, PdqmError>,
) -> Exchange {
recorded(
(query_consumer(), base),
vec![Entity::Query(request)],
on_behalf,
result,
)
}
pub(super) fn match_exchange<T>(
base: &Url,
(request, patient): (SecretString, Option<(&str, &SecretString)>),
on_behalf: &OnBehalfOf,
result: &Result<T, PdqmError>,
) -> Exchange {
let mut entities = vec![Entity::Query(request)];
if let Some((system, value)) = patient {
entities.push(Entity::Patient {
system: Some(system.to_owned()),
namespace: None,
value: value.clone(),
});
}
recorded((match_consumer(), base), entities, on_behalf, result)
}
fn recorded<T>(
(kind, base): (EventKind, &Url),
entities: Vec<Entity>,
on_behalf: &OnBehalfOf,
result: &Result<T, PdqmError>,
) -> Exchange {
let outcome = match result {
Ok(_) => Outcome::Success,
Err(PdqmError::Timeout | PdqmError::Transport(_)) => Outcome::SeriousFailure,
Err(_) => Outcome::MinorFailure,
};
Exchange {
kind,
recorded: Timestamp::now(),
outcome,
outcome_description: None,
direction: Direction::Sent {
server: Peer::server(base),
},
on_behalf: on_behalf.clone(),
entities,
security: Vec::new(),
}
}