datasynth_core/models/sourcing/
rfx.rs1use chrono::NaiveDate;
4use rust_decimal::Decimal;
5use serde::{Deserialize, Serialize};
6use std::collections::HashMap;
7
8use super::super::graph_properties::{GraphPropertyValue, ToNodeProperties};
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
12#[serde(rename_all = "snake_case")]
13pub enum RfxType {
14 Rfi,
16 #[default]
18 Rfp,
19 Rfq,
21}
22
23#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
25#[serde(rename_all = "snake_case")]
26pub enum RfxStatus {
27 #[default]
29 Draft,
30 Published,
32 Closed,
34 Awarded,
36 Cancelled,
38 NoAward,
40}
41
42#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
44#[serde(rename_all = "snake_case")]
45pub enum ScoringMethod {
46 LowestPrice,
48 #[default]
50 BestValue,
51 QualityBased,
53}
54
55#[derive(Debug, Clone, Serialize, Deserialize)]
57pub struct RfxEvaluationCriterion {
58 pub name: String,
60 pub weight: f64,
62 pub description: String,
64}
65
66#[derive(Debug, Clone, Serialize, Deserialize)]
68pub struct RfxLineItem {
69 pub item_number: u16,
71 pub description: String,
73 pub material_id: Option<String>,
75 pub quantity: Decimal,
77 pub uom: String,
79 pub target_price: Option<Decimal>,
81}
82
83#[derive(Debug, Clone, Serialize, Deserialize)]
85pub struct RfxEvent {
86 pub rfx_id: String,
88 pub rfx_type: RfxType,
90 pub company_code: String,
92 pub title: String,
94 pub description: String,
96 pub status: RfxStatus,
98 pub sourcing_project_id: String,
100 pub category_id: String,
102 pub scoring_method: ScoringMethod,
104 pub criteria: Vec<RfxEvaluationCriterion>,
106 pub line_items: Vec<RfxLineItem>,
108 pub invited_vendors: Vec<String>,
110 pub publish_date: NaiveDate,
112 pub response_deadline: NaiveDate,
114 pub bid_count: u32,
116 pub owner_id: String,
118 pub awarded_vendor_id: Option<String>,
120 pub awarded_bid_id: Option<String>,
122}
123
124impl ToNodeProperties for RfxEvent {
125 fn node_type_name(&self) -> &'static str {
126 "rfx_event"
127 }
128 fn node_type_code(&self) -> u16 {
129 321
130 }
131 fn to_node_properties(&self) -> HashMap<String, GraphPropertyValue> {
132 let mut p = HashMap::new();
133 p.insert(
134 "rfxId".into(),
135 GraphPropertyValue::String(self.rfx_id.clone()),
136 );
137 p.insert(
138 "rfxType".into(),
139 GraphPropertyValue::String(format!("{:?}", self.rfx_type)),
140 );
141 p.insert(
142 "entityCode".into(),
143 GraphPropertyValue::String(self.company_code.clone()),
144 );
145 p.insert(
146 "title".into(),
147 GraphPropertyValue::String(self.title.clone()),
148 );
149 p.insert(
150 "status".into(),
151 GraphPropertyValue::String(format!("{:?}", self.status)),
152 );
153 p.insert(
154 "scoringMethod".into(),
155 GraphPropertyValue::String(format!("{:?}", self.scoring_method)),
156 );
157 p.insert(
158 "publishDate".into(),
159 GraphPropertyValue::Date(self.publish_date),
160 );
161 p.insert(
162 "responseDeadline".into(),
163 GraphPropertyValue::Date(self.response_deadline),
164 );
165 p.insert(
166 "bidCount".into(),
167 GraphPropertyValue::Int(self.bid_count as i64),
168 );
169 p.insert(
170 "invitedVendorCount".into(),
171 GraphPropertyValue::Int(self.invited_vendors.len() as i64),
172 );
173 p.insert(
174 "isAwarded".into(),
175 GraphPropertyValue::Bool(matches!(self.status, RfxStatus::Awarded)),
176 );
177 p
178 }
179}