datasynth_core/models/sourcing/spend_analysis.rs
1//! Spend analysis models for procurement category management.
2
3use rust_decimal::Decimal;
4use serde::{Deserialize, Serialize};
5
6/// Spend analysis for a procurement category.
7#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct SpendAnalysis {
9 /// Category identifier (e.g., GL account group or material group)
10 pub category_id: String,
11 /// Category description
12 pub category_name: String,
13 /// Company code
14 pub company_code: String,
15 /// Total spend in the analysis period
16 #[serde(with = "rust_decimal::serde::str")]
17 pub total_spend: Decimal,
18 /// Number of active vendors in this category
19 pub vendor_count: u32,
20 /// Number of transactions in this category
21 pub transaction_count: u32,
22 /// Herfindahl-Hirschman Index (0-10000) measuring vendor concentration
23 pub hhi_index: f64,
24 /// Top vendor spend shares
25 pub vendor_shares: Vec<VendorSpendShare>,
26 /// Percentage of spend under contract
27 pub contract_coverage: f64,
28 /// Percentage of spend through preferred vendors
29 pub preferred_vendor_coverage: f64,
30 /// Average unit price trend (year-over-year change)
31 pub price_trend_pct: f64,
32 /// Analysis period (fiscal year)
33 pub fiscal_year: u16,
34}
35
36/// Vendor's share of category spend.
37#[derive(Debug, Clone, Serialize, Deserialize)]
38pub struct VendorSpendShare {
39 /// Vendor ID
40 pub vendor_id: String,
41 /// Vendor name
42 pub vendor_name: String,
43 /// Spend amount
44 #[serde(with = "rust_decimal::serde::str")]
45 pub spend_amount: Decimal,
46 /// Share of category spend (0.0 to 1.0)
47 pub share: f64,
48 /// Whether this is a preferred/contracted vendor
49 pub is_preferred: bool,
50}