diff --git a/pkg/clinical/presentation/graph/clinical.graphql b/pkg/clinical/presentation/graph/clinical.graphql index 631e2423..72ae0cb6 100644 --- a/pkg/clinical/presentation/graph/clinical.graphql +++ b/pkg/clinical/presentation/graph/clinical.graphql @@ -178,6 +178,7 @@ extend type Mutation { input: PatchCompositionInput! ): Composition! + # Observation patchPatientHeight(id: String!, value: String!): Observation! patchPatientWeight(id: String!, value: String!): Observation! patchPatientBMI(id: String!, value: String!): Observation! @@ -188,6 +189,7 @@ extend type Mutation { patchPatientOxygenSaturation(id: String!, value: String!): Observation! patchPatientPulseRate(id: String!, value: String!): Observation! patchPatientViralLoad(id: String!, value: String!): Observation! + patchPatientMuac(id: String!, value: String!): Observation! # Consent recordConsent(input: ConsentInput!): ConsentOutput! diff --git a/pkg/clinical/presentation/graph/clinical.resolvers.go b/pkg/clinical/presentation/graph/clinical.resolvers.go index 756bf98d..27a23c27 100644 --- a/pkg/clinical/presentation/graph/clinical.resolvers.go +++ b/pkg/clinical/presentation/graph/clinical.resolvers.go @@ -233,6 +233,12 @@ func (r *mutationResolver) PatchPatientViralLoad(ctx context.Context, id string, return r.usecases.PatchPatientViralLoad(ctx, id, value) } +// PatchPatientMuac is the resolver for the patchPatientMuac field. +func (r *mutationResolver) PatchPatientMuac(ctx context.Context, id string, value string) (*dto.Observation, error) { + r.CheckDependencies() + return r.usecases.PatchPatientMuac(ctx, id, value) +} + // RecordConsent is the resolver for the recordConsent field. func (r *mutationResolver) RecordConsent(ctx context.Context, input dto.ConsentInput) (*dto.ConsentOutput, error) { return r.usecases.RecordConsent(ctx, input) diff --git a/pkg/clinical/presentation/graph/generated/generated.go b/pkg/clinical/presentation/graph/generated/generated.go index 873fbda0..5325e908 100644 --- a/pkg/clinical/presentation/graph/generated/generated.go +++ b/pkg/clinical/presentation/graph/generated/generated.go @@ -222,6 +222,7 @@ type ComplexityRoot struct { PatchPatientBmi func(childComplexity int, id string, value string) int PatchPatientDiastolicBloodPressure func(childComplexity int, id string, value string) int PatchPatientHeight func(childComplexity int, id string, value string) int + PatchPatientMuac func(childComplexity int, id string, value string) int PatchPatientOxygenSaturation func(childComplexity int, id string, value string) int PatchPatientPulseRate func(childComplexity int, id string, value string) int PatchPatientRespiratoryRate func(childComplexity int, id string, value string) int @@ -440,6 +441,7 @@ type MutationResolver interface { PatchPatientOxygenSaturation(ctx context.Context, id string, value string) (*dto.Observation, error) PatchPatientPulseRate(ctx context.Context, id string, value string) (*dto.Observation, error) PatchPatientViralLoad(ctx context.Context, id string, value string) (*dto.Observation, error) + PatchPatientMuac(ctx context.Context, id string, value string) (*dto.Observation, error) RecordConsent(ctx context.Context, input dto.ConsentInput) (*dto.ConsentOutput, error) CreateQuestionnaireResponse(ctx context.Context, questionnaireID string, encounterID string, input dto.QuestionnaireResponse) (*dto.QuestionnaireResponse, error) } @@ -1299,6 +1301,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Mutation.PatchPatientHeight(childComplexity, args["id"].(string), args["value"].(string)), true + case "Mutation.patchPatientMuac": + if e.complexity.Mutation.PatchPatientMuac == nil { + break + } + + args, err := ec.field_Mutation_patchPatientMuac_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.PatchPatientMuac(childComplexity, args["id"].(string), args["value"].(string)), true + case "Mutation.patchPatientOxygenSaturation": if e.complexity.Mutation.PatchPatientOxygenSaturation == nil { break @@ -2698,6 +2712,7 @@ extend type Mutation { input: PatchCompositionInput! ): Composition! + # Observation patchPatientHeight(id: String!, value: String!): Observation! patchPatientWeight(id: String!, value: String!): Observation! patchPatientBMI(id: String!, value: String!): Observation! @@ -2708,6 +2723,7 @@ extend type Mutation { patchPatientOxygenSaturation(id: String!, value: String!): Observation! patchPatientPulseRate(id: String!, value: String!): Observation! patchPatientViralLoad(id: String!, value: String!): Observation! + patchPatientMuac(id: String!, value: String!): Observation! # Consent recordConsent(input: ConsentInput!): ConsentOutput! @@ -3640,6 +3656,30 @@ func (ec *executionContext) field_Mutation_patchPatientHeight_args(ctx context.C return args, nil } +func (ec *executionContext) field_Mutation_patchPatientMuac_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["id"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + arg0, err = ec.unmarshalNString2string(ctx, tmp) + if err != nil { + return nil, err + } + } + args["id"] = arg0 + var arg1 string + if tmp, ok := rawArgs["value"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("value")) + arg1, err = ec.unmarshalNString2string(ctx, tmp) + if err != nil { + return nil, err + } + } + args["value"] = arg1 + return args, nil +} + func (ec *executionContext) field_Mutation_patchPatientOxygenSaturation_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -11481,6 +11521,77 @@ func (ec *executionContext) fieldContext_Mutation_patchPatientViralLoad(ctx cont return fc, nil } +func (ec *executionContext) _Mutation_patchPatientMuac(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Mutation_patchPatientMuac(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.Mutation().PatchPatientMuac(rctx, fc.Args["id"].(string), fc.Args["value"].(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.Observation) + fc.Result = res + return ec.marshalNObservation2ᚖgithubᚗcomᚋsavannahghiᚋclinicalᚋpkgᚋclinicalᚋapplicationᚋdtoᚐObservation(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Mutation_patchPatientMuac(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Mutation", + 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_Observation_id(ctx, field) + case "status": + return ec.fieldContext_Observation_status(ctx, field) + case "patientID": + return ec.fieldContext_Observation_patientID(ctx, field) + case "encounterID": + return ec.fieldContext_Observation_encounterID(ctx, field) + case "name": + return ec.fieldContext_Observation_name(ctx, field) + case "value": + return ec.fieldContext_Observation_value(ctx, field) + case "timeRecorded": + return ec.fieldContext_Observation_timeRecorded(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Observation", 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_Mutation_patchPatientMuac_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + func (ec *executionContext) _Mutation_recordConsent(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Mutation_recordConsent(ctx, field) if err != nil { @@ -20977,6 +21088,13 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) if out.Values[i] == graphql.Null { out.Invalids++ } + case "patchPatientMuac": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_patchPatientMuac(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } case "recordConsent": out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { return ec._Mutation_recordConsent(ctx, field) diff --git a/pkg/clinical/usecases/clinical/observation.go b/pkg/clinical/usecases/clinical/observation.go index 92bf35d8..2288afc5 100644 --- a/pkg/clinical/usecases/clinical/observation.go +++ b/pkg/clinical/usecases/clinical/observation.go @@ -112,6 +112,11 @@ func (c *UseCasesClinicalImpl) PatchPatientViralLoad(ctx context.Context, id str return c.PatchPatientObservations(ctx, id, value) } +// PatchPatientMuac patches the muac record of a patient +func (c *UseCasesClinicalImpl) PatchPatientMuac(ctx context.Context, id string, value string) (*dto.Observation, error) { + return c.PatchPatientObservations(ctx, id, value) +} + // RecordWeight records a patient's weight func (c *UseCasesClinicalImpl) RecordWeight(ctx context.Context, input dto.ObservationInput) (*dto.Observation, error) { weightObservation, err := c.RecordObservation(ctx, input, common.WeightCIELTerminologyCode) diff --git a/pkg/clinical/usecases/clinical/observation_test.go b/pkg/clinical/usecases/clinical/observation_test.go index b3a6b7a1..a2c4390e 100644 --- a/pkg/clinical/usecases/clinical/observation_test.go +++ b/pkg/clinical/usecases/clinical/observation_test.go @@ -4393,6 +4393,136 @@ func TestUseCasesClinicalImpl_GetPatientMuacEntries(t *testing.T) { } } +func TestUseCasesClinicalImpl_PatchPatientMuac(t *testing.T) { + type args struct { + ctx context.Context + id string + value string + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Happy Case - successfully patch patient observation", + args: args{ + ctx: context.Background(), + id: gofakeit.UUID(), + value: "160", + }, + wantErr: false, + }, + { + name: "Sad Case - missing observation ID", + args: args{ + ctx: context.Background(), + value: "160", + }, + wantErr: true, + }, + { + name: "Sad Case - Fail validation nil value", + args: args{ + ctx: context.Background(), + id: gofakeit.UUID(), + value: "", + }, + wantErr: true, + }, + { + name: "Sad Case - fail to get observation", + args: args{ + ctx: context.Background(), + id: gofakeit.UUID(), + value: "160", + }, + wantErr: true, + }, + { + name: "Sad Case: fail to get encounter", + args: args{ + ctx: context.Background(), + id: gofakeit.UUID(), + value: "160", + }, + wantErr: true, + }, + { + name: "Sad Case: fail on finished encounter", + args: args{ + ctx: context.Background(), + id: gofakeit.UUID(), + value: "160", + }, + wantErr: true, + }, + { + name: "Sad Case - fail to patch patient muac observation", + args: args{ + ctx: context.Background(), + id: gofakeit.UUID(), + value: "160", + }, + wantErr: true, + }, + } + for _, tt := range tests { + fakeExt := fakeExtMock.NewFakeBaseExtensionMock() + fakeFHIR := fakeFHIRMock.NewFHIRMock() + fakeOCL := fakeOCLMock.NewFakeOCLMock() + fakePubSub := fakePubSubMock.NewPubSubServiceMock() + + fakeUpload := fakeUploadMock.NewFakeUploadMock() + + infra := infrastructure.NewInfrastructureInteractor(fakeExt, fakeFHIR, fakeOCL, fakeUpload, fakePubSub) + u := clinicalUsecase.NewUseCasesClinicalImpl(infra) + + if tt.name == "Sad Case - fail to get observation" { + fakeFHIR.MockGetFHIRObservationFn = func(ctx context.Context, id string) (*domain.FHIRObservationRelayPayload, error) { + return nil, fmt.Errorf("an error occurred") + } + } + + if tt.name == "Sad Case: fail to get encounter" { + fakeFHIR.MockGetFHIREncounterFn = func(ctx context.Context, id string) (*domain.FHIREncounterRelayPayload, error) { + return nil, fmt.Errorf("an error occurred") + } + } + + if tt.name == "Sad Case: fail on finished encounter" { + fakeFHIR.MockGetFHIREncounterFn = func(ctx context.Context, id string) (*domain.FHIREncounterRelayPayload, error) { + UUID := uuid.New().String() + PatientRef := "Patient/" + uuid.NewString() + return &domain.FHIREncounterRelayPayload{ + Resource: &domain.FHIREncounter{ + ID: &UUID, + Text: &domain.FHIRNarrative{}, + Identifier: []*domain.FHIRIdentifier{}, + Status: domain.EncounterStatusEnum(domain.EncounterStatusEnumFinished), + Subject: &domain.FHIRReference{ + ID: &UUID, + Reference: &PatientRef, + }, + }, + }, nil + } + } + + if tt.name == "Sad Case - fail to patch patient muac observation" { + fakeFHIR.MockPatchFHIRObservationFn = func(ctx context.Context, id string, input domain.FHIRObservationInput) (*domain.FHIRObservation, error) { + return nil, fmt.Errorf("an error occurred") + } + } + + _, err := u.PatchPatientMuac(tt.args.ctx, tt.args.id, tt.args.value) + if (err != nil) != tt.wantErr { + t.Errorf("UseCasesClinicalImpl.PatchPatientMuac() error = %v, wantErr %v", err, tt.wantErr) + return + } + } +} + func TestUseCasesClinicalImpl_GetPatientOxygenSaturationEntries(t *testing.T) { first := 10 ctx := context.Background() diff --git a/pkg/clinical/usecases/usecases.go b/pkg/clinical/usecases/usecases.go index 198169d2..d5c06c74 100644 --- a/pkg/clinical/usecases/usecases.go +++ b/pkg/clinical/usecases/usecases.go @@ -98,6 +98,7 @@ type Clinical interface { PatchPatientOxygenSaturation(ctx context.Context, id string, value string) (*dto.Observation, error) PatchPatientPulseRate(ctx context.Context, id string, value string) (*dto.Observation, error) PatchPatientViralLoad(ctx context.Context, id string, value string) (*dto.Observation, error) + PatchPatientMuac(ctx context.Context, id string, value string) (*dto.Observation, error) // Questionnaire CreateQuestionnaire(ctx context.Context, questionnaireInput *domain.FHIRQuestionnaire) (*domain.FHIRQuestionnaire, error)