Repository: juspay/hyperswitch
File: crates/api_models/src/admin.rs (Rust)

Code before:
        if other.webhook_password.is_some() {
            self.webhook_password = other.webhook_password;
        }
        if other.webhook_url.is_some() {
            self.webhook_url = other.webhook_url;
        }
        if other.payment_created_enabled.is_some() {
            self.payment_created_enabled = other.payment_created_enabled;
        }
        if other.payment_succeeded_enabled.is_some() {
            self.payment_succeeded_enabled = other.payment_succeeded_enabled;
        }
        if other.payment_failed_enabled.is_some() {
            self.payment_failed_enabled = other.payment_failed_enabled;
        }
        if other.payment_statuses_enabled.is_some() {
            self.payment_statuses_enabled = other.payment_statuses_enabled;
        }
        if other.refund_statuses_enabled.is_some() {
            self.refund_statuses_enabled = other.refund_statuses_enabled;
        }
        #[cfg(feature = "payouts")]
        if other.payout_statuses_enabled.is_some() {
            self.payout_statuses_enabled = other.payout_statuses_enabled;
        }
    }

    fn validate_statuses<T>(statuses: &[T], status_type_name: &str) -> Result<(), String>
    where
        T: strum::IntoEnumIterator + Copy + PartialEq + std::fmt::Debug,
        T: Into<Option<api_enums::EventType>>,
    {
        let valid_statuses: Vec<T> = T::iter().filter(|s| (*s).into().is_some()).collect();

        for status in statuses {
            if !valid_statuses.contains(status) {
                return Err(format!(
                    "Invalid {status_type_name} webhook status provided: {status:?}"
                ));
            }
        }
        Ok(())
    }

    pub fn validate(&self) -> Result<(), String> {
        if let Some(payment_statuses) = &self.payment_statuses_enabled {
            Self::validate_statuses(payment_statuses, "payment")?;
        }

        if let Some(refund_statuses) = &self.refund_statuses_enabled {
            Self::validate_statuses(refund_statuses, "refund")?;

Review comment (suggestion):
This logic will not be applicable for any new field added to `WebhookDetails`.

do de-structuring of `WebhookDetails` and then use the individual fields.

Code after:
                .payment_created_enabled
                .or(self.payment_created_enabled),
            payment_succeeded_enabled: other
                .payment_succeeded_enabled
                .or(self.payment_succeeded_enabled),
            payment_failed_enabled: other.payment_failed_enabled.or(self.payment_failed_enabled),
            payment_statuses_enabled: other
                .payment_statuses_enabled
                .or(self.payment_statuses_enabled),
            refund_statuses_enabled: other
                .refund_statuses_enabled
                .or(self.refund_statuses_enabled),
            #[cfg(feature = "payouts")]
            payout_statuses_enabled: other
                .payout_statuses_enabled
                .or(self.payout_statuses_enabled),
        }
    }

    fn validate_statuses<T>(statuses: &[T], status_type_name: &str) -> Result<(), String>
    where
        T: strum::IntoEnumIterator + Copy + PartialEq + std::fmt::Debug,
        T: Into<Option<api_enums::EventType>>,
    {
        let valid_statuses: Vec<T> = T::iter().filter(|s| (*s).into().is_some()).collect();

        for status in statuses {
            if !valid_statuses.contains(status) {
                return Err(format!(
                    "Invalid {status_type_name} webhook status provided: {status:?}"
                ));
            }
        }
        Ok(())
    }

    pub fn validate(&self) -> Result<(), String> {
        if let Some(payment_statuses) = &self.payment_statuses_enabled {
            Self::validate_statuses(payment_statuses, "payment")?;
        }

        if let Some(refund_statuses) = &self.refund_statuses_enabled {
            Self::validate_statuses(refund_statuses, "refund")?;
        }

        #[cfg(feature = "payouts")]
        {
            if let Some(payout_statuses) = &self.payout_statuses_enabled {
                Self::validate_statuses(payout_statuses, "payout")?;
            }
        }