admin panel have more control over payment now
This commit is contained in:
@@ -335,6 +335,7 @@ async fn order_detail_page(
|
||||
.all(&ctx.db)
|
||||
.await?;
|
||||
|
||||
let (bank_iban, bank_account_name) = settings::bank_details(&ctx).await?;
|
||||
format::view(
|
||||
&v,
|
||||
"account/order_detail.html",
|
||||
@@ -347,8 +348,8 @@ async fn order_detail_page(
|
||||
"customer_avatar": user.avatar_id,
|
||||
"order": order_view::detail(
|
||||
&order,
|
||||
settings::get(&ctx, "bank_iban").unwrap_or(""),
|
||||
settings::get(&ctx, "bank_account_name").unwrap_or(""),
|
||||
&bank_iban,
|
||||
&bank_account_name,
|
||||
),
|
||||
"items": order_view::items(&items),
|
||||
"lang": current_lang(&jar),
|
||||
|
||||
@@ -93,6 +93,7 @@ async fn render_show(
|
||||
.await?;
|
||||
|
||||
let carrier = order_carrier(ctx, &order).await?;
|
||||
let (bank_iban, bank_account_name) = settings::bank_details(ctx).await?;
|
||||
// The order can be sent only if it maps to a real carrier and hasn't been
|
||||
// dispatched yet.
|
||||
let can_ship = carrier != "none" && order.tracking_number.is_none();
|
||||
@@ -103,8 +104,8 @@ async fn render_show(
|
||||
json!({
|
||||
"order": view::detail(
|
||||
&order,
|
||||
settings::get(ctx, "bank_iban").unwrap_or(""),
|
||||
settings::get(ctx, "bank_account_name").unwrap_or(""),
|
||||
&bank_iban,
|
||||
&bank_account_name,
|
||||
),
|
||||
"items": view::items(&items),
|
||||
"statuses": ORDER_STATUSES,
|
||||
|
||||
112
src/controllers/admin_payments.rs
Normal file
112
src/controllers/admin_payments.rs
Normal file
@@ -0,0 +1,112 @@
|
||||
//! Admin management for checkout payment methods and bank-transfer details.
|
||||
|
||||
use axum_extra::extract::cookie::CookieJar;
|
||||
use loco_rs::prelude::*;
|
||||
use sea_orm::{ActiveModelTrait, EntityTrait, QueryOrder, Set};
|
||||
use serde::Deserialize;
|
||||
use serde_json::json;
|
||||
|
||||
use crate::{
|
||||
controllers::i18n::current_lang,
|
||||
models::{payment_methods, shop_settings},
|
||||
shared::guard,
|
||||
};
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct PaymentMethodForm {
|
||||
enabled: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct BankSettingsForm {
|
||||
bank_account_name: String,
|
||||
bank_iban: String,
|
||||
}
|
||||
|
||||
fn is_checked(value: &Option<String>) -> bool {
|
||||
matches!(value.as_deref(), Some("on" | "true" | "1"))
|
||||
}
|
||||
|
||||
fn trimmed(value: &str) -> Option<String> {
|
||||
let value = value.trim();
|
||||
(!value.is_empty()).then(|| value.to_string())
|
||||
}
|
||||
|
||||
#[debug_handler]
|
||||
async fn index(
|
||||
auth: auth::JWT,
|
||||
jar: CookieJar,
|
||||
ViewEngine(v): ViewEngine<TeraView>,
|
||||
State(ctx): State<AppContext>,
|
||||
) -> Result<Response> {
|
||||
guard::current_admin(auth, &ctx).await?;
|
||||
let methods = payment_methods::Entity::find()
|
||||
.order_by_asc(payment_methods::Column::Position)
|
||||
.all(&ctx.db)
|
||||
.await?;
|
||||
let rows: Vec<serde_json::Value> = methods
|
||||
.iter()
|
||||
.map(|m| {
|
||||
json!({
|
||||
"id": m.id,
|
||||
"code": m.code,
|
||||
"label_key": m.label_key(),
|
||||
"enabled": m.enabled,
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
let bank_account_name = shop_settings::Entity::get(&ctx.db, "bank_account_name")
|
||||
.await?
|
||||
.unwrap_or_default();
|
||||
let bank_iban = shop_settings::Entity::get(&ctx.db, "bank_iban")
|
||||
.await?
|
||||
.unwrap_or_default();
|
||||
|
||||
format::view(
|
||||
&v,
|
||||
"admin/payments/index.html",
|
||||
json!({
|
||||
"methods": rows,
|
||||
"bank_account_name": bank_account_name,
|
||||
"bank_iban": bank_iban,
|
||||
"lang": current_lang(&jar),
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
#[debug_handler]
|
||||
async fn update_method(
|
||||
auth: auth::JWT,
|
||||
Path(id): Path<i32>,
|
||||
State(ctx): State<AppContext>,
|
||||
Form(form): Form<PaymentMethodForm>,
|
||||
) -> Result<Response> {
|
||||
guard::current_admin(auth, &ctx).await?;
|
||||
let method = payment_methods::Entity::find_by_id(id)
|
||||
.one(&ctx.db)
|
||||
.await?
|
||||
.ok_or_else(|| Error::NotFound)?;
|
||||
let mut active = method.into_active_model();
|
||||
active.enabled = Set(is_checked(&form.enabled));
|
||||
active.update(&ctx.db).await?;
|
||||
format::redirect("/admin/payments")
|
||||
}
|
||||
|
||||
#[debug_handler]
|
||||
async fn update_bank(
|
||||
auth: auth::JWT,
|
||||
State(ctx): State<AppContext>,
|
||||
Form(form): Form<BankSettingsForm>,
|
||||
) -> Result<Response> {
|
||||
guard::current_admin(auth, &ctx).await?;
|
||||
shop_settings::Entity::set(&ctx.db, "bank_account_name", trimmed(&form.bank_account_name)).await?;
|
||||
shop_settings::Entity::set(&ctx.db, "bank_iban", trimmed(&form.bank_iban)).await?;
|
||||
format::redirect("/admin/payments")
|
||||
}
|
||||
|
||||
pub fn routes() -> Routes {
|
||||
Routes::new()
|
||||
.add("/admin/payments", get(index))
|
||||
.add("/admin/payments/methods/{id}", post(update_method))
|
||||
.add("/admin/payments/bank", post(update_bank))
|
||||
}
|
||||
@@ -14,7 +14,7 @@ use crate::{
|
||||
mailers::auth::AuthMailer,
|
||||
models::{
|
||||
customer_profiles::{self, ProfileFields},
|
||||
order_items, orders, shipping_methods,
|
||||
order_items, orders, payment_methods, shipping_methods,
|
||||
users::{self, normalize_account_type},
|
||||
},
|
||||
controllers::i18n::current_lang,
|
||||
@@ -22,8 +22,6 @@ use crate::{
|
||||
views::checkout as view,
|
||||
};
|
||||
|
||||
const PAYMENT_METHODS: [&str; 2] = ["cod", "bank_transfer"];
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct CheckoutForm {
|
||||
email: String,
|
||||
@@ -76,6 +74,10 @@ async fn enabled_shipping_methods(ctx: &AppContext) -> Result<Vec<shipping_metho
|
||||
.await?)
|
||||
}
|
||||
|
||||
async fn enabled_payment_methods(ctx: &AppContext) -> Result<Vec<payment_methods::Model>> {
|
||||
Ok(payment_methods::Entity::enabled(&ctx.db).await?)
|
||||
}
|
||||
|
||||
#[debug_handler]
|
||||
async fn checkout_page(
|
||||
jar: CookieJar,
|
||||
@@ -102,6 +104,16 @@ async fn checkout_page(
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
let payments: Vec<serde_json::Value> = enabled_payment_methods(&ctx)
|
||||
.await?
|
||||
.iter()
|
||||
.map(|m| {
|
||||
json!({
|
||||
"code": m.code,
|
||||
"label_key": m.label_key(),
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Prefill the form for a logged-in customer: contact name/email come from
|
||||
// the user account, the address/phone from their saved profile (if any).
|
||||
@@ -130,6 +142,7 @@ async fn checkout_page(
|
||||
"subtotal": format_price(subtotal),
|
||||
"subtotal_cents": subtotal,
|
||||
"shipping_methods": methods,
|
||||
"payment_methods": payments,
|
||||
"packeta_api_key": settings::get(&ctx, "packeta_api_key").unwrap_or(""),
|
||||
"logged_in_admin": is_admin,
|
||||
"logged_in_customer": is_customer,
|
||||
@@ -239,7 +252,7 @@ async fn place_order(
|
||||
(None, None, None, None)
|
||||
};
|
||||
|
||||
if !PAYMENT_METHODS.contains(&form.payment_method.as_str()) {
|
||||
if payment_methods::Entity::find_enabled(&ctx.db, &form.payment_method).await?.is_none() {
|
||||
return Err(Error::BadRequest("invalid payment method".to_string()));
|
||||
}
|
||||
|
||||
@@ -392,14 +405,15 @@ async fn order_confirmation(
|
||||
let c = guard::chrome(&ctx, &jar).await;
|
||||
let account_created = params.contains_key("account_created");
|
||||
|
||||
let (bank_iban, bank_account_name) = settings::bank_details(&ctx).await?;
|
||||
format::view(
|
||||
&v,
|
||||
"shop/order_confirmed.html",
|
||||
json!({
|
||||
"order": view::detail(
|
||||
&order,
|
||||
settings::get(&ctx, "bank_iban").unwrap_or(""),
|
||||
settings::get(&ctx, "bank_account_name").unwrap_or(""),
|
||||
&bank_iban,
|
||||
&bank_account_name,
|
||||
),
|
||||
"items": view::items(&items),
|
||||
"logged_in_admin": c.logged_in_admin,
|
||||
|
||||
@@ -9,6 +9,7 @@ pub mod admin_dashboard;
|
||||
pub mod admin_discount_profiles;
|
||||
pub mod admin_form;
|
||||
pub mod admin_orders;
|
||||
pub mod admin_payments;
|
||||
pub mod admin_products;
|
||||
pub mod admin_shipping;
|
||||
pub mod cart;
|
||||
|
||||
Reference in New Issue
Block a user