backend/service/
plantings.rs

1//! Service layer for plantings.
2
3use actix_http::StatusCode;
4use chrono::Days;
5use uuid::Uuid;
6
7use crate::{
8    config::data::SharedPool,
9    error::ServiceError,
10    model::{
11        dto::{
12            core::TimelinePage,
13            plantings::{
14                DeletePlantingDto, PlantingDto, PlantingSearchParameters, UpdatePlantingDto,
15            },
16        },
17        entity::{plantings::Planting, plantings_impl::FindPlantingsParameters},
18    },
19};
20
21/// Time offset in days for loading plantings in the timeline.
22pub const TIME_LINE_LOADING_OFFSET_DAYS: u64 = 356;
23
24/// Search plantings from the database.
25///
26/// # Errors
27/// If the connection to the database could not be established.
28pub async fn find(
29    search_parameters: PlantingSearchParameters,
30    pool: &SharedPool,
31) -> Result<TimelinePage<PlantingDto>, ServiceError> {
32    let mut conn = pool.get().await?;
33
34    let from = search_parameters
35        .relative_to_date
36        .checked_sub_days(Days::new(TIME_LINE_LOADING_OFFSET_DAYS))
37        .ok_or_else(|| {
38            ServiceError::new(
39                StatusCode::BAD_REQUEST,
40                "Could not add days to relative_to_date",
41            )
42        })?;
43
44    let to = search_parameters
45        .relative_to_date
46        .checked_add_days(Days::new(TIME_LINE_LOADING_OFFSET_DAYS))
47        .ok_or_else(|| {
48            ServiceError::new(
49                StatusCode::BAD_REQUEST,
50                "Could not add days to relative_to_date",
51            )
52        })?;
53
54    let search_parameters = FindPlantingsParameters {
55        layer_id: search_parameters.layer_id,
56        plant_id: search_parameters.plant_id,
57        from,
58        to,
59    };
60    let result = Planting::find(search_parameters, &mut conn).await?;
61
62    Ok(TimelinePage {
63        results: result,
64        from,
65        to,
66    })
67}
68
69/// Get all plantings that have a specific seed id.
70/// Also returns a plantings map id.
71///
72/// # Errors
73/// If the connection to the database could not be established.
74pub async fn find_by_seed_id(
75    seed_id: i32,
76    pool: &SharedPool,
77) -> Result<Vec<PlantingDto>, ServiceError> {
78    let mut conn = pool.get().await?;
79    let result = Planting::find_by_seed_id(seed_id, &mut conn).await?;
80    Ok(result)
81}
82
83/// Create a new planting in the database.
84///
85/// # Errors
86/// If the connection to the database could not be established.
87pub async fn create(
88    dtos: Vec<PlantingDto>,
89    map_id: i32,
90    user_id: Uuid,
91    pool: &SharedPool,
92) -> Result<Vec<PlantingDto>, ServiceError> {
93    let mut conn = pool.get().await?;
94    let result = Planting::create(dtos, map_id, user_id, &mut conn).await?;
95    Ok(result)
96}
97
98/// Update the planting in the database.
99///
100/// # Errors
101/// If the connection to the database could not be established.
102pub async fn update(
103    dto: UpdatePlantingDto,
104    map_id: i32,
105    user_id: Uuid,
106    pool: &SharedPool,
107) -> Result<Vec<PlantingDto>, ServiceError> {
108    let mut conn = pool.get().await?;
109    let result = Planting::update(dto, map_id, user_id, &mut conn).await?;
110    Ok(result)
111}
112
113/// Delete the planting from the database.
114///
115/// # Errors
116/// If the connection to the database could not be established.
117pub async fn delete_by_ids(
118    dtos: Vec<DeletePlantingDto>,
119    map_id: i32,
120    user_id: Uuid,
121    pool: &SharedPool,
122) -> Result<(), ServiceError> {
123    let mut conn = pool.get().await?;
124    let _ = Planting::delete_by_ids(dtos, map_id, user_id, &mut conn).await?;
125    Ok(())
126}