global discount price
This commit is contained in:
@@ -9,20 +9,22 @@
|
||||
//! prices still layer on top (lowest price wins). Both are computed off the
|
||||
//! regular price.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use axum_extra::extract::cookie::CookieJar;
|
||||
use loco_rs::prelude::*;
|
||||
use sea_orm::{ActiveModelTrait, EntityTrait, QueryOrder, Set};
|
||||
use sea_orm::{
|
||||
ActiveModelTrait, ColumnTrait, EntityTrait, QueryFilter, QueryOrder, Set, TransactionTrait,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use serde_json::json;
|
||||
|
||||
use crate::{
|
||||
controllers::i18n::current_lang,
|
||||
models::products,
|
||||
models::{audience_discount_profiles, discount_profiles, products},
|
||||
shared::{
|
||||
guard,
|
||||
money::{format_price, parse_percent, parse_price_to_cents},
|
||||
money::{format_bp, format_price, parse_percent, parse_price_to_cents},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -122,13 +124,79 @@ async fn index(
|
||||
.all(&ctx.db)
|
||||
.await?;
|
||||
let rows: Vec<serde_json::Value> = list.iter().map(list_row).collect();
|
||||
|
||||
// Profiles applied globally to this audience, plus all profiles to choose from.
|
||||
let assigned: HashSet<i32> = audience_discount_profiles::Entity::find()
|
||||
.filter(audience_discount_profiles::Column::Audience.eq(audience))
|
||||
.all(&ctx.db)
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(|a| a.discount_profile_id)
|
||||
.collect();
|
||||
let all_profiles = discount_profiles::Entity::find()
|
||||
.order_by_asc(discount_profiles::Column::Name)
|
||||
.all(&ctx.db)
|
||||
.await?;
|
||||
let profiles: Vec<serde_json::Value> = all_profiles
|
||||
.iter()
|
||||
.map(|p| {
|
||||
json!({
|
||||
"id": p.id,
|
||||
"name": p.name,
|
||||
"percent": format_bp(p.percent_bp),
|
||||
"scope_type": p.scope_type,
|
||||
"assigned": assigned.contains(&p.id),
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
|
||||
format::view(
|
||||
&v,
|
||||
"admin/catalog/discounts.html",
|
||||
json!({ "products": rows, "audience": audience, "lang": current_lang(&jar) }),
|
||||
json!({
|
||||
"products": rows,
|
||||
"profiles": profiles,
|
||||
"audience": audience,
|
||||
"lang": current_lang(&jar),
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
/// Replace the profiles applied to this audience with the submitted checkbox set
|
||||
/// (`profile_ids`, a repeated field parsed directly from the body).
|
||||
#[debug_handler]
|
||||
async fn sync_profiles(
|
||||
auth: auth::JWT,
|
||||
Query(params): Query<HashMap<String, String>>,
|
||||
State(ctx): State<AppContext>,
|
||||
body: String,
|
||||
) -> Result<Response> {
|
||||
guard::current_admin(auth, &ctx).await?;
|
||||
let audience = read_audience(¶ms);
|
||||
|
||||
let profile_ids: Vec<i32> = form_urlencoded::parse(body.as_bytes())
|
||||
.filter(|(k, _)| k == "profile_ids")
|
||||
.filter_map(|(_, value)| value.parse::<i32>().ok())
|
||||
.collect();
|
||||
|
||||
let txn = ctx.db.begin().await?;
|
||||
audience_discount_profiles::Entity::delete_many()
|
||||
.filter(audience_discount_profiles::Column::Audience.eq(audience))
|
||||
.exec(&txn)
|
||||
.await?;
|
||||
for profile_id in profile_ids {
|
||||
audience_discount_profiles::ActiveModel {
|
||||
audience: Set(audience.to_string()),
|
||||
discount_profile_id: Set(profile_id),
|
||||
..Default::default()
|
||||
}
|
||||
.insert(&txn)
|
||||
.await?;
|
||||
}
|
||||
txn.commit().await?;
|
||||
list_redirect(audience)
|
||||
}
|
||||
|
||||
/// What to pre-fill the form with: the chosen input mode and the raw values for
|
||||
/// each field, so a rejected submit (or a re-edit) shows what the admin had.
|
||||
#[derive(Default)]
|
||||
@@ -284,6 +352,7 @@ async fn remove(
|
||||
pub fn routes() -> Routes {
|
||||
Routes::new()
|
||||
.add("/admin/catalog/discounts", get(index))
|
||||
.add("/admin/catalog/discounts/profiles", post(sync_profiles))
|
||||
.add("/admin/catalog/discounts/{id}/edit", get(edit))
|
||||
.add("/admin/catalog/discounts/{id}", post(update))
|
||||
.add("/admin/catalog/discounts/{id}/remove", post(remove))
|
||||
|
||||
Reference in New Issue
Block a user