1use actix_web::http::StatusCode;
2use chrono::Utc;
3use uuid::Uuid;
4
5use super::drawings::{
6 DrawingDto, DrawingVariant, UpdateAddDateDrawingDto, UpdateDrawingsDto, UpdateNotesDrawingDto,
7 UpdateRemoveDateDrawingDto,
8};
9use crate::{
10 error::ServiceError,
11 model::{
12 dto::drawings::DrawingCreateDto,
13 entity::drawings::{Drawing, UpdateDrawing},
14 r#enum::drawing_shape_type::DrawingShapeType,
15 },
16};
17
18fn _internal_server_error_mismatch_json(_: serde_json::Error) -> ServiceError {
21 ServiceError::new(
22 StatusCode::INTERNAL_SERVER_ERROR,
23 "mismatch between database json and drawings properties",
24 )
25}
26
27impl TryFrom<(DrawingShapeType, serde_json::Value)> for DrawingVariant {
28 type Error = serde_json::Error;
29
30 fn try_from(value: (DrawingShapeType, serde_json::Value)) -> Result<Self, Self::Error> {
31 let (shape_type, val) = value;
32 match shape_type {
33 DrawingShapeType::Rectangle => serde_json::from_value(val).map(Self::Rectangle),
34 DrawingShapeType::Ellipse => serde_json::from_value(val).map(Self::Ellipse),
35 DrawingShapeType::FreeLine => serde_json::from_value(val).map(Self::FreeLine),
36 DrawingShapeType::BezierPolygon => serde_json::from_value(val).map(Self::BezierPolygon),
37 DrawingShapeType::LabelText => serde_json::from_value(val).map(Self::LabelText),
38 DrawingShapeType::Image => serde_json::from_value(val).map(Self::Image),
39 }
40 }
41}
42
43impl TryFrom<DrawingVariant> for (DrawingShapeType, serde_json::Value) {
44 type Error = serde_json::Error;
45
46 fn try_from(drawing_variant: DrawingVariant) -> Result<Self, Self::Error> {
47 Ok(match drawing_variant {
48 DrawingVariant::Rectangle(x) => (DrawingShapeType::Rectangle, serde_json::to_value(x)?),
49 DrawingVariant::Ellipse(x) => (DrawingShapeType::Ellipse, serde_json::to_value(x)?),
50 DrawingVariant::FreeLine(x) => (DrawingShapeType::FreeLine, serde_json::to_value(x)?),
51 DrawingVariant::BezierPolygon(x) => {
52 (DrawingShapeType::BezierPolygon, serde_json::to_value(x)?)
53 }
54 DrawingVariant::LabelText(x) => (DrawingShapeType::LabelText, serde_json::to_value(x)?),
55 DrawingVariant::Image(x) => (DrawingShapeType::Image, serde_json::to_value(x)?),
56 })
57 }
58}
59
60impl TryFrom<Drawing> for DrawingDto {
61 type Error = ServiceError;
62
63 fn try_from(drawing: Drawing) -> Result<Self, Self::Error> {
64 let drawing_variant = DrawingVariant::try_from((drawing.shape_type, drawing.properties))
65 .map_err(_internal_server_error_mismatch_json)?;
66 Ok(Self {
67 id: drawing.id,
68 variant: drawing_variant,
69 layer_id: drawing.layer_id,
70 add_date: drawing.add_date,
71 remove_date: drawing.remove_date,
72 rotation: drawing.rotation,
73 scale_x: drawing.scale_x,
74 scale_y: drawing.scale_y,
75 x: drawing.x,
76 y: drawing.y,
77 notes: drawing.notes,
78 created_at: Some(drawing.created_at),
79 modified_at: Some(drawing.modified_at),
80 created_by: Some(drawing.created_by),
81 modified_by: Some(drawing.modified_by),
82 })
83 }
84}
85
86impl TryFrom<(DrawingCreateDto, Uuid)> for Drawing {
87 type Error = ServiceError;
88
89 fn try_from((drawing_dto, user_id): (DrawingCreateDto, Uuid)) -> Result<Self, Self::Error> {
90 let (shape_type, properties) = drawing_dto
91 .variant
92 .try_into()
93 .map_err(_internal_server_error_mismatch_json)?;
94 Ok(Self {
95 id: drawing_dto.id,
96 shape_type,
97 layer_id: drawing_dto.layer_id,
98 add_date: drawing_dto.add_date,
99 remove_date: drawing_dto.remove_date,
100 rotation: drawing_dto.rotation,
101 scale_x: drawing_dto.scale_x,
102 scale_y: drawing_dto.scale_y,
103 x: drawing_dto.x,
104 y: drawing_dto.y,
105 properties,
106 notes: drawing_dto.notes,
107 created_at: Utc::now().naive_utc(),
108 modified_at: Utc::now().naive_utc(),
109 created_by: user_id,
110 modified_by: user_id,
111 })
112 }
113}
114
115impl TryFrom<(DrawingDto, Uuid)> for UpdateDrawing {
116 type Error = ServiceError;
117
118 fn try_from((drawing_dto, user_id): (DrawingDto, Uuid)) -> Result<Self, Self::Error> {
119 let (shape_type, properties) = drawing_dto
120 .variant
121 .try_into()
122 .map_err(_internal_server_error_mismatch_json)?;
123
124 Ok(Self {
125 id: drawing_dto.id,
126 shape_type: Some(shape_type),
127 layer_id: Some(drawing_dto.layer_id),
128 add_date: Some(drawing_dto.add_date),
129 remove_date: Some(drawing_dto.remove_date),
130 rotation: Some(drawing_dto.rotation),
131 scale_x: Some(drawing_dto.scale_x),
132 scale_y: Some(drawing_dto.scale_y),
133 x: Some(drawing_dto.x),
134 y: Some(drawing_dto.y),
135 properties: Some(properties),
136 notes: Some(drawing_dto.notes),
137 modified_by: Some(user_id),
138 })
139 }
140}
141
142impl From<(UpdateAddDateDrawingDto, Uuid)> for UpdateDrawing {
143 fn from((dto, user_id): (UpdateAddDateDrawingDto, Uuid)) -> Self {
144 Self {
145 id: dto.id,
146 add_date: Some(dto.add_date),
147 modified_by: Some(user_id),
148 ..Default::default()
149 }
150 }
151}
152
153impl From<(UpdateRemoveDateDrawingDto, Uuid)> for UpdateDrawing {
154 fn from((dto, user_id): (UpdateRemoveDateDrawingDto, Uuid)) -> Self {
155 Self {
156 id: dto.id,
157 modified_by: Some(user_id),
158 remove_date: Some(dto.remove_date),
159 ..Default::default()
160 }
161 }
162}
163
164impl From<(UpdateNotesDrawingDto, Uuid)> for UpdateDrawing {
165 fn from((dto, user_id): (UpdateNotesDrawingDto, Uuid)) -> Self {
166 Self {
167 id: dto.id,
168 notes: Some(dto.notes),
169 modified_by: Some(user_id),
170 ..Default::default()
171 }
172 }
173}
174
175impl TryFrom<DrawingConversion> for Vec<UpdateDrawing> {
176 type Error = ServiceError;
177
178 fn try_from(DrawingConversion(dto, user_id): DrawingConversion) -> Result<Self, Self::Error> {
179 match dto {
180 UpdateDrawingsDto::Update(vec) => vec
181 .into_iter()
182 .map(|drawing_dto| UpdateDrawing::try_from((drawing_dto, user_id)))
183 .collect(),
184 UpdateDrawingsDto::UpdateAddDate(vec) => Ok(vec
185 .into_iter()
186 .map(|update_add_date_drawing_dto| (update_add_date_drawing_dto, user_id).into())
187 .collect()),
188 UpdateDrawingsDto::UpdateRemoveDate(vec) => Ok(vec
189 .into_iter()
190 .map(|update_remove_date_drawing_dto| {
191 (update_remove_date_drawing_dto, user_id).into()
192 })
193 .collect()),
194 UpdateDrawingsDto::UpdateNotes(vec) => Ok(vec
195 .into_iter()
196 .map(|update_notes_drawing_dto| (update_notes_drawing_dto, user_id).into())
197 .collect()),
198 }
199 }
200}
201
202pub struct DrawingConversion(pub UpdateDrawingsDto, pub Uuid);