mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-28 04:04:55 +08:00
fix(router): [worldpayvantiv] dispute validations and statuses (#8862)
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
@ -838,6 +838,3 @@ click_to_pay = {connector_list = "adyen, cybersource, trustpay"}
|
|||||||
[revenue_recovery]
|
[revenue_recovery]
|
||||||
monitoring_threshold_in_seconds = 60
|
monitoring_threshold_in_seconds = 60
|
||||||
retry_algorithm_type = "cascading"
|
retry_algorithm_type = "cascading"
|
||||||
|
|
||||||
[list_dispute_supported_connectors]
|
|
||||||
connector_list = "worldpayvantiv"
|
|
||||||
|
|||||||
@ -3856,7 +3856,60 @@ fn get_dispute_stage(
|
|||||||
|
|
||||||
pub fn get_dispute_status(
|
pub fn get_dispute_status(
|
||||||
dispute_cycle: String,
|
dispute_cycle: String,
|
||||||
) -> Result<api_models::enums::DisputeStatus, error_stack::Report<errors::ConnectorError>> {
|
dispute_activities: Vec<Activity>,
|
||||||
|
) -> Result<common_enums::DisputeStatus, error_stack::Report<errors::ConnectorError>> {
|
||||||
|
if let Some(activity) = get_last_non_auxiliary_activity_type(dispute_activities) {
|
||||||
|
match activity.as_ref() {
|
||||||
|
"Merchant Accept"
|
||||||
|
| "Issuer Accepted Pre-Arbitration"
|
||||||
|
| "Vantiv Accept"
|
||||||
|
| "Sent Credit" => Ok(common_enums::DisputeStatus::DisputeAccepted),
|
||||||
|
|
||||||
|
"Merchant Represent"
|
||||||
|
| "Respond to Dispute"
|
||||||
|
| "Respond to PreArb"
|
||||||
|
| "Request Arbitration"
|
||||||
|
| "Request Pre-Arbitration"
|
||||||
|
| "Create Arbitration"
|
||||||
|
| "Record Arbitration"
|
||||||
|
| "Create Pre-Arbitration"
|
||||||
|
| "File Arbitration"
|
||||||
|
| "File Pre-Arbitration"
|
||||||
|
| "File Visa Pre-Arbitration"
|
||||||
|
| "Send Representment"
|
||||||
|
| "Send Response"
|
||||||
|
| "Arbitration"
|
||||||
|
| "Arbitration (Mastercard)"
|
||||||
|
| "Arbitration Chargeback"
|
||||||
|
| "Issuer Declined Pre-Arbitration"
|
||||||
|
| "Issuer Arbitration"
|
||||||
|
| "Request Response to Pre-Arbitration"
|
||||||
|
| "Vantiv Represent"
|
||||||
|
| "Vantiv Respond"
|
||||||
|
| "Auto Represent"
|
||||||
|
| "Arbitration Ruling" => Ok(common_enums::DisputeStatus::DisputeChallenged),
|
||||||
|
|
||||||
|
"Arbitration Lost" | "Unsuccessful Arbitration" | "Unsuccessful Pre-Arbitration" => {
|
||||||
|
Ok(common_enums::DisputeStatus::DisputeLost)
|
||||||
|
}
|
||||||
|
|
||||||
|
"Arbitration Won"
|
||||||
|
| "Arbitration Split"
|
||||||
|
| "Successful Arbitration"
|
||||||
|
| "Successful Pre-Arbitration" => Ok(common_enums::DisputeStatus::DisputeWon),
|
||||||
|
|
||||||
|
"Chargeback Reversal" => Ok(common_enums::DisputeStatus::DisputeCancelled),
|
||||||
|
|
||||||
|
"Receive Network Transaction" => Ok(common_enums::DisputeStatus::DisputeOpened),
|
||||||
|
|
||||||
|
"Unaccept" | "Unrepresent" => Ok(common_enums::DisputeStatus::DisputeOpened),
|
||||||
|
|
||||||
|
unexpected_activity => Err(errors::ConnectorError::UnexpectedResponseError(
|
||||||
|
bytes::Bytes::from(format!("Dispute Activity: {unexpected_activity})")),
|
||||||
|
)
|
||||||
|
.into()),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
match connector_utils::normalize_string(dispute_cycle.clone())
|
match connector_utils::normalize_string(dispute_cycle.clone())
|
||||||
.change_context(errors::ConnectorError::RequestEncodingFailed)?
|
.change_context(errors::ConnectorError::RequestEncodingFailed)?
|
||||||
.as_str()
|
.as_str()
|
||||||
@ -3878,12 +3931,12 @@ pub fn get_dispute_status(
|
|||||||
"firstchargeback" | "retrievalrequest" | "rapiddisputeresolution" => {
|
"firstchargeback" | "retrievalrequest" | "rapiddisputeresolution" => {
|
||||||
Ok(api_models::enums::DisputeStatus::DisputeOpened)
|
Ok(api_models::enums::DisputeStatus::DisputeOpened)
|
||||||
}
|
}
|
||||||
_ => Err(errors::ConnectorError::NotSupported {
|
dispute_cycle => Err(errors::ConnectorError::UnexpectedResponseError(
|
||||||
message: format!("Dispute status {dispute_cycle}"),
|
bytes::Bytes::from(format!("Dispute Stage: {dispute_cycle}")),
|
||||||
connector: "worldpayvantiv",
|
)
|
||||||
}
|
|
||||||
.into()),
|
.into()),
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_string_to_primitive_date(
|
fn convert_string_to_primitive_date(
|
||||||
@ -3914,7 +3967,7 @@ impl TryFrom<ChargebackCase> for DisputeSyncResponse {
|
|||||||
amount,
|
amount,
|
||||||
currency: item.chargeback_currency_type,
|
currency: item.chargeback_currency_type,
|
||||||
dispute_stage: get_dispute_stage(item.cycle.clone())?,
|
dispute_stage: get_dispute_stage(item.cycle.clone())?,
|
||||||
dispute_status: get_dispute_status(item.cycle.clone())?,
|
dispute_status: get_dispute_status(item.cycle.clone(), item.activity)?,
|
||||||
connector_status: item.cycle.clone(),
|
connector_status: item.cycle.clone(),
|
||||||
connector_dispute_id: item.case_id.clone(),
|
connector_dispute_id: item.case_id.clone(),
|
||||||
connector_reason: item.reason_code_description.clone(),
|
connector_reason: item.reason_code_description.clone(),
|
||||||
@ -4148,3 +4201,40 @@ impl
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_last_non_auxiliary_activity_type(activities: Vec<Activity>) -> Option<String> {
|
||||||
|
let auxiliary_activities: std::collections::HashSet<&'static str> = [
|
||||||
|
"Add Note",
|
||||||
|
"Attach Document",
|
||||||
|
"Attempted Attach Document",
|
||||||
|
"Delete Document",
|
||||||
|
"Update Document",
|
||||||
|
"Move To Error Queue",
|
||||||
|
"Assign to Vantiv",
|
||||||
|
"Assign To Merchant",
|
||||||
|
"Merchant Auto Assign",
|
||||||
|
"Issuer Recalled",
|
||||||
|
"Network Decision",
|
||||||
|
"Request Declined",
|
||||||
|
"Sent Gift",
|
||||||
|
"Successful PayPal",
|
||||||
|
]
|
||||||
|
.iter()
|
||||||
|
.copied()
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let mut last_non_auxiliary_activity = None;
|
||||||
|
|
||||||
|
for activity in activities {
|
||||||
|
let auxiliary_activity = activity
|
||||||
|
.activity_type
|
||||||
|
.as_deref()
|
||||||
|
.map(|activity_type| auxiliary_activities.contains(activity_type))
|
||||||
|
.unwrap_or(false);
|
||||||
|
|
||||||
|
if !auxiliary_activity {
|
||||||
|
last_non_auxiliary_activity = activity.activity_type.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
last_non_auxiliary_activity
|
||||||
|
}
|
||||||
|
|||||||
@ -276,8 +276,10 @@ pub async fn accept_dispute(
|
|||||||
core_utils::validate_profile_id_from_auth_layer(profile_id, &dispute)?;
|
core_utils::validate_profile_id_from_auth_layer(profile_id, &dispute)?;
|
||||||
let dispute_id = dispute.dispute_id.clone();
|
let dispute_id = dispute.dispute_id.clone();
|
||||||
common_utils::fp_utils::when(
|
common_utils::fp_utils::when(
|
||||||
!(dispute.dispute_stage == storage_enums::DisputeStage::Dispute
|
!core_utils::should_proceed_with_accept_dispute(
|
||||||
&& dispute.dispute_status == storage_enums::DisputeStatus::DisputeOpened),
|
dispute.dispute_stage,
|
||||||
|
dispute.dispute_status,
|
||||||
|
),
|
||||||
|| {
|
|| {
|
||||||
metrics::ACCEPT_DISPUTE_STATUS_VALIDATION_FAILURE_METRIC.add(1, &[]);
|
metrics::ACCEPT_DISPUTE_STATUS_VALIDATION_FAILURE_METRIC.add(1, &[]);
|
||||||
Err(errors::ApiErrorResponse::DisputeStatusValidationFailed {
|
Err(errors::ApiErrorResponse::DisputeStatusValidationFailed {
|
||||||
|
|||||||
@ -929,6 +929,9 @@ pub fn validate_dispute_status(
|
|||||||
DisputeStatus::DisputeChallenged
|
DisputeStatus::DisputeChallenged
|
||||||
| DisputeStatus::DisputeWon
|
| DisputeStatus::DisputeWon
|
||||||
| DisputeStatus::DisputeLost
|
| DisputeStatus::DisputeLost
|
||||||
|
| DisputeStatus::DisputeAccepted
|
||||||
|
| DisputeStatus::DisputeCancelled
|
||||||
|
| DisputeStatus::DisputeExpired
|
||||||
),
|
),
|
||||||
DisputeStatus::DisputeWon => matches!(dispute_status, DisputeStatus::DisputeWon),
|
DisputeStatus::DisputeWon => matches!(dispute_status, DisputeStatus::DisputeWon),
|
||||||
DisputeStatus::DisputeLost => matches!(dispute_status, DisputeStatus::DisputeLost),
|
DisputeStatus::DisputeLost => matches!(dispute_status, DisputeStatus::DisputeLost),
|
||||||
@ -2614,12 +2617,27 @@ pub fn should_proceed_with_submit_evidence(
|
|||||||
dispute_stage: DisputeStage,
|
dispute_stage: DisputeStage,
|
||||||
dispute_status: DisputeStatus,
|
dispute_status: DisputeStatus,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
matches!(dispute_stage, DisputeStage::DisputeReversal)
|
matches!(
|
||||||
|| matches!(
|
dispute_stage,
|
||||||
|
DisputeStage::PreDispute
|
||||||
|
| DisputeStage::Dispute
|
||||||
|
| DisputeStage::PreArbitration
|
||||||
|
| DisputeStage::Arbitration
|
||||||
|
) && matches!(
|
||||||
dispute_status,
|
dispute_status,
|
||||||
DisputeStatus::DisputeExpired
|
DisputeStatus::DisputeOpened | DisputeStatus::DisputeChallenged
|
||||||
| DisputeStatus::DisputeCancelled
|
)
|
||||||
| DisputeStatus::DisputeWon
|
}
|
||||||
| DisputeStatus::DisputeLost,
|
|
||||||
|
pub fn should_proceed_with_accept_dispute(
|
||||||
|
dispute_stage: DisputeStage,
|
||||||
|
dispute_status: DisputeStatus,
|
||||||
|
) -> bool {
|
||||||
|
matches!(
|
||||||
|
dispute_stage,
|
||||||
|
DisputeStage::PreDispute | DisputeStage::Dispute | DisputeStage::PreArbitration
|
||||||
|
) && matches!(
|
||||||
|
dispute_status,
|
||||||
|
DisputeStatus::DisputeChallenged | DisputeStatus::DisputeOpened
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user