optirs_core/research/
funding.rs

1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3
4/// Represents a funding source
5#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct FundingSource {
7    pub id: String,
8    pub name: String,
9    pub agency: String,
10    pub program: Option<String>,
11    pub grant_number: Option<String>,
12    pub amount: Option<f64>,
13    pub currency: String,
14    pub start_date: Option<chrono::DateTime<chrono::Utc>>,
15    pub end_date: Option<chrono::DateTime<chrono::Utc>>,
16}
17
18/// Represents a grant or funding award
19#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct Grant {
21    pub id: String,
22    pub title: String,
23    pub abstract_text: Option<String>,
24    pub principal_investigator: String,
25    pub co_investigators: Vec<String>,
26    pub funding_source: FundingSource,
27    pub status: GrantStatus,
28}
29
30/// Status of a grant
31#[derive(Debug, Clone, Serialize, Deserialize)]
32pub enum GrantStatus {
33    Draft,
34    Submitted,
35    UnderReview,
36    Awarded,
37    Rejected,
38    Active,
39    Completed,
40}
41
42/// Manager for funding and grants
43#[derive(Debug, Default)]
44pub struct FundingManager {
45    grants: HashMap<String, Grant>,
46    funding_sources: HashMap<String, FundingSource>,
47}
48
49impl FundingManager {
50    pub fn new() -> Self {
51        Self {
52            grants: HashMap::new(),
53            funding_sources: HashMap::new(),
54        }
55    }
56
57    pub fn add_grant(&mut self, grant: Grant) {
58        self.grants.insert(grant.id.clone(), grant);
59    }
60
61    pub fn get_grant(&self, id: &str) -> Option<&Grant> {
62        self.grants.get(id)
63    }
64
65    pub fn add_funding_source(&mut self, source: FundingSource) {
66        self.funding_sources.insert(source.id.clone(), source);
67    }
68
69    pub fn get_funding_source(&self, id: &str) -> Option<&FundingSource> {
70        self.funding_sources.get(id)
71    }
72
73    pub fn list_active_grants(&self) -> Vec<&Grant> {
74        self.grants
75            .values()
76            .filter(|g| matches!(g.status, GrantStatus::Active))
77            .collect()
78    }
79}