dynamic prices with dicounts

This commit is contained in:
Priec
2026-06-22 08:47:22 +02:00
parent e98c70aa63
commit 262ec1bfdb
3 changed files with 56 additions and 4 deletions

View File

@@ -25,6 +25,7 @@ use crate::{
shared::{
guard,
money::{format_bp, format_price, parse_percent, parse_price_to_cents},
pricing,
},
};
@@ -89,9 +90,9 @@ fn percent_off(regular_cents: i64, sale_cents: i64) -> i64 {
off.round() as i64
}
/// Row shape for the discounts list, carrying both audiences' values so the
/// template can show whichever tab is active.
fn list_row(product: &products::Model) -> serde_json::Value {
/// Row shape for the discounts list, carrying both audiences' per-product values
/// plus the resolved effective price for the active tab (after profiles).
fn list_row(product: &products::Model, effective: &pricing::PricedProduct) -> serde_json::Value {
json!({
"id": product.id,
"name": product.name,
@@ -106,6 +107,11 @@ fn list_row(product: &products::Model) -> serde_json::Value {
"business_percent_off": product
.business_sale_price_cents
.map(|sale| percent_off(product.price_cents, sale)),
// The price this audience actually pays after the per-product discount
// and any applied profiles.
"effective_price": format_price(effective.price_cents),
"effective_reduced": effective.is_reduced(),
"effective_percent_off": percent_off(product.price_cents, effective.price_cents),
})
}
@@ -123,7 +129,12 @@ async fn index(
.order_by_asc(products::Column::Name)
.all(&ctx.db)
.await?;
let rows: Vec<serde_json::Value> = list.iter().map(list_row).collect();
let effective = pricing::audience_price_many(&ctx, &list, audience).await?;
let rows: Vec<serde_json::Value> = list
.iter()
.zip(effective.iter())
.map(|(product, priced)| list_row(product, priced))
.collect();
// Profiles applied globally to this audience, plus all profiles to choose from.
let assigned: HashSet<i32> = audience_discount_profiles::Entity::find()