Skip to content

Commit 5c4e7c9

Browse files
kashif-mKashifgithub-actions[bot]
authored
refactor: add mapping for ConnectorError in payouts flow (#2608)
Co-authored-by: Kashif <[email protected]> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Kashif <[email protected]>
1 parent cfabfa6 commit 5c4e7c9

File tree

96 files changed

+2310
-62
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

96 files changed

+2310
-62
lines changed

crates/api_models/src/payouts.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ pub struct PayoutCreateResponse {
382382
pub error_code: Option<String>,
383383

384384
/// The business profile that is associated with this payment
385-
pub profile_id: Option<String>,
385+
pub profile_id: String,
386386
}
387387

388388
#[derive(Default, Debug, Clone, Deserialize, ToSchema)]

crates/diesel_models/src/payout_attempt.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub struct PayoutAttempt {
2626
pub created_at: PrimitiveDateTime,
2727
#[serde(with = "common_utils::custom_serde::iso8601")]
2828
pub last_modified_at: PrimitiveDateTime,
29-
pub profile_id: Option<String>,
29+
pub profile_id: String,
3030
pub merchant_connector_id: Option<String>,
3131
}
3232

@@ -51,7 +51,7 @@ impl Default for PayoutAttempt {
5151
business_label: None,
5252
created_at: now,
5353
last_modified_at: now,
54-
profile_id: None,
54+
profile_id: String::default(),
5555
merchant_connector_id: None,
5656
}
5757
}

crates/diesel_models/src/schema.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -755,7 +755,7 @@ diesel::table! {
755755
created_at -> Timestamp,
756756
last_modified_at -> Timestamp,
757757
#[max_length = 64]
758-
profile_id -> Nullable<Varchar>,
758+
profile_id -> Varchar,
759759
#[max_length = 32]
760760
merchant_connector_id -> Nullable<Varchar>,
761761
}

crates/router/src/connector/adyen/transformers.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4010,8 +4010,12 @@ impl<F> TryFrom<&AdyenRouterData<&types::PayoutsRouterData<F>>> for AdyenPayoutC
40104010
iban: Some(b.iban),
40114011
tax_id: None,
40124012
},
4013-
_ => Err(errors::ConnectorError::NotSupported {
4014-
message: "Bank transfers via ACH or Bacs are not supported".to_string(),
4013+
payouts::BankPayout::Ach(..) => Err(errors::ConnectorError::NotSupported {
4014+
message: "Bank transfer via ACH is not supported".to_string(),
4015+
connector: "Adyen",
4016+
})?,
4017+
payouts::BankPayout::Bacs(..) => Err(errors::ConnectorError::NotSupported {
4018+
message: "Bank transfer via Bacs is not supported".to_string(),
40154019
connector: "Adyen",
40164020
})?,
40174021
};

crates/router/src/core/errors/utils.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,11 @@ impl<T> ConnectorErrorExt<T> for error_stack::Result<T, errors::ConnectorError>
400400
field_names: field_names.to_vec(),
401401
}
402402
}
403+
errors::ConnectorError::NotSupported { message, connector } => {
404+
errors::ApiErrorResponse::NotSupported {
405+
message: format!("{} by {}", message, connector),
406+
}
407+
}
403408
_ => errors::ApiErrorResponse::InternalServerError,
404409
};
405410
err.change_context(error)

crates/router/src/core/payouts.rs

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ pub struct PayoutData {
3535
pub payout_attempt: storage::PayoutAttempt,
3636
pub payout_method_data: Option<payouts::PayoutMethodData>,
3737
pub merchant_connector_account: Option<payment_helpers::MerchantConnectorAccountType>,
38+
pub profile_id: String,
3839
}
3940

4041
// ********************************************** CORE FLOWS **********************************************
@@ -96,9 +97,7 @@ pub async fn payouts_create_core(
9697
merchant_account: domain::MerchantAccount,
9798
key_store: domain::MerchantKeyStore,
9899
req: payouts::PayoutCreateRequest,
99-
) -> RouterResponse<payouts::PayoutCreateResponse>
100-
where
101-
{
100+
) -> RouterResponse<payouts::PayoutCreateResponse> {
102101
// Form connector data
103102
let connector_data = get_connector_data(
104103
&state,
@@ -111,7 +110,7 @@ where
111110
.await?;
112111

113112
// Validate create request
114-
let (payout_id, payout_method_data) =
113+
let (payout_id, payout_method_data, profile_id) =
115114
validator::validate_create_request(&state, &merchant_account, &req, &key_store).await?;
116115

117116
// Create DB entries
@@ -121,6 +120,7 @@ where
121120
&key_store,
122121
&req,
123122
&payout_id,
123+
&profile_id,
124124
&connector_data.connector_name,
125125
payout_method_data.as_ref(),
126126
)
@@ -561,18 +561,8 @@ pub async fn create_recipient(
561561
let customer_details = payout_data.customer_details.to_owned();
562562
let connector_name = connector_data.connector_name.to_string();
563563

564-
let profile_id = core_utils::get_profile_id_from_business_details(
565-
payout_data.payout_attempt.business_country,
566-
payout_data.payout_attempt.business_label.as_ref(),
567-
merchant_account,
568-
payout_data.payout_attempt.profile_id.as_ref(),
569-
&*state.store,
570-
false,
571-
)
572-
.await?;
573-
574564
// Create the connector label using {profile_id}_{connector_name}
575-
let connector_label = format!("{profile_id}_{}", connector_name);
565+
let connector_label = format!("{}_{}", payout_data.profile_id, connector_name);
576566

577567
let (should_call_connector, _connector_customer_id) =
578568
helpers::should_call_payout_connector_create_customer(
@@ -1124,13 +1114,15 @@ pub async fn response_handler(
11241114
}
11251115

11261116
// DB entries
1117+
#[allow(clippy::too_many_arguments)]
11271118
#[cfg(feature = "payouts")]
11281119
pub async fn payout_create_db_entries(
11291120
state: &AppState,
11301121
merchant_account: &domain::MerchantAccount,
11311122
key_store: &domain::MerchantKeyStore,
11321123
req: &payouts::PayoutCreateRequest,
11331124
payout_id: &String,
1125+
profile_id: &String,
11341126
connector_name: &api_enums::PayoutConnectors,
11351127
stored_payout_method_data: Option<&payouts::PayoutMethodData>,
11361128
) -> RouterResult<PayoutData> {
@@ -1231,8 +1223,7 @@ pub async fn payout_create_db_entries(
12311223
} else {
12321224
storage_enums::PayoutStatus::RequiresPayoutMethodData
12331225
};
1234-
let _id = core_utils::get_or_generate_uuid("payout_attempt_id", None)?;
1235-
let payout_attempt_id = format!("{}_{}", merchant_id.to_owned(), payout_id.to_owned());
1226+
let payout_attempt_id = utils::get_payment_attempt_id(payout_id, 1);
12361227

12371228
let payout_attempt_req = storage::PayoutAttemptNew::default()
12381229
.set_payout_attempt_id(payout_attempt_id.to_string())
@@ -1247,7 +1238,7 @@ pub async fn payout_create_db_entries(
12471238
.set_payout_token(req.payout_token.to_owned())
12481239
.set_created_at(Some(common_utils::date_time::now()))
12491240
.set_last_modified_at(Some(common_utils::date_time::now()))
1250-
.set_profile_id(req.profile_id.to_owned())
1241+
.set_profile_id(Some(profile_id.to_string()))
12511242
.to_owned();
12521243
let payout_attempt = db
12531244
.insert_payout_attempt(payout_attempt_req)
@@ -1269,6 +1260,7 @@ pub async fn payout_create_db_entries(
12691260
.cloned()
12701261
.or(stored_payout_method_data.cloned()),
12711262
merchant_connector_account: None,
1263+
profile_id: profile_id.to_owned(),
12721264
})
12731265
}
12741266

@@ -1318,12 +1310,15 @@ pub async fn make_payout_data(
13181310
.await
13191311
.map_or(None, |c| c);
13201312

1313+
let profile_id = payout_attempt.profile_id.clone();
1314+
13211315
Ok(PayoutData {
13221316
billing_address,
13231317
customer_details,
13241318
payouts,
13251319
payout_attempt,
13261320
payout_method_data: None,
13271321
merchant_connector_account: None,
1322+
profile_id,
13281323
})
13291324
}

crates/router/src/core/payouts/validator.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ use crate::{
88
utils as core_utils,
99
},
1010
db::StorageInterface,
11-
logger,
1211
routes::AppState,
1312
types::{api::payouts, domain, storage},
1413
utils,
@@ -24,8 +23,6 @@ pub async fn validate_uniqueness_of_payout_id_against_merchant_id(
2423
let payout = db
2524
.find_payout_by_merchant_id_payout_id(merchant_id, payout_id)
2625
.await;
27-
28-
logger::debug!(?payout);
2926
match payout {
3027
Err(err) => {
3128
if err.current_context().is_db_not_found() {
@@ -58,7 +55,7 @@ pub async fn validate_create_request(
5855
merchant_account: &domain::MerchantAccount,
5956
req: &payouts::PayoutCreateRequest,
6057
merchant_key_store: &domain::MerchantKeyStore,
61-
) -> RouterResult<(String, Option<payouts::PayoutMethodData>)> {
58+
) -> RouterResult<(String, Option<payouts::PayoutMethodData>, String)> {
6259
let merchant_id = &merchant_account.merchant_id;
6360

6461
// Merchant ID
@@ -111,5 +108,16 @@ pub async fn validate_create_request(
111108
None => None,
112109
};
113110

114-
Ok((payout_id, payout_method_data))
111+
// Profile ID
112+
let profile_id = core_utils::get_profile_id_from_business_details(
113+
req.business_country,
114+
req.business_label.as_ref(),
115+
merchant_account,
116+
req.profile_id.as_ref(),
117+
&*state.store,
118+
false,
119+
)
120+
.await?;
121+
122+
Ok((payout_id, payout_method_data, profile_id))
115123
}

crates/router/src/core/utils.rs

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -48,33 +48,21 @@ pub async fn get_mca_for_payout<'a>(
4848
merchant_account: &domain::MerchantAccount,
4949
key_store: &domain::MerchantKeyStore,
5050
payout_data: &PayoutData,
51-
) -> RouterResult<(helpers::MerchantConnectorAccountType, String)> {
52-
let payout_attempt = &payout_data.payout_attempt;
53-
let profile_id = get_profile_id_from_business_details(
54-
payout_attempt.business_country,
55-
payout_attempt.business_label.as_ref(),
56-
merchant_account,
57-
payout_attempt.profile_id.as_ref(),
58-
&*state.store,
59-
false,
60-
)
61-
.await
62-
.change_context(errors::ApiErrorResponse::InternalServerError)
63-
.attach_printable("profile_id is not set in payout_attempt")?;
51+
) -> RouterResult<helpers::MerchantConnectorAccountType> {
6452
match payout_data.merchant_connector_account.to_owned() {
65-
Some(mca) => Ok((mca, profile_id)),
53+
Some(mca) => Ok(mca),
6654
None => {
6755
let merchant_connector_account = helpers::get_merchant_connector_account(
6856
state,
6957
merchant_account.merchant_id.as_str(),
7058
None,
7159
key_store,
72-
&profile_id,
60+
&payout_data.profile_id,
7361
connector_id,
74-
payout_attempt.merchant_connector_id.as_ref(),
62+
payout_data.payout_attempt.merchant_connector_id.as_ref(),
7563
)
7664
.await?;
77-
Ok((merchant_connector_account, profile_id))
65+
Ok(merchant_connector_account)
7866
}
7967
}
8068
}
@@ -89,7 +77,7 @@ pub async fn construct_payout_router_data<'a, F>(
8977
_request: &api_models::payouts::PayoutRequest,
9078
payout_data: &mut PayoutData,
9179
) -> RouterResult<types::PayoutsRouterData<F>> {
92-
let (merchant_connector_account, profile_id) = get_mca_for_payout(
80+
let merchant_connector_account = get_mca_for_payout(
9381
state,
9482
connector_id,
9583
merchant_account,
@@ -135,7 +123,7 @@ pub async fn construct_payout_router_data<'a, F>(
135123
let payouts = &payout_data.payouts;
136124
let payout_attempt = &payout_data.payout_attempt;
137125
let customer_details = &payout_data.customer_details;
138-
let connector_label = format!("{profile_id}_{}", payout_attempt.connector);
126+
let connector_label = format!("{}_{}", payout_data.profile_id, payout_attempt.connector);
139127
let connector_customer_id = customer_details
140128
.as_ref()
141129
.and_then(|c| c.connector_customer.as_ref())
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
ALTER TABLE
2+
payout_attempt
3+
ALTER COLUMN
4+
profile_id DROP NOT NULL;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
ALTER TABLE
2+
payout_attempt
3+
ALTER COLUMN
4+
profile_id
5+
SET
6+
NOT NULL;

0 commit comments

Comments
 (0)