mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-11-03 05:17:02 +08:00
feat(router): Pass customers address in retrieve customer (#2376)
This commit is contained in:
@ -17,6 +17,15 @@ impl AddressNew {
|
||||
}
|
||||
|
||||
impl Address {
|
||||
#[instrument(skip(conn))]
|
||||
pub async fn find_by_address_id<'a>(
|
||||
conn: &PgPooledConn,
|
||||
address_id: &str,
|
||||
) -> StorageResult<Self> {
|
||||
generics::generic_find_by_id::<<Self as HasTable>::Table, _, _>(conn, address_id.to_owned())
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(skip(conn))]
|
||||
pub async fn update_by_address_id(
|
||||
conn: &PgPooledConn,
|
||||
|
||||
@ -40,7 +40,7 @@ pub async fn create_customer(
|
||||
customer_data.merchant_id = merchant_id.to_owned();
|
||||
|
||||
let key = key_store.key.get_inner().peek();
|
||||
let address_id = if let Some(addr) = &customer_data.address {
|
||||
let address = if let Some(addr) = &customer_data.address {
|
||||
let customer_address: api_models::payments::AddressDetails = addr.clone();
|
||||
|
||||
let address = customer_data
|
||||
@ -53,8 +53,7 @@ pub async fn create_customer(
|
||||
db.insert_address_for_customers(address, &key_store)
|
||||
.await
|
||||
.switch()
|
||||
.attach_printable("Failed while inserting new address")?
|
||||
.address_id,
|
||||
.attach_printable("Failed while inserting new address")?,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
@ -81,7 +80,7 @@ pub async fn create_customer(
|
||||
metadata: customer_data.metadata,
|
||||
id: None,
|
||||
connector_customer: None,
|
||||
address_id,
|
||||
address_id: address.clone().map(|addr| addr.address_id),
|
||||
created_at: common_utils::date_time::now(),
|
||||
modified_at: common_utils::date_time::now(),
|
||||
})
|
||||
@ -107,10 +106,12 @@ pub async fn create_customer(
|
||||
}
|
||||
}
|
||||
};
|
||||
let mut customer_response: customers::CustomerResponse = customer.into();
|
||||
customer_response.address = customer_data.address;
|
||||
|
||||
Ok(services::ApplicationResponse::Json(customer_response))
|
||||
let address_details = address.map(api_models::payments::AddressDetails::from);
|
||||
|
||||
Ok(services::ApplicationResponse::Json(
|
||||
customers::CustomerResponse::from((customer, address_details)),
|
||||
))
|
||||
}
|
||||
|
||||
#[instrument(skip(state))]
|
||||
@ -129,8 +130,17 @@ pub async fn retrieve_customer(
|
||||
)
|
||||
.await
|
||||
.switch()?;
|
||||
|
||||
Ok(services::ApplicationResponse::Json(response.into()))
|
||||
let address = match &response.address_id {
|
||||
Some(address_id) => Some(api_models::payments::AddressDetails::from(
|
||||
db.find_address_by_address_id(address_id, &key_store)
|
||||
.await
|
||||
.switch()?,
|
||||
)),
|
||||
None => None,
|
||||
};
|
||||
Ok(services::ApplicationResponse::Json(
|
||||
customers::CustomerResponse::from((response, address)),
|
||||
))
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
@ -294,7 +304,7 @@ pub async fn update_customer(
|
||||
|
||||
let key = key_store.key.get_inner().peek();
|
||||
|
||||
let address_id = if let Some(addr) = &update_customer.address {
|
||||
let address = if let Some(addr) = &update_customer.address {
|
||||
match customer.address_id {
|
||||
Some(address_id) => {
|
||||
let customer_address: api_models::payments::AddressDetails = addr.clone();
|
||||
@ -303,14 +313,15 @@ pub async fn update_customer(
|
||||
.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)
|
||||
Some(
|
||||
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
|
||||
))?,
|
||||
)
|
||||
}
|
||||
None => {
|
||||
let customer_address: api_models::payments::AddressDetails = addr.clone();
|
||||
@ -329,13 +340,19 @@ pub async fn update_customer(
|
||||
db.insert_address_for_customers(address, &key_store)
|
||||
.await
|
||||
.switch()
|
||||
.attach_printable("Failed while inserting new address")?
|
||||
.address_id,
|
||||
.attach_printable("Failed while inserting new address")?,
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
match &customer.address_id {
|
||||
Some(address_id) => Some(
|
||||
db.find_address_by_address_id(address_id, &key_store)
|
||||
.await
|
||||
.switch()?,
|
||||
),
|
||||
None => None,
|
||||
}
|
||||
};
|
||||
|
||||
let response = db
|
||||
@ -364,7 +381,7 @@ pub async fn update_customer(
|
||||
metadata: update_customer.metadata,
|
||||
description: update_customer.description,
|
||||
connector_customer: None,
|
||||
address_id,
|
||||
address_id: address.clone().map(|addr| addr.address_id),
|
||||
})
|
||||
}
|
||||
.await
|
||||
@ -375,9 +392,7 @@ pub async fn update_customer(
|
||||
.await
|
||||
.switch()?;
|
||||
|
||||
let mut customer_update_response: customers::CustomerResponse = response.into();
|
||||
customer_update_response.address = update_customer.address;
|
||||
Ok(services::ApplicationResponse::Json(
|
||||
customer_update_response,
|
||||
customers::CustomerResponse::from((response, update_customer.address)),
|
||||
))
|
||||
}
|
||||
|
||||
@ -28,6 +28,12 @@ where
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
) -> CustomResult<domain::Address, errors::StorageError>;
|
||||
|
||||
async fn find_address_by_address_id(
|
||||
&self,
|
||||
address_id: &str,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
) -> CustomResult<domain::Address, errors::StorageError>;
|
||||
|
||||
async fn insert_address_for_payments(
|
||||
&self,
|
||||
payment_id: &str,
|
||||
@ -82,6 +88,25 @@ mod storage {
|
||||
};
|
||||
#[async_trait::async_trait]
|
||||
impl AddressInterface for Store {
|
||||
async fn find_address_by_address_id(
|
||||
&self,
|
||||
address_id: &str,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
) -> CustomResult<domain::Address, errors::StorageError> {
|
||||
let conn = connection::pg_connection_read(self).await?;
|
||||
storage_types::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
|
||||
}
|
||||
|
||||
async fn find_address_by_merchant_id_payment_id_address_id(
|
||||
&self,
|
||||
merchant_id: &str,
|
||||
@ -237,6 +262,25 @@ mod storage {
|
||||
};
|
||||
#[async_trait::async_trait]
|
||||
impl AddressInterface for Store {
|
||||
async fn find_address_by_address_id(
|
||||
&self,
|
||||
address_id: &str,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
) -> CustomResult<domain::Address, errors::StorageError> {
|
||||
let conn = connection::pg_connection_read(self).await?;
|
||||
storage_types::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
|
||||
}
|
||||
|
||||
async fn find_address_by_merchant_id_payment_id_address_id(
|
||||
&self,
|
||||
merchant_id: &str,
|
||||
@ -447,6 +491,31 @@ mod storage {
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl AddressInterface for MockDb {
|
||||
async fn find_address_by_address_id(
|
||||
&self,
|
||||
address_id: &str,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
) -> CustomResult<domain::Address, errors::StorageError> {
|
||||
match self
|
||||
.addresses
|
||||
.lock()
|
||||
.await
|
||||
.iter()
|
||||
.find(|address| address.address_id == address_id)
|
||||
{
|
||||
Some(address) => address
|
||||
.clone()
|
||||
.convert(key_store.key.get_inner())
|
||||
.await
|
||||
.change_context(errors::StorageError::DecryptionError),
|
||||
None => {
|
||||
return Err(
|
||||
errors::StorageError::ValueNotFound("address not found".to_string()).into(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn find_address_by_merchant_id_payment_id_address_id(
|
||||
&self,
|
||||
_merchant_id: &str,
|
||||
|
||||
@ -2,6 +2,7 @@ use api_models::customers;
|
||||
pub use api_models::customers::{CustomerDeleteResponse, CustomerId, CustomerRequest};
|
||||
use serde::Serialize;
|
||||
|
||||
use super::payments;
|
||||
use crate::{core::errors::RouterResult, newtype, types::domain};
|
||||
|
||||
newtype!(
|
||||
@ -13,8 +14,8 @@ pub(crate) trait CustomerRequestExt: Sized {
|
||||
fn validate(self) -> RouterResult<Self>;
|
||||
}
|
||||
|
||||
impl From<domain::Customer> for CustomerResponse {
|
||||
fn from(cust: domain::Customer) -> Self {
|
||||
impl From<(domain::Customer, Option<payments::AddressDetails>)> for CustomerResponse {
|
||||
fn from((cust, address): (domain::Customer, Option<payments::AddressDetails>)) -> Self {
|
||||
customers::CustomerResponse {
|
||||
customer_id: cust.customer_id,
|
||||
name: cust.name,
|
||||
@ -24,7 +25,7 @@ impl From<domain::Customer> for CustomerResponse {
|
||||
description: cust.description,
|
||||
created_at: cust.created_at,
|
||||
metadata: cust.metadata,
|
||||
address: None,
|
||||
address,
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// use actix_web::HttpMessage;
|
||||
use actix_web::http::header::HeaderMap;
|
||||
use api_models::enums as api_enums;
|
||||
use api_models::{enums as api_enums, payments};
|
||||
use common_utils::{
|
||||
crypto::Encryptable,
|
||||
ext_traits::{StringExt, ValueExt},
|
||||
@ -798,3 +798,19 @@ impl
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<domain::Address> for payments::AddressDetails {
|
||||
fn from(addr: domain::Address) -> Self {
|
||||
Self {
|
||||
city: addr.city,
|
||||
country: addr.country,
|
||||
line1: addr.line1.map(Encryptable::into_inner),
|
||||
line2: addr.line2.map(Encryptable::into_inner),
|
||||
line3: addr.line3.map(Encryptable::into_inner),
|
||||
zip: addr.zip.map(Encryptable::into_inner),
|
||||
state: addr.state.map(Encryptable::into_inner),
|
||||
first_name: addr.first_name.map(Encryptable::into_inner),
|
||||
last_name: addr.last_name.map(Encryptable::into_inner),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user