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::{
13            drawing_variant_impl::{ConversionError, DrawingVariantEntity},
14            drawings::DrawingCreateDto,
15        },
16        entity::drawings::{Drawing, UpdateDrawing},
17        r#enum::drawing_shape_type::DrawingShapeType,
18    },
19};
20
21/// In case of a logic bug: If the JSON in the db
22/// doesn't match `DrawingVariant`, we return 500.
23fn _internal_server_error_mismatch_json(_: ConversionError) -> ServiceError {
24    ServiceError::new(
25        StatusCode::INTERNAL_SERVER_ERROR,
26        "Error while converting from database",
27    )
28}
29
30impl TryFrom<(Uuid, DrawingVariant)> for DrawingVariantEntity {
31    type Error = ConversionError;
32
33    fn try_from((drawing_id, variant): (Uuid, DrawingVariant)) -> Result<Self, Self::Error> {
34        Ok(match variant {
35            DrawingVariant::Rectangle(dto) => Self::Rectangle((drawing_id, dto).into()),
36
37            DrawingVariant::Ellipse(dto) => Self::Ellipse((drawing_id, dto).into()),
38
39            DrawingVariant::FreeLine(dto) => Self::FreeLine((drawing_id, dto).try_into()?),
40
41            DrawingVariant::BezierPolygon(dto) => {
42                Self::BezierPolygon((drawing_id, dto).try_into()?)
43            }
44
45            DrawingVariant::LabelText(dto) => Self::LabelText((drawing_id, dto).into()),
46
47            DrawingVariant::Image(dto) => Self::Image((drawing_id, dto).into()),
48        })
49    }
50}
51
52impl TryFrom<DrawingVariantEntity> for DrawingVariant {
53    type Error = ConversionError;
54    fn try_from(value: DrawingVariantEntity) -> Result<Self, Self::Error> {
55        match value {
56            DrawingVariantEntity::Rectangle(x) => Ok(Self::Rectangle(x.into())),
57            DrawingVariantEntity::Ellipse(x) => Ok(Self::Ellipse(x.into())),
58            DrawingVariantEntity::FreeLine(x) => Ok(Self::FreeLine(x.into())),
59            DrawingVariantEntity::BezierPolygon(x) => Ok(Self::BezierPolygon(x.into())),
60            DrawingVariantEntity::LabelText(x) => Ok(Self::LabelText(x.into())),
61            DrawingVariantEntity::Image(x) => Ok(Self::Image(x.into())),
62        }
63    }
64}
65
66impl TryFrom<DrawingVariantWithId> for (DrawingShapeType, DrawingVariantEntity) {
67    type Error = ConversionError;
68    fn try_from(variant_id: DrawingVariantWithId) -> Result<Self, Self::Error> {
69        let drawing_variant = variant_id.drawing_variant;
70        let drawing_id = variant_id.id;
71
72        Ok(match &drawing_variant {
73            DrawingVariant::Rectangle(_x) => (
74                DrawingShapeType::Rectangle,
75                (drawing_id, drawing_variant).try_into()?,
76            ),
77            DrawingVariant::Ellipse(_x) => (
78                DrawingShapeType::Ellipse,
79                (drawing_id, drawing_variant).try_into()?,
80            ),
81            DrawingVariant::FreeLine(_x) => (
82                DrawingShapeType::FreeLine,
83                (drawing_id, drawing_variant).try_into()?,
84            ),
85            DrawingVariant::BezierPolygon(_x) => (
86                DrawingShapeType::BezierPolygon,
87                (drawing_id, drawing_variant).try_into()?,
88            ),
89            DrawingVariant::LabelText(_x) => (
90                DrawingShapeType::LabelText,
91                (drawing_id, drawing_variant).try_into()?,
92            ),
93            DrawingVariant::Image(_x) => (
94                DrawingShapeType::Image,
95                (drawing_id, drawing_variant).try_into()?,
96            ),
97        })
98    }
99}
100
101impl TryFrom<DrawingWithProps> for DrawingDto {
102    type Error = ServiceError;
103
104    fn try_from(drawing: DrawingWithProps) -> Result<Self, Self::Error> {
105        let drawing_variant = DrawingVariant::try_from(drawing.variants)
106            .map_err(_internal_server_error_mismatch_json)?;
107        Ok(Self {
108            id: drawing.drawing.id,
109            variant: drawing_variant,
110            layer_id: drawing.drawing.layer_id,
111            add_date: drawing.drawing.add_date,
112            remove_date: drawing.drawing.remove_date,
113            rotation: drawing.drawing.rotation,
114            scale_x: drawing.drawing.scale_x,
115            scale_y: drawing.drawing.scale_y,
116            x: drawing.drawing.x,
117            y: drawing.drawing.y,
118            notes: drawing.drawing.notes,
119            created_at: Some(drawing.drawing.created_at),
120            modified_at: Some(drawing.drawing.modified_at),
121            created_by: Some(drawing.drawing.created_by),
122            modified_by: Some(drawing.drawing.modified_by),
123        })
124    }
125}
126impl TryFrom<(DrawingCreateDto, Uuid)> for DrawingWithProps {
127    type Error = ServiceError;
128    fn try_from((drawing_dto, user_id): (DrawingCreateDto, Uuid)) -> Result<Self, Self::Error> {
129        let (shape_type, properties) = DrawingVariantWithId {
130            drawing_variant: drawing_dto.variant,
131            id: drawing_dto.id,
132        }
133        .try_into()
134        .map_err(_internal_server_error_mismatch_json)?;
135        let drawing = Drawing {
136            id: drawing_dto.id,
137            shape_type,
138            layer_id: drawing_dto.layer_id,
139            add_date: drawing_dto.add_date,
140            remove_date: drawing_dto.remove_date,
141            rotation: drawing_dto.rotation,
142            scale_x: drawing_dto.scale_x,
143            scale_y: drawing_dto.scale_y,
144            x: drawing_dto.x,
145            y: drawing_dto.y,
146            notes: drawing_dto.notes,
147            created_at: Utc::now().naive_utc(),
148            modified_at: Utc::now().naive_utc(),
149            created_by: user_id,
150            modified_by: user_id,
151        };
152
153        Ok(Self {
154            drawing,
155            variants: properties,
156        })
157    }
158}
159impl TryFrom<(DrawingDto, Uuid)> for UpdateDrawingWithProps {
160    type Error = ServiceError;
161    fn try_from((drawing_dto, user_id): (DrawingDto, Uuid)) -> Result<Self, Self::Error> {
162        let (shape_type, properties) = DrawingVariantWithId {
163            drawing_variant: drawing_dto.variant,
164            id: drawing_dto.id,
165        }
166        .try_into()
167        .map_err(_internal_server_error_mismatch_json)?;
168        Ok(Self {
169            update_drawing: UpdateDrawing {
170                id: drawing_dto.id,
171                shape_type: Some(shape_type),
172                layer_id: Some(drawing_dto.layer_id),
173                add_date: Some(drawing_dto.add_date),
174                remove_date: Some(drawing_dto.remove_date),
175                rotation: Some(drawing_dto.rotation),
176                scale_x: Some(drawing_dto.scale_x),
177                scale_y: Some(drawing_dto.scale_y),
178                x: Some(drawing_dto.x),
179                y: Some(drawing_dto.y),
180                notes: Some(drawing_dto.notes),
181                modified_by: Some(user_id),
182            },
183            properties: Some(properties),
184        })
185    }
186}
187
188impl From<(UpdateAddDateDrawingDto, Uuid)> for UpdateDrawingWithProps {
189    fn from((dto, user_id): (UpdateAddDateDrawingDto, Uuid)) -> Self {
190        Self {
191            update_drawing: UpdateDrawing {
192                id: dto.id,
193                add_date: Some(dto.add_date),
194                modified_by: Some(user_id),
195                ..Default::default()
196            },
197            properties: None,
198        }
199    }
200}
201
202impl From<(UpdateRemoveDateDrawingDto, Uuid)> for UpdateDrawingWithProps {
203    fn from((dto, user_id): (UpdateRemoveDateDrawingDto, Uuid)) -> Self {
204        Self {
205            update_drawing: UpdateDrawing {
206                id: dto.id,
207                remove_date: Some(dto.remove_date),
208                modified_by: Some(user_id),
209                ..Default::default()
210            },
211            properties: None,
212        }
213    }
214}
215
216impl From<(UpdateNotesDrawingDto, Uuid)> for UpdateDrawingWithProps {
217    fn from((dto, user_id): (UpdateNotesDrawingDto, Uuid)) -> Self {
218        Self {
219            update_drawing: UpdateDrawing {
220                id: dto.id,
221                notes: Some(dto.notes),
222                modified_by: Some(user_id),
223                ..Default::default()
224            },
225            properties: None,
226        }
227    }
228}
229impl TryFrom<DrawingConversion> for Vec<UpdateDrawingWithProps> {
230    type Error = ServiceError;
231
232    fn try_from(DrawingConversion(dto, user_id): DrawingConversion) -> Result<Self, Self::Error> {
233        match dto {
234            UpdateDrawingsDto::Update(vec) => vec
235                .into_iter()
236                .map(|drawing_dto| UpdateDrawingWithProps::try_from((drawing_dto, user_id)))
237                .collect(),
238            UpdateDrawingsDto::UpdateAddDate(vec) => Ok(vec
239                .into_iter()
240                .map(|drawing_dto| (drawing_dto, user_id).into())
241                .collect()),
242            UpdateDrawingsDto::UpdateRemoveDate(vec) => Ok(vec
243                .into_iter()
244                .map(|drawing_dto| (drawing_dto, user_id).into())
245                .collect()),
246            UpdateDrawingsDto::UpdateNotes(vec) => Ok(vec
247                .into_iter()
248                .map(|drawing_dto| (drawing_dto, user_id).into())
249                .collect()),
250        }
251    }
252}
253pub struct DrawingConversion(pub UpdateDrawingsDto, pub Uuid);
254pub struct DrawingVariantWithId {
255    pub drawing_variant: DrawingVariant,
256    pub id: Uuid,
257}
258pub struct DrawingWithProps {
259    pub drawing: Drawing,
260    pub variants: DrawingVariantEntity,
261}
262pub struct UpdateDrawingWithProps {
263    pub update_drawing: UpdateDrawing,
264    pub properties: Option<DrawingVariantEntity>,
265}