koprogo_api/application/dto/
skill_dto.rs1use crate::domain::entities::{ExpertiseLevel, Skill, SkillCategory};
2use serde::{Deserialize, Serialize};
3use uuid::Uuid;
4
5#[derive(Debug, Serialize, Deserialize)]
7pub struct CreateSkillDto {
8 pub building_id: Uuid,
9 pub skill_category: SkillCategory,
10 pub skill_name: String,
11 pub expertise_level: ExpertiseLevel,
12 pub description: String,
13 pub is_available_for_help: bool,
14 pub hourly_rate_credits: Option<i32>, pub years_of_experience: Option<i32>,
16 pub certifications: Option<String>,
17}
18
19#[derive(Debug, Serialize, Deserialize)]
21pub struct UpdateSkillDto {
22 pub skill_name: Option<String>,
23 pub expertise_level: Option<ExpertiseLevel>,
24 pub description: Option<String>,
25 pub is_available_for_help: Option<bool>,
26 pub hourly_rate_credits: Option<Option<i32>>,
27 pub years_of_experience: Option<Option<i32>>,
28 pub certifications: Option<Option<String>>,
29}
30
31#[derive(Debug, Serialize, Clone)]
33pub struct SkillResponseDto {
34 pub id: Uuid,
35 pub owner_id: Uuid,
36 pub owner_name: String, pub building_id: Uuid,
38 pub skill_category: SkillCategory,
39 pub skill_name: String,
40 pub expertise_level: ExpertiseLevel,
41 pub description: String,
42 pub is_available_for_help: bool,
43 pub hourly_rate_credits: Option<i32>,
44 pub years_of_experience: Option<i32>,
45 pub certifications: Option<String>,
46 pub created_at: chrono::DateTime<chrono::Utc>,
47 pub updated_at: chrono::DateTime<chrono::Utc>,
48 pub is_free: bool,
50 pub is_professional: bool,
51}
52
53impl SkillResponseDto {
54 pub fn from_skill(skill: Skill, owner_name: String) -> Self {
56 let is_free = skill.is_free();
57 let is_professional = skill.is_professional();
58
59 Self {
60 id: skill.id,
61 owner_id: skill.owner_id,
62 owner_name,
63 building_id: skill.building_id,
64 skill_category: skill.skill_category,
65 skill_name: skill.skill_name,
66 expertise_level: skill.expertise_level,
67 description: skill.description,
68 is_available_for_help: skill.is_available_for_help,
69 hourly_rate_credits: skill.hourly_rate_credits,
70 years_of_experience: skill.years_of_experience,
71 certifications: skill.certifications,
72 created_at: skill.created_at,
73 updated_at: skill.updated_at,
74 is_free,
75 is_professional,
76 }
77 }
78}
79
80#[derive(Debug, Serialize, Clone)]
82pub struct SkillSummaryDto {
83 pub id: Uuid,
84 pub owner_id: Uuid,
85 pub owner_name: String, pub building_id: Uuid,
87 pub skill_category: SkillCategory,
88 pub skill_name: String,
89 pub expertise_level: ExpertiseLevel,
90 pub is_available_for_help: bool,
91 pub hourly_rate_credits: Option<i32>,
92 pub is_free: bool,
93 pub is_professional: bool,
94}
95
96impl SkillSummaryDto {
97 pub fn from_skill(skill: Skill, owner_name: String) -> Self {
99 let is_free = skill.is_free();
100 let is_professional = skill.is_professional();
101
102 Self {
103 id: skill.id,
104 owner_id: skill.owner_id,
105 owner_name,
106 building_id: skill.building_id,
107 skill_category: skill.skill_category,
108 skill_name: skill.skill_name,
109 expertise_level: skill.expertise_level,
110 is_available_for_help: skill.is_available_for_help,
111 hourly_rate_credits: skill.hourly_rate_credits,
112 is_free,
113 is_professional,
114 }
115 }
116}
117
118#[derive(Debug, Serialize)]
120pub struct SkillStatisticsDto {
121 pub total_skills: i64,
122 pub available_skills: i64,
123 pub free_skills: i64,
124 pub paid_skills: i64,
125 pub professional_skills: i64,
126 pub skills_by_category: Vec<CategoryCount>,
127 pub skills_by_expertise: Vec<ExpertiseCount>,
128}
129
130#[derive(Debug, Serialize)]
132pub struct CategoryCount {
133 pub category: SkillCategory,
134 pub count: i64,
135}
136
137#[derive(Debug, Serialize)]
139pub struct ExpertiseCount {
140 pub level: ExpertiseLevel,
141 pub count: i64,
142}
143
144#[cfg(test)]
145mod tests {
146 use super::*;
147
148 #[test]
149 fn test_skill_response_dto_from_skill() {
150 let skill = Skill::new(
151 Uuid::new_v4(),
152 Uuid::new_v4(),
153 SkillCategory::Technology,
154 "Web Development".to_string(),
155 ExpertiseLevel::Advanced,
156 "Full-stack web development".to_string(),
157 true,
158 Some(10),
159 Some(5),
160 Some("Certified Developer".to_string()),
161 )
162 .unwrap();
163
164 let dto = SkillResponseDto::from_skill(skill.clone(), "John Doe".to_string());
165
166 assert_eq!(dto.owner_name, "John Doe");
167 assert_eq!(dto.skill_name, "Web Development");
168 assert_eq!(dto.expertise_level, ExpertiseLevel::Advanced);
169 assert!(!dto.is_free);
170 assert!(dto.is_professional);
171 }
172
173 #[test]
174 fn test_skill_summary_dto_from_skill() {
175 let skill = Skill::new(
176 Uuid::new_v4(),
177 Uuid::new_v4(),
178 SkillCategory::Gardening,
179 "Gardening".to_string(),
180 ExpertiseLevel::Beginner,
181 "Basic gardening".to_string(),
182 true,
183 None,
184 Some(1),
185 None,
186 )
187 .unwrap();
188
189 let dto = SkillSummaryDto::from_skill(skill.clone(), "Jane Smith".to_string());
190
191 assert_eq!(dto.owner_name, "Jane Smith");
192 assert_eq!(dto.skill_name, "Gardening");
193 assert!(dto.is_free);
194 assert!(!dto.is_professional);
195 }
196}