From f702051cae4a210b42ae4e2385ffe43ff3ad902f Mon Sep 17 00:00:00 2001 From: Muchogo Date: Mon, 27 Mar 2023 13:42:47 +0300 Subject: [PATCH] feat: list patient conditions --- pkg/clinical/application/dto/input.go | 1 - pkg/clinical/domain/condition.go | 5 +- .../cloudhealthcare/mock/fhir_mock.go | 45 ++++- .../presentation/graph/clinical.graphql | 3 + .../presentation/graph/clinical.resolvers.go | 16 ++ .../presentation/graph/generated/generated.go | 187 +++++++++++++++++- .../presentation/graph/inputs.graphql | 1 - pkg/clinical/usecases/clinical/condition.go | 70 +++++-- .../usecases/clinical/condition_test.go | 100 +++++++++- pkg/clinical/usecases/usecases.go | 1 + 10 files changed, 391 insertions(+), 38 deletions(-) diff --git a/pkg/clinical/application/dto/input.go b/pkg/clinical/application/dto/input.go index 967dff82..9d55a2ec 100644 --- a/pkg/clinical/application/dto/input.go +++ b/pkg/clinical/application/dto/input.go @@ -60,7 +60,6 @@ type ConditionInput struct { Code string `json:"condition"` System string `json:"system"` Status ConditionStatus `json:"status"` - PatientID string `json:"patientID"` EncounterID string `json:"encounterID"` Note string `json:"note"` OnsetDate *scalarutils.Date `json:"onsetDate"` diff --git a/pkg/clinical/domain/condition.go b/pkg/clinical/domain/condition.go index f8c07f6f..5cf262f9 100644 --- a/pkg/clinical/domain/condition.go +++ b/pkg/clinical/domain/condition.go @@ -238,9 +238,8 @@ type FHIRConditionStageInput struct { // FHIRConditionRelayConnection is a Relay connection for Condition type FHIRConditionRelayConnection struct { - Edges []*FHIRConditionRelayEdge `json:"edges,omitempty"` - - PageInfo *firebasetools.PageInfo `json:"pageInfo,omitempty"` + Edges []*FHIRConditionRelayEdge `json:"edges,omitempty"` + PageInfo *firebasetools.PageInfo `json:"pageInfo,omitempty"` } // FHIRConditionRelayEdge is a Relay edge for Condition diff --git a/pkg/clinical/infrastructure/datastore/cloudhealthcare/mock/fhir_mock.go b/pkg/clinical/infrastructure/datastore/cloudhealthcare/mock/fhir_mock.go index 264cd8c5..a308d299 100644 --- a/pkg/clinical/infrastructure/datastore/cloudhealthcare/mock/fhir_mock.go +++ b/pkg/clinical/infrastructure/datastore/cloudhealthcare/mock/fhir_mock.go @@ -391,7 +391,50 @@ func NewFHIRMock() *FHIRMock { return true, nil }, MockSearchFHIRConditionFn: func(ctx context.Context, params map[string]interface{}, tenant dto.TenantIdentifiers) (*domain.FHIRConditionRelayConnection, error) { - return &domain.FHIRConditionRelayConnection{}, nil + id := gofakeit.UUID() + statusSystem := scalarutils.URI("http://terminology.hl7.org/CodeSystem/condition-clinical") + status := "inactive" + uri := scalarutils.URI("1234567345") + + return &domain.FHIRConditionRelayConnection{ + Edges: []*domain.FHIRConditionRelayEdge{ + { + Node: &domain.FHIRCondition{ + ID: &id, + Text: &domain.FHIRNarrative{}, + Identifier: []*domain.FHIRIdentifier{}, + ClinicalStatus: &domain.FHIRCodeableConcept{ + Coding: []*domain.FHIRCoding{ + { + System: &statusSystem, + Code: scalarutils.Code(string(status)), + Display: string(status), + }, + }, + Text: string(status), + }, + Code: &domain.FHIRCodeableConcept{ + Coding: []*domain.FHIRCoding{ + { + System: &uri, + Code: scalarutils.Code("1234"), + Display: "1234567", + }, + }, + Text: "1234", + }, + OnsetDateTime: &scalarutils.Date{}, + RecordedDate: &scalarutils.Date{}, + Subject: &domain.FHIRReference{ + ID: &id, + }, + Encounter: &domain.FHIRReference{ + ID: &id, + }, + }, + }, + }, + }, nil }, MockUpdateFHIRConditionFn: func(ctx context.Context, input domain.FHIRConditionInput) (*domain.FHIRConditionRelayPayload, error) { return &domain.FHIRConditionRelayPayload{}, nil diff --git a/pkg/clinical/presentation/graph/clinical.graphql b/pkg/clinical/presentation/graph/clinical.graphql index 5ed95678..b2ba83f5 100644 --- a/pkg/clinical/presentation/graph/clinical.graphql +++ b/pkg/clinical/presentation/graph/clinical.graphql @@ -4,6 +4,9 @@ extend type Query { getEpisodeOfCare(id: ID!): EpisodeOfCare + # Conditions + listPatientConditions(patientID: ID!): [Condition!]! + # Encounter listPatientEncounters(patientID: String!): [Encounter!]! diff --git a/pkg/clinical/presentation/graph/clinical.resolvers.go b/pkg/clinical/presentation/graph/clinical.resolvers.go index 15261bfc..ad6122e9 100644 --- a/pkg/clinical/presentation/graph/clinical.resolvers.go +++ b/pkg/clinical/presentation/graph/clinical.resolvers.go @@ -6,6 +6,7 @@ package graph import ( "context" + "fmt" "github.com/savannahghi/clinical/pkg/clinical/application/dto" "github.com/savannahghi/clinical/pkg/clinical/presentation/graph/generated" @@ -116,6 +117,11 @@ func (r *queryResolver) GetEpisodeOfCare(ctx context.Context, id string) (*dto.E return r.usecases.GetEpisodeOfCare(ctx, id) } +// ListPatientConditions is the resolver for the listPatientConditions field. +func (r *queryResolver) ListPatientConditions(ctx context.Context, patientID string) ([]*dto.Condition, error) { + panic(fmt.Errorf("not implemented: ListPatientConditions - listPatientConditions")) +} + // ListPatientEncounters is the resolver for the listPatientEncounters field. func (r *queryResolver) ListPatientEncounters(ctx context.Context, patientID string) ([]*dto.Encounter, error) { r.CheckDependencies() @@ -169,3 +175,13 @@ func (r *Resolver) Query() generated.QueryResolver { return &queryResolver{r} } type mutationResolver struct{ *Resolver } type queryResolver struct{ *Resolver } + +// !!! WARNING !!! +// The code below was going to be deleted when updating resolvers. It has been copied here so you have +// one last chance to move it out of harms way if you want. There are two reasons this happens: +// - When renaming or deleting a resolver the old code will be put in here. You can safely delete +// it when you're done. +// - You have helper methods in this file. Move them out to keep these resolver files clean. +func (r *queryResolver) GetPatientConditions(ctx context.Context, patientID string) ([]*dto.Condition, error) { + panic(fmt.Errorf("not implemented: GetPatientConditions - getPatientConditions")) +} diff --git a/pkg/clinical/presentation/graph/generated/generated.go b/pkg/clinical/presentation/graph/generated/generated.go index b2e2bfb9..e3cdba73 100644 --- a/pkg/clinical/presentation/graph/generated/generated.go +++ b/pkg/clinical/presentation/graph/generated/generated.go @@ -390,6 +390,7 @@ type ComplexityRoot struct { GetPatientRespiratoryRateEntries func(childComplexity int, patientID string) int GetPatientTemperatureEntries func(childComplexity int, patientID string) int GetPatientWeightEntries func(childComplexity int, patientID string) int + ListPatientConditions func(childComplexity int, patientID string) int ListPatientEncounters func(childComplexity int, patientID string) int PatientHealthTimeline func(childComplexity int, input dto.HealthTimelineInput) int __resolve__service func(childComplexity int) int @@ -435,6 +436,7 @@ type QueryResolver interface { PatientHealthTimeline(ctx context.Context, input dto.HealthTimelineInput) (*dto.HealthTimeline, error) GetMedicalData(ctx context.Context, patientID string) (*dto.MedicalData, error) GetEpisodeOfCare(ctx context.Context, id string) (*dto.EpisodeOfCare, error) + ListPatientConditions(ctx context.Context, patientID string) ([]*dto.Condition, error) ListPatientEncounters(ctx context.Context, patientID string) ([]*dto.Encounter, error) GetPatientTemperatureEntries(ctx context.Context, patientID string) ([]*dto.Observation, error) GetPatientBloodPressureEntries(ctx context.Context, patientID string) ([]*dto.Observation, error) @@ -2178,6 +2180,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Query.GetPatientWeightEntries(childComplexity, args["patientID"].(string)), true + case "Query.listPatientConditions": + if e.complexity.Query.ListPatientConditions == nil { + break + } + + args, err := ec.field_Query_listPatientConditions_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.ListPatientConditions(childComplexity, args["patientID"].(string)), true + case "Query.listPatientEncounters": if e.complexity.Query.ListPatientEncounters == nil { break @@ -2384,6 +2398,9 @@ var sources = []*ast.Source{ getEpisodeOfCare(id: ID!): EpisodeOfCare + # Conditions + listPatientConditions(patientID: ID!): [Condition!]! + # Encounter listPatientEncounters(patientID: String!): [Encounter!]! @@ -2560,7 +2577,6 @@ input ConditionInput { code: String! system: String! status: ConditionStatus! - patientID: String! encounterID: String! onsetDate: Date @@ -4872,6 +4888,21 @@ func (ec *executionContext) field_Query_getPatientWeightEntries_args(ctx context return args, nil } +func (ec *executionContext) field_Query_listPatientConditions_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 string + if tmp, ok := rawArgs["patientID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("patientID")) + arg0, err = ec.unmarshalNID2string(ctx, tmp) + if err != nil { + return nil, err + } + } + args["patientID"] = arg0 + return args, nil +} + func (ec *executionContext) field_Query_listPatientEncounters_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -15251,6 +15282,83 @@ func (ec *executionContext) fieldContext_Query_getEpisodeOfCare(ctx context.Cont return fc, nil } +func (ec *executionContext) _Query_listPatientConditions(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_listPatientConditions(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().ListPatientConditions(rctx, fc.Args["patientID"].(string)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*dto.Condition) + fc.Result = res + return ec.marshalNCondition2ᚕᚖgithubᚗcomᚋsavannahghiᚋclinicalᚋpkgᚋclinicalᚋapplicationᚋdtoᚐConditionᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_listPatientConditions(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "id": + return ec.fieldContext_Condition_id(ctx, field) + case "status": + return ec.fieldContext_Condition_status(ctx, field) + case "name": + return ec.fieldContext_Condition_name(ctx, field) + case "code": + return ec.fieldContext_Condition_code(ctx, field) + case "system": + return ec.fieldContext_Condition_system(ctx, field) + case "onsetDate": + return ec.fieldContext_Condition_onsetDate(ctx, field) + case "recordedDate": + return ec.fieldContext_Condition_recordedDate(ctx, field) + case "note": + return ec.fieldContext_Condition_note(ctx, field) + case "patientID": + return ec.fieldContext_Condition_patientID(ctx, field) + case "encounterID": + return ec.fieldContext_Condition_encounterID(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Condition", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_listPatientConditions_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return + } + return fc, nil +} + func (ec *executionContext) _Query_listPatientEncounters(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_listPatientEncounters(ctx, field) if err != nil { @@ -18202,7 +18310,7 @@ func (ec *executionContext) unmarshalInputConditionInput(ctx context.Context, ob asMap[k] = v } - fieldsInOrder := [...]string{"code", "system", "status", "patientID", "encounterID", "onsetDate", "note"} + fieldsInOrder := [...]string{"code", "system", "status", "encounterID", "onsetDate", "note"} for _, k := range fieldsInOrder { v, ok := asMap[k] if !ok { @@ -18233,14 +18341,6 @@ func (ec *executionContext) unmarshalInputConditionInput(ctx context.Context, ob if err != nil { return it, err } - case "patientID": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("patientID")) - it.PatientID, err = ec.unmarshalNString2string(ctx, v) - if err != nil { - return it, err - } case "encounterID": var err error @@ -22194,6 +22294,29 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr return ec.OperationContext.RootResolverMiddleware(ctx, innerFunc) } + out.Concurrently(i, func() graphql.Marshaler { + return rrm(innerCtx) + }) + case "listPatientConditions": + field := field + + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_listPatientConditions(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, innerFunc) + } + out.Concurrently(i, func() graphql.Marshaler { return rrm(innerCtx) }) @@ -22864,6 +22987,50 @@ func (ec *executionContext) marshalNCondition2githubᚗcomᚋsavannahghiᚋclini return ec._Condition(ctx, sel, &v) } +func (ec *executionContext) marshalNCondition2ᚕᚖgithubᚗcomᚋsavannahghiᚋclinicalᚋpkgᚋclinicalᚋapplicationᚋdtoᚐConditionᚄ(ctx context.Context, sel ast.SelectionSet, v []*dto.Condition) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNCondition2ᚖgithubᚗcomᚋsavannahghiᚋclinicalᚋpkgᚋclinicalᚋapplicationᚋdtoᚐCondition(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + func (ec *executionContext) marshalNCondition2ᚖgithubᚗcomᚋsavannahghiᚋclinicalᚋpkgᚋclinicalᚋapplicationᚋdtoᚐCondition(ctx context.Context, sel ast.SelectionSet, v *dto.Condition) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { diff --git a/pkg/clinical/presentation/graph/inputs.graphql b/pkg/clinical/presentation/graph/inputs.graphql index d94dc0e8..a39add8e 100644 --- a/pkg/clinical/presentation/graph/inputs.graphql +++ b/pkg/clinical/presentation/graph/inputs.graphql @@ -39,7 +39,6 @@ input ConditionInput { code: String! system: String! status: ConditionStatus! - patientID: String! encounterID: String! onsetDate: Date diff --git a/pkg/clinical/usecases/clinical/condition.go b/pkg/clinical/usecases/clinical/condition.go index 9381cf26..d5e575e4 100644 --- a/pkg/clinical/usecases/clinical/condition.go +++ b/pkg/clinical/usecases/clinical/condition.go @@ -3,6 +3,7 @@ package clinical import ( "context" "fmt" + "github.com/google/uuid" "github.com/savannahghi/clinical/pkg/clinical/application/dto" "github.com/savannahghi/clinical/pkg/clinical/domain" "github.com/savannahghi/scalarutils" @@ -91,21 +92,6 @@ func (c *UseCasesClinicalImpl) CreateCondition(ctx context.Context, input dto.Co } } - patient, err := c.infrastructure.FHIR.GetFHIRPatient(ctx, input.PatientID) - if err != nil { - return nil, err - } - - patientRef := fmt.Sprintf("Patient/%s", *patient.Resource.ID) - patientType := scalarutils.URI("Patient") - - conditionInput.Subject = &domain.FHIRReferenceInput{ - ID: patient.Resource.ID, - Reference: &patientRef, - Display: patient.Resource.Name[0].Text, - Type: &patientType, - } - encounter, err := c.infrastructure.FHIR.GetFHIREncounter(ctx, input.EncounterID) if err != nil { return nil, err @@ -125,6 +111,21 @@ func (c *UseCasesClinicalImpl) CreateCondition(ctx context.Context, input dto.Co Type: &encounterType, } + patient, err := c.infrastructure.FHIR.GetFHIRPatient(ctx, *encounter.Resource.Subject.ID) + if err != nil { + return nil, err + } + + patientRef := fmt.Sprintf("Patient/%s", *patient.Resource.ID) + patientType := scalarutils.URI("Patient") + + conditionInput.Subject = &domain.FHIRReferenceInput{ + ID: patient.Resource.ID, + Reference: &patientRef, + Display: patient.Resource.Name[0].Text, + Type: &patientType, + } + tags, err := c.GetTenantMetaTags(ctx) if err != nil { return nil, err @@ -164,3 +165,42 @@ func mapFHIRConditionToConditionDTO(condition domain.FHIRCondition) *dto.Conditi return &output } + +// ListPatientConditions lists a patients conditions +// TODO: pagination +func (c UseCasesClinicalImpl) ListPatientConditions(ctx context.Context, patientID string) ([]*dto.Condition, error) { + _, err := uuid.Parse(patientID) + if err != nil { + return nil, fmt.Errorf("invalid patient id: %s", patientID) + } + + identifiers, err := c.infrastructure.BaseExtension.GetTenantIdentifiers(ctx) + if err != nil { + return nil, fmt.Errorf("failed to get tenant identifiers from context: %w", err) + } + + patient, err := c.infrastructure.FHIR.GetFHIRPatient(ctx, patientID) + if err != nil { + return nil, err + } + + patientRef := fmt.Sprintf("Patient/%s", *patient.Resource.ID) + params := map[string]interface{}{ + "subject": patientRef, + "_sort": "date", + } + + conditionsResponse, err := c.infrastructure.FHIR.SearchFHIRCondition(ctx, params, *identifiers) + if err != nil { + return nil, err + } + + conditions := []*dto.Condition{} + + for _, edge := range conditionsResponse.Edges { + condition := mapFHIRConditionToConditionDTO(*edge.Node) + conditions = append(conditions, condition) + } + + return conditions, nil +} diff --git a/pkg/clinical/usecases/clinical/condition_test.go b/pkg/clinical/usecases/clinical/condition_test.go index 7cc50060..6b2f65c3 100644 --- a/pkg/clinical/usecases/clinical/condition_test.go +++ b/pkg/clinical/usecases/clinical/condition_test.go @@ -35,7 +35,6 @@ func TestUseCasesClinicalImpl_CreateCondition(t *testing.T) { Code: "386661006", System: "SNOMED", Status: dto.ConditionStatusActive, - PatientID: gofakeit.UUID(), EncounterID: gofakeit.UUID(), Note: "Fever Fever", OnsetDate: &scalarutils.Date{ @@ -55,7 +54,6 @@ func TestUseCasesClinicalImpl_CreateCondition(t *testing.T) { Code: "386661006", System: "SNOMED", Status: dto.ConditionStatusActive, - PatientID: gofakeit.UUID(), EncounterID: gofakeit.UUID(), Note: "Fever Fever", OnsetDate: &scalarutils.Date{ @@ -75,7 +73,6 @@ func TestUseCasesClinicalImpl_CreateCondition(t *testing.T) { Code: "386661006", System: "SNOMED", Status: dto.ConditionStatusActive, - PatientID: gofakeit.UUID(), EncounterID: gofakeit.UUID(), Note: "Fever Fever", OnsetDate: &scalarutils.Date{ @@ -95,7 +92,6 @@ func TestUseCasesClinicalImpl_CreateCondition(t *testing.T) { Code: "386661006", System: "SNOMED", Status: dto.ConditionStatusActive, - PatientID: gofakeit.UUID(), EncounterID: gofakeit.UUID(), Note: "Fever Fever", OnsetDate: &scalarutils.Date{ @@ -115,7 +111,6 @@ func TestUseCasesClinicalImpl_CreateCondition(t *testing.T) { Code: "386661006", System: "SNOMED", Status: dto.ConditionStatusActive, - PatientID: gofakeit.UUID(), EncounterID: gofakeit.UUID(), Note: "Fever Fever", OnsetDate: &scalarutils.Date{ @@ -135,7 +130,6 @@ func TestUseCasesClinicalImpl_CreateCondition(t *testing.T) { Code: "386661006", System: "SNOMED", Status: dto.ConditionStatusActive, - PatientID: gofakeit.UUID(), EncounterID: gofakeit.UUID(), Note: "Fever Fever", OnsetDate: &scalarutils.Date{ @@ -155,7 +149,6 @@ func TestUseCasesClinicalImpl_CreateCondition(t *testing.T) { Code: "386661006", System: "SNOMED", Status: dto.ConditionStatusActive, - PatientID: gofakeit.UUID(), EncounterID: gofakeit.UUID(), Note: "Fever Fever", OnsetDate: &scalarutils.Date{ @@ -232,3 +225,96 @@ func TestUseCasesClinicalImpl_CreateCondition(t *testing.T) { }) } } + +func TestUseCasesClinicalImpl_ListPatientConditions(t *testing.T) { + + type args struct { + ctx context.Context + patientID string + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "happy case: list conditions", + args: args{ + ctx: context.Background(), + patientID: gofakeit.UUID(), + }, + wantErr: false, + }, + { + name: "sad case: invalid patient id", + args: args{ + ctx: context.Background(), + patientID: "invalid", + }, + wantErr: true, + }, + { + name: "sad case: fail to get identifiers", + args: args{ + ctx: context.Background(), + patientID: gofakeit.UUID(), + }, + wantErr: true, + }, + { + name: "sad case: fail to get patient", + args: args{ + ctx: context.Background(), + patientID: gofakeit.UUID(), + }, + wantErr: true, + }, + { + name: "sad case: fail to search condition", + args: args{ + ctx: context.Background(), + patientID: gofakeit.UUID(), + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + fakeExt := fakeExtMock.NewFakeBaseExtensionMock() + fakeFHIR := fakeFHIRMock.NewFHIRMock() + fakeOCL := fakeOCLMock.NewFakeOCLMock() + fakeMCH := fakeMyCarehubMock.NewFakeMyCareHubServiceMock() + + infra := infrastructure.NewInfrastructureInteractor(fakeExt, fakeFHIR, fakeOCL, fakeMCH) + c := clinicalUsecase.NewUseCasesClinicalImpl(infra) + + if tt.name == "sad case: fail to get identifiers" { + fakeExt.MockGetTenantIdentifiersFn = func(ctx context.Context) (*dto.TenantIdentifiers, error) { + return nil, fmt.Errorf("failed to get identifiers") + } + } + + if tt.name == "sad case: fail to get patient" { + fakeFHIR.MockGetFHIRPatientFn = func(ctx context.Context, id string) (*domain.FHIRPatientRelayPayload, error) { + return nil, fmt.Errorf("failed to get patient") + } + } + + if tt.name == "sad case: fail to search condition" { + fakeFHIR.MockSearchFHIRConditionFn = func(ctx context.Context, params map[string]interface{}, tenant dto.TenantIdentifiers) (*domain.FHIRConditionRelayConnection, error) { + return nil, fmt.Errorf("failed to find condition") + } + } + + got, err := c.ListPatientConditions(tt.args.ctx, tt.args.patientID) + if (err != nil) != tt.wantErr { + t.Errorf("ListPatientConditions() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !tt.wantErr && got == nil { + t.Errorf("expected a value to be returned, got: %v", got) + return + } + }) + } +} diff --git a/pkg/clinical/usecases/usecases.go b/pkg/clinical/usecases/usecases.go index f98b58de..9dca62f3 100644 --- a/pkg/clinical/usecases/usecases.go +++ b/pkg/clinical/usecases/usecases.go @@ -18,6 +18,7 @@ type Clinical interface { EndEpisodeOfCare(ctx context.Context, id string) (*dto.EpisodeOfCare, error) CreateCondition(ctx context.Context, input dto.ConditionInput) (*dto.Condition, error) + ListPatientConditions(ctx context.Context, patientID string) ([]*dto.Condition, error) PatientHealthTimeline(ctx context.Context, input dto.HealthTimelineInput) (*dto.HealthTimeline, error) GetMedicalData(ctx context.Context, patientID string) (*dto.MedicalData, error)