backend/model/dto/
drawings_impl.rs

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
18/// In case of a logic bug: If the JSON in the db
19/// doesn't match `DrawingVariant`, we return 500.
20fn _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);