Repository: moov-io/customers
Pull request #144 (2020-09-10 16:35:11)

Filter customer by type
This PR introduces the ability to search for customers by type. Currently, there are two customer types, INDIVIDUAL and BUSINESS.

adamdecaf: @jmbrown412 I'll fix this up. 

Patch:
diff --git a/api/admin.yaml b/api/admin.yaml
index b0c8c44..2588f49 100644
--- a/api/admin.yaml
+++ b/api/admin.yaml
@@ -196,7 +196,7 @@ components:
     UpdateAccountStatus:
       properties:
         status:
-          $ref: 'https://raw.githubusercontent.com/moov-io/customers/master/openapi.yaml#/components/schemas/AccountStatus'
+          $ref: 'https://raw.githubusercontent.com/moov-io/customers/master/api/client.yaml#/components/schemas/AccountStatus'
       required:
         - status
     CreateUserDisclaimer:
@@ -218,7 +218,7 @@ components:
           description: Free form text for admin users
           example: User submitted address information
         status:
-          $ref: 'https://raw.githubusercontent.com/moov-io/customers/master/openapi.yaml#/components/schemas/CustomerStatus'
+          $ref: 'https://raw.githubusercontent.com/moov-io/customers/master/api/client.yaml#/components/schemas/CustomerStatus'
       required:
         - status
     UpdateCustomerAddress:
diff --git a/api/client.yaml b/api/client.yaml
index 77580b8..46f1418 100644
--- a/api/client.yaml
+++ b/api/client.yaml
@@ -58,6 +58,12 @@ paths:
           example: Verified
           schema:
             type: string
+        - name: type
+          in: path
+          description: Optional parameter for searching by customer type
+          example: individual
+          schema:
+            type: string
         - name: skip
           in: path
           description: Optional parameter for searching for customers by skipping over an initial group
diff --git a/cmd/server/customer_search.go b/cmd/server/customer_search.go
index dbfc77b..1f2e737 100644
--- a/cmd/server/customer_search.go
+++ b/cmd/server/customer_search.go
@@ -43,6 +43,7 @@ type searchParams struct {
 	Query  string
 	Email  string
 	Status string
+	Type   string
 	Skip   int64
 	Count  int64
 }
@@ -52,6 +53,7 @@ func readSearchParams(r *http.Request) (searchParams, error) {
 		Query:  strings.ToLower(strings.TrimSpace(r.URL.Query().Get("query"))),
 		Email:  strings.ToLower(strings.TrimSpace(r.URL.Query().Get("email"))),
 		Status: strings.ToLower(strings.TrimSpace(r.URL.Query().Get("status"))),
+		Type:   strings.ToLower(strings.TrimSpace(r.URL.Query().Get("type"))),
 	}
 	skip, count, exists, err := moovhttp.GetSkipAndCount(r)
 	if exists && err != nil {
@@ -113,6 +115,10 @@ func buildSearchQuery(params searchParams) (string, []interface{}) {
 		query += " and status like ?"
 		args = append(args, "%"+params.Status)
 	}
+	if params.Type != "" {
+		query += " and type like ?"
+		args = append(args, "%"+params.Type)
+	}
 	query += " order by created_at asc limit ?"
 	args = append(args, fmt.Sprintf("%d", params.Count))
 
diff --git a/pkg/client/api/openapi.yaml b/pkg/client/api/openapi.yaml
index 02d5b00..755d5bc 100644
--- a/pkg/client/api/openapi.yaml
+++ b/pkg/client/api/openapi.yaml
@@ -63,6 +63,15 @@ paths:
         schema:
           type: string
         style: simple
+      - description: Optional parameter for searching by customer type
+        example: individual
+        explode: false
+        in: path
+        name: type
+        required: false
+        schema:
+          type: string
+        style: simple
       - description: Optional parameter for searching for customers by skipping over
           an initial group
         example: 10
diff --git a/pkg/client/api_customers.go b/pkg/client/api_customers.go
index 0ec6487..5438c83 100644
--- a/pkg/client/api_customers.go
+++ b/pkg/client/api_customers.go
@@ -1534,11 +1534,12 @@ Search for customers using different filter parameters
  * @param query Optional parameter for searching by customer name
  * @param email Optional parameter for searching by customer email
  * @param status Optional parameter for searching by customer status
+ * @param type_ Optional parameter for searching by customer type
  * @param skip Optional parameter for searching for customers by skipping over an initial group
  * @param count Optional parameter for searching for customers by specifying the amount to return
 @return []Customer
 */
-func (a *CustomersApiService) SearchCustomers(ctx _context.Context, query string, email string, status string, skip string, count string) ([]Customer, *_nethttp.Response, error) {
+func (a *CustomersApiService) SearchCustomers(ctx _context.Context, query string, email string, status string, type_ string, skip string, count string) ([]Customer, *_nethttp.Response, error) {
 	var (
 		localVarHTTPMethod   = _nethttp.MethodGet
 		localVarPostBody     interface{}
@@ -1556,6 +1557,8 @@ func (a *CustomersApiService) SearchCustomers(ctx _context.Context, query string
 
 	localVarPath = strings.Replace(localVarPath, "{"+"status"+"}", _neturl.QueryEscape(parameterToString(status, "")), -1)
 
+	localVarPath = strings.Replace(localVarPath, "{"+"type"+"}", _neturl.QueryEscape(parameterToString(type_, "")), -1)
+
 	localVarPath = strings.Replace(localVarPath, "{"+"skip"+"}", _neturl.QueryEscape(parameterToString(skip, "")), -1)
 
 	localVarPath = strings.Replace(localVarPath, "{"+"count"+"}", _neturl.QueryEscape(parameterToString(count, "")), -1)
diff --git a/pkg/client/docs/CustomersApi.md b/pkg/client/docs/CustomersApi.md
index 6cbc1c3..6ac0e89 100644
--- a/pkg/client/docs/CustomersApi.md
+++ b/pkg/client/docs/CustomersApi.md
@@ -714,7 +714,7 @@ No authorization required
 
 ## SearchCustomers
 
-> []Customer SearchCustomers(ctx, query, email, status, skip, count)
+> []Customer SearchCustomers(ctx, query, email, status, type_, skip, count)
 
 Get customers
 
@@ -729,6 +729,7 @@ Name | Type | Description  | Notes
 **query** | **string**| Optional parameter for searching by customer name | 
 **email** | **string**| Optional parameter for searching by customer email | 
 **status** | **string**| Optional parameter for searching by customer status | 
+**type_** | **string**| Optional parameter for searching by customer type | 
 **skip** | **string**| Optional parameter for searching for customers by skipping over an initial group | 
 **count** | **string**| Optional parameter for searching for customers by specifying the amount to return | 
 


Test patch:
diff --git a/cmd/server/customer_search_scope_test.go b/cmd/server/customer_search_scope_test.go
index 1968ed9..37b9d17 100644
--- a/cmd/server/customer_search_scope_test.go
+++ b/cmd/server/customer_search_scope_test.go
@@ -42,7 +42,7 @@ func (scope *Scope) GetCustomers(query string) ([]*client.Customer, error) {
 	return customers, nil
 }
 
-func (scope *Scope) CreateCustomers(count int) []client.Customer {
+func (scope *Scope) CreateCustomers(count int, customerType client.CustomerType) []client.Customer {
 	var customers []client.Customer
 	for i := 0; i < count; i++ {
 		var firstName string
@@ -51,17 +51,18 @@ func (scope *Scope) CreateCustomers(count int) []client.Customer {
 		scope.fuzzer.Fuzz(&firstName)
 		scope.fuzzer.Fuzz(&lastName)
 		scope.fuzzer.Fuzz(&email)
-		customer := scope.CreateCustomer(firstName, lastName, email)
+		customer := scope.CreateCustomer(firstName, lastName, email, customerType)
 		customers = append(customers, customer)
 	}
 	return customers
 }
 
-func (scope *Scope) CreateCustomer(firstName, lastName, email string) client.Customer {
+func (scope *Scope) CreateCustomer(firstName, lastName, email string, customerType client.CustomerType) client.Customer {
 	cust, _, _ := (customerRequest{
 		FirstName: firstName,
 		LastName:  lastName,
 		Email:     email,
+		Type:      customerType,
 	}).asCustomer(testCustomerSSNStorage(scope.t))
 	if err := scope.customerRepo.createCustomer(cust); err != nil {
 		scope.t.Error(err)
diff --git a/cmd/server/customer_search_test.go b/cmd/server/customer_search_test.go
index a86332b..140b003 100644
--- a/cmd/server/customer_search_test.go
+++ b/cmd/server/customer_search_test.go
@@ -145,28 +145,28 @@ func TestCustomerSearch__query(t *testing.T) {
 
 func TestGet20MostRecentlyCreatedCustomersByDefault(t *testing.T) {
 	scope := Setup(t)
-	scope.CreateCustomers(100)
+	scope.CreateCustomers(100, client.INDIVIDUAL)
 	customers, _ := scope.GetCustomers("")
 	scope.assert.Equal(20, len(customers))
 }
 
 func TestGet10MostRecentlyCreatedCustomersByDefault(t *testing.T) {
 	scope := Setup(t)
-	scope.CreateCustomers(10)
+	scope.CreateCustomers(10, client.INDIVIDUAL)
 	customers, _ := scope.GetCustomers("")
 	scope.assert.Equal(10, len(customers))
 }
 
 func TestGet50MostRecentlyCreatedCustomersWhenSpecifyingLimit(t *testing.T) {
 	scope := Setup(t)
-	scope.CreateCustomers(100)
+	scope.CreateCustomers(100, client.INDIVIDUAL)
 	customers, _ := scope.GetCustomers("?count=50")
 	scope.assert.Equal(50, len(customers))
 }
 
 func TestGet100MostRecentlyCreatedCustomersWhenSpecifyingMoreThanAvailable(t *testing.T) {
 	scope := Setup(t)
-	scope.CreateCustomers(100)
+	scope.CreateCustomers(100, client.INDIVIDUAL)
 	customers, _ := scope.GetCustomers("?count=120")
 	scope.assert.Equal(100, len(customers))
 }
@@ -174,7 +174,7 @@ func TestGet100MostRecentlyCreatedCustomersWhenSpecifyingMoreThanAvailable(t *te
 func TestGetCustomersWithVerifiedStatus(t *testing.T) {
 	// Create two customers. 1 with Unknown STATUS and 1 with Verified
 	scope := Setup(t)
-	scope.CreateCustomers(2)
+	scope.CreateCustomers(2, client.INDIVIDUAL)
 	customers, _ := scope.GetCustomers("?count=120")
 	scope.assert.Equal(2, len(customers))
 	for i := 0; i < len(customers); i++ {
@@ -203,8 +203,8 @@ func TestGetCustomersWithVerifiedStatus(t *testing.T) {
 
 func TestGetCustomersByName(t *testing.T) {
 	scope := Setup(t)
-	_ = scope.CreateCustomer("Jane", "Doe", "jane.doe@gmail.com")
-	_ = scope.CreateCustomer("John", "Doe", "jane.doe@gmail.com")
+	_ = scope.CreateCustomer("Jane", "Doe", "jane.doe@gmail.com", client.INDIVIDUAL)
+	_ = scope.CreateCustomer("John", "Doe", "jane.doe@gmail.com", client.INDIVIDUAL)
 
 	customers, _ := scope.GetCustomers("?query=jane")
 	scope.assert.Equal(1, len(customers))
@@ -227,8 +227,8 @@ func TestGetCustomersByName(t *testing.T) {
 
 func TestGetCustomersByEmail(t *testing.T) {
 	scope := Setup(t)
-	_ = scope.CreateCustomer("Jane", "Doe", "jane.doe@gmail.com")
-	_ = scope.CreateCustomer("John", "Doe", "john.doe@gmail.com")
+	_ = scope.CreateCustomer("Jane", "Doe", "jane.doe@gmail.com", client.INDIVIDUAL)
+	_ = scope.CreateCustomer("John", "Doe", "john.doe@gmail.com", client.INDIVIDUAL)
 
 	customers, _ := scope.GetCustomers("?email=jane.doe@gmail.com")
 	scope.assert.Equal(1, len(customers))
@@ -242,8 +242,8 @@ func TestGetCustomersByEmail(t *testing.T) {
 
 func TestGetCustomersByNameAndEmail(t *testing.T) {
 	scope := Setup(t)
-	_ = scope.CreateCustomer("Jane", "Doe", "jane.doe@gmail.com")
-	_ = scope.CreateCustomer("John", "Doe", "john.doe@gmail.com")
+	_ = scope.CreateCustomer("Jane", "Doe", "jane.doe@gmail.com", client.INDIVIDUAL)
+	_ = scope.CreateCustomer("John", "Doe", "john.doe@gmail.com", client.INDIVIDUAL)
 
 	customers, _ := scope.GetCustomers("?query=jane+doe&email=jane.doe@gmail.com")
 	scope.assert.Equal(1, len(customers))
@@ -269,7 +269,7 @@ func TestGetCustomersByNameAndEmail(t *testing.T) {
 
 func TestGetCustomersUsingPaging(t *testing.T) {
 	scope := Setup(t)
-	_ = scope.CreateCustomers(30)
+	_ = scope.CreateCustomers(30, client.INDIVIDUAL)
 
 	// Get first page of 10
 	customers, _ := scope.GetCustomers("?skip=0&count=10")
@@ -290,7 +290,7 @@ func TestGetCustomersUsingPaging(t *testing.T) {
 
 func TestGetCustomersUsingPagingFailure(t *testing.T) {
 	scope := Setup(t)
-	_ = scope.CreateCustomers(30)
+	_ = scope.CreateCustomers(30, client.INDIVIDUAL)
 
 	customers, _ := scope.GetCustomers("?skip=123abc")
 	scope.assert.Equal(0, len(customers))
@@ -301,3 +301,15 @@ func TestGetCustomersUsingPagingFailure(t *testing.T) {
 	customers, _ = scope.GetCustomers("?skip=123abc&count=123abc")
 	scope.assert.Equal(0, len(customers))
 }
+
+func TestGetCustomersByType(t *testing.T) {
+	scope := Setup(t)
+	_ = scope.CreateCustomers(10, client.INDIVIDUAL)
+	_ = scope.CreateCustomers(20, client.BUSINESS)
+
+	individualCustomers, _ := scope.GetCustomers("?type=individual")
+	scope.assert.Equal(10, len(individualCustomers))
+
+	businessCustomers, _ := scope.GetCustomers("?type=business")
+	scope.assert.Equal(20, len(businessCustomers))
+}