koprogo_api/application/dto/
document_dto.rs1use crate::domain::entities::{Document, DocumentType};
2use chrono::{DateTime, Utc};
3use serde::{Deserialize, Serialize};
4use uuid::Uuid;
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct DocumentResponse {
9 pub id: Uuid,
10 pub building_id: Uuid,
11 pub document_type: DocumentType,
12 pub title: String,
13 pub description: Option<String>,
14 pub file_path: String,
15 pub file_size: i64,
16 pub file_size_mb: f64,
17 pub mime_type: String,
18 pub uploaded_by: Uuid,
19 pub related_meeting_id: Option<Uuid>,
20 pub related_expense_id: Option<Uuid>,
21 pub created_at: DateTime<Utc>,
22 pub updated_at: DateTime<Utc>,
23}
24
25impl From<Document> for DocumentResponse {
26 fn from(doc: Document) -> Self {
27 let file_size_mb = doc.file_size_mb();
28 Self {
29 id: doc.id,
30 building_id: doc.building_id,
31 document_type: doc.document_type,
32 title: doc.title,
33 description: doc.description,
34 file_path: doc.file_path,
35 file_size: doc.file_size,
36 file_size_mb,
37 mime_type: doc.mime_type,
38 uploaded_by: doc.uploaded_by,
39 related_meeting_id: doc.related_meeting_id,
40 related_expense_id: doc.related_expense_id,
41 created_at: doc.created_at,
42 updated_at: doc.updated_at,
43 }
44 }
45}
46
47#[derive(Debug, Clone, Serialize, Deserialize)]
50pub struct UploadDocumentRequest {
51 #[serde(default)]
52 pub organization_id: Uuid, pub building_id: Uuid,
54 pub document_type: DocumentType,
55 pub title: String,
56 pub description: Option<String>,
57 pub uploaded_by: Uuid,
58 pub related_meeting_id: Option<Uuid>,
59 pub related_expense_id: Option<Uuid>,
60}
61
62#[derive(Debug, Clone, Serialize, Deserialize)]
64pub struct LinkDocumentToMeetingRequest {
65 pub meeting_id: Uuid,
66}
67
68#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct LinkDocumentToExpenseRequest {
71 pub expense_id: Uuid,
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77
78 #[test]
79 fn test_document_response_from_entity() {
80 let org_id = Uuid::new_v4();
81 let building_id = Uuid::new_v4();
82 let uploader_id = Uuid::new_v4();
83
84 let document = Document::new(
85 org_id,
86 building_id,
87 DocumentType::Invoice,
88 "Test Invoice".to_string(),
89 Some("Test description".to_string()),
90 "/documents/test.pdf".to_string(),
91 1048576, "application/pdf".to_string(),
93 uploader_id,
94 )
95 .unwrap();
96
97 let response = DocumentResponse::from(document.clone());
98
99 assert_eq!(response.id, document.id);
100 assert_eq!(response.title, "Test Invoice");
101 assert_eq!(response.file_size, 1048576);
102 assert_eq!(response.file_size_mb, 1.0);
103 }
104
105 #[test]
106 fn test_upload_request_serialization() {
107 let org_id = Uuid::new_v4();
108 let building_id = Uuid::new_v4();
109 let uploader_id = Uuid::new_v4();
110
111 let request = UploadDocumentRequest {
112 organization_id: org_id,
113 building_id,
114 document_type: DocumentType::Contract,
115 title: "Contrat de syndic".to_string(),
116 description: Some("Contrat annuel".to_string()),
117 uploaded_by: uploader_id,
118 related_meeting_id: None,
119 related_expense_id: None,
120 };
121
122 let json = serde_json::to_string(&request).unwrap();
123 assert!(json.contains("Contrat de syndic"));
124
125 let deserialized: UploadDocumentRequest = serde_json::from_str(&json).unwrap();
126 assert_eq!(deserialized.title, request.title);
127 }
128}