aboutsummaryrefslogtreecommitdiff
path: root/src/controller
diff options
context:
space:
mode:
Diffstat (limited to 'src/controller')
-rw-r--r--src/controller/balance.rs49
-rw-r--r--src/controller/balancing.rs191
-rw-r--r--src/controller/categories.rs57
-rw-r--r--src/controller/error.rs16
-rw-r--r--src/controller/incomes.rs87
-rw-r--r--src/controller/login.rs34
-rw-r--r--src/controller/mod.rs1
-rw-r--r--src/controller/payments.rs103
-rw-r--r--src/controller/statistics.rs23
-rw-r--r--src/controller/utils.rs45
-rw-r--r--src/controller/wallet.rs7
11 files changed, 423 insertions, 190 deletions
diff --git a/src/controller/balance.rs b/src/controller/balance.rs
index c5d9d4a..9398dae 100644
--- a/src/controller/balance.rs
+++ b/src/controller/balance.rs
@@ -1,29 +1,32 @@
use http_body_util::Full;
-use hyper::body::Bytes;
use hyper::Response;
+use hyper::body::Bytes;
use std::collections::HashMap;
-use tera::Context;
use crate::controller::utils;
use crate::controller::wallet::Wallet;
use crate::db;
+use crate::model::balancing::Balancing;
use crate::model::user::User;
use crate::payer;
use crate::templates;
pub async fn get(wallet: &Wallet) -> Response<Full<Bytes>> {
- let users = db::users::list(&wallet.pool).await;
+ let users = db::users::list(&wallet.db_conn).await;
- let incomes_from = db::incomes::defined_for_all(&wallet.pool).await;
+ let incomes_from = db::incomes::defined_for_all(&wallet.db_conn).await;
let user_incomes = match incomes_from {
- Some(from) => db::incomes::cumulative(&wallet.pool, from).await,
+ Some(from) => db::incomes::cumulative(&wallet.db_conn, from).await,
None => HashMap::new(),
};
let template_user_incomes =
get_template_user_incomes(&users, &user_incomes);
let total_income: i64 = user_incomes.values().sum();
- let user_payments = db::payments::repartition(&wallet.pool).await;
+ let user_payments = with_balancing(
+ db::payments::repartition(&wallet.db_conn).await,
+ db::balancing::list(&wallet.db_conn).await,
+ );
let template_user_payments =
get_template_user_payments(&users, &user_payments);
let total_payments: i64 = user_payments.iter().map(|p| p.1).sum();
@@ -31,18 +34,16 @@ pub async fn get(wallet: &Wallet) -> Response<Full<Bytes>> {
let exceeding_payers =
payer::exceeding(&users, &user_incomes, &user_payments);
- let mut context = Context::new();
- context.insert("header", &templates::Header::Balance);
- context.insert("connected_user", &wallet.user);
- context.insert(
- "incomes_from",
- &incomes_from.map(|d| d.format("%d/%m/%Y").to_string()),
+ let context = minijinja::context!(
+ header => templates::Header::Balance,
+ connected_user => wallet.user,
+ incomes_from => incomes_from.map(|d| d.format("%d/%m/%Y").to_string()),
+ total_income => total_income,
+ user_incomes => template_user_incomes,
+ total_payments => total_payments,
+ user_payments => template_user_payments,
+ exceeding_payers => exceeding_payers
);
- context.insert("total_income", &total_income);
- context.insert("user_incomes", &template_user_incomes);
- context.insert("total_payments", &total_payments);
- context.insert("user_payments", &template_user_payments);
- context.insert("exceeding_payers", &exceeding_payers);
utils::template(&wallet.assets, &wallet.templates, "balance.html", context)
}
@@ -70,3 +71,17 @@ fn get_template_user_incomes(
user_incomes.sort_by_key(|i| i.1);
user_incomes
}
+
+fn with_balancing(
+ user_payments: HashMap<i64, i64>,
+ balancings: Vec<Balancing>,
+) -> HashMap<i64, i64> {
+ let mut user_payments = user_payments;
+ for balancing in balancings {
+ let src = user_payments.entry(balancing.source).or_insert(0);
+ *src += balancing.amount;
+ let dest = user_payments.entry(balancing.destination).or_insert(0);
+ *dest -= balancing.amount;
+ }
+ user_payments
+}
diff --git a/src/controller/balancing.rs b/src/controller/balancing.rs
new file mode 100644
index 0000000..c3d5ee8
--- /dev/null
+++ b/src/controller/balancing.rs
@@ -0,0 +1,191 @@
+use http_body_util::Full;
+use hyper::Response;
+use hyper::body::Bytes;
+use std::collections::HashMap;
+
+use crate::controller::utils;
+use crate::controller::wallet::Wallet;
+use crate::db;
+use crate::queries;
+use crate::templates;
+use crate::validation;
+
+static PER_PAGE: i64 = 10;
+
+pub async fn table(
+ wallet: &Wallet,
+ query: queries::Balancing,
+) -> Response<Full<Bytes>> {
+ let page = query.page.unwrap_or(1);
+ let count = db::balancing::count(&wallet.db_conn).await;
+ let balancings =
+ db::balancing::list_for_table(&wallet.db_conn, page, PER_PAGE).await;
+ let max_page = (count as f32 / PER_PAGE as f32).ceil() as i64;
+
+ let context = minijinja::context!(
+ header => templates::Header::Balancing,
+ connected_user => wallet.user,
+ balancings => balancings,
+ page => page,
+ max_page => max_page,
+ highlight => query.highlight
+ );
+
+ utils::template(
+ &wallet.assets,
+ &wallet.templates,
+ "balancing/table.html",
+ context,
+ )
+}
+
+pub async fn create_form(
+ wallet: &Wallet,
+ query: queries::Balancing,
+) -> Response<Full<Bytes>> {
+ create_form_feedback(wallet, query, HashMap::new(), None).await
+}
+
+async fn create_form_feedback(
+ wallet: &Wallet,
+ query: queries::Balancing,
+ form: HashMap<String, String>,
+ error: Option<String>,
+) -> Response<Full<Bytes>> {
+ let users = db::users::list(&wallet.db_conn).await;
+
+ let context = minijinja::context!(
+ header => templates::Header::Balancing,
+ connected_user => wallet.user,
+ users => users,
+ query => query,
+ form => form,
+ error => error,
+ );
+
+ utils::template(
+ &wallet.assets,
+ &wallet.templates,
+ "balancing/create.html",
+ context,
+ )
+}
+
+pub async fn create(
+ wallet: &Wallet,
+ query: queries::Balancing,
+ form: HashMap<String, String>,
+) -> Response<Full<Bytes>> {
+ let error = |e: &str| {
+ create_form_feedback(wallet, query, form.clone(), Some(e.to_string()))
+ };
+
+ match validation::balancing::create(&form) {
+ Some(balancing) => {
+ match db::balancing::create(&wallet.db_conn, balancing).await {
+ Some(id) => {
+ let row = db::balancing::get_row(&wallet.db_conn, id).await;
+ let page = (row - 1) / PER_PAGE + 1;
+ utils::redirect(&format!(
+ "/balancings?page={}&highlight={}",
+ page, id
+ ))
+ }
+ None => error("Erreur serveur").await,
+ }
+ }
+ None => error("Erreur lors de la validation du formulaire.").await,
+ }
+}
+
+pub async fn update_form(
+ id: i64,
+ wallet: &Wallet,
+ query: queries::Balancing,
+) -> Response<Full<Bytes>> {
+ update_form_feedback(id, wallet, query, HashMap::new(), None).await
+}
+
+async fn update_form_feedback(
+ id: i64,
+ wallet: &Wallet,
+ query: queries::Balancing,
+ form: HashMap<String, String>,
+ error: Option<String>,
+) -> Response<Full<Bytes>> {
+ let users = db::users::list(&wallet.db_conn).await;
+ let balancing = db::balancing::get(&wallet.db_conn, id).await;
+
+ let context = minijinja::context!(
+ header => &templates::Header::Balancing,
+ connected_user => &wallet.user,
+ users => &users,
+ id => &id,
+ balancing => &balancing,
+ query => &query,
+ form => &form,
+ error => &error
+ );
+
+ utils::template(
+ &wallet.assets,
+ &wallet.templates,
+ "balancing/update.html",
+ context,
+ )
+}
+
+pub async fn update(
+ id: i64,
+ wallet: &Wallet,
+ query: queries::Balancing,
+ form: HashMap<String, String>,
+) -> Response<Full<Bytes>> {
+ let error = |e: &str| {
+ update_form_feedback(
+ id,
+ wallet,
+ query,
+ form.clone(),
+ Some(e.to_string()),
+ )
+ };
+
+ match validation::balancing::update(&form) {
+ Some(balancing) => {
+ if db::balancing::update(&wallet.db_conn, id, balancing).await {
+ let row = db::balancing::get_row(&wallet.db_conn, id).await;
+ let page = (row - 1) / PER_PAGE + 1;
+ utils::redirect(&format!(
+ "/balancings?page={}&highlight={}",
+ page, id
+ ))
+ } else {
+ error("Erreur serveur").await
+ }
+ }
+ None => error("Erreur lors de la validation du formulaire.").await,
+ }
+}
+
+pub async fn delete(
+ id: i64,
+ wallet: &Wallet,
+ query: queries::Balancing,
+) -> Response<Full<Bytes>> {
+ if db::balancing::delete(&wallet.db_conn, id).await {
+ utils::redirect(&format!(
+ "/balancings?page={}",
+ query.page.unwrap_or(1)
+ ))
+ } else {
+ update_form_feedback(
+ id,
+ wallet,
+ query,
+ HashMap::new(),
+ Some("Erreur serveur".to_string()),
+ )
+ .await
+ }
+}
diff --git a/src/controller/categories.rs b/src/controller/categories.rs
index ff2d8e7..bda2abc 100644
--- a/src/controller/categories.rs
+++ b/src/controller/categories.rs
@@ -1,8 +1,7 @@
use http_body_util::Full;
-use hyper::body::Bytes;
use hyper::Response;
+use hyper::body::Bytes;
use std::collections::HashMap;
-use tera::Context;
use crate::controller::utils;
use crate::controller::wallet::Wallet;
@@ -15,13 +14,14 @@ pub async fn table(
wallet: &Wallet,
query: queries::Categories,
) -> Response<Full<Bytes>> {
- let categories = db::categories::list(&wallet.pool).await;
+ let categories = db::categories::list(&wallet.db_conn).await;
- let mut context = Context::new();
- context.insert("header", &templates::Header::Categories);
- context.insert("connected_user", &wallet.user);
- context.insert("categories", &categories);
- context.insert("highlight", &query.highlight);
+ let context = minijinja::context!(
+ header => templates::Header::Categories,
+ connected_user => wallet.user,
+ categories => categories,
+ highlight => query.highlight
+ );
utils::template(
&wallet.assets,
@@ -40,11 +40,12 @@ async fn create_form_feedback(
form: HashMap<String, String>,
error: Option<String>,
) -> Response<Full<Bytes>> {
- let mut context = Context::new();
- context.insert("header", &templates::Header::Categories);
- context.insert("connected_user", &wallet.user.clone());
- context.insert("form", &form);
- context.insert("error", &error);
+ let context = minijinja::context!(
+ header => &templates::Header::Categories,
+ connected_user => &wallet.user.clone(),
+ form => &form,
+ error => &error
+ );
utils::template(
&wallet.assets,
@@ -64,7 +65,7 @@ pub async fn create(
match validation::category::create(&form) {
Some(category) => {
- match db::categories::create(&wallet.pool, &category).await {
+ match db::categories::create(&wallet.db_conn, category).await {
Some(id) => {
utils::redirect(&format!("/categories?highlight={}", id))
}
@@ -85,18 +86,19 @@ async fn update_form_feedback(
form: HashMap<String, String>,
error: Option<String>,
) -> Response<Full<Bytes>> {
- let category = db::categories::get(&wallet.pool, id).await;
+ let category = db::categories::get(&wallet.db_conn, id).await;
let is_category_used =
- db::payments::is_category_used(&wallet.pool, id).await;
-
- let mut context = Context::new();
- context.insert("header", &templates::Header::Categories);
- context.insert("connected_user", &wallet.user);
- context.insert("id", &id);
- context.insert("category", &category);
- context.insert("is_category_used", &is_category_used);
- context.insert("form", &form);
- context.insert("error", &error);
+ db::payments::is_category_used(&wallet.db_conn, id).await;
+
+ let context = minijinja::context!(
+ header => templates::Header::Categories,
+ connected_user => wallet.user,
+ id => id,
+ category => category,
+ is_category_used => is_category_used,
+ form => form,
+ error => error
+ );
utils::template(
&wallet.assets,
@@ -117,7 +119,8 @@ pub async fn update(
match validation::category::update(&form) {
Some(update_category) => {
- if db::categories::update(&wallet.pool, id, &update_category).await
+ if db::categories::update(&wallet.db_conn, id, update_category)
+ .await
{
utils::redirect(&format!("/categories?highlight={}", id))
} else {
@@ -129,7 +132,7 @@ pub async fn update(
}
pub async fn delete(id: i64, wallet: &Wallet) -> Response<Full<Bytes>> {
- if db::categories::delete(&wallet.pool, id).await {
+ if db::categories::delete(&wallet.db_conn, id).await {
utils::redirect("/categories")
} else {
update_form_feedback(
diff --git a/src/controller/error.rs b/src/controller/error.rs
index 0f6dcc1..dc04421 100644
--- a/src/controller/error.rs
+++ b/src/controller/error.rs
@@ -1,9 +1,8 @@
use http_body_util::Full;
+use hyper::Response;
use hyper::body::Bytes;
use hyper::header::CACHE_CONTROL;
-use hyper::Response;
use std::collections::HashMap;
-use tera::{Context, Tera};
use crate::controller::utils;
use crate::controller::wallet::Wallet;
@@ -24,14 +23,15 @@ pub fn error(
pub fn template(
assets: &HashMap<String, String>,
- templates: &Tera,
+ templates: &minijinja::Environment<'_>,
title: &str,
message: &str,
) -> String {
- let mut context = Context::new();
- context.insert("title", title);
- context.insert("message", message);
- context.insert("assets", assets);
+ let context = minijinja::context!(
+ title => title,
+ message => message,
+ assets => assets
+ );
- templates.render("error.html", &context).unwrap()
+ templates.render_str("error.html", &context).unwrap()
}
diff --git a/src/controller/incomes.rs b/src/controller/incomes.rs
index f22098b..3c8f15d 100644
--- a/src/controller/incomes.rs
+++ b/src/controller/incomes.rs
@@ -1,10 +1,9 @@
use chrono::Datelike;
use chrono::Utc;
use http_body_util::Full;
-use hyper::body::Bytes;
use hyper::Response;
+use hyper::body::Bytes;
use std::collections::HashMap;
-use tera::Context;
use crate::controller::utils;
use crate::controller::wallet::Wallet;
@@ -20,17 +19,18 @@ pub async fn table(
query: queries::Incomes,
) -> Response<Full<Bytes>> {
let page = query.page.unwrap_or(1);
- let count = db::incomes::count(&wallet.pool).await;
- let incomes = db::incomes::list(&wallet.pool, page, PER_PAGE).await;
+ let count = db::incomes::count(&wallet.db_conn).await;
+ let incomes = db::incomes::list(&wallet.db_conn, page, PER_PAGE).await;
let max_page = (count as f32 / PER_PAGE as f32).ceil() as i64;
- let mut context = Context::new();
- context.insert("header", &templates::Header::Incomes);
- context.insert("connected_user", &wallet.user);
- context.insert("incomes", &incomes);
- context.insert("page", &page);
- context.insert("max_page", &max_page);
- context.insert("highlight", &query.highlight);
+ let context = minijinja::context!(
+ header => templates::Header::Incomes,
+ connected_user => wallet.user,
+ incomes => incomes,
+ page => page,
+ max_page => max_page,
+ highlight => query.highlight
+ );
utils::template(
&wallet.assets,
@@ -68,17 +68,18 @@ async fn create_form_feedback(
form: HashMap<String, String>,
error: Option<String>,
) -> Response<Full<Bytes>> {
- let users = db::users::list(&wallet.pool).await;
-
- let mut context = Context::new();
- context.insert("header", &templates::Header::Incomes);
- context.insert("connected_user", &wallet.user);
- context.insert("users", &users);
- context.insert("query", &query);
- context.insert("current_month", &Utc::now().date_naive().month());
- context.insert("months", &MONTHS);
- context.insert("form", &form);
- context.insert("error", &error);
+ let users = db::users::list(&wallet.db_conn).await;
+
+ let context = minijinja::context!(
+ header => templates::Header::Incomes,
+ connected_user => wallet.user,
+ users => users,
+ query => query,
+ current_month => Utc::now().date_naive().month(),
+ months => MONTHS,
+ form => form,
+ error => error,
+ );
utils::template(
&wallet.assets,
@@ -100,7 +101,7 @@ pub async fn create(
match validation::income::create(&form) {
Some(income) => {
if !db::incomes::defined_at(
- &wallet.pool,
+ &wallet.db_conn,
income.user_id,
income.date,
)
@@ -109,9 +110,10 @@ pub async fn create(
{
error("Un revenu est déjà défini à cette date.").await
} else {
- match db::incomes::create(&wallet.pool, &income).await {
+ match db::incomes::create(&wallet.db_conn, income).await {
Some(id) => {
- let row = db::incomes::get_row(&wallet.pool, id).await;
+ let row =
+ db::incomes::get_row(&wallet.db_conn, id).await;
let page = (row - 1) / PER_PAGE + 1;
utils::redirect(&format!(
"/incomes?page={}&highlight={}",
@@ -141,19 +143,20 @@ async fn update_form_feedback(
form: HashMap<String, String>,
error: Option<String>,
) -> Response<Full<Bytes>> {
- let users = db::users::list(&wallet.pool).await;
- let income = db::incomes::get(&wallet.pool, id).await;
-
- let mut context = Context::new();
- context.insert("header", &templates::Header::Incomes);
- context.insert("connected_user", &wallet.user);
- context.insert("users", &users);
- context.insert("id", &id);
- context.insert("income", &income);
- context.insert("query", &query);
- context.insert("months", &MONTHS);
- context.insert("form", &form);
- context.insert("error", &error);
+ let users = db::users::list(&wallet.db_conn).await;
+ let income = db::incomes::get(&wallet.db_conn, id).await;
+
+ let context = minijinja::context!(
+ header => &templates::Header::Incomes,
+ connected_user => &wallet.user,
+ users => &users,
+ id => &id,
+ income => &income,
+ query => &query,
+ months => &MONTHS,
+ form => &form,
+ error => &error
+ );
utils::template(
&wallet.assets,
@@ -182,15 +185,15 @@ pub async fn update(
match validation::income::update(&form) {
Some(income) => {
let existing_incomes = db::incomes::defined_at(
- &wallet.pool,
+ &wallet.db_conn,
income.user_id,
income.date,
)
.await;
if existing_incomes.into_iter().any(|eid| eid != id) {
error("Un revenu est déjà défini à cette date.").await
- } else if db::incomes::update(&wallet.pool, id, &income).await {
- let row = db::incomes::get_row(&wallet.pool, id).await;
+ } else if db::incomes::update(&wallet.db_conn, id, income).await {
+ let row = db::incomes::get_row(&wallet.db_conn, id).await;
let page = (row - 1) / PER_PAGE + 1;
utils::redirect(&format!(
"/incomes?page={}&highlight={}",
@@ -209,7 +212,7 @@ pub async fn delete(
wallet: &Wallet,
query: queries::Incomes,
) -> Response<Full<Bytes>> {
- if db::incomes::delete(&wallet.pool, id).await {
+ if db::incomes::delete(&wallet.db_conn, id).await {
utils::redirect(&format!("/incomes?page={}", query.page.unwrap_or(1)))
} else {
update_form_feedback(
diff --git a/src/controller/login.rs b/src/controller/login.rs
index dd50a3a..252fdf8 100644
--- a/src/controller/login.rs
+++ b/src/controller/login.rs
@@ -1,11 +1,10 @@
use bcrypt;
use http_body_util::Full;
+use hyper::Response;
use hyper::body::Bytes;
use hyper::header::SET_COOKIE;
-use hyper::Response;
-use sqlx::sqlite::SqlitePool;
use std::collections::HashMap;
-use tera::{Context, Tera};
+use tokio_rusqlite::Connection;
use crate::controller::utils::with_headers;
use crate::controller::wallet::Wallet;
@@ -18,14 +17,15 @@ use crate::validation;
pub async fn page(
assets: &HashMap<String, String>,
- templates: &Tera,
+ templates: &minijinja::Environment<'_>,
error: Option<&str>,
) -> Response<Full<Bytes>> {
let connected_user: Option<User> = None;
- let mut context = Context::new();
- context.insert("connected_user", &connected_user);
- context.insert("error", &error);
+ let context = minijinja::context!(
+ connected_user => &connected_user,
+ error => &error
+ );
utils::template(assets, templates, "login.html", context)
}
@@ -33,20 +33,21 @@ pub async fn page(
pub async fn login(
config: &Config,
assets: &HashMap<String, String>,
- templates: &Tera,
+ templates: &minijinja::Environment<'_>,
form: HashMap<String, String>,
- pool: SqlitePool,
+ db_conn: Connection,
) -> Response<Full<Bytes>> {
match validation::login::login(&form) {
Some(login) => {
- match db::users::get_password_hash(&pool, login.email.clone()).await
+ match db::users::get_password_hash(&db_conn, login.email.clone())
+ .await
{
Some(hash) => match bcrypt::verify(login.password, &hash) {
Ok(true) => {
let login_token = cookie::generate_token();
if db::users::set_login_token(
- &pool,
+ &db_conn,
login.email,
login_token.clone().to_string(),
)
@@ -75,7 +76,10 @@ pub async fn login(
}
Ok(false) => not_authorized(assets, templates).await,
Err(err) => {
- error!("Error verifying bcrypt password: {:?}", err);
+ log::error!(
+ "Error verifying bcrypt password: {:?}",
+ err
+ );
server_error(assets, templates, "Erreur serveur").await
}
},
@@ -88,7 +92,7 @@ pub async fn login(
async fn server_error(
assets: &HashMap<String, String>,
- templates: &Tera,
+ templates: &minijinja::Environment<'_>,
msg: &str,
) -> Response<Full<Bytes>> {
page(assets, templates, Some(msg)).await
@@ -96,7 +100,7 @@ async fn server_error(
async fn not_authorized(
assets: &HashMap<String, String>,
- templates: &Tera,
+ templates: &minijinja::Environment<'_>,
) -> Response<Full<Bytes>> {
page(
assets,
@@ -107,7 +111,7 @@ async fn not_authorized(
}
pub async fn logout(config: &Config, wallet: &Wallet) -> Response<Full<Bytes>> {
- if db::users::remove_login_token(&wallet.pool, wallet.user.id).await {
+ if db::users::remove_login_token(&wallet.db_conn, wallet.user.id).await {
with_headers(
utils::redirect("/"),
vec![(SET_COOKIE, &cookie::logout(config))],
diff --git a/src/controller/mod.rs b/src/controller/mod.rs
index e2ef561..bbead68 100644
--- a/src/controller/mod.rs
+++ b/src/controller/mod.rs
@@ -1,4 +1,5 @@
pub mod balance;
+pub mod balancing;
pub mod categories;
pub mod error;
pub mod incomes;
diff --git a/src/controller/payments.rs b/src/controller/payments.rs
index 8184015..554f61a 100644
--- a/src/controller/payments.rs
+++ b/src/controller/payments.rs
@@ -1,9 +1,8 @@
use http_body_util::Full;
+use hyper::Response;
use hyper::body::Bytes;
use hyper::header::CONTENT_TYPE;
-use hyper::Response;
use std::collections::HashMap;
-use tera::Context;
use crate::controller::utils;
use crate::controller::wallet::Wallet;
@@ -20,24 +19,25 @@ pub async fn table(
query: queries::Payments,
) -> Response<Full<Bytes>> {
let page = query.page.unwrap_or(1);
- let count = db::payments::count(&wallet.pool, &query).await;
+ let count = db::payments::count(&wallet.db_conn, &query).await;
let payments =
- db::payments::list_for_table(&wallet.pool, &query, PER_PAGE).await;
+ db::payments::list_for_table(&wallet.db_conn, &query, PER_PAGE).await;
let max_page = (count.count as f32 / PER_PAGE as f32).ceil() as i64;
- let users = db::users::list(&wallet.pool).await;
- let categories = db::categories::list(&wallet.pool).await;
-
- let mut context = Context::new();
- context.insert("header", &templates::Header::Payments);
- context.insert("connected_user", &wallet.user);
- context.insert("payments", &payments);
- context.insert("page", &page);
- context.insert("max_page", &max_page);
- context.insert("query", &query);
- context.insert("count", &count.count);
- context.insert("total_cost", &count.total_cost);
- context.insert("users", &users);
- context.insert("categories", &categories);
+ let users = db::users::list(&wallet.db_conn).await;
+ let categories = db::categories::list(&wallet.db_conn).await;
+
+ let context = minijinja::context!(
+ header => templates::Header::Payments,
+ connected_user => wallet.user,
+ payments => payments,
+ page => page,
+ max_page => max_page,
+ query => query,
+ count => count.count,
+ total_cost => count.total_cost,
+ users => users,
+ categories => categories
+ );
utils::template(
&wallet.assets,
@@ -60,17 +60,18 @@ async fn create_form_feedback(
form: HashMap<String, String>,
error: Option<String>,
) -> Response<Full<Bytes>> {
- let users = db::users::list(&wallet.pool).await;
- let categories = db::categories::list(&wallet.pool).await;
-
- let mut context = Context::new();
- context.insert("header", &templates::Header::Payments);
- context.insert("connected_user", &wallet.user);
- context.insert("users", &users);
- context.insert("categories", &categories);
- context.insert("query", &query);
- context.insert("form", &form);
- context.insert("error", &error);
+ let users = db::users::list(&wallet.db_conn).await;
+ let categories = db::categories::list(&wallet.db_conn).await;
+
+ let context = minijinja::context!(
+ header => templates::Header::Payments,
+ connected_user => wallet.user,
+ users => users,
+ categories => categories,
+ query => query,
+ form => form,
+ error => error
+ );
utils::template(
&wallet.assets,
@@ -91,10 +92,12 @@ pub async fn create(
match validation::payment::create(&form) {
Some(create_payment) => {
- match db::payments::create(&wallet.pool, &create_payment).await {
+ match db::payments::create(&wallet.db_conn, create_payment.clone())
+ .await
+ {
Some(id) => {
let row = db::payments::get_row(
- &wallet.pool,
+ &wallet.db_conn,
id,
create_payment.frequency,
)
@@ -138,20 +141,21 @@ async fn update_form_feedback(
form: HashMap<String, String>,
error: Option<String>,
) -> Response<Full<Bytes>> {
- let payment = db::payments::get_for_form(&wallet.pool, id).await;
- let users = db::users::list(&wallet.pool).await;
- let categories = db::categories::list(&wallet.pool).await;
-
- let mut context = Context::new();
- context.insert("header", &templates::Header::Payments);
- context.insert("connected_user", &wallet.user);
- context.insert("id", &id);
- context.insert("payment", &payment);
- context.insert("users", &users);
- context.insert("categories", &categories);
- context.insert("query", &query);
- context.insert("form", &form);
- context.insert("error", &error);
+ let payment = db::payments::get_for_form(&wallet.db_conn, id).await;
+ let users = db::users::list(&wallet.db_conn).await;
+ let categories = db::categories::list(&wallet.db_conn).await;
+
+ let context = minijinja::context!(
+ header => templates::Header::Payments,
+ connected_user => wallet.user,
+ id => id,
+ payment => payment,
+ users => users,
+ categories => categories,
+ query => query,
+ form => form,
+ error => error
+ );
utils::template(
&wallet.assets,
@@ -179,10 +183,10 @@ pub async fn update(
match validation::payment::update(&form) {
Some(update_payment) => {
- if db::payments::update(&wallet.pool, id, &update_payment).await {
+ if db::payments::update(&wallet.db_conn, id, update_payment).await {
let frequency = query.frequency.unwrap_or(Frequency::Punctual);
let row =
- db::payments::get_row(&wallet.pool, id, frequency).await;
+ db::payments::get_row(&wallet.db_conn, id, frequency).await;
let page = (row - 1) / PER_PAGE + 1;
// TODO: keep name, cost, user and category when updating a line
let query = queries::Payments {
@@ -210,7 +214,7 @@ pub async fn delete(
wallet: &Wallet,
query: queries::Payments,
) -> Response<Full<Bytes>> {
- if db::payments::delete(&wallet.pool, id).await {
+ if db::payments::delete(&wallet.db_conn, id).await {
let query = queries::Payments {
highlight: None,
..query
@@ -232,7 +236,8 @@ pub async fn search_category(
wallet: &Wallet,
query: queries::PaymentCategory,
) -> Response<Full<Bytes>> {
- match db::payments::search_category(&wallet.pool, query.payment_name).await
+ match db::payments::search_category(&wallet.db_conn, query.payment_name)
+ .await
{
Some(category_id) => utils::with_headers(
Response::new(format!("{}", category_id).into()),
diff --git a/src/controller/statistics.rs b/src/controller/statistics.rs
index eb1e704..5efbe73 100644
--- a/src/controller/statistics.rs
+++ b/src/controller/statistics.rs
@@ -1,7 +1,6 @@
use http_body_util::Full;
-use hyper::body::Bytes;
use hyper::Response;
-use tera::Context;
+use hyper::body::Bytes;
use crate::controller::utils;
use crate::controller::wallet::Wallet;
@@ -9,19 +8,17 @@ use crate::db;
use crate::templates;
pub async fn get(wallet: &Wallet) -> Response<Full<Bytes>> {
- let categories = db::categories::list(&wallet.pool).await;
- let payments = db::payments::list_for_stats(&wallet.pool).await;
- let incomes = db::incomes::total_each_month(&wallet.pool).await;
+ let categories = db::categories::list(&wallet.db_conn).await;
+ let payments = db::payments::list_for_stats(&wallet.db_conn).await;
+ let incomes = db::incomes::total_each_month(&wallet.db_conn).await;
- let mut context = Context::new();
- context.insert("header", &templates::Header::Statistics);
- context.insert("connected_user", &wallet.user);
- context.insert(
- "json_categories",
- &serde_json::to_string(&categories).unwrap(),
+ let context = minijinja::context!(
+ header => templates::Header::Statistics,
+ connected_user => wallet.user,
+ json_categories => serde_json::to_string(&categories).unwrap(),
+ json_payments => serde_json::to_string(&payments).unwrap(),
+ json_incomes => serde_json::to_string(&incomes).unwrap()
);
- context.insert("json_payments", &serde_json::to_string(&payments).unwrap());
- context.insert("json_incomes", &serde_json::to_string(&incomes).unwrap());
utils::template(
&wallet.assets,
diff --git a/src/controller/utils.rs b/src/controller/utils.rs
index 1b58c68..32eb1d0 100644
--- a/src/controller/utils.rs
+++ b/src/controller/utils.rs
@@ -1,11 +1,10 @@
use http_body_util::Full;
use hyper::body::Bytes;
use hyper::header::{
- HeaderName, HeaderValue, CACHE_CONTROL, CONTENT_TYPE, LOCATION,
+ CACHE_CONTROL, CONTENT_TYPE, HeaderName, HeaderValue, LOCATION,
};
use hyper::{Response, StatusCode};
use std::collections::HashMap;
-use tera::{Context, Tera};
use crate::controller::error;
@@ -23,29 +22,45 @@ pub fn with_headers(
pub fn template(
assets: &HashMap<String, String>,
- templates: &Tera,
+ templates: &minijinja::Environment<'_>,
path: &str,
- context: Context,
+ context: minijinja::Value,
) -> Response<Full<Bytes>> {
- let mut context = context;
- context.insert("assets", assets);
+ let context = minijinja::context! { ..context, ..minijinja::context! {
+ assets => assets
+ }};
- match templates.render(path, &context) {
+ match render_template(templates, path, context) {
Ok(template) => with_headers(
Response::new(template.into()),
vec![(CONTENT_TYPE, "text/html"), (CACHE_CONTROL, "no-cache")],
),
- Err(err) => server_error(
- assets,
- templates,
- &format!("Erreur lors de la préparation de la page : {:?}", err),
- ),
+ Err(err) => {
+ log::error!("ERROR template rendering {}\n{:?}", path, err);
+ server_error(
+ assets,
+ templates,
+ &format!(
+ "Erreur lors de la préparation de la page : {:?}",
+ err
+ ),
+ )
+ }
}
}
+fn render_template(
+ templates: &minijinja::Environment<'_>,
+ name: &str,
+ context: minijinja::Value,
+) -> Result<String, minijinja::Error> {
+ let template = templates.get_template(name)?;
+ template.render(context)
+}
+
fn server_error(
assets: &HashMap<String, String>,
- templates: &Tera,
+ templates: &minijinja::Environment<'_>,
msg: &str,
) -> Response<Full<Bytes>> {
with_headers(
@@ -56,8 +71,8 @@ fn server_error(
)
}
-pub fn text(str: String) -> Response<Full<Bytes>> {
- let mut response = Response::new(str.into());
+pub fn text(str: impl Into<String>) -> Response<Full<Bytes>> {
+ let mut response = Response::new(str.into().into());
*response.status_mut() = StatusCode::OK;
response
}
diff --git a/src/controller/wallet.rs b/src/controller/wallet.rs
index 2a4a593..edc773d 100644
--- a/src/controller/wallet.rs
+++ b/src/controller/wallet.rs
@@ -1,13 +1,12 @@
-use sqlx::sqlite::SqlitePool;
use std::collections::HashMap;
-use tera::Tera;
+use tokio_rusqlite::Connection;
use crate::model::user::User;
#[derive(Clone)]
pub struct Wallet {
- pub pool: SqlitePool,
+ pub db_conn: Connection,
pub assets: HashMap<String, String>,
- pub templates: Tera,
+ pub templates: minijinja::Environment<'static>,
pub user: User,
}