koprogo_api/application/dto/
budget_dto.rs

1use crate::domain::entities::{Budget, BudgetStatus};
2use chrono::{DateTime, Utc};
3use serde::{Deserialize, Serialize};
4use uuid::Uuid;
5
6/// Request pour créer un nouveau budget
7#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct CreateBudgetRequest {
9    #[serde(default)]
10    pub organization_id: Uuid, // Will be overridden by JWT token
11    pub building_id: Uuid,
12    pub fiscal_year: i32,
13    pub ordinary_budget: f64,
14    pub extraordinary_budget: f64,
15    pub notes: Option<String>,
16}
17
18/// Request pour mettre à jour un budget (Draft uniquement)
19#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct UpdateBudgetRequest {
21    pub ordinary_budget: Option<f64>,
22    pub extraordinary_budget: Option<f64>,
23    pub notes: Option<String>,
24}
25
26/// Response DTO pour un budget
27#[derive(Debug, Clone, Serialize, Deserialize)]
28pub struct BudgetResponse {
29    pub id: Uuid,
30    pub organization_id: Uuid,
31    pub building_id: Uuid,
32    pub fiscal_year: i32,
33    pub ordinary_budget: f64,
34    pub extraordinary_budget: f64,
35    pub total_budget: f64,
36    pub status: BudgetStatus,
37    pub submitted_date: Option<DateTime<Utc>>,
38    pub approved_date: Option<DateTime<Utc>>,
39    pub approved_by_meeting_id: Option<Uuid>,
40    pub monthly_provision_amount: f64,
41    pub notes: Option<String>,
42    pub created_at: DateTime<Utc>,
43    pub updated_at: DateTime<Utc>,
44    // Computed fields
45    pub is_active: bool,
46    pub is_editable: bool,
47}
48
49impl From<Budget> for BudgetResponse {
50    fn from(budget: Budget) -> Self {
51        let is_active = budget.is_active();
52        let is_editable = budget.is_editable();
53
54        Self {
55            id: budget.id,
56            organization_id: budget.organization_id,
57            building_id: budget.building_id,
58            fiscal_year: budget.fiscal_year,
59            ordinary_budget: budget.ordinary_budget,
60            extraordinary_budget: budget.extraordinary_budget,
61            total_budget: budget.total_budget,
62            status: budget.status,
63            submitted_date: budget.submitted_date,
64            approved_date: budget.approved_date,
65            approved_by_meeting_id: budget.approved_by_meeting_id,
66            monthly_provision_amount: budget.monthly_provision_amount,
67            notes: budget.notes,
68            created_at: budget.created_at,
69            updated_at: budget.updated_at,
70            is_active,
71            is_editable,
72        }
73    }
74}
75
76/// Response DTO pour variance analysis (budget vs actual)
77#[derive(Debug, Clone, Serialize, Deserialize)]
78pub struct BudgetVarianceResponse {
79    pub budget_id: Uuid,
80    pub fiscal_year: i32,
81    pub building_id: Uuid,
82
83    // Budget prévu
84    pub budgeted_ordinary: f64,
85    pub budgeted_extraordinary: f64,
86    pub budgeted_total: f64,
87
88    // Réalisé (YTD - Year To Date)
89    pub actual_ordinary: f64,
90    pub actual_extraordinary: f64,
91    pub actual_total: f64,
92
93    // Variance (budget - actual)
94    pub variance_ordinary: f64,
95    pub variance_extraordinary: f64,
96    pub variance_total: f64,
97
98    // Variance en % ((budget - actual) / budget * 100)
99    pub variance_ordinary_pct: f64,
100    pub variance_extraordinary_pct: f64,
101    pub variance_total_pct: f64,
102
103    // Alertes
104    pub has_overruns: bool,              // Dépassements > 10%
105    pub overrun_categories: Vec<String>, // Catégories en dépassement
106    pub months_elapsed: i32,             // Mois écoulés dans l'exercice
107    pub projected_year_end_total: f64,   // Projection fin d'année
108}
109
110/// Response avec statistiques budgétaires
111#[derive(Debug, Clone, Serialize, Deserialize)]
112pub struct BudgetStatsResponse {
113    pub total_budgets: i64,
114    pub draft_count: i64,
115    pub submitted_count: i64,
116    pub approved_count: i64,
117    pub rejected_count: i64,
118    pub archived_count: i64,
119    pub average_total_budget: f64,
120    pub average_monthly_provision: f64,
121}