use chrono::NaiveDate;
use rust_decimal::Decimal;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use super::super::graph_properties::{GraphPropertyValue, ToNodeProperties};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
#[serde(rename_all = "snake_case")]
pub enum SourcingProjectType {
#[default]
NewSourcing,
Renewal,
Consolidation,
Emergency,
StrategicPartnership,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
#[serde(rename_all = "snake_case")]
pub enum SourcingProjectStatus {
#[default]
Draft,
SpendAnalysis,
Qualification,
RfxActive,
Evaluation,
Negotiation,
Awarded,
Completed,
Cancelled,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SourcingProject {
pub project_id: String,
pub project_name: String,
pub company_code: String,
pub project_type: SourcingProjectType,
pub status: SourcingProjectStatus,
pub category_id: String,
#[serde(with = "crate::serde_decimal")]
pub estimated_annual_spend: Decimal,
pub target_savings_pct: f64,
pub owner_id: String,
pub start_date: NaiveDate,
pub target_end_date: NaiveDate,
pub actual_end_date: Option<NaiveDate>,
pub spend_analysis_id: Option<String>,
pub rfx_ids: Vec<String>,
pub contract_id: Option<String>,
pub actual_savings_pct: Option<f64>,
}
impl ToNodeProperties for SourcingProject {
fn node_type_name(&self) -> &'static str {
"sourcing_project"
}
fn node_type_code(&self) -> u16 {
320
}
fn to_node_properties(&self) -> HashMap<String, GraphPropertyValue> {
let mut p = HashMap::new();
p.insert(
"projectId".into(),
GraphPropertyValue::String(self.project_id.clone()),
);
p.insert(
"projectName".into(),
GraphPropertyValue::String(self.project_name.clone()),
);
p.insert(
"entityCode".into(),
GraphPropertyValue::String(self.company_code.clone()),
);
p.insert(
"projectType".into(),
GraphPropertyValue::String(format!("{:?}", self.project_type)),
);
p.insert(
"status".into(),
GraphPropertyValue::String(format!("{:?}", self.status)),
);
p.insert(
"estimatedValue".into(),
GraphPropertyValue::Decimal(self.estimated_annual_spend),
);
p.insert(
"targetSavingsPct".into(),
GraphPropertyValue::Float(self.target_savings_pct),
);
p.insert(
"owner".into(),
GraphPropertyValue::String(self.owner_id.clone()),
);
p.insert(
"startDate".into(),
GraphPropertyValue::Date(self.start_date),
);
p.insert(
"targetEndDate".into(),
GraphPropertyValue::Date(self.target_end_date),
);
p.insert(
"bidCount".into(),
GraphPropertyValue::Int(self.rfx_ids.len() as i64),
);
p.insert(
"isComplete".into(),
GraphPropertyValue::Bool(matches!(
self.status,
SourcingProjectStatus::Completed | SourcingProjectStatus::Awarded
)),
);
p
}
}