mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-11-01 11:06:50 +08:00
refactor(router): refactor customer <> address in customers and payments flow (#2158)
This commit is contained in:
committed by
GitHub
parent
809832213e
commit
8ee2ce1f4f
@ -20,14 +20,15 @@ pub struct AddressNew {
|
||||
pub country_code: Option<String>,
|
||||
pub customer_id: String,
|
||||
pub merchant_id: String,
|
||||
pub payment_id: Option<String>,
|
||||
pub created_at: PrimitiveDateTime,
|
||||
pub modified_at: PrimitiveDateTime,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Identifiable, Queryable)]
|
||||
#[diesel(table_name = address)]
|
||||
#[derive(Clone, Debug, Queryable, Identifiable)]
|
||||
#[diesel(table_name = address, primary_key(address_id))]
|
||||
pub struct Address {
|
||||
pub id: i32,
|
||||
pub id: Option<i32>,
|
||||
pub address_id: String,
|
||||
pub city: Option<String>,
|
||||
pub country: Option<enums::CountryAlpha2>,
|
||||
@ -44,6 +45,7 @@ pub struct Address {
|
||||
pub modified_at: PrimitiveDateTime,
|
||||
pub customer_id: String,
|
||||
pub merchant_id: String,
|
||||
pub payment_id: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, AsChangeset, router_derive::DebugAsDisplay)]
|
||||
|
||||
@ -18,6 +18,7 @@ pub struct CustomerNew {
|
||||
pub connector_customer: Option<serde_json::Value>,
|
||||
pub created_at: PrimitiveDateTime,
|
||||
pub modified_at: PrimitiveDateTime,
|
||||
pub address_id: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Identifiable, Queryable)]
|
||||
@ -35,6 +36,7 @@ pub struct Customer {
|
||||
pub metadata: Option<pii::SecretSerdeValue>,
|
||||
pub connector_customer: Option<serde_json::Value>,
|
||||
pub modified_at: PrimitiveDateTime,
|
||||
pub address_id: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, AsChangeset, router_derive::DebugAsDisplay)]
|
||||
@ -48,4 +50,5 @@ pub struct CustomerUpdateInternal {
|
||||
pub metadata: Option<pii::SecretSerdeValue>,
|
||||
pub modified_at: Option<PrimitiveDateTime>,
|
||||
pub connector_customer: Option<serde_json::Value>,
|
||||
pub address_id: Option<String>,
|
||||
}
|
||||
|
||||
@ -76,12 +76,33 @@ impl Address {
|
||||
}
|
||||
|
||||
#[instrument(skip(conn))]
|
||||
pub async fn find_by_address_id<'a>(
|
||||
pub async fn find_by_merchant_id_payment_id_address_id<'a>(
|
||||
conn: &PgPooledConn,
|
||||
merchant_id: &str,
|
||||
payment_id: &str,
|
||||
address_id: &str,
|
||||
) -> StorageResult<Self> {
|
||||
generics::generic_find_by_id::<<Self as HasTable>::Table, _, _>(conn, address_id.to_owned())
|
||||
.await
|
||||
match generics::generic_find_one::<<Self as HasTable>::Table, _, _>(
|
||||
conn,
|
||||
dsl::payment_id
|
||||
.eq(payment_id.to_owned())
|
||||
.and(dsl::merchant_id.eq(merchant_id.to_owned()))
|
||||
.and(dsl::address_id.eq(address_id.to_owned())),
|
||||
)
|
||||
.await
|
||||
{
|
||||
Err(error) => match error.current_context() {
|
||||
errors::DatabaseError::NotFound => {
|
||||
generics::generic_find_by_id::<<Self as HasTable>::Table, _, _>(
|
||||
conn,
|
||||
address_id.to_owned(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
_ => Err(error),
|
||||
},
|
||||
result => result,
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip(conn))]
|
||||
|
||||
@ -5,7 +5,7 @@ diesel::table! {
|
||||
use crate::enums::diesel_exports::*;
|
||||
|
||||
address (address_id) {
|
||||
id -> Int4,
|
||||
id -> Nullable<Int4>,
|
||||
#[max_length = 64]
|
||||
address_id -> Varchar,
|
||||
#[max_length = 128]
|
||||
@ -27,6 +27,8 @@ diesel::table! {
|
||||
customer_id -> Varchar,
|
||||
#[max_length = 64]
|
||||
merchant_id -> Varchar,
|
||||
#[max_length = 64]
|
||||
payment_id -> Nullable<Varchar>,
|
||||
}
|
||||
}
|
||||
|
||||
@ -197,6 +199,8 @@ diesel::table! {
|
||||
metadata -> Nullable<Json>,
|
||||
connector_customer -> Nullable<Jsonb>,
|
||||
modified_at -> Timestamp,
|
||||
#[max_length = 64]
|
||||
address_id -> Nullable<Varchar>,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -7,7 +7,6 @@ use masking::ExposeInterface;
|
||||
use router_env::{instrument, tracing};
|
||||
|
||||
use crate::{
|
||||
consts,
|
||||
core::{
|
||||
errors::{self},
|
||||
payment_methods::cards,
|
||||
@ -23,7 +22,7 @@ use crate::{
|
||||
},
|
||||
storage::{self, enums},
|
||||
},
|
||||
utils::generate_id,
|
||||
utils::CustomerAddress,
|
||||
};
|
||||
|
||||
pub const REDACTED: &str = "Redacted";
|
||||
@ -41,64 +40,25 @@ pub async fn create_customer(
|
||||
customer_data.merchant_id = merchant_id.to_owned();
|
||||
|
||||
let key = key_store.key.get_inner().peek();
|
||||
if let Some(addr) = &customer_data.address {
|
||||
let address_id = if let Some(addr) = &customer_data.address {
|
||||
let customer_address: api_models::payments::AddressDetails = addr.clone();
|
||||
|
||||
let address = async {
|
||||
Ok(domain::Address {
|
||||
city: customer_address.city,
|
||||
country: customer_address.country,
|
||||
line1: customer_address
|
||||
.line1
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
line2: customer_address
|
||||
.line2
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
line3: customer_address
|
||||
.line3
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
zip: customer_address
|
||||
.zip
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
state: customer_address
|
||||
.state
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
first_name: customer_address
|
||||
.first_name
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
last_name: customer_address
|
||||
.last_name
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
phone_number: customer_data
|
||||
.phone
|
||||
.clone()
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
country_code: customer_data.phone_country_code.clone(),
|
||||
customer_id: customer_id.to_string(),
|
||||
merchant_id: merchant_id.to_string(),
|
||||
id: None,
|
||||
address_id: generate_id(consts::ID_LENGTH, "add"),
|
||||
created_at: common_utils::date_time::now(),
|
||||
modified_at: common_utils::date_time::now(),
|
||||
})
|
||||
}
|
||||
.await
|
||||
.switch()
|
||||
.attach_printable("Failed while encrypting address")?;
|
||||
|
||||
db.insert_address(address, &key_store)
|
||||
let address = customer_data
|
||||
.get_domain_address(customer_address, merchant_id, customer_id, key)
|
||||
.await
|
||||
.switch()
|
||||
.attach_printable("Failed while inserting new address")?;
|
||||
}
|
||||
.attach_printable("Failed while encrypting address")?;
|
||||
|
||||
Some(
|
||||
db.insert_address_for_customers(address, &key_store)
|
||||
.await
|
||||
.switch()
|
||||
.attach_printable("Failed while inserting new address")?
|
||||
.address_id,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let new_customer = async {
|
||||
Ok(domain::Customer {
|
||||
@ -121,6 +81,7 @@ pub async fn create_customer(
|
||||
metadata: customer_data.metadata,
|
||||
id: None,
|
||||
connector_customer: None,
|
||||
address_id,
|
||||
created_at: common_utils::date_time::now(),
|
||||
modified_at: common_utils::date_time::now(),
|
||||
})
|
||||
@ -287,11 +248,12 @@ pub async fn delete_customer(
|
||||
.await
|
||||
.switch()?,
|
||||
),
|
||||
phone: Some(redacted_encrypted_value.clone()),
|
||||
phone: Box::new(Some(redacted_encrypted_value.clone())),
|
||||
description: Some(REDACTED.to_string()),
|
||||
phone_country_code: Some(REDACTED.to_string()),
|
||||
metadata: None,
|
||||
connector_customer: None,
|
||||
address_id: None,
|
||||
};
|
||||
db.update_customer_by_customer_id_merchant_id(
|
||||
req.customer_id.clone(),
|
||||
@ -321,73 +283,59 @@ pub async fn update_customer(
|
||||
) -> errors::CustomerResponse<customers::CustomerResponse> {
|
||||
let db = state.store.as_ref();
|
||||
//Add this in update call if customer can be updated anywhere else
|
||||
db.find_customer_by_customer_id_merchant_id(
|
||||
&update_customer.customer_id,
|
||||
&merchant_account.merchant_id,
|
||||
&key_store,
|
||||
)
|
||||
.await
|
||||
.switch()?;
|
||||
|
||||
let key = key_store.key.get_inner().peek();
|
||||
|
||||
if let Some(addr) = &update_customer.address {
|
||||
let customer_address: api_models::payments::AddressDetails = addr.clone();
|
||||
let update_address = async {
|
||||
Ok(storage::AddressUpdate::Update {
|
||||
city: customer_address.city,
|
||||
country: customer_address.country,
|
||||
line1: customer_address
|
||||
.line1
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
line2: customer_address
|
||||
.line2
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
line3: customer_address
|
||||
.line3
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
zip: customer_address
|
||||
.zip
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
state: customer_address
|
||||
.state
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
first_name: customer_address
|
||||
.first_name
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
last_name: customer_address
|
||||
.last_name
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
phone_number: update_customer
|
||||
.phone
|
||||
.clone()
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
country_code: update_customer.phone_country_code.clone(),
|
||||
})
|
||||
}
|
||||
.await
|
||||
.switch()
|
||||
.attach_printable("Failed while encrypting Address while Update")?;
|
||||
db.update_address_by_merchant_id_customer_id(
|
||||
let customer = db
|
||||
.find_customer_by_customer_id_merchant_id(
|
||||
&update_customer.customer_id,
|
||||
&merchant_account.merchant_id,
|
||||
update_address,
|
||||
&key_store,
|
||||
)
|
||||
.await
|
||||
.switch()
|
||||
.attach_printable(format!(
|
||||
"Failed while updating address: merchant_id: {}, customer_id: {}",
|
||||
merchant_account.merchant_id, update_customer.customer_id
|
||||
))?;
|
||||
.switch()?;
|
||||
|
||||
let key = key_store.key.get_inner().peek();
|
||||
|
||||
let address_id = if let Some(addr) = &update_customer.address {
|
||||
match customer.address_id {
|
||||
Some(address_id) => {
|
||||
let customer_address: api_models::payments::AddressDetails = addr.clone();
|
||||
let update_address = update_customer
|
||||
.get_address_update(customer_address, key)
|
||||
.await
|
||||
.switch()
|
||||
.attach_printable("Failed while encrypting Address while Update")?;
|
||||
db.update_address(address_id.clone(), update_address, &key_store)
|
||||
.await
|
||||
.switch()
|
||||
.attach_printable(format!(
|
||||
"Failed while updating address: merchant_id: {}, customer_id: {}",
|
||||
merchant_account.merchant_id, update_customer.customer_id
|
||||
))?;
|
||||
Some(address_id)
|
||||
}
|
||||
None => {
|
||||
let customer_address: api_models::payments::AddressDetails = addr.clone();
|
||||
|
||||
let address = update_customer
|
||||
.get_domain_address(
|
||||
customer_address,
|
||||
&merchant_account.merchant_id,
|
||||
&customer.customer_id,
|
||||
key,
|
||||
)
|
||||
.await
|
||||
.switch()
|
||||
.attach_printable("Failed while encrypting address")?;
|
||||
Some(
|
||||
db.insert_address_for_customers(address, &key_store)
|
||||
.await
|
||||
.switch()
|
||||
.attach_printable("Failed while inserting new address")?
|
||||
.address_id,
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let response = db
|
||||
@ -406,14 +354,17 @@ pub async fn update_customer(
|
||||
types::encrypt_optional(inner.map(|inner| inner.expose()), key)
|
||||
})
|
||||
.await?,
|
||||
phone: update_customer
|
||||
.phone
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
phone: Box::new(
|
||||
update_customer
|
||||
.phone
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
),
|
||||
phone_country_code: update_customer.phone_country_code,
|
||||
metadata: update_customer.metadata,
|
||||
description: update_customer.description,
|
||||
connector_customer: None,
|
||||
address_id,
|
||||
})
|
||||
}
|
||||
.await
|
||||
|
||||
@ -796,7 +796,14 @@ pub async fn list_payment_methods(
|
||||
let shipping_address = payment_intent
|
||||
.as_ref()
|
||||
.async_map(|pi| async {
|
||||
helpers::get_address_by_id(db, pi.shipping_address_id.clone(), &key_store).await
|
||||
helpers::get_address_by_id(
|
||||
db,
|
||||
pi.shipping_address_id.clone(),
|
||||
&key_store,
|
||||
pi.payment_id.clone(),
|
||||
merchant_account.merchant_id.clone(),
|
||||
)
|
||||
.await
|
||||
})
|
||||
.await
|
||||
.transpose()?
|
||||
@ -805,7 +812,14 @@ pub async fn list_payment_methods(
|
||||
let billing_address = payment_intent
|
||||
.as_ref()
|
||||
.async_map(|pi| async {
|
||||
helpers::get_address_by_id(db, pi.billing_address_id.clone(), &key_store).await
|
||||
helpers::get_address_by_id(
|
||||
db,
|
||||
pi.billing_address_id.clone(),
|
||||
&key_store,
|
||||
pi.payment_id.clone(),
|
||||
merchant_account.merchant_id.clone(),
|
||||
)
|
||||
.await
|
||||
})
|
||||
.await
|
||||
.transpose()?
|
||||
|
||||
@ -104,176 +104,138 @@ pub fn filter_mca_based_on_business_profile(
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
pub async fn get_address_for_payment_request(
|
||||
pub async fn create_or_find_address_for_payment_by_request(
|
||||
db: &dyn StorageInterface,
|
||||
req_address: Option<&api::Address>,
|
||||
address_id: Option<&str>,
|
||||
merchant_id: &str,
|
||||
customer_id: Option<&String>,
|
||||
merchant_key_store: &domain::MerchantKeyStore,
|
||||
payment_id: &str,
|
||||
) -> CustomResult<Option<domain::Address>, errors::ApiErrorResponse> {
|
||||
let key = merchant_key_store.key.get_inner().peek();
|
||||
|
||||
Ok(match req_address {
|
||||
Some(address) => {
|
||||
match address_id {
|
||||
Some(id) => {
|
||||
let address_update = async {
|
||||
Ok(storage::AddressUpdate::Update {
|
||||
city: address
|
||||
.address
|
||||
.as_ref()
|
||||
.and_then(|value| value.city.clone()),
|
||||
country: address.address.as_ref().and_then(|value| value.country),
|
||||
line1: address
|
||||
.address
|
||||
.as_ref()
|
||||
.and_then(|value| value.line1.clone())
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
line2: address
|
||||
.address
|
||||
.as_ref()
|
||||
.and_then(|value| value.line2.clone())
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
line3: address
|
||||
.address
|
||||
.as_ref()
|
||||
.and_then(|value| value.line3.clone())
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
state: address
|
||||
.address
|
||||
.as_ref()
|
||||
.and_then(|value| value.state.clone())
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
zip: address
|
||||
.address
|
||||
.as_ref()
|
||||
.and_then(|value| value.zip.clone())
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
first_name: address
|
||||
.address
|
||||
.as_ref()
|
||||
.and_then(|value| value.first_name.clone())
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
last_name: address
|
||||
.address
|
||||
.as_ref()
|
||||
.and_then(|value| value.last_name.clone())
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
phone_number: address
|
||||
.phone
|
||||
.as_ref()
|
||||
.and_then(|value| value.number.clone())
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
country_code: address
|
||||
.phone
|
||||
.as_ref()
|
||||
.and_then(|value| value.country_code.clone()),
|
||||
})
|
||||
}
|
||||
.await
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed while encrypting address")?;
|
||||
Some(
|
||||
db.update_address(id.to_owned(), address_update, merchant_key_store)
|
||||
.await
|
||||
.to_not_found_response(errors::ApiErrorResponse::AddressNotFound)?,
|
||||
)
|
||||
}
|
||||
None => {
|
||||
// generate a new address here
|
||||
let customer_id = customer_id.get_required_value("customer_id")?;
|
||||
Ok(match address_id {
|
||||
Some(id) => Some(
|
||||
db.find_address_by_merchant_id_payment_id_address_id(
|
||||
merchant_id,
|
||||
payment_id,
|
||||
id,
|
||||
merchant_key_store,
|
||||
)
|
||||
.await,
|
||||
)
|
||||
.transpose()
|
||||
.to_not_found_response(errors::ApiErrorResponse::AddressNotFound)?,
|
||||
None => match req_address {
|
||||
Some(address) => {
|
||||
// generate a new address here
|
||||
let customer_id = customer_id.get_required_value("customer_id")?;
|
||||
|
||||
let address_details = address.address.clone().unwrap_or_default();
|
||||
Some(
|
||||
db.insert_address(
|
||||
async {
|
||||
Ok(domain::Address {
|
||||
phone_number: address
|
||||
.phone
|
||||
.as_ref()
|
||||
.and_then(|a| a.number.clone())
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
country_code: address
|
||||
.phone
|
||||
.as_ref()
|
||||
.and_then(|a| a.country_code.clone()),
|
||||
customer_id: customer_id.to_string(),
|
||||
merchant_id: merchant_id.to_string(),
|
||||
address_id: generate_id(consts::ID_LENGTH, "add"),
|
||||
city: address_details.city,
|
||||
country: address_details.country,
|
||||
line1: address_details
|
||||
.line1
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
line2: address_details
|
||||
.line2
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
line3: address_details
|
||||
.line3
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
id: None,
|
||||
state: address_details
|
||||
.state
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
created_at: common_utils::date_time::now(),
|
||||
first_name: address_details
|
||||
.first_name
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
last_name: address_details
|
||||
.last_name
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
modified_at: common_utils::date_time::now(),
|
||||
zip: address_details
|
||||
.zip
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
})
|
||||
}
|
||||
.await
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed while encrypting address while insert")?,
|
||||
merchant_key_store,
|
||||
let address_details = address.address.clone().unwrap_or_default();
|
||||
Some(
|
||||
db.insert_address_for_payments(
|
||||
payment_id,
|
||||
get_domain_address_for_payments(
|
||||
address_details,
|
||||
address,
|
||||
merchant_id,
|
||||
customer_id,
|
||||
payment_id,
|
||||
key,
|
||||
)
|
||||
.await
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed while inserting new address")?,
|
||||
.attach_printable("Failed while encrypting address while insert")?,
|
||||
merchant_key_store,
|
||||
)
|
||||
}
|
||||
.await
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed while inserting new address")?,
|
||||
)
|
||||
}
|
||||
}
|
||||
None => match address_id {
|
||||
Some(id) => Some(db.find_address(id, merchant_key_store).await)
|
||||
.transpose()
|
||||
.to_not_found_response(errors::ApiErrorResponse::AddressNotFound)?,
|
||||
None => None,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn get_domain_address_for_payments(
|
||||
address_details: api_models::payments::AddressDetails,
|
||||
address: &api_models::payments::Address,
|
||||
merchant_id: &str,
|
||||
customer_id: &str,
|
||||
payment_id: &str,
|
||||
key: &[u8],
|
||||
) -> CustomResult<domain::Address, common_utils::errors::CryptoError> {
|
||||
async {
|
||||
Ok(domain::Address {
|
||||
id: None,
|
||||
phone_number: address
|
||||
.phone
|
||||
.as_ref()
|
||||
.and_then(|a| a.number.clone())
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
country_code: address.phone.as_ref().and_then(|a| a.country_code.clone()),
|
||||
customer_id: customer_id.to_string(),
|
||||
merchant_id: merchant_id.to_string(),
|
||||
address_id: generate_id(consts::ID_LENGTH, "add"),
|
||||
city: address_details.city,
|
||||
country: address_details.country,
|
||||
line1: address_details
|
||||
.line1
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
line2: address_details
|
||||
.line2
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
line3: address_details
|
||||
.line3
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
state: address_details
|
||||
.state
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
created_at: common_utils::date_time::now(),
|
||||
first_name: address_details
|
||||
.first_name
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
last_name: address_details
|
||||
.last_name
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
modified_at: common_utils::date_time::now(),
|
||||
zip: address_details
|
||||
.zip
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
payment_id: Some(payment_id.to_owned()),
|
||||
})
|
||||
}
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_address_by_id(
|
||||
db: &dyn StorageInterface,
|
||||
address_id: Option<String>,
|
||||
merchant_key_store: &domain::MerchantKeyStore,
|
||||
payment_id: String,
|
||||
merchant_id: String,
|
||||
) -> CustomResult<Option<domain::Address>, errors::ApiErrorResponse> {
|
||||
match address_id {
|
||||
None => Ok(None),
|
||||
Some(address_id) => Ok(db.find_address(&address_id, merchant_key_store).await.ok()),
|
||||
Some(address_id) => Ok(db
|
||||
.find_address_by_merchant_id_payment_id_address_id(
|
||||
&merchant_id,
|
||||
&payment_id,
|
||||
&address_id,
|
||||
merchant_key_store,
|
||||
)
|
||||
.await
|
||||
.ok()),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1081,15 +1043,18 @@ pub async fn create_customer_if_not_exist<'a, F: Clone, R>(
|
||||
)
|
||||
})
|
||||
.await?,
|
||||
phone: request_customer_details
|
||||
.phone
|
||||
.clone()
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
phone: Box::new(
|
||||
request_customer_details
|
||||
.phone
|
||||
.clone()
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
),
|
||||
phone_country_code: request_customer_details.phone_country_code,
|
||||
description: None,
|
||||
connector_customer: None,
|
||||
metadata: None,
|
||||
address_id: None,
|
||||
})
|
||||
}
|
||||
.await
|
||||
@ -1136,6 +1101,7 @@ pub async fn create_customer_if_not_exist<'a, F: Clone, R>(
|
||||
metadata: None,
|
||||
modified_at: common_utils::date_time::now(),
|
||||
connector_customer: None,
|
||||
address_id: None,
|
||||
})
|
||||
}
|
||||
.await
|
||||
|
||||
@ -136,22 +136,24 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
|
||||
.or_else(|| request.customer_id.clone()),
|
||||
)?;
|
||||
|
||||
let shipping_address = helpers::get_address_for_payment_request(
|
||||
let shipping_address = helpers::create_or_find_address_for_payment_by_request(
|
||||
db,
|
||||
request.shipping.as_ref(),
|
||||
payment_intent.shipping_address_id.as_deref(),
|
||||
merchant_id,
|
||||
payment_intent.customer_id.as_ref(),
|
||||
key_store,
|
||||
&payment_intent.payment_id,
|
||||
)
|
||||
.await?;
|
||||
let billing_address = helpers::get_address_for_payment_request(
|
||||
let billing_address = helpers::create_or_find_address_for_payment_by_request(
|
||||
db,
|
||||
request.billing.as_ref(),
|
||||
payment_intent.billing_address_id.as_deref(),
|
||||
merchant_id,
|
||||
payment_intent.customer_id.as_ref(),
|
||||
key_store,
|
||||
&payment_intent.payment_id,
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
||||
@ -79,23 +79,25 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsCancelRequest>
|
||||
.await
|
||||
.to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;
|
||||
|
||||
let shipping_address = helpers::get_address_for_payment_request(
|
||||
let shipping_address = helpers::create_or_find_address_for_payment_by_request(
|
||||
db,
|
||||
None,
|
||||
payment_intent.shipping_address_id.as_deref(),
|
||||
merchant_id,
|
||||
payment_intent.customer_id.as_ref(),
|
||||
key_store,
|
||||
&payment_intent.payment_id,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let billing_address = helpers::get_address_for_payment_request(
|
||||
let billing_address = helpers::create_or_find_address_for_payment_by_request(
|
||||
db,
|
||||
None,
|
||||
payment_intent.billing_address_id.as_deref(),
|
||||
merchant_id,
|
||||
payment_intent.customer_id.as_ref(),
|
||||
key_store,
|
||||
&payment_intent.payment_id,
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
||||
@ -153,23 +153,25 @@ impl<F: Send + Clone> GetTracker<F, payments::PaymentData<F>, api::PaymentsCaptu
|
||||
|
||||
amount = payment_attempt.amount.into();
|
||||
|
||||
let shipping_address = helpers::get_address_for_payment_request(
|
||||
let shipping_address = helpers::create_or_find_address_for_payment_by_request(
|
||||
db,
|
||||
None,
|
||||
payment_intent.shipping_address_id.as_deref(),
|
||||
merchant_id,
|
||||
payment_intent.customer_id.as_ref(),
|
||||
key_store,
|
||||
&payment_intent.payment_id,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let billing_address = helpers::get_address_for_payment_request(
|
||||
let billing_address = helpers::create_or_find_address_for_payment_by_request(
|
||||
db,
|
||||
None,
|
||||
payment_intent.billing_address_id.as_deref(),
|
||||
merchant_id,
|
||||
payment_intent.customer_id.as_ref(),
|
||||
key_store,
|
||||
&payment_intent.payment_id,
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
||||
@ -145,22 +145,24 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Co
|
||||
.or_else(|| request.customer_id.clone()),
|
||||
)?;
|
||||
|
||||
let shipping_address = helpers::get_address_for_payment_request(
|
||||
let shipping_address = helpers::create_or_find_address_for_payment_by_request(
|
||||
db,
|
||||
request.shipping.as_ref(),
|
||||
payment_intent.shipping_address_id.as_deref(),
|
||||
merchant_id,
|
||||
payment_intent.customer_id.as_ref(),
|
||||
key_store,
|
||||
&payment_intent.payment_id,
|
||||
)
|
||||
.await?;
|
||||
let billing_address = helpers::get_address_for_payment_request(
|
||||
let billing_address = helpers::create_or_find_address_for_payment_by_request(
|
||||
db,
|
||||
request.billing.as_ref(),
|
||||
payment_intent.billing_address_id.as_deref(),
|
||||
merchant_id,
|
||||
payment_intent.customer_id.as_ref(),
|
||||
key_store,
|
||||
&payment_intent.payment_id,
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
||||
@ -104,7 +104,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
|
||||
)
|
||||
.map(|x| x.to_not_found_response(errors::ApiErrorResponse::PaymentNotFound));
|
||||
|
||||
let shipping_address_fut = helpers::get_address_for_payment_request(
|
||||
let shipping_address_fut = helpers::create_or_find_address_for_payment_by_request(
|
||||
db,
|
||||
request.shipping.as_ref(),
|
||||
payment_intent.shipping_address_id.as_deref(),
|
||||
@ -114,9 +114,10 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
|
||||
.as_ref()
|
||||
.or(customer_details.customer_id.as_ref()),
|
||||
key_store,
|
||||
&payment_intent.payment_id,
|
||||
);
|
||||
|
||||
let billing_address_fut = helpers::get_address_for_payment_request(
|
||||
let billing_address_fut = helpers::create_or_find_address_for_payment_by_request(
|
||||
db,
|
||||
request.billing.as_ref(),
|
||||
payment_intent.billing_address_id.as_deref(),
|
||||
@ -126,6 +127,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
|
||||
.as_ref()
|
||||
.or(customer_details.customer_id.as_ref()),
|
||||
key_store,
|
||||
&payment_intent.payment_id,
|
||||
);
|
||||
|
||||
let config_update_fut = request
|
||||
|
||||
@ -92,23 +92,25 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
|
||||
|
||||
let customer_details = helpers::get_customer_details_from_request(request);
|
||||
|
||||
let shipping_address = helpers::get_address_for_payment_request(
|
||||
let shipping_address = helpers::create_or_find_address_for_payment_by_request(
|
||||
db,
|
||||
request.shipping.as_ref(),
|
||||
None,
|
||||
merchant_id,
|
||||
customer_details.customer_id.as_ref(),
|
||||
merchant_key_store,
|
||||
&payment_id,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let billing_address = helpers::get_address_for_payment_request(
|
||||
let billing_address = helpers::create_or_find_address_for_payment_by_request(
|
||||
db,
|
||||
request.billing.as_ref(),
|
||||
None,
|
||||
merchant_id,
|
||||
customer_details.customer_id.as_ref(),
|
||||
merchant_key_store,
|
||||
&payment_id,
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
||||
@ -77,23 +77,25 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, PaymentsRejectRequest> for P
|
||||
.await
|
||||
.to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;
|
||||
|
||||
let shipping_address = helpers::get_address_for_payment_request(
|
||||
let shipping_address = helpers::create_or_find_address_for_payment_by_request(
|
||||
db,
|
||||
None,
|
||||
payment_intent.shipping_address_id.as_deref(),
|
||||
merchant_id,
|
||||
payment_intent.customer_id.as_ref(),
|
||||
key_store,
|
||||
&payment_intent.payment_id,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let billing_address = helpers::get_address_for_payment_request(
|
||||
let billing_address = helpers::create_or_find_address_for_payment_by_request(
|
||||
db,
|
||||
None,
|
||||
payment_intent.billing_address_id.as_deref(),
|
||||
merchant_id,
|
||||
payment_intent.customer_id.as_ref(),
|
||||
key_store,
|
||||
&payment_intent.payment_id,
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
||||
@ -90,23 +90,25 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsSessionRequest>
|
||||
|
||||
let amount = payment_intent.amount.into();
|
||||
|
||||
let shipping_address = helpers::get_address_for_payment_request(
|
||||
let shipping_address = helpers::create_or_find_address_for_payment_by_request(
|
||||
db,
|
||||
None,
|
||||
payment_intent.shipping_address_id.as_deref(),
|
||||
merchant_id,
|
||||
payment_intent.customer_id.as_ref(),
|
||||
key_store,
|
||||
&payment_intent.payment_id,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let billing_address = helpers::get_address_for_payment_request(
|
||||
let billing_address = helpers::create_or_find_address_for_payment_by_request(
|
||||
db,
|
||||
None,
|
||||
payment_intent.billing_address_id.as_deref(),
|
||||
merchant_id,
|
||||
payment_intent.customer_id.as_ref(),
|
||||
key_store,
|
||||
&payment_intent.payment_id,
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
||||
@ -85,22 +85,24 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsStartRequest> f
|
||||
currency = payment_attempt.currency.get_required_value("currency")?;
|
||||
amount = payment_attempt.amount.into();
|
||||
|
||||
let shipping_address = helpers::get_address_for_payment_request(
|
||||
let shipping_address = helpers::create_or_find_address_for_payment_by_request(
|
||||
db,
|
||||
None,
|
||||
payment_intent.shipping_address_id.as_deref(),
|
||||
merchant_id,
|
||||
payment_intent.customer_id.as_ref(),
|
||||
mechant_key_store,
|
||||
&payment_intent.payment_id,
|
||||
)
|
||||
.await?;
|
||||
let billing_address = helpers::get_address_for_payment_request(
|
||||
let billing_address = helpers::create_or_find_address_for_payment_by_request(
|
||||
db,
|
||||
None,
|
||||
payment_intent.billing_address_id.as_deref(),
|
||||
merchant_id,
|
||||
payment_intent.customer_id.as_ref(),
|
||||
mechant_key_store,
|
||||
&payment_intent.payment_id,
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
||||
@ -241,12 +241,16 @@ async fn get_tracker_for_sync<
|
||||
db,
|
||||
payment_intent.shipping_address_id.clone(),
|
||||
mechant_key_store,
|
||||
payment_intent.payment_id.clone(),
|
||||
merchant_account.merchant_id.clone(),
|
||||
)
|
||||
.await?;
|
||||
let billing_address = helpers::get_address_by_id(
|
||||
db,
|
||||
payment_intent.billing_address_id.clone(),
|
||||
mechant_key_store,
|
||||
payment_intent.payment_id.clone(),
|
||||
merchant_account.merchant_id.clone(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
||||
@ -146,7 +146,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
|
||||
)?;
|
||||
}
|
||||
|
||||
let shipping_address = helpers::get_address_for_payment_request(
|
||||
let shipping_address = helpers::create_or_find_address_for_payment_by_request(
|
||||
db,
|
||||
request.shipping.as_ref(),
|
||||
payment_intent.shipping_address_id.as_deref(),
|
||||
@ -156,9 +156,10 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
|
||||
.as_ref()
|
||||
.or(customer_details.customer_id.as_ref()),
|
||||
key_store,
|
||||
&payment_intent.payment_id,
|
||||
)
|
||||
.await?;
|
||||
let billing_address = helpers::get_address_for_payment_request(
|
||||
let billing_address = helpers::create_or_find_address_for_payment_by_request(
|
||||
db,
|
||||
request.billing.as_ref(),
|
||||
payment_intent.billing_address_id.as_deref(),
|
||||
@ -168,6 +169,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
|
||||
.as_ref()
|
||||
.or(customer_details.customer_id.as_ref()),
|
||||
key_store,
|
||||
&payment_intent.payment_id,
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
||||
@ -1158,13 +1158,14 @@ pub async fn payout_create_db_entries(
|
||||
.customer_id;
|
||||
|
||||
// Get or create address
|
||||
let billing_address = payment_helpers::get_address_for_payment_request(
|
||||
let billing_address = payment_helpers::create_or_find_address_for_payment_by_request(
|
||||
db,
|
||||
req.billing.as_ref(),
|
||||
None,
|
||||
merchant_id,
|
||||
Some(&customer_id.to_owned()),
|
||||
key_store,
|
||||
payout_id,
|
||||
)
|
||||
.await?;
|
||||
let address_id = billing_address
|
||||
@ -1293,13 +1294,14 @@ pub async fn make_payout_data(
|
||||
.await
|
||||
.to_not_found_response(errors::ApiErrorResponse::PayoutNotFound)?;
|
||||
|
||||
let billing_address = payment_helpers::get_address_for_payment_request(
|
||||
let billing_address = payment_helpers::create_or_find_address_for_payment_by_request(
|
||||
db,
|
||||
None,
|
||||
Some(&payouts.address_id.to_owned()),
|
||||
merchant_id,
|
||||
Some(&payouts.customer_id.to_owned()),
|
||||
key_store,
|
||||
&payouts.payout_id,
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
||||
@ -297,6 +297,7 @@ pub async fn get_or_create_customer_details(
|
||||
id: None,
|
||||
created_at: common_utils::date_time::now(),
|
||||
modified_at: common_utils::date_time::now(),
|
||||
address_id: None,
|
||||
};
|
||||
|
||||
Ok(Some(
|
||||
|
||||
@ -28,14 +28,23 @@ where
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
) -> CustomResult<domain::Address, errors::StorageError>;
|
||||
|
||||
async fn insert_address(
|
||||
async fn insert_address_for_payments(
|
||||
&self,
|
||||
payment_id: &str,
|
||||
address: domain::Address,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
) -> CustomResult<domain::Address, errors::StorageError>;
|
||||
|
||||
async fn insert_address_for_customers(
|
||||
&self,
|
||||
address: domain::Address,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
) -> CustomResult<domain::Address, errors::StorageError>;
|
||||
|
||||
async fn find_address(
|
||||
async fn find_address_by_merchant_id_payment_id_address_id(
|
||||
&self,
|
||||
merchant_id: &str,
|
||||
payment_id: &str,
|
||||
address_id: &str,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
) -> CustomResult<domain::Address, errors::StorageError>;
|
||||
@ -51,23 +60,30 @@ where
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl AddressInterface for Store {
|
||||
async fn find_address(
|
||||
async fn find_address_by_merchant_id_payment_id_address_id(
|
||||
&self,
|
||||
merchant_id: &str,
|
||||
payment_id: &str,
|
||||
address_id: &str,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
) -> CustomResult<domain::Address, errors::StorageError> {
|
||||
let conn = connection::pg_connection_read(self).await?;
|
||||
storage::Address::find_by_address_id(&conn, address_id)
|
||||
.await
|
||||
.map_err(Into::into)
|
||||
.into_report()
|
||||
.async_and_then(|address| async {
|
||||
address
|
||||
.convert(key_store.key.get_inner())
|
||||
.await
|
||||
.change_context(errors::StorageError::DecryptionError)
|
||||
})
|
||||
.await
|
||||
storage::Address::find_by_merchant_id_payment_id_address_id(
|
||||
&conn,
|
||||
merchant_id,
|
||||
payment_id,
|
||||
address_id,
|
||||
)
|
||||
.await
|
||||
.map_err(Into::into)
|
||||
.into_report()
|
||||
.async_and_then(|address| async {
|
||||
address
|
||||
.convert(key_store.key.get_inner())
|
||||
.await
|
||||
.change_context(errors::StorageError::DecryptionError)
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
@ -91,8 +107,31 @@ impl AddressInterface for Store {
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
async fn insert_address(
|
||||
async fn insert_address_for_payments(
|
||||
&self,
|
||||
_payment_id: &str,
|
||||
address: domain::Address,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
) -> CustomResult<domain::Address, errors::StorageError> {
|
||||
let conn = connection::pg_connection_write(self).await?;
|
||||
address
|
||||
.construct_new()
|
||||
.await
|
||||
.change_context(errors::StorageError::EncryptionError)?
|
||||
.insert(&conn)
|
||||
.await
|
||||
.map_err(Into::into)
|
||||
.into_report()
|
||||
.async_and_then(|address| async {
|
||||
address
|
||||
.convert(key_store.key.get_inner())
|
||||
.await
|
||||
.change_context(errors::StorageError::DecryptionError)
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
async fn insert_address_for_customers(
|
||||
&self,
|
||||
address: domain::Address,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
@ -150,8 +189,10 @@ impl AddressInterface for Store {
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl AddressInterface for MockDb {
|
||||
async fn find_address(
|
||||
async fn find_address_by_merchant_id_payment_id_address_id(
|
||||
&self,
|
||||
_merchant_id: &str,
|
||||
_payment_id: &str,
|
||||
address_id: &str,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
) -> CustomResult<domain::Address, errors::StorageError> {
|
||||
@ -205,8 +246,27 @@ impl AddressInterface for MockDb {
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
async fn insert_address(
|
||||
async fn insert_address_for_payments(
|
||||
&self,
|
||||
_payment_id: &str,
|
||||
address_new: domain::Address,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
) -> CustomResult<domain::Address, errors::StorageError> {
|
||||
let mut addresses = self.addresses.lock().await;
|
||||
|
||||
let address = Conversion::convert(address_new)
|
||||
.await
|
||||
.change_context(errors::StorageError::EncryptionError)?;
|
||||
|
||||
addresses.push(address.clone());
|
||||
|
||||
address
|
||||
.convert(key_store.key.get_inner())
|
||||
.await
|
||||
.change_context(errors::StorageError::DecryptionError)
|
||||
}
|
||||
|
||||
async fn insert_address_for_customers(
|
||||
&self,
|
||||
address_new: domain::Address,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
|
||||
@ -17,7 +17,6 @@ use super::{
|
||||
pub struct Address {
|
||||
#[serde(skip_serializing)]
|
||||
pub id: Option<i32>,
|
||||
#[serde(skip_serializing)]
|
||||
pub address_id: String,
|
||||
pub city: Option<String>,
|
||||
pub country: Option<enums::CountryAlpha2>,
|
||||
@ -38,6 +37,7 @@ pub struct Address {
|
||||
pub modified_at: PrimitiveDateTime,
|
||||
pub customer_id: String,
|
||||
pub merchant_id: String,
|
||||
pub payment_id: Option<String>,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
@ -47,9 +47,7 @@ impl behaviour::Conversion for Address {
|
||||
|
||||
async fn convert(self) -> CustomResult<Self::DstType, ValidationError> {
|
||||
Ok(diesel_models::address::Address {
|
||||
id: self.id.ok_or(ValidationError::MissingRequiredField {
|
||||
field_name: "id".to_string(),
|
||||
})?,
|
||||
id: self.id,
|
||||
address_id: self.address_id,
|
||||
city: self.city,
|
||||
country: self.country,
|
||||
@ -66,6 +64,7 @@ impl behaviour::Conversion for Address {
|
||||
modified_at: self.modified_at,
|
||||
customer_id: self.customer_id,
|
||||
merchant_id: self.merchant_id,
|
||||
payment_id: self.payment_id,
|
||||
})
|
||||
}
|
||||
|
||||
@ -76,7 +75,7 @@ impl behaviour::Conversion for Address {
|
||||
async {
|
||||
let inner_decrypt = |inner| types::decrypt(inner, key.peek());
|
||||
Ok(Self {
|
||||
id: Some(other.id),
|
||||
id: other.id,
|
||||
address_id: other.address_id,
|
||||
city: other.city,
|
||||
country: other.country,
|
||||
@ -93,6 +92,7 @@ impl behaviour::Conversion for Address {
|
||||
modified_at: other.modified_at,
|
||||
customer_id: other.customer_id,
|
||||
merchant_id: other.merchant_id,
|
||||
payment_id: other.payment_id,
|
||||
})
|
||||
}
|
||||
.await
|
||||
@ -102,11 +102,6 @@ impl behaviour::Conversion for Address {
|
||||
}
|
||||
|
||||
async fn construct_new(self) -> CustomResult<Self::NewDstType, ValidationError> {
|
||||
common_utils::fp_utils::when(self.id.is_some(), || {
|
||||
Err(ValidationError::InvalidValue {
|
||||
message: "id present while creating a new database entry".to_string(),
|
||||
})
|
||||
})?;
|
||||
let now = date_time::now();
|
||||
Ok(Self::NewDstType {
|
||||
address_id: self.address_id,
|
||||
@ -123,6 +118,7 @@ impl behaviour::Conversion for Address {
|
||||
country_code: self.country_code,
|
||||
customer_id: self.customer_id,
|
||||
merchant_id: self.merchant_id,
|
||||
payment_id: self.payment_id,
|
||||
created_at: now,
|
||||
modified_at: now,
|
||||
})
|
||||
|
||||
@ -21,6 +21,7 @@ pub struct Customer {
|
||||
pub metadata: Option<pii::SecretSerdeValue>,
|
||||
pub modified_at: PrimitiveDateTime,
|
||||
pub connector_customer: Option<serde_json::Value>,
|
||||
pub address_id: Option<String>,
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
@ -43,6 +44,7 @@ impl super::behaviour::Conversion for Customer {
|
||||
metadata: self.metadata,
|
||||
modified_at: self.modified_at,
|
||||
connector_customer: self.connector_customer,
|
||||
address_id: self.address_id,
|
||||
})
|
||||
}
|
||||
|
||||
@ -69,6 +71,7 @@ impl super::behaviour::Conversion for Customer {
|
||||
metadata: item.metadata,
|
||||
modified_at: item.modified_at,
|
||||
connector_customer: item.connector_customer,
|
||||
address_id: item.address_id,
|
||||
})
|
||||
}
|
||||
.await
|
||||
@ -91,6 +94,7 @@ impl super::behaviour::Conversion for Customer {
|
||||
created_at: now,
|
||||
modified_at: now,
|
||||
connector_customer: self.connector_customer,
|
||||
address_id: self.address_id,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -100,11 +104,12 @@ pub enum CustomerUpdate {
|
||||
Update {
|
||||
name: crypto::OptionalEncryptableName,
|
||||
email: crypto::OptionalEncryptableEmail,
|
||||
phone: crypto::OptionalEncryptablePhone,
|
||||
phone: Box<crypto::OptionalEncryptablePhone>,
|
||||
description: Option<String>,
|
||||
phone_country_code: Option<String>,
|
||||
metadata: Option<pii::SecretSerdeValue>,
|
||||
connector_customer: Option<serde_json::Value>,
|
||||
address_id: Option<String>,
|
||||
},
|
||||
ConnectorCustomer {
|
||||
connector_customer: Option<serde_json::Value>,
|
||||
@ -122,6 +127,7 @@ impl From<CustomerUpdate> for CustomerUpdateInternal {
|
||||
phone_country_code,
|
||||
metadata,
|
||||
connector_customer,
|
||||
address_id,
|
||||
} => Self {
|
||||
name: name.map(Encryption::from),
|
||||
email: email.map(Encryption::from),
|
||||
@ -131,6 +137,7 @@ impl From<CustomerUpdate> for CustomerUpdateInternal {
|
||||
metadata,
|
||||
connector_customer,
|
||||
modified_at: Some(date_time::now()),
|
||||
address_id,
|
||||
},
|
||||
CustomerUpdate::ConnectorCustomer { connector_customer } => Self {
|
||||
connector_customer,
|
||||
|
||||
@ -32,7 +32,14 @@ use crate::{
|
||||
db::StorageInterface,
|
||||
logger,
|
||||
routes::metrics,
|
||||
types::{self, domain},
|
||||
types::{
|
||||
self,
|
||||
domain::{
|
||||
self,
|
||||
types::{encrypt_optional, AsyncLift},
|
||||
},
|
||||
storage,
|
||||
},
|
||||
};
|
||||
|
||||
pub mod error_parser {
|
||||
@ -397,3 +404,128 @@ pub fn add_connector_http_status_code_metrics(option_status_code: Option<u16>) {
|
||||
logger::info!("Skip metrics as no http status code received from connector")
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
pub trait CustomerAddress {
|
||||
async fn get_address_update(
|
||||
&self,
|
||||
address_details: api_models::payments::AddressDetails,
|
||||
key: &[u8],
|
||||
) -> CustomResult<storage::AddressUpdate, common_utils::errors::CryptoError>;
|
||||
|
||||
async fn get_domain_address(
|
||||
&self,
|
||||
address_details: api_models::payments::AddressDetails,
|
||||
merchant_id: &str,
|
||||
customer_id: &str,
|
||||
key: &[u8],
|
||||
) -> CustomResult<domain::Address, common_utils::errors::CryptoError>;
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl CustomerAddress for api_models::customers::CustomerRequest {
|
||||
async fn get_address_update(
|
||||
&self,
|
||||
address_details: api_models::payments::AddressDetails,
|
||||
key: &[u8],
|
||||
) -> CustomResult<storage::AddressUpdate, common_utils::errors::CryptoError> {
|
||||
async {
|
||||
Ok(storage::AddressUpdate::Update {
|
||||
city: address_details.city,
|
||||
country: address_details.country,
|
||||
line1: address_details
|
||||
.line1
|
||||
.async_lift(|inner| encrypt_optional(inner, key))
|
||||
.await?,
|
||||
line2: address_details
|
||||
.line2
|
||||
.async_lift(|inner| encrypt_optional(inner, key))
|
||||
.await?,
|
||||
line3: address_details
|
||||
.line3
|
||||
.async_lift(|inner| encrypt_optional(inner, key))
|
||||
.await?,
|
||||
zip: address_details
|
||||
.zip
|
||||
.async_lift(|inner| encrypt_optional(inner, key))
|
||||
.await?,
|
||||
state: address_details
|
||||
.state
|
||||
.async_lift(|inner| encrypt_optional(inner, key))
|
||||
.await?,
|
||||
first_name: address_details
|
||||
.first_name
|
||||
.async_lift(|inner| encrypt_optional(inner, key))
|
||||
.await?,
|
||||
last_name: address_details
|
||||
.last_name
|
||||
.async_lift(|inner| encrypt_optional(inner, key))
|
||||
.await?,
|
||||
phone_number: self
|
||||
.phone
|
||||
.clone()
|
||||
.async_lift(|inner| encrypt_optional(inner, key))
|
||||
.await?,
|
||||
country_code: self.phone_country_code.clone(),
|
||||
})
|
||||
}
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_domain_address(
|
||||
&self,
|
||||
address_details: api_models::payments::AddressDetails,
|
||||
merchant_id: &str,
|
||||
customer_id: &str,
|
||||
key: &[u8],
|
||||
) -> CustomResult<domain::Address, common_utils::errors::CryptoError> {
|
||||
async {
|
||||
Ok(domain::Address {
|
||||
id: None,
|
||||
city: address_details.city,
|
||||
country: address_details.country,
|
||||
line1: address_details
|
||||
.line1
|
||||
.async_lift(|inner| encrypt_optional(inner, key))
|
||||
.await?,
|
||||
line2: address_details
|
||||
.line2
|
||||
.async_lift(|inner| encrypt_optional(inner, key))
|
||||
.await?,
|
||||
line3: address_details
|
||||
.line3
|
||||
.async_lift(|inner| encrypt_optional(inner, key))
|
||||
.await?,
|
||||
zip: address_details
|
||||
.zip
|
||||
.async_lift(|inner| encrypt_optional(inner, key))
|
||||
.await?,
|
||||
state: address_details
|
||||
.state
|
||||
.async_lift(|inner| encrypt_optional(inner, key))
|
||||
.await?,
|
||||
first_name: address_details
|
||||
.first_name
|
||||
.async_lift(|inner| encrypt_optional(inner, key))
|
||||
.await?,
|
||||
last_name: address_details
|
||||
.last_name
|
||||
.async_lift(|inner| encrypt_optional(inner, key))
|
||||
.await?,
|
||||
phone_number: self
|
||||
.phone
|
||||
.clone()
|
||||
.async_lift(|inner| encrypt_optional(inner, key))
|
||||
.await?,
|
||||
country_code: self.phone_country_code.clone(),
|
||||
customer_id: customer_id.to_string(),
|
||||
merchant_id: merchant_id.to_string(),
|
||||
address_id: generate_id(consts::ID_LENGTH, "add"),
|
||||
payment_id: None,
|
||||
created_at: common_utils::date_time::now(),
|
||||
modified_at: common_utils::date_time::now(),
|
||||
})
|
||||
}
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
-- This file should undo anything in `up.sql`
|
||||
ALTER TABLE address DROP COLUMN payment_id;
|
||||
ALTER TABLE customers DROP COLUMN address_id;
|
||||
@ -0,0 +1,3 @@
|
||||
-- Your SQL goes here
|
||||
ALTER TABLE address ADD COLUMN payment_id VARCHAR(64);
|
||||
ALTER TABLE customers ADD COLUMN address_id VARCHAR(64);
|
||||
@ -0,0 +1,2 @@
|
||||
-- This file should undo anything in `up.sql`
|
||||
ALTER TABLE address ALTER COLUMN id SET NOT NULL;
|
||||
@ -0,0 +1,2 @@
|
||||
-- Your SQL goes here
|
||||
ALTER TABLE address ALTER COLUMN id DROP NOT NULL;
|
||||
Reference in New Issue
Block a user