Repository: juspay/hyperswitch
File: crates/router/src/core/payments/transformers.rs (Rust)

Code before:
                .connector_metadata
                .map(|secret| secret.expose()),
        })
    }
}

#[cfg(feature = "v2")]
impl<F: Clone> TryFrom<PaymentAdditionalData<'_, F>> for types::PaymentsCaptureData {
    type Error = error_stack::Report<errors::ApiErrorResponse>;

    fn try_from(additional_data: PaymentAdditionalData<'_, F>) -> Result<Self, Self::Error> {
        use masking::ExposeOptionInterface;

        let payment_data = additional_data.payment_data;
        let connector = api::ConnectorData::get_connector_by_name(
            &additional_data.state.conf.connectors,
            &additional_data.connector_name,
            api::GetToken::Connector,
            payment_data.payment_attempt.merchant_connector_id.clone(),
        )?;
        let amount_to_capture = payment_data
            .payment_attempt
            .amount_details
            .get_amount_to_capture()
            .unwrap_or(payment_data.payment_attempt.get_total_amount());
        if amount_to_capture <= MinorUnit::new(0) {
            return Err(errors::ApiErrorResponse::InvalidDataFormat {
                field_name: "amount".to_string(),
                expected_format: "positive integer".to_string(),
            }.into());
        }

        let amount = payment_data.payment_attempt.get_total_amount();
        Ok(Self {
            capture_method: Some(payment_data.payment_intent.capture_method),
            amount_to_capture: amount_to_capture.get_amount_as_i64(), // This should be removed once we start moving to connector module
            minor_amount_to_capture: amount_to_capture,
            currency: payment_data.currency,
            connector_transaction_id: connector
                .connector
                .connector_transaction_id(&payment_data.payment_attempt)?
                .ok_or(errors::ApiErrorResponse::ResourceIdNotFound)?,
            payment_amount: amount.get_amount_as_i64(), // This should be removed once we start moving to connector module
            minor_payment_amount: amount,
            connector_meta: payment_data
                .payment_attempt
                .connector_metadata
                .expose_option(),
            // TODO: add multiple capture data
            multiple_capture_data: None,
            // TODO: why do we need browser info during capture?

Review comment (refactor):
This validation should happen in operation get_trackers / validate_request and there's already a helper function for this - `validate_request_amount_and_amount_to_capture`

Code after:
                .connector_metadata
                .map(|secret| secret.expose()),
        })
    }
}

#[cfg(feature = "v2")]
impl<F: Clone> TryFrom<PaymentAdditionalData<'_, F>> for types::PaymentsCaptureData {
    type Error = error_stack::Report<errors::ApiErrorResponse>;

    fn try_from(additional_data: PaymentAdditionalData<'_, F>) -> Result<Self, Self::Error> {
        use masking::ExposeOptionInterface;

        let payment_data = additional_data.payment_data;
        let connector = api::ConnectorData::get_connector_by_name(
            &additional_data.state.conf.connectors,
            &additional_data.connector_name,
            api::GetToken::Connector,
            payment_data.payment_attempt.merchant_connector_id.clone(),
        )?;
        let amount_to_capture = payment_data
            .payment_attempt
            .amount_details
            .get_amount_to_capture()
            .unwrap_or(payment_data.payment_attempt.get_total_amount());

        let amount = payment_data.payment_attempt.get_total_amount();
        Ok(Self {
            capture_method: Some(payment_data.payment_intent.capture_method),
            amount_to_capture: amount_to_capture.get_amount_as_i64(), // This should be removed once we start moving to connector module
            minor_amount_to_capture: amount_to_capture,
            currency: payment_data.currency,
            connector_transaction_id: connector
                .connector
                .connector_transaction_id(&payment_data.payment_attempt)?
                .ok_or(errors::ApiErrorResponse::ResourceIdNotFound)?,
            payment_amount: amount.get_amount_as_i64(), // This should be removed once we start moving to connector module
            minor_payment_amount: amount,
            connector_meta: payment_data
                .payment_attempt
                .connector_metadata
                .expose_option(),
            // TODO: add multiple capture data
            multiple_capture_data: None,
            // TODO: why do we need browser info during capture?
            browser_info: None,
            metadata: payment_data.payment_intent.metadata.expose_option(),
            integrity_object: None,
            split_payments: None,
            webhook_url: None,
        })