1use crate::client::SquareClient;
6use crate::api::{Verb, SquareAPI};
7use crate::errors::{SquareError, ListParametersBuilderError, ValidationError};
8use crate::response::SquareResponse;
9use crate::objects::{Address, Customer, enums::CustomerCreationSource, SearchQueryAttribute,
10 TimeRange, CustomerFilter, CustomerTextFilter, CreationSource};
11
12use serde::{Deserialize, Serialize};
13use uuid::Uuid;
14use crate::builder::{Builder, ParentBuilder, Validate, Buildable};
15
16impl SquareClient {
17 pub fn customers(&self) -> Customers {
18 Customers {
19 client: &self
20 }
21 }
22}
23
24pub struct Customers<'a> {
25 client: &'a SquareClient,
26}
27
28impl<'a> Customers<'a> {
29 pub async fn list(self, list_parameters: Vec<(String, String)>)
32 -> Result<SquareResponse, SquareError> {
33 self.client.request(
34 Verb::GET,
35 SquareAPI::Customers("".to_string()),
36 None::<&Customer>,
37 Some(list_parameters),
38 ).await
39 }
40
41 pub async fn create(self, customer: Customer)
44 -> Result<SquareResponse, SquareError> {
45 self.client.request(
46 Verb::POST,
47 SquareAPI::Customers("".to_string()),
48 Some(&customer),
49 None,
50 ).await
51 }
52
53 pub async fn search(self, customer_search_query: CustomerSearchQuery)
56 -> Result<SquareResponse, SquareError>{
57 self.client.request(
58 Verb::POST,
59 SquareAPI::Customers("/search".to_string()),
60 Some(&customer_search_query),
61 None,
62 ).await
63 }
64
65 pub async fn delete(self, customer_to_delete: CustomerDelete)
68 -> Result<SquareResponse, SquareError > {
69 self.client.request(
70 Verb::DELETE,
71 SquareAPI::Customers(format!("/{}", customer_to_delete.customer_id.unwrap())),
72 None::<&CustomerSearchQuery>,
73 customer_to_delete.version,
74 ).await
75 }
76}
77
78#[derive(Default)]
82pub struct CustomerListParametersBuilder {
83 cursor: Option<String>,
84 limit: Option<String>,
85 sort_field: Option<String>,
86 sort_order: Option<String>,
87}
88
89impl CustomerListParametersBuilder {
90 pub fn new() -> Self {
91 Default::default()
92 }
93
94 pub fn cursor(mut self, cursor: String) -> Self {
95 self.cursor = Some(cursor.clone());
96
97 self
98 }
99
100 pub fn limit(mut self, limit: i32) -> Self {
101 if limit < 1 || limit > 100 { return self }
102 let limit = limit.to_string();
103 self.limit = Some(limit);
104
105 self
106 }
107
108 pub fn sort_field_default(mut self) -> Self {
109 self.sort_field = Some("DEFAULT".to_string());
110
111 self
112 }
113
114 pub fn sort_field_created_at(mut self) -> Self {
115 self.sort_field = Some("CREATED_AT".to_string());
116
117 self
118 }
119
120 pub fn sort_order_desc(mut self) -> Self {
121 self.sort_order = Some("DESC".to_string());
122
123 self
124 }
125
126 pub fn sort_order_asc(mut self) -> Self {
127 self.sort_order = Some("ASC".to_string());
128
129 self
130 }
131
132 pub async fn build(mut self) -> Result<Vec<(String, String)>, ListParametersBuilderError> {
133 let mut res = Vec::new();
134 if let Some(cursor) = self.cursor.take() {
135 res.push(("cursor".to_string(), cursor))
136 }
137 if let Some(limit) = self.limit.take() {
138 res.push(("limit".to_string(), limit))
139 }
140 if let Some(sort_field) = self.sort_field.take() {
141 res.push(("sort_field".to_string(), sort_field))
142 }
143 if let Some(sort_order) = self.sort_order.take() {
144 res.push(("sort_order".to_string(), sort_order))
145 }
146
147 Ok(res)
148 }
149}
150
151impl Validate for Customer {
155 fn validate(mut self) -> Result<Self, ValidationError> where Self: Sized {
156 if self.given_name.is_some() ||
157 self.family_name.is_some() ||
158 self.company_name.is_some() ||
159 self.email_address.is_some() ||
160 self.phone_number.is_some() {
161 self.idempotency_key = Some(Uuid::new_v4().to_string());
162
163 Ok(self)
164 } else {
165 Err(ValidationError)
166 }
167 }
168}
169
170impl<T: ParentBuilder> Builder<Customer, T> {
171 pub fn given_name(mut self, given_name: String) -> Self {
172 self.body.given_name = Some(given_name);
173
174 self
175 }
176
177 pub fn family_name(mut self, family_name: String) -> Self {
178 self.body.family_name = Some(family_name);
179
180 self
181 }
182
183 pub fn nickname(mut self, nickname: String) -> Self {
184 self.body.nickname = Some(nickname);
185
186 self
187 }
188
189 pub fn email_address(mut self, email_address: String) -> Self {
190 self.body.email_address = Some(email_address);
191
192 self
193 }
194
195 pub fn address_from_address(mut self, address: Address) -> Self {
196 self.body.address = Some(address);
197
198 self
199 }
200
201 pub fn birthday(mut self, birthday: String) -> Self {
202 self.body.birthday = Some(birthday);
203
204 self
205 }
206
207 pub fn phone_number(mut self, phone_number: String) -> Self {
208 self.body.phone_number = Some(phone_number);
209
210 self
211 }
212
213 pub fn note(mut self, note: String) -> Self {
214 self.body.birthday = Some(note);
215
216 self
217 }
218}
219
220#[derive(Debug, Default)]
224pub struct CustomerDelete {
225 customer_id: Option<String>,
226 version: Option<Vec<(String, String)>>,
227}
228
229impl Validate for CustomerDelete {
230 fn validate(self) -> Result<Self, ValidationError> where Self: Sized {
231 if self.customer_id.is_some() {
232 Ok(self)
233 } else {
234 Err(ValidationError)
235 }
236 }
237}
238
239impl<T: ParentBuilder> Builder<CustomerDelete, T> {
240 pub fn customer_id(mut self, customer_id: String) -> Self {
241 self.body.customer_id = Some(customer_id);
242
243 self
244 }
245
246 pub fn version(mut self, version: i64) -> Self {
247 self.body.version = Some(vec![("version".to_string(), version.to_string())]);
248
249 self
250 }
251}
252
253#[derive(Clone, Debug, Serialize, Deserialize, Default)]
257pub struct CustomerSearchQuery {
258 #[serde(skip_serializing_if = "Option::is_none")]
259 pub cursor: Option<String>,
260 #[serde(skip_serializing_if = "Option::is_none")]
261 pub limit: Option<i64>,
262 #[serde(skip_serializing_if = "Option::is_none")]
263 pub query: Option<SearchQueryAttribute>
264}
265
266impl Validate for CustomerSearchQuery {
267 fn validate(self) -> Result<Self, ValidationError> where Self: Sized {
268 Ok(self)
269 }
270}
271
272impl<T: ParentBuilder> Builder<CustomerSearchQuery, T> {
273 pub fn cursor(mut self, cursor: String) -> Self {
274 self.body.cursor = Some(cursor);
275
276 self
277 }
278
279 pub fn limit(mut self, limit: i64) -> Self {
280 if limit < 1 || limit > 100 { return self };
281 self.body.limit = Some(limit);
282
283 self
284 }
285
286 pub fn created_at(mut self, start: String, end: String) -> Self {
287 let time_range = TimeRange {
288 start_at: Some(start),
289 end_at: Some(end),
290 };
291 let filter = CustomerFilter {
292 created_at: Some(time_range.clone()),
293 creation_source: None,
294 email_address: None,
295 group_ids: None,
296 phone_number: None,
297 reference_id: None,
298 updated_at: None
299 };
300 let query = SearchQueryAttribute {
301 filter: Some(filter.clone()),
302 sort: None
303 };
304
305 if let Some(ref mut query) = &mut self.body.query {
306 if let Some(ref mut filter) = query.filter {
307 filter.created_at = Some(time_range);
308 } else {
309 query.filter = Some(filter);
310 }
311 } else {
312 self.body.query = Some(query);
313 }
314
315 self
316 }
317
318 pub fn updated_at(mut self, start: String, end: String) -> Self {
319 let time_range = TimeRange {
320 start_at: Some(start),
321 end_at: Some(end),
322 };
323 let filter = CustomerFilter {
324 created_at: None,
325 creation_source: None,
326 email_address: None,
327 group_ids: None,
328 phone_number: None,
329 reference_id: None,
330 updated_at: Some(time_range.clone())
331 };
332 let query = SearchQueryAttribute {
333 filter: Some(filter.clone()),
334 sort: None
335 };
336
337 if let Some(ref mut query) = &mut self.body.query {
338 if let Some(ref mut filter) = query.filter {
339 filter.updated_at = Some(time_range);
340 } else {
341 query.filter = Some(filter);
342 }
343 } else {
344 self.body.query = Some(query);
345 }
346
347 self
348 }
349
350 pub fn exact_email_address(mut self, email: String) -> Self {
351 let email_group = CustomerTextFilter {
352 exact: Some(email.clone()),
353 fuzzy: None
354 };
355 let filter = CustomerFilter {
356 created_at: None,
357 creation_source: None,
358 email_address: Some(email_group.clone()),
359 group_ids: None,
360 phone_number: None,
361 reference_id: None,
362 updated_at: None
363 };
364 let query = SearchQueryAttribute {
365 filter: Some(filter.clone()),
366 sort: None
367 };
368
369 if let Some(ref mut query) = &mut self.body.query {
370 if let Some(ref mut filter) = query.filter {
371 if let Some(ref mut email_group) = &mut filter.email_address {
372 email_group.exact = Some(email);
373 } else {
374 filter.email_address = Some(email_group)
375 }
376 } else {
377 query.filter = Some(filter);
378 }
379 } else {
380 self.body.query = Some(query);
381 }
382
383 self
384 }
385
386 pub fn fuzzy_email_address(mut self, email: String) -> Self {
387 let email_group = CustomerTextFilter {
388 exact: None,
389 fuzzy: Some(email.clone())
390 };
391 let filter = CustomerFilter {
392 created_at: None,
393 creation_source: None,
394 email_address: Some(email_group.clone()),
395 group_ids: None,
396 phone_number: None,
397 reference_id: None,
398 updated_at: None
399 };
400 let query = SearchQueryAttribute {
401 filter: Some(filter.clone()),
402 sort: None
403 };
404
405 if let Some(ref mut query) = &mut self.body.query {
406 if let Some(ref mut filter) = query.filter {
407 if let Some(ref mut email_group) = &mut filter.email_address {
408 email_group.fuzzy = Some(email);
409 } else {
410 filter.email_address = Some(email_group)
411 }
412 } else {
413 query.filter = Some(filter);
414 }
415 } else {
416 self.body.query = Some(query);
417 }
418
419 self
420 }
421
422 pub fn exact_phone_number(mut self, number: String) -> Self {
423 let phone_group = CustomerTextFilter {
424 exact: Some(number.clone()),
425 fuzzy: None,
426 };
427 let filter = CustomerFilter {
428 created_at: None,
429 creation_source: None,
430 email_address: None,
431 group_ids: None,
432 phone_number: Some(phone_group.clone()),
433 reference_id: None,
434 updated_at: None
435 };
436 let query = SearchQueryAttribute {
437 filter: Some(filter.clone()),
438 sort: None
439 };
440
441 if let Some(ref mut query) = &mut self.body.query {
442 if let Some(ref mut filter) = query.filter {
443 if let Some(ref mut phone_group) = &mut filter.phone_number {
444 phone_group.exact = Some(number);
445 } else {
446 filter.phone_number = Some(phone_group)
447 }
448 } else {
449 query.filter = Some(filter);
450 }
451 } else {
452 self.body.query = Some(query);
453 }
454
455 self
456 }
457
458 pub fn fuzzy_phone_number(mut self, number: String) -> Self {
459 let phone_group = CustomerTextFilter {
460 exact: None,
461 fuzzy: Some(number.clone())
462 };
463 let filter = CustomerFilter {
464 created_at: None,
465 creation_source: None,
466 email_address: None,
467 group_ids: None,
468 phone_number: Some(phone_group.clone()),
469 reference_id: None,
470 updated_at: None
471 };
472 let query = SearchQueryAttribute {
473 filter: Some(filter.clone()),
474 sort: None
475 };
476
477 if let Some(ref mut query) = &mut self.body.query {
478 if let Some(ref mut filter) = query.filter {
479 if let Some(ref mut phone_group) = &mut filter.phone_number {
480 phone_group.fuzzy = Some(number);
481 } else {
482 filter.phone_number = Some(phone_group)
483 }
484 } else {
485 query.filter = Some(filter);
486 }
487 } else {
488 self.body.query = Some(query);
489 }
490
491 self
492 }
493
494 pub fn exact_reference_id(mut self, id: String) -> Self {
495 let reference_id_group = CustomerTextFilter {
496 exact: Some(id.clone()),
497 fuzzy: None,
498 };
499 let filter = CustomerFilter {
500 created_at: None,
501 creation_source: None,
502 email_address: None,
503 group_ids: None,
504 phone_number: None,
505 reference_id: Some(reference_id_group.clone()),
506 updated_at: None
507 };
508 let query = SearchQueryAttribute {
509 filter: Some(filter.clone()),
510 sort: None
511 };
512
513 if let Some(ref mut query) = &mut self.body.query {
514 if let Some(ref mut filter) = query.filter {
515 if let Some(ref mut reference_id_group) = &mut filter.reference_id {
516 reference_id_group.exact = Some(id);
517 } else {
518 filter.reference_id = Some(reference_id_group)
519 }
520 } else {
521 query.filter = Some(filter);
522 }
523 } else {
524 self.body.query = Some(query);
525 }
526
527 self
528 }
529
530 pub fn fuzzy_reference_id(mut self, id: String) -> Self {
531 let reference_id_group = CustomerTextFilter {
532 exact: None,
533 fuzzy: Some(id.clone()),
534 };
535 let filter = CustomerFilter {
536 created_at: None,
537 creation_source: None,
538 email_address: None,
539 group_ids: None,
540 phone_number: None,
541 reference_id: Some(reference_id_group.clone()),
542 updated_at: None
543 };
544 let query = SearchQueryAttribute {
545 filter: Some(filter.clone()),
546 sort: None
547 };
548
549 if let Some(ref mut query) = &mut self.body.query {
550 if let Some(ref mut filter) = query.filter {
551 if let Some(ref mut reference_id_group) = &mut filter.reference_id {
552 reference_id_group.fuzzy = Some(id);
553 } else {
554 filter.reference_id = Some(reference_id_group)
555 }
556 } else {
557 query.filter = Some(filter);
558 }
559 } else {
560 self.body.query = Some(query);
561 }
562
563 self
564 }
565
566 pub fn set_creation_source_exclude(mut self) -> Self {
567 let creation_source = CreationSource {
568 rule: Some("EXCLUDE".to_string()),
569 values: None
570 };
571 let filter = CustomerFilter {
572 created_at: None,
573 creation_source: Some(creation_source.clone()),
574 email_address: None,
575 group_ids: None,
576 phone_number: None,
577 reference_id: None,
578 updated_at: None
579 };
580 let query = SearchQueryAttribute {
581 filter: Some(filter.clone()),
582 sort: None
583 };
584
585 if let Some(ref mut query) = &mut self.body.query {
586 if let Some(ref mut filter) = query.filter {
587 if let Some(ref mut creation_source) = &mut filter.creation_source {
588 creation_source.rule = Some("EXCLUDE".to_string());
589 } else {
590 filter.creation_source = Some(creation_source)
591 }
592 } else {
593 query.filter = Some(filter);
594 }
595 } else {
596 self.body.query = Some(query);
597 }
598
599 self
600 }
601
602 pub fn set_creation_source_include(mut self) -> Self {
603 let creation_source = CreationSource {
604 rule: Some("INCLUDE".to_string()),
605 values: None
606 };
607 let filter = CustomerFilter {
608 created_at: None,
609 creation_source: Some(creation_source.clone()),
610 email_address: None,
611 group_ids: None,
612 phone_number: None,
613 reference_id: None,
614 updated_at: None
615 };
616 let query = SearchQueryAttribute {
617 filter: Some(filter.clone()),
618 sort: None
619 };
620
621 if let Some(ref mut query) = &mut self.body.query {
622 if let Some(ref mut filter) = query.filter {
623 if let Some(ref mut creation_source) = &mut filter.creation_source {
624 creation_source.rule = Some("INCLUDE".to_string());
625 } else {
626 filter.creation_source = Some(creation_source)
627 }
628 } else {
629 query.filter = Some(filter);
630 }
631 } else {
632 self.body.query = Some(query);
633 }
634
635 self
636 }
637
638 pub fn creation_source_value(mut self, value: CustomerCreationSource) -> Self {
639 let values = vec![value.clone()];
640 let creation_source = CreationSource {
641 rule: Some("INCLUDE".to_string()),
642 values: Some(values.clone())
643 };
644 let filter = CustomerFilter {
645 created_at: None,
646 creation_source: Some(creation_source.clone()),
647 email_address: None,
648 group_ids: None,
649 phone_number: None,
650 reference_id: None,
651 updated_at: None
652 };
653 let query = SearchQueryAttribute {
654 filter: Some(filter.clone()),
655 sort: None
656 };
657
658 if let Some(ref mut query) = &mut self.body.query {
659 if let Some(ref mut filter) = &mut query.filter {
660 if let Some(ref mut creation_source) = &mut filter.creation_source {
661 if let Some(ref mut values) = &mut creation_source.values {
662 for val in values.iter() {
663 if *val == value {return self}
664 }
665 values.push(value)
666 } else {
667 creation_source.values = Some(values);
668 }
669 } else {
670 filter.creation_source = Some(creation_source)
671 }
672 } else {
673 query.filter = Some(filter);
674 }
675 } else {
676 self.body.query = Some(query);
677 }
678
679 self
680 }
681}
682
683#[cfg(test)]
684mod test_customers {
685 use super::*;
686
687 #[tokio::test]
688 async fn test_list_parameter_builder() {
689 let sut = CustomerListParametersBuilder::new();
690 let expected = vec![
691 ("limit".to_string(), "4".to_string()),
692 ("sort_field".to_string(), "DEFAULT".to_string())
693 ];
694 let actual =
695 sut.limit(4).limit(101).sort_field_default().build().await;
696
697 assert!(actual.is_ok());
698 assert_eq!(expected, actual.unwrap())
699 }
700
701 #[tokio::test]
702 async fn test_list_customers() {
703 use dotenv::dotenv;
704 use std::env;
705
706 dotenv().ok();
707 let access_token = env::var("ACCESS_TOKEN").expect("ACCESS_TOKEN to be set");
708 let sut = SquareClient::new(&access_token);
709
710 let input = vec![("limit".to_string(), "23".to_string()),
711 ("sort_field".to_string(), "DEFAULT".to_string())];
712
713 let result = sut.customers().list(input).await;
714
715 assert!(result.is_ok());
716 println!("{:?}", result.unwrap())
717 }
718
719 #[tokio::test]
720 async fn test_customer_builder() {
721 let expected = Customer {
722 id: None,
723 birthday: Some("1996-11-02".to_string()),
724 address: Some(Address{
725 address_line_1: Some("1234 Hillborrow Rd.".to_string()),
726 address_line_2: None,
727 address_line_3: None,
728 locality: Some("Charleston".to_string()),
729 sublocality: None,
730 administrative_district_level: Some("MA".to_string()),
731 postal_code: Some("12345".to_string()),
732 country: Some("United States".to_string())
733 }),
734 company_name: None,
735 created_at: None,
736 creation_source: None,
737 updated_at: None,
738 email_address: None,
739 family_name: Some("Ramsey".to_string()),
740 given_name: Some("Pierre".to_string()),
741 group_ids: None,
742 nickname: None,
743 note: None,
744 phone_number: Some("123-456-7890".to_string()),
745 preferences: None,
746 reference_id: None,
747 segment_ids: None,
748 tax_ids: None,
749 version: None,
750 cards: None,
751 idempotency_key: None
752 };
753
754 let address = Address{
755 address_line_1: Some("1234 Hillborrow Rd.".to_string()),
756 address_line_2: None,
757 address_line_3: None,
758 locality: Some("Charleston".to_string()),
759 sublocality: None,
760 administrative_district_level: Some("MA".to_string()),
761 postal_code: Some("12345".to_string()),
762 country: Some("United States".to_string())
763 };
764
765 let mut actual = Builder::from(Customer::default())
766 .address_from_address(address)
767 .given_name("Pierre".to_string())
768 .family_name("Ramsey".to_string())
769 .phone_number("123-456-7890".to_string())
770 .phone_number("123-456-7890".to_string())
771 .birthday("1996-11-02".to_string())
772 .build();
773
774 assert!(actual.is_ok());
775
776 actual.as_mut().unwrap().idempotency_key = None;
777
778 assert_eq!(format!("{:?}", expected), format!("{:?}", actual.unwrap()))
779 }
780
781 async fn test_create_customer() {
783 use dotenv::dotenv;
784 use std::env;
785
786 dotenv().ok();
787 let access_token = env::var("ACCESS_TOKEN").expect("ACCESS_TOKEN to be set");
788 let sut = SquareClient::new(&access_token);
789
790 let input = Builder::from(Customer::default())
791 .given_name("Boyd".to_string())
792 .nickname("the coolest".to_string())
793 .build().unwrap();
794
795 let result = sut.customers().create(input).await;
796
797 assert!(result.is_ok());
798 println!("{:?}", result.unwrap())
799 }
800
801 #[tokio::test]
802 async fn test_customer_delete_builder() {
803 let expected = CustomerDelete {
804 customer_id: Some("dew212ewfd32123ca".to_string()),
805 version: None
806 };
807
808 let actual = Builder::from(CustomerDelete::default())
809 .customer_id("dew212ewfd32123ca".to_string())
810 .build();
811
812 assert!(actual.is_ok());
813 assert_eq!(format!("{:?}", expected), format!("{:?}", actual.unwrap()))
814 }
815
816 async fn test_delete_customer() {
818 use dotenv::dotenv;
819 use std::env;
820
821 dotenv().ok();
822 let access_token = env::var("ACCESS_TOKEN").expect("ACCESS_TOKEN to be set");
823 let sut = SquareClient::new(&access_token);
824
825 let input = CustomerDelete {
826 customer_id: Some("WPGEDT7V38Y318JVGZ1G1C39W4".to_string()),
827 version: None
828 };
829
830 let res = sut.customers().delete(input).await;
831
832 assert!(res.is_ok());
833 }
834
835 #[tokio::test]
836 async fn test_customer_search_query_builder() {
837 let expected = CustomerSearchQuery {
838 cursor: None,
839 limit: Some(5),
840 query: Some(SearchQueryAttribute {
841 filter: Some(CustomerFilter {
842 created_at: Some(TimeRange {
843 end_at: Some("2022-01-23T20:21:54.859Z".to_string()),
844 start_at: Some("2018-01-23T20:21:54.859Z".to_string())
845 }),
846 creation_source: Some(CreationSource {
847 rule: Some("EXCLUDE".to_string()),
848 values: Some(vec![CustomerCreationSource::Appointments,
849 CustomerCreationSource::Coupon])
850 }),
851 email_address: Some(CustomerTextFilter {
852 exact: Some("emil.k.hofstetter@gmail.com".to_string()),
853 fuzzy: Some("3umel.us@gmail.com".to_string())
854 }),
855 group_ids: None,
856 phone_number: Some(CustomerTextFilter {
857 exact: Some("571-694-6282".to_string()),
858 fuzzy: Some("0176-47-85-993".to_string())
859 }),
860 reference_id: Some(CustomerTextFilter {
861 exact: Some("cmiw9u209md82".to_string()),
862 fuzzy: Some("432mi23cß2".to_string())
863 }),
864 updated_at: None
865 }),
866 sort: None
867 })
868 };
869
870 let actual = Builder::from(CustomerSearchQuery::default())
871 .limit(5).limit(1001).created_at(
872 "2018-01-23T20:21:54.859Z".to_string(),
873 "2022-01-23T20:21:54.859Z".to_string(),
874 ).fuzzy_email_address("3umel.us@gmail.com".to_string())
875 .exact_email_address("emil.k.hofstetter@gmail.com".to_string())
876 .exact_phone_number("571-694-6282".to_string())
877 .fuzzy_phone_number("0176-47-85-993".to_string())
878 .fuzzy_reference_id("432mi23cß2".to_string())
879 .exact_reference_id("cmiw9u209md82".to_string())
880 .creation_source_value(CustomerCreationSource::Appointments)
881 .creation_source_value(CustomerCreationSource::Coupon)
882 .creation_source_value(CustomerCreationSource::Appointments)
883 .set_creation_source_exclude()
884 .build();
885
886 assert!(actual.is_ok());
887 assert_eq!(format!("{:?}", expected), format!("{:?}", actual.unwrap()));
888 }
889
890 #[tokio::test]
891 async fn test_search_customers() {
892 use dotenv::dotenv;
893 use std::env;
894
895 dotenv().ok();
896 let access_token = env::var("ACCESS_TOKEN").expect("ACCESS_TOKEN to be set");
897 let sut = SquareClient::new(&access_token);
898
899 let input = CustomerSearchQuery {
900 cursor: None,
901 limit: None,
902 query: Some(SearchQueryAttribute {
903 filter: Some(CustomerFilter {
904 created_at: Some(TimeRange {
905 end_at: None,
906 start_at: None,
907 }),
908 creation_source: Some(CreationSource {
909 rule: Some("INCLUDE".to_string()),
910 values: Some(vec![CustomerCreationSource::Appointments,
911 CustomerCreationSource::ThirdParty]),
912 }),
913 email_address: Some(CustomerTextFilter {
914 exact: None,
915 fuzzy: Some(".co".to_string()),
916 }),
917 group_ids: None,
918 phone_number: Some(CustomerTextFilter {
919 exact: None,
920 fuzzy: None,
921 }),
922 reference_id: Some(CustomerTextFilter {
923 exact: None,
924 fuzzy: None,
925 }),
926 updated_at: None
927 }),
928 sort: None
929 })
930 };
931
932 let result = sut.customers().search(input).await;
933
934 assert!(result.is_ok())
936 }
937}