diff --git a/src/areas/models.rs b/src/areas/models.rs index 9b29f55..7534b48 100644 --- a/src/areas/models.rs +++ b/src/areas/models.rs @@ -6,8 +6,6 @@ use crate::sensors::db::Entity as SensorDB; use crate::soil::profiles::db::Entity as SoilProfileDB; use crate::transects::db::Entity as TransectDB; use crate::transects::models::Transect; -use crate::transects::nodes::db::Entity as TransectNodeDB; -use crate::transects::nodes::models::TransectNode; use chrono::NaiveDateTime; use sea_orm::entity::prelude::*; use sea_orm::ColumnTrait; @@ -117,54 +115,20 @@ impl Area { .unwrap(); // Query for transects with related transect nodes and their corresponding plots - let transects: Vec<( - crate::transects::db::Model, - Vec, - )> = TransectDB::find() + let transects: Vec = TransectDB::find() .filter(crate::transects::db::Column::AreaId.eq(area.id)) - .find_with_related(TransectNodeDB) + // .find_with_related(TransectNodeDB) .all(&db) .await .unwrap(); let mut transects_with_nodes: Vec = Vec::new(); - for (transect, nodes) in transects { - let mut transect_nodes: Vec = Vec::new(); - - for node in nodes { - let plot: PlotSimple = PlotDB::find() - .filter(crate::plots::db::Column::Id.eq(node.plot_id)) - .column_as(Expr::cust("ST_X(plot.geom)"), "coord_x") - .column_as(Expr::cust("ST_Y(plot.geom)"), "coord_y") - .column_as(Expr::cust("ST_Z(plot.geom)"), "coord_z") - .column_as( - Expr::cust("ST_X(st_transform(plot.geom, 4326))"), - "longitude", - ) - .column_as( - Expr::cust("ST_Y(st_transform(plot.geom, 4326))"), - "latitude", - ) - .column_as(Expr::cust("st_srid(plot.geom)"), "coord_srid") - .into_model::() - .one(&db) + for transect in transects { + transects_with_nodes.push( + Transect::get_one(transect.id, &db) .await - .unwrap() - .unwrap(); // Unwrapping safely assuming plot always exists - - transect_nodes.push(TransectNode { - id: node.id, - name: None, // `name` doesn't exist in the `transectnode::Model` - order: node.order, - plot, - }); - } - - transects_with_nodes.push(Transect { - id: transect.id, - name: transect.name, - nodes: transect_nodes, - }); + .expect("Transect not found"), + ); } // Query for soil profiles with matching area_id @@ -207,8 +171,7 @@ impl Area { plots, soil_profiles, sensors, - // transects: transects_with_nodes, // Include transects with nodes - transects: vec![], + transects: transects_with_nodes, // Include transects with nodes project, geom, } diff --git a/src/areas/services.rs b/src/areas/services.rs index a7e67d9..cda74ef 100644 --- a/src/areas/services.rs +++ b/src/areas/services.rs @@ -32,7 +32,7 @@ pub async fn get_convex_hull(db: &DatabaseConnection, area_id: Uuid) -> Option, - longitude: Option, - coord_srid: Option, - coord_x: Option, - coord_y: Option, - coord_z: Option, + pub id: Uuid, + pub name: String, + pub latitude: Option, + pub longitude: Option, + pub coord_srid: Option, + pub coord_x: Option, + pub coord_y: Option, + pub coord_z: Option, } #[derive(ToSchema, Serialize)] pub struct Plot { diff --git a/src/transects/models.rs b/src/transects/models.rs index fbe7404..da56f62 100644 --- a/src/transects/models.rs +++ b/src/transects/models.rs @@ -1,4 +1,11 @@ -use crate::transects::nodes::models::TransectNode; +use crate::plots::db::Entity as PlotDB; +use crate::plots::models::PlotSimple; +use crate::transects::db::Entity as TransectDB; +use crate::transects::nodes::db::Entity as TransectNodeDB; +use crate::transects::nodes::models::TransectNodeAsPlotWithOrder; +use sea_orm::ColumnTrait; +use sea_orm::{DatabaseConnection, EntityTrait, QueryFilter, QuerySelect}; +use sea_query::Expr; use serde::Serialize; use utoipa::ToSchema; use uuid::Uuid; @@ -7,5 +14,132 @@ use uuid::Uuid; pub struct Transect { pub id: Uuid, pub name: Option, - pub nodes: Vec, + pub nodes: Vec, +} + +impl Transect { + pub async fn get_all(db: &DatabaseConnection) -> Vec { + // Query for transects with related transect nodes and their corresponding plots + let transects: Vec<( + crate::transects::db::Model, + Vec, + )> = TransectDB::find() + .find_with_related(TransectNodeDB) + .all(db) + .await + .unwrap(); + + let mut transects_with_nodes: Vec = Vec::new(); + for (transect, nodes) in transects { + let mut transect_nodes: Vec = Vec::new(); + + for node in nodes { + // Fetch associated plot for the node + let plot: PlotSimple = PlotDB::find() + .filter(crate::plots::db::Column::Id.eq(node.plot_id)) + .column_as(Expr::cust("ST_X(plot.geom)"), "coord_x") + .column_as(Expr::cust("ST_Y(plot.geom)"), "coord_y") + .column_as(Expr::cust("ST_Z(plot.geom)"), "coord_z") + .column_as( + Expr::cust("ST_X(st_transform(plot.geom, 4326))"), + "longitude", + ) + .column_as( + Expr::cust("ST_Y(st_transform(plot.geom, 4326))"), + "latitude", + ) + .column_as(Expr::cust("st_srid(plot.geom)"), "coord_srid") + .into_model::() + .one(db) + .await + .unwrap() + .unwrap(); // Assuming plot always exists + + transect_nodes.push(TransectNodeAsPlotWithOrder { + id: plot.id, + order: node.order, + name: plot.name, + latitude: plot.latitude, + longitude: plot.longitude, + coord_srid: plot.coord_srid, + coord_x: plot.coord_x, + coord_y: plot.coord_y, + coord_z: plot.coord_z, + }); + } + + transects_with_nodes.push(Transect { + id: transect.id, + name: transect.name.clone(), + nodes: transect_nodes, + }); + } + + transects_with_nodes + } + + pub async fn get_one(transect_id: Uuid, db: &DatabaseConnection) -> Option { + // Query for the single transect with the provided id and its related transect nodes + let transect_tuple: Option<( + crate::transects::db::Model, + Vec, + )> = TransectDB::find() + .filter(crate::transects::db::Column::Id.eq(transect_id)) + .find_with_related(TransectNodeDB) + .all(db) + .await + .unwrap() + .into_iter() + .next(); // Retrieve the first result, if any + + // If a transect is found, process it, otherwise return None + if let Some((transect, nodes)) = transect_tuple { + let mut transect_nodes: Vec = Vec::new(); + + // Iterate over nodes and fetch the associated plot for each node + for node in nodes { + let plot: PlotSimple = PlotDB::find() + .filter(crate::plots::db::Column::Id.eq(node.plot_id)) + .column_as(Expr::cust("ST_X(plot.geom)"), "coord_x") + .column_as(Expr::cust("ST_Y(plot.geom)"), "coord_y") + .column_as(Expr::cust("ST_Z(plot.geom)"), "coord_z") + .column_as( + Expr::cust("ST_X(st_transform(plot.geom, 4326))"), + "longitude", + ) + .column_as( + Expr::cust("ST_Y(st_transform(plot.geom, 4326))"), + "latitude", + ) + .column_as(Expr::cust("st_srid(plot.geom)"), "coord_srid") + .into_model::() + .one(db) + .await + .unwrap() + .unwrap(); // Assuming plot always exists + + transect_nodes.push(TransectNodeAsPlotWithOrder { + id: plot.id, + order: node.order, + name: plot.name, + latitude: plot.latitude, + longitude: plot.longitude, + coord_srid: plot.coord_srid, + coord_x: plot.coord_x, + coord_y: plot.coord_y, + coord_z: plot.coord_z, + }); + } + + // Return the constructed Transect + Some(Transect { + id: transect.id, + name: transect.name, + nodes: transect_nodes, + }) + } else { + // Return None if no transect is found + None + } + } } diff --git a/src/transects/nodes/models.rs b/src/transects/nodes/models.rs index 4dda77c..e816a2f 100644 --- a/src/transects/nodes/models.rs +++ b/src/transects/nodes/models.rs @@ -6,7 +6,21 @@ use uuid::Uuid; #[derive(ToSchema, Serialize)] pub struct TransectNode { pub id: Uuid, - pub name: Option, pub order: i32, pub plot: PlotSimple, } + +#[derive(ToSchema, Serialize)] +pub struct TransectNodeAsPlotWithOrder { + // A transect node is really a plot with an order value, this is similar to + // the PlotSimple struct but with an additional order field + pub id: Uuid, + pub name: String, + pub latitude: Option, + pub longitude: Option, + pub coord_srid: Option, + pub coord_x: Option, + pub coord_y: Option, + pub coord_z: Option, + pub order: i32, +}