koprogo_api/application/dto/
marketplace_dto.rs

1// DTOs for Marketplace API (Issue #276)
2
3use crate::domain::entities::ServiceProvider;
4use serde::{Deserialize, Serialize};
5use validator::Validate;
6
7/// Request DTO for creating a service provider
8#[derive(Debug, Serialize, Deserialize, Validate, Clone)]
9pub struct CreateServiceProviderDto {
10    #[validate(length(min = 1, max = 200, message = "Company name must be 1-200 characters"))]
11    pub company_name: String,
12
13    pub trade_category: String, // e.g., "Plombier", "Electricien"
14
15    pub specializations: Option<Vec<String>>,
16
17    pub service_zone_postal_codes: Option<Vec<String>>,
18
19    pub certifications: Option<Vec<String>>,
20
21    pub ipi_registration: Option<String>,
22
23    pub bce_number: Option<String>,
24}
25
26/// Response DTO for service provider (public marketplace view)
27#[derive(Debug, Serialize, Deserialize, Clone)]
28pub struct ServiceProviderResponseDto {
29    pub id: String,
30    pub organization_id: String,
31    pub company_name: String,
32    pub trade_category: String,
33    pub specializations: Vec<String>,
34    pub service_zone_postal_codes: Vec<String>,
35    pub certifications: Vec<String>,
36    pub ipi_registration: Option<String>,
37    pub bce_number: Option<String>,
38    pub rating_avg: Option<f64>,
39    pub reviews_count: i32,
40    pub is_verified: bool,
41    pub public_profile_slug: String,
42    pub created_at: String,
43    pub updated_at: String,
44}
45
46/// Query parameters for searching service providers (public marketplace)
47#[derive(Debug, Deserialize, Clone)]
48pub struct SearchServiceProvidersQuery {
49    pub trade_category: Option<String>,
50    pub postal_code: Option<String>,
51    pub min_rating: Option<f64>,
52    pub is_verified_only: Option<bool>,
53}
54
55/// Request DTO for contract evaluation
56#[derive(Debug, Serialize, Deserialize, Validate, Clone)]
57pub struct CreateContractEvaluationDto {
58    pub service_provider_id: String,
59    pub quote_id: Option<String>,
60    pub ticket_id: Option<String>,
61    #[validate(length(min = 1))]
62    pub criteria: std::collections::HashMap<String, u8>,
63    pub would_recommend: bool,
64    pub comments: Option<String>,
65    pub is_anonymous: Option<bool>,
66}
67
68/// Response DTO for contract evaluation
69#[derive(Debug, Serialize, Deserialize, Clone)]
70pub struct ContractEvaluationResponseDto {
71    pub id: String,
72    pub organization_id: String,
73    pub service_provider_id: String,
74    pub evaluator_id: String,
75    pub building_id: String,
76    pub quote_id: Option<String>,
77    pub ticket_id: Option<String>,
78    pub criteria: std::collections::HashMap<String, u8>,
79    pub global_score: f64,
80    pub comments: Option<String>,
81    pub would_recommend: bool,
82    pub is_legal_evaluation: bool,
83    pub is_anonymous: bool,
84    pub created_at: String,
85}
86
87/// Response DTO for L13 annual report (contract evaluations)
88#[derive(Debug, Serialize, Deserialize, Clone)]
89pub struct ContractEvaluationsAnnualReportDto {
90    pub building_id: String,
91    pub report_year: i32,
92    pub total_evaluations: i32,
93    pub total_providers_evaluated: i32,
94    pub average_global_score: f64,
95    pub recommendation_rate: f64, // % who would recommend
96    pub evaluations: Vec<ContractEvaluationResponseDto>,
97}
98
99impl From<ServiceProvider> for ServiceProviderResponseDto {
100    fn from(provider: ServiceProvider) -> Self {
101        ServiceProviderResponseDto {
102            id: provider.id.to_string(),
103            organization_id: provider.organization_id.to_string(),
104            company_name: provider.company_name,
105            trade_category: provider.trade_category.to_sql().to_string(),
106            specializations: provider.specializations,
107            service_zone_postal_codes: provider.service_zone_postal_codes,
108            certifications: provider.certifications,
109            ipi_registration: provider.ipi_registration,
110            bce_number: provider.bce_number,
111            rating_avg: provider.rating_avg,
112            reviews_count: provider.reviews_count,
113            is_verified: provider.is_verified,
114            public_profile_slug: provider.public_profile_slug,
115            created_at: provider.created_at.to_rfc3339(),
116            updated_at: provider.updated_at.to_rfc3339(),
117        }
118    }
119}