use super::types::PricingGuardrailsOutput;
use crate::gate::Violation;
use crate::packs::{InvariantDef, InvariantResult};
pub fn get_invariants() -> Vec<InvariantDef> {
vec![
InvariantDef::critical(
"margin_maintained",
"All products must maintain minimum margin",
),
InvariantDef::critical(
"within_bounds",
"All prices must be within defined guardrails",
),
InvariantDef::advisory(
"competitive_position",
"Pricing should achieve competitive positioning goals",
),
InvariantDef::advisory(
"price_stability",
"Price changes should be reasonable",
),
]
}
pub const INVARIANTS: &[InvariantDef] = &[];
pub fn check_all_invariants(output: &PricingGuardrailsOutput) -> Vec<InvariantResult> {
vec![
check_margin_maintained(output),
check_within_bounds(output),
check_competitive_position(output),
check_price_stability(output),
]
}
fn check_margin_maintained(output: &PricingGuardrailsOutput) -> InvariantResult {
let invariant = "margin_maintained";
if output.recommendations.is_empty() {
return InvariantResult::pass(invariant);
}
if output.guardrail_compliance.all_margins_met {
InvariantResult::pass(invariant)
} else {
let failed_products: Vec<_> = output
.recommendations
.iter()
.filter(|r| !r.margin_target_met)
.map(|r| format!("{} ({:.1}%)", r.product_id, r.margin_pct))
.collect();
let violation = Violation::new(
invariant,
1.0,
format!(
"Products below minimum margin: {}",
failed_products.join(", ")
),
);
InvariantResult::fail(invariant, violation)
}
}
fn check_within_bounds(output: &PricingGuardrailsOutput) -> InvariantResult {
let invariant = "within_bounds";
if output.recommendations.is_empty() {
return InvariantResult::pass(invariant);
}
if output.guardrail_compliance.all_within_bounds {
InvariantResult::pass(invariant)
} else {
let out_of_bounds: Vec<_> = output
.recommendations
.iter()
.filter(|r| !r.within_bounds)
.map(|r| format!("{} (${:.2})", r.product_id, r.recommended_price))
.collect();
let violation = Violation::new(
invariant,
1.0,
format!("Products outside price bounds: {}", out_of_bounds.join(", ")),
);
InvariantResult::fail(invariant, violation)
}
}
fn check_competitive_position(output: &PricingGuardrailsOutput) -> InvariantResult {
let invariant = "competitive_position";
if output.recommendations.is_empty() {
return InvariantResult::pass(invariant);
}
if output.guardrail_compliance.competitive_position_achieved {
InvariantResult::pass(invariant)
} else {
let products_with_competitor_data: Vec<_> = output
.recommendations
.iter()
.filter(|r| r.competitive_position.competitor_count > 0)
.collect();
if products_with_competitor_data.is_empty() {
return InvariantResult::pass(invariant);
}
let violation = Violation::new(
invariant,
0.5,
"Competitive positioning strategy not fully achieved",
);
InvariantResult::fail(invariant, violation)
}
}
fn check_price_stability(output: &PricingGuardrailsOutput) -> InvariantResult {
let invariant = "price_stability";
if output.recommendations.is_empty() {
return InvariantResult::pass(invariant);
}
let extreme_changes: Vec<_> = output
.recommendations
.iter()
.filter(|r| {
r.price_change_pct
.map(|pct| pct.abs() > 30.0)
.unwrap_or(false)
})
.map(|r| {
format!(
"{} ({:+.1}%)",
r.product_id,
r.price_change_pct.unwrap_or(0.0)
)
})
.collect();
if extreme_changes.is_empty() {
InvariantResult::pass(invariant)
} else {
let violation = Violation::new(
invariant,
0.3,
format!(
"Large price changes detected: {}",
extreme_changes.join(", ")
),
);
InvariantResult::fail(invariant, violation)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::packs::pricing_guardrails::types::*;
fn create_valid_output() -> PricingGuardrailsOutput {
PricingGuardrailsOutput {
recommendations: vec![
PricingRecommendation {
product_id: "SKU-001".to_string(),
recommended_price: 100.0,
previous_price: Some(95.0),
price_change: Some(5.0),
price_change_pct: Some(5.26),
margin_pct: 25.0,
markup_pct: 33.3,
competitive_position: CompetitivePosition {
avg_competitor_price: Some(105.0),
position_vs_avg_pct: Some(-4.76),
competitor_count: 2,
lowest_in_market: true,
highest_in_market: false,
},
within_bounds: true,
margin_target_met: true,
rationale: "Achieves target margin".to_string(),
},
PricingRecommendation {
product_id: "SKU-002".to_string(),
recommended_price: 75.0,
previous_price: None,
price_change: None,
price_change_pct: None,
margin_pct: 30.0,
markup_pct: 42.9,
competitive_position: CompetitivePosition::default(),
within_bounds: true,
margin_target_met: true,
rationale: "New price set to target margin".to_string(),
},
],
margin_analysis: MarginAnalysis {
total_products: 2,
products_meeting_margin: 2,
average_margin_pct: 27.5,
min_margin_pct: 25.0,
max_margin_pct: 30.0,
},
guardrail_compliance: GuardrailCompliance {
all_within_bounds: true,
all_margins_met: true,
competitive_position_achieved: true,
violations: vec![],
},
}
}
#[test]
fn test_all_pass_valid_output() {
let output = create_valid_output();
let results = check_all_invariants(&output);
for result in &results {
assert!(result.passed, "Invariant {} failed", result.invariant);
}
}
#[test]
fn test_margin_maintained_failure() {
let mut output = create_valid_output();
output.guardrail_compliance.all_margins_met = false;
output.recommendations[0].margin_target_met = false;
output.recommendations[0].margin_pct = 15.0;
let result = check_margin_maintained(&output);
assert!(!result.passed);
assert!(result.violation.as_ref().unwrap().severity == 1.0); }
#[test]
fn test_within_bounds_failure() {
let mut output = create_valid_output();
output.guardrail_compliance.all_within_bounds = false;
output.recommendations[0].within_bounds = false;
let result = check_within_bounds(&output);
assert!(!result.passed);
assert!(result.violation.as_ref().unwrap().severity == 1.0); }
#[test]
fn test_competitive_position_failure() {
let mut output = create_valid_output();
output.guardrail_compliance.competitive_position_achieved = false;
let result = check_competitive_position(&output);
assert!(!result.passed);
assert!(result.violation.as_ref().unwrap().severity < 1.0); }
#[test]
fn test_price_stability_extreme_change() {
let mut output = create_valid_output();
output.recommendations[0].price_change_pct = Some(50.0);
let result = check_price_stability(&output);
assert!(!result.passed);
assert!(result.violation.as_ref().unwrap().severity < 1.0); assert!(result
.violation
.as_ref()
.unwrap()
.explanation
.contains("Large price changes"));
}
#[test]
fn test_price_stability_moderate_change() {
let mut output = create_valid_output();
output.recommendations[0].price_change_pct = Some(15.0);
let result = check_price_stability(&output);
assert!(result.passed);
}
#[test]
fn test_empty_recommendations() {
let output = PricingGuardrailsOutput::no_valid_pricing("No products");
let results = check_all_invariants(&output);
let margin_result = results.iter().find(|r| r.invariant == "margin_maintained").unwrap();
assert!(margin_result.passed);
let bounds_result = results.iter().find(|r| r.invariant == "within_bounds").unwrap();
assert!(bounds_result.passed);
}
#[test]
fn test_invariant_definitions() {
let invariants = get_invariants();
assert_eq!(invariants.len(), 4);
let margin_inv = invariants.iter().find(|i| i.name == "margin_maintained").unwrap();
assert!(margin_inv.critical);
let bounds_inv = invariants.iter().find(|i| i.name == "within_bounds").unwrap();
assert!(bounds_inv.critical);
let comp_inv = invariants.iter().find(|i| i.name == "competitive_position").unwrap();
assert!(!comp_inv.critical);
let stability_inv = invariants.iter().find(|i| i.name == "price_stability").unwrap();
assert!(!stability_inv.critical);
}
}