1use actix_http::StatusCode;
4use postgis_diesel::types::{Point, Polygon};
5use uuid::Uuid;
6
7use crate::{
8 config::{auth::user_info::UserInfo, data::SharedPool},
9 error::ServiceError,
10 model::{
11 dto::{
12 base_layer_images::BaseLayerImageDto, layers::LayerDto, MapDto, MapSearchParameters,
13 NewMapDto, Page, PageParameters, UpdateMapDto, UpdateMapGeometryDto,
14 },
15 entity::{base_layer_images::BaseLayerImages, layers::Layer, Map, MapCollaborator},
16 r#enum::layer_type::LayerType,
17 },
18};
19
20const LAYER_TYPES: [LayerType; 6] = [
22 LayerType::Base,
23 LayerType::Drawing,
24 LayerType::Soiltexture,
25 LayerType::Hydrology,
26 LayerType::Shade,
27 LayerType::Plants,
28];
29
30pub async fn find(
35 search_parameters: MapSearchParameters,
36 page_parameters: PageParameters,
37 pool: &SharedPool,
38 user_info: UserInfo,
39) -> Result<Page<MapDto>, ServiceError> {
40 let mut conn = pool.get().await?;
41 let collaborating_in = MapCollaborator::find_by_user_id(user_info.id, &mut conn).await?;
42 let result = Map::find(
43 search_parameters,
44 page_parameters,
45 &mut conn,
46 user_info,
47 collaborating_in,
48 )
49 .await?;
50 Ok(result)
51}
52
53pub async fn find_by_id(id: i64, pool: &SharedPool) -> Result<MapDto, ServiceError> {
58 let mut conn = pool.get().await?;
59 let result = Map::find_by_id(id, &mut conn).await?;
60 Ok(result)
61}
62
63pub async fn create(
68 new_map: NewMapDto,
69 user_id: Uuid,
70 pool: &SharedPool,
71) -> Result<MapDto, ServiceError> {
72 let mut conn = pool.get().await?;
73
74 if Map::is_name_taken(&new_map.name, &mut conn).await? {
75 return Err(ServiceError::new(
76 StatusCode::CONFLICT,
77 "Map name already taken",
78 ));
79 }
80
81 let geometry_validation_result = is_valid_map_geometry(&new_map.geometry);
82 if let Some(error) = geometry_validation_result {
83 return Err(error);
84 }
85
86 let result = Map::create(new_map, user_id, &mut conn).await?;
87 for (layer_type, order_index) in LAYER_TYPES.iter().zip(0..) {
88 let new_layer = LayerDto {
89 id: Uuid::now_v7(),
90 type_: *layer_type,
91 name: format!("{layer_type} Layer"),
92 map_id: result.id,
93 order_index,
94 marked_deleted: false,
95 };
96 let layer = Layer::create(result.id.into(), new_layer, &mut conn).await?;
97
98 if layer.type_ == LayerType::Base {
102 BaseLayerImages::create(
103 BaseLayerImageDto {
104 id: Uuid::now_v7(),
105 layer_id: layer.id,
106 path: String::new(),
107 rotation: 0,
108 scale: 100,
109 x: 0,
110 y: 0,
111 },
112 &mut conn,
113 )
114 .await?;
115 }
116 }
117
118 Ok(result)
119}
120
121pub async fn update(
128 map_update: UpdateMapDto,
129 id: i64,
130 pool: &SharedPool,
131) -> Result<MapDto, ServiceError> {
132 let mut conn = pool.get().await?;
133
134 let result = Map::update(map_update, id, &mut conn).await?;
135 Ok(result)
136}
137
138pub async fn update_geometry(
145 map_update_geometry: UpdateMapGeometryDto,
146 id: i64,
147 pool: &SharedPool,
148) -> Result<MapDto, ServiceError> {
149 let mut conn = pool.get().await?;
150
151 let geometry_validation_result = is_valid_map_geometry(&map_update_geometry.geometry);
152 if let Some(error) = geometry_validation_result {
153 return Err(error);
154 }
155
156 let result = Map::update_geometry(map_update_geometry, id, &mut conn).await?;
157 Ok(result)
158}
159
160pub async fn delete_by_id(id: i64, pool: &SharedPool) -> Result<MapDto, ServiceError> {
167 let mut conn = pool.get().await?;
168
169 let result = Map::mark_for_deletion(id, &mut conn).await?;
170
171 Ok(result)
172}
173
174fn is_valid_map_geometry(geometry: &Polygon<Point>) -> Option<ServiceError> {
176 if geometry.rings.len() != 1 {
177 return Some(ServiceError {
178 status_code: StatusCode::BAD_REQUEST,
179 reason: "Map geometry must have exactly one ring".to_owned(),
180 });
181 }
182
183 let geometry_points_length = geometry.rings.get(0).unwrap_or(&Vec::new()).len();
184
185 if geometry_points_length < 3 + 1 {
186 return Some(ServiceError {
187 status_code: StatusCode::BAD_REQUEST,
188 reason: "Map geometry must be a polygon of at least three points.".to_owned(),
189 });
190 }
191
192 None
193}