Skip to content

Commit 6bf5baa

Browse files
committed
add overarching goals endpoints
1 parent 252858c commit 6bf5baa

File tree

6 files changed

+428
-4
lines changed

6 files changed

+428
-4
lines changed

entity/src/overarching_goals.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,23 @@
33
use crate::Id;
44
use sea_orm::entity::prelude::*;
55
use serde::{Deserialize, Serialize};
6+
use utoipa::ToSchema;
67

7-
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)]
8+
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize, ToSchema)]
89
#[sea_orm(schema_name = "refactor_platform", table_name = "overarching_goals")]
910
pub struct Model {
11+
#[serde(skip_deserializing)]
1012
#[sea_orm(primary_key)]
1113
pub id: Id,
1214
pub coaching_session_id: Option<Id>,
1315
pub user_id: Id,
1416
pub title: Option<String>,
1517
pub body: Option<String>,
18+
#[serde(skip_deserializing)]
1619
pub completed_at: Option<DateTimeWithTimeZone>,
20+
#[serde(skip_deserializing)]
1721
pub created_at: DateTimeWithTimeZone,
22+
#[serde(skip_deserializing)]
1823
pub updated_at: DateTimeWithTimeZone,
1924
}
2025

entity_api/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ pub mod coaching_session;
1111
pub mod error;
1212
pub mod note;
1313
pub mod organization;
14+
pub mod overarching_goal;
1415
pub mod user;
1516

1617
pub(crate) fn uuid_parse_str(uuid_str: &str) -> Result<Id, error::Error> {

entity_api/src/overarching_goal.rs

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
use super::error::{EntityApiErrorCode, Error};
2+
use crate::uuid_parse_str;
3+
use entity::overarching_goals::{self, ActiveModel, Entity, Model};
4+
use entity::Id;
5+
use sea_orm::{
6+
entity::prelude::*,
7+
ActiveModelTrait,
8+
ActiveValue::{Set, Unchanged},
9+
DatabaseConnection, TryIntoModel,
10+
};
11+
use std::collections::HashMap;
12+
13+
use log::*;
14+
15+
pub async fn create(
16+
db: &DatabaseConnection,
17+
overarching_goal_model: Model,
18+
) -> Result<Model, Error> {
19+
debug!(
20+
"New Overarching Goal Model to be inserted: {:?}",
21+
overarching_goal_model
22+
);
23+
24+
let now = chrono::Utc::now();
25+
26+
let overarching_goal_active_model: ActiveModel = ActiveModel {
27+
coaching_session_id: Set(overarching_goal_model.coaching_session_id),
28+
user_id: Set(overarching_goal_model.user_id),
29+
title: Set(overarching_goal_model.title),
30+
body: Set(overarching_goal_model.body),
31+
created_at: Set(now.into()),
32+
updated_at: Set(now.into()),
33+
..Default::default()
34+
};
35+
36+
Ok(overarching_goal_active_model
37+
.save(db)
38+
.await?
39+
.try_into_model()?)
40+
}
41+
42+
pub async fn update(db: &DatabaseConnection, id: Id, model: Model) -> Result<Model, Error> {
43+
let result = Entity::find_by_id(id).one(db).await?;
44+
45+
match result {
46+
Some(overarching_goal) => {
47+
debug!(
48+
"Existing Overarching Goal model to be Updated: {:?}",
49+
overarching_goal
50+
);
51+
52+
let active_model: ActiveModel = ActiveModel {
53+
id: Unchanged(model.id),
54+
coaching_session_id: Unchanged(model.coaching_session_id),
55+
user_id: Unchanged(model.user_id),
56+
body: Set(model.body),
57+
title: Set(model.title),
58+
completed_at: Set(model.completed_at),
59+
updated_at: Set(chrono::Utc::now().into()),
60+
created_at: Unchanged(model.created_at),
61+
};
62+
63+
Ok(active_model.update(db).await?.try_into_model()?)
64+
}
65+
None => {
66+
error!("Overarching Goal with id {} not found", id);
67+
68+
Err(Error {
69+
inner: None,
70+
error_code: EntityApiErrorCode::RecordNotFound,
71+
})
72+
}
73+
}
74+
}
75+
76+
pub async fn find_by_id(db: &DatabaseConnection, id: Id) -> Result<Option<Model>, Error> {
77+
match Entity::find_by_id(id).one(db).await {
78+
Ok(Some(overarching_goal)) => {
79+
debug!("Overarching Goal found: {:?}", overarching_goal);
80+
81+
Ok(Some(overarching_goal))
82+
}
83+
Ok(None) => {
84+
error!("Overarching Goal with id {} not found", id);
85+
86+
Err(Error {
87+
inner: None,
88+
error_code: EntityApiErrorCode::RecordNotFound,
89+
})
90+
}
91+
Err(err) => {
92+
error!(
93+
"Overarching Goal with id {} not found and returned error {}",
94+
id, err
95+
);
96+
Err(Error {
97+
inner: None,
98+
error_code: EntityApiErrorCode::RecordNotFound,
99+
})
100+
}
101+
}
102+
}
103+
104+
pub async fn find_by(
105+
db: &DatabaseConnection,
106+
query_params: HashMap<String, String>,
107+
) -> Result<Vec<Model>, Error> {
108+
let mut query = Entity::find();
109+
110+
for (key, value) in query_params {
111+
match key.as_str() {
112+
"coaching_session_id" => {
113+
let coaching_session_id = uuid_parse_str(&value)?;
114+
115+
query = query
116+
.filter(overarching_goals::Column::CoachingSessionId.eq(coaching_session_id));
117+
}
118+
_ => {
119+
return Err(Error {
120+
inner: None,
121+
error_code: EntityApiErrorCode::InvalidQueryTerm,
122+
});
123+
}
124+
}
125+
}
126+
127+
Ok(query.all(db).await?)
128+
}
129+
130+
#[cfg(test)]
131+
// We need to gate seaORM's mock feature behind conditional compilation because
132+
// the feature removes the Clone trait implementation from seaORM's DatabaseConnection.
133+
// see https://github.com/SeaQL/sea-orm/issues/830
134+
#[cfg(feature = "mock")]
135+
mod tests {
136+
use super::*;
137+
use entity::{overarching_goals::Model, Id};
138+
use sea_orm::{DatabaseBackend, MockDatabase, Transoverarching_goal};
139+
140+
#[tokio::test]
141+
async fn create_returns_a_new_overarching_goal_model() -> Result<(), Error> {
142+
let now = chrono::Utc::now();
143+
144+
let overarching_goal_model = Model {
145+
id: Id::new_v4(),
146+
coaching_session_id: Id::new_v4(),
147+
body: Some("This is a overarching_goal".to_owned()),
148+
due_by: Some(now.into()),
149+
user_id: Id::new_v4(),
150+
status_changed_at: None,
151+
status: Default::default(),
152+
created_at: now.into(),
153+
updated_at: now.into(),
154+
};
155+
156+
let db = MockDatabase::new(DatabaseBackend::Postgres)
157+
.append_query_results(vec![vec![overarching_goal_model.clone()]])
158+
.into_connection();
159+
160+
let overarching_goal = create(&db, overarching_goal_model.clone().into()).await?;
161+
162+
assert_eq!(overarching_goal.id, overarching_goal_model.id);
163+
164+
Ok(())
165+
}
166+
167+
#[tokio::test]
168+
async fn update_returns_an_updated_overarching_goal_model() -> Result<(), Error> {
169+
let now = chrono::Utc::now();
170+
171+
let overarching_goal_model = Model {
172+
id: Id::new_v4(),
173+
coaching_session_id: Id::new_v4(),
174+
due_by: Some(now.into()),
175+
body: Some("This is a overarching_goal".to_owned()),
176+
user_id: Id::new_v4(),
177+
status_changed_at: None,
178+
status: Default::default(),
179+
created_at: now.into(),
180+
updated_at: now.into(),
181+
};
182+
183+
let db = MockDatabase::new(DatabaseBackend::Postgres)
184+
.append_query_results(vec![
185+
vec![overarching_goal_model.clone()],
186+
vec![overarching_goal_model.clone()],
187+
])
188+
.into_connection();
189+
190+
let overarching_goal = update(
191+
&db,
192+
overarching_goal_model.id,
193+
overarching_goal_model.clone(),
194+
)
195+
.await?;
196+
197+
assert_eq!(overarching_goal.body, overarching_goal_model.body);
198+
199+
Ok(())
200+
}
201+
202+
#[tokio::test]
203+
async fn find_by_returns_all_overarching_goals_associated_with_coaching_session(
204+
) -> Result<(), Error> {
205+
let db = MockDatabase::new(DatabaseBackend::Postgres).into_connection();
206+
let mut query_params = HashMap::new();
207+
let coaching_session_id = Id::new_v4();
208+
209+
query_params.insert(
210+
"coaching_session_id".to_owned(),
211+
coaching_session_id.to_string(),
212+
);
213+
214+
let _ = find_by(&db, query_params).await;
215+
216+
assert_eq!(
217+
db.into_transaction_log(),
218+
[Transoverarching_goal::from_sql_and_values(
219+
DatabaseBackend::Postgres,
220+
r#"SELECT "overarching_goals"."id", "overarching_goals"."coaching_session_id", "overarching_goals"."user_id", "overarching_goals"."body", "overarching_goals"."title", "overarching_goals"."created_at", "overarching_goals"."updated_at" FROM "refactor_platform"."overarching_goals" WHERE "overarching_goals"."coaching_session_id" = $1"#,
221+
[coaching_session_id.into()]
222+
)]
223+
);
224+
225+
Ok(())
226+
}
227+
}

web/src/controller/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ pub(crate) mod coaching_session_controller;
66
pub(crate) mod note_controller;
77
pub(crate) mod organization;
88
pub(crate) mod organization_controller;
9+
pub(crate) mod overarching_goal_controller;
910
pub(crate) mod user_session_controller;
1011

1112
#[derive(Debug, Serialize)]

0 commit comments

Comments
 (0)