diff --git a/src/decider/gatewaydecider/constants.rs b/src/decider/gatewaydecider/constants.rs index 1a5ded74..42678ea3 100644 --- a/src/decider/gatewaydecider/constants.rs +++ b/src/decider/gatewaydecider/constants.rs @@ -742,6 +742,7 @@ pub const paymentFlowsRequiredForGwFiltering: [&str; 12] = [ "CROSS_BORDER_PAYMENT", "SINGLE_BLOCK_MULTIPLE_DEBIT", "ONE_TIME_MANDATE", + "PARTIAL_TPV" ]; pub const getCardBrandCacheExpiry: i32 = 2 * 24 * 60 * 60; diff --git a/src/decider/gatewaydecider/flows.rs b/src/decider/gatewaydecider/flows.rs index b867ef11..137e049c 100644 --- a/src/decider/gatewaydecider/flows.rs +++ b/src/decider/gatewaydecider/flows.rs @@ -1161,6 +1161,9 @@ pub async fn getFailureReasonWithFilter( "filterFunctionalGatewaysForOTMFlow" => { "No functional gateways after filtering for OTM flow.".to_string() } + "filterFunctionalGatewaysForAvailablePaymentFlows" => { + "No functional gateways after filtering for available payment flows.".to_string() + } "filterFunctionalGateways" => { if Utils::is_card_transaction(txn_card_info) { if m_internal_meta diff --git a/src/decider/gatewaydecider/gw_filter.rs b/src/decider/gatewaydecider/gw_filter.rs index 5095ff78..461121aa 100644 --- a/src/decider/gatewaydecider/gw_filter.rs +++ b/src/decider/gatewaydecider/gw_filter.rs @@ -229,6 +229,7 @@ pub async fn newGwFilters( let _ = filterFunctionalGatewaysForSplitSettlement(this).await; let _ = filterFunctionalGatewaysForMerchantRequiredFlow(this).await; let _ = filterFunctionalGatewaysForOTMFlow(this).await; + let _ = FilterFunctionalGatewaysForAvailableFlows(this.await) ; let _ = filterGatewaysForMGASelectionIntegrity(this).await; let funcGateways = returnGwListWithLog(this, DeciderFilterName::FinalFunctionalGateways, false); @@ -1453,6 +1454,86 @@ pub async fn filterFunctionalGatewaysForOTMFlow(this: &mut DeciderFlow<'_>) -> V ) } +pub async fn filterFunctionalGatewaysForAvailablePaymentFlows(this: &mut DeciderFlow<'_>) -> GatewayList { + let st = getGws(this); + let txn_detail = this.get().dpTxnDetail.clone(); + let macc = this.get().dpMerchantAccount.clone(); + let order_reference = this.get().dpOrder.clone(); + let txn_card_info = this.get().dpTxnCardInfo.clone(); + let all_flows = Utils::get_payment_flow_list_from_txn_detail(&txn_detail); + let relevant_flows = Utils::filter_relevant_payment_flows(all_flows); + + if relevant_flows.is_empty() { + setGws(this, st); + } else { + if let Ok(Some(jbc)) = find_bank_code(txn_card_info.paymentMethod.clone()).await { + let (metadata, pl_ref_id_map) = Utils::get_order_metadata_and_pl_ref_id_map( + this, + macc.enableGatewayReferenceIdBasedRouting, + &order_reference, + ); + let possible_ref_ids_of_merchant = + Utils::get_all_possible_ref_ids(metadata, order_reference, pl_ref_id_map); + let enabled_mgas = + SETMA::get_enabled_mgas_by_merchant_id_and_ref_id(this, macc.merchantId, possible_ref_ids_of_merchant).await; + + let filtered_mgas_by_enablement: Vec<_> = enabled_mgas + .into_iter() + .filter(|mga| { + relevant_flows.iter().all(|flow| { + Utils::is_payment_flow_enabled_in_mga(mga, flow).unwrap_or(false) + }) + }) + .collect(); + + let eligible_mga_post_filtering: Vec<_> = filtered_mgas_by_enablement + .into_iter() + .filter(|mga| st.contains(&mga.gateway)) + .collect(); + + let all_mga_ids: Vec<_> = eligible_mga_post_filtering + .iter() + .map(|mga| mga.id.merchantGwAccId) + .collect(); + + let mut final_eligible_mga = eligible_mga_post_filtering.clone(); + + for flow in relevant_flows { + let current_gws: Vec<_> = final_eligible_mga.iter().map(|mga| mga.gateway.clone()).collect(); + let gpmf_entries = GPMF::find_all_gpmf_by_country_code_gw_pf_id_pmt_jbcid_db( + crate::types::country::country_iso::CountryISO::IND, + current_gws, + Utils::text_to_payment_flow_or_error(&flow), + txn_card_info.paymentMethodType.clone(), + jbc.id, + ) + .await + .unwrap_or_default(); + + let gpmf_ids: Vec<_> = gpmf_entries.iter().map(|entry| entry.id.clone()).collect(); + let mgpmf_entries = + MGPMF::get_all_mgpmf_by_mga_id_and_gpmf_ids(all_mga_ids.clone(), gpmf_ids).await; + let mgpmf_mga_ids: Vec<_> = mgpmf_entries + .iter() + .map(|entry| entry.merchantGatewayAccountId) + .collect(); + + final_eligible_mga = final_eligible_mga + .into_iter() + .filter(|mga| mgpmf_mga_ids.contains(&mga.id.merchantGwAccId)) + .collect(); + } + + let final_gws = final_eligible_mga.iter().map(|mga| mga.gateway.clone()).collect(); + Utils::set_mgas(this, final_eligible_mga); + setGws(this, final_gws); + } else { + setGws(this, st); + } + } + returnGwListWithLog(this, DeciderFilterName::FilterFunctionalGatewaysForAvailableFlows, true) +} + /// Filters gateways based on transaction validation type (Card Mandate, TPV, E-Mandate) pub async fn filterGatewaysForValidationType( this: &mut DeciderFlow<'_>, diff --git a/src/decider/gatewaydecider/gw_filter_new.rs b/src/decider/gatewaydecider/gw_filter_new.rs index 2737dd84..a0d0002a 100644 --- a/src/decider/gatewaydecider/gw_filter_new.rs +++ b/src/decider/gatewaydecider/gw_filter_new.rs @@ -93,6 +93,7 @@ pub async fn newGwFilters(this: &mut DeciderFlow<'_>) -> (GatewayList, Vec) -> Vec } +pub async fn filterFunctionalGatewaysForAvailablePaymentFlows(this: &mut DeciderFlow<'_>) -> GatewayList { + let st = getGws(this); + let txn_detail = this.get().dpTxnDetail.clone(); + let macc = this.get().dpMerchantAccount.clone(); + let order_reference = this.get().dpOrder.clone(); + let txn_card_info = this.get().dpTxnCardInfo.clone(); + let all_flows = Utils::get_payment_flow_list_from_txn_detail(&txn_detail); + let relevant_flows = Utils::filter_relevant_payment_flows(all_flows); + + if relevant_flows.is_empty() { + setGws(this, st); + } else { + if let Ok(Some(jbc)) = find_bank_code(txn_card_info.paymentMethod.clone()).await { + let (metadata, pl_ref_id_map) = Utils::get_order_metadata_and_pl_ref_id_map( + this, + macc.enableGatewayReferenceIdBasedRouting, + &order_reference, + ); + let possible_ref_ids_of_merchant = + Utils::get_all_possible_ref_ids(metadata, order_reference, pl_ref_id_map); + let enabled_mgas = + SETMA::get_enabled_mgas_by_merchant_id_and_ref_id(this, macc.merchantId, possible_ref_ids_of_merchant).await; + + let filtered_mgas_by_enablement: Vec<_> = enabled_mgas + .into_iter() + .filter(|mga| { + relevant_flows.iter().all(|flow| { + Utils::is_payment_flow_enabled_in_mga(mga, flow).unwrap_or(false) + }) + }) + .collect(); + + let eligible_mga_post_filtering: Vec<_> = filtered_mgas_by_enablement + .into_iter() + .filter(|mga| st.contains(&mga.gateway)) + .collect(); + + let all_mga_ids: Vec<_> = eligible_mga_post_filtering + .iter() + .map(|mga| mga.id.merchantGwAccId) + .collect(); + + let mut final_eligible_mga = eligible_mga_post_filtering.clone(); + + for flow in relevant_flows { + let current_gws: Vec<_> = final_eligible_mga.iter().map(|mga| mga.gateway.clone()).collect(); + let gpmf_entries = GPMF::find_all_gpmf_by_country_code_gw_pf_id_pmt_jbcid_db( + crate::types::country::country_iso::CountryISO::IND, + current_gws, + Utils::text_to_payment_flow_or_error(&flow), + txn_card_info.paymentMethodType.clone(), + jbc.id, + ) + .await + .unwrap_or_default(); + + let gpmf_ids: Vec<_> = gpmf_entries.iter().map(|entry| entry.id.clone()).collect(); + let mgpmf_entries = + MGPMF::get_all_mgpmf_by_mga_id_and_gpmf_ids(all_mga_ids.clone(), gpmf_ids).await; + let mgpmf_mga_ids: Vec<_> = mgpmf_entries + .iter() + .map(|entry| entry.merchantGatewayAccountId) + .collect(); + + final_eligible_mga = final_eligible_mga + .into_iter() + .filter(|mga| mgpmf_mga_ids.contains(&mga.id.merchantGwAccId)) + .collect(); + } + + let final_gws = final_eligible_mga.iter().map(|mga| mga.gateway.clone()).collect(); + Utils::set_mgas(this, final_eligible_mga); + setGws(this, final_gws); + } else { + setGws(this, st); + } + } + returnGwListWithLog(this, DeciderFilterName::FilterFunctionalGatewaysForAvailableFlows, true) +} + /// Filters gateways based on transaction validation type (Card Mandate, TPV, E-Mandate) pub async fn filterGatewaysForValidationType(this: &mut DeciderFlow<'_>) -> () { diff --git a/src/decider/gatewaydecider/types.rs b/src/decider/gatewaydecider/types.rs index ed9cad8d..2a7df075 100644 --- a/src/decider/gatewaydecider/types.rs +++ b/src/decider/gatewaydecider/types.rs @@ -76,6 +76,7 @@ pub enum DeciderFilterName { FilterGatewaysForEMITenureSpecficGatewayCreds, FilterFunctionalGatewaysForReversePennyDrop, FilterFunctionalGatewaysForOTM, + FilterFunctionalGatewaysForAvailableFlows } impl fmt::Display for DeciderFilterName { @@ -158,6 +159,9 @@ impl fmt::Display for DeciderFilterName { Self::FilterFunctionalGatewaysForOTM => { write!(f, "FilterFunctionalGatewaysForOTM") } + Self::FilterFunctionalGatewaysForAvailableFlows => { + write!(f, "FilterFunctionalGatewaysForAvailableFlows") + } } } } diff --git a/src/decider/gatewaydecider/utils.rs b/src/decider/gatewaydecider/utils.rs index 45c6451b..fb348932 100644 --- a/src/decider/gatewaydecider/utils.rs +++ b/src/decider/gatewaydecider/utils.rs @@ -1218,6 +1218,21 @@ pub fn set_payment_flow_list(decider_flow: &mut DeciderFlow<'_>, payment_flow_li decider_flow.writer.paymentFlowList = payment_flow_list; } +pub fn filter_relevant_payment_flows(flowslist: Vec) -> Vec { + let required_flows: HashSet = [ + "ONE_TIME_MANDATE".to_string(), + "PARTIAL_TPV".to_string(), + ] + .iter() + .cloned() + .collect(); + + flowslist + .into_iter() + .filter(|flow| required_flows.contains(flow)) + .collect() +} + pub fn check_if_enabled_in_mga( mga: &ETM::merchant_gateway_account::MerchantGatewayAccount, payment_flow: &str, @@ -1395,7 +1410,8 @@ pub fn decider_filter_order(filter_name: &str) -> i32 { "filterGatewaysForEMITenureSpecficGatewayCreds" => 24, "filterGatewaysForMGASelectionIntegrity" => 25, "FilterFunctionalGatewaysForOTM" => 26, - _ => 27, + "FilterFunctionalGatewaysForAvailableFlows" => 27, + _ => 28, } }