Calendar (WIP)
This commit is contained in:
parent
9d3f9e9c60
commit
79a0aeb1b8
24 changed files with 613 additions and 231 deletions
|
|
@ -1,10 +1,9 @@
|
|||
use chrono::prelude::*;
|
||||
use chrono::{prelude::*, Days};
|
||||
use common::ron_api::Difficulty;
|
||||
use itertools::Itertools;
|
||||
|
||||
use super::{Connection, DBError, Result};
|
||||
use crate::data::model;
|
||||
|
||||
use common::ron_api::Difficulty;
|
||||
use crate::{data::model, user_authentication};
|
||||
|
||||
impl Connection {
|
||||
/// Returns all the recipe titles where recipe is written in the given language.
|
||||
|
|
@ -106,11 +105,10 @@ SELECT COUNT(*)
|
|||
FROM [Recipe]
|
||||
INNER JOIN [User] ON [User].[id] = [Recipe].[user_id]
|
||||
INNER JOIN [Group] ON [Group].[recipe_id] = [Recipe].[id]
|
||||
WHERE [Group].[id] IN ({}) AND ([user_id] = $2 OR (SELECT [is_admin] FROM [User] WHERE [id] = $2))
|
||||
WHERE [Group].[id] IN ({}) AND ([user_id] = $1 OR (SELECT [is_admin] FROM [User] WHERE [id] = $1))
|
||||
"#,
|
||||
params
|
||||
);
|
||||
|
||||
let mut query = sqlx::query_scalar::<_, u64>(&query_str).bind(user_id);
|
||||
for id in group_ids {
|
||||
query = query.bind(id);
|
||||
|
|
@ -147,11 +145,10 @@ FROM [Recipe]
|
|||
INNER JOIN [User] ON [User].[id] = [Recipe].[user_id]
|
||||
INNER JOIN [Group] ON [Group].[recipe_id] = [Recipe].[id]
|
||||
INNER JOIN [Step] ON [Step].[group_id] = [Group].[id]
|
||||
WHERE [Step].[id] IN ({}) AND ([user_id] = $2 OR (SELECT [is_admin] FROM [User] WHERE [id] = $2))
|
||||
WHERE [Step].[id] IN ({}) AND ([user_id] = $1 OR (SELECT [is_admin] FROM [User] WHERE [id] = $1))
|
||||
"#,
|
||||
params
|
||||
);
|
||||
|
||||
let mut query = sqlx::query_scalar::<_, u64>(&query_str).bind(user_id);
|
||||
for id in steps_ids {
|
||||
query = query.bind(id);
|
||||
|
|
@ -199,11 +196,10 @@ INNER JOIN [Group] ON [Group].[recipe_id] = [Recipe].[id]
|
|||
INNER JOIN [Step] ON [Step].[group_id] = [Group].[id]
|
||||
INNER JOIN [Ingredient] ON [Ingredient].[step_id] = [Step].[id]
|
||||
WHERE [Ingredient].[id] IN ({}) AND
|
||||
([user_id] = $2 OR (SELECT [is_admin] FROM [User] WHERE [id] = $2))
|
||||
([user_id] = $1 OR (SELECT [is_admin] FROM [User] WHERE [id] = $1))
|
||||
"#,
|
||||
params
|
||||
);
|
||||
|
||||
let mut query = sqlx::query_scalar::<_, u64>(&query_str).bind(user_id);
|
||||
for id in ingredients_ids {
|
||||
query = query.bind(id);
|
||||
|
|
@ -755,6 +751,73 @@ VALUES ($1, $2)
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn add_schedule_recipe(
|
||||
&self,
|
||||
user_id: i64,
|
||||
recipe_id: i64,
|
||||
date: NaiveDate,
|
||||
servings: u32,
|
||||
) -> Result<()> {
|
||||
sqlx::query(
|
||||
r#"
|
||||
INSERT INTO [RecipeScheduled] (user_id, recipe_id, date, servings)
|
||||
VALUES ($1, $2, $3, $4)
|
||||
"#,
|
||||
)
|
||||
.bind(user_id)
|
||||
.bind(recipe_id)
|
||||
.bind(date)
|
||||
.bind(servings)
|
||||
.execute(&self.pool)
|
||||
.await
|
||||
.map(|_| ())
|
||||
.map_err(DBError::from)
|
||||
}
|
||||
|
||||
pub async fn remove_scheduled_recipe(
|
||||
&self,
|
||||
user_id: i64,
|
||||
recipe_id: i64,
|
||||
date: NaiveDate,
|
||||
) -> Result<()> {
|
||||
sqlx::query(
|
||||
r#"
|
||||
DELETE FROM [RecipeScheduled]
|
||||
WHERE [user_id] = $1 AND [recipe_id] = $2 AND [date] = $3
|
||||
"#,
|
||||
)
|
||||
.bind(user_id)
|
||||
.bind(recipe_id)
|
||||
.bind(date)
|
||||
.execute(&self.pool)
|
||||
.await
|
||||
.map(|_| ())
|
||||
.map_err(DBError::from)
|
||||
}
|
||||
|
||||
pub async fn get_scheduled_recipes(
|
||||
&self,
|
||||
user_id: i64,
|
||||
start_date: NaiveDate,
|
||||
end_date: NaiveDate,
|
||||
) -> Result<Vec<(NaiveDate, String, i64)>> {
|
||||
sqlx::query_as(
|
||||
r#"
|
||||
SELECT [date], [Recipe].[title], [Recipe].[id], [RecipeScheduled].[date]
|
||||
FROM [RecipeScheduled]
|
||||
INNER JOIN [Recipe] ON [Recipe].[id] = [RecipeScheduled].[recipe_id]
|
||||
WHERE [RecipeScheduled].[user_id] = $1 AND [date] >= $2 AND [date] <= $3
|
||||
ORDER BY [date]
|
||||
"#,
|
||||
)
|
||||
.bind(user_id)
|
||||
.bind(start_date)
|
||||
.bind(end_date)
|
||||
.fetch_all(&self.pool)
|
||||
.await
|
||||
.map_err(DBError::from)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
@ -884,4 +947,83 @@ VALUES
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn schedule_recipe() -> Result<()> {
|
||||
let connection = Connection::new_in_memory().await?;
|
||||
let user_id = create_a_user(&connection).await?;
|
||||
|
||||
let recipe_id_1 = connection.create_recipe(user_id).await?;
|
||||
connection.set_recipe_title(recipe_id_1, "recipe 1").await?;
|
||||
|
||||
let recipe_id_2 = connection.create_recipe(user_id).await?;
|
||||
connection.set_recipe_title(recipe_id_2, "recipe 2").await?;
|
||||
|
||||
let today = NaiveDate::from_ymd_opt(2025, 1, 23).unwrap();
|
||||
let yesterday = today - Days::new(1);
|
||||
let tomorrow = today + Days::new(1);
|
||||
|
||||
connection
|
||||
.add_schedule_recipe(user_id, recipe_id_1, today, 4)
|
||||
.await?;
|
||||
connection
|
||||
.add_schedule_recipe(user_id, recipe_id_2, yesterday, 4)
|
||||
.await?;
|
||||
connection
|
||||
.add_schedule_recipe(user_id, recipe_id_1, tomorrow, 4)
|
||||
.await?;
|
||||
|
||||
assert_eq!(
|
||||
connection
|
||||
.get_scheduled_recipes(user_id, today, today)
|
||||
.await?,
|
||||
vec![(
|
||||
NaiveDate::from_ymd_opt(2025, 1, 23).unwrap(),
|
||||
"recipe 1".to_string(),
|
||||
1
|
||||
)]
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
connection
|
||||
.get_scheduled_recipes(user_id, yesterday, tomorrow)
|
||||
.await?,
|
||||
vec![
|
||||
(
|
||||
NaiveDate::from_ymd_opt(2025, 1, 22).unwrap(),
|
||||
"recipe 2".to_string(),
|
||||
2
|
||||
),
|
||||
(
|
||||
NaiveDate::from_ymd_opt(2025, 1, 23).unwrap(),
|
||||
"recipe 1".to_string(),
|
||||
1
|
||||
),
|
||||
(
|
||||
NaiveDate::from_ymd_opt(2025, 1, 24).unwrap(),
|
||||
"recipe 1".to_string(),
|
||||
1
|
||||
)
|
||||
]
|
||||
);
|
||||
|
||||
connection
|
||||
.remove_scheduled_recipe(user_id, recipe_id_1, today)
|
||||
.await?;
|
||||
connection
|
||||
.remove_scheduled_recipe(user_id, recipe_id_2, yesterday)
|
||||
.await?;
|
||||
connection
|
||||
.remove_scheduled_recipe(user_id, recipe_id_1, tomorrow)
|
||||
.await?;
|
||||
|
||||
assert_eq!(
|
||||
connection
|
||||
.get_scheduled_recipes(user_id, yesterday, tomorrow)
|
||||
.await?,
|
||||
vec![]
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use chrono::{prelude::*, Duration};
|
||||
use rand::distributions::{Alphanumeric, DistString};
|
||||
use rand::distr::{Alphanumeric, SampleString};
|
||||
use sqlx::Sqlite;
|
||||
|
||||
use super::{Connection, DBError, Result};
|
||||
|
|
@ -57,7 +57,7 @@ pub enum ResetPasswordResult {
|
|||
}
|
||||
|
||||
fn generate_token() -> String {
|
||||
Alphanumeric.sample_string(&mut rand::thread_rng(), consts::TOKEN_SIZE)
|
||||
Alphanumeric.sample_string(&mut rand::rng(), consts::TOKEN_SIZE)
|
||||
}
|
||||
|
||||
impl Connection {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue