Skip to content

Commit

Permalink
feat: record biopsy (#354)
Browse files Browse the repository at this point in the history
- biopsy is recorded as diagnostic report as recommended by FHIR

[Link to documentation]: https://savannahghi.atlassian.net/wiki/spaces/OHE/pages/468025506/API+Documentation#Record-Biopsy

Signed-off-by: Kathurima Kimathi <kathurimakimathi415@gmail.com>
  • Loading branch information
KathurimaKimathi committed Feb 9, 2024
1 parent 925b8fe commit d8e7ede
Show file tree
Hide file tree
Showing 12 changed files with 409 additions and 38 deletions.
8 changes: 7 additions & 1 deletion .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ linters:
- ireturn
- importas
- wsl
- revive
- exportloopref
- nilerr
- makezero
Expand All @@ -39,4 +38,11 @@ linters-settings:
funlen:
lines: -1
statements: -1
revive:
rules:
- name: unused-parameter
severity: warning
disabled: true
arguments:
- allowRegex: "^_"

5 changes: 4 additions & 1 deletion pkg/clinical/application/common/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,14 +155,17 @@ const (
// LowRiskCIELCode represents the CIEL code for a low-risk condition
LowRiskCIELCode = "166675"

// CIELTerminologySystem is the identity of ciel terminology system
// CIELTerminologySystem is the identity of CIEL terminology system
CIELTerminologySystem = "https://CIELterminology.org"

// MammogramTerminologyCode is the terminology code used to represent mammogram results.
MammogramTerminologyCode = "163591"

// BenignNeoplasmOfBreastOfSkinTerminologyCode is the terminology code used to represent benign of skin results.
BenignNeoplasmOfBreastOfSkinTerminologyCode = "147661"

// BiopsyTerminologySystem is the terminology code used to represent Biopsy of cervix.
BiopsyTerminologySystem = "161826"
)

// DefaultIdentifier assigns a patient a code to function as their
Expand Down
2 changes: 1 addition & 1 deletion pkg/clinical/application/dto/input.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ type Expression struct {
type DiagnosticReportInput struct {
EncounterID string `json:"encounterID,omitempty" validate:"required"`
Note string `json:"note,omitempty"`
Media Media `json:"media" validate:"required"`
Media *Media `json:"media"`
Findings string `json:"findings,omitempty" validate:"required"`
}

Expand Down
2 changes: 2 additions & 0 deletions pkg/clinical/presentation/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ var ClinicalAllowedOrigins = []string{
"https://review-advantage.web.app",
"https://prod-empower.web.app",
"https://staging-empower.web.app",
"https://uat.empower.savannahghi.org",
"https://empower.savannahghi.org",
}

var (
Expand Down
1 change: 1 addition & 0 deletions pkg/clinical/presentation/graph/clinical.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -218,4 +218,5 @@ extend type Mutation {

# Diagnostic Report
recordMammographyResult(input: DiagnosticReportInput!): DiagnosticReport!
recordBiopsy(input: DiagnosticReportInput!): DiagnosticReport!
}
5 changes: 5 additions & 0 deletions pkg/clinical/presentation/graph/clinical.resolvers.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

119 changes: 116 additions & 3 deletions pkg/clinical/presentation/graph/generated/generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

82 changes: 62 additions & 20 deletions pkg/clinical/usecases/clinical/diagnostic_report.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,39 @@ func (c *UseCasesClinicalImpl) RecordMammographyResult(ctx context.Context, inpu
return nil, err
}

observationsReference := fmt.Sprintf("Observation/%s", observationOutput.ID)
return c.RecordDiagnosticReport(ctx, common.MammogramTerminologyCode, input, observationOutput, nil)
}

// RecordBiopsy is used to record biopsy test results as observations
// FHIR recommends use of diagnostic resource to record the findings and interpretation of biopsy test results
// performed on patients, groups of patients, devices, and locations, and/or specimens.
func (c *UseCasesClinicalImpl) RecordBiopsy(ctx context.Context, input dto.DiagnosticReportInput) (*dto.DiagnosticReport, error) {
err := input.Validate()
if err != nil {
return nil, err
}

observationInput := &dto.ObservationInput{
Status: dto.ObservationStatusFinal,
EncounterID: input.EncounterID,
Value: input.Findings,
}

observationOutput, err := c.RecordObservation(ctx, *observationInput, common.BiopsyTerminologySystem, []ObservationInputMutatorFunc{addProcedureCategory})
if err != nil {
return nil, err
}

return c.RecordDiagnosticReport(ctx, common.BiopsyTerminologySystem, input, observationOutput, []DiagnosticReportMutatorFunc{addCytologyCategory})
}

// RecordDiagnosticReport is a re-usable method to help with diagnostic report recording
func (c *UseCasesClinicalImpl) RecordDiagnosticReport(ctx context.Context, conceptID string, input dto.DiagnosticReportInput, observation *dto.Observation, mutators []DiagnosticReportMutatorFunc) (*dto.DiagnosticReport, error) {
observationsReference := fmt.Sprintf("Observation/%s", observation.ID)
observationType := scalarutils.URI("Observation")
encounterReference := fmt.Sprintf("Encounter/%s", observationOutput.EncounterID)
encounterReference := fmt.Sprintf("Encounter/%s", observation.EncounterID)
encounterType := scalarutils.URI("Encounter")
patientReference := fmt.Sprintf("Patient/%s", observationOutput.PatientID)
patientReference := fmt.Sprintf("Patient/%s", observation.PatientID)
patientType := scalarutils.URI("Patient")

tags, err := c.GetTenantMetaTags(ctx)
Expand All @@ -57,18 +85,17 @@ func (c *UseCasesClinicalImpl) RecordMammographyResult(ctx context.Context, inpu
orgRef := fmt.Sprintf("Organization/%s", *facility.Resource.ID)
orgType := scalarutils.URI("Organization")
id := uuid.New().String()
mediaReference := fmt.Sprintf("Media/%s", input.Media.ID)
mediaType := scalarutils.URI("Media")
instant := scalarutils.Instant(time.Now().Format(time.RFC3339))

concept, err := c.GetConcept(ctx, dto.TerminologySourceCIEL, common.MammogramTerminologyCode)
concept, err := c.GetConcept(ctx, dto.TerminologySourceCIEL, conceptID)
if err != nil {
return nil, err
}

diagnosticReport := &domain.FHIRDiagnosticReportInput{
ID: &id,
Status: domain.DiagnosticReportStatusPreliminary,
ID: &id,
Status: domain.DiagnosticReportStatusFinal,
Category: []*domain.FHIRCodeableConceptInput{},
Code: domain.FHIRCodeableConceptInput{
Coding: []*domain.FHIRCodingInput{
{
Expand All @@ -80,12 +107,12 @@ func (c *UseCasesClinicalImpl) RecordMammographyResult(ctx context.Context, inpu
Text: concept.DisplayName,
},
Subject: &domain.FHIRReferenceInput{
ID: &observationOutput.PatientID,
ID: &observation.PatientID,
Reference: &patientReference,
Type: &patientType,
},
Encounter: &domain.FHIRReferenceInput{
ID: &observationOutput.EncounterID,
ID: &observation.EncounterID,
Reference: &encounterReference,
Type: &encounterType,
},
Expand All @@ -106,19 +133,10 @@ func (c *UseCasesClinicalImpl) RecordMammographyResult(ctx context.Context, inpu
Display: *facility.Resource.Name,
},
},
Media: []*domain.FHIRDiagnosticReportMediaInput{
{
ID: &input.Media.ID,
Link: &domain.FHIRReferenceInput{
Reference: &mediaReference,
Type: &mediaType,
},
},
},
Conclusion: &input.Note,
Result: []*domain.FHIRReferenceInput{
{
ID: &observationOutput.ID,
ID: &observation.ID,
Reference: &observationsReference,
Type: &observationType,
},
Expand All @@ -129,6 +147,30 @@ func (c *UseCasesClinicalImpl) RecordMammographyResult(ctx context.Context, inpu
Tag: tags,
}

if input.Media != nil {
mediaReference := fmt.Sprintf("Media/%s", input.Media.ID)
mediaType := scalarutils.URI("Media")

diagnosticReport.Media = []*domain.FHIRDiagnosticReportMediaInput{
{
ID: &input.Media.ID,
Link: &domain.FHIRReferenceInput{
Reference: &mediaReference,
Type: &mediaType,
},
},
}
}

if len(mutators) > 0 {
for _, mutator := range mutators {
err = mutator(ctx, diagnosticReport)
if err != nil {
return nil, err
}
}
}

result, err := c.infrastructure.FHIR.CreateFHIRDiagnosticReport(ctx, diagnosticReport)
if err != nil {
return nil, err
Expand Down
Loading

0 comments on commit d8e7ede

Please sign in to comment.