use std::collections::HashMap; pub use common_utils::types::MinorUnit; use common_utils::{pii, types::TimeRange}; use serde::{Deserialize, Serialize}; use time::PrimitiveDateTime; use utoipa::ToSchema; use super::payments::AmountFilter; use crate::{ admin::{self, MerchantConnectorInfo}, enums, }; #[derive(Default, Debug, ToSchema, Clone, Deserialize, Serialize)] #[serde(deny_unknown_fields)] pub struct RefundRequest { /// The payment id against which refund is to be initiated #[schema( max_length = 30, min_length = 30, example = "pay_mbabizu24mvu3mela5njyhpit4", value_type = String, )] pub payment_id: common_utils::id_type::PaymentId, /// Unique Identifier for the Refund. This is to ensure idempotency for multiple partial refunds initiated against the same payment. If this is not passed by the merchant, this field shall be auto generated and provided in the API response. It is recommended to generate uuid(v4) as the refund_id. #[schema( max_length = 30, min_length = 30, example = "ref_mbabizu24mvu3mela5njyhpit4" )] pub refund_id: Option, /// The identifier for the Merchant Account #[schema(max_length = 255, example = "y3oqhf46pyzuxjbcn2giaqnb44", value_type = Option)] pub merchant_id: Option, /// Total amount for which the refund is to be initiated. Amount for the payment in lowest denomination of the currency. (i.e) in cents for USD denomination, in paisa for INR denomination etc., If not provided, this will default to the full payment amount #[schema(value_type = Option , minimum = 100, example = 6540)] pub amount: Option, /// Reason for the refund. Often useful for displaying to users and your customer support executive. In case the payment went through Stripe, this field needs to be passed with one of these enums: `duplicate`, `fraudulent`, or `requested_by_customer` #[schema(max_length = 255, example = "Customer returned the product")] pub reason: Option, /// To indicate whether to refund needs to be instant or scheduled. Default value is instant #[schema(default = "Instant", example = "Instant")] pub refund_type: Option, /// You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. Metadata is useful for storing additional, structured information on an object. #[schema(value_type = Option, example = r#"{ "city": "NY", "unit": "245" }"#)] pub metadata: Option, /// Merchant connector details used to make payments. #[schema(value_type = Option)] pub merchant_connector_details: Option, /// Charge specific fields for controlling the revert of funds from either platform or connected account #[schema(value_type = Option)] pub split_refunds: Option, } #[cfg(feature = "v2")] #[derive(Debug, ToSchema, Clone, Deserialize, Serialize)] #[serde(deny_unknown_fields)] pub struct RefundsCreateRequest { /// The payment id against which refund is initiated #[schema( max_length = 30, min_length = 30, example = "pay_mbabizu24mvu3mela5njyhpit4", value_type = String, )] pub payment_id: common_utils::id_type::GlobalPaymentId, /// Unique Identifier for the Refund. This is to ensure idempotency for multiple partial refunds initiated against the same payment. #[schema( max_length = 30, min_length = 30, example = "ref_mbabizu24mvu3mela5njyhpit4", value_type = Option, )] pub merchant_reference_id: Option, /// Total amount for which the refund is to be initiated. Amount for the payment in lowest denomination of the currency. (i.e) in cents for USD denomination, in paisa for INR denomination etc., If not provided, this will default to the amount_captured of the payment #[schema(value_type = Option , minimum = 100, example = 6540)] pub amount: Option, /// Reason for the refund. Often useful for displaying to users and your customer support executive. #[schema(max_length = 255, example = "Customer returned the product")] pub reason: Option, /// To indicate whether to refund needs to be instant or scheduled. Default value is instant #[schema(default = "Instant", example = "Instant")] pub refund_type: Option, /// Metadata is useful for storing additional, unstructured information on an object. #[schema(value_type = Option, example = r#"{ "city": "NY", "unit": "245" }"#)] pub metadata: Option, } #[derive(Default, Debug, Clone, Deserialize)] pub struct RefundsRetrieveBody { pub force_sync: Option, } #[derive(Default, Debug, ToSchema, Clone, Deserialize, Serialize)] pub struct RefundsRetrieveRequest { /// Unique Identifier for the Refund. This is to ensure idempotency for multiple partial refund initiated against the same payment. If the identifiers is not defined by the merchant, this filed shall be auto generated and provide in the API response. It is recommended to generate uuid(v4) as the refund_id. #[schema( max_length = 30, min_length = 30, example = "ref_mbabizu24mvu3mela5njyhpit4" )] pub refund_id: String, /// `force_sync` with the connector to get refund details /// (defaults to false) pub force_sync: Option, /// Merchant connector details used to make payments. pub merchant_connector_details: Option, } #[derive(Default, Debug, ToSchema, Clone, Deserialize, Serialize)] #[serde(deny_unknown_fields)] pub struct RefundUpdateRequest { #[serde(skip)] pub refund_id: String, /// An arbitrary string attached to the object. Often useful for displaying to users and your customer support executive #[schema(max_length = 255, example = "Customer returned the product")] pub reason: Option, /// You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. Metadata is useful for storing additional, structured information on an object. #[schema(value_type = Option, example = r#"{ "city": "NY", "unit": "245" }"#)] pub metadata: Option, } #[derive(Default, Debug, ToSchema, Clone, Deserialize, Serialize)] #[serde(deny_unknown_fields)] pub struct RefundManualUpdateRequest { #[serde(skip)] pub refund_id: String, /// Merchant ID #[schema(value_type = String)] pub merchant_id: common_utils::id_type::MerchantId, /// The status for refund pub status: Option, /// The code for the error pub error_code: Option, /// The error message pub error_message: Option, } /// To indicate whether to refund needs to be instant or scheduled #[derive( Default, Debug, Clone, Copy, ToSchema, Deserialize, Serialize, Eq, PartialEq, strum::Display, )] #[serde(rename_all = "snake_case")] pub enum RefundType { #[default] Scheduled, Instant, } #[cfg(feature = "v1")] #[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize, ToSchema)] pub struct RefundResponse { /// Unique Identifier for the refund pub refund_id: String, /// The payment id against which refund is initiated #[schema(value_type = String)] pub payment_id: common_utils::id_type::PaymentId, /// The refund amount, which should be less than or equal to the total 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(value_type = i64 , minimum = 100, example = 6540)] pub amount: MinorUnit, /// The three-letter ISO currency code pub currency: String, /// The status for refund pub status: RefundStatus, /// An arbitrary string attached to the object. Often useful for displaying to users and your customer support executive pub reason: Option, /// You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. Metadata is useful for storing additional, structured information on an object #[schema(value_type = Option)] pub metadata: Option, /// The error message pub error_message: Option, /// The code for the error pub error_code: Option, /// Error code unified across the connectors is received here if there was an error while calling connector pub unified_code: Option, /// Error message unified across the connectors is received here if there was an error while calling connector pub unified_message: Option, /// The timestamp at which refund is created #[serde(with = "common_utils::custom_serde::iso8601::option")] pub created_at: Option, /// The timestamp at which refund is updated #[serde(with = "common_utils::custom_serde::iso8601::option")] pub updated_at: Option, /// The connector used for the refund and the corresponding payment #[schema(example = "stripe")] pub connector: String, /// The id of business profile for this refund #[schema(value_type = Option)] pub profile_id: Option, /// The merchant_connector_id of the processor through which this payment went through #[schema(value_type = Option)] pub merchant_connector_id: Option, /// Charge specific fields for controlling the revert of funds from either platform or connected account #[schema(value_type = Option,)] pub split_refunds: Option, } #[cfg(feature = "v1")] impl RefundResponse { pub fn get_refund_id_as_string(&self) -> String { self.refund_id.clone() } } #[cfg(feature = "v2")] #[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize, ToSchema)] pub struct RefundResponse { /// Global Refund Id for the refund #[schema(value_type = String)] pub id: common_utils::id_type::GlobalRefundId, /// The payment id against which refund is initiated #[schema(value_type = String)] pub payment_id: common_utils::id_type::GlobalPaymentId, /// Unique Identifier for the Refund. This is to ensure idempotency for multiple partial refunds initiated against the same payment. #[schema( max_length = 30, min_length = 30, example = "ref_mbabizu24mvu3mela5njyhpit4", value_type = Option, )] pub merchant_reference_id: Option, /// The refund amount #[schema(value_type = i64 , minimum = 100, example = 6540)] pub amount: MinorUnit, /// The three-letter ISO currency code #[schema(value_type = Currency)] pub currency: common_enums::Currency, /// The status for refund pub status: RefundStatus, /// An arbitrary string attached to the object pub reason: Option, /// Metadata is useful for storing additional, unstructured information on an object #[schema(value_type = Option)] pub metadata: Option, /// The error details for the refund pub error_details: Option, /// The timestamp at which refund is created #[serde(with = "common_utils::custom_serde::iso8601")] pub created_at: PrimitiveDateTime, /// The timestamp at which refund is updated #[serde(with = "common_utils::custom_serde::iso8601")] pub updated_at: PrimitiveDateTime, /// The connector used for the refund and the corresponding payment #[schema(example = "stripe", value_type = Connector)] pub connector: enums::Connector, /// The id of business profile for this refund #[schema(value_type = String)] pub profile_id: common_utils::id_type::ProfileId, /// The merchant_connector_id of the processor through which this payment went through #[schema(value_type = String)] pub merchant_connector_id: common_utils::id_type::MerchantConnectorAccountId, /// The reference id of the connector for the refund pub connector_refund_reference_id: Option, } #[cfg(feature = "v2")] impl RefundResponse { pub fn get_refund_id_as_string(&self) -> String { self.id.get_string_repr().to_owned() } } #[cfg(feature = "v2")] #[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize, ToSchema)] pub struct RefundErrorDetails { pub code: String, pub message: String, } #[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize, ToSchema)] pub struct RefundListRequest { /// The identifier for the payment #[schema(value_type = Option)] pub payment_id: Option, /// The identifier for the refund pub refund_id: Option, /// The identifier for business profile #[schema(value_type = Option)] pub profile_id: Option, /// Limit on the number of objects to return pub limit: Option, /// The starting point within a list of objects pub offset: Option, /// 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) #[serde(flatten)] pub time_range: Option, /// The amount to filter reufnds list. Amount takes two option fields start_amount and end_amount from which objects can be filtered as per required scenarios (less_than, greater_than, equal_to and range) pub amount_filter: Option, /// The list of connectors to filter refunds list pub connector: Option>, /// The list of merchant connector ids to filter the refunds list for selected label #[schema(value_type = Option>)] pub merchant_connector_id: Option>, /// The list of currencies to filter refunds list #[schema(value_type = Option>)] pub currency: Option>, /// The list of refund statuses to filter refunds list #[schema(value_type = Option>)] pub refund_status: Option>, } #[derive(Debug, Clone, Eq, PartialEq, Serialize, ToSchema)] pub struct RefundListResponse { /// The number of refunds included in the list pub count: usize, /// The total number of refunds in the list pub total_count: i64, /// The List of refund response object pub data: Vec, } #[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq, ToSchema)] pub struct RefundListMetaData { /// The list of available connector filters pub connector: Vec, /// The list of available currency filters #[schema(value_type = Vec)] pub currency: Vec, /// The list of available refund status filters #[schema(value_type = Vec)] pub refund_status: Vec, } #[derive(Clone, Debug, serde::Serialize, ToSchema)] pub struct RefundListFilters { /// 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>, /// The list of available currency filters #[schema(value_type = Vec)] pub currency: Vec, /// The list of available refund status filters #[schema(value_type = Vec)] pub refund_status: Vec, } #[derive(Clone, Debug, serde::Serialize)] pub struct RefundAggregateResponse { /// The list of refund status with their count pub status_with_count: HashMap, } /// The status for refunds #[derive( Debug, Eq, Clone, Copy, PartialEq, Default, Deserialize, Serialize, ToSchema, strum::Display, strum::EnumIter, )] #[serde(rename_all = "snake_case")] pub enum RefundStatus { Succeeded, Failed, #[default] Pending, Review, } impl From for RefundStatus { fn from(status: enums::RefundStatus) -> Self { match status { enums::RefundStatus::Failure | enums::RefundStatus::TransactionFailure => Self::Failed, enums::RefundStatus::ManualReview => Self::Review, enums::RefundStatus::Pending => Self::Pending, enums::RefundStatus::Success => Self::Succeeded, } } } impl From for enums::RefundStatus { fn from(status: RefundStatus) -> Self { match status { RefundStatus::Failed => Self::Failure, RefundStatus::Review => Self::ManualReview, RefundStatus::Pending => Self::Pending, RefundStatus::Succeeded => Self::Success, } } }