profile of a new registered users

This commit is contained in:
Priec
2026-06-18 21:11:48 +02:00
parent b9c1277876
commit c6624e1b3d
20 changed files with 501 additions and 17 deletions

View File

@@ -0,0 +1,40 @@
//! `SeaORM` Entity for customer shipping/contact profiles. Hand-written to match
//! the `customer_profiles` migration (1:1 with `users` via a unique `user_id`).
use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)]
#[sea_orm(table_name = "customer_profiles")]
pub struct Model {
pub created_at: DateTimeWithTimeZone,
pub updated_at: DateTimeWithTimeZone,
#[sea_orm(primary_key)]
pub id: i32,
#[sea_orm(unique)]
pub user_id: i32,
pub phone_prefix: Option<String>,
pub phone: Option<String>,
pub address: Option<String>,
pub city: Option<String>,
pub zip: Option<String>,
pub country: Option<String>,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
#[sea_orm(
belongs_to = "super::users::Entity",
from = "Column::UserId",
to = "super::users::Column::Id",
on_update = "Cascade",
on_delete = "Cascade"
)]
Users,
}
impl Related<super::users::Entity> for Entity {
fn to() -> RelationDef {
Relation::Users.def()
}
}

View File

@@ -4,6 +4,7 @@ pub mod prelude;
pub mod audit_logs;
pub mod categories;
pub mod customer_profiles;
pub mod o_auth2_sessions;
pub mod order_items;
pub mod orders;

View File

@@ -2,6 +2,7 @@
pub use super::audit_logs::Entity as AuditLogs;
pub use super::categories::Entity as Categories;
pub use super::customer_profiles::Entity as CustomerProfiles;
pub use super::o_auth2_sessions::Entity as OAuth2Sessions;
pub use super::order_items::Entity as OrderItems;
pub use super::orders::Entity as Orders;

View File

@@ -0,0 +1,64 @@
//! Per-customer shipping/contact profile: the address + phone fields used to
//! prefill checkout. One row per user (unique `user_id`); `name`/`email` are
//! read from `users`, never duplicated here.
pub use crate::models::_entities::customer_profiles::{ActiveModel, Column, Entity, Model};
use sea_orm::entity::prelude::*;
use sea_orm::{ActiveValue, IntoActiveModel, QueryFilter, TryIntoModel};
pub type CustomerProfiles = Entity;
/// The editable profile fields, shared by the profile page and the checkout
/// "save my address" path.
#[derive(Debug, Default, Clone)]
pub struct ProfileFields {
pub phone_prefix: Option<String>,
pub phone: Option<String>,
pub address: Option<String>,
pub city: Option<String>,
pub zip: Option<String>,
pub country: Option<String>,
}
#[async_trait::async_trait]
impl ActiveModelBehavior for ActiveModel {
async fn before_save<C>(self, _db: &C, _insert: bool) -> std::result::Result<Self, DbErr>
where
C: ConnectionTrait,
{
Ok(self)
}
}
impl Model {
/// The profile for `user_id`, if one exists.
pub async fn find_for_user(db: &DatabaseConnection, user_id: i32) -> Result<Option<Self>, DbErr> {
Entity::find()
.filter(Column::UserId.eq(user_id))
.one(db)
.await
}
/// Insert or update the profile for `user_id` with `fields`, returning the
/// persisted row. The unique `user_id` index keeps this 1:1.
pub async fn upsert(
db: &DatabaseConnection,
user_id: i32,
fields: ProfileFields,
) -> Result<Self, DbErr> {
let mut active = match Self::find_for_user(db, user_id).await? {
Some(existing) => existing.into_active_model(),
None => ActiveModel {
user_id: ActiveValue::set(user_id),
..Default::default()
},
};
active.phone_prefix = ActiveValue::set(fields.phone_prefix);
active.phone = ActiveValue::set(fields.phone);
active.address = ActiveValue::set(fields.address);
active.city = ActiveValue::set(fields.city);
active.zip = ActiveValue::set(fields.zip);
active.country = ActiveValue::set(fields.country);
active.save(db).await?.try_into_model()
}
}

View File

@@ -8,6 +8,7 @@ pub mod _entities;
pub mod audit_logs;
pub mod categories;
pub mod customer_profiles;
pub mod o_auth2_sessions;
pub mod order_items;
pub mod orders;