noah_sdk/api/
customers.rs

1//! Customers API
2//!
3//! This module provides functionality to manage customers in the Noah API.
4//!
5//! # Examples
6//!
7//! ```no_run
8//! use noah_sdk::{NoahClient, Config, Environment, AuthConfig};
9//! use noah_sdk::models::customers::CustomerInput;
10//! use noah_sdk::models::common::CustomerID;
11//! use noah_sdk::models::FullName;
12//! use noah_sdk::models::StreetAddress;
13//!
14//! # #[cfg(feature = "async")]
15//! # async fn example() -> Result<(), Box<dyn std::error::Error>> {
16//! let config = Config::new(Environment::Sandbox);
17//! let auth = AuthConfig::with_api_key("your-api-key".to_string());
18//! let client = NoahClient::new(config, auth)?;
19//!
20//! // Create or update a customer
21//! use noah_sdk::models::customers::{CustomerInput, IndividualCustomerInput, FullName, StreetAddress};
22//! use noah_sdk::models::common::*;
23//! let customer_id = "customer-123".to_string();
24//! // Note: IndividualCustomerInput requires many fields (customer_type, full_name,
25//! // date_of_birth, email, identities, primary_residence, etc.)
26//! // This is a simplified example - see the API documentation for full field details
27//! # let customer_input = CustomerInput::Individual(IndividualCustomerInput {
28//! #     customer_type: "Individual".to_string(),
29//! #     full_name: FullName {
30//! #         first_name: "John".to_string(),
31//! #         last_name: "Doe".to_string(),
32//! #         middle_name: None,
33//! #     },
34//! #     date_of_birth: "1990-01-01".to_string(),
35//! #     email: Some("john@example.com".to_string()),
36//! #     phone_number: None,
37//! #     identities: vec![],
38//! #     primary_residence: StreetAddress {
39//! #         street: "123 Main St".to_string(),
40//! #         street2: None,
41//! #         city: "New York".to_string(),
42//! #         post_code: "10001".to_string(),
43//! #         state: "NY".to_string(),
44//! #         country: "US".to_string(),
45//! #     },
46//! # });
47//! client.create_or_update_customer(&customer_id, &customer_input).await?;
48//!
49//! // Retrieve customer
50//! let customer = client.get_customer(&customer_id).await?;
51//! println!("Customer: {:?}", customer);
52//! # Ok(())
53//! # }
54//! ```
55
56use crate::client::NoahClient;
57use crate::error::Result;
58use crate::models::common::*;
59use crate::models::customers::{Customer, CustomerInput, GetCustomersResponse};
60
61impl NoahClient {
62    /// Retrieve a customer by their ID
63    ///
64    /// # Arguments
65    ///
66    /// * `customer_id` - The unique identifier of the customer to retrieve
67    ///
68    /// # Returns
69    ///
70    /// Returns a [`Customer`] object containing the customer's information.
71    ///
72    /// # Errors
73    ///
74    /// This function will return an error if:
75    /// - The customer ID is invalid
76    /// - The customer does not exist
77    /// - The API request fails
78    ///
79    /// # Examples
80    ///
81    /// ```no_run
82    /// use noah_sdk::{NoahClient, Config, Environment, AuthConfig};
83    /// use noah_sdk::models::common::CustomerID;
84    ///
85    /// # #[cfg(feature = "async")]
86    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
87    /// let config = Config::new(Environment::Sandbox);
88    /// let auth = AuthConfig::with_api_key("your-api-key".to_string());
89    /// let client = NoahClient::new(config, auth)?;
90    ///
91    /// let customer_id = "customer-123".to_string();
92    /// let customer = client.get_customer(&customer_id).await?;
93    /// # Ok(())
94    /// # }
95    /// ```
96    #[cfg(feature = "async")]
97    pub async fn get_customer(&self, customer_id: &CustomerID) -> Result<Customer> {
98        let path = format!("/customers/{customer_id}");
99        self.get(&path).await
100    }
101
102    /// Retrieve a customer by their ID (blocking)
103    ///
104    /// Synchronous version of [`get_customer`](Self::get_customer). See that method for
105    /// detailed documentation.
106    #[cfg(feature = "sync")]
107    pub fn get_customer_blocking(&self, customer_id: &CustomerID) -> Result<Customer> {
108        let path = format!("/customers/{customer_id}");
109        self.get_blocking(&path)
110    }
111
112    /// Create a new customer or update an existing one
113    ///
114    /// This method will create a customer if they don't exist, or update an existing customer
115    /// if they do. The customer ID is used as the unique identifier.
116    ///
117    /// # Arguments
118    ///
119    /// * `customer_id` - The unique identifier for the customer
120    /// * `customer` - The customer data to create or update
121    ///
122    /// # Returns
123    ///
124    /// Returns `Ok(())` if the operation succeeds.
125    ///
126    /// # Errors
127    ///
128    /// This function will return an error if:
129    /// - The customer data is invalid
130    /// - The API request fails
131    /// - Authentication fails
132    ///
133    /// # Examples
134    ///
135    /// ```no_run
136    /// use noah_sdk::{NoahClient, Config, Environment, AuthConfig};
137    /// use noah_sdk::models::customers::CustomerInput;
138    /// use noah_sdk::models::common::CustomerID;
139    ///
140    /// # #[cfg(feature = "async")]
141    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
142    /// let config = Config::new(Environment::Sandbox);
143    /// let auth = AuthConfig::with_api_key("your-api-key".to_string());
144    /// let client = NoahClient::new(config, auth)?;
145    ///
146    /// use noah_sdk::models::customers::{CustomerInput, IndividualCustomerInput, FullName, StreetAddress};
147    /// use noah_sdk::models::common::*;
148    /// let customer_id = "customer-123".to_string();
149    /// // Note: IndividualCustomerInput requires many fields - see API docs for details
150    /// # let customer = CustomerInput::Individual(IndividualCustomerInput {
151    /// #     customer_type: "Individual".to_string(),
152    /// #     full_name: FullName {
153    /// #         first_name: "John".to_string(),
154    /// #         last_name: "Doe".to_string(),
155    /// #         middle_name: None,
156    /// #     },
157    /// #     date_of_birth: "1990-01-01".to_string(),
158    /// #     email: Some("john@example.com".to_string()),
159    /// #     phone_number: None,
160    /// #     identities: vec![],
161    /// #     primary_residence: StreetAddress {
162    /// #         street: "123 Main St".to_string(),
163    /// #         street2: None,
164    /// #         city: "New York".to_string(),
165    /// #         post_code: "10001".to_string(),
166    /// #         state: "NY".to_string(),
167    /// #         country: "US".to_string(),
168    /// #     },
169    /// # });
170    /// client.create_or_update_customer(&customer_id, &customer).await?;
171    /// # Ok(())
172    /// # }
173    /// ```
174    #[cfg(feature = "async")]
175    pub async fn create_or_update_customer(
176        &self,
177        customer_id: &CustomerID,
178        customer: &CustomerInput,
179    ) -> Result<()> {
180        let path = format!("/customers/{customer_id}");
181        let _response: Option<serde_json::Value> = self.put(&path, customer).await?;
182        Ok(())
183    }
184
185    /// Create a new customer or update an existing one (blocking)
186    ///
187    /// Synchronous version of [`create_or_update_customer`](Self::create_or_update_customer).
188    /// See that method for detailed documentation.
189    #[cfg(feature = "sync")]
190    pub fn create_or_update_customer_blocking(
191        &self,
192        customer_id: &CustomerID,
193        customer: &CustomerInput,
194    ) -> Result<()> {
195        let path = format!("/customers/{customer_id}");
196        let _response: Option<serde_json::Value> = self.put_blocking(&path, customer)?;
197        Ok(())
198    }
199
200    /// List customers with optional pagination and sorting
201    ///
202    /// Retrieves a paginated list of customers. Supports pagination and sorting options.
203    ///
204    /// # Arguments
205    ///
206    /// * `page_size` - Optional number of items per page
207    /// * `page_token` - Optional token for pagination to get the next page
208    /// * `sort_direction` - Optional sort direction (ascending or descending)
209    ///
210    /// # Returns
211    ///
212    /// Returns a [`GetCustomersResponse`] containing the list of customers and pagination info.
213    ///
214    /// # Examples
215    ///
216    /// ```no_run
217    /// use noah_sdk::{NoahClient, Config, Environment, AuthConfig};
218    /// use noah_sdk::models::common::SortDirection;
219    ///
220    /// # #[cfg(feature = "async")]
221    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
222    /// let config = Config::new(Environment::Sandbox);
223    /// let auth = AuthConfig::with_api_key("your-api-key".to_string());
224    /// let client = NoahClient::new(config, auth)?;
225    ///
226    /// // Get first page, sorted descending
227    /// let customers = client.get_customers(
228    ///     Some(50),
229    ///     None,
230    ///     Some(&SortDirection::Desc)
231    /// ).await?;
232    /// # Ok(())
233    /// # }
234    /// ```
235    #[cfg(feature = "async")]
236    pub async fn get_customers(
237        &self,
238        page_size: Option<u32>,
239        page_token: Option<&str>,
240        sort_direction: Option<&SortDirection>,
241    ) -> Result<GetCustomersResponse> {
242        let mut path = "/customers".to_string();
243        let mut query_params = Vec::new();
244
245        if let Some(size) = page_size {
246            query_params.push(format!("PageSize={size}"));
247        }
248        if let Some(token) = page_token {
249            query_params.push(format!("PageToken={token}"));
250        }
251        if let Some(sort) = sort_direction {
252            query_params.push(format!("SortDirection={sort:?}"));
253        }
254
255        if !query_params.is_empty() {
256            path.push('?');
257            path.push_str(&query_params.join("&"));
258        }
259
260        self.get(&path).await
261    }
262
263    /// List customers with optional pagination and sorting (blocking)
264    ///
265    /// Synchronous version of [`get_customers`](Self::get_customers). See that method for
266    /// detailed documentation.
267    #[cfg(feature = "sync")]
268    pub fn get_customers_blocking(
269        &self,
270        page_size: Option<u32>,
271        page_token: Option<&str>,
272        sort_direction: Option<&SortDirection>,
273    ) -> Result<GetCustomersResponse> {
274        let mut path = "/customers".to_string();
275        let mut query_params = Vec::new();
276
277        if let Some(size) = page_size {
278            query_params.push(format!("PageSize={size}"));
279        }
280        if let Some(token) = page_token {
281            query_params.push(format!("PageToken={token}"));
282        }
283        if let Some(sort) = sort_direction {
284            query_params.push(format!("SortDirection={sort:?}"));
285        }
286
287        if !query_params.is_empty() {
288            path.push('?');
289            path.push_str(&query_params.join("&"));
290        }
291
292        self.get_blocking(&path)
293    }
294}