Skip to content

Commit

Permalink
feat(router): Pass customers address in retrieve customer (#2376)
Browse files Browse the repository at this point in the history
  • Loading branch information
ShankarSinghC authored Sep 27, 2023
1 parent ee91552 commit f6cfb05
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 29 deletions.
9 changes: 9 additions & 0 deletions crates/diesel_models/src/query/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
65 changes: 40 additions & 25 deletions crates/router/src/core/customers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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(),
})
Expand All @@ -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))]
Expand All @@ -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)]
Expand Down Expand Up @@ -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();
Expand All @@ -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();
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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)),
))
}
69 changes: 69 additions & 0 deletions crates/router/src/db/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
7 changes: 4 additions & 3 deletions crates/router/src/types/api/customers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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!(
Expand All @@ -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,
Expand All @@ -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()
}
Expand Down
18 changes: 17 additions & 1 deletion crates/router/src/types/transformers.rs
Original file line number Diff line number Diff line change
@@ -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},
Expand Down Expand Up @@ -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),
}
}
}

0 comments on commit f6cfb05

Please sign in to comment.