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}