sure_client_rs/client/merchants.rs
1use bon::bon;
2use reqwest::Method;
3
4use crate::ApiError;
5use crate::error::ApiResult;
6use crate::models::merchant::{
7 CreateMerchantData, CreateMerchantRequest, MerchantCollection, MerchantDetail,
8 UpdateMerchantData, UpdateMerchantRequest,
9};
10use crate::models::{DeleteResponse, PaginatedResponse};
11use crate::types::MerchantId;
12use std::collections::HashMap;
13
14use super::SureClient;
15
16const MAX_PER_PAGE: u32 = 100;
17
18#[bon]
19impl SureClient {
20 /// List merchants
21 ///
22 /// Retrieves a paginated list of merchants.
23 ///
24 /// # Arguments
25 /// * `page` - Page number (default: 1)
26 /// * `per_page` - Items per page (default: 25, max: 100)
27 ///
28 /// # Returns
29 /// A paginated response containing merchants and pagination metadata.
30 ///
31 /// # Errors
32 /// Returns `ApiError::Unauthorized` if the API key is invalid.
33 /// Returns `ApiError::Network` if the request fails due to network issues.
34 ///
35 /// # Example
36 /// ```no_run
37 /// use sure_client_rs::{SureClient, BearerToken};
38 ///
39 /// # async fn example(client: SureClient) -> Result<(), Box<dyn std::error::Error>> {
40 /// // Use defaults (page 1, per_page 25)
41 /// let response = client.get_merchants().call().await?;
42 ///
43 /// for merchant in response.items.merchants {
44 /// println!("Merchant: {}", merchant.name);
45 /// }
46 ///
47 /// // Or customize parameters using the builder
48 /// let response = client.get_merchants().page(2).per_page(50).call().await?;
49 /// # Ok(())
50 /// # }
51 /// ```
52 #[builder]
53 pub async fn get_merchants(
54 &self,
55 #[builder(default = 1)] page: u32,
56 #[builder(default = 25)] per_page: u32,
57 ) -> ApiResult<PaginatedResponse<MerchantCollection>> {
58 if per_page > MAX_PER_PAGE {
59 return Err(ApiError::InvalidParameter(format!(
60 "per_page cannot exceed {MAX_PER_PAGE}",
61 )));
62 }
63
64 let mut query_params = HashMap::new();
65
66 query_params.insert("page", page.to_string());
67 query_params.insert("per_page", per_page.to_string());
68
69 self.execute_request(Method::GET, "/api/v1/merchants", Some(&query_params), None)
70 .await
71 }
72
73 /// Get a specific merchant by ID
74 ///
75 /// Retrieves detailed information about a single merchant.
76 ///
77 /// # Arguments
78 /// * `id` - The merchant ID to retrieve
79 ///
80 /// # Returns
81 /// Detailed merchant information.
82 ///
83 /// # Errors
84 /// Returns `ApiError::NotFound` if the merchant doesn't exist.
85 /// Returns `ApiError::Unauthorized` if the API key is invalid.
86 /// Returns `ApiError::Network` if the request fails due to network issues.
87 ///
88 /// # Example
89 /// ```no_run
90 /// use sure_client_rs::{SureClient, BearerToken, MerchantId};
91 /// use uuid::Uuid;
92 ///
93 /// # async fn example(client: SureClient) -> Result<(), Box<dyn std::error::Error>> {
94 /// let merchant_id = MerchantId::new(Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap());
95 /// let merchant = client.get_merchant(&merchant_id).await?;
96 ///
97 /// println!("Merchant: {}", merchant.name);
98 /// # Ok(())
99 /// # }
100 /// ```
101 pub async fn get_merchant(&self, id: &MerchantId) -> ApiResult<MerchantDetail> {
102 self.execute_request(
103 Method::GET,
104 &format!("/api/v1/merchants/{}", id),
105 None,
106 None,
107 )
108 .await
109 }
110}
111
112#[bon]
113impl SureClient {
114 /// Create a new merchant
115 ///
116 /// Creates a new merchant with the specified details.
117 ///
118 /// # Arguments
119 /// * `name` - Merchant name (required)
120 /// * `color` - Merchant color (hex code)
121 ///
122 /// # Returns
123 /// The newly created merchant with full details.
124 ///
125 /// # Errors
126 /// Returns `ApiError::ValidationError` if required fields are missing or invalid.
127 /// Returns `ApiError::Unauthorized` if the API key is invalid.
128 /// Returns `ApiError::Network` if the request fails due to network issues.
129 ///
130 /// # Example
131 /// ```no_run
132 /// use sure_client_rs::{SureClient, BearerToken};
133 ///
134 /// # async fn example(client: SureClient) -> Result<(), Box<dyn std::error::Error>> {
135 /// let merchant = client.create_merchant()
136 /// .name("Starbucks".to_string())
137 /// .color("#00704A".to_string())
138 /// .call()
139 /// .await?;
140 ///
141 /// println!("Created merchant: {}", merchant.name);
142 /// # Ok(())
143 /// # }
144 /// ```
145 #[builder]
146 pub async fn create_merchant(
147 &self,
148 name: String,
149 color: Option<String>,
150 ) -> ApiResult<MerchantDetail> {
151 let request = CreateMerchantRequest {
152 merchant: CreateMerchantData { name, color },
153 };
154
155 self.execute_request(
156 Method::POST,
157 "/api/v1/merchants",
158 None,
159 Some(serde_json::to_string(&request)?),
160 )
161 .await
162 }
163
164 /// Update a merchant
165 ///
166 /// Updates an existing merchant with new values. Only fields provided will be updated.
167 ///
168 /// # Arguments
169 /// * `id` - The merchant ID to update
170 /// * `name` - Updated merchant name
171 /// * `color` - Updated merchant color (hex code)
172 ///
173 /// # Returns
174 /// The updated merchant.
175 ///
176 /// # Errors
177 /// Returns `ApiError::NotFound` if the merchant doesn't exist.
178 /// Returns `ApiError::ValidationError` if the provided values are invalid.
179 /// Returns `ApiError::Unauthorized` if the API key is invalid.
180 /// Returns `ApiError::Network` if the request fails due to network issues.
181 ///
182 /// # Example
183 /// ```no_run
184 /// use sure_client_rs::{SureClient, BearerToken, MerchantId};
185 /// use uuid::Uuid;
186 ///
187 /// # async fn example(client: SureClient) -> Result<(), Box<dyn std::error::Error>> {
188 /// let merchant_id = MerchantId::new(Uuid::new_v4());
189 ///
190 /// let merchant = client.update_merchant()
191 /// .id(&merchant_id)
192 /// .name("Updated Merchant Name".to_string())
193 /// .color("#FF0000".to_string())
194 /// .call()
195 /// .await?;
196 ///
197 /// println!("Updated merchant: {}", merchant.name);
198 /// # Ok(())
199 /// # }
200 /// ```
201 #[builder]
202 pub async fn update_merchant(
203 &self,
204 id: &MerchantId,
205 name: Option<String>,
206 color: Option<String>,
207 ) -> ApiResult<MerchantDetail> {
208 let request = UpdateMerchantRequest {
209 merchant: UpdateMerchantData { name, color },
210 };
211
212 self.execute_request(
213 Method::PATCH,
214 &format!("/api/v1/merchants/{}", id),
215 None,
216 Some(serde_json::to_string(&request)?),
217 )
218 .await
219 }
220
221 /// Delete a merchant
222 ///
223 /// Permanently deletes a merchant.
224 ///
225 /// # Arguments
226 /// * `id` - The merchant ID to delete
227 ///
228 /// # Returns
229 /// A confirmation message.
230 ///
231 /// # Errors
232 /// Returns `ApiError::NotFound` if the merchant doesn't exist.
233 /// Returns `ApiError::Unauthorized` if the API key is invalid.
234 /// Returns `ApiError::Network` if the request fails due to network issues.
235 ///
236 /// # Example
237 /// ```no_run
238 /// use sure_client_rs::{SureClient, BearerToken, MerchantId};
239 /// use uuid::Uuid;
240 ///
241 /// # async fn example(client: SureClient) -> Result<(), Box<dyn std::error::Error>> {
242 /// let merchant_id = MerchantId::new(Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap());
243 /// let response = client.delete_merchant(&merchant_id).await?;
244 ///
245 /// println!("Deleted: {}", response.message);
246 /// # Ok(())
247 /// # }
248 /// ```
249 pub async fn delete_merchant(&self, id: &MerchantId) -> ApiResult<DeleteResponse> {
250 self.execute_request(
251 Method::DELETE,
252 &format!("/api/v1/merchants/{}", id),
253 None,
254 None,
255 )
256 .await
257 }
258}