Spaces:
Sleeping
Sleeping
| use crate::application::services::pricing::LogisticsZone; | |
| use crate::infrastructure::db::DbPool; | |
| use serde::{Deserialize, Serialize}; | |
| pub struct CarrierRecord { | |
| pub carrier_id: String, | |
| pub name: String, | |
| pub service_type: String, | |
| pub base_rate: f64, | |
| pub per_kg_rate: f64, | |
| } | |
| pub struct RoutingService { | |
| pool: DbPool, | |
| } | |
| impl RoutingService { | |
| pub fn new(pool: DbPool) -> Self { | |
| Self { pool } | |
| } | |
| pub async fn select_optimal_carrier( | |
| &self, | |
| zone: LogisticsZone, | |
| weight_grams: f64, | |
| ) -> Result<CarrierRecord, sqlx::Error> { | |
| let service_type = match zone { | |
| LogisticsZone::Local => "LOCAL", | |
| LogisticsZone::Regional => "REGIONAL", | |
| LogisticsZone::National => "NATIONAL", | |
| }; | |
| let carriers = sqlx::query_as::<_, CarrierRecord>( | |
| "SELECT carrier_id, name, service_type, base_rate, per_kg_rate FROM carrier_registry WHERE service_type = $1 AND is_active = TRUE" | |
| ) | |
| .bind(service_type) | |
| .fetch_all(&self.pool) | |
| .await?; | |
| // Simple cost-based selection: base_rate + (kg * per_kg_rate) | |
| let weight_kg = weight_grams / 1000.0; | |
| let best_carrier = carriers.into_iter().min_by(|a, b| { | |
| let cost_a = a.base_rate + (weight_kg * a.per_kg_rate); | |
| let cost_b = b.base_rate + (weight_kg * b.per_kg_rate); | |
| cost_a | |
| .partial_cmp(&cost_b) | |
| .unwrap_or(std::cmp::Ordering::Equal) | |
| }); | |
| best_carrier.ok_or_else(|| sqlx::Error::RowNotFound) | |
| } | |
| } | |