use crate::constants;
pub use asx_rs::as4::pmode::{MepType, PMode, PModeRegistry, PModeSecurity, PayloadPackagingMode};
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum BdewAction {
Utilmd,
Aperak,
Contrl,
Mscons,
Invoic,
Remadv,
Iftsta,
Ordrsp,
Orders,
Ordchg,
Reqote,
Insrpt,
Pricat,
Quotes,
Custom(String),
}
impl BdewAction {
pub fn all_standard() -> Vec<Self> {
vec![
Self::Utilmd,
Self::Aperak,
Self::Contrl,
Self::Mscons,
Self::Invoic,
Self::Remadv,
Self::Iftsta,
Self::Ordrsp,
Self::Orders,
Self::Ordchg,
Self::Reqote,
Self::Insrpt,
Self::Pricat,
Self::Quotes,
]
}
pub fn from_message_type_str(message_type: &str) -> Self {
match message_type {
"UTILMD" => Self::Utilmd,
"APERAK" => Self::Aperak,
"CONTRL" => Self::Contrl,
"MSCONS" => Self::Mscons,
"INVOIC" => Self::Invoic,
"REMADV" => Self::Remadv,
"IFTSTA" => Self::Iftsta,
"ORDRSP" => Self::Ordrsp,
"ORDERS" => Self::Orders,
"ORDCHG" => Self::Ordchg,
"REQOTE" => Self::Reqote,
"INSRPT" => Self::Insrpt,
"PRICAT" => Self::Pricat,
"QUOTES" => Self::Quotes,
other => Self::Custom(format!("{}:{}", crate::constants::SERVICE, other)),
}
}
pub fn as_uri(&self) -> String {
let svc = constants::SERVICE;
match self {
Self::Utilmd => format!("{svc}:UTILMD"),
Self::Aperak => format!("{svc}:APERAK"),
Self::Contrl => format!("{svc}:CONTRL"),
Self::Mscons => format!("{svc}:MSCONS"),
Self::Invoic => format!("{svc}:INVOIC"),
Self::Remadv => format!("{svc}:REMADV"),
Self::Iftsta => format!("{svc}:IFTSTA"),
Self::Ordrsp => format!("{svc}:ORDRSP"),
Self::Orders => format!("{svc}:ORDERS"),
Self::Ordchg => format!("{svc}:ORDCHG"),
Self::Reqote => format!("{svc}:REQOTE"),
Self::Insrpt => format!("{svc}:INSRPT"),
Self::Pricat => format!("{svc}:PRICAT"),
Self::Quotes => format!("{svc}:QUOTES"),
Self::Custom(uri) => uri.clone(),
}
}
}
pub fn bdew_pmode(
id: impl Into<String>,
partner_mp_id: impl Into<String>,
action: BdewAction,
) -> PMode {
PMode {
id: id.into(),
partner_id: partner_mp_id.into(),
service: constants::SERVICE.to_string(),
service_type: constants::SERVICE_TYPE.to_string(),
action: action.as_uri(),
mep: MepType::OneWayPush,
security: PModeSecurity {
sign: true,
encrypt: false,
encrypt_soap_headers: false,
compress: false,
},
payload_packaging: PayloadPackagingMode::MimeAttachment,
endpoint_url: None,
}
}
pub fn bdew_pmode_with_endpoint(
id: impl Into<String>,
partner_mp_id: impl Into<String>,
action: BdewAction,
endpoint_url: impl Into<String>,
) -> PMode {
PMode {
endpoint_url: Some(endpoint_url.into()),
..bdew_pmode(id, partner_mp_id, action)
}
}
pub fn bdew_pmode_encrypted(
id: impl Into<String>,
partner_mp_id: impl Into<String>,
action: BdewAction,
) -> PMode {
PMode {
security: PModeSecurity {
sign: true,
encrypt: true,
encrypt_soap_headers: false,
compress: false,
},
..bdew_pmode(id, partner_mp_id, action)
}
}
pub fn bdew_pmode_encrypted_with_endpoint(
id: impl Into<String>,
partner_mp_id: impl Into<String>,
action: BdewAction,
endpoint_url: impl Into<String>,
) -> PMode {
PMode {
endpoint_url: Some(endpoint_url.into()),
..bdew_pmode_encrypted(id, partner_mp_id, action)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::constants;
#[test]
fn bdew_action_utilmd_uri() {
assert_eq!(BdewAction::Utilmd.as_uri(), "urn:bdew:as4:service:UTILMD");
}
#[test]
fn bdew_action_aperak_uri() {
assert_eq!(BdewAction::Aperak.as_uri(), "urn:bdew:as4:service:APERAK");
}
#[test]
fn bdew_action_custom_uri_passthrough() {
let uri = "urn:custom:action:FOO";
assert_eq!(BdewAction::Custom(uri.to_string()).as_uri(), uri);
}
#[test]
fn bdew_pmode_defaults() {
let pm = bdew_pmode("pm-1", "9900000000001", BdewAction::Utilmd);
assert_eq!(pm.partner_id, "9900000000001");
assert_eq!(pm.service, constants::SERVICE);
assert_eq!(pm.service_type, "");
assert_eq!(pm.action, BdewAction::Utilmd.as_uri());
assert_eq!(pm.mep, MepType::OneWayPush);
assert!(pm.security.sign);
assert!(!pm.security.encrypt);
assert_eq!(pm.payload_packaging, PayloadPackagingMode::MimeAttachment);
assert!(
pm.endpoint_url.is_none(),
"bdew_pmode leaves endpoint_url unset"
);
}
#[test]
fn bdew_pmode_with_endpoint_sets_url() {
let url = "https://partner.example/as4/inbox";
let pm = bdew_pmode_with_endpoint("pm-1", "9900000000001", BdewAction::Utilmd, url);
assert_eq!(pm.endpoint_url.as_deref(), Some(url));
assert!(pm.security.sign);
assert!(!pm.security.encrypt);
}
#[test]
fn bdew_pmode_encrypted_sets_encrypt() {
let pm = bdew_pmode_encrypted("pm-enc", "9900000000001", BdewAction::Aperak);
assert!(pm.security.sign);
assert!(pm.security.encrypt);
assert_eq!(pm.mep, MepType::OneWayPush);
assert!(pm.endpoint_url.is_none());
}
#[test]
fn bdew_pmode_encrypted_with_endpoint_sets_both() {
let url = "https://enc-partner.example/as4";
let pm = bdew_pmode_encrypted_with_endpoint(
"pm-enc-ep",
"9900000000002",
BdewAction::Mscons,
url,
);
assert!(pm.security.encrypt);
assert_eq!(pm.endpoint_url.as_deref(), Some(url));
}
#[test]
fn pmode_registry_resolves_by_partner_and_action() {
let mut registry = PModeRegistry::new();
registry.register(bdew_pmode("pm-u", "9900000000001", BdewAction::Utilmd));
registry.register(bdew_pmode("pm-a", "9900000000001", BdewAction::Aperak));
let pm = registry.resolve(
"9900000000001",
constants::SERVICE,
&BdewAction::Utilmd.as_uri(),
);
assert!(pm.is_some());
assert_eq!(pm.unwrap().id, "pm-u");
assert!(
registry
.resolve(
"9900000000002",
constants::SERVICE,
&BdewAction::Utilmd.as_uri()
)
.is_none()
);
}
}