refactor(router): added a new type minor unit to amount (#4629)

Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
Co-authored-by: Hrithikesh <61539176+hrithikesh026@users.noreply.github.com>
This commit is contained in:
Sahkal Poddar
2024-05-21 15:40:05 +05:30
committed by GitHub
parent 2cd360e6a9
commit 443b7e6ea2
61 changed files with 679 additions and 436 deletions

View File

@ -1,10 +1,10 @@
use common_utils::events::ApiEventMetric;
use common_utils::{events::ApiEventMetric, types::MinorUnit};
/// QueryParams to be send to convert the amount -> from_currency -> to_currency
#[derive(Debug, serde::Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct CurrencyConversionParams {
pub amount: i64,
pub amount: MinorUnit,
pub to_currency: String,
pub from_currency: String,
}

View File

@ -5,7 +5,7 @@ use common_utils::{
consts::SURCHARGE_PERCENTAGE_PRECISION_LENGTH,
crypto::OptionalEncryptableName,
pii,
types::{Percentage, Surcharge},
types::{MinorUnit, Percentage, Surcharge},
};
use serde::de;
use utoipa::{schema, ToSchema};
@ -492,7 +492,7 @@ pub struct SurchargeDetailsResponse {
#[serde(rename_all = "snake_case", tag = "type", content = "value")]
pub enum SurchargeResponse {
/// Fixed Surcharge value
Fixed(i64),
Fixed(MinorUnit),
/// Surcharge percentage
Rate(SurchargePercentage),
}
@ -638,7 +638,7 @@ pub struct PaymentMethodListRequest {
/// Filter by amount
#[schema(example = 60)]
pub amount: Option<i64>,
pub amount: Option<MinorUnit>,
/// Indicates whether the payment method is eligible for recurring payments
#[schema(example = true)]

View File

@ -10,6 +10,7 @@ use common_utils::{
crypto,
ext_traits::{ConfigExt, Encode},
pii::{self, Email},
types::MinorUnit,
};
use masking::{PeekInterface, Secret};
use router_derive::Setter;
@ -223,8 +224,8 @@ pub struct PaymentsRequest {
pub currency: Option<api_enums::Currency>,
/// The Amount to be captured / debited from the users payment method. It shall be in lowest denomination of the currency. (i.e) in cents for USD denomination, in paisa for INR denomination etc., If not provided, the default amount_to_capture will be the payment amount.
#[schema(example = 6540)]
pub amount_to_capture: Option<i64>,
#[schema(value_type = Option<i64>, example = 6540)]
pub amount_to_capture: Option<MinorUnit>,
/// Unique identifier for the payment. This ensures idempotency for multiple payments
/// that have been done by a single merchant. This field is auto generated and is returned in the API response.
@ -476,21 +477,22 @@ pub struct PaymentsRequest {
}
impl PaymentsRequest {
pub fn get_total_capturable_amount(&self) -> Option<i64> {
pub fn get_total_capturable_amount(&self) -> Option<MinorUnit> {
let surcharge_amount = self
.surcharge_details
.map(|surcharge_details| surcharge_details.get_total_surcharge_amount())
.unwrap_or(0);
.unwrap_or_default();
self.amount
.map(|amount| i64::from(amount) + surcharge_amount)
.map(|amount| MinorUnit::from(amount) + surcharge_amount)
}
}
#[derive(
Default, Debug, Clone, serde::Serialize, serde::Deserialize, Copy, ToSchema, PartialEq,
)]
pub struct RequestSurchargeDetails {
pub surcharge_amount: i64,
pub tax_amount: Option<i64>,
#[schema(value_type = i64, example = 6540)]
pub surcharge_amount: MinorUnit,
pub tax_amount: Option<MinorUnit>,
}
/// Browser information to be used for 3DS 2.0
@ -533,10 +535,11 @@ pub struct BrowserInformation {
impl RequestSurchargeDetails {
pub fn is_surcharge_zero(&self) -> bool {
self.surcharge_amount == 0 && self.tax_amount.unwrap_or(0) == 0
self.surcharge_amount == MinorUnit::new(0)
&& self.tax_amount.unwrap_or_default() == MinorUnit::new(0)
}
pub fn get_total_surcharge_amount(&self) -> i64 {
self.surcharge_amount + self.tax_amount.unwrap_or(0)
pub fn get_total_surcharge_amount(&self) -> MinorUnit {
self.surcharge_amount + self.tax_amount.unwrap_or_default()
}
}
@ -567,7 +570,8 @@ pub struct PaymentAttemptResponse {
#[schema(value_type = AttemptStatus, example = "charged")]
pub status: enums::AttemptStatus,
/// The payment attempt amount. Amount for the payment in lowest denomination of the currency. (i.e) in cents for USD denomination, in paisa for INR denomination etc.,
pub amount: i64,
#[schema(value_type = i64, example = 6540)]
pub amount: MinorUnit,
/// The currency of the amount of the payment attempt
#[schema(value_type = Option<Currency>, example = "USD")]
pub currency: Option<enums::Currency>,
@ -621,7 +625,8 @@ pub struct CaptureResponse {
#[schema(value_type = CaptureStatus, example = "charged")]
pub status: enums::CaptureStatus,
/// The capture amount. Amount for the payment in lowest denomination of the currency. (i.e) in cents for USD denomination, in paisa for INR denomination etc.,
pub amount: i64,
#[schema(value_type = i64, example = 6540)]
pub amount: MinorUnit,
/// The currency of the amount of the capture
#[schema(value_type = Option<Currency>, example = "USD")]
pub currency: Option<enums::Currency>,
@ -704,21 +709,23 @@ pub enum Amount {
Zero,
}
impl From<Amount> for i64 {
impl From<Amount> for MinorUnit {
fn from(amount: Amount) -> Self {
match amount {
Amount::Value(val) => val.get(),
Amount::Zero => 0,
Amount::Value(val) => Self::new(val.get()),
Amount::Zero => Self::new(0),
}
}
}
impl From<i64> for Amount {
fn from(val: i64) -> Self {
NonZeroI64::new(val).map_or(Self::Zero, Amount::Value)
impl From<MinorUnit> for Amount {
fn from(minor_unit: MinorUnit) -> Self {
match minor_unit.get_amount_as_i64() {
0 => Self::Zero,
val => NonZeroI64::new(val).map_or(Self::Zero, Self::Value),
}
}
}
#[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone)]
#[serde(deny_unknown_fields)]
pub struct PaymentsRedirectRequest {
@ -806,15 +813,15 @@ pub struct MandateData {
#[derive(Clone, Eq, PartialEq, Copy, Debug, Default, serde::Serialize, serde::Deserialize)]
pub struct SingleUseMandate {
pub amount: i64,
pub amount: MinorUnit,
pub currency: api_enums::Currency,
}
#[derive(Clone, Eq, PartialEq, Debug, Default, ToSchema, serde::Serialize, serde::Deserialize)]
pub struct MandateAmountData {
/// The maximum amount to be debited for the mandate transaction
#[schema(example = 6540)]
pub amount: i64,
#[schema(value_type = i64, example = 6540)]
pub amount: MinorUnit,
/// The currency for the transaction
#[schema(value_type = Currency, example = "USD")]
pub currency: api_enums::Currency,
@ -2878,7 +2885,8 @@ pub struct PaymentsCaptureRequest {
/// The unique identifier for the merchant
pub merchant_id: Option<String>,
/// The Amount to be captured/ debited from the user's payment method.
pub amount_to_capture: Option<i64>,
#[schema(value_type = i64, example = 6540)]
pub amount_to_capture: Option<MinorUnit>,
/// Decider to refund the uncaptured amount
pub refund_uncaptured_amount: Option<bool>,
/// Provides information about a card payment that customers see on their statements.
@ -3131,21 +3139,21 @@ pub struct PaymentsResponse {
pub status: api_enums::IntentStatus,
/// The payment amount. Amount for the payment in lowest denomination of the currency. (i.e) in cents for USD denomination, in paisa for INR denomination etc.,
#[schema(example = 100)]
pub amount: i64,
#[schema(value_type = i64, example = 6540)]
pub amount: MinorUnit,
/// The payment net amount. net_amount = amount + surcharge_details.surcharge_amount + surcharge_details.tax_amount,
/// If no surcharge_details, net_amount = amount
#[schema(example = 110)]
pub net_amount: i64,
#[schema(value_type = i64, example = 6540)]
pub net_amount: MinorUnit,
/// The maximum amount that could be captured from the payment
#[schema(minimum = 100, example = 6540)]
pub amount_capturable: Option<i64>,
#[schema(value_type = i64, minimum = 100, example = 6540)]
pub amount_capturable: Option<MinorUnit>,
/// The amount which is already captured from the payment
#[schema(minimum = 100, example = 6540)]
pub amount_received: Option<i64>,
#[schema(value_type = i64, example = 6540)]
pub amount_received: Option<MinorUnit>,
/// The connector used for the payment
#[schema(example = "stripe")]
@ -3511,7 +3519,8 @@ pub struct IncrementalAuthorizationResponse {
/// The unique identifier of authorization
pub authorization_id: String,
/// Amount the authorization has been made for
pub amount: i64,
#[schema(value_type = i64, example = 6540)]
pub amount: MinorUnit,
#[schema(value_type= AuthorizationStatus)]
/// The status of the authorization
pub status: common_enums::AuthorizationStatus,
@ -3520,7 +3529,7 @@ pub struct IncrementalAuthorizationResponse {
/// Error message sent by the connector for authorization
pub error_message: Option<String>,
/// Previously authorized amount for the payment
pub previously_authorized_amount: i64,
pub previously_authorized_amount: MinorUnit,
}
#[derive(Clone, Debug, serde::Serialize)]
@ -3756,7 +3765,7 @@ pub struct PgRedirectResponse {
pub status: api_enums::IntentStatus,
pub gateway_id: String,
pub customer_id: Option<String>,
pub amount: Option<i64>,
pub amount: Option<MinorUnit>,
}
#[derive(Debug, serde::Serialize, PartialEq, Eq, serde::Deserialize)]
@ -4374,7 +4383,7 @@ pub struct PaymentsIncrementalAuthorizationRequest {
pub payment_id: String,
/// The total amount including previously authorized amount and additional amount
#[schema(value_type = i64, example = 6540)]
pub amount: i64,
pub amount: MinorUnit,
/// Reason for incremental authorization
pub reason: Option<String>,
}
@ -4577,6 +4586,7 @@ pub mod amount {
use super::Amount;
struct AmountVisitor;
struct OptionalAmountVisitor;
use crate::payments::MinorUnit;
// This is defined to provide guarded deserialization of amount
// which itself handles zero and non-zero values internally
@ -4609,7 +4619,7 @@ pub mod amount {
"invalid value `{v}`, expected a positive integer"
)));
}
Ok(Amount::from(v))
Ok(Amount::from(MinorUnit::new(v)))
}
}
@ -4681,7 +4691,8 @@ pub struct RetrievePaymentLinkResponse {
pub payment_link_id: String,
pub merchant_id: String,
pub link_to_pay: String,
pub amount: i64,
#[schema(value_type = i64, example = 6540)]
pub amount: MinorUnit,
#[serde(with = "common_utils::custom_serde::iso8601")]
pub created_at: PrimitiveDateTime,
#[serde(with = "common_utils::custom_serde::iso8601::option")]

View File

@ -1,4 +1,8 @@
use common_utils::{consts::SURCHARGE_PERCENTAGE_PRECISION_LENGTH, events, types::Percentage};
use common_utils::{
consts::SURCHARGE_PERCENTAGE_PRECISION_LENGTH,
events,
types::{MinorUnit, Percentage},
};
use euclid::frontend::{
ast::Program,
dir::{DirKeyKind, EuclidDirFilter},
@ -15,7 +19,7 @@ pub struct SurchargeDetailsOutput {
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case", tag = "type", content = "value")]
pub enum SurchargeOutput {
Fixed { amount: i64 },
Fixed { amount: MinorUnit },
Rate(Percentage<SURCHARGE_PERCENTAGE_PRECISION_LENGTH>),
}