rain_sdk/api/
disputes.rs

1//! Disputes API
2//!
3//! This module provides functionality to manage disputes.
4
5use crate::client::RainClient;
6use crate::error::Result;
7use crate::models::disputes::*;
8use uuid::Uuid;
9
10impl RainClient {
11    /// Get all disputes
12    ///
13    /// # Arguments
14    ///
15    /// * `params` - Query parameters to filter disputes
16    ///
17    /// # Returns
18    ///
19    /// Returns a [`Vec<Dispute>`] containing the list of disputes.
20    #[cfg(feature = "async")]
21    pub async fn list_disputes(&self, params: &ListDisputesParams) -> Result<Vec<Dispute>> {
22        let path = "/issuing/disputes";
23        let query_string = serde_urlencoded::to_string(params)?;
24        let full_path = if query_string.is_empty() {
25            path.to_string()
26        } else {
27            format!("{path}?{query_string}")
28        };
29        self.get(&full_path).await
30    }
31
32    /// Get a dispute by its id
33    ///
34    /// # Arguments
35    ///
36    /// * `dispute_id` - The unique identifier of the dispute
37    ///
38    /// # Returns
39    ///
40    /// Returns a [`Dispute`] containing the dispute information.
41    #[cfg(feature = "async")]
42    pub async fn get_dispute(&self, dispute_id: &Uuid) -> Result<Dispute> {
43        let path = format!("/issuing/disputes/{dispute_id}");
44        self.get(&path).await
45    }
46
47    /// Update a dispute
48    ///
49    /// # Arguments
50    ///
51    /// * `dispute_id` - The unique identifier of the dispute
52    /// * `request` - The update request
53    ///
54    /// # Returns
55    ///
56    /// Returns success (204 No Content) with no response body.
57    #[cfg(feature = "async")]
58    pub async fn update_dispute(
59        &self,
60        dispute_id: &Uuid,
61        request: &UpdateDisputeRequest,
62    ) -> Result<()> {
63        let path = format!("/issuing/disputes/{dispute_id}");
64        let _: serde_json::Value = self.patch(&path, request).await?;
65        Ok(())
66    }
67
68    /// Get a dispute's file evidence
69    ///
70    /// # Arguments
71    ///
72    /// * `dispute_id` - The unique identifier of the dispute
73    ///
74    /// # Returns
75    ///
76    /// Returns the file evidence as raw bytes (application/octet-stream).
77    #[cfg(feature = "async")]
78    pub async fn get_dispute_evidence(&self, dispute_id: &Uuid) -> Result<Vec<u8>> {
79        let path = format!("/issuing/disputes/{dispute_id}/evidence");
80        self.get_bytes(&path).await
81    }
82
83    /// Upload a file as evidence for a dispute
84    ///
85    /// # Arguments
86    ///
87    /// * `dispute_id` - The unique identifier of the dispute
88    /// * `request` - The evidence upload request
89    ///
90    /// # Returns
91    ///
92    /// Returns success (204 No Content) with no response body.
93    #[cfg(feature = "async")]
94    pub async fn upload_dispute_evidence(
95        &self,
96        dispute_id: &Uuid,
97        request: &UploadDisputeEvidenceRequest,
98    ) -> Result<()> {
99        let path = format!("/issuing/disputes/{dispute_id}/evidence");
100
101        use reqwest::multipart::{Form, Part};
102        let form = Form::new()
103            .text("name", request.name.clone())
104            .text("type", request.evidence_type.clone())
105            .part(
106                "evidence",
107                Part::bytes(request.file.clone()).file_name(request.name.clone()),
108            );
109
110        self.put_multipart_no_content(&path, form).await
111    }
112
113    /// Create a dispute for a transaction
114    ///
115    /// # Arguments
116    ///
117    /// * `transaction_id` - The unique identifier of the transaction
118    /// * `request` - The dispute creation request
119    ///
120    /// # Returns
121    ///
122    /// Returns a [`Dispute`] containing the created dispute information.
123    #[cfg(feature = "async")]
124    pub async fn create_transaction_dispute(
125        &self,
126        transaction_id: &Uuid,
127        request: &CreateDisputeRequest,
128    ) -> Result<Dispute> {
129        let path = format!("/issuing/transactions/{transaction_id}/disputes");
130        self.post(&path, request).await
131    }
132
133    // ============================================================================
134    // Blocking Methods
135    // ============================================================================
136
137    /// Get all disputes (blocking)
138    #[cfg(feature = "sync")]
139    pub fn list_disputes_blocking(&self, params: &ListDisputesParams) -> Result<Vec<Dispute>> {
140        let path = "/issuing/disputes";
141        let query_string = serde_urlencoded::to_string(params)?;
142        let full_path = if query_string.is_empty() {
143            path.to_string()
144        } else {
145            format!("{path}?{query_string}")
146        };
147        self.get_blocking(&full_path)
148    }
149
150    /// Get a dispute by its id (blocking)
151    #[cfg(feature = "sync")]
152    pub fn get_dispute_blocking(&self, dispute_id: &Uuid) -> Result<Dispute> {
153        let path = format!("/issuing/disputes/{dispute_id}");
154        self.get_blocking(&path)
155    }
156
157    /// Update a dispute (blocking)
158    #[cfg(feature = "sync")]
159    pub fn update_dispute_blocking(
160        &self,
161        dispute_id: &Uuid,
162        request: &UpdateDisputeRequest,
163    ) -> Result<()> {
164        let path = format!("/issuing/disputes/{dispute_id}");
165        let _: serde_json::Value = self.patch_blocking(&path, request)?;
166        Ok(())
167    }
168
169    /// Get a dispute's file evidence (blocking)
170    #[cfg(feature = "sync")]
171    pub fn get_dispute_evidence_blocking(&self, dispute_id: &Uuid) -> Result<Vec<u8>> {
172        let path = format!("/issuing/disputes/{dispute_id}/evidence");
173        self.get_bytes_blocking(&path)
174    }
175
176    /// Upload a file as evidence for a dispute (blocking)
177    #[cfg(feature = "sync")]
178    pub fn upload_dispute_evidence_blocking(
179        &self,
180        dispute_id: &Uuid,
181        request: &UploadDisputeEvidenceRequest,
182    ) -> Result<()> {
183        let path = format!("/issuing/disputes/{dispute_id}/evidence");
184
185        use reqwest::blocking::multipart::{Form, Part};
186        let form = Form::new()
187            .text("name", request.name.clone())
188            .text("type", request.evidence_type.clone())
189            .part(
190                "evidence",
191                Part::bytes(request.file.clone()).file_name(request.name.clone()),
192            );
193
194        let url = self.build_url(&path)?;
195        let response = self.put_multipart_blocking_no_content(&path, form)?;
196        Ok(response)
197    }
198
199    /// Create a dispute for a transaction (blocking)
200    #[cfg(feature = "sync")]
201    pub fn create_transaction_dispute_blocking(
202        &self,
203        transaction_id: &Uuid,
204        request: &CreateDisputeRequest,
205    ) -> Result<Dispute> {
206        let path = format!("/issuing/transactions/{transaction_id}/disputes");
207        self.post_blocking(&path, request)
208    }
209}