1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
//! Create and manage customer profiles and sync CRM systems with Square.
//!
//! The Customers API enables you to create and manage customer profiles, as well as search for
//! customers based on various criteria (including customer group membership). You can also use the
//! API to sync contacts between your CRM system and Square.

use crate::models::{
    AddGroupToCustomerResponse, BulkCreateCustomersRequest, BulkCreateCustomersResponse,
    BulkDeleteCustomersRequest, BulkDeleteCustomersResponse, BulkRetrieveCustomersRequest,
    BulkRetrieveCustomersResponse, BulkUpdateCustomersRequest, BulkUpdateCustomersResponse,
    DeleteCustomerParameters, RemoveGroupFromCustomerResponse,
};
use crate::{
    config::Configuration,
    http::client::HttpClient,
    models::{
        errors::SquareApiError, CreateCustomerRequest, CreateCustomerResponse,
        DeleteCustomerResponse, ListCustomersParameters, ListCustomersResponse,
        RetrieveCustomerResponse, SearchCustomersRequest, SearchCustomersResponse,
        UpdateCustomerRequest, UpdateCustomerResponse,
    },
    SquareClient,
};

const DEFAULT_URI: &str = "/customers";

/// Create and manage [Customer] profiles and sync CRM systems with Square.
pub struct CustomersApi {
    /// App config information
    config: Configuration,
    /// HTTP Client for requests to the Customers API endpoints
    http_client: HttpClient,
}

impl CustomersApi {
    /// Instantiates a new `CustomersApi`
    pub fn new(square_client: SquareClient) -> CustomersApi {
        CustomersApi {
            config: square_client.config,
            http_client: square_client.http_client,
        }
    }

    /// Lists [Customer] profiles associated with a Square account.
    ///
    /// Under normal operating conditions, newly created or updated customer profiles become
    /// available for the listing operation in well under 30 seconds. Occasionally, propagation of
    /// the new or updated profiles can take closer to one minute or longer, especially during
    /// network incidents and outages.
    pub async fn list_customers(
        &self,
        params: &ListCustomersParameters,
    ) -> Result<ListCustomersResponse, SquareApiError> {
        let url = format!("{}{}", &self.url(), params.to_query_string());
        let response = self.http_client.get(&url).await?;

        response.deserialize().await
    }

    /// Creates a new [Customer] for a business.
    ///
    /// You must provide at least one of the following values in your request to this endpoint:
    ///
    /// * `given_name`
    /// * `family_name`
    /// * `company_name`
    /// * `email_address`
    /// * `phone_number`
    pub async fn create_customer(
        &self,
        body: &CreateCustomerRequest,
    ) -> Result<CreateCustomerResponse, SquareApiError> {
        let response = self.http_client.post(&self.url(), body).await?;

        response.deserialize().await
    }

    /// Creates multiple customer profiles for a business.
    ///
    /// This endpoint takes a map of individual create requests and returns a map of responses.
    ///
    /// You must provide at least one of the following values in each create request:
    ///
    /// * `given_name`
    /// * `family_name`
    /// * `company_name`
    /// * `email_address`
    /// * `phone_number`
    ///
    /// Permissions:CUSTOMERS_WRITE
    pub async fn bulk_create_customers(
        &self,
        body: &BulkCreateCustomersRequest,
    ) -> Result<BulkCreateCustomersResponse, SquareApiError> {
        let url = format!("{}/bulk-create", &self.url());
        let response = self.http_client.post(&url, body).await?;

        response.deserialize().await
    }

    /// Deletes multiple customer profiles.
    ///
    /// The endpoint takes a list of customer IDs and returns a map of responses.
    /// Permissions:CUSTOMERS_WRITE
    pub async fn bulk_delete_customers(
        &self,
        body: &BulkDeleteCustomersRequest,
    ) -> Result<BulkDeleteCustomersResponse, SquareApiError> {
        let url = format!("{}/bulk-delete", &self.url());
        let response = self.http_client.post(&url, body).await?;

        response.deserialize().await
    }

    /// Retrieves multiple customer profiles.
    ///
    /// This endpoint takes a list of customer IDs and returns a map of responses.
    /// Permissions:CUSTOMERS_READ
    pub async fn bulk_retrieve_customers(
        &self,
        body: &BulkRetrieveCustomersRequest,
    ) -> Result<BulkRetrieveCustomersResponse, SquareApiError> {
        let url = format!("{}/bulk-retrieve", &self.url());
        let response = self.http_client.post(&url, body).await?;

        response.deserialize().await
    }

    /// Updates multiple customer profiles.
    ///
    /// This endpoint takes a map of individual update requests and returns a map of responses.
    ///
    /// You cannot use this endpoint to change cards on file. To make changes, use the Cards API
    /// Use the Cards API to save a credit or debit card on file.Reference or Gift Cards API
    /// Permissions:CUSTOMERS_WRITE
    pub async fn bulk_update_customers(
        &self,
        body: &BulkUpdateCustomersRequest,
    ) -> Result<BulkUpdateCustomersResponse, SquareApiError> {
        let url = format!("{}/bulk-update", &self.url());
        let response = self.http_client.post(&url, body).await?;

        response.deserialize().await
    }

    /// Searches the [Customer] profiles associated with a Square account using a supported query
    /// filter.
    ///
    /// Calling `SearchCustomers` without any explicit query filter returns all customer profiles
    /// ordered alphabetically based on `given_name` and `family_name`.
    ///
    /// Under normal operating conditions, newly created or updated customer profiles become
    /// available for the search operation in well under 30 seconds. Occasionally, propagation of
    /// the new or updated profiles can take closer to one minute or longer, especially during
    /// network incidents and outages.
    pub async fn search_customers(
        &self,
        body: &SearchCustomersRequest,
    ) -> Result<SearchCustomersResponse, SquareApiError> {
        let url = format!("{}/search", &self.url());
        let response = self.http_client.post(&url, body).await?;

        response.deserialize().await
    }

    /// Deletes a [Customer] profile from a business.
    ///
    /// This operation also unlinks any associated cards on file.
    ///
    /// As a best practice, you should include the version field in the request to enable optimistic
    /// concurrency control. The value must be set to the current version of the customer profile.
    ///
    /// To delete a customer profile that was created by merging existing profiles, you must use the
    /// ID of the newly created profile.
    pub async fn delete_customer(
        &self,
        customer_id: impl AsRef<str>,
        params: &DeleteCustomerParameters,
    ) -> Result<DeleteCustomerResponse, SquareApiError> {
        let url = format!(
            "{}/{}{}",
            &self.url(),
            customer_id.as_ref(),
            params.to_query_string()
        );
        let response = self.http_client.delete(&url).await?;

        response.deserialize().await
    }

    /// Returns details for a single [Customer].
    pub async fn retrieve_customer(
        &self,
        customer_id: impl AsRef<str>,
    ) -> Result<RetrieveCustomerResponse, SquareApiError> {
        let url = format!("{}/{}", &self.url(), customer_id.as_ref());
        let response = self.http_client.get(&url).await?;

        response.deserialize().await
    }

    /// Updates a [Customer] profile.
    ///
    /// To change an attribute, specify the new value. To remove an attribute, specify the value as
    /// an empty string or empty object.
    ///
    /// As a best practice, you should include the `version` field in the request to enable
    /// [optimistic
    /// concurrency](https://developer.squareup.com/docs/working-with-apis/optimistic-concurrency)
    /// control. The value must be set to the current version of the customer profile.
    ///
    /// To update a customer profile that was created by merging existing profiles, you must use the
    /// ID of the newly created profile.
    ///
    /// You cannot use this endpoint to change cards on file. To make changes, use the [Cards
    /// API](https://developer.squareup.com/reference/square/cards-api) or [Gift Cards
    /// API](https://developer.squareup.com/reference/square/giftcards-api).
    pub async fn update_customer(
        &self,
        customer_id: impl AsRef<str>,
        body: &UpdateCustomerRequest,
    ) -> Result<UpdateCustomerResponse, SquareApiError> {
        let url = format!("{}/{}", &self.url(), customer_id.as_ref());
        let response = self.http_client.put(&url, body).await?;

        response.deserialize().await
    }

    /// Removes a group membership from a [Customer].
    ///
    /// The customer is identified by the customer_id value and the customer group is
    /// identified by the group_id value.
    pub async fn remove_group_from_customer(
        &self,
        customer_id: impl AsRef<str>,
        group_id: impl AsRef<str>,
    ) -> Result<RemoveGroupFromCustomerResponse, SquareApiError> {
        let url = format!(
            "{}/{}/groups/{}",
            &self.url(),
            customer_id.as_ref(),
            group_id.as_ref()
        );
        let response = self.http_client.delete(&url).await?;

        response.deserialize().await
    }

    /// Adds a group membership to a [Customer].
    ///
    /// Adds a group membership to a customer.
    /// The customer is identified by the customer_id value and the customer group is identified by
    /// the group_id value.
    pub async fn add_group_to_customer(
        &self,
        customer_id: impl AsRef<str>,
        group_id: impl AsRef<str>,
    ) -> Result<AddGroupToCustomerResponse, SquareApiError> {
        let url = format!(
            "{}/{}/groups/{}",
            &self.url(),
            customer_id.as_ref(),
            group_id.as_ref()
        );
        let response = self.http_client.empty_put(&url).await?;

        response.deserialize().await
    }

    fn url(&self) -> String {
        format!("{}{}", &self.config.get_base_url(), DEFAULT_URI)
    }
}