From 9327b9577a884e0bfc59fbcfd7cedf6eec95a867 Mon Sep 17 00:00:00 2001 From: Robin Muhia <109961694+robinmuhia@users.noreply.github.com> Date: Wed, 8 May 2024 12:31:45 +0300 Subject: [PATCH] feat: add contact and identifier types (#37) --- enums.go | 112 ++++++++++++++++++++++ enums_test.go | 253 ++++++++++++++++++++++++++++++++++++++++++++++++++ input.go | 12 ++- 3 files changed, 372 insertions(+), 5 deletions(-) create mode 100644 enums.go create mode 100644 enums_test.go diff --git a/enums.go b/enums.go new file mode 100644 index 0000000..0e6b4f5 --- /dev/null +++ b/enums.go @@ -0,0 +1,112 @@ +package healthcrm + +import ( + "fmt" + "io" + "strconv" +) + +type IdentifierType string + +type ContactType string + +const ( + // Identifier types + IdentifierTypeNationalID IdentifierType = "NATIONAL_ID" + IdentifierTypePassportNo IdentifierType = "PASSPORT_NO" + IdentifierTypeMilitaryID IdentifierType = "MILITARY_ID" + IdentifierTypeAlienID IdentifierType = "ALIEN_ID" + IdentifierTypeNHIFNo IdentifierType = "NHIF_NO" + IdentifierTypePatientNo IdentifierType = "PATIENT_NO" + IdentifierTypePayerMemberNo IdentifierType = "PAYER_MEMBER_NO" + IdentifierTypeSmartMemberNo IdentifierType = "SMART_MEMBER_NO" + IdentifierTypeFHIRPatientID IdentifierType = "FHIR_PATIENT_ID" + IdentifierTypeERPCustomerID IdentifierType = "ERP_CUSTOMER_ID" + IdentifierTypeCCCNumber IdentifierType = "CCC_NUMBER" +) + +const ( + ContactTypePhoneNumber ContactType = "PHONE_NUMBER" + ContactTypeEmail ContactType = "EMAIL" +) + +// IsValid returns true if a contact type is valid +func (f ContactType) IsValid() bool { + switch f { + case ContactTypePhoneNumber, ContactTypeEmail: + return true + default: + return false + } +} + +// String converts the contact type enum to a string +func (f ContactType) String() string { + return string(f) +} + +// UnmarshalGQL converts the supplied value to a contact type. +func (f *ContactType) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *f = ContactType(str) + if !f.IsValid() { + return fmt.Errorf("%s is not a valid ContactType type", str) + } + + return nil +} + +// MarshalGQL writes the contact type to the supplied writer +func (f ContactType) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(f.String())) +} + +// IsValid returns true if an identifier type is valid +func (f IdentifierType) IsValid() bool { + switch f { + case + IdentifierTypeNationalID, + IdentifierTypePassportNo, + IdentifierTypeMilitaryID, + IdentifierTypeAlienID, + IdentifierTypeNHIFNo, + IdentifierTypePatientNo, + IdentifierTypePayerMemberNo, + IdentifierTypeSmartMemberNo, + IdentifierTypeFHIRPatientID, + IdentifierTypeERPCustomerID, + IdentifierTypeCCCNumber: + return true + default: + return false + } +} + +// String converts the identifier type enum to a string +func (f IdentifierType) String() string { + return string(f) +} + +// UnmarshalGQL converts the supplied value to an identifier type. +func (f *IdentifierType) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *f = IdentifierType(str) + if !f.IsValid() { + return fmt.Errorf("%s is not a valid IdentifierType type", str) + } + + return nil +} + +// MarshalGQL writes the identifier type to the supplied writer +func (f IdentifierType) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(f.String())) +} diff --git a/enums_test.go b/enums_test.go new file mode 100644 index 0000000..ff85af2 --- /dev/null +++ b/enums_test.go @@ -0,0 +1,253 @@ +package healthcrm + +import ( + "bytes" + "strconv" + "testing" +) + +func TestIdentifierType_String(t *testing.T) { + tests := []struct { + name string + e IdentifierType + want string + }{ + { + name: "happy case: enum to string", + e: IdentifierTypeNationalID, + want: "NATIONAL_ID", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.e.String(); got != tt.want { + t.Errorf("IdentifierType.String() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestIdentifierType_IsValid(t *testing.T) { + tests := []struct { + name string + e IdentifierType + want bool + }{ + { + name: "valid type", + e: IdentifierTypeNationalID, + want: true, + }, + { + name: "invalid type", + e: IdentifierType("invalid"), + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.e.IsValid(); got != tt.want { + t.Errorf("IdentifierType.IsValid() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestIdentifierType_UnmarshalGQL(t *testing.T) { + value := IdentifierTypeNationalID + invalid := IdentifierType("invalid") + + type args struct { + v interface{} + } + + tests := []struct { + name string + e *IdentifierType + args args + wantErr bool + }{ + { + name: "valid type", + e: &value, + args: args{ + v: "NATIONAL_ID", + }, + wantErr: false, + }, + { + name: "invalid type", + e: &invalid, + args: args{ + v: "this is not a valid type", + }, + wantErr: true, + }, + { + name: "non string type", + e: &invalid, + args: args{ + v: 1, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := tt.e.UnmarshalGQL(tt.args.v); (err != nil) != tt.wantErr { + t.Errorf("IdentifierType.UnmarshalGQL() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestIdentifierType_MarshalGQL(t *testing.T) { + w := &bytes.Buffer{} + + tests := []struct { + name string + e IdentifierType + b *bytes.Buffer + wantW string + panic bool + }{ + { + name: "valid type enums", + e: IdentifierTypeNationalID, + b: w, + wantW: strconv.Quote("NATIONAL_ID"), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.e.MarshalGQL(tt.b) + + if gotW := w.String(); gotW != tt.wantW { + t.Errorf("IdentifierType.MarshalGQL() = %v, want %v", gotW, tt.wantW) + } + }) + } +} + +func TestContactType_String(t *testing.T) { + tests := []struct { + name string + e ContactType + want string + }{ + { + name: "happy case: enum to string", + e: ContactTypePhoneNumber, + want: "PHONE_NUMBER", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.e.String(); got != tt.want { + t.Errorf("ContactType.String() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestContactType_IsValid(t *testing.T) { + tests := []struct { + name string + e ContactType + want bool + }{ + { + name: "valid type", + e: ContactTypePhoneNumber, + want: true, + }, + { + name: "invalid type", + e: ContactType("invalid"), + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.e.IsValid(); got != tt.want { + t.Errorf("ContactType.IsValid() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestContactType_UnmarshalGQL(t *testing.T) { + value := ContactTypePhoneNumber + invalid := ContactType("invalid") + + type args struct { + v interface{} + } + + tests := []struct { + name string + e *ContactType + args args + wantErr bool + }{ + { + name: "valid type", + e: &value, + args: args{ + v: "PHONE_NUMBER", + }, + wantErr: false, + }, + { + name: "invalid type", + e: &invalid, + args: args{ + v: "this is not a valid type", + }, + wantErr: true, + }, + { + name: "non string type", + e: &invalid, + args: args{ + v: 1, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := tt.e.UnmarshalGQL(tt.args.v); (err != nil) != tt.wantErr { + t.Errorf("ContactType.UnmarshalGQL() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestContactType_MarshalGQL(t *testing.T) { + w := &bytes.Buffer{} + + tests := []struct { + name string + e ContactType + b *bytes.Buffer + wantW string + panic bool + }{ + { + name: "valid type enums", + e: ContactTypePhoneNumber, + b: w, + wantW: strconv.Quote("PHONE_NUMBER"), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.e.MarshalGQL(tt.b) + + if gotW := w.String(); gotW != tt.wantW { + t.Errorf("ContactType.MarshalGQL() = %v, want %v", gotW, tt.wantW) + } + }) + } +} diff --git a/input.go b/input.go index b895165..1a41276 100644 --- a/input.go +++ b/input.go @@ -1,6 +1,8 @@ package healthcrm -import "fmt" +import ( + "fmt" +) // Facility is the hospitals data class type Facility struct { @@ -96,12 +98,12 @@ type ProfileInput struct { // ProfileIdentifierInput is used to create profile(s) identifier(s) type ProfileIdentifierInput struct { - IdentifierValue string `json:"identifier_value"` - IdentifierType string `json:"identifier_type"` + IdentifierType IdentifierType `json:"identifier_type"` + IdentifierValue string `json:"identifier_value"` } // ProfileContanctInput is used to create profile(s) contact(s) type ProfileContactInput struct { - ContactType string `json:"contact_type"` - ContactValue string `json:"contact_value"` + ContactType ContactType `json:"contact_type"` + ContactValue string `json:"contact_value"` }