use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct LogisticsConfig { pub weight_coefficient: f64, pub distance_coefficient: f64, pub complexity_bias: f64, } #[derive(Debug, Clone, Serialize, Deserialize)] pub enum LogisticsZone { Local, // Within city (< 50km) Regional, // Within state (50 - 300km) National, // Outside state (> 300km) } impl Default for LogisticsConfig { fn default() -> Self { Self { weight_coefficient: 0.15, // Adjusted for Indian gram-based pricing distance_coefficient: 1.0, complexity_bias: 1.0, } } } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct PricingFeatures { pub distance_km: f64, pub user_rate_per_km: f64, pub product_weight: f64, pub base_charge: f64, pub config: LogisticsConfig, } // ======================================================== // ADVANCED OOPS CONCEPTS: POLYMORPHIC ZONAL PRICING // ======================================================== /// Strategy trait for calculating regional zone pricing coefficients. pub trait ZonalPricingStrategy: Send + Sync { fn multiplier(&self) -> f64; } pub struct LocalZoneStrategy; impl ZonalPricingStrategy for LocalZoneStrategy { fn multiplier(&self) -> f64 { 1.0 } } pub struct RegionalZoneStrategy; impl ZonalPricingStrategy for RegionalZoneStrategy { fn multiplier(&self) -> f64 { 1.5 } } pub struct NationalZoneStrategy; impl ZonalPricingStrategy for NationalZoneStrategy { fn multiplier(&self) -> f64 { 2.5 } } /// Factory pattern to retrieve the correct zonal pricing strategy object dynamically. pub struct ZonalPricingStrategyFactory; impl ZonalPricingStrategyFactory { pub fn get_strategy(distance_km: f64) -> Box { if distance_km < 50.0 { Box::new(LocalZoneStrategy) } else if distance_km < 300.0 { Box::new(RegionalZoneStrategy) } else { Box::new(NationalZoneStrategy) } } } // ======================================================== // PRICING ENGINE CLASS IMPLEMENTATION // ======================================================== /// The `PricingEngine` handles the platform's economic logic, including dynamic delivery fees /// and trust-adjusted platform service charges. Refactored using dynamic strategy patterns. pub struct PricingEngine; impl PricingEngine { /// Estimates the delivery fee using a multi-factor linear estimation model. /// /// The model accounts for: /// 1. **Zonal Logic**: Higher multipliers for cross-state shipments (polymorphically resolved). /// 2. **Volumetric Weight**: Uses a gram-to-kg conversion with configurable coefficients. /// 3. **Distance Variable**: Direct linear scaling with the merchant's custom rate-per-km. pub fn estimate_delivery_fee(features: PricingFeatures) -> f64 { let strategy = ZonalPricingStrategyFactory::get_strategy(features.distance_km); let zone_multiplier = strategy.multiplier(); // Convert weight from grams to kg for institutional pricing parity let weight_kg = features.product_weight / 1000.0; let weight_component = weight_kg * features.config.weight_coefficient * 50.0; // ₹50 per kg baseline let base_with_zone = features.base_charge * zone_multiplier; let distance_component = features.distance_km * (features.user_rate_per_km * features.config.distance_coefficient); let raw_total = (base_with_zone + distance_component + weight_component) * features.config.complexity_bias; // Perform final rounding to match currency precision (raw_total * 100.0).round() / 100.0 } /// Calculates the platform's service fee for a transaction. /// /// This is a **Secure Incentive** model: /// - Base fees are tiered by transaction value. /// - **Trust Discount**: High trust scores (0-100) provide a linear discount of up to 50%. pub fn calculate_platform_fee(_price: f64, _trust_score: f64) -> f64 { 0.0 } /// Aggregates all price components into a final total consumer charge. pub fn calculate_total_consumer_price( product_price: f64, delivery_fee: f64, tax_amount: f64, _trust_score: f64, ) -> f64 { ((product_price + delivery_fee + tax_amount) * 100.0).round() / 100.0 } } #[cfg(test)] mod tests { use super::*; #[test] fn test_zero_distance_pricing() { let features = PricingFeatures { distance_km: 0.0, user_rate_per_km: 15.0, product_weight: 500.0, base_charge: 20.0, config: LogisticsConfig::default(), }; let fee = PricingEngine::estimate_delivery_fee(features); // (0 * 15 + 0.5 * 0.15 * 50 + 20 * 1.0) * 1.0 = 23.75 assert_eq!(fee, 23.75); } #[test] fn test_extreme_weight_pricing() { let features = PricingFeatures { distance_km: 10.0, user_rate_per_km: 15.0, product_weight: 100000.0, // 100kg base_charge: 20.0, config: LogisticsConfig::default(), }; let fee = PricingEngine::estimate_delivery_fee(features); // (150 + 100 * 0.15 * 50 + 20) = 150 + 750 + 20 = 920.0 assert_eq!(fee, 920.0); } }