backend/model/
dto.rs

1//! DTOs of `PermaplanT`.
2#![allow(clippy::module_name_repetitions)] // There needs to be a difference between DTOs and entities otherwise imports will be messy.
3
4use chrono::{NaiveDate, NaiveDateTime};
5use postgis_diesel::types::{Point, Polygon};
6use serde::{Deserialize, Serialize};
7use typeshare::typeshare;
8use utoipa::{IntoParams, ToSchema};
9use uuid::Uuid;
10
11use self::layers::LayerDto;
12
13use super::r#enum::{
14    herbaceous_or_woody::HerbaceousOrWoody, include_archived_seeds::IncludeArchivedSeeds,
15    life_cycle::LifeCycle, privacy_access_control::PrivacyAccessControl, quality::Quality,
16    quantity::Quantity, spatial_relation_type::SpatialRelationType,
17};
18
19pub mod actions;
20pub mod application_settings_impl;
21pub mod areas;
22pub mod areas_impl;
23pub mod base_layer_images;
24pub mod base_layer_images_impl;
25pub mod coordinates_impl;
26pub mod core;
27pub mod drawing_variant_impl;
28pub mod drawings;
29pub mod drawings_impl;
30pub mod guided_tours_impl;
31pub mod layer_impl;
32pub mod layers;
33pub mod map_collaborator_impl;
34pub mod map_impl;
35pub mod new_map_collaborator_impl;
36pub mod new_map_impl;
37pub mod new_seed_impl;
38pub mod page_impl;
39pub mod plantings;
40pub mod plantings_impl;
41pub mod plants_impl;
42pub mod seed_impl;
43pub mod timeline;
44pub mod update_map_geometry_impl;
45pub mod update_map_impl;
46
47/// Contains configuration the frontend needs to run.
48#[typeshare]
49#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, ToSchema)]
50pub struct ConfigDto {
51    /// The base URL of the authorization server
52    pub issuer_uri: String,
53    /// The `client_id` the frontend should use to log in
54    pub client_id: String,
55    /// The version must be an exact match between frontend and backend.
56    pub version: String,
57}
58
59/// Represents seeds of a user.
60#[typeshare]
61#[derive(Serialize, Deserialize, ToSchema)]
62pub struct SeedDto {
63    /// The record id of the seed.
64    pub id: i32,
65    /// An additional name for the seed.
66    pub name: String,
67    /// The id of the plant this seed belongs to.
68    #[serde(skip_serializing_if = "Option::is_none")]
69    pub plant_id: Option<i32>,
70    /// When the seeds were harvested.
71    pub harvest_year: i16,
72    /// How many seeds there are.
73    pub quantity: Quantity,
74    /// When the seeds should be used by.
75    #[serde(skip_serializing_if = "Option::is_none")]
76    pub use_by: Option<NaiveDate>,
77    /// Where the seeds came from.
78    #[serde(skip_serializing_if = "Option::is_none")]
79    pub origin: Option<String>,
80    /// What the seeds taste like.
81    #[serde(skip_serializing_if = "Option::is_none")]
82    pub taste: Option<String>,
83    /// The yield of the seeds.
84    #[serde(skip_serializing_if = "Option::is_none")]
85    pub yield_: Option<String>,
86    /// How many generations the seeds have been grown.
87    #[serde(skip_serializing_if = "Option::is_none")]
88    pub generation: Option<i16>,
89    /// The quality of the seeds.
90    #[serde(skip_serializing_if = "Option::is_none")]
91    pub quality: Option<Quality>,
92    /// How much the seeds cost.
93    #[serde(skip_serializing_if = "Option::is_none")]
94    pub price: Option<i16>,
95    /// Notes about the seeds.
96    #[serde(skip_serializing_if = "Option::is_none")]
97    pub notes: Option<String>,
98    /// The id of the creator of the seed.
99    pub created_by: Uuid,
100    /// Timestamp indicating when the seed was archived.
101    /// Empty if the seed was not archived.
102    #[serde(skip_serializing_if = "Option::is_none")]
103    pub archived_at: Option<String>,
104}
105
106#[allow(clippy::missing_docs_in_private_items)] // TODO: See #97.
107#[typeshare]
108#[derive(Serialize, Deserialize, ToSchema)]
109pub struct NewSeedDto {
110    pub name: String,
111    #[serde(skip_serializing_if = "Option::is_none")]
112    pub plant_id: Option<i32>,
113    pub harvest_year: i16,
114    pub quantity: Quantity,
115    #[serde(skip_serializing_if = "Option::is_none")]
116    pub use_by: Option<NaiveDate>,
117    #[serde(skip_serializing_if = "Option::is_none")]
118    pub origin: Option<String>,
119    #[serde(skip_serializing_if = "Option::is_none")]
120    pub taste: Option<String>,
121    #[serde(skip_serializing_if = "Option::is_none")]
122    pub yield_: Option<String>,
123    #[serde(skip_serializing_if = "Option::is_none")]
124    pub generation: Option<i16>,
125    #[serde(skip_serializing_if = "Option::is_none")]
126    pub quality: Option<Quality>,
127    #[serde(skip_serializing_if = "Option::is_none")]
128    pub price: Option<i16>,
129    #[serde(skip_serializing_if = "Option::is_none")]
130    pub notes: Option<String>,
131}
132
133/// Data that is required when archiving a seed.
134#[typeshare]
135#[derive(Serialize, Deserialize, ToSchema)]
136pub struct ArchiveSeedDto {
137    /// Whether the seed should be archived.
138    pub archived: bool,
139}
140
141/// The essential identifying information of a plant.
142#[typeshare]
143#[derive(Debug, Serialize, PartialEq, Eq, Deserialize, ToSchema)]
144pub struct PlantsSummaryDto {
145    /// The plants database id.
146    pub id: i32,
147    /// Biological name of this plant (E.g. "Triticum aestivum", "Prunus cerasus")
148    pub unique_name: String,
149    /// A list of common english names (E.g. "Bread wheat", "Sour cherry")
150    #[serde(skip_serializing_if = "Option::is_none")]
151    pub common_name_en: Option<Vec<Option<String>>>,
152    /// A list of common german names (E.g. "Brotweizen", "Sauerkirsche")
153    #[serde(skip_serializing_if = "Option::is_none")]
154    pub common_name_de: Option<Vec<Option<String>>>,
155    /// How far a plant spreads (The 'width' of a plant) in cm
156    #[serde(skip_serializing_if = "Option::is_none")]
157    pub spread: Option<i32>,
158    /// Indicates life span of the plant.
159    pub life_cycle: Vec<LifeCycle>,
160    /// Informs about the plants physiology.
161    #[serde(skip_serializing_if = "Option::is_none")]
162    pub herbaceous_or_woody: Option<HerbaceousOrWoody>,
163    #[serde(skip_serializing_if = "Option::is_none")]
164    pub has_drought_tolerance: Option<bool>,
165    #[serde(skip_serializing_if = "Option::is_none")]
166    pub hardiness_zone: Option<String>,
167    #[serde(skip_serializing_if = "Option::is_none")]
168    pub functions: Option<String>,
169    #[serde(skip_serializing_if = "Option::is_none")]
170    pub edible: Option<bool>,
171    pub edible_parts: Vec<Option<String>>,
172    #[serde(skip_serializing_if = "Option::is_none")]
173    pub warning: Option<String>,
174    pub sowing_outdoors: Vec<Option<i16>>,
175    pub harvest_time: Vec<Option<i16>>,
176    pub icon_path: Option<String>,
177}
178
179/// Query parameters for searching plants.
180#[typeshare]
181#[derive(Debug, Deserialize, IntoParams)]
182pub struct PlantsSearchParameters {
183    /// The system will check if this string occurs in the plants common name or unique name.
184    #[serde(skip_serializing_if = "Option::is_none")]
185    pub name: Option<String>,
186}
187
188/// Query parameters for searching spatial plant relations.
189#[typeshare]
190#[derive(Debug, Deserialize, IntoParams)]
191pub struct RelationSearchParameters {
192    /// The id of the plant to find relations for.
193    pub plant_id: i32,
194}
195
196/// Use to return spatial relations for the plant.
197#[typeshare]
198#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
199pub struct RelationsDto {
200    /// The id of the plant in the relation.
201    pub id: i32,
202    /// The type of relation.
203    pub relations: Vec<RelationDto>,
204}
205
206/// Use to return a spatial relation.
207#[typeshare]
208#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
209pub struct RelationDto {
210    /// The id of the plant in the relation.
211    pub id: i32,
212    /// The type of relation.
213    pub relation: SpatialRelationType,
214}
215
216/// Query parameters for searching seeds.
217#[typeshare]
218#[derive(Debug, Deserialize, IntoParams)]
219pub struct SeedSearchParameters {
220    /// Name of the seed to search for.
221    #[serde(skip_serializing_if = "Option::is_none")]
222    pub name: Option<String>,
223    /// The exact harvest year of the seed.
224    #[serde(skip_serializing_if = "Option::is_none")]
225    pub harvest_year: Option<i16>,
226    /// Whether archived, not archived or both kinds of seeds should be included.
227    /// If no value is provided, a default value of `NotArchived` is assumed.
228    #[serde(skip_serializing_if = "Option::is_none")]
229    pub archived: Option<IncludeArchivedSeeds>,
230}
231
232/// Query parameters paginating list endpoints.
233#[typeshare]
234#[derive(Debug, Deserialize, IntoParams)]
235pub struct PageParameters {
236    /// Number of results in per page.
237    #[serde(skip_serializing_if = "Option::is_none")]
238    pub per_page: Option<i32>,
239    /// Page number to be returned.
240    /// Note: pages start at one.
241    #[serde(skip_serializing_if = "Option::is_none")]
242    pub page: Option<i32>,
243}
244
245/// A page of results returned from a list endpoint.
246#[typeshare]
247#[derive(Debug, Serialize, PartialEq, Eq, Deserialize, ToSchema)]
248#[aliases(
249    PagePlantsSummaryDto = Page<PlantsSummaryDto>,
250    PageSeedDto = Page<SeedDto>,
251    PageMapDto = Page<MapDto>,
252    PageLayerDto = Page<LayerDto>
253)]
254pub struct Page<T> {
255    /// Resulting records.
256    pub results: Vec<T>,
257    /// Current page number.
258    pub page: i32,
259    /// Results per page.
260    pub per_page: i32,
261    /// Number of pages in total.
262    pub total_pages: i32,
263}
264
265/// The whole information of a map.
266#[typeshare]
267#[derive(Serialize, Deserialize, ToSchema)]
268pub struct MapDto {
269    /// The id of the map.
270    pub id: i32,
271    /// The name of the map.
272    pub name: String,
273    /// When the map was created.
274    pub created_at: NaiveDateTime,
275    /// When a map was last modified, e.g by modifying plantings.
276    pub modified_at: NaiveDateTime,
277    /// The id of the creator of the map.
278    pub created_by: Uuid,
279    /// By whom the map was last modified.
280    pub modified_by: Uuid,
281    /// The date the map is supposed to be deleted.
282    #[serde(skip_serializing_if = "Option::is_none")]
283    pub deletion_date: Option<NaiveDate>,
284    /// The date the last time the map view was opened by any user.
285    #[serde(skip_serializing_if = "Option::is_none")]
286    pub last_visit: Option<NaiveDate>,
287    /// A flag indicating if this map is marked for deletion.
288    pub is_inactive: bool,
289    /// The zoom factor of the map.
290    pub zoom_factor: i16,
291    /// An enum indicating if this map is private or not.
292    pub privacy: PrivacyAccessControl,
293    /// The description of the map.
294    #[serde(skip_serializing_if = "Option::is_none")]
295    pub description: Option<String>,
296    /// The location of the map as a latitude/longitude point.
297    #[serde(skip_serializing_if = "Option::is_none")]
298    pub location: Option<Coordinates>,
299    /// The geometry of the map.
300    ///
301    /// E.g. `{"rings": [[{"x": 0.0,"y": 0.0},{"x": 1000.0,"y": 0.0},{"x": 1000.0,"y": 1000.0},{"x": 0.0,"y": 1000.0},{"x": 0.0,"y": 0.0}]],"srid": 4326}`
302    #[typeshare(serialized_as = "object")]
303    #[schema(value_type = Object)]
304    pub geometry: Polygon<Point>,
305}
306
307/// The information of a map necessary for its creation.
308#[typeshare]
309#[derive(Serialize, Deserialize, ToSchema)]
310pub struct NewMapDto {
311    /// The name of the map.
312    pub name: String,
313    /// The date the map is supposed to be deleted.
314    #[serde(skip_serializing_if = "Option::is_none")]
315    pub deletion_date: Option<NaiveDate>,
316    /// The date the last time the map view was opened by any user.
317    #[serde(skip_serializing_if = "Option::is_none")]
318    pub last_visit: Option<NaiveDate>,
319    /// A flag indicating if this map is marked for deletion.
320    pub is_inactive: bool,
321    /// The zoom factor of the map.
322    pub zoom_factor: i16,
323    /// An enum indicating if this map is private or not.
324    pub privacy: PrivacyAccessControl,
325    /// The description of the map.
326    #[serde(skip_serializing_if = "Option::is_none")]
327    pub description: Option<String>,
328    /// The location of the map as a latitude/longitude point.
329    #[serde(skip_serializing_if = "Option::is_none")]
330    pub location: Option<Coordinates>,
331    /// The geometry of the map.
332    ///
333    /// E.g. `{"rings": [[{"x": 0.0,"y": 0.0},{"x": 1000.0,"y": 0.0},{"x": 1000.0,"y": 1000.0},{"x": 0.0,"y": 1000.0},{"x": 0.0,"y": 0.0}]],"srid": 4326}`
334    #[typeshare(serialized_as = "object")]
335    #[schema(value_type = Object)]
336    pub geometry: Polygon<Point>,
337}
338
339/// The information for updating a map.
340#[typeshare]
341#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
342pub struct UpdateMapDto {
343    /// The name of the map.
344    #[serde(skip_serializing_if = "Option::is_none")]
345    pub name: Option<String>,
346    /// An enum indicating if this map is private or not.
347    #[serde(skip_serializing_if = "Option::is_none")]
348    pub privacy: Option<PrivacyAccessControl>,
349    /// The description of the map.
350    #[serde(skip_serializing_if = "Option::is_none")]
351    pub description: Option<String>,
352    /// The location of the map as a latitude/longitude point.
353    #[serde(skip_serializing_if = "Option::is_none")]
354    pub location: Option<Coordinates>,
355}
356
357/// Data for updating a maps geometry.
358#[typeshare]
359#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
360pub struct UpdateMapGeometryDto {
361    /// The geometry of the map.
362    ///
363    /// E.g. `{"rings": [[{"x": 0.0,"y": 0.0},{"x": 1000.0,"y": 0.0},{"x": 1000.0,"y": 1000.0},{"x": 0.0,"y": 1000.0},{"x": 0.0,"y": 0.0}]],"srid": 4326}`
364    #[typeshare(serialized_as = "object")]
365    #[schema(value_type = Object)]
366    pub geometry: Polygon<Point>,
367}
368
369/// Query parameters for searching maps.
370#[typeshare]
371#[derive(Debug, Deserialize, IntoParams)]
372pub struct MapSearchParameters {
373    /// Name of the map to search for.
374    #[serde(skip_serializing_if = "Option::is_none")]
375    pub name: Option<String>,
376    /// Whether or not the map is active.
377    #[serde(skip_serializing_if = "Option::is_none")]
378    pub is_inactive: Option<bool>,
379    /// The creator of the map.
380    #[serde(skip_serializing_if = "Option::is_none")]
381    pub created_by: Option<Uuid>,
382    /// The selected privacy of the map.
383    #[serde(skip_serializing_if = "Option::is_none")]
384    pub privacy: Option<PrivacyAccessControl>,
385}
386
387/// Support struct for transmitting latitude/longitude coordinates.
388#[typeshare]
389#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
390pub struct Coordinates {
391    /// Latitude of the point.
392    pub latitude: f64,
393    /// Longitude of the point.
394    pub longitude: f64,
395}
396
397/// Query parameters for connecting to a map.
398#[typeshare]
399#[derive(Debug, Deserialize, IntoParams)]
400pub struct ConnectToMapQueryParams {
401    /// The id of the map to connect to.
402    pub map_id: i32,
403    /// The id of the user connecting to the map.
404    pub user_id: String,
405}
406
407/// Query parameters to configure the generation of the heatmap.
408#[typeshare]
409#[derive(Debug, Deserialize, IntoParams)]
410pub struct HeatMapQueryParams {
411    /// The id of the plant layer the planting will be planted on.
412    pub plant_layer_id: Uuid,
413    /// The id of the shade layer the planting will be planted on.
414    pub shade_layer_id: Uuid,
415    /// The id of the hydrology layer the planting will be planted on.
416    pub hydrology_layer_id: Uuid,
417    /// The id of the soil layer the planting will be planted on.
418    pub soil_layer_id: Uuid,
419    /// The id of the plant you want to plant.
420    pub plant_id: i32,
421    /// The date at which to generate the heatmap.
422    /// Will be set to the current date if `None`.
423    #[serde(skip_serializing_if = "Option::is_none")]
424    pub date: Option<NaiveDate>,
425}
426
427#[typeshare]
428#[derive(Serialize, Deserialize, ToSchema)]
429/// Completion status of all Guided Tours.
430pub struct GuidedToursDto {
431    /// Whether or not the Map Editor Guided Tour was completed.
432    pub editor_tour_completed: bool,
433    /// Whether or not the Map Editor Guided Tour was paused.
434    pub editor_tour_paused: bool,
435}
436
437#[typeshare]
438#[derive(Serialize, Deserialize, ToSchema)]
439/// The information for updating an users Guided Tour status.
440pub struct UpdateGuidedToursDto {
441    /// Whether or not the Map Editor Guided Tour was completed.
442    #[serde(skip_serializing_if = "Option::is_none")]
443    pub editor_tour_completed: Option<bool>,
444    /// Whether or not the Map Editor Guided Tour was paused.
445    #[serde(skip_serializing_if = "Option::is_none")]
446    pub editor_tour_paused: Option<bool>,
447}
448
449/// Application setting
450#[typeshare]
451#[derive(Serialize, Deserialize, ToSchema)]
452pub struct ApplicationSettingDto {
453    /// The id of the setting
454    pub id: i32,
455    /// The unique key of the setting
456    pub key: String,
457    /// The value of the setting
458    pub value: String,
459}
460
461#[typeshare]
462#[derive(Debug, Serialize, ToSchema)]
463#[serde(rename_all = "camelCase")]
464/// Information on user collaborating on a map.
465pub struct MapCollaboratorDto {
466    /// The id of the map.
467    pub map_id: i32,
468    /// The id of the collaborator.
469    pub user_id: Uuid,
470    /// The user name of the collaborator.
471    pub username: String,
472}
473
474#[typeshare]
475#[derive(Debug, Deserialize, ToSchema)]
476#[serde(rename_all = "camelCase")]
477/// The information of a map collaborator necessary for its creation.
478pub struct NewMapCollaboratorDto {
479    /// The id of the collaborator.
480    pub user_id: Uuid,
481}
482
483#[typeshare]
484#[derive(Debug, Serialize, Deserialize, ToSchema)]
485#[serde(rename_all = "camelCase")]
486pub struct DeleteMapCollaboratorDto {
487    /// The id of the collaborator.
488    pub user_id: Uuid,
489}
490
491#[typeshare]
492#[derive(Debug, Deserialize, IntoParams)]
493#[serde(rename_all = "camelCase")]
494/// Query params for searching map collaborators.
495pub struct MapCollaboratorSearchParameters {
496    /// The id of the map.
497    pub map_id: i32,
498}
499
500#[typeshare]
501#[derive(Debug, Deserialize, IntoParams)]
502#[serde(rename_all = "camelCase")]
503/// Query params for searching users.
504pub struct UserSearchParameters {
505    /// The name of the user to search for.
506    pub username: String,
507}