koprogo_api/application/dto/
energy_bill_upload_dto.rs

1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use uuid::Uuid;
4
5use crate::domain::entities::{EnergyBillUpload, EnergyType};
6
7/// DTO for uploading energy bill with GDPR consent
8#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct UploadEnergyBillRequest {
10    pub campaign_id: Uuid,
11    pub unit_id: Uuid,
12    pub building_id: Uuid,
13
14    // Bill details
15    pub bill_period_start: DateTime<Utc>,
16    pub bill_period_end: DateTime<Utc>,
17    pub total_kwh: f64, // Plain text (will be encrypted)
18    pub energy_type: EnergyType,
19    pub provider: Option<String>,
20    pub postal_code: String, // 4-digit Belgian postal code
21
22    // File details
23    pub file_hash: String, // SHA-256 of uploaded PDF
24    pub file_path: String, // S3 path (will be encrypted)
25
26    // OCR metadata
27    pub ocr_confidence: Option<f64>,
28
29    // GDPR Consent (required)
30    pub consent: GdprConsentData,
31}
32
33/// DTO for GDPR consent data
34#[derive(Debug, Clone, Serialize, Deserialize)]
35pub struct GdprConsentData {
36    pub accepted: bool, // Must be true
37    pub timestamp: DateTime<Utc>,
38    pub ip: String,
39    pub user_agent: String,
40}
41
42/// DTO for energy bill upload response (anonymized)
43#[derive(Debug, Clone, Serialize, Deserialize)]
44pub struct EnergyBillUploadResponse {
45    pub id: Uuid,
46    pub campaign_id: Uuid,
47    pub unit_id: Uuid,
48    pub building_id: Uuid,
49    pub organization_id: Uuid,
50
51    // Bill period (public)
52    pub bill_period_start: DateTime<Utc>,
53    pub bill_period_end: DateTime<Utc>,
54
55    // Consumption (encrypted - not exposed)
56    // total_kwh_encrypted: NOT INCLUDED (sensitive)
57    pub energy_type: EnergyType,
58    pub provider: Option<String>,
59    pub postal_code: String,
60
61    // File metadata (hashes only)
62    pub file_hash: String,
63    // file_path_encrypted: NOT INCLUDED (sensitive)
64    pub ocr_confidence: f64,
65    pub manually_verified: bool,
66    pub verified_at: Option<DateTime<Utc>>,
67
68    // GDPR status
69    pub consent_timestamp: DateTime<Utc>,
70    pub anonymized: bool,
71    pub retention_until: DateTime<Utc>,
72    pub deleted_at: Option<DateTime<Utc>>,
73
74    pub uploaded_at: DateTime<Utc>,
75    pub created_at: DateTime<Utc>,
76    pub updated_at: DateTime<Utc>,
77}
78
79impl From<EnergyBillUpload> for EnergyBillUploadResponse {
80    fn from(upload: EnergyBillUpload) -> Self {
81        Self {
82            id: upload.id,
83            campaign_id: upload.campaign_id,
84            unit_id: upload.unit_id,
85            building_id: upload.building_id,
86            organization_id: upload.organization_id,
87            bill_period_start: upload.bill_period_start,
88            bill_period_end: upload.bill_period_end,
89            energy_type: upload.energy_type,
90            provider: upload.provider,
91            postal_code: upload.postal_code,
92            file_hash: upload.file_hash,
93            ocr_confidence: upload.ocr_confidence,
94            manually_verified: upload.manually_verified,
95            verified_at: upload.verified_at,
96            consent_timestamp: upload.consent_timestamp,
97            anonymized: upload.anonymized,
98            retention_until: upload.retention_until,
99            deleted_at: upload.deleted_at,
100            uploaded_at: upload.uploaded_at,
101            created_at: upload.created_at,
102            updated_at: upload.updated_at,
103        }
104    }
105}
106
107/// DTO for decrypted consumption (owner only)
108#[derive(Debug, Clone, Serialize, Deserialize)]
109pub struct DecryptedConsumptionResponse {
110    pub upload_id: Uuid,
111    pub total_kwh: f64, // Decrypted value
112    pub energy_type: EnergyType,
113    pub bill_period_start: DateTime<Utc>,
114    pub bill_period_end: DateTime<Utc>,
115}
116
117/// DTO for manual correction of OCR data
118#[derive(Debug, Clone, Serialize, Deserialize)]
119pub struct CorrectOcrDataRequest {
120    pub total_kwh: f64,
121    pub energy_type: Option<EnergyType>,
122    pub provider: Option<String>,
123    pub bill_period_start: Option<DateTime<Utc>>,
124    pub bill_period_end: Option<DateTime<Utc>>,
125}
126
127/// DTO for verification request (admin)
128#[derive(Debug, Clone, Serialize, Deserialize)]
129pub struct VerifyUploadRequest {
130    pub verified: bool,
131}