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