Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(dispute): change dispute currency type to currency enum #6454

Merged
merged 3 commits into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions api-reference-v2/openapi_spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -7192,8 +7192,7 @@
"description": "The dispute amount"
},
"currency": {
"type": "string",
"description": "The three-letter ISO currency code"
"$ref": "#/components/schemas/Currency"
},
"dispute_stage": {
"$ref": "#/components/schemas/DisputeStage"
Expand Down
3 changes: 1 addition & 2 deletions api-reference/openapi_spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -10040,8 +10040,7 @@
"description": "The dispute amount"
},
"currency": {
"type": "string",
"description": "The three-letter ISO currency code"
"$ref": "#/components/schemas/Currency"
},
"dispute_stage": {
"$ref": "#/components/schemas/DisputeStage"
Expand Down
11 changes: 6 additions & 5 deletions crates/api_models/src/disputes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ use serde::de::Error;
use time::PrimitiveDateTime;
use utoipa::ToSchema;

use super::enums::{DisputeStage, DisputeStatus};
use crate::{admin::MerchantConnectorInfo, enums, files};
use super::enums::{Currency, DisputeStage, DisputeStatus};
use crate::{admin::MerchantConnectorInfo, files};

#[derive(Clone, Debug, Serialize, ToSchema, Eq, PartialEq)]
pub struct DisputeResponse {
Expand All @@ -21,7 +21,8 @@ pub struct DisputeResponse {
/// The dispute amount
pub amount: String,
/// The three-letter ISO currency code
pub currency: String,
#[schema(value_type = Currency)]
pub currency: Currency,
/// Stage of the dispute
pub dispute_stage: DisputeStage,
/// Status of the dispute
Expand Down Expand Up @@ -137,7 +138,7 @@ pub struct DisputeListGetConstraints {
pub connector: Option<Vec<String>>,
/// The comma separated list of currencies of the disputes
#[serde(default, deserialize_with = "parse_comma_separated")]
pub currency: Option<Vec<common_enums::Currency>>,
pub currency: Option<Vec<Currency>>,
/// The merchant connector id to filter the disputes list
pub merchant_connector_id: Option<common_utils::id_type::MerchantConnectorAccountId>,
/// The time range for which objects are needed. TimeRange has two fields start_time and end_time from which objects can be filtered as per required scenarios (created_at, time less than, greater than etc).
Expand All @@ -150,7 +151,7 @@ pub struct DisputeListFilters {
/// The map of available connector filters, where the key is the connector name and the value is a list of MerchantConnectorInfo instances
pub connector: HashMap<String, Vec<MerchantConnectorInfo>>,
/// The list of available currency filters
pub currency: Vec<enums::Currency>,
pub currency: Vec<Currency>,
/// The list of available dispute status filters
pub dispute_status: Vec<DisputeStatus>,
/// The list of available dispute stage filters
Expand Down
2 changes: 2 additions & 0 deletions crates/diesel_models/src/dispute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ pub struct DisputeNew {
pub merchant_connector_id: Option<common_utils::id_type::MerchantConnectorAccountId>,
pub dispute_amount: i64,
pub organization_id: common_utils::id_type::OrganizationId,
pub dispute_currency: Option<storage_enums::Currency>,
}

#[derive(Clone, Debug, PartialEq, Serialize, Identifiable, Queryable, Selectable)]
Expand Down Expand Up @@ -61,6 +62,7 @@ pub struct Dispute {
pub merchant_connector_id: Option<common_utils::id_type::MerchantConnectorAccountId>,
pub dispute_amount: i64,
pub organization_id: common_utils::id_type::OrganizationId,
pub dispute_currency: Option<storage_enums::Currency>,
}

#[derive(Debug)]
Expand Down
1 change: 1 addition & 0 deletions crates/diesel_models/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,7 @@ diesel::table! {
dispute_amount -> Int8,
#[max_length = 32]
organization_id -> Varchar,
dispute_currency -> Nullable<Currency>,
}
}

Expand Down
1 change: 1 addition & 0 deletions crates/diesel_models/src/schema_v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,7 @@ diesel::table! {
dispute_amount -> Int8,
#[max_length = 32]
organization_id -> Varchar,
dispute_currency -> Nullable<Currency>,
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -829,7 +829,7 @@ pub struct AirwallexObjectData {
pub struct AirwallexDisputeObject {
pub payment_intent_id: String,
pub dispute_amount: i64,
pub dispute_currency: String,
pub dispute_currency: enums::Currency,
pub stage: AirwallexDisputeStage,
pub dispute_id: String,
pub dispute_reason_type: Option<String>,
Expand Down
2 changes: 1 addition & 1 deletion crates/hyperswitch_connectors/src/connectors/novalnet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -906,7 +906,7 @@ impl webhooks::IncomingWebhook for Novalnet {
novalnet::get_novalnet_dispute_status(notif.event.event_type).to_string();
Ok(disputes::DisputePayload {
amount: novalnet::option_to_result(amount)?.to_string(),
currency: novalnet::option_to_result(currency)?.to_string(),
currency: novalnet::option_to_result(currency)?,
dispute_stage: api_models::enums::DisputeStage::Dispute,
connector_dispute_id: notif.event.tid.to_string(),
connector_reason: reason,
Expand Down
2 changes: 1 addition & 1 deletion crates/hyperswitch_interfaces/src/disputes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pub struct DisputePayload {
/// amount
pub amount: String,
/// currency
pub currency: String,
pub currency: common_enums::enums::Currency,
/// dispute_stage
pub dispute_stage: common_enums::enums::DisputeStage,
/// connector_status
Expand Down
4 changes: 2 additions & 2 deletions crates/router/src/compatibility/stripe/webhooks.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#[cfg(feature = "payouts")]
use api_models::payouts as payout_models;
use api_models::{
enums::{DisputeStatus, MandateStatus},
enums::{Currency, DisputeStatus, MandateStatus},
webhooks::{self as api},
};
#[cfg(feature = "payouts")]
Expand Down Expand Up @@ -93,7 +93,7 @@ pub enum StripeWebhookObject {
pub struct StripeDisputeResponse {
pub id: String,
pub amount: String,
pub currency: String,
pub currency: Currency,
pub payment_intent: common_utils::id_type::PaymentId,
pub reason: Option<String>,
pub status: StripeDisputeStatus,
Expand Down
2 changes: 1 addition & 1 deletion crates/router/src/connector/adyen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1895,7 +1895,7 @@ impl api::IncomingWebhook for Adyen {
.change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;
Ok(api::disputes::DisputePayload {
amount: notif.amount.value.to_string(),
currency: notif.amount.currency.to_string(),
currency: notif.amount.currency,
dispute_stage: api_models::enums::DisputeStage::from(notif.event_code.clone()),
connector_dispute_id: notif.psp_reference,
connector_reason: notif.reason,
Expand Down
2 changes: 1 addition & 1 deletion crates/router/src/connector/bluesnap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1149,7 +1149,7 @@ impl api::IncomingWebhook for Bluesnap {
dispute_details.invoice_charge_amount.abs().to_string(),
dispute_details.currency,
)?,
currency: dispute_details.currency.to_string(),
currency: dispute_details.currency,
dispute_stage: api_models::enums::DisputeStage::Dispute,
connector_dispute_id: dispute_details.reversal_ref_num,
connector_reason: dispute_details.reversal_reason,
Expand Down
35 changes: 15 additions & 20 deletions crates/router/src/connector/braintree.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
pub mod transformers;
use std::str::FromStr;

use api_models::webhooks::IncomingWebhookEvent;
use base64::Engine;
Expand Down Expand Up @@ -998,25 +997,21 @@ impl api::IncomingWebhook for Braintree {
let response = decode_webhook_payload(notif.bt_payload.replace('\n', "").as_bytes())?;

match response.dispute {
Some(dispute_data) => {
let currency = enums::Currency::from_str(dispute_data.currency_iso_code.as_str())
.change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;
Ok(api::disputes::DisputePayload {
amount: connector_utils::to_currency_lower_unit(
dispute_data.amount_disputed.to_string(),
currency,
)?,
currency: dispute_data.currency_iso_code,
dispute_stage: transformers::get_dispute_stage(dispute_data.kind.as_str())?,
connector_dispute_id: dispute_data.id,
connector_reason: dispute_data.reason,
connector_reason_code: dispute_data.reason_code,
challenge_required_by: dispute_data.reply_by_date,
connector_status: dispute_data.status,
created_at: dispute_data.created_at,
updated_at: dispute_data.updated_at,
})
}
Some(dispute_data) => Ok(api::disputes::DisputePayload {
amount: connector_utils::to_currency_lower_unit(
dispute_data.amount_disputed.to_string(),
dispute_data.currency_iso_code,
)?,
currency: dispute_data.currency_iso_code,
dispute_stage: transformers::get_dispute_stage(dispute_data.kind.as_str())?,
connector_dispute_id: dispute_data.id,
connector_reason: dispute_data.reason,
connector_reason_code: dispute_data.reason_code,
challenge_required_by: dispute_data.reply_by_date,
connector_status: dispute_data.status,
created_at: dispute_data.created_at,
updated_at: dispute_data.updated_at,
}),
None => Err(errors::ConnectorError::WebhookResourceObjectNotFound)?,
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/router/src/connector/braintree/transformers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1766,7 +1766,7 @@ pub struct BraintreeDisputeData {
pub amount_won: Option<String>,
pub case_number: Option<String>,
pub chargeback_protection_level: Option<String>,
pub currency_iso_code: String,
pub currency_iso_code: enums::Currency,
#[serde(default, with = "common_utils::custom_serde::iso8601::option")]
pub created_at: Option<PrimitiveDateTime>,
pub evidence: Option<DisputeEvidence>,
Expand Down
2 changes: 1 addition & 1 deletion crates/router/src/connector/checkout/transformers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1252,7 +1252,7 @@ pub struct CheckoutDisputeWebhookData {
pub payment_id: Option<String>,
pub action_id: Option<String>,
pub amount: i32,
pub currency: String,
pub currency: enums::Currency,
#[serde(default, with = "common_utils::custom_serde::iso8601::option")]
pub evidence_required_by: Option<PrimitiveDateTime>,
pub reason_code: Option<String>,
Expand Down
2 changes: 1 addition & 1 deletion crates/router/src/connector/payme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1280,7 +1280,7 @@ impl api::IncomingWebhook for Payme {

Ok(api::disputes::DisputePayload {
amount: webhook_object.price.to_string(),
currency: webhook_object.currency.to_string(),
currency: webhook_object.currency,
dispute_stage: api_models::enums::DisputeStage::Dispute,
connector_dispute_id: webhook_object.payme_transaction_id,
connector_reason: None,
Expand Down
2 changes: 1 addition & 1 deletion crates/router/src/connector/paypal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2001,7 +2001,7 @@ impl api::IncomingWebhook for Paypal {
payload.dispute_amount.value.get_amount_as_string(),
payload.dispute_amount.currency_code,
)?,
currency: payload.dispute_amount.currency_code.to_string(),
currency: payload.dispute_amount.currency_code,
dispute_stage: api_models::enums::DisputeStage::from(
payload.dispute_life_cycle_stage.clone(),
),
Expand Down
2 changes: 1 addition & 1 deletion crates/router/src/connector/rapyd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -974,7 +974,7 @@ impl api::IncomingWebhook for Rapyd {
}?;
Ok(api::disputes::DisputePayload {
amount: webhook_dispute_data.amount.to_string(),
currency: webhook_dispute_data.currency.to_string(),
currency: webhook_dispute_data.currency,
dispute_stage: api_models::enums::DisputeStage::Dispute,
connector_dispute_id: webhook_dispute_data.token,
connector_reason: Some(webhook_dispute_data.dispute_reason_description),
Expand Down
3 changes: 2 additions & 1 deletion crates/router/src/connector/stripe/transformers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3640,7 +3640,8 @@ pub struct WebhookEventObjectData {
pub id: String,
pub object: WebhookEventObjectType,
pub amount: Option<i32>,
pub currency: String,
#[serde(default, deserialize_with = "connector_util::convert_uppercase")]
pub currency: enums::Currency,
pub payment_intent: Option<String>,
pub client_secret: Option<Secret<String>>,
pub reason: Option<String>,
Expand Down
2 changes: 1 addition & 1 deletion crates/router/src/connector/trustpay/transformers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1790,7 +1790,7 @@ pub struct WebhookReferences {
#[serde(rename_all = "PascalCase")]
pub struct WebhookAmount {
pub amount: f64,
pub currency: String,
pub currency: enums::Currency,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
Expand Down
13 changes: 12 additions & 1 deletion crates/router/src/connector/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use hyperswitch_domain_models::{
SyncIntegrityObject,
},
};
use masking::{ExposeInterface, Secret};
use masking::{Deserialize, ExposeInterface, Secret};
use once_cell::sync::Lazy;
use regex::Regex;
use serde::Serializer;
Expand Down Expand Up @@ -3143,3 +3143,14 @@ impl NetworkTokenData for domain::NetworkTokenData {
Secret::new(year)
}
}

pub fn convert_uppercase<'de, D, T>(v: D) -> Result<T, D::Error>
where
D: serde::Deserializer<'de>,
T: FromStr,
<T as FromStr>::Err: std::fmt::Debug + std::fmt::Display + std::error::Error,
{
use serde::de::Error;
let output = <&str>::deserialize(v)?;
output.to_uppercase().parse::<T>().map_err(D::Error::custom)
}
3 changes: 2 additions & 1 deletion crates/router/src/core/webhooks/incoming.rs
Original file line number Diff line number Diff line change
Expand Up @@ -942,7 +942,7 @@ async fn get_or_update_dispute_object(
let new_dispute = diesel_models::dispute::DisputeNew {
dispute_id,
amount: dispute_details.amount.clone(),
currency: dispute_details.currency,
currency: dispute_details.currency.to_string(),
dispute_stage: dispute_details.dispute_stage,
dispute_status: common_enums::DisputeStatus::foreign_try_from(event_type)
.change_context(errors::ApiErrorResponse::WebhookProcessingFailure)
Expand All @@ -963,6 +963,7 @@ async fn get_or_update_dispute_object(
merchant_connector_id: payment_attempt.merchant_connector_id.clone(),
dispute_amount: dispute_details.amount.parse::<i64>().unwrap_or(0),
organization_id: organization_id.clone(),
dispute_currency: Some(dispute_details.currency),
};
state
.store
Expand Down
11 changes: 8 additions & 3 deletions crates/router/src/db/dispute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ impl DisputeInterface for MockDb {
merchant_connector_id: dispute.merchant_connector_id,
dispute_amount: dispute.dispute_amount,
organization_id: dispute.organization_id,
dispute_currency: dispute.dispute_currency,
};

locked_disputes.push(new_dispute.clone());
Expand Down Expand Up @@ -308,9 +309,12 @@ impl DisputeInterface for MockDb {
.currency
.as_ref()
.map_or(true, |currencies| {
currencies
.iter()
.any(|currency| dispute.currency.as_str() == currency.to_string())
currencies.iter().any(|currency| {
dispute
.dispute_currency
.map(|dispute_currency| &dispute_currency == currency)
.unwrap_or(dispute.currency.as_str() == currency.to_string())
})
})
&& dispute_constraints
.time_range
Expand Down Expand Up @@ -502,6 +506,7 @@ mod tests {
merchant_connector_id: None,
dispute_amount: 1040,
organization_id: common_utils::id_type::OrganizationId::default(),
dispute_currency: Some(common_enums::Currency::default()),
}
}

Expand Down
12 changes: 9 additions & 3 deletions crates/router/src/services/kafka/dispute.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use common_utils::id_type;
use common_utils::{ext_traits::StringExt, id_type};
use diesel_models::enums as storage_enums;
use masking::Secret;
use time::OffsetDateTime;
Expand All @@ -9,7 +9,7 @@ use crate::types::storage::dispute::Dispute;
pub struct KafkaDispute<'a> {
pub dispute_id: &'a String,
pub dispute_amount: i64,
pub currency: &'a String,
pub currency: storage_enums::Currency,
pub dispute_stage: &'a storage_enums::DisputeStage,
pub dispute_status: &'a storage_enums::DisputeStatus,
pub payment_id: &'a id_type::PaymentId,
Expand Down Expand Up @@ -41,7 +41,13 @@ impl<'a> KafkaDispute<'a> {
Self {
dispute_id: &dispute.dispute_id,
dispute_amount: dispute.amount.parse::<i64>().unwrap_or_default(),
currency: &dispute.currency,
currency: dispute.dispute_currency.unwrap_or(
dispute
.currency
.to_uppercase()
.parse_enum("Currency")
.unwrap_or_default(),
),
dispute_stage: &dispute.dispute_stage,
dispute_status: &dispute.dispute_status,
payment_id: &dispute.payment_id,
Expand Down
11 changes: 9 additions & 2 deletions crates/router/src/services/kafka/dispute_event.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use common_utils::ext_traits::StringExt;
use diesel_models::enums as storage_enums;
use masking::Secret;
use time::OffsetDateTime;
Expand All @@ -9,7 +10,7 @@ use crate::types::storage::dispute::Dispute;
pub struct KafkaDisputeEvent<'a> {
pub dispute_id: &'a String,
pub dispute_amount: i64,
pub currency: &'a String,
pub currency: storage_enums::Currency,
pub dispute_stage: &'a storage_enums::DisputeStage,
pub dispute_status: &'a storage_enums::DisputeStatus,
pub payment_id: &'a common_utils::id_type::PaymentId,
Expand Down Expand Up @@ -41,7 +42,13 @@ impl<'a> KafkaDisputeEvent<'a> {
Self {
dispute_id: &dispute.dispute_id,
dispute_amount: dispute.amount.parse::<i64>().unwrap_or_default(),
currency: &dispute.currency,
currency: dispute.dispute_currency.unwrap_or(
dispute
.currency
.to_uppercase()
.parse_enum("Currency")
.unwrap_or_default(),
),
dispute_stage: &dispute.dispute_stage,
dispute_status: &dispute.dispute_status,
payment_id: &dispute.payment_id,
Expand Down
Loading
Loading