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    ///
21    /// # Errors
22    ///
23    /// This method can return the following errors:
24    /// - `401` - Invalid authorization
25    /// - `500` - Internal server error
26    #[cfg(feature = "async")]
27    pub async fn list_disputes(&self, params: &ListDisputesParams) -> Result<Vec<Dispute>> {
28        let path = "/disputes";
29        let query_string = serde_urlencoded::to_string(params)?;
30        let full_path = if query_string.is_empty() {
31            path.to_string()
32        } else {
33            format!("{path}?{query_string}")
34        };
35        self.get(&full_path).await
36    }
37
38    /// Get a dispute by its id
39    ///
40    /// # Arguments
41    ///
42    /// * `dispute_id` - The unique identifier of the dispute
43    ///
44    /// # Returns
45    ///
46    /// Returns a [`Dispute`] containing the dispute information.
47    ///
48    /// # Errors
49    ///
50    /// This method can return the following errors:
51    /// - `401` - Invalid authorization
52    /// - `404` - Dispute not found
53    /// - `500` - Internal server error
54    #[cfg(feature = "async")]
55    pub async fn get_dispute(&self, dispute_id: &Uuid) -> Result<Dispute> {
56        let path = format!("/disputes/{dispute_id}");
57        self.get(&path).await
58    }
59
60    /// Update a dispute
61    ///
62    /// # Arguments
63    ///
64    /// * `dispute_id` - The unique identifier of the dispute
65    /// * `request` - The update request
66    ///
67    /// # Returns
68    ///
69    /// Returns success (204 No Content) with no response body.
70    ///
71    /// # Errors
72    ///
73    /// This method can return the following errors:
74    /// - `400` - Invalid request
75    /// - `401` - Invalid authorization
76    /// - `404` - Dispute not found
77    /// - `500` - Internal server error
78    #[cfg(feature = "async")]
79    pub async fn update_dispute(
80        &self,
81        dispute_id: &Uuid,
82        request: &UpdateDisputeRequest,
83    ) -> Result<()> {
84        let path = format!("/disputes/{dispute_id}");
85        let _: serde_json::Value = self.patch(&path, request).await?;
86        Ok(())
87    }
88
89    /// Get a dispute's file evidence
90    ///
91    /// # Arguments
92    ///
93    /// * `dispute_id` - The unique identifier of the dispute
94    ///
95    /// # Returns
96    ///
97    /// Returns the file evidence as raw bytes (application/octet-stream).
98    #[cfg(feature = "async")]
99    pub async fn get_dispute_evidence(&self, dispute_id: &Uuid) -> Result<Vec<u8>> {
100        let path = format!("/disputes/{dispute_id}/evidence");
101        self.get_bytes(&path).await
102    }
103
104    /// Upload a file as evidence for a dispute
105    ///
106    /// # Arguments
107    ///
108    /// * `dispute_id` - The unique identifier of the dispute
109    /// * `request` - The evidence upload request
110    ///
111    /// # Returns
112    ///
113    /// Returns success (204 No Content) with no response body.
114    #[cfg(feature = "async")]
115    pub async fn upload_dispute_evidence(
116        &self,
117        dispute_id: &Uuid,
118        request: &UploadDisputeEvidenceRequest,
119    ) -> Result<()> {
120        let path = format!("/disputes/{dispute_id}/evidence");
121
122        use reqwest::multipart::{Form, Part};
123        let form = Form::new()
124            .text("name", request.name.clone())
125            .text("type", request.evidence_type.clone())
126            .part(
127                "evidence",
128                Part::bytes(request.file.clone()).file_name(request.name.clone()),
129            );
130
131        self.put_multipart_no_content(&path, form).await
132    }
133
134    /// Create a dispute for a transaction
135    ///
136    /// # Arguments
137    ///
138    /// * `transaction_id` - The unique identifier of the transaction
139    /// * `request` - The dispute creation request
140    ///
141    /// # Returns
142    ///
143    /// Returns a [`Dispute`] containing the created dispute information.
144    ///
145    /// # Errors
146    ///
147    /// This method can return the following errors:
148    /// - `400` - Invalid request
149    /// - `401` - Invalid authorization
150    /// - `404` - Transaction not found
151    /// - `500` - Internal server error
152    #[cfg(feature = "async")]
153    pub async fn create_transaction_dispute(
154        &self,
155        transaction_id: &Uuid,
156        request: &CreateDisputeRequest,
157    ) -> Result<Dispute> {
158        let path = format!("/transactions/{transaction_id}/disputes");
159        self.post(&path, request).await
160    }
161
162    // ============================================================================
163    // Blocking Methods
164    // ============================================================================
165
166    /// Get all disputes (blocking)
167    #[cfg(feature = "sync")]
168    pub fn list_disputes_blocking(&self, params: &ListDisputesParams) -> Result<Vec<Dispute>> {
169        let path = "/disputes";
170        let query_string = serde_urlencoded::to_string(params)?;
171        let full_path = if query_string.is_empty() {
172            path.to_string()
173        } else {
174            format!("{path}?{query_string}")
175        };
176        self.get_blocking(&full_path)
177    }
178
179    /// Get a dispute by its id (blocking)
180    #[cfg(feature = "sync")]
181    pub fn get_dispute_blocking(&self, dispute_id: &Uuid) -> Result<Dispute> {
182        let path = format!("/disputes/{dispute_id}");
183        self.get_blocking(&path)
184    }
185
186    /// Update a dispute (blocking)
187    #[cfg(feature = "sync")]
188    pub fn update_dispute_blocking(
189        &self,
190        dispute_id: &Uuid,
191        request: &UpdateDisputeRequest,
192    ) -> Result<()> {
193        let path = format!("/disputes/{dispute_id}");
194        let _: serde_json::Value = self.patch_blocking(&path, request)?;
195        Ok(())
196    }
197
198    /// Get a dispute's file evidence (blocking)
199    #[cfg(feature = "sync")]
200    pub fn get_dispute_evidence_blocking(&self, dispute_id: &Uuid) -> Result<Vec<u8>> {
201        let path = format!("/disputes/{dispute_id}/evidence");
202        self.get_bytes_blocking(&path)
203    }
204
205    /// Upload a file as evidence for a dispute (blocking)
206    #[cfg(feature = "sync")]
207    pub fn upload_dispute_evidence_blocking(
208        &self,
209        dispute_id: &Uuid,
210        request: &UploadDisputeEvidenceRequest,
211    ) -> Result<()> {
212        let path = format!("/disputes/{dispute_id}/evidence");
213
214        use reqwest::blocking::multipart::{Form, Part};
215        let form = Form::new()
216            .text("name", request.name.clone())
217            .text("type", request.evidence_type.clone())
218            .part(
219                "evidence",
220                Part::bytes(request.file.clone()).file_name(request.name.clone()),
221            );
222
223        let url = self.build_url(&path)?;
224        let response = self.put_multipart_blocking_no_content(&path, form)?;
225        Ok(response)
226    }
227
228    /// Create a dispute for a transaction (blocking)
229    #[cfg(feature = "sync")]
230    pub fn create_transaction_dispute_blocking(
231        &self,
232        transaction_id: &Uuid,
233        request: &CreateDisputeRequest,
234    ) -> Result<Dispute> {
235        let path = format!("/transactions/{transaction_id}/disputes");
236        self.post_blocking(&path, request)
237    }
238}