Skip to main content

datasynth_core/models/sourcing/
rfx.rs

1//! RFx (Request for Information/Proposal/Quotation) models.
2
3use chrono::NaiveDate;
4use rust_decimal::Decimal;
5use serde::{Deserialize, Serialize};
6
7/// Type of RFx event.
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
9#[serde(rename_all = "snake_case")]
10pub enum RfxType {
11    /// Request for Information (discovery)
12    Rfi,
13    /// Request for Proposal (complex requirements)
14    #[default]
15    Rfp,
16    /// Request for Quotation (price-focused)
17    Rfq,
18}
19
20/// Status of an RFx event.
21#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
22#[serde(rename_all = "snake_case")]
23pub enum RfxStatus {
24    /// RFx created, not yet published
25    #[default]
26    Draft,
27    /// Published and open for responses
28    Published,
29    /// Response period ended, under evaluation
30    Closed,
31    /// Evaluation complete, winner selected
32    Awarded,
33    /// RFx cancelled
34    Cancelled,
35    /// No suitable bids received
36    NoAward,
37}
38
39/// Scoring method for bid evaluation.
40#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
41#[serde(rename_all = "snake_case")]
42pub enum ScoringMethod {
43    /// Lowest price wins
44    LowestPrice,
45    /// Best value (weighted price + quality)
46    #[default]
47    BestValue,
48    /// Quality-based selection (price secondary)
49    QualityBased,
50}
51
52/// Evaluation criterion for an RFx.
53#[derive(Debug, Clone, Serialize, Deserialize)]
54pub struct RfxEvaluationCriterion {
55    /// Criterion name
56    pub name: String,
57    /// Weight (0.0 to 1.0, all criteria sum to 1.0)
58    pub weight: f64,
59    /// Description of what is being evaluated
60    pub description: String,
61}
62
63/// Line item within an RFx.
64#[derive(Debug, Clone, Serialize, Deserialize)]
65pub struct RfxLineItem {
66    /// Item number
67    pub item_number: u16,
68    /// Material/service description
69    pub description: String,
70    /// Material ID (if applicable)
71    pub material_id: Option<String>,
72    /// Required quantity
73    pub quantity: Decimal,
74    /// Unit of measure
75    pub uom: String,
76    /// Target unit price (budget)
77    pub target_price: Option<Decimal>,
78}
79
80/// An RFx (Request for x) event.
81#[derive(Debug, Clone, Serialize, Deserialize)]
82pub struct RfxEvent {
83    /// Unique RFx identifier
84    pub rfx_id: String,
85    /// RFx type (RFI/RFP/RFQ)
86    pub rfx_type: RfxType,
87    /// Company code
88    pub company_code: String,
89    /// Title
90    pub title: String,
91    /// Description
92    pub description: String,
93    /// Current status
94    pub status: RfxStatus,
95    /// Sourcing project ID
96    pub sourcing_project_id: String,
97    /// Spend category
98    pub category_id: String,
99    /// Scoring method
100    pub scoring_method: ScoringMethod,
101    /// Evaluation criteria
102    pub criteria: Vec<RfxEvaluationCriterion>,
103    /// Line items
104    pub line_items: Vec<RfxLineItem>,
105    /// Invited vendor IDs
106    pub invited_vendors: Vec<String>,
107    /// Publication date
108    pub publish_date: NaiveDate,
109    /// Response deadline
110    pub response_deadline: NaiveDate,
111    /// Number of bids received
112    pub bid_count: u32,
113    /// Owner (sourcing manager)
114    pub owner_id: String,
115    /// Awarded vendor ID
116    pub awarded_vendor_id: Option<String>,
117    /// Awarded bid ID
118    pub awarded_bid_id: Option<String>,
119}