diff --git a/.gitignore b/.gitignore index c1b65c7..7bd2441 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ coverage.html coverage.json coverage_report.txt .vscode/ -venv \ No newline at end of file +venv +.env/ \ No newline at end of file diff --git a/healthcrm.go b/healthcrm.go index 454cdc8..83632cd 100644 --- a/healthcrm.go +++ b/healthcrm.go @@ -367,3 +367,30 @@ func (h *HealthCRMLib) GetService(ctx context.Context, serviceID string) (*Facil return &service, nil } + +// CreateProfile is used to create profile in health CRM service +func (h *HealthCRMLib) CreateProfile(ctx context.Context, profile *Profile) (*ProfileOutput, error) { + path := "/v1/identities/profiles/" + response, err := h.client.MakeRequest(ctx, http.MethodPost, path, nil, profile) + if err != nil { + return nil, err + } + + respBytes, err := io.ReadAll(response.Body) + if err != nil { + return nil, fmt.Errorf("could not read response: %w", err) + } + + if response.StatusCode != http.StatusCreated { + return nil, errors.New(string(respBytes)) + } + + var profileResponse *ProfileOutput + + err = json.Unmarshal(respBytes, &profileResponse) + if err != nil { + return nil, err + } + + return profileResponse, nil +} diff --git a/healthcrm_test.go b/healthcrm_test.go index 2fbf24b..91a9081 100644 --- a/healthcrm_test.go +++ b/healthcrm_test.go @@ -1199,3 +1199,112 @@ func TestHealthCRMLib_GetService(t *testing.T) { }) } } + +func TestHealthCRMLib_CreateProfile(t *testing.T) { + type args struct { + ctx context.Context + profile *Profile + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Happy Case: Create Profile", + args: args{ + ctx: context.Background(), + profile: &Profile{ + FirstName: "TestProfile", + LastName: "BikoTest", + OtherName: "SteveTest", + DateOfBirth: "", + Gender: "MALE", + EnrolmentDate: "", + SladeCode: "", + ServiceCode: "", + Contacts: []*ProfileContactInput{ + { + ContactType: "PHONE_NUMBER", + ContactValue: "+254788223223", + }, + }, + Identifiers: []*ProfileIdentifierInput{ + { + IdentifierType: "SLADE_CODE", + IdentifierValue: "3243", + }, + }, + }, + }, + wantErr: false, + }, + { + name: "Sad Case: Unable To Create Profile", + args: args{ + ctx: context.Background(), + profile: &Profile{ + FirstName: gofakeit.FirstName(), + LastName: gofakeit.LastName(), + }, + }, + wantErr: true, + }, + { + name: "Sad Case: Unable To Make Request", + args: args{ + ctx: context.Background(), + profile: &Profile{ + FirstName: gofakeit.FirstName(), + LastName: gofakeit.LastName(), + }, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.name == "Happy Case: Create Profile" { + path := fmt.Sprintf("%s/v1/identities/profiles/", BaseURL) + httpmock.RegisterResponder(http.MethodPost, path, func(r *http.Request) (*http.Response, error) { + resp := &ProfileOutput{ + FirstName: gofakeit.FirstName(), + LastName: gofakeit.LastName(), + OtherName: gofakeit.BeerName(), + DateOfBirth: gofakeit.Date().String(), + Gender: gofakeit.Gender(), + EnrolmentDate: gofakeit.Date().String(), + SladeCode: "50202", + ServiceCode: "50", + Contacts: []*ProfileContactOutput{ + { + ContactType: "PHONE_NUMBER", + ContactValue: "+254788223223", + }, + }, + Identifiers: []*ProfileIdentifierOutput{ + { + IdentifierType: "SLADE_CODE", + IdentifierValue: "3243", + }, + }, + } + return httpmock.NewJsonResponse(http.StatusCreated, resp) + }) + } + + httpmock.Activate() + defer httpmock.DeactivateAndReset() + MockAuthenticate() + h, err := NewHealthCRMLib() + if err != nil { + t.Errorf("unable to initialize sdk: %v", err) + } + _, err = h.CreateProfile(tt.args.ctx, tt.args.profile) + if (err != nil) != tt.wantErr { + t.Errorf("HealthCRMLib.CreateProfile() error = %v, wantErr %v", err, tt.wantErr) + return + } + }) + } +} diff --git a/input.go b/input.go index 27fdf71..8d4d4fe 100644 --- a/input.go +++ b/input.go @@ -4,26 +4,26 @@ import "fmt" // Facility is the hospitals data class type Facility struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` - Description string `json:"description,omitempty"` - FacilityType string `json:"facility_type,omitempty"` - County string `json:"county,omitempty"` - Country string `json:"country,omitempty"` - Address string `json:"address,omitempty"` - Coordinates *Coordinates `json:"coordinates,omitempty"` - Contacts []Contacts `json:"contacts,omitempty"` - Identifiers []Identifiers `json:"identifiers,omitempty"` - BusinessHours []BusinessHours `json:"businesshours,omitempty"` + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + FacilityType string `json:"facility_type,omitempty"` + County string `json:"county,omitempty"` + Country string `json:"country,omitempty"` + Address string `json:"address,omitempty"` + Coordinates *Coordinates `json:"coordinates,omitempty"` + Contacts []Contacts `json:"contacts,omitempty"` + Identifiers []Identifiers `json:"identifiers,omitempty"` + BusinessHours []BusinessHours `json:"businesshours,omitempty"` } // Coordinates represents geographical coordinates using latitude and longitude. // Latitude measures the north-south position, while longitude measures // the east-west position. type Coordinates struct { - Latitude string `json:"latitude,omitempty"` - Longitude string `json:"longitude,omitempty"` - Radius string `json:"radius,omitempty"` + Latitude string `json:"latitude,omitempty"` + Longitude string `json:"longitude,omitempty"` + Radius string `json:"radius,omitempty"` } // ToString returns the location in comma-separated values format. @@ -40,41 +40,67 @@ func (c Coordinates) ToString() (string, error) { // Contacts models facility's model data class type Contacts struct { - ContactType string `json:"contact_type,omitempty"` - ContactValue string `json:"contact_value,omitempty"` - Role string `json:"role,omitempty"` -} + ContactType string `json:"contact_type,omitempty"` + ContactValue string `json:"contact_value,omitempty"` + Role string `json:"role,omitempty"` +} // Identifiers models facility's identifiers; can be MFL Code, Slade Code etc... type Identifiers struct { - IdentifierType string `json:"identifier_type,omitempty"` - IdentifierValue string `json:"identifier_value,omitempty"` - ValidFrom string `json:"valid_from,omitempty"` - ValidTo string `json:"valid_to,omitempty"` + IdentifierType string `json:"identifier_type,omitempty"` + IdentifierValue string `json:"identifier_value,omitempty"` + ValidFrom string `json:"valid_from,omitempty"` + ValidTo string `json:"valid_to,omitempty"` } // BusinessHours models data to store business hours type BusinessHours struct { - Day string `json:"day"` - OpeningTime string `json:"opening_time"` - ClosingTime string `json:"closing_time"` + Day string `json:"day"` + OpeningTime string `json:"opening_time"` + ClosingTime string `json:"closing_time"` } // Pagination is used to hold pagination values type Pagination struct { - Page string `json:"page"` - PageSize string `json:"page_size"` + Page string `json:"page"` + PageSize string `json:"page_size"` } // FacilityServiceInput models is used to create a new service type FacilityServiceInput struct { - Name string `json:"name"` - Description string `json:"description"` - Identifiers []*ServiceIdentifierInput `json:"identifiers"` + Name string `json:"name"` + Description string `json:"description"` + Identifiers []*ServiceIdentifierInput `json:"identifiers"` } // ServiceIdentifierInput is used to create an identifier type ServiceIdentifierInput struct { - IdentifierType string `json:"identifier_type"` - IdentifierValue string `json:"identifier_value"` + IdentifierType string `json:"identifier_type"` + IdentifierValue string `json:"identifier_value"` +} + +// Profile is the host of users/client data class +type Profile struct { + FirstName string `json:"first_name"` + LastName string `json:"last_name"` + OtherName string `json:"other_name"` + DateOfBirth string `json:"date_of_birth"` + Gender string `json:"gender"` + EnrolmentDate string `json:"enrolment_date"` + SladeCode string `json:"slade_code"` + ServiceCode string `json:"service_code"` + Contacts []*ProfileContactInput `json:"contacts,omitempty"` + Identifiers []*ProfileIdentifierInput `json:"identifiers,omitempty"` +} + +// ProfileIdentifierInput is used to create profile(s) identifier(s) +type ProfileIdentifierInput struct { + IdentifierValue string `json:"identifier_value"` + IdentifierType string `json:"identifier_type"` +} + +// ProfileContanctInput is used to create profile(s) contancts) +type ProfileContactInput struct { + ContactType string `json:"contact_type"` + ContactValue string `json:"contact_value"` } diff --git a/output.go b/output.go index a1b2a7c..571c404 100644 --- a/output.go +++ b/output.go @@ -4,96 +4,132 @@ import "time" // FacilityPage is the hospitals model used to show facility details type FacilityPage struct { - Count int `json:"count"` - Next string `json:"next"` - Previous any `json:"previous"` - PageSize int `json:"page_size"` - CurrentPage int `json:"current_page"` - TotalPages int `json:"total_pages"` - StartIndex int `json:"start_index"` - EndIndex int `json:"end_index"` - Results []FacilityOutput `json:"results"` + Count int `json:"count"` + Next string `json:"next"` + Previous any `json:"previous"` + PageSize int `json:"page_size"` + CurrentPage int `json:"current_page"` + TotalPages int `json:"total_pages"` + StartIndex int `json:"start_index"` + EndIndex int `json:"end_index"` + Results []FacilityOutput `json:"results"` } // CoordinatesOutput is used to show geographical coordinates type CoordinatesOutput struct { - Latitude float64 `json:"latitude"` - Longitude float64 `json:"longitude"` + Latitude float64 `json:"latitude"` + Longitude float64 `json:"longitude"` } // ContactsOutput is used to show facility contacts type ContactsOutput struct { - ID string `json:"id"` - ContactType string `json:"contact_type"` - ContactValue string `json:"contact_value"` - Active bool `json:"active"` - Role string `json:"role"` - FacilityID string `json:"facility_id"` + ID string `json:"id"` + ContactType string `json:"contact_type"` + ContactValue string `json:"contact_value"` + Active bool `json:"active"` + Role string `json:"role"` + FacilityID string `json:"facility_id"` } // IdentifiersOutput is used to display facility identifiers type IdentifiersOutput struct { - ID string `json:"id"` - IdentifierType string `json:"identifier_type"` - IdentifierValue string `json:"identifier_value"` - ValidFrom string `json:"valid_from"` - ValidTo string `json:"valid_to"` - FacilityID string `json:"facility_id"` + ID string `json:"id"` + IdentifierType string `json:"identifier_type"` + IdentifierValue string `json:"identifier_value"` + ValidFrom string `json:"valid_from"` + ValidTo string `json:"valid_to"` + FacilityID string `json:"facility_id"` } // FacilityOutput is used to display facility(ies) type FacilityOutput struct { - ID string `json:"id,omitempty"` - Created time.Time `json:"created,omitempty"` - Name string `json:"name,omitempty"` - Description string `json:"description,omitempty"` - FacilityType string `json:"facility_type,omitempty"` - County string `json:"county,omitempty"` - Country string `json:"country,omitempty"` - Coordinates CoordinatesOutput `json:"coordinates,omitempty"` - Distance float64 `json:"distance,omitempty"` - Status string `json:"status,omitempty"` - Address string `json:"address,omitempty"` - Contacts []ContactsOutput `json:"contacts,omitempty"` - Identifiers []IdentifiersOutput `json:"identifiers,omitempty"` - BusinessHours []BusinessHoursOutput `json:"businesshours,omitempty"` - Services []FacilityService `json:"services,omitempty"` + ID string `json:"id,omitempty"` + Created time.Time `json:"created,omitempty"` + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + FacilityType string `json:"facility_type,omitempty"` + County string `json:"county,omitempty"` + Country string `json:"country,omitempty"` + Coordinates CoordinatesOutput `json:"coordinates,omitempty"` + Distance float64 `json:"distance,omitempty"` + Status string `json:"status,omitempty"` + Address string `json:"address,omitempty"` + Contacts []ContactsOutput `json:"contacts,omitempty"` + Identifiers []IdentifiersOutput `json:"identifiers,omitempty"` + BusinessHours []BusinessHoursOutput `json:"businesshours,omitempty"` + Services []FacilityService `json:"services,omitempty"` } // BusinessHoursOutput models data that show facility's operational hours type BusinessHoursOutput struct { - ID string `json:"id"` - Day string `json:"day"` - OpeningTime string `json:"opening_time"` - ClosingTime string `json:"closing_time"` - FacilityID string `json:"facility_id"` + ID string `json:"id"` + Day string `json:"day"` + OpeningTime string `json:"opening_time"` + ClosingTime string `json:"closing_time"` + FacilityID string `json:"facility_id"` } // FacilityServicePage models the services offered in a facility type FacilityServicePage struct { - Results []FacilityService `json:"results"` - Count int `json:"count"` - Next string `json:"next"` - Previous string `json:"previous"` - PageSize int `json:"page_size"` - CurrentPage int `json:"current_page"` - TotalPages int `json:"total_pages"` - StartIndex int `json:"start_index"` - EndIndex int `json:"end_index"` + Results []FacilityService `json:"results"` + Count int `json:"count"` + Next string `json:"next"` + Previous string `json:"previous"` + PageSize int `json:"page_size"` + CurrentPage int `json:"current_page"` + TotalPages int `json:"total_pages"` + StartIndex int `json:"start_index"` + EndIndex int `json:"end_index"` } // FacilityService models the data class that is used to show facility services type FacilityService struct { - ID string `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - Identifiers []*ServiceIdentifier `json:"identifiers"` + ID string `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + Identifiers []*ServiceIdentifier `json:"identifiers"` } // ServiceIdentifier models the structure of facility's service identifiers type ServiceIdentifier struct { - ID string `json:"id"` - IdentifierType string `json:"identifier_type"` - IdentifierValue string `json:"identifier_value"` - ServiceID string `json:"service_id"` + ID string `json:"id"` + IdentifierType string `json:"identifier_type"` + IdentifierValue string `json:"identifier_value"` + ServiceID string `json:"service_id"` } + +// +// ProfileOutput is used to display profile(s) +type ProfileOutput struct { + ID string `json:"id,omitempty"` + Created string `json:"created,omitempty"` + Active bool `json:"active"` + FirstName string `json:"first_name"` + LastName string `json:"last_name"` + OtherName string `json:"other_name"` + DateOfBirth string `json:"date_of_birth"` + Gender string `json:"gender"` + EnrolmentDate string `json:"enrolment_date"` + SladeCode string `json:"slade_code"` + ServiceCode string `json:"service_code"` + Contacts []*ProfileContactOutput `json:"contacts,omitempty"` + Identifiers []*ProfileIdentifierOutput `json:"identifiers,omitempty"` +} + +// ProfileContactOutput is used to show profile contacts +type ProfileContactOutput struct { + ID string `json:"id"` + ContactType string `json:"contact_type"` + ContactValue string `json:"contact_value"` + DateVerified string `json:"date_verified"` + Verified bool `json:"verifed,omitempty"` +} + +// ProfileIndentifierOutput is used to display profile identifiers +type ProfileIdentifierOutput struct { + ID string `json:"id"` + IdentifierType string `json:"identifier_type"` + IdentifierValue string `json:"identifier_value"` + ValidFrom string `json:"valid_from"` + ValidTo string `json:"valid_to"` +} \ No newline at end of file