datasynth_core/models/sourcing/
bid_evaluation.rs1use rust_decimal::Decimal;
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6
7use super::super::graph_properties::{GraphPropertyValue, ToNodeProperties};
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct BidEvaluationEntry {
12 pub criterion_name: String,
14 pub raw_score: f64,
16 pub weight: f64,
18 pub weighted_score: f64,
20}
21
22#[derive(Debug, Clone, Serialize, Deserialize)]
24pub struct RankedBid {
25 pub bid_id: String,
27 pub vendor_id: String,
29 pub rank: u32,
31 pub total_score: f64,
33 pub price_score: f64,
35 pub quality_score: f64,
37 #[serde(with = "rust_decimal::serde::str")]
39 pub total_amount: Decimal,
40 pub criterion_scores: Vec<BidEvaluationEntry>,
42}
43
44#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
46#[serde(rename_all = "snake_case")]
47pub enum AwardRecommendation {
48 Award,
50 Backup,
52 Reject,
54}
55
56#[derive(Debug, Clone, Serialize, Deserialize)]
58pub struct BidEvaluation {
59 pub evaluation_id: String,
61 pub rfx_id: String,
63 pub company_code: String,
65 pub evaluator_id: String,
67 pub ranked_bids: Vec<RankedBid>,
69 pub recommendation: AwardRecommendation,
71 pub recommended_vendor_id: Option<String>,
73 pub recommended_bid_id: Option<String>,
75 pub notes: Option<String>,
77 pub is_finalized: bool,
79}
80
81impl ToNodeProperties for BidEvaluation {
82 fn node_type_name(&self) -> &'static str {
83 "bid_evaluation"
84 }
85 fn node_type_code(&self) -> u16 {
86 323
87 }
88 fn to_node_properties(&self) -> HashMap<String, GraphPropertyValue> {
89 let mut p = HashMap::new();
90 p.insert(
91 "evaluationId".into(),
92 GraphPropertyValue::String(self.evaluation_id.clone()),
93 );
94 p.insert(
95 "rfxId".into(),
96 GraphPropertyValue::String(self.rfx_id.clone()),
97 );
98 p.insert(
99 "entityCode".into(),
100 GraphPropertyValue::String(self.company_code.clone()),
101 );
102 p.insert(
103 "evaluatorId".into(),
104 GraphPropertyValue::String(self.evaluator_id.clone()),
105 );
106 p.insert(
107 "recommendation".into(),
108 GraphPropertyValue::String(format!("{:?}", self.recommendation)),
109 );
110 p.insert(
111 "bidCount".into(),
112 GraphPropertyValue::Int(self.ranked_bids.len() as i64),
113 );
114 if let Some(top) = self.ranked_bids.first() {
115 p.insert(
116 "topBidScore".into(),
117 GraphPropertyValue::Float(top.total_score),
118 );
119 p.insert(
120 "topBidAmount".into(),
121 GraphPropertyValue::Decimal(top.total_amount),
122 );
123 }
124 if let Some(ref vendor_id) = self.recommended_vendor_id {
125 p.insert(
126 "recommendedVendorId".into(),
127 GraphPropertyValue::String(vendor_id.clone()),
128 );
129 }
130 p.insert(
131 "isFinalized".into(),
132 GraphPropertyValue::Bool(self.is_finalized),
133 );
134 p
135 }
136}