profile of a new registered users
This commit is contained in:
@@ -10,9 +10,9 @@ use time::Duration as TimeDuration;
|
||||
|
||||
use crate::{
|
||||
controllers::cart::{resolve_cart, CART_COOKIE},
|
||||
models::{order_items, orders, shipping_methods},
|
||||
models::{customer_profiles::{self, ProfileFields}, order_items, orders, shipping_methods},
|
||||
controllers::i18n::current_lang,
|
||||
shared::{money::format_price, settings},
|
||||
shared::{guard, money::format_price, settings},
|
||||
views::checkout as view,
|
||||
};
|
||||
|
||||
@@ -33,6 +33,8 @@ struct CheckoutForm {
|
||||
carrier_code: String,
|
||||
pickup_point_id: Option<String>,
|
||||
pickup_point_name: Option<String>,
|
||||
// Present (as "on") only when a logged-in customer ticks "save my address".
|
||||
save_profile: Option<String>,
|
||||
}
|
||||
|
||||
fn trimmed(value: &str) -> Option<String> {
|
||||
@@ -86,6 +88,19 @@ async fn checkout_page(
|
||||
})
|
||||
.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).
|
||||
let user = guard::current_user(&ctx, &jar).await;
|
||||
let is_admin = user.as_ref().is_some_and(|u| guard::is_admin(&ctx, u));
|
||||
let is_customer = user.is_some() && !is_admin;
|
||||
let profile = match (&user, is_customer) {
|
||||
(Some(u), true) => customer_profiles::Model::find_for_user(&ctx.db, u.id).await?,
|
||||
_ => None,
|
||||
};
|
||||
let p = |get: fn(&customer_profiles::Model) -> Option<String>| {
|
||||
profile.as_ref().and_then(get)
|
||||
};
|
||||
|
||||
format::view(
|
||||
&v,
|
||||
"shop/checkout.html",
|
||||
@@ -96,6 +111,16 @@ async fn checkout_page(
|
||||
"currency": currency,
|
||||
"shipping_methods": methods,
|
||||
"packeta_api_key": settings::get(&ctx, "packeta_api_key").unwrap_or(""),
|
||||
"logged_in_admin": is_admin,
|
||||
"logged_in_customer": is_customer,
|
||||
"prefill_email": user.as_ref().filter(|_| is_customer).map(|u| u.email.clone()),
|
||||
"prefill_name": user.as_ref().filter(|_| is_customer).map(|u| u.name.clone()),
|
||||
"prefill_phone_prefix": p(|x| x.phone_prefix.clone()),
|
||||
"prefill_phone": p(|x| x.phone.clone()),
|
||||
"prefill_address": p(|x| x.address.clone()),
|
||||
"prefill_city": p(|x| x.city.clone()),
|
||||
"prefill_zip": p(|x| x.zip.clone()),
|
||||
"prefill_country": p(|x| x.country.clone()),
|
||||
"lang": current_lang(&jar),
|
||||
}),
|
||||
)
|
||||
@@ -119,7 +144,7 @@ async fn place_order(
|
||||
trimmed(&form.phone).ok_or_else(|| Error::BadRequest("phone is required".to_string()))?;
|
||||
let phone = match trimmed(&form.phone_prefix) {
|
||||
Some(prefix) => format!("{prefix} {number}"),
|
||||
None => number,
|
||||
None => number.clone(),
|
||||
};
|
||||
|
||||
// Contact and shipping-address fields are mandatory (also enforced in the
|
||||
@@ -157,6 +182,28 @@ async fn place_order(
|
||||
(None, None)
|
||||
};
|
||||
|
||||
// If a logged-in customer opted in, persist this address to their profile
|
||||
// so the next checkout is prefilled. Phone is stored split (prefix + number)
|
||||
// to match the profile/checkout fields. Best-effort: a failure here is logged
|
||||
// but must not block the order.
|
||||
if form.save_profile.is_some() {
|
||||
if let Some(user) = guard::current_user(&ctx, &jar).await {
|
||||
if !guard::is_admin(&ctx, &user) {
|
||||
let fields = ProfileFields {
|
||||
phone_prefix: trimmed(&form.phone_prefix),
|
||||
phone: Some(number.clone()),
|
||||
address: Some(address.clone()),
|
||||
city: Some(city.clone()),
|
||||
zip: Some(zip.clone()),
|
||||
country: Some(country.clone()),
|
||||
};
|
||||
if let Err(err) = customer_profiles::Model::upsert(&ctx.db, user.id, fields).await {
|
||||
tracing::error!(error = %err, user_id = user.id, "failed to save checkout profile");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let order = orders::place(
|
||||
&ctx,
|
||||
&valid,
|
||||
@@ -198,6 +245,7 @@ async fn order_confirmation(
|
||||
.filter(order_items::Column::OrderId.eq(order.id))
|
||||
.all(&ctx.db)
|
||||
.await?;
|
||||
let (logged_in_admin, logged_in_customer) = guard::chrome(&ctx, &jar).await;
|
||||
|
||||
format::view(
|
||||
&v,
|
||||
@@ -209,6 +257,8 @@ async fn order_confirmation(
|
||||
settings::get(&ctx, "bank_account_name").unwrap_or(""),
|
||||
),
|
||||
"items": view::items(&items),
|
||||
"logged_in_admin": logged_in_admin,
|
||||
"logged_in_customer": logged_in_customer,
|
||||
"lang": current_lang(&jar),
|
||||
}),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user