mirror of
https://github.com/juspay/hyperswitch.git
synced 2026-03-13 09:02:06 +08:00
feat(installments): add InstallmentEntries struct for validated installment data
This commit is contained in:
@@ -1249,7 +1249,7 @@ pub struct NetworkTransactionIdAndDecryptedWalletTokenDetails {
|
||||
}
|
||||
|
||||
/// Billing frequency for a card installment plan
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema, PartialEq, Eq, Hash)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum BillingFrequency {
|
||||
/// Monthly billing
|
||||
@@ -1396,6 +1396,72 @@ pub struct InstallmentOptionData {
|
||||
pub interest_rate: InstallmentInterestRate,
|
||||
}
|
||||
|
||||
/// A validated list of installment entries with no duplicate counts per billing frequency.
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq)]
|
||||
#[serde(try_from = "Vec<InstallmentOptionData>")]
|
||||
pub struct InstallmentEntries(Vec<InstallmentOptionData>);
|
||||
|
||||
impl InstallmentEntries {
|
||||
fn validate_no_duplicate_counts_per_frequency(
|
||||
installments: &[InstallmentOptionData],
|
||||
) -> Result<(), errors::ValidationError> {
|
||||
installments
|
||||
.iter()
|
||||
.try_fold(
|
||||
HashMap::<&BillingFrequency, HashSet<NonZeroU8>>::new(),
|
||||
|mut seen, entry| {
|
||||
entry
|
||||
.number_of_installments
|
||||
.as_slice()
|
||||
.iter()
|
||||
.try_fold(&mut seen, |seen, &count| {
|
||||
seen.entry(&entry.billing_frequency)
|
||||
.or_default()
|
||||
.insert(count)
|
||||
.then_some(seen)
|
||||
.ok_or_else(|| {
|
||||
error_stack::report!(
|
||||
errors::ValidationError::InvalidValue {
|
||||
message: format!(
|
||||
"installment count {count} appears in multiple entries with the same billing frequency."
|
||||
),
|
||||
}
|
||||
)
|
||||
})
|
||||
})?;
|
||||
Ok(seen)
|
||||
},
|
||||
)
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Vec<InstallmentOptionData>> for InstallmentEntries {
|
||||
type Error = Report<errors::ValidationError>;
|
||||
|
||||
fn try_from(entries: Vec<InstallmentOptionData>) -> Result<Self, errors::ValidationError> {
|
||||
Self::validate_no_duplicate_counts_per_frequency(&entries)?;
|
||||
Ok(Self(entries))
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Deref for InstallmentEntries {
|
||||
type Target = Vec<InstallmentOptionData>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoIterator for InstallmentEntries {
|
||||
type Item = InstallmentOptionData;
|
||||
type IntoIter = std::vec::IntoIter<InstallmentOptionData>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.0.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
/// Installment options grouped by payment method
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema, PartialEq)]
|
||||
pub struct InstallmentOption {
|
||||
@@ -1403,7 +1469,8 @@ pub struct InstallmentOption {
|
||||
#[schema(value_type = PaymentMethod)]
|
||||
pub payment_method: common_enums::PaymentMethod,
|
||||
/// List of available installment configurations
|
||||
pub installments: Vec<InstallmentOptionData>,
|
||||
#[schema(value_type = Vec<InstallmentOptionData>)]
|
||||
pub installments: InstallmentEntries,
|
||||
}
|
||||
|
||||
/// A list of installment options stored as a single JSONB column value.
|
||||
|
||||
Reference in New Issue
Block a user