phone number + country

This commit is contained in:
Priec
2026-06-17 18:02:46 +02:00
parent cd7a756a54
commit d18bdeaf6e
13 changed files with 96 additions and 6 deletions

View File

@@ -178,6 +178,7 @@ async fn ship(
order_number: &order.order_number,
recipient_name: recipient,
email: &order.email,
phone: order.phone.as_deref(),
address: order.address.as_deref(),
city: order.city.as_deref(),
zip: order.zip.as_deref(),

View File

@@ -21,6 +21,8 @@ const PAYMENT_METHODS: [&str; 2] = ["cod", "bank_transfer"];
#[derive(Debug, Deserialize)]
struct CheckoutForm {
email: String,
phone_prefix: String,
phone: String,
customer_name: String,
address: String,
city: String,
@@ -111,6 +113,25 @@ async fn place_order(
}
let email =
trimmed(&form.email).ok_or_else(|| Error::BadRequest("email is required".to_string()))?;
// Combine the dialling-code prefix with the local number into one E.164-ish
// value (e.g. "+421 900123456").
let number =
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,
};
// Contact and shipping-address fields are mandatory (also enforced in the
// browser via `required`).
let require = |value: &str, field: &str| -> Result<String> {
trimmed(value).ok_or_else(|| Error::BadRequest(format!("{field} is required")))
};
let customer_name = require(&form.customer_name, "name")?;
let address = require(&form.address, "address")?;
let city = require(&form.city, "city")?;
let zip = require(&form.zip, "zip")?;
let country = require(&form.country, "country")?;
if !PAYMENT_METHODS.contains(&form.payment_method.as_str()) {
return Err(Error::BadRequest("invalid payment method".to_string()));
@@ -141,11 +162,12 @@ async fn place_order(
&valid,
orders::Checkout {
email,
customer_name: trimmed(&form.customer_name),
address: trimmed(&form.address),
city: trimmed(&form.city),
zip: trimmed(&form.zip),
country: trimmed(&form.country),
phone,
customer_name: Some(customer_name),
address: Some(address),
city: Some(city),
zip: Some(zip),
country: Some(country),
note: form.note.as_deref().and_then(trimmed),
payment_method: form.payment_method,
method,

View File

@@ -19,6 +19,7 @@ pub struct ShipmentRequest<'a> {
pub order_number: &'a str,
pub recipient_name: &'a str,
pub email: &'a str,
pub phone: Option<&'a str>,
pub address: Option<&'a str>,
pub city: Option<&'a str>,
pub zip: Option<&'a str>,

View File

@@ -60,6 +60,7 @@ pub async fn create_shipment(ctx: &AppContext, req: ShipmentRequest<'_>) -> Resu
<name>{}</name>\
<surname>-</surname>\
<email>{}</email>\
<phone>{}</phone>\
<addressId>{}</addressId>\
<value>{:.2}</value>\
<cod>{:.2}</cod>\
@@ -72,6 +73,7 @@ pub async fn create_shipment(ctx: &AppContext, req: ShipmentRequest<'_>) -> Resu
xml_escape(req.order_number),
xml_escape(req.recipient_name),
xml_escape(req.email),
xml_escape(req.phone.unwrap_or("")),
xml_escape(address_id),
value,
cod,

View File

@@ -13,6 +13,7 @@ pub struct Model {
#[sea_orm(unique)]
pub order_number: String,
pub email: String,
pub phone: Option<String>,
pub customer_name: Option<String>,
pub status: String,
pub total_cents: i64,

View File

@@ -12,6 +12,7 @@ pub type Orders = Entity;
/// database inside [`place`] so the customer cannot influence what they pay.
pub struct Checkout {
pub email: String,
pub phone: String,
pub customer_name: Option<String>,
pub address: Option<String>,
pub city: Option<String>,
@@ -64,6 +65,7 @@ pub async fn place(ctx: &AppContext, items: &[(i32, i32)], details: Checkout) ->
let order = ActiveModel {
order_number: Set(generate_order_number()),
email: Set(details.email),
phone: Set(Some(details.phone)),
customer_name: Set(details.customer_name),
status: Set("pending".to_string()),
total_cents: Set(subtotal + details.method.price_cents),

View File

@@ -28,6 +28,7 @@ pub fn detail(order: &orders::Model, bank_iban: &str, bank_account_name: &str) -
"id": order.id,
"order_number": order.order_number,
"email": order.email,
"phone": order.phone,
"customer_name": order.customer_name,
"status": order.status,
"subtotal": format_price(order.total_cents - order.shipping_cents),