backend/model/dto/
areas_impl.rs

1//! Contains the implementations related to [`AreaDto`].
2
3use reqwest::StatusCode;
4
5use crate::{
6    error::ServiceError,
7    model::{
8        dto::areas::{AreaDto, AreaKind, AreaType, AreaUpdate, NewAreaDto, UpdateAreaDto},
9        entity::areas::{
10            Hydrology, Shading, SoilTexture, UpdateHydrology, UpdateShading, UpdateSoilTexture,
11        },
12    },
13};
14
15// From AreaDto => entity
16
17impl From<Shading> for AreaDto {
18    fn from(entity: Shading) -> Self {
19        Self {
20            id: entity.id,
21            layer_id: entity.layer_id,
22            area_type: AreaType::Shade(entity.shade),
23            geometry: entity.geometry,
24            add_date: entity.add_date,
25            remove_date: entity.remove_date,
26            notes: entity.notes,
27        }
28    }
29}
30
31impl From<Hydrology> for AreaDto {
32    fn from(entity: Hydrology) -> Self {
33        Self {
34            id: entity.id,
35            layer_id: entity.layer_id,
36            area_type: AreaType::Hydrology(entity.water_requirement),
37            geometry: entity.geometry,
38            add_date: entity.add_date,
39            remove_date: entity.remove_date,
40            notes: entity.notes,
41        }
42    }
43}
44
45impl From<SoilTexture> for AreaDto {
46    fn from(entity: SoilTexture) -> Self {
47        Self {
48            id: entity.id,
49            layer_id: entity.layer_id,
50            area_type: AreaType::SoilTexture(entity.soil_texture),
51            geometry: entity.geometry,
52            add_date: entity.add_date,
53            remove_date: entity.remove_date,
54            notes: entity.notes,
55        }
56    }
57}
58
59/// Error message when invalid area types are supplied.
60const INVALID_AREA_TYPE: &str = "invalid area type";
61
62/// Maps `NewAreaDto`s to `Shading`s.
63/// Precondition is that all `dtos` have `area_type == AreaType::Shade(_)`.
64///
65/// # Errors
66/// * Returns an error if any `dtos` have a different `area_type`.
67pub fn from_new_area_dto_to_shading(dtos: Vec<NewAreaDto>) -> Result<Vec<Shading>, ServiceError> {
68    dtos.into_iter()
69        .map(|dto| match dto.area_type {
70            AreaType::Shade(shade) => Ok(Shading {
71                id: dto.id,
72                layer_id: dto.layer_id,
73                shade,
74                geometry: dto.geometry,
75                add_date: dto.add_date,
76                remove_date: None,
77                notes: String::new(),
78            }),
79            _ => Err(ServiceError::new(
80                StatusCode::BAD_REQUEST,
81                INVALID_AREA_TYPE,
82            )),
83        })
84        .collect()
85}
86
87/// Maps `NewAreaDto`s to `Hydrology`s.
88/// Precondition is that all `dtos` have `area_type == AreaType::Hydrology(_)`.
89///
90/// # Errors
91/// * Returns an error if any `dtos` have a different `area_type`.
92pub fn from_new_area_dto_to_hydrology(
93    dtos: Vec<NewAreaDto>,
94) -> Result<Vec<Hydrology>, ServiceError> {
95    dtos.into_iter()
96        .map(|dto| match dto.area_type {
97            AreaType::Hydrology(water_requirement) => Ok(Hydrology {
98                id: dto.id,
99                layer_id: dto.layer_id,
100                water_requirement,
101                geometry: dto.geometry,
102                add_date: dto.add_date,
103                remove_date: None,
104                notes: String::new(),
105            }),
106            _ => Err(ServiceError::new(
107                StatusCode::BAD_REQUEST,
108                INVALID_AREA_TYPE,
109            )),
110        })
111        .collect()
112}
113
114/// Maps `NewAreaDto`s to `SoilTexture`s.
115/// Precondition is that all `dtos` have `area_type == AreaType::SoilTexture(_)`.
116///
117/// # Errors
118/// * Returns an error if any `dtos` have a different `area_type`.
119pub fn from_new_area_dto_to_soil_texture(
120    dtos: Vec<NewAreaDto>,
121) -> Result<Vec<SoilTexture>, ServiceError> {
122    dtos.into_iter()
123        .map(|dto| match dto.area_type {
124            AreaType::SoilTexture(soil_texture) => Ok(SoilTexture {
125                id: dto.id,
126                layer_id: dto.layer_id,
127                soil_texture,
128                geometry: dto.geometry,
129                add_date: dto.add_date,
130                remove_date: None,
131                notes: String::new(),
132            }),
133            _ => Err(ServiceError::new(
134                StatusCode::BAD_REQUEST,
135                INVALID_AREA_TYPE,
136            )),
137        })
138        .collect()
139}
140
141/// Maps `UpdateAreaDto` to `UpdateShading`s.
142/// Precondition is that the `dto` has `area_kind == AreaKind::Shade`.
143///
144/// # Errors
145/// * Returns an error if the `dto` has a different `area_kind`.
146pub fn from_update_area_dto_to_update_shading(
147    dto: UpdateAreaDto,
148) -> Result<Vec<UpdateShading>, ServiceError> {
149    if dto.area_kind == AreaKind::Shade {
150        match dto.update {
151            AreaUpdate::UpdateValue(geometry_vec) => Ok(geometry_vec
152                .into_iter()
153                .map(|v| UpdateShading {
154                    id: v.id,
155                    shade: match v.area_type {
156                        AreaType::Shade(shade) => Some(shade),
157                        _ => None,
158                    },
159                    ..Default::default()
160                })
161                .collect()),
162            AreaUpdate::UpdateAddDate(add_date_vec) => Ok(add_date_vec
163                .into_iter()
164                .map(|v| UpdateShading {
165                    id: v.id,
166                    add_date: Some(v.add_date),
167                    ..Default::default()
168                })
169                .collect()),
170            AreaUpdate::UpdateRemoveDate(remove_date_vec) => Ok(remove_date_vec
171                .into_iter()
172                .map(|v| UpdateShading {
173                    id: v.id,
174                    remove_date: Some(v.remove_date),
175                    ..Default::default()
176                })
177                .collect()),
178            AreaUpdate::UpdateNotes(notes_vec) => Ok(notes_vec
179                .into_iter()
180                .map(|v| UpdateShading {
181                    id: v.id,
182                    notes: Some(v.notes),
183                    ..Default::default()
184                })
185                .collect()),
186        }
187    } else {
188        Err(ServiceError::new(
189            StatusCode::BAD_REQUEST,
190            INVALID_AREA_TYPE,
191        ))
192    }
193}
194
195/// Maps `UpdateAreaDto` to `UpdateHydrology`s.
196/// Precondition is that the `dto` has `area_kind == AreaKind::Hydrology`.
197///
198/// # Errors
199/// * Returns an error if the `dto` has a different `area_kind`.
200pub fn from_update_area_dto_to_update_hydrology(
201    dto: UpdateAreaDto,
202) -> Result<Vec<UpdateHydrology>, ServiceError> {
203    if dto.area_kind == AreaKind::Hydrology {
204        match dto.update {
205            AreaUpdate::UpdateValue(geometry_vec) => Ok(geometry_vec
206                .into_iter()
207                .map(|v| UpdateHydrology {
208                    id: v.id,
209                    water_requirement: match v.area_type {
210                        AreaType::Hydrology(water_requirement) => Some(water_requirement),
211                        _ => None,
212                    },
213                    ..Default::default()
214                })
215                .collect()),
216            AreaUpdate::UpdateAddDate(add_date_vec) => Ok(add_date_vec
217                .into_iter()
218                .map(|v| UpdateHydrology {
219                    id: v.id,
220                    add_date: Some(v.add_date),
221                    ..Default::default()
222                })
223                .collect()),
224            AreaUpdate::UpdateRemoveDate(remove_date_vec) => Ok(remove_date_vec
225                .into_iter()
226                .map(|v| UpdateHydrology {
227                    id: v.id,
228                    remove_date: Some(v.remove_date),
229                    ..Default::default()
230                })
231                .collect()),
232            AreaUpdate::UpdateNotes(notes_vec) => Ok(notes_vec
233                .into_iter()
234                .map(|v| UpdateHydrology {
235                    id: v.id,
236                    notes: Some(v.notes),
237                    ..Default::default()
238                })
239                .collect()),
240        }
241    } else {
242        Err(ServiceError::new(
243            StatusCode::BAD_REQUEST,
244            INVALID_AREA_TYPE,
245        ))
246    }
247}
248
249/// Maps `UpdateAreaDto` to `UpdateSoilTexture`s.
250/// Precondition is that the `dto` has `area_kind == AreaKind::SoilTexture`.
251///
252/// # Errors
253/// * Returns an error if the `dto` has a different `area_kind`.
254pub fn from_update_area_dto_to_update_soil_texture(
255    dto: UpdateAreaDto,
256) -> Result<Vec<UpdateSoilTexture>, ServiceError> {
257    if dto.area_kind == AreaKind::SoilTexture {
258        match dto.update {
259            AreaUpdate::UpdateValue(geometry_vec) => Ok(geometry_vec
260                .into_iter()
261                .map(|v| UpdateSoilTexture {
262                    id: v.id,
263                    soil_texture: match v.area_type {
264                        AreaType::SoilTexture(soil_texture) => Some(soil_texture),
265                        _ => None,
266                    },
267                    ..Default::default()
268                })
269                .collect()),
270            AreaUpdate::UpdateAddDate(add_date_vec) => Ok(add_date_vec
271                .into_iter()
272                .map(|v| UpdateSoilTexture {
273                    id: v.id,
274                    add_date: Some(v.add_date),
275                    ..Default::default()
276                })
277                .collect()),
278            AreaUpdate::UpdateRemoveDate(remove_date_vec) => Ok(remove_date_vec
279                .into_iter()
280                .map(|v| UpdateSoilTexture {
281                    id: v.id,
282                    remove_date: Some(v.remove_date),
283                    ..Default::default()
284                })
285                .collect()),
286            AreaUpdate::UpdateNotes(notes_vec) => Ok(notes_vec
287                .into_iter()
288                .map(|v| UpdateSoilTexture {
289                    id: v.id,
290                    notes: Some(v.notes),
291                    ..Default::default()
292                })
293                .collect()),
294        }
295    } else {
296        Err(ServiceError::new(
297            StatusCode::BAD_REQUEST,
298            INVALID_AREA_TYPE,
299        ))
300    }
301}