use crate::{helpers::object_key::is_null_or_undefined, model::ViolationDetails};
pub fn itemization_should_should_not_be_empty_if_totals_greater_than_zero(
data: &serde_json::Value,
) -> Option<ViolationDetails> {
let total = data
.get("header")
.and_then(|header| header.get("total"))
.and_then(|total| total.as_i64())
.unwrap_or(0);
let subtotal = data
.get("header")
.and_then(|header| header.get("subtotal"))
.and_then(|subtotal| subtotal.as_i64())
.unwrap_or(0);
if total + subtotal <= 0 {
return None;
}
let Some(itemization) = data.get("itemization") else {
return Some(ViolationDetails {
details: Some("itemization is missing".to_string()),
});
};
if itemization.is_null() {
return Some(ViolationDetails {
details: Some("itemization is null".to_string()),
});
}
if itemization.is_object() {
if is_null_or_undefined(itemization.get("general"))
&& is_null_or_undefined(itemization.get("lodging"))
&& is_null_or_undefined(itemization.get("ecommerce"))
&& is_null_or_undefined(itemization.get("car_rental"))
&& is_null_or_undefined(itemization.get("transit_route"))
&& is_null_or_undefined(itemization.get("subscription"))
&& is_null_or_undefined(itemization.get("flight"))
{
return Some(ViolationDetails {
details: Some("itemization is empty".to_string()),
});
}
}
None
}
#[cfg(test)]
mod tests {
use super::*;
use pretty_assertions::assert_eq;
#[test]
fn test_itemization_should_should_not_be_null_if_totals_greater_than_zero() {
let rule_invalid_serde_json_value = serde_json::json!({
"header": { "total": 100, "subtotal": 100 },
"itemization": null
});
let result = itemization_should_should_not_be_empty_if_totals_greater_than_zero(
&rule_invalid_serde_json_value,
)
.unwrap();
assert_eq!(result.details, Some("itemization is null".to_string()));
}
#[test]
fn test_itemization_should_should_not_be_empty_if_totals_greater_than_zero() {
let rule_invalid_serde_json_value1 = serde_json::json!({
"header": { "total": 100, "subtotal": 100 },
"itemization": {
"general": null,
"lodging": null,
"ecommerce": null,
"car_rental": null,
"transit_route": null,
"subscription": null,
"flight": null
}
});
let rule_invalid_serde_json_value2 = serde_json::json!({
"header": { "total": 100, "subtotal": 100 },
"itemization": {
"general": {},
"lodging": {},
"ecommerce": {},
"car_rental": {},
"transit_route": {},
"subscription": {},
"flight": {}
}
});
let result1 = itemization_should_should_not_be_empty_if_totals_greater_than_zero(
&rule_invalid_serde_json_value1,
)
.unwrap();
let result2 = itemization_should_should_not_be_empty_if_totals_greater_than_zero(
&rule_invalid_serde_json_value2,
)
.unwrap();
assert_eq!(result1.details, Some("itemization is empty".to_string()));
assert_eq!(result2.details, Some("itemization is empty".to_string()));
}
#[test]
fn allow_empty_itemization_if_totals_zero() {
let rule_valid_serde_json_value = serde_json::json!({
"header": { "total": 0, "subtotal": 0 },
"itemization": {
"general": null,
"lodging": null,
"ecommerce": null,
"car_rental": null,
"transit_route": null,
"subscription": null,
"flight": null
}
});
let result = itemization_should_should_not_be_empty_if_totals_greater_than_zero(
&rule_valid_serde_json_value,
);
assert!(result.is_none());
let rule_valid_serde_json_value = serde_json::json!({
"header": { "total": 0, "subtotal": 0 },
"itemization": {}
});
let result = itemization_should_should_not_be_empty_if_totals_greater_than_zero(
&rule_valid_serde_json_value,
);
assert!(result.is_none());
}
}