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    experience::Experience, include_archived_seeds::IncludeArchivedSeeds, life_cycle::LifeCycle,
15    membership::Membership, privacy_option::PrivacyOption, quality::Quality, quantity::Quantity,
16    salutation::Salutation, 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 blossoms_impl;
26pub mod coordinates_impl;
27pub mod core;
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;
46pub mod users_impl;
47
48/// Contains configuration the frontend needs to run.
49#[typeshare]
50#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, ToSchema)]
51pub struct ConfigDto {
52    /// The base URL of the authorization server
53    pub issuer_uri: String,
54    /// The `client_id` the frontend should use to log in
55    pub client_id: String,
56    /// The version must be an exact match between frontend and backend.
57    pub version: String,
58}
59
60/// Represents seeds of a user.
61#[typeshare]
62#[derive(Serialize, Deserialize, ToSchema)]
63pub struct SeedDto {
64    /// The record id of the seed.
65    pub id: i32,
66    /// An additional name for the seed.
67    pub name: String,
68    /// The id of the plant this seed belongs to.
69    #[serde(skip_serializing_if = "Option::is_none")]
70    pub plant_id: Option<i32>,
71    /// When the seeds were harvested.
72    pub harvest_year: i16,
73    /// How many seeds there are.
74    pub quantity: Quantity,
75    /// When the seeds should be used by.
76    #[serde(skip_serializing_if = "Option::is_none")]
77    pub use_by: Option<NaiveDate>,
78    /// Where the seeds came from.
79    #[serde(skip_serializing_if = "Option::is_none")]
80    pub origin: Option<String>,
81    /// What the seeds taste like.
82    #[serde(skip_serializing_if = "Option::is_none")]
83    pub taste: Option<String>,
84    /// The yield of the seeds.
85    #[serde(skip_serializing_if = "Option::is_none")]
86    pub yield_: Option<String>,
87    /// How many generations the seeds have been grown.
88    #[serde(skip_serializing_if = "Option::is_none")]
89    pub generation: Option<i16>,
90    /// The quality of the seeds.
91    #[serde(skip_serializing_if = "Option::is_none")]
92    pub quality: Option<Quality>,
93    /// How much the seeds cost.
94    #[serde(skip_serializing_if = "Option::is_none")]
95    pub price: Option<i16>,
96    /// Notes about the seeds.
97    #[serde(skip_serializing_if = "Option::is_none")]
98    pub notes: Option<String>,
99    /// The id of the creator of the seed.
100    pub created_by: Uuid,
101    /// Timestamp indicating when the seed was archived.
102    /// Empty if the seed was not archived.
103    #[serde(skip_serializing_if = "Option::is_none")]
104    pub archived_at: Option<String>,
105}
106
107#[allow(clippy::missing_docs_in_private_items)] // TODO: See #97.
108#[typeshare]
109#[derive(Serialize, Deserialize, ToSchema)]
110pub struct NewSeedDto {
111    pub name: String,
112    #[serde(skip_serializing_if = "Option::is_none")]
113    pub plant_id: Option<i32>,
114    pub harvest_year: i16,
115    pub quantity: Quantity,
116    #[serde(skip_serializing_if = "Option::is_none")]
117    pub use_by: Option<NaiveDate>,
118    #[serde(skip_serializing_if = "Option::is_none")]
119    pub origin: Option<String>,
120    #[serde(skip_serializing_if = "Option::is_none")]
121    pub taste: Option<String>,
122    #[serde(skip_serializing_if = "Option::is_none")]
123    pub yield_: Option<String>,
124    #[serde(skip_serializing_if = "Option::is_none")]
125    pub generation: Option<i16>,
126    #[serde(skip_serializing_if = "Option::is_none")]
127    pub quality: Option<Quality>,
128    #[serde(skip_serializing_if = "Option::is_none")]
129    pub price: Option<i16>,
130    #[serde(skip_serializing_if = "Option::is_none")]
131    pub notes: Option<String>,
132}
133
134/// Data that is required when archiving a seed.
135#[typeshare]
136#[derive(Serialize, Deserialize, ToSchema)]
137pub struct ArchiveSeedDto {
138    /// Whether the seed should be archived.
139    pub archived: bool,
140}
141
142/// The essential identifying information of a plant.
143#[typeshare]
144#[derive(Debug, Serialize, PartialEq, Eq, Deserialize, ToSchema)]
145pub struct PlantsSummaryDto {
146    /// The plants database id.
147    pub id: i32,
148    /// Biological name of this plant (E.g. "Triticum aestivum", "Prunus cerasus")
149    pub unique_name: String,
150    /// A list of common english names (E.g. "Bread wheat", "Sour cherry")
151    #[serde(skip_serializing_if = "Option::is_none")]
152    pub common_name_en: Option<Vec<Option<String>>>,
153    /// A list of common german names (E.g. "Brotweizen", "Sauerkirsche")
154    #[serde(skip_serializing_if = "Option::is_none")]
155    pub common_name_de: Option<Vec<Option<String>>>,
156    /// How far a plant spreads (The 'width' of a plant) in cm
157    #[serde(skip_serializing_if = "Option::is_none")]
158    pub spread: Option<i32>,
159    /// Indicates life span of the plant.
160    pub life_cycle: Vec<LifeCycle>,
161    #[serde(skip_serializing_if = "Option::is_none")]
162    pub functions: Option<String>,
163    #[serde(skip_serializing_if = "Option::is_none")]
164    pub edible: Option<bool>,
165    pub edible_parts: Vec<Option<String>>,
166    #[serde(skip_serializing_if = "Option::is_none")]
167    pub warning: Option<String>,
168    pub sowing_outdoors: Vec<Option<i16>>,
169    pub harvest_time: Vec<Option<i16>>,
170    pub icon_path: Option<String>,
171}
172
173/// Query parameters for searching plants.
174#[typeshare]
175#[derive(Debug, Deserialize, IntoParams)]
176pub struct PlantsSearchParameters {
177    /// The system will check if this string occurs in the plants common name or unique name.
178    #[serde(skip_serializing_if = "Option::is_none")]
179    pub name: Option<String>,
180}
181
182/// Query parameters for searching spatial plant relations.
183#[typeshare]
184#[derive(Debug, Deserialize, IntoParams)]
185pub struct RelationSearchParameters {
186    /// The id of the plant to find relations for.
187    pub plant_id: i32,
188}
189
190/// Use to return spatial relations for the plant.
191#[typeshare]
192#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
193pub struct RelationsDto {
194    /// The id of the plant in the relation.
195    pub id: i32,
196    /// The type of relation.
197    pub relations: Vec<RelationDto>,
198}
199
200/// Use to return a spatial relation.
201#[typeshare]
202#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
203pub struct RelationDto {
204    /// The id of the plant in the relation.
205    pub id: i32,
206    /// The type of relation.
207    pub relation: SpatialRelationType,
208}
209
210/// Query parameters for searching seeds.
211#[typeshare]
212#[derive(Debug, Deserialize, IntoParams)]
213pub struct SeedSearchParameters {
214    /// Name of the seed to search for.
215    #[serde(skip_serializing_if = "Option::is_none")]
216    pub name: Option<String>,
217    /// The exact harvest year of the seed.
218    #[serde(skip_serializing_if = "Option::is_none")]
219    pub harvest_year: Option<i16>,
220    /// Whether archived, not archived or both kinds of seeds should be included.
221    /// If no value is provided, a default value of `NotArchived` is assumed.
222    #[serde(skip_serializing_if = "Option::is_none")]
223    pub archived: Option<IncludeArchivedSeeds>,
224}
225
226/// Query parameters paginating list endpoints.
227#[typeshare]
228#[derive(Debug, Deserialize, IntoParams)]
229pub struct PageParameters {
230    /// Number of results in per page.
231    #[serde(skip_serializing_if = "Option::is_none")]
232    pub per_page: Option<i32>,
233    /// Page number to be returned.
234    /// Note: pages start at one.
235    #[serde(skip_serializing_if = "Option::is_none")]
236    pub page: Option<i32>,
237}
238
239/// A page of results returned from a list endpoint.
240#[typeshare]
241#[derive(Debug, Serialize, PartialEq, Eq, Deserialize, ToSchema)]
242#[aliases(
243    PagePlantsSummaryDto = Page<PlantsSummaryDto>,
244    PageSeedDto = Page<SeedDto>,
245    PageMapDto = Page<MapDto>,
246    PageLayerDto = Page<LayerDto>
247)]
248pub struct Page<T> {
249    /// Resulting records.
250    pub results: Vec<T>,
251    /// Current page number.
252    pub page: i32,
253    /// Results per page.
254    pub per_page: i32,
255    /// Number of pages in total.
256    pub total_pages: i32,
257}
258
259/// The whole information of a map.
260#[typeshare]
261#[derive(Serialize, Deserialize, ToSchema)]
262pub struct MapDto {
263    /// The id of the map.
264    pub id: i32,
265    /// The name of the map.
266    pub name: String,
267    /// When the map was created.
268    pub created_at: NaiveDateTime,
269    /// When a map was last modified, e.g by modifying plantings.
270    pub modified_at: NaiveDateTime,
271    /// The id of the creator of the map.
272    pub created_by: Uuid,
273    /// By whom the map was last modified.
274    pub modified_by: Uuid,
275    /// The date the map is supposed to be deleted.
276    #[serde(skip_serializing_if = "Option::is_none")]
277    pub deletion_date: Option<NaiveDate>,
278    /// The date the last time the map view was opened by any user.
279    #[serde(skip_serializing_if = "Option::is_none")]
280    pub last_visit: Option<NaiveDate>,
281    /// A flag indicating if this map is marked for deletion.
282    pub is_inactive: bool,
283    /// The zoom factor of the map.
284    pub zoom_factor: i16,
285    /// The amount of honors the map received.
286    pub honors: i16,
287    /// The amount of visits the map had.
288    pub visits: i16,
289    /// The amount of plants harvested on the map.
290    pub harvested: i16,
291    /// An enum indicating if this map is private or not.
292    pub privacy: PrivacyOption,
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    /// The amount of honors the map received.
324    pub honors: i16,
325    /// The amount of visits the map had.
326    pub visits: i16,
327    /// The amount of plants harvested on the map.
328    pub harvested: i16,
329    /// An enum indicating if this map is private or not.
330    pub privacy: PrivacyOption,
331    /// The description of the map.
332    #[serde(skip_serializing_if = "Option::is_none")]
333    pub description: Option<String>,
334    /// The location of the map as a latitude/longitude point.
335    #[serde(skip_serializing_if = "Option::is_none")]
336    pub location: Option<Coordinates>,
337    /// The geometry of the map.
338    ///
339    /// 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}`
340    #[typeshare(serialized_as = "object")]
341    #[schema(value_type = Object)]
342    pub geometry: Polygon<Point>,
343}
344
345/// The information for updating a map.
346#[typeshare]
347#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
348pub struct UpdateMapDto {
349    /// The name of the map.
350    #[serde(skip_serializing_if = "Option::is_none")]
351    pub name: Option<String>,
352    /// An enum indicating if this map is private or not.
353    #[serde(skip_serializing_if = "Option::is_none")]
354    pub privacy: Option<PrivacyOption>,
355    /// The description of the map.
356    #[serde(skip_serializing_if = "Option::is_none")]
357    pub description: Option<String>,
358    /// The location of the map as a latitude/longitude point.
359    #[serde(skip_serializing_if = "Option::is_none")]
360    pub location: Option<Coordinates>,
361}
362
363/// Data for updating a maps geometry.
364#[typeshare]
365#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
366pub struct UpdateMapGeometryDto {
367    /// The geometry of the map.
368    ///
369    /// 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}`
370    #[typeshare(serialized_as = "object")]
371    #[schema(value_type = Object)]
372    pub geometry: Polygon<Point>,
373}
374
375/// Query parameters for searching maps.
376#[typeshare]
377#[derive(Debug, Deserialize, IntoParams)]
378pub struct MapSearchParameters {
379    /// Name of the map to search for.
380    #[serde(skip_serializing_if = "Option::is_none")]
381    pub name: Option<String>,
382    /// Whether or not the map is active.
383    #[serde(skip_serializing_if = "Option::is_none")]
384    pub is_inactive: Option<bool>,
385    /// The creator of the map.
386    #[serde(skip_serializing_if = "Option::is_none")]
387    pub created_by: Option<Uuid>,
388    /// The selected privacy of the map.
389    #[serde(skip_serializing_if = "Option::is_none")]
390    pub privacy: Option<PrivacyOption>,
391}
392
393/// Support struct for transmitting latitude/longitude coordinates.
394#[typeshare]
395#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
396pub struct Coordinates {
397    /// Latitude of the point.
398    pub latitude: f64,
399    /// Longitude of the point.
400    pub longitude: f64,
401}
402
403/// Query parameters for connecting to a map.
404#[typeshare]
405#[derive(Debug, Deserialize, IntoParams)]
406pub struct ConnectToMapQueryParams {
407    /// The id of the map to connect to.
408    pub map_id: i32,
409    /// The id of the user connecting to the map.
410    pub user_id: String,
411}
412
413/// Query parameters to configure the generation of the heatmap.
414#[typeshare]
415#[derive(Debug, Deserialize, IntoParams)]
416pub struct HeatMapQueryParams {
417    /// The id of the plant layer the planting will be planted on.
418    pub plant_layer_id: Uuid,
419    /// The id of the shade layer the planting will be planted on.
420    pub shade_layer_id: Uuid,
421    /// The id of the hydrology layer the planting will be planted on.
422    pub hydrology_layer_id: Uuid,
423    /// The id of the soil layer the planting will be planted on.
424    pub soil_layer_id: Uuid,
425    /// The id of the plant you want to plant.
426    pub plant_id: i32,
427    /// The date at which to generate the heatmap.
428    /// Will be set to the current date if `None`.
429    #[serde(skip_serializing_if = "Option::is_none")]
430    pub date: Option<NaiveDate>,
431}
432
433#[typeshare]
434#[derive(Serialize, Deserialize, ToSchema)]
435/// All of the application managed user data.
436pub struct UsersDto {
437    /// The preferred salutation of the user.
438    pub salutation: Salutation,
439    /// The title(s) of the user.
440    #[serde(skip_serializing_if = "Option::is_none")]
441    pub title: Option<String>,
442    /// The current country of the user.
443    pub country: String,
444    /// The phone number of the user.
445    #[serde(skip_serializing_if = "Option::is_none")]
446    pub phone: Option<String>,
447    /// The website of the user.
448    #[serde(skip_serializing_if = "Option::is_none")]
449    pub website: Option<String>,
450    /// The organization the user belongs to.
451    #[serde(skip_serializing_if = "Option::is_none")]
452    pub organization: Option<String>,
453    /// The experience level in permaculture of the user.
454    #[serde(skip_serializing_if = "Option::is_none")]
455    pub experience: Option<Experience>,
456    /// The membership type of the user.
457    #[serde(skip_serializing_if = "Option::is_none")]
458    pub membership: Option<Membership>,
459    /// A collection of years in which the user was a member.
460    #[serde(skip_serializing_if = "Option::is_none")]
461    pub member_years: Option<Vec<Option<i32>>>,
462    /// The date since when the user is a member.
463    #[serde(skip_serializing_if = "Option::is_none")]
464    pub member_since: Option<NaiveDate>,
465    /// The amount of permacoins the user earned in each year as a member.
466    #[serde(skip_serializing_if = "Option::is_none")]
467    pub permacoins: Option<Vec<Option<i32>>>,
468}
469
470#[typeshare]
471#[derive(Serialize, Deserialize, ToSchema)]
472/// Completion status of all Guided Tours.
473pub struct GuidedToursDto {
474    /// Whether or not the Map Editor Guided Tour was completed.
475    pub editor_tour_completed: bool,
476}
477
478#[typeshare]
479#[derive(Serialize, Deserialize, ToSchema)]
480/// The information for updating an users Guided Tour status.
481pub struct UpdateGuidedToursDto {
482    /// Whether or not the Map Editor Guided Tour was completed.
483    #[serde(skip_serializing_if = "Option::is_none")]
484    pub editor_tour_completed: Option<bool>,
485}
486
487#[typeshare]
488#[derive(Serialize, Deserialize, ToSchema)]
489/// Information on a specific Blossom gained by a user.
490pub struct GainedBlossomsDto {
491    /// The title of the Blossom.
492    pub blossom: String,
493    /// The number of times this Blossom was gained by this user.
494    pub times_gained: i32,
495    /// The date on which the user gained this Blossom.
496    pub gained_date: NaiveDate,
497}
498
499/// Application setting
500#[typeshare]
501#[derive(Serialize, Deserialize, ToSchema)]
502pub struct ApplicationSettingDto {
503    /// The id of the setting
504    pub id: i32,
505    /// The unique key of the setting
506    pub key: String,
507    /// The value of the setting
508    pub value: String,
509}
510
511#[typeshare]
512#[derive(Debug, Serialize, ToSchema)]
513#[serde(rename_all = "camelCase")]
514/// Information on user collaborating on a map.
515pub struct MapCollaboratorDto {
516    /// The id of the map.
517    pub map_id: i32,
518    /// The id of the collaborator.
519    pub user_id: Uuid,
520    /// The user name of the collaborator.
521    pub username: String,
522}
523
524#[typeshare]
525#[derive(Debug, Deserialize, ToSchema)]
526#[serde(rename_all = "camelCase")]
527/// The information of a map collaborator necessary for its creation.
528pub struct NewMapCollaboratorDto {
529    /// The id of the collaborator.
530    pub user_id: Uuid,
531}
532
533#[typeshare]
534#[derive(Debug, Serialize, Deserialize, ToSchema)]
535#[serde(rename_all = "camelCase")]
536pub struct DeleteMapCollaboratorDto {
537    /// The id of the collaborator.
538    pub user_id: Uuid,
539}
540
541#[typeshare]
542#[derive(Debug, Deserialize, IntoParams)]
543#[serde(rename_all = "camelCase")]
544/// Query params for searching map collaborators.
545pub struct MapCollaboratorSearchParameters {
546    /// The id of the map.
547    pub map_id: i32,
548}
549
550#[typeshare]
551#[derive(Debug, Deserialize, IntoParams)]
552#[serde(rename_all = "camelCase")]
553/// Query params for searching users.
554pub struct UserSearchParameters {
555    /// The name of the user to search for.
556    pub username: String,
557}