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