Improve validation for address, person and customer. Add IsComlete() functions for each and TrimSpace() for address and person // update tests

This commit is contained in:
Florian Schlegel
2020-07-22 12:56:11 +02:00
parent 99f2489ea8
commit 9e4d49d9b0
6 changed files with 161 additions and 62 deletions
+15 -13
View File
@@ -1,5 +1,7 @@
package address
import "strings"
type AddressType string
type ContactType string
type SalutationType string
@@ -52,19 +54,6 @@ type Address struct {
Custom interface{}
}
// Person is a field Customer and of Address
// Only Customer->Person has Contacts
type Person struct {
FirstName string
MiddleName string
LastName string
Title TitleType
Salutation SalutationType
Birthday string
Contacts map[string]*Contact // key must be contactID
DefaultContacts map[ContactType]string // reference by contactID
}
func (address *Address) GetID() string {
return address.Id
}
@@ -97,3 +86,16 @@ func (address *Address) Equals(otherAddress *Address) bool {
return equal
}
func (address *Address) TrimSpace() {
if address == nil {
return
}
address.Person.TrimSpace()
address.Street = strings.TrimSpace(address.Street)
address.StreetNumber = strings.TrimSpace(address.StreetNumber)
address.ZIP = strings.TrimSpace(address.ZIP)
address.City = strings.TrimSpace(address.City)
address.Country = strings.TrimSpace(address.Country)
address.CountryCode = strings.TrimSpace(address.CountryCode)
}
+30
View File
@@ -0,0 +1,30 @@
package address
import (
"strings"
)
// Person is a field Customer and of Address
// Only Customer->Person has Contacts
type Person struct {
FirstName string
MiddleName string
LastName string
Title TitleType
Salutation SalutationType
Birthday string
Contacts map[string]*Contact // key must be contactID
DefaultContacts map[ContactType]string // reference by contactID
}
func (person *Person) TrimSpace() {
if person == nil {
return
}
person.FirstName = strings.TrimSpace(person.FirstName)
person.MiddleName = strings.TrimSpace(person.MiddleName)
person.LastName = strings.TrimSpace(person.LastName)
person.Title = TitleType(strings.TrimSpace(string(person.Title)))
person.Salutation = SalutationType(strings.TrimSpace(string(person.Salutation)))
person.Birthday = strings.TrimSpace(person.Birthday)
}
+63
View File
@@ -0,0 +1,63 @@
package address
import (
"errors"
"github.com/hashicorp/go-multierror"
)
func (addr *Address) IsComplete() error {
addr.TrimSpace()
// Return error if required field is missing
var mErr *multierror.Error
if addr == nil {
mErr = multierror.Append(mErr, errors.New("address is nil"))
return mErr.ErrorOrNil()
}
errPerson := addr.Person.IsComplete()
if errPerson != nil {
mErr = multierror.Append(mErr, errPerson)
}
if addr.Street == "" {
mErr = multierror.Append(mErr, errors.New("address street is empty"))
}
if addr.StreetNumber == "" {
mErr = multierror.Append(mErr, errors.New("address street number is empty"))
}
if len(addr.ZIP) < 4 {
mErr = multierror.Append(mErr, errors.New("address zip is not valid"))
}
if addr.City == "" {
mErr = multierror.Append(mErr, errors.New("address city is empty"))
}
if addr.Country == "" {
mErr = multierror.Append(mErr, errors.New("address country is empty"))
}
if addr.CountryCode == "" {
mErr = multierror.Append(mErr, errors.New("address country code is empty"))
}
return mErr.ErrorOrNil()
}
func (person *Person) IsComplete() error {
var mErr *multierror.Error
if person == nil {
mErr = multierror.Append(mErr, errors.New("person is nil"))
return mErr.ErrorOrNil()
}
person.TrimSpace()
if person.Salutation == "" {
mErr = multierror.Append(mErr, errors.New("person salutation is empty"))
}
if person.FirstName == "" {
mErr = multierror.Append(mErr, errors.New("person firstname is empty"))
}
if person.LastName == "" {
mErr = multierror.Append(mErr, errors.New("person lastname is empty"))
}
return mErr.ErrorOrNil()
}
+2 -41
View File
@@ -61,7 +61,6 @@ type Customer struct {
Email string // unique, used as Login Credential
Person *address.Person
IsGuest bool
IsComplete bool // upsert checks if customer data is complete, so that a customer could place an order
Company *Company
Addresses []*address.Address
Localization *Localization
@@ -189,44 +188,6 @@ func (customer *Customer) OverrideId(id string) error {
return customer.Upsert()
}
// checkFields Checks if all required fields are specified
// @TODO which are teh required fields
func CheckRequiredAddressFields(address *address.Address) error {
// Return error if required field is missing
var mErr *multierror.Error
if address.Person == nil {
mErr = multierror.Append(mErr, errors.New("required person is nil"))
} else {
if address.Person.Salutation == "" {
mErr = multierror.Append(mErr, errors.New("required person salutation is empty"))
}
if address.Person.FirstName == "" {
mErr = multierror.Append(mErr, errors.New("required person firstname is empty"))
}
if address.Person.LastName == "" {
mErr = multierror.Append(mErr, errors.New("required person lastname is empty"))
}
}
if address.Street == "" {
mErr = multierror.Append(mErr, errors.New("required address street is empty"))
}
if address.StreetNumber == "" {
mErr = multierror.Append(mErr, errors.New("required address street number is empty"))
}
if address.ZIP == "" {
mErr = multierror.Append(mErr, errors.New("required address zip is empty"))
}
if address.City == "" {
mErr = multierror.Append(mErr, errors.New("required address city is empty"))
}
if address.Country == "" {
mErr = multierror.Append(mErr, errors.New("required address country is empty"))
}
return mErr.ErrorOrNil()
}
func (customer *Customer) AddDefaultBillingAddress(addr *address.Address) (string, error) {
addr.Type = address.AddressDefaultBilling
return customer.AddAddress(addr)
@@ -239,7 +200,7 @@ func (customer *Customer) AddDefaultShippingAddress(addr *address.Address) (stri
// AddAddress adds a new address to the customers profile and returns its unique id
func (customer *Customer) AddAddress(addr *address.Address) (string, error) {
err := CheckRequiredAddressFields(addr)
err := addr.IsComplete()
if err != nil {
log.Println("Error", err)
return "", err
@@ -307,7 +268,7 @@ func (customer *Customer) ChangeAddress(addr *address.Address) error {
log.Println("Error: Could not find address with id "+addr.GetID(), "for customer ", customer.Person.LastName)
return err
}
err = CheckRequiredAddressFields(addr)
err = addr.IsComplete()
if err != nil {
return err
}
+12 -8
View File
@@ -149,7 +149,8 @@ func TestCustomerChangeAddress(t *testing.T) {
Street: "Holzweg",
StreetNumber: "5",
City: "Bern",
Country: "CH",
Country: "Schweiz",
CountryCode: "CH",
ZIP: "1234",
}
log.Println("Original Address:")
@@ -170,7 +171,8 @@ func TestCustomerChangeAddress(t *testing.T) {
Street: "Steinweg",
StreetNumber: "5",
City: "Bern",
Country: "CH",
Country: "Schweiz",
CountryCode: "CH",
ZIP: "1234",
}
err = customer.ChangeAddress(addressNew)
@@ -193,7 +195,7 @@ func TestCustomerChangeAddress(t *testing.T) {
}
}
func TestCheckRequiredAddressFields(t *testing.T) {
func TestAddressComplete(t *testing.T) {
type args struct {
address *address.Address
}
@@ -207,7 +209,7 @@ func TestCheckRequiredAddressFields(t *testing.T) {
args: args{
address: &address.Address{},
},
wantErr: "6 errors occurred:\n\t* required person is nil\n\t* required address street is empty\n\t* required address street number is empty\n\t* required address zip is empty\n\t* required address city is empty\n\t* required address country is empty\n\n",
wantErr: "7 errors occurred:\n\t* person is nil\n\t* address street is empty\n\t* address street number is empty\n\t* address zip is not valid\n\t* address city is empty\n\t* address country is empty\n\t* address country code is empty\n\n",
},
{
name: "all person fields empty",
@@ -216,12 +218,13 @@ func TestCheckRequiredAddressFields(t *testing.T) {
Person: &address.Person{},
Street: "x",
StreetNumber: "x",
ZIP: "x",
ZIP: "xxxx",
City: "x",
Country: "x",
CountryCode: "x",
},
},
wantErr: "3 errors occurred:\n\t* required person salutation is empty\n\t* required person firstname is empty\n\t* required person lastname is empty\n\n",
wantErr: "3 errors occurred:\n\t* person salutation is empty\n\t* person firstname is empty\n\t* person lastname is empty\n\n",
},
{
name: "all fields set",
@@ -234,9 +237,10 @@ func TestCheckRequiredAddressFields(t *testing.T) {
},
Street: "x",
StreetNumber: "x",
ZIP: "x",
ZIP: "xxxx",
City: "x",
Country: "x",
CountryCode: "x",
},
},
wantErr: "",
@@ -244,7 +248,7 @@ func TestCheckRequiredAddressFields(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := CheckRequiredAddressFields(tt.args.address)
err := tt.args.address.IsComplete()
if tt.wantErr != "" {
assert.EqualError(t, err, tt.wantErr)
} else {
+39
View File
@@ -0,0 +1,39 @@
package customer
import (
"fmt"
"strings"
"github.com/hashicorp/go-multierror"
)
// IsCustomerComplete returns an error if not all mandatory data is set
func (customer *Customer) IsCustomerComplete() error {
addr, err := customer.GetDefaultBillingAddress()
if err != nil {
return err
}
var mErr *multierror.Error
if e := customer.GetEmail(); !strings.ContainsRune(e, '@') {
mErr = multierror.Append(mErr, fmt.Errorf("invalid email address %q", e))
}
if err := addr.IsComplete(); err != nil {
mErr = multierror.Append(mErr, err)
}
person := customer.GetPerson()
if err := person.IsComplete(); err != nil {
mErr = multierror.Append(mErr, fmt.Errorf("person is not complete"))
}
// Birthday is not part of regular person.IsComplete() check
if person != nil {
if len(person.Birthday) != 10 {
mErr = multierror.Append(mErr, fmt.Errorf("person birthday not valid"))
}
}
return mErr.ErrorOrNil()
}