From a5eba794b57d6e33e5f163ddece63b140d650056 Mon Sep 17 00:00:00 2001 From: Jason Kulatunga Date: Mon, 19 Feb 2024 18:31:18 -0800 Subject: [PATCH 01/29] make sure tokens support modifiers during query make sure we can use multiple AND clauses in query. --- backend/pkg/database/gorm_repository_query.go | 22 ++++-- .../gorm_repository_query_sql_test.go | 74 +++++++++++++++++++ .../database/gorm_repository_query_test.go | 8 +- backend/pkg/database/interface.go | 1 + 4 files changed, 97 insertions(+), 8 deletions(-) diff --git a/backend/pkg/database/gorm_repository_query.go b/backend/pkg/database/gorm_repository_query.go index 66195976a..029a48d77 100644 --- a/backend/pkg/database/gorm_repository_query.go +++ b/backend/pkg/database/gorm_repository_query.go @@ -313,9 +313,10 @@ func ProcessSearchParameter(searchCodeWithModifier string, searchParamTypeLookup searchParameter.Type = SearchParameterType(searchParamTypeStr) } - //if this is a token search parameter with a modifier, we need to throw an error - if searchParameter.Type == SearchParameterTypeToken && len(searchParameter.Modifier) > 0 { - return searchParameter, fmt.Errorf("token search parameter %s cannot have a modifier", searchParameter.Name) + //only a limited set of token modifiers are allowed. Otherwise we need to throw an error + allowedTokenModifiers := []string{"not"} + if searchParameter.Type == SearchParameterTypeToken && len(searchParameter.Modifier) > 0 && !lo.Contains(allowedTokenModifiers, searchParameter.Modifier) { + return searchParameter, fmt.Errorf("token search parameter %s does not support this modifier: %s", searchParameter.Name, searchParameter.Modifier) } return searchParameter, nil @@ -332,8 +333,8 @@ func ProcessSearchParameter(searchCodeWithModifier string, searchParamTypeLookup // // For example, searchParamCodeValueOrValuesWithPrefix may be: // -// "code": "29463-7,3141-9,27113001" -// "code": ["le29463-7", "gt3141-9", "27113001"] +// "code": "29463-7,3141-9,27113001" = OR +// "code": ["le29463-7", "gt3141-9", "27113001"] = AND func ProcessSearchParameterValueIntoOperatorTree(searchParameter SearchParameter, searchParamCodeValueOrValuesWithPrefix interface{}) (SearchParameterValueOperatorTree, error) { searchParamCodeValuesWithPrefix := []string{} @@ -344,6 +345,11 @@ func ProcessSearchParameterValueIntoOperatorTree(searchParameter SearchParameter case []string: searchParamCodeValuesWithPrefix = v break + case []interface{}: + for _, searchParamCodeValue := range v { + searchParamCodeValuesWithPrefix = append(searchParamCodeValuesWithPrefix, fmt.Sprintf("%v", searchParamCodeValue)) + } + break default: return nil, fmt.Errorf("invalid search parameter value type %T, must be a string or a list of strings (%s=%v)", v, searchParameter.Name, searchParamCodeValueOrValuesWithPrefix) } @@ -574,7 +580,11 @@ func SearchCodeToWhereClause(searchParam SearchParameter, searchParamValue Searc //setup the clause clause := []string{} if searchParamValue.Value.(string) != "" { - clause = append(clause, fmt.Sprintf("%sJson.value ->> '$.code' = @%s", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, namedParameterSuffix))) + if searchParam.Modifier == "" { + clause = append(clause, fmt.Sprintf("%sJson.value ->> '$.code' = @%s", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, namedParameterSuffix))) + } else if searchParam.Modifier == "not" { + clause = append(clause, fmt.Sprintf("%sJson.value ->> '$.code' <> @%s", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, namedParameterSuffix))) + } } //append the code and/or system clauses (if required) diff --git a/backend/pkg/database/gorm_repository_query_sql_test.go b/backend/pkg/database/gorm_repository_query_sql_test.go index c146be9c0..14b04e067 100644 --- a/backend/pkg/database/gorm_repository_query_sql_test.go +++ b/backend/pkg/database/gorm_repository_query_sql_test.go @@ -149,6 +149,80 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithMultipleWhereCon }) } +func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenWithNotModifier() { + //setup + sqliteRepo := suite.TestRepository.(*GormRepository) + sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true}) + + //test + authContext := context.WithValue(context.Background(), pkg.ContextKeyTypeAuthUsername, "test_username") + + sqlQuery, err := sqliteRepo.sqlQueryResources(authContext, models.QueryResource{ + Select: []string{}, + Where: map[string]interface{}{ + "code:not": "test_code", + }, + From: "Observation", + }) + require.NoError(suite.T(), err) + var results []map[string]interface{} + statement := sqlQuery.Find(&results).Statement + sqlString := statement.SQL.String() + sqlParams := statement.Vars + + //assert + require.NoError(suite.T(), err) + require.Equal(suite.T(), + strings.Join([]string{ + "SELECT fhir.*", + "FROM fhir_observation as fhir, json_each(fhir.code) as codeJson", + "WHERE ((codeJson.value ->> '$.code' <> ?)) AND (user_id = ?)", + "GROUP BY `fhir`.`id`", + "ORDER BY fhir.sort_date DESC", + }, " "), + sqlString) + require.Equal(suite.T(), sqlParams, []interface{}{ + "test_code", "00000000-0000-0000-0000-000000000000", + }) +} + +func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenMultipleValuesWithNotModifier() { + //setup + sqliteRepo := suite.TestRepository.(*GormRepository) + sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true}) + + //test + authContext := context.WithValue(context.Background(), pkg.ContextKeyTypeAuthUsername, "test_username") + + sqlQuery, err := sqliteRepo.sqlQueryResources(authContext, models.QueryResource{ + Select: []string{}, + Where: map[string]interface{}{ + "code:not": []string{"test_code", "test_code2"}, + }, + From: "Observation", + }) + require.NoError(suite.T(), err) + var results []map[string]interface{} + statement := sqlQuery.Find(&results).Statement + sqlString := statement.SQL.String() + sqlParams := statement.Vars + + //assert + require.NoError(suite.T(), err) + require.Equal(suite.T(), + strings.Join([]string{ + "SELECT fhir.*", + "FROM fhir_observation as fhir, json_each(fhir.code) as codeJson", + "WHERE ((codeJson.value ->> '$.code' <> ?)) AND ((codeJson.value ->> '$.code' <> ?)) AND (user_id = ?)", + "GROUP BY `fhir`.`id`", + "ORDER BY fhir.sort_date DESC", + }, " "), + sqlString) + require.Equal(suite.T(), sqlParams, []interface{}{ + "test_code", "test_code2", "00000000-0000-0000-0000-000000000000", + }) +} + func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithPrimitiveOrderByAggregation() { //setup sqliteRepo := suite.TestRepository.(*GormRepository) diff --git a/backend/pkg/database/gorm_repository_query_test.go b/backend/pkg/database/gorm_repository_query_test.go index 53cb50b21..116c11d0e 100644 --- a/backend/pkg/database/gorm_repository_query_test.go +++ b/backend/pkg/database/gorm_repository_query_test.go @@ -38,7 +38,9 @@ func TestProcessSearchParameter(t *testing.T) { {"url:below", map[string]string{"url": "string"}, SearchParameter{Type: "string", Name: "url", Modifier: "below"}, false}, {"url:above", map[string]string{"url": "string"}, SearchParameter{Type: "string", Name: "url", Modifier: "above"}, false}, - {"display:text", map[string]string{"display": "token"}, SearchParameter{}, true}, + {"display", map[string]string{"display": "token"}, SearchParameter{Type: "token", Name: "display", Modifier: ""}, false}, + {"display:not", map[string]string{"display": "token"}, SearchParameter{Type: "token", Name: "display", Modifier: "not"}, false}, + {"display:unsupported", map[string]string{"display": "token"}, SearchParameter{}, true}, } //test && assert @@ -161,7 +163,9 @@ func TestSearchCodeToWhereClause(t *testing.T) { {SearchParameter{Type: "token", Name: "code", Modifier: ""}, SearchParameterValue{Value: "ha125", Prefix: "", SecondaryValues: map[string]interface{}{"codeSystem": "http://acme.org/conditions/codes"}}, "0_0", "(codeJson.value ->> '$.code' = @code_0_0 AND codeJson.value ->> '$.system' = @codeSystem_0_0)", map[string]interface{}{"code_0_0": "ha125", "codeSystem_0_0": "http://acme.org/conditions/codes"}, false}, {SearchParameter{Type: "token", Name: "code", Modifier: ""}, SearchParameterValue{Value: "ha125", Prefix: "", SecondaryValues: map[string]interface{}{}}, "0_0", "(codeJson.value ->> '$.code' = @code_0_0)", map[string]interface{}{"code_0_0": "ha125"}, false}, - {SearchParameter{Type: "token", Name: "identifier", Modifier: "otype"}, SearchParameterValue{Value: "MR|446053", Prefix: "", SecondaryValues: map[string]interface{}{"identifierSystem": "http://terminology.hl7.org/CodeSystem/v2-0203"}}, "0_0", "(identifierJson.value ->> '$.code' = @identifier_0_0 AND identifierJson.value ->> '$.system' = @identifierSystem_0_0)", map[string]interface{}{"identifier_0_0": "MR|446053", "identifierSystem_0_0": "http://terminology.hl7.org/CodeSystem/v2-0203"}, false}, + {SearchParameter{Type: "token", Name: "identifier", Modifier: ""}, SearchParameterValue{Value: "MR|446053", Prefix: "", SecondaryValues: map[string]interface{}{"identifierSystem": "http://terminology.hl7.org/CodeSystem/v2-0203"}}, "0_0", "(identifierJson.value ->> '$.code' = @identifier_0_0 AND identifierJson.value ->> '$.system' = @identifierSystem_0_0)", map[string]interface{}{"identifier_0_0": "MR|446053", "identifierSystem_0_0": "http://terminology.hl7.org/CodeSystem/v2-0203"}, false}, + {SearchParameter{Type: "token", Name: "gender", Modifier: ""}, SearchParameterValue{Value: "male", Prefix: "", SecondaryValues: map[string]interface{}{"genderSystem": "http://terminology.hl7.org/CodeSystem/v2-0203"}}, "0_0", "(genderJson.value ->> '$.code' = @gender_0_0 AND genderJson.value ->> '$.system' = @genderSystem_0_0)", map[string]interface{}{"gender_0_0": "male", "genderSystem_0_0": "http://terminology.hl7.org/CodeSystem/v2-0203"}, false}, + {SearchParameter{Type: "token", Name: "gender", Modifier: "not"}, SearchParameterValue{Value: "male", Prefix: "", SecondaryValues: map[string]interface{}{"genderSystem": "http://terminology.hl7.org/CodeSystem/v2-0203"}}, "0_0", "(genderJson.value ->> '$.code' <> @gender_0_0 AND genderJson.value ->> '$.system' = @genderSystem_0_0)", map[string]interface{}{"gender_0_0": "male", "genderSystem_0_0": "http://terminology.hl7.org/CodeSystem/v2-0203"}, false}, {SearchParameter{Type: "keyword", Name: "id", Modifier: ""}, SearchParameterValue{Value: "1234", Prefix: "", SecondaryValues: map[string]interface{}{}}, "0_0", "(id = @id_0_0)", map[string]interface{}{"id_0_0": "1234"}, false}, } diff --git a/backend/pkg/database/interface.go b/backend/pkg/database/interface.go index 65adea781..382ea01cc 100644 --- a/backend/pkg/database/interface.go +++ b/backend/pkg/database/interface.go @@ -19,6 +19,7 @@ type DatabaseRepository interface { GetCurrentUser(ctx context.Context) (*models.User, error) DeleteCurrentUser(ctx context.Context) error + //get a count of every resource type GetSummary(ctx context.Context) (*models.Summary, error) GetResourceByResourceTypeAndId(context.Context, string, string) (*models.ResourceBase, error) From 68859546c0209e4621c80d6f781e9a2a48da41b9 Mon Sep 17 00:00:00 2001 From: Jason Kulatunga Date: Tue, 20 Feb 2024 10:22:19 -0800 Subject: [PATCH 02/29] adding tests to ensure that the same field with multiple modifiers is correctly handled. adding IPS query logic. Adding IPS sections. TODO: tests broken. --- backend/pkg/constants.go | 17 ++ backend/pkg/database/gorm_repository_query.go | 10 + .../gorm_repository_query_sql_test.go | 79 +++++- .../pkg/database/gorm_repository_summary.go | 241 ++++++++++++++++++ 4 files changed, 345 insertions(+), 2 deletions(-) create mode 100644 backend/pkg/database/gorm_repository_summary.go diff --git a/backend/pkg/constants.go b/backend/pkg/constants.go index 8062ffe07..e87ed5bf9 100644 --- a/backend/pkg/constants.go +++ b/backend/pkg/constants.go @@ -10,6 +10,8 @@ type DatabaseRepositoryType string type InstallationVerificationStatus string type InstallationQuotaStatus string +type IPSSections string + const ( ResourceListPageSize int = 20 @@ -50,4 +52,19 @@ const ( InstallationVerificationStatusVerified InstallationVerificationStatus = "VERIFIED" //email has been verified InstallationQuotaStatusActive InstallationQuotaStatus = "ACTIVE" InstallationQuotaStatusConsumed InstallationQuotaStatus = "CONSUMED" + + IPSSectionsMedicationSummary IPSSections = "medication_summary" + IPSSectionsAllergiesIntolerances IPSSections = "allergies_intolerances" + IPSSectionsProblemList IPSSections = "problem_list" + IPSSectionsImmunizations IPSSections = "immunizations" + IPSSectionsHistoryOfProcedures IPSSections = "history_of_procedures" + IPSSectionsMedicalDevices IPSSections = "medical_devices" + IPSSectionsDiagnosticResults IPSSections = "diagnostic_results" + IPSSectionsVitalSigns IPSSections = "vital_signs" + IPSSectionsHistoryOfIllnesses IPSSections = "history_of_illnesses" + IPSSectionsPregnancy IPSSections = "pregnancy" + IPSSectionsSocialHistory IPSSections = "social_history" + IPSSectionsPlanOfCare IPSSections = "plan_of_care" + IPSSectionsFunctionalStatus IPSSections = "functional_status" + IPSSectionsAdvanceDirectives IPSSections = "advance_directives" ) diff --git a/backend/pkg/database/gorm_repository_query.go b/backend/pkg/database/gorm_repository_query.go index 029a48d77..562cb4a07 100644 --- a/backend/pkg/database/gorm_repository_query.go +++ b/backend/pkg/database/gorm_repository_query.go @@ -3,6 +3,7 @@ package database import ( "context" "fmt" + "log" "sort" "strconv" "strings" @@ -230,6 +231,15 @@ func (gr *GormRepository) sqlQueryResources(ctx context.Context, query models.Qu } } + log.Printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") + log.Printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") + log.Printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") + log.Printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") + log.Printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") + log.Printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") + log.Printf("whereClauses: %v", whereClauses) + log.Printf("whereNamedParameters: %v", whereNamedParameters) + //ensure Where and From clauses are unique whereClauses = lo.Uniq(whereClauses) whereClauses = lo.Compact(whereClauses) diff --git a/backend/pkg/database/gorm_repository_query_sql_test.go b/backend/pkg/database/gorm_repository_query_sql_test.go index 14b04e067..3605574a5 100644 --- a/backend/pkg/database/gorm_repository_query_sql_test.go +++ b/backend/pkg/database/gorm_repository_query_sql_test.go @@ -186,7 +186,7 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenWithNotModi }) } -func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenMultipleValuesWithNotModifier() { +func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenMultipleANDValuesWithNotModifier() { //setup sqliteRepo := suite.TestRepository.(*GormRepository) sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true}) @@ -197,7 +197,7 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenMultipleVal sqlQuery, err := sqliteRepo.sqlQueryResources(authContext, models.QueryResource{ Select: []string{}, Where: map[string]interface{}{ - "code:not": []string{"test_code", "test_code2"}, + "code:not": []string{"test_code", "test_code2"}, //AND condition }, From: "Observation", }) @@ -223,6 +223,81 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenMultipleVal }) } +func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenMultipleORValues() { + //setup + sqliteRepo := suite.TestRepository.(*GormRepository) + sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true}) + + //test + authContext := context.WithValue(context.Background(), pkg.ContextKeyTypeAuthUsername, "test_username") + + sqlQuery, err := sqliteRepo.sqlQueryResources(authContext, models.QueryResource{ + Select: []string{}, + Where: map[string]interface{}{ + "code": "test_code,test_code2", //OR condition + }, + From: "Observation", + }) + require.NoError(suite.T(), err) + var results []map[string]interface{} + statement := sqlQuery.Find(&results).Statement + sqlString := statement.SQL.String() + sqlParams := statement.Vars + + //assert + require.NoError(suite.T(), err) + require.Equal(suite.T(), + strings.Join([]string{ + "SELECT fhir.*", + "FROM fhir_observation as fhir, json_each(fhir.code) as codeJson", + "WHERE ((codeJson.value ->> '$.code' = ?)) OR ((codeJson.value ->> '$.code' = ?)) AND (user_id = ?)", + "GROUP BY `fhir`.`id`", + "ORDER BY fhir.sort_date DESC", + }, " "), + sqlString) + require.Equal(suite.T(), sqlParams, []interface{}{ + "test_code", "test_code2", "00000000-0000-0000-0000-000000000000", + }) +} + +func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenMixedMultipleANDORValues() { + //setup + sqliteRepo := suite.TestRepository.(*GormRepository) + sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true}) + + //test + authContext := context.WithValue(context.Background(), pkg.ContextKeyTypeAuthUsername, "test_username") + + sqlQuery, err := sqliteRepo.sqlQueryResources(authContext, models.QueryResource{ + Select: []string{}, + Where: map[string]interface{}{ + "code:not": []string{"test_code", "test_code2", "test_code3"}, //AND condition + "code": "test_code4,test_code5,test_code6", //OR condition + }, + From: "Observation", + }) + require.NoError(suite.T(), err) + var results []map[string]interface{} + statement := sqlQuery.Find(&results).Statement + sqlString := statement.SQL.String() + sqlParams := statement.Vars + + //assert + require.NoError(suite.T(), err) + require.Equal(suite.T(), + strings.Join([]string{ + "SELECT fhir.*", + "FROM fhir_observation as fhir, json_each(fhir.code) as codeJson", + "WHERE ((codeJson.value ->> '$.code' <> ?)) AND ((codeJson.value ->> '$.code' <> ?)) AND ((codeJson.value ->> '$.code' <> ?)) AND ((codeJson.value ->> '$.code' = ?) OR (codeJson.value ->> '$.code' = ?) OR (codeJson.value ->> '$.code' = ?)) AND (user_id = ?)", + "GROUP BY `fhir`.`id`", + "ORDER BY fhir.sort_date DESC", + }, " "), + sqlString) + require.Equal(suite.T(), sqlParams, []interface{}{ + "test_code", "test_code2", "test_code3", "test_code4", "00000000-0000-0000-0000-000000000000", + }) +} + func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithPrimitiveOrderByAggregation() { //setup sqliteRepo := suite.TestRepository.(*GormRepository) diff --git a/backend/pkg/database/gorm_repository_summary.go b/backend/pkg/database/gorm_repository_summary.go new file mode 100644 index 000000000..1749904ef --- /dev/null +++ b/backend/pkg/database/gorm_repository_summary.go @@ -0,0 +1,241 @@ +package database + +import ( + "context" + "github.com/fastenhealth/fasten-onprem/backend/pkg" + "github.com/fastenhealth/fasten-onprem/backend/pkg/models" + databaseModel "github.com/fastenhealth/fasten-onprem/backend/pkg/models/database" +) + +// GetInternationalPatientSummary will generate an IPS bundle, which can then be used to generate a IPS QR code, PDF or JSON bundle +// The IPS bundle will contain a summary of all the data in the system, including a list of all sources, and the main Patient +// See: https://github.com/fastenhealth/fasten-onprem/issues/170 +// See: https://github.com/jddamore/fhir-ips-server/blob/main/docs/Summary_Creation_Steps.md +func (gr *GormRepository) GetInternationalPatientSummary(ctx context.Context) (*models.Summary, error) { + currentUser, currentUserErr := gr.GetCurrentUser(ctx) + if currentUserErr != nil { + return nil, currentUserErr + } + + // we want a count of all resources for this user by type + var resourceCountResults []map[string]interface{} + + resourceTypes := databaseModel.GetAllowedResourceTypes() + for _, resourceType := range resourceTypes { + tableName, err := databaseModel.GetTableNameByResourceType(resourceType) + if err != nil { + return nil, err + } + var count int64 + + gr.QueryResources(ctx, models.QueryResource{ + Use: "", + Select: nil, + From: "", + Where: nil, + Limit: nil, + Offset: nil, + Aggregations: nil, + }) + + result := gr.GormClient.WithContext(ctx). + Table(tableName). + Where(models.OriginBase{ + UserID: currentUser.ID, + }). + Count(&count) + if result.Error != nil { + return nil, result.Error + } + if count == 0 { + continue //don't add resource counts if the count is 0 + } + resourceCountResults = append(resourceCountResults, map[string]interface{}{ + "resource_type": resourceType, + "count": count, + }) + } + + // we want a list of all sources (when they were last updated) + sources, err := gr.GetSources(ctx) + if err != nil { + return nil, err + } + + // we want the main Patient for each source + patients, err := gr.GetPatientForSources(ctx) + if err != nil { + return nil, err + } + + if resourceCountResults == nil { + resourceCountResults = []map[string]interface{}{} + } + summary := &models.Summary{ + Sources: sources, + ResourceTypeCounts: resourceCountResults, + Patients: patients, + } + + return summary, nil +} + +// https://github.com/jddamore/fhir-ips-server/blob/main/docs/Summary_Creation_Steps.md +func generateIPSSectionQueries(sectionType pkg.IPSSections) ([]models.QueryResource, error) { + + queries := []models.QueryResource{} + switch sectionType { + case pkg.IPSSectionsAllergiesIntolerances: + queries = append(queries, models.QueryResource{ + Select: nil, + From: "AllergyIntolerance", + Where: map[string]interface{}{ + "clinicalStatus:not": []string{"inactive", "resolved"}, + "verificationStatus:not": []string{"entered-in-error"}, + }, + }) + break + case pkg.IPSSectionsProblemList: + queries = append(queries, models.QueryResource{ + Select: nil, + From: "Condition", + Where: map[string]interface{}{ + "clinicalStatus:not": []string{"inactive", "resolved"}, + "verificationStatus:not": []string{"entered-in-error"}, + }, + }) + break + case pkg.IPSSectionsMedicationSummary: + queries = append(queries, models.QueryResource{ + Select: nil, + From: "MedicationStatement", + Where: map[string]interface{}{ + "status": "active,intended,unknown,on-hold", + }, + }) + queries = append(queries, models.QueryResource{ + Select: nil, + From: "MedicationRequest", + Where: map[string]interface{}{ + "status": "active,unknown,on-hold", + }, + }) + break + case pkg.IPSSectionsDiagnosticResults: + queries = append(queries, models.QueryResource{ + Select: nil, + From: "DiagnosticReport", + Where: map[string]interface{}{ + "category": "LAB", + }, + }) + + //TODO: group by code, sort by date, limit to the most recent 3 + queries = append(queries, models.QueryResource{ + Select: nil, + From: "Observation", + Where: map[string]interface{}{ + "category": "laboratory", + "status:not": "preliminary", + }, + }) + break + case pkg.IPSSectionsVitalSigns: + //TODO: group by code, sort by date, limit to the most recent 3 + queries = append(queries, models.QueryResource{ + Select: nil, + From: "Observation", + Where: map[string]interface{}{ + "category": "vital-signs", + }, + }) + break + case pkg.IPSSectionsSocialHistory: + queries = append(queries, models.QueryResource{ + Select: nil, + From: "Observation", + Where: map[string]interface{}{ + "category": "social-history", + "status:not": "preliminary", + }, + }) + break + case pkg.IPSSectionsPregnancy: + //TODO: determine the code for pregnancy from IPS specification + queries = append(queries, models.QueryResource{ + Select: nil, + From: "Observation", + Where: map[string]interface{}{ + "status:not": "preliminary", + }, + }) + break + case pkg.IPSSectionsImmunizations: + queries = append(queries, models.QueryResource{ + Select: nil, + From: "Immunization", + Where: map[string]interface{}{ + "status:not": "entered-in-error", + }, + }) + break + case pkg.IPSSectionsAdvanceDirectives: + queries = append(queries, models.QueryResource{ + Select: nil, + From: "Consent", + Where: map[string]interface{}{ + "status": "active", + }, + }) + break + case pkg.IPSSectionsFunctionalStatus: + queries = append(queries, models.QueryResource{ + Select: nil, + From: "ClinicalImpression", + Where: map[string]interface{}{ + "status": "in-progress,completed", + }, + }) + break + case pkg.IPSSectionsMedicalDevices: + queries = append(queries, models.QueryResource{ + Select: nil, + From: "Device", + Where: map[string]interface{}{ + "status": "entered-in-error", + }, + }) + break + case pkg.IPSSectionsHistoryOfIllnesses: + //TODO: last updated date should be older than 5 years (dateTime or period.high) + //TODO: check if where clause with multiple modifiers for the same field works as expected + queries = append(queries, models.QueryResource{ + Select: nil, + From: "Condition", + Where: map[string]interface{}{ + "clinicalStatus:not": []string{"entered-in-error"}, + "clinicalStatus": "inactive,remission,resolved", + }, + }) + break + case pkg.IPSSectionsPlanOfCare: + queries = append(queries, models.QueryResource{ + Select: nil, + From: "CarePlan", + Where: map[string]interface{}{ + "status": "active,on-hold,unknown", + }, + }) + break + case pkg.IPSSectionsHistoryOfProcedures: + queries = append(queries, models.QueryResource{ + Select: nil, + From: "Procedure", + Where: map[string]interface{}{ + "status:not": []string{"entered-in-error", "not-done"}, + }, + }) + } + + return queries, nil +} From 0af00e00f428920a5aba3942535f9df1041404dc Mon Sep 17 00:00:00 2001 From: Jason Kulatunga Date: Tue, 20 Feb 2024 11:09:43 -0800 Subject: [PATCH 03/29] reorganize tests fixed bug where field with multiple modifiers was not correctly queried. --- backend/pkg/database/gorm_repository_query.go | 74 +++-- .../gorm_repository_query_sql_test.go | 295 ++++++++++-------- 2 files changed, 202 insertions(+), 167 deletions(-) diff --git a/backend/pkg/database/gorm_repository_query.go b/backend/pkg/database/gorm_repository_query.go index 562cb4a07..f3284f85b 100644 --- a/backend/pkg/database/gorm_repository_query.go +++ b/backend/pkg/database/gorm_repository_query.go @@ -3,7 +3,6 @@ package database import ( "context" "fmt" - "log" "sort" "strconv" "strings" @@ -231,14 +230,9 @@ func (gr *GormRepository) sqlQueryResources(ctx context.Context, query models.Qu } } - log.Printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") - log.Printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") - log.Printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") - log.Printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") - log.Printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") - log.Printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") - log.Printf("whereClauses: %v", whereClauses) - log.Printf("whereNamedParameters: %v", whereNamedParameters) + // Debugging + //log.Printf("whereClauses: %v", whereClauses) + //log.Printf("whereNamedParameters: %v", whereNamedParameters) //ensure Where and From clauses are unique whereClauses = lo.Uniq(whereClauses) @@ -472,8 +466,12 @@ func ProcessSearchParameterValue(searchParameter SearchParameter, searchValueWit return searchParameterValue, nil } -func NamedParameterWithSuffix(parameterName string, suffix string) string { - return fmt.Sprintf("%s_%s", parameterName, suffix) +func NamedParameterWithSuffix(parameterName string, parameterModifier string, suffix string) string { + if len(parameterModifier) > 0 { + return fmt.Sprintf("%s-%s_%s", parameterName, parameterModifier, suffix) + } else { + return fmt.Sprintf("%s_%s", parameterName, suffix) + } } // SearchCodeToWhereClause converts a searchCode and searchCodeValue to a where clause and a map of named parameters @@ -481,10 +479,10 @@ func SearchCodeToWhereClause(searchParam SearchParameter, searchParamValue Searc //add named parameters to the lookup map. Basically, this is a map of all the named parameters that will be used in the where clause we're generating searchClauseNamedParams := map[string]interface{}{ - NamedParameterWithSuffix(searchParam.Name, namedParameterSuffix): searchParamValue.Value, + NamedParameterWithSuffix(searchParam.Name, searchParam.Modifier, namedParameterSuffix): searchParamValue.Value, } for k, v := range searchParamValue.SecondaryValues { - searchClauseNamedParams[NamedParameterWithSuffix(k, namedParameterSuffix)] = v + searchClauseNamedParams[NamedParameterWithSuffix(k, "", namedParameterSuffix)] = v } //parse the searchCode and searchCodeValue to determine the correct where clause @@ -495,27 +493,27 @@ func SearchCodeToWhereClause(searchParam SearchParameter, searchParamValue Searc case SearchParameterTypeNumber, SearchParameterTypeDate: if searchParamValue.Prefix == "" || searchParamValue.Prefix == "eq" { - return fmt.Sprintf("(%s = @%s)", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, namedParameterSuffix)), searchClauseNamedParams, nil + return fmt.Sprintf("(%s = @%s)", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, searchParam.Modifier, namedParameterSuffix)), searchClauseNamedParams, nil } else if searchParamValue.Prefix == "lt" || searchParamValue.Prefix == "eb" { - return fmt.Sprintf("(%s < @%s)", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, namedParameterSuffix)), searchClauseNamedParams, nil + return fmt.Sprintf("(%s < @%s)", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, searchParam.Modifier, namedParameterSuffix)), searchClauseNamedParams, nil } else if searchParamValue.Prefix == "le" { - return fmt.Sprintf("(%s <= @%s)", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, namedParameterSuffix)), searchClauseNamedParams, nil + return fmt.Sprintf("(%s <= @%s)", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, searchParam.Modifier, namedParameterSuffix)), searchClauseNamedParams, nil } else if searchParamValue.Prefix == "gt" || searchParamValue.Prefix == "sa" { - return fmt.Sprintf("(%s > @%s)", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, namedParameterSuffix)), searchClauseNamedParams, nil + return fmt.Sprintf("(%s > @%s)", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, searchParam.Modifier, namedParameterSuffix)), searchClauseNamedParams, nil } else if searchParamValue.Prefix == "ge" { - return fmt.Sprintf("(%s >= @%s)", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, namedParameterSuffix)), searchClauseNamedParams, nil + return fmt.Sprintf("(%s >= @%s)", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, searchParam.Modifier, namedParameterSuffix)), searchClauseNamedParams, nil } else if searchParamValue.Prefix == "ne" { - return fmt.Sprintf("(%s <> @%s)", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, namedParameterSuffix)), searchClauseNamedParams, nil + return fmt.Sprintf("(%s <> @%s)", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, searchParam.Modifier, namedParameterSuffix)), searchClauseNamedParams, nil } else if searchParam.Modifier == "ap" { return "", nil, fmt.Errorf("search modifier 'ap' not supported for search parameter type %s (%s=%s)", searchParam.Type, searchParam.Name, searchParamValue.Value) } case SearchParameterTypeUri: if searchParam.Modifier == "" { - return fmt.Sprintf("(%s = @%s)", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, namedParameterSuffix)), searchClauseNamedParams, nil + return fmt.Sprintf("(%s = @%s)", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, searchParam.Modifier, namedParameterSuffix)), searchClauseNamedParams, nil } else if searchParam.Modifier == "below" { - searchClauseNamedParams[NamedParameterWithSuffix(searchParam.Name, namedParameterSuffix)] = searchParamValue.Value.(string) + "%" // column starts with "http://example.com" - return fmt.Sprintf("(%s LIKE @%s)", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, namedParameterSuffix)), searchClauseNamedParams, nil + searchClauseNamedParams[NamedParameterWithSuffix(searchParam.Name, searchParam.Modifier, namedParameterSuffix)] = searchParamValue.Value.(string) + "%" // column starts with "http://example.com" + return fmt.Sprintf("(%s LIKE @%s)", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, searchParam.Modifier, namedParameterSuffix)), searchClauseNamedParams, nil } else if searchParam.Modifier == "above" { return "", nil, fmt.Errorf("search modifier 'above' not supported for search parameter type %s (%s=%s)", searchParam.Type, searchParam.Name, searchParamValue.Value) } @@ -524,14 +522,14 @@ func SearchCodeToWhereClause(searchParam SearchParameter, searchParamValue Searc //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// case SearchParameterTypeString: if searchParam.Modifier == "" { - searchClauseNamedParams[NamedParameterWithSuffix(searchParam.Name, namedParameterSuffix)] = searchParamValue.Value.(string) + "%" // "eve" matches "Eve" and "Evelyn" - return fmt.Sprintf("(%sJson.value LIKE @%s)", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, namedParameterSuffix)), searchClauseNamedParams, nil + searchClauseNamedParams[NamedParameterWithSuffix(searchParam.Name, searchParam.Modifier, namedParameterSuffix)] = searchParamValue.Value.(string) + "%" // "eve" matches "Eve" and "Evelyn" + return fmt.Sprintf("(%sJson.value LIKE @%s)", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, searchParam.Modifier, namedParameterSuffix)), searchClauseNamedParams, nil } else if searchParam.Modifier == "exact" { // "eve" matches "eve" (not "Eve" or "EVE") - return fmt.Sprintf("(%sJson.value = @%s)", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, namedParameterSuffix)), searchClauseNamedParams, nil + return fmt.Sprintf("(%sJson.value = @%s)", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, searchParam.Modifier, namedParameterSuffix)), searchClauseNamedParams, nil } else if searchParam.Modifier == "contains" { - searchClauseNamedParams[NamedParameterWithSuffix(searchParam.Name, namedParameterSuffix)] = "%" + searchParamValue.Value.(string) + "%" // "eve" matches "Eve", "Evelyn" and "Severine" - return fmt.Sprintf("(%sJson.value LIKE @%s)", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, namedParameterSuffix)), searchClauseNamedParams, nil + searchClauseNamedParams[NamedParameterWithSuffix(searchParam.Name, searchParam.Modifier, namedParameterSuffix)] = "%" + searchParamValue.Value.(string) + "%" // "eve" matches "Eve", "Evelyn" and "Severine" + return fmt.Sprintf("(%sJson.value LIKE @%s)", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, searchParam.Modifier, namedParameterSuffix)), searchClauseNamedParams, nil } case SearchParameterTypeQuantity: @@ -539,17 +537,17 @@ func SearchCodeToWhereClause(searchParam SearchParameter, searchParamValue Searc var clause string if searchParamValue.Prefix == "" || searchParamValue.Prefix == "eq" { //TODO: when no prefix is specified, we need to search using BETWEEN (+/- 0.05) - clause = fmt.Sprintf("%sJson.value ->> '$.value' = @%s", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, namedParameterSuffix)) + clause = fmt.Sprintf("%sJson.value ->> '$.value' = @%s", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, searchParam.Modifier, namedParameterSuffix)) } else if searchParamValue.Prefix == "lt" || searchParamValue.Prefix == "eb" { - clause = fmt.Sprintf("%sJson.value ->> '$.value' < @%s", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, namedParameterSuffix)) + clause = fmt.Sprintf("%sJson.value ->> '$.value' < @%s", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, searchParam.Modifier, namedParameterSuffix)) } else if searchParamValue.Prefix == "le" { - clause = fmt.Sprintf("%sJson.value ->> '$.value' <= @%s", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, namedParameterSuffix)) + clause = fmt.Sprintf("%sJson.value ->> '$.value' <= @%s", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, searchParam.Modifier, namedParameterSuffix)) } else if searchParamValue.Prefix == "gt" || searchParamValue.Prefix == "sa" { - clause = fmt.Sprintf("%sJson.value ->> '$.value' > @%s", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, namedParameterSuffix)) + clause = fmt.Sprintf("%sJson.value ->> '$.value' > @%s", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, searchParam.Modifier, namedParameterSuffix)) } else if searchParamValue.Prefix == "ge" { - clause = fmt.Sprintf("%sJson.value ->> '$.value' >= @%s", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, namedParameterSuffix)) + clause = fmt.Sprintf("%sJson.value ->> '$.value' >= @%s", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, searchParam.Modifier, namedParameterSuffix)) } else if searchParamValue.Prefix == "ne" { - clause = fmt.Sprintf("%sJson.value ->> '$.value' <> @%s", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, namedParameterSuffix)) + clause = fmt.Sprintf("%sJson.value ->> '$.value' <> @%s", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, searchParam.Modifier, namedParameterSuffix)) } else if searchParamValue.Prefix == "ap" { return "", nil, fmt.Errorf("search modifier 'ap' not supported for search parameter type %s (%s=%s)", searchParam.Type, searchParam.Name, searchParamValue.Value) } @@ -561,7 +559,7 @@ func SearchCodeToWhereClause(searchParam SearchParameter, searchParamValue Searc for _, k := range allowedSecondaryKeys { namedParameterKey := fmt.Sprintf("%s%s", searchParam.Name, strings.Title(k)) if _, ok := searchParamValue.SecondaryValues[namedParameterKey]; ok { - clause += fmt.Sprintf(` AND %sJson.value ->> '$.%s' = @%s`, searchParam.Name, k, NamedParameterWithSuffix(namedParameterKey, namedParameterSuffix)) + clause += fmt.Sprintf(` AND %sJson.value ->> '$.%s' = @%s`, searchParam.Name, k, NamedParameterWithSuffix(namedParameterKey, searchParam.Modifier, namedParameterSuffix)) } } @@ -591,9 +589,9 @@ func SearchCodeToWhereClause(searchParam SearchParameter, searchParamValue Searc clause := []string{} if searchParamValue.Value.(string) != "" { if searchParam.Modifier == "" { - clause = append(clause, fmt.Sprintf("%sJson.value ->> '$.code' = @%s", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, namedParameterSuffix))) + clause = append(clause, fmt.Sprintf("%sJson.value ->> '$.code' = @%s", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, searchParam.Modifier, namedParameterSuffix))) } else if searchParam.Modifier == "not" { - clause = append(clause, fmt.Sprintf("%sJson.value ->> '$.code' <> @%s", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, namedParameterSuffix))) + clause = append(clause, fmt.Sprintf("%sJson.value ->> '$.code' <> @%s", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, searchParam.Modifier, namedParameterSuffix))) } } @@ -604,14 +602,14 @@ func SearchCodeToWhereClause(searchParam SearchParameter, searchParamValue Searc for _, k := range allowedSecondaryKeys { namedParameterKey := fmt.Sprintf("%s%s", searchParam.Name, strings.Title(k)) if _, ok := searchParamValue.SecondaryValues[namedParameterKey]; ok { - clause = append(clause, fmt.Sprintf(`%sJson.value ->> '$.%s' = @%s`, searchParam.Name, k, NamedParameterWithSuffix(namedParameterKey, namedParameterSuffix))) + clause = append(clause, fmt.Sprintf(`%sJson.value ->> '$.%s' = @%s`, searchParam.Name, k, NamedParameterWithSuffix(namedParameterKey, searchParam.Modifier, namedParameterSuffix))) } } return fmt.Sprintf("(%s)", strings.Join(clause, " AND ")), searchClauseNamedParams, nil case SearchParameterTypeKeyword: //setup the clause - return fmt.Sprintf("(%s = @%s)", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, namedParameterSuffix)), searchClauseNamedParams, nil + return fmt.Sprintf("(%s = @%s)", searchParam.Name, NamedParameterWithSuffix(searchParam.Name, searchParam.Modifier, namedParameterSuffix)), searchClauseNamedParams, nil case SearchParameterTypeReference: return "", nil, fmt.Errorf("search parameter type %s not supported", searchParam.Type) } diff --git a/backend/pkg/database/gorm_repository_query_sql_test.go b/backend/pkg/database/gorm_repository_query_sql_test.go index 3605574a5..756b8569d 100644 --- a/backend/pkg/database/gorm_repository_query_sql_test.go +++ b/backend/pkg/database/gorm_repository_query_sql_test.go @@ -149,7 +149,7 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithMultipleWhereCon }) } -func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenWithNotModifier() { +func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithPrimitiveOrderByAggregation() { //setup sqliteRepo := suite.TestRepository.(*GormRepository) sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true}) @@ -160,9 +160,10 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenWithNotModi sqlQuery, err := sqliteRepo.sqlQueryResources(authContext, models.QueryResource{ Select: []string{}, Where: map[string]interface{}{ - "code:not": "test_code", + "activityCode": "test_code", }, - From: "Observation", + From: "CarePlan", + Aggregations: &models.QueryResourceAggregations{OrderBy: &models.QueryResourceAggregation{Field: "instantiatesUri"}}, }) require.NoError(suite.T(), err) var results []map[string]interface{} @@ -175,18 +176,17 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenWithNotModi require.Equal(suite.T(), strings.Join([]string{ "SELECT fhir.*", - "FROM fhir_observation as fhir, json_each(fhir.code) as codeJson", - "WHERE ((codeJson.value ->> '$.code' <> ?)) AND (user_id = ?)", + "FROM fhir_care_plan as fhir, json_each(fhir.activityCode) as activityCodeJson", + "WHERE ((activityCodeJson.value ->> '$.code' = ?)) AND (user_id = ?)", "GROUP BY `fhir`.`id`", - "ORDER BY fhir.sort_date DESC", - }, " "), - sqlString) + "ORDER BY fhir.instantiatesUri ASC", + }, " "), sqlString) require.Equal(suite.T(), sqlParams, []interface{}{ "test_code", "00000000-0000-0000-0000-000000000000", }) } -func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenMultipleANDValuesWithNotModifier() { +func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithKeywordOrderByAggregation() { //setup sqliteRepo := suite.TestRepository.(*GormRepository) sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true}) @@ -195,11 +195,10 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenMultipleAND authContext := context.WithValue(context.Background(), pkg.ContextKeyTypeAuthUsername, "test_username") sqlQuery, err := sqliteRepo.sqlQueryResources(authContext, models.QueryResource{ - Select: []string{}, - Where: map[string]interface{}{ - "code:not": []string{"test_code", "test_code2"}, //AND condition - }, - From: "Observation", + Select: []string{}, + Where: map[string]interface{}{}, + From: "CarePlan", + Aggregations: &models.QueryResourceAggregations{OrderBy: &models.QueryResourceAggregation{Field: "id"}}, }) require.NoError(suite.T(), err) var results []map[string]interface{} @@ -212,18 +211,17 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenMultipleAND require.Equal(suite.T(), strings.Join([]string{ "SELECT fhir.*", - "FROM fhir_observation as fhir, json_each(fhir.code) as codeJson", - "WHERE ((codeJson.value ->> '$.code' <> ?)) AND ((codeJson.value ->> '$.code' <> ?)) AND (user_id = ?)", + "FROM fhir_care_plan as fhir", + "WHERE (user_id = ?)", "GROUP BY `fhir`.`id`", - "ORDER BY fhir.sort_date DESC", - }, " "), - sqlString) + "ORDER BY fhir.id ASC", + }, " "), sqlString) require.Equal(suite.T(), sqlParams, []interface{}{ - "test_code", "test_code2", "00000000-0000-0000-0000-000000000000", + "00000000-0000-0000-0000-000000000000", }) } -func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenMultipleORValues() { +func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithComplexOrderByAggregation() { //setup sqliteRepo := suite.TestRepository.(*GormRepository) sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true}) @@ -234,9 +232,10 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenMultipleORV sqlQuery, err := sqliteRepo.sqlQueryResources(authContext, models.QueryResource{ Select: []string{}, Where: map[string]interface{}{ - "code": "test_code,test_code2", //OR condition + "code": "test_code", }, - From: "Observation", + From: "Observation", + Aggregations: &models.QueryResourceAggregations{OrderBy: &models.QueryResourceAggregation{Field: "valueString:value"}}, }) require.NoError(suite.T(), err) var results []map[string]interface{} @@ -249,18 +248,17 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenMultipleORV require.Equal(suite.T(), strings.Join([]string{ "SELECT fhir.*", - "FROM fhir_observation as fhir, json_each(fhir.code) as codeJson", - "WHERE ((codeJson.value ->> '$.code' = ?)) OR ((codeJson.value ->> '$.code' = ?)) AND (user_id = ?)", + "FROM fhir_observation as fhir, json_each(fhir.code) as codeJson, json_each(fhir.valueString) as valueStringJson", + "WHERE ((codeJson.value ->> '$.code' = ?)) AND (user_id = ?)", "GROUP BY `fhir`.`id`", - "ORDER BY fhir.sort_date DESC", - }, " "), - sqlString) + "ORDER BY (valueStringJson.value ->> '$.value') ASC", + }, " "), sqlString) require.Equal(suite.T(), sqlParams, []interface{}{ - "test_code", "test_code2", "00000000-0000-0000-0000-000000000000", + "test_code", "00000000-0000-0000-0000-000000000000", }) } -func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenMixedMultipleANDORValues() { +func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithPrimitiveCountByAggregation() { //setup sqliteRepo := suite.TestRepository.(*GormRepository) sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true}) @@ -271,10 +269,10 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenMixedMultip sqlQuery, err := sqliteRepo.sqlQueryResources(authContext, models.QueryResource{ Select: []string{}, Where: map[string]interface{}{ - "code:not": []string{"test_code", "test_code2", "test_code3"}, //AND condition - "code": "test_code4,test_code5,test_code6", //OR condition + "activityCode": "test_code", }, - From: "Observation", + From: "CarePlan", + Aggregations: &models.QueryResourceAggregations{CountBy: &models.QueryResourceAggregation{Field: "instantiatesUri"}}, }) require.NoError(suite.T(), err) var results []map[string]interface{} @@ -286,19 +284,18 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenMixedMultip require.NoError(suite.T(), err) require.Equal(suite.T(), strings.Join([]string{ - "SELECT fhir.*", - "FROM fhir_observation as fhir, json_each(fhir.code) as codeJson", - "WHERE ((codeJson.value ->> '$.code' <> ?)) AND ((codeJson.value ->> '$.code' <> ?)) AND ((codeJson.value ->> '$.code' <> ?)) AND ((codeJson.value ->> '$.code' = ?) OR (codeJson.value ->> '$.code' = ?) OR (codeJson.value ->> '$.code' = ?)) AND (user_id = ?)", - "GROUP BY `fhir`.`id`", - "ORDER BY fhir.sort_date DESC", - }, " "), - sqlString) + "SELECT count(*) as value, fhir.instantiatesUri as label", + "FROM fhir_care_plan as fhir, json_each(fhir.activityCode) as activityCodeJson", + "WHERE ((activityCodeJson.value ->> '$.code' = ?)) AND (user_id = ?)", + "GROUP BY `fhir`.`instantiatesUri`", + "ORDER BY count(*) DESC", + }, " "), sqlString) require.Equal(suite.T(), sqlParams, []interface{}{ - "test_code", "test_code2", "test_code3", "test_code4", "00000000-0000-0000-0000-000000000000", + "test_code", "00000000-0000-0000-0000-000000000000", }) } -func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithPrimitiveOrderByAggregation() { +func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithKeywordCountByAggregation() { //setup sqliteRepo := suite.TestRepository.(*GormRepository) sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true}) @@ -312,7 +309,7 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithPrimitiveOrderBy "activityCode": "test_code", }, From: "CarePlan", - Aggregations: &models.QueryResourceAggregations{OrderBy: &models.QueryResourceAggregation{Field: "instantiatesUri"}}, + Aggregations: &models.QueryResourceAggregations{CountBy: &models.QueryResourceAggregation{Field: "source_resource_type"}}, }) require.NoError(suite.T(), err) var results []map[string]interface{} @@ -324,18 +321,18 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithPrimitiveOrderBy require.NoError(suite.T(), err) require.Equal(suite.T(), strings.Join([]string{ - "SELECT fhir.*", + "SELECT count(*) as value, fhir.source_resource_type as label", "FROM fhir_care_plan as fhir, json_each(fhir.activityCode) as activityCodeJson", "WHERE ((activityCodeJson.value ->> '$.code' = ?)) AND (user_id = ?)", - "GROUP BY `fhir`.`id`", - "ORDER BY fhir.instantiatesUri ASC", + "GROUP BY `fhir`.`source_resource_type`", + "ORDER BY count(*) DESC", }, " "), sqlString) require.Equal(suite.T(), sqlParams, []interface{}{ "test_code", "00000000-0000-0000-0000-000000000000", }) } -func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithKeywordOrderByAggregation() { +func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithWildcardCountByAggregation() { //setup sqliteRepo := suite.TestRepository.(*GormRepository) sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true}) @@ -347,7 +344,7 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithKeywordOrderByAg Select: []string{}, Where: map[string]interface{}{}, From: "CarePlan", - Aggregations: &models.QueryResourceAggregations{OrderBy: &models.QueryResourceAggregation{Field: "id"}}, + Aggregations: &models.QueryResourceAggregations{CountBy: &models.QueryResourceAggregation{Field: "*"}}, }) require.NoError(suite.T(), err) var results []map[string]interface{} @@ -359,18 +356,18 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithKeywordOrderByAg require.NoError(suite.T(), err) require.Equal(suite.T(), strings.Join([]string{ - "SELECT fhir.*", + "SELECT count(*) as value, fhir.source_resource_type as label", "FROM fhir_care_plan as fhir", "WHERE (user_id = ?)", - "GROUP BY `fhir`.`id`", - "ORDER BY fhir.id ASC", + "GROUP BY `fhir`.`source_resource_type`", + "ORDER BY count(*) DESC", }, " "), sqlString) require.Equal(suite.T(), sqlParams, []interface{}{ "00000000-0000-0000-0000-000000000000", }) } -func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithComplexOrderByAggregation() { +func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithComplexCountByAggregation() { //setup sqliteRepo := suite.TestRepository.(*GormRepository) sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true}) @@ -384,7 +381,7 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithComplexOrderByAg "code": "test_code", }, From: "Observation", - Aggregations: &models.QueryResourceAggregations{OrderBy: &models.QueryResourceAggregation{Field: "valueString:value"}}, + Aggregations: &models.QueryResourceAggregations{CountBy: &models.QueryResourceAggregation{Field: "code:code"}}, }) require.NoError(suite.T(), err) var results []map[string]interface{} @@ -396,18 +393,18 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithComplexOrderByAg require.NoError(suite.T(), err) require.Equal(suite.T(), strings.Join([]string{ - "SELECT fhir.*", - "FROM fhir_observation as fhir, json_each(fhir.code) as codeJson, json_each(fhir.valueString) as valueStringJson", + "SELECT (codeJson.value ->> '$.code') as label, count(*) as value", + "FROM fhir_observation as fhir, json_each(fhir.code) as codeJson", "WHERE ((codeJson.value ->> '$.code' = ?)) AND (user_id = ?)", - "GROUP BY `fhir`.`id`", - "ORDER BY (valueStringJson.value ->> '$.value') ASC", + "GROUP BY (codeJson.value ->> '$.code')", + "ORDER BY count(*) DESC", }, " "), sqlString) require.Equal(suite.T(), sqlParams, []interface{}{ "test_code", "00000000-0000-0000-0000-000000000000", }) } -func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithPrimitiveCountByAggregation() { +func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithComplexGroupByWithOrderByMaxFnAggregation() { //setup sqliteRepo := suite.TestRepository.(*GormRepository) sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true}) @@ -418,10 +415,13 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithPrimitiveCountBy sqlQuery, err := sqliteRepo.sqlQueryResources(authContext, models.QueryResource{ Select: []string{}, Where: map[string]interface{}{ - "activityCode": "test_code", + "code": "test_code", + }, + From: "Observation", + Aggregations: &models.QueryResourceAggregations{ + GroupBy: &models.QueryResourceAggregation{Field: "code:code"}, + OrderBy: &models.QueryResourceAggregation{Field: "sort_date", Function: "max"}, }, - From: "CarePlan", - Aggregations: &models.QueryResourceAggregations{CountBy: &models.QueryResourceAggregation{Field: "instantiatesUri"}}, }) require.NoError(suite.T(), err) var results []map[string]interface{} @@ -433,18 +433,18 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithPrimitiveCountBy require.NoError(suite.T(), err) require.Equal(suite.T(), strings.Join([]string{ - "SELECT count(*) as value, fhir.instantiatesUri as label", - "FROM fhir_care_plan as fhir, json_each(fhir.activityCode) as activityCodeJson", - "WHERE ((activityCodeJson.value ->> '$.code' = ?)) AND (user_id = ?)", - "GROUP BY `fhir`.`instantiatesUri`", - "ORDER BY count(*) DESC", + "SELECT (codeJson.value ->> '$.code') as label, max(fhir.sort_date) as value", + "FROM fhir_observation as fhir, json_each(fhir.code) as codeJson", + "WHERE ((codeJson.value ->> '$.code' = ?)) AND (user_id = ?)", + "GROUP BY (codeJson.value ->> '$.code')", + "ORDER BY max(fhir.sort_date) DESC", }, " "), sqlString) require.Equal(suite.T(), sqlParams, []interface{}{ "test_code", "00000000-0000-0000-0000-000000000000", }) } -func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithKeywordCountByAggregation() { +func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenGroupByNoModifier() { //setup sqliteRepo := suite.TestRepository.(*GormRepository) sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true}) @@ -454,11 +454,11 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithKeywordCountByAg sqlQuery, err := sqliteRepo.sqlQueryResources(authContext, models.QueryResource{ Select: []string{}, - Where: map[string]interface{}{ - "activityCode": "test_code", + Where: map[string]interface{}{}, + From: "Observation", + Aggregations: &models.QueryResourceAggregations{ + GroupBy: &models.QueryResourceAggregation{Field: "code"}, }, - From: "CarePlan", - Aggregations: &models.QueryResourceAggregations{CountBy: &models.QueryResourceAggregation{Field: "source_resource_type"}}, }) require.NoError(suite.T(), err) var results []map[string]interface{} @@ -470,18 +470,18 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithKeywordCountByAg require.NoError(suite.T(), err) require.Equal(suite.T(), strings.Join([]string{ - "SELECT count(*) as value, fhir.source_resource_type as label", - "FROM fhir_care_plan as fhir, json_each(fhir.activityCode) as activityCodeJson", - "WHERE ((activityCodeJson.value ->> '$.code' = ?)) AND (user_id = ?)", - "GROUP BY `fhir`.`source_resource_type`", + "SELECT ((codeJson.value ->> '$.system') || '|' || (codeJson.value ->> '$.code')) as label, count(*) as value", + "FROM fhir_observation as fhir, json_each(fhir.code) as codeJson", + "WHERE (user_id = ?)", + "GROUP BY ((codeJson.value ->> '$.system') || '|' || (codeJson.value ->> '$.code'))", "ORDER BY count(*) DESC", }, " "), sqlString) require.Equal(suite.T(), sqlParams, []interface{}{ - "test_code", "00000000-0000-0000-0000-000000000000", + "00000000-0000-0000-0000-000000000000", }) } -func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithWildcardCountByAggregation() { +func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenGroupByNoModifierWithLimit() { //setup sqliteRepo := suite.TestRepository.(*GormRepository) sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true}) @@ -489,11 +489,15 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithWildcardCountByA //test authContext := context.WithValue(context.Background(), pkg.ContextKeyTypeAuthUsername, "test_username") + limit := 10 sqlQuery, err := sqliteRepo.sqlQueryResources(authContext, models.QueryResource{ - Select: []string{}, - Where: map[string]interface{}{}, - From: "CarePlan", - Aggregations: &models.QueryResourceAggregations{CountBy: &models.QueryResourceAggregation{Field: "*"}}, + Select: []string{}, + Where: map[string]interface{}{}, + From: "Observation", + Limit: &limit, + Aggregations: &models.QueryResourceAggregations{ + GroupBy: &models.QueryResourceAggregation{Field: "code"}, + }, }) require.NoError(suite.T(), err) var results []map[string]interface{} @@ -505,18 +509,19 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithWildcardCountByA require.NoError(suite.T(), err) require.Equal(suite.T(), strings.Join([]string{ - "SELECT count(*) as value, fhir.source_resource_type as label", - "FROM fhir_care_plan as fhir", + "SELECT ((codeJson.value ->> '$.system') || '|' || (codeJson.value ->> '$.code')) as label, count(*) as value", + "FROM fhir_observation as fhir, json_each(fhir.code) as codeJson", "WHERE (user_id = ?)", - "GROUP BY `fhir`.`source_resource_type`", + "GROUP BY ((codeJson.value ->> '$.system') || '|' || (codeJson.value ->> '$.code'))", "ORDER BY count(*) DESC", + "LIMIT 10", }, " "), sqlString) require.Equal(suite.T(), sqlParams, []interface{}{ "00000000-0000-0000-0000-000000000000", }) } -func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithComplexCountByAggregation() { +func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenWithNotModifier() { //setup sqliteRepo := suite.TestRepository.(*GormRepository) sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true}) @@ -527,10 +532,9 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithComplexCountByAg sqlQuery, err := sqliteRepo.sqlQueryResources(authContext, models.QueryResource{ Select: []string{}, Where: map[string]interface{}{ - "code": "test_code", + "code:not": "test_code", }, - From: "Observation", - Aggregations: &models.QueryResourceAggregations{CountBy: &models.QueryResourceAggregation{Field: "code:code"}}, + From: "Observation", }) require.NoError(suite.T(), err) var results []map[string]interface{} @@ -542,18 +546,19 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithComplexCountByAg require.NoError(suite.T(), err) require.Equal(suite.T(), strings.Join([]string{ - "SELECT (codeJson.value ->> '$.code') as label, count(*) as value", + "SELECT fhir.*", "FROM fhir_observation as fhir, json_each(fhir.code) as codeJson", - "WHERE ((codeJson.value ->> '$.code' = ?)) AND (user_id = ?)", - "GROUP BY (codeJson.value ->> '$.code')", - "ORDER BY count(*) DESC", - }, " "), sqlString) + "WHERE ((codeJson.value ->> '$.code' <> ?)) AND (user_id = ?)", + "GROUP BY `fhir`.`id`", + "ORDER BY fhir.sort_date DESC", + }, " "), + sqlString) require.Equal(suite.T(), sqlParams, []interface{}{ "test_code", "00000000-0000-0000-0000-000000000000", }) } -func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithComplexGroupByWithOrderByMaxFnAggregation() { +func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenMultipleANDValuesWithNotModifier() { //setup sqliteRepo := suite.TestRepository.(*GormRepository) sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true}) @@ -564,13 +569,46 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithComplexGroupByWi sqlQuery, err := sqliteRepo.sqlQueryResources(authContext, models.QueryResource{ Select: []string{}, Where: map[string]interface{}{ - "code": "test_code", + "code:not": []string{"test_code", "test_code2"}, //AND condition }, From: "Observation", - Aggregations: &models.QueryResourceAggregations{ - GroupBy: &models.QueryResourceAggregation{Field: "code:code"}, - OrderBy: &models.QueryResourceAggregation{Field: "sort_date", Function: "max"}, + }) + require.NoError(suite.T(), err) + var results []map[string]interface{} + statement := sqlQuery.Find(&results).Statement + sqlString := statement.SQL.String() + sqlParams := statement.Vars + + //assert + require.NoError(suite.T(), err) + require.Equal(suite.T(), + strings.Join([]string{ + "SELECT fhir.*", + "FROM fhir_observation as fhir, json_each(fhir.code) as codeJson", + "WHERE ((codeJson.value ->> '$.code' <> ?)) AND ((codeJson.value ->> '$.code' <> ?)) AND (user_id = ?)", + "GROUP BY `fhir`.`id`", + "ORDER BY fhir.sort_date DESC", + }, " "), + sqlString) + require.Equal(suite.T(), sqlParams, []interface{}{ + "test_code", "test_code2", "00000000-0000-0000-0000-000000000000", + }) +} + +func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenMultipleORValues() { + //setup + sqliteRepo := suite.TestRepository.(*GormRepository) + sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true}) + + //test + authContext := context.WithValue(context.Background(), pkg.ContextKeyTypeAuthUsername, "test_username") + + sqlQuery, err := sqliteRepo.sqlQueryResources(authContext, models.QueryResource{ + Select: []string{}, + Where: map[string]interface{}{ + "code": "test_code,test_code2", //OR condition }, + From: "Observation", }) require.NoError(suite.T(), err) var results []map[string]interface{} @@ -582,18 +620,19 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithComplexGroupByWi require.NoError(suite.T(), err) require.Equal(suite.T(), strings.Join([]string{ - "SELECT (codeJson.value ->> '$.code') as label, max(fhir.sort_date) as value", + "SELECT fhir.*", "FROM fhir_observation as fhir, json_each(fhir.code) as codeJson", - "WHERE ((codeJson.value ->> '$.code' = ?)) AND (user_id = ?)", - "GROUP BY (codeJson.value ->> '$.code')", - "ORDER BY max(fhir.sort_date) DESC", - }, " "), sqlString) + "WHERE ((codeJson.value ->> '$.code' = ?) OR (codeJson.value ->> '$.code' = ?)) AND (user_id = ?)", + "GROUP BY `fhir`.`id`", + "ORDER BY fhir.sort_date DESC", + }, " "), + sqlString) require.Equal(suite.T(), sqlParams, []interface{}{ - "test_code", "00000000-0000-0000-0000-000000000000", + "test_code", "test_code2", "00000000-0000-0000-0000-000000000000", }) } -func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenGroupByNoModifier() { +func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenMultipleORANDValues() { //setup sqliteRepo := suite.TestRepository.(*GormRepository) sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true}) @@ -603,11 +642,10 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenGroupByNoMo sqlQuery, err := sqliteRepo.sqlQueryResources(authContext, models.QueryResource{ Select: []string{}, - Where: map[string]interface{}{}, - From: "Observation", - Aggregations: &models.QueryResourceAggregations{ - GroupBy: &models.QueryResourceAggregation{Field: "code"}, + Where: map[string]interface{}{ + "code": []string{"test_code,test_code2", "test_code3,test_code4"}, //OR-AND condition }, + From: "Observation", }) require.NoError(suite.T(), err) var results []map[string]interface{} @@ -619,18 +657,19 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenGroupByNoMo require.NoError(suite.T(), err) require.Equal(suite.T(), strings.Join([]string{ - "SELECT ((codeJson.value ->> '$.system') || '|' || (codeJson.value ->> '$.code')) as label, count(*) as value", + "SELECT fhir.*", "FROM fhir_observation as fhir, json_each(fhir.code) as codeJson", - "WHERE (user_id = ?)", - "GROUP BY ((codeJson.value ->> '$.system') || '|' || (codeJson.value ->> '$.code'))", - "ORDER BY count(*) DESC", - }, " "), sqlString) + "WHERE ((codeJson.value ->> '$.code' = ?) OR (codeJson.value ->> '$.code' = ?)) AND ((codeJson.value ->> '$.code' = ?) OR (codeJson.value ->> '$.code' = ?)) AND (user_id = ?)", + "GROUP BY `fhir`.`id`", + "ORDER BY fhir.sort_date DESC", + }, " "), + sqlString) require.Equal(suite.T(), sqlParams, []interface{}{ - "00000000-0000-0000-0000-000000000000", + "test_code", "test_code2", "test_code3", "test_code4", "00000000-0000-0000-0000-000000000000", }) } -func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenGroupByNoModifierWithLimit() { +func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenMultipleModifiersMultipleANDORValues() { //setup sqliteRepo := suite.TestRepository.(*GormRepository) sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true}) @@ -638,15 +677,13 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenGroupByNoMo //test authContext := context.WithValue(context.Background(), pkg.ContextKeyTypeAuthUsername, "test_username") - limit := 10 sqlQuery, err := sqliteRepo.sqlQueryResources(authContext, models.QueryResource{ Select: []string{}, - Where: map[string]interface{}{}, - From: "Observation", - Limit: &limit, - Aggregations: &models.QueryResourceAggregations{ - GroupBy: &models.QueryResourceAggregation{Field: "code"}, + Where: map[string]interface{}{ + "code:not": []string{"test_code", "test_code2,test_code3"}, //AND-OR condition + "code": "test_code4,test_code5,test_code6", //OR condition }, + From: "Observation", }) require.NoError(suite.T(), err) var results []map[string]interface{} @@ -658,14 +695,14 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenGroupByNoMo require.NoError(suite.T(), err) require.Equal(suite.T(), strings.Join([]string{ - "SELECT ((codeJson.value ->> '$.system') || '|' || (codeJson.value ->> '$.code')) as label, count(*) as value", + "SELECT fhir.*", "FROM fhir_observation as fhir, json_each(fhir.code) as codeJson", - "WHERE (user_id = ?)", - "GROUP BY ((codeJson.value ->> '$.system') || '|' || (codeJson.value ->> '$.code'))", - "ORDER BY count(*) DESC", - "LIMIT 10", - }, " "), sqlString) + "WHERE ((codeJson.value ->> '$.code' <> ?)) AND ((codeJson.value ->> '$.code' <> ?) OR (codeJson.value ->> '$.code' <> ?)) AND ((codeJson.value ->> '$.code' = ?) OR (codeJson.value ->> '$.code' = ?) OR (codeJson.value ->> '$.code' = ?)) AND (user_id = ?)", + "GROUP BY `fhir`.`id`", + "ORDER BY fhir.sort_date DESC", + }, " "), + sqlString) require.Equal(suite.T(), sqlParams, []interface{}{ - "00000000-0000-0000-0000-000000000000", + "test_code", "test_code2", "test_code3", "test_code4", "test_code5", "test_code6", "00000000-0000-0000-0000-000000000000", }) } From 43dc56c65109c97028d6e804e12af23a708ff50a Mon Sep 17 00:00:00 2001 From: Jason Kulatunga Date: Tue, 20 Feb 2024 11:45:36 -0800 Subject: [PATCH 04/29] fixing tests. --- backend/pkg/constants.go | 17 +++++++++++++++++ backend/pkg/database/gorm_repository_query.go | 4 ++-- .../pkg/database/gorm_repository_query_test.go | 8 ++++---- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/backend/pkg/constants.go b/backend/pkg/constants.go index e87ed5bf9..c3ead6709 100644 --- a/backend/pkg/constants.go +++ b/backend/pkg/constants.go @@ -68,3 +68,20 @@ const ( IPSSectionsFunctionalStatus IPSSections = "functional_status" IPSSectionsAdvanceDirectives IPSSections = "advance_directives" ) + +var IPSSectionsList = []IPSSections{ + IPSSectionsMedicationSummary, + IPSSectionsAllergiesIntolerances, + IPSSectionsProblemList, + IPSSectionsImmunizations, + IPSSectionsHistoryOfProcedures, + IPSSectionsMedicalDevices, + IPSSectionsDiagnosticResults, + IPSSectionsVitalSigns, + IPSSectionsHistoryOfIllnesses, + IPSSectionsPregnancy, + IPSSectionsSocialHistory, + IPSSectionsPlanOfCare, + IPSSectionsFunctionalStatus, + IPSSectionsAdvanceDirectives, +} diff --git a/backend/pkg/database/gorm_repository_query.go b/backend/pkg/database/gorm_repository_query.go index f3284f85b..f329f1bb7 100644 --- a/backend/pkg/database/gorm_repository_query.go +++ b/backend/pkg/database/gorm_repository_query.go @@ -468,7 +468,7 @@ func ProcessSearchParameterValue(searchParameter SearchParameter, searchValueWit func NamedParameterWithSuffix(parameterName string, parameterModifier string, suffix string) string { if len(parameterModifier) > 0 { - return fmt.Sprintf("%s-%s_%s", parameterName, parameterModifier, suffix) + return fmt.Sprintf("%s_%s_%s", parameterName, parameterModifier, suffix) } else { return fmt.Sprintf("%s_%s", parameterName, suffix) } @@ -482,7 +482,7 @@ func SearchCodeToWhereClause(searchParam SearchParameter, searchParamValue Searc NamedParameterWithSuffix(searchParam.Name, searchParam.Modifier, namedParameterSuffix): searchParamValue.Value, } for k, v := range searchParamValue.SecondaryValues { - searchClauseNamedParams[NamedParameterWithSuffix(k, "", namedParameterSuffix)] = v + searchClauseNamedParams[NamedParameterWithSuffix(k, searchParam.Modifier, namedParameterSuffix)] = v } //parse the searchCode and searchCodeValue to determine the correct where clause diff --git a/backend/pkg/database/gorm_repository_query_test.go b/backend/pkg/database/gorm_repository_query_test.go index 116c11d0e..69e1d8a97 100644 --- a/backend/pkg/database/gorm_repository_query_test.go +++ b/backend/pkg/database/gorm_repository_query_test.go @@ -149,10 +149,10 @@ func TestSearchCodeToWhereClause(t *testing.T) { {SearchParameter{Type: "date", Name: "issueDate", Modifier: ""}, SearchParameterValue{Value: time.Date(2013, time.January, 14, 10, 0, 0, 0, time.UTC), Prefix: "lt", SecondaryValues: map[string]interface{}{}}, "1_1", "(issueDate < @issueDate_1_1)", map[string]interface{}{"issueDate_1_1": time.Date(2013, time.January, 14, 10, 0, 0, 0, time.UTC)}, false}, {SearchParameter{Type: "string", Name: "given", Modifier: ""}, SearchParameterValue{Value: "eve", Prefix: "", SecondaryValues: map[string]interface{}{}}, "0_0", "(givenJson.value LIKE @given_0_0)", map[string]interface{}{"given_0_0": "eve%"}, false}, - {SearchParameter{Type: "string", Name: "given", Modifier: "contains"}, SearchParameterValue{Value: "eve", Prefix: "", SecondaryValues: map[string]interface{}{}}, "0_0", "(givenJson.value LIKE @given_0_0)", map[string]interface{}{"given_0_0": "%eve%"}, false}, - {SearchParameter{Type: "string", Name: "given", Modifier: "exact"}, SearchParameterValue{Value: "eve", Prefix: "", SecondaryValues: map[string]interface{}{}}, "0_0", "(givenJson.value = @given_0_0)", map[string]interface{}{"given_0_0": "eve"}, false}, + {SearchParameter{Type: "string", Name: "given", Modifier: "contains"}, SearchParameterValue{Value: "eve", Prefix: "", SecondaryValues: map[string]interface{}{}}, "0_0", "(givenJson.value LIKE @given_contains_0_0)", map[string]interface{}{"given_contains_0_0": "%eve%"}, false}, + {SearchParameter{Type: "string", Name: "given", Modifier: "exact"}, SearchParameterValue{Value: "eve", Prefix: "", SecondaryValues: map[string]interface{}{}}, "0_0", "(givenJson.value = @given_exact_0_0)", map[string]interface{}{"given_exact_0_0": "eve"}, false}, - {SearchParameter{Type: "uri", Name: "url", Modifier: "below"}, SearchParameterValue{Value: "http://acme.org/fhir/", Prefix: "", SecondaryValues: map[string]interface{}{}}, "0_0", "(url LIKE @url_0_0)", map[string]interface{}{"url_0_0": "http://acme.org/fhir/%"}, false}, + {SearchParameter{Type: "uri", Name: "url", Modifier: "below"}, SearchParameterValue{Value: "http://acme.org/fhir/", Prefix: "", SecondaryValues: map[string]interface{}{}}, "0_0", "(url LIKE @url_below_0_0)", map[string]interface{}{"url_below_0_0": "http://acme.org/fhir/%"}, false}, {SearchParameter{Type: "uri", Name: "url", Modifier: "above"}, SearchParameterValue{Value: "http://acme.org/fhir/", Prefix: "", SecondaryValues: map[string]interface{}{}}, "0_0", "", map[string]interface{}{}, true}, //above modifier not supported {SearchParameter{Type: "quantity", Name: "valueQuantity", Modifier: ""}, SearchParameterValue{Value: float64(5.4), Prefix: "", SecondaryValues: map[string]interface{}{"valueQuantityCode": "mg"}}, "0_0", "(valueQuantityJson.value ->> '$.value' = @valueQuantity_0_0 AND valueQuantityJson.value ->> '$.code' = @valueQuantityCode_0_0)", map[string]interface{}{"valueQuantity_0_0": float64(5.4), "valueQuantityCode_0_0": "mg"}, false}, @@ -165,7 +165,7 @@ func TestSearchCodeToWhereClause(t *testing.T) { {SearchParameter{Type: "token", Name: "code", Modifier: ""}, SearchParameterValue{Value: "ha125", Prefix: "", SecondaryValues: map[string]interface{}{}}, "0_0", "(codeJson.value ->> '$.code' = @code_0_0)", map[string]interface{}{"code_0_0": "ha125"}, false}, {SearchParameter{Type: "token", Name: "identifier", Modifier: ""}, SearchParameterValue{Value: "MR|446053", Prefix: "", SecondaryValues: map[string]interface{}{"identifierSystem": "http://terminology.hl7.org/CodeSystem/v2-0203"}}, "0_0", "(identifierJson.value ->> '$.code' = @identifier_0_0 AND identifierJson.value ->> '$.system' = @identifierSystem_0_0)", map[string]interface{}{"identifier_0_0": "MR|446053", "identifierSystem_0_0": "http://terminology.hl7.org/CodeSystem/v2-0203"}, false}, {SearchParameter{Type: "token", Name: "gender", Modifier: ""}, SearchParameterValue{Value: "male", Prefix: "", SecondaryValues: map[string]interface{}{"genderSystem": "http://terminology.hl7.org/CodeSystem/v2-0203"}}, "0_0", "(genderJson.value ->> '$.code' = @gender_0_0 AND genderJson.value ->> '$.system' = @genderSystem_0_0)", map[string]interface{}{"gender_0_0": "male", "genderSystem_0_0": "http://terminology.hl7.org/CodeSystem/v2-0203"}, false}, - {SearchParameter{Type: "token", Name: "gender", Modifier: "not"}, SearchParameterValue{Value: "male", Prefix: "", SecondaryValues: map[string]interface{}{"genderSystem": "http://terminology.hl7.org/CodeSystem/v2-0203"}}, "0_0", "(genderJson.value ->> '$.code' <> @gender_0_0 AND genderJson.value ->> '$.system' = @genderSystem_0_0)", map[string]interface{}{"gender_0_0": "male", "genderSystem_0_0": "http://terminology.hl7.org/CodeSystem/v2-0203"}, false}, + {SearchParameter{Type: "token", Name: "gender", Modifier: "not"}, SearchParameterValue{Value: "male", Prefix: "", SecondaryValues: map[string]interface{}{"genderSystem": "http://terminology.hl7.org/CodeSystem/v2-0203"}}, "0_0", "(genderJson.value ->> '$.code' <> @gender_not_0_0 AND genderJson.value ->> '$.system' = @genderSystem_not_0_0)", map[string]interface{}{"gender_not_0_0": "male", "genderSystem_not_0_0": "http://terminology.hl7.org/CodeSystem/v2-0203"}, false}, {SearchParameter{Type: "keyword", Name: "id", Modifier: ""}, SearchParameterValue{Value: "1234", Prefix: "", SecondaryValues: map[string]interface{}{}}, "0_0", "(id = @id_0_0)", map[string]interface{}{"id_0_0": "1234"}, false}, } From 21d12dd312c3e470667b102f2211a9a487b328a0 Mon Sep 17 00:00:00 2001 From: Jason Kulatunga Date: Wed, 21 Feb 2024 14:15:36 -0800 Subject: [PATCH 05/29] trying to fix permissions error when pulling docker images without auth. --- .github/workflows/docker.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml index 0d9798cd9..5cf578d12 100644 --- a/.github/workflows/docker.yaml +++ b/.github/workflows/docker.yaml @@ -57,6 +57,14 @@ jobs: type=raw,value=${{ matrix.flavor }},enable=${{ github.ref_name == 'main' }} # if this is a (non main) branch build, tag it with the flavor and branch name (eg. main-branch and sandbox-branch) type=ref,event=branch,prefix=${{ matrix.flavor }}-,enable=${{ github.ref_name != 'main' }} + labels: | + maintainer=AnalogJ + org.opencontainers.image.title=Fasten Health - ${{ matrix.flavor }} + org.opencontainers.image.authors=Jason Kulatunga - support@fastenhealth.com + org.opencontainers.image.description=An open-source personal medical record that never leaves the patients hands without their consent + org.opencontainers.image.vendor=Fasten Health, Inc. + org.opencontainers.image.source=https://github.com/fastenhealth/fasten-onprem/ + org.opencontainers.image.revision=${{ github.sha }} images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} # Build and push Docker image with Buildx (don't push on PR) # https://github.com/docker/build-push-action From bf446a0e6e4d0eb5eeb052abfc9abae2f2bbd3e0 Mon Sep 17 00:00:00 2001 From: Jason Kulatunga Date: Wed, 21 Feb 2024 14:16:20 -0800 Subject: [PATCH 06/29] generate basic IPS summary bundle. Still missing lots of important functionality. --- backend/pkg/constants.go | 4 +- .../pkg/database/gorm_repository_summary.go | 446 +++++++++++++++--- backend/pkg/database/interface.go | 1 + backend/pkg/web/handler/summary.go | 13 + backend/pkg/web/server.go | 1 + 5 files changed, 396 insertions(+), 69 deletions(-) diff --git a/backend/pkg/constants.go b/backend/pkg/constants.go index c3ead6709..db8a6d754 100644 --- a/backend/pkg/constants.go +++ b/backend/pkg/constants.go @@ -61,7 +61,7 @@ const ( IPSSectionsMedicalDevices IPSSections = "medical_devices" IPSSectionsDiagnosticResults IPSSections = "diagnostic_results" IPSSectionsVitalSigns IPSSections = "vital_signs" - IPSSectionsHistoryOfIllnesses IPSSections = "history_of_illnesses" + IPSSectionsHistoryOfIllness IPSSections = "history_of_illness" IPSSectionsPregnancy IPSSections = "pregnancy" IPSSectionsSocialHistory IPSSections = "social_history" IPSSectionsPlanOfCare IPSSections = "plan_of_care" @@ -78,7 +78,7 @@ var IPSSectionsList = []IPSSections{ IPSSectionsMedicalDevices, IPSSectionsDiagnosticResults, IPSSectionsVitalSigns, - IPSSectionsHistoryOfIllnesses, + IPSSectionsHistoryOfIllness, IPSSectionsPregnancy, IPSSectionsSocialHistory, IPSSectionsPlanOfCare, diff --git a/backend/pkg/database/gorm_repository_summary.go b/backend/pkg/database/gorm_repository_summary.go index 1749904ef..de284bf00 100644 --- a/backend/pkg/database/gorm_repository_summary.go +++ b/backend/pkg/database/gorm_repository_summary.go @@ -2,85 +2,234 @@ package database import ( "context" + "encoding/json" + "fmt" "github.com/fastenhealth/fasten-onprem/backend/pkg" "github.com/fastenhealth/fasten-onprem/backend/pkg/models" - databaseModel "github.com/fastenhealth/fasten-onprem/backend/pkg/models/database" + "github.com/fastenhealth/gofhir-models/fhir401" + "github.com/google/uuid" + "log" + "time" ) +func (gr *GormRepository) GetInternationalPatientSummaryBundle(ctx context.Context) (interface{}, error) { + summaryTime := time.Now() + timestamp := summaryTime.Format(time.RFC3339) + + //Algorithm to create the IPS bundle + // 1. Generate the IPS Section Lists (GetInternationalPatientSummarySectionResources) + // - Process each resource, generating a Markdown narrative in the text field for each resource + // - keep track of the earliest and latest date of the resources in the section + // 2. Create the Composition Section (generateIPSCompositionSection) + // - Populate it with the data from the Header + // - Generate a Section Narrative, written in Markdown, which summarizes the contents of the section at a high level, with dates and counts + // 3. Query all the Patient Resources + // - Merge the Patient resources together? + // 4. Create a Fasten Health Organization resource. This is the custodian of the IPS + // 5. Create the IPS Composition + // - Populate it with the Composition Sections and references to the Patient resource + Fasten Health Organziation resource + // - Generate a Composition Narrative, written in Markdown, which summarizes the contents of the IPS & Patient at a high level, with dates and counts + // 6. Create the IPS Bundle + + //Step 1. Generate the IPS Section Lists + summarySectionResources, err := gr.GetInternationalPatientSummarySectionResources(ctx) + if err != nil { + return nil, err + } + + //Step 2. Create the Composition Section + compositionSections := []fhir401.CompositionSection{} + for sectionType, sectionResources := range summarySectionResources { + compositionSection, err := generateIPSCompositionSection(sectionType, sectionResources) + if err != nil { + return nil, err + } + compositionSections = append(compositionSections, *compositionSection) + } + + //TODO: Step 3. Query all the Patient Resources & merge them together + + //TODO: Step 4. Create a Fasten Health Organization resource. + + compositionUUID := uuid.New().String() + + //Step 5. Create the IPS Composition + ipsComposition := &fhir401.Composition{ + Id: stringPtr(compositionUUID), + Text: &fhir401.Narrative{ + Status: fhir401.NarrativeStatusGenerated, + Div: "PLACEHOLDER NARRATIVE SUMMARY FOR COMPOSITION", //TODO + }, + Identifier: &fhir401.Identifier{ + System: stringPtr("https://www.fastenhealth.com"), //TODO + Value: &compositionUUID, + }, + Status: fhir401.CompositionStatusFinal, + Type: fhir401.CodeableConcept{ + Coding: []fhir401.Coding{ + { + System: stringPtr("http://loinc.org"), + Code: stringPtr("60591-5"), + Display: stringPtr("Patient Summary"), + }, + }, + }, + Subject: &fhir401.Reference{ + Reference: stringPtr("Patient/123"), //TODO + }, + Date: timestamp, + Author: []fhir401.Reference{ + { + Reference: stringPtr("Organization/fastenhealth.com"), //TODO: The type of author(s) contribute to determine the "nature"of the Patient Summary: e.g. a "human-curated" IPS Vs. an "automatically generated" IPS. + }, + }, + Title: fmt.Sprintf("Patient Summary as of %s", summaryTime.Format("January 2, 2006 15:04")), + Attester: []fhir401.CompositionAttester{ + { + Mode: fhir401.CompositionAttestationModePersonal, + Time: ×tamp, + Party: &fhir401.Reference{ + Reference: stringPtr("Patient/123"), + }, + }, + }, + Custodian: &fhir401.Reference{ + Reference: stringPtr("Organization/fastenhealth.com"), + }, + Event: []fhir401.CompositionEvent{ + { + Code: []fhir401.CodeableConcept{ + { + Coding: []fhir401.Coding{ + { + System: stringPtr("http://terminology.hl7.org/CodeSystem/v3-ActClass"), + Code: stringPtr("PCPR"), + }, + }, + }, + }, + Period: &fhir401.Period{ + Start: ×tamp, //TODO: this should be the oldest record in the summary + End: ×tamp, + }, + }, + }, + } + + // Step 6. Create the IPS Bundle + bundleUUID := uuid.New().String() + ipsBundle := &fhir401.Bundle{ + Id: &bundleUUID, + Timestamp: ×tamp, + Language: stringPtr("en-US"), + Entry: []fhir401.BundleEntry{}, + Type: fhir401.BundleTypeDocument, + } + + // Add the Composition to the bundle + ipsCompositionJson, err := json.Marshal(ipsComposition) + if err != nil { + return nil, err + } + ipsBundle.Entry = append(ipsBundle.Entry, fhir401.BundleEntry{ + Resource: json.RawMessage(ipsCompositionJson), + }) + + // TODO: Add the Patient to the bundle + // TODO: Add the Fasten Health Organization to the bundle + + // Add all the resources to the bundle + for _, sectionResources := range summarySectionResources { + for _, resource := range sectionResources { + ipsBundle.Entry = append(ipsBundle.Entry, fhir401.BundleEntry{ + Resource: json.RawMessage(resource.ResourceRaw), + }) + } + } + + return ipsBundle, nil +} + // GetInternationalPatientSummary will generate an IPS bundle, which can then be used to generate a IPS QR code, PDF or JSON bundle // The IPS bundle will contain a summary of all the data in the system, including a list of all sources, and the main Patient // See: https://github.com/fastenhealth/fasten-onprem/issues/170 // See: https://github.com/jddamore/fhir-ips-server/blob/main/docs/Summary_Creation_Steps.md -func (gr *GormRepository) GetInternationalPatientSummary(ctx context.Context) (*models.Summary, error) { - currentUser, currentUserErr := gr.GetCurrentUser(ctx) - if currentUserErr != nil { - return nil, currentUserErr - } +func (gr *GormRepository) GetInternationalPatientSummarySectionResources(ctx context.Context) (map[pkg.IPSSections][]models.ResourceBase, error) { + + summarySectionResources := map[pkg.IPSSections][]models.ResourceBase{} - // we want a count of all resources for this user by type - var resourceCountResults []map[string]interface{} + // generate queries for each IPS Section + for ndx, _ := range pkg.IPSSectionsList { + sectionName := pkg.IPSSectionsList[ndx] - resourceTypes := databaseModel.GetAllowedResourceTypes() - for _, resourceType := range resourceTypes { - tableName, err := databaseModel.GetTableNameByResourceType(resourceType) + //initialize the section + summarySectionResources[sectionName] = []models.ResourceBase{} + + queries, err := generateIPSSectionQueries(sectionName) if err != nil { return nil, err } - var count int64 - - gr.QueryResources(ctx, models.QueryResource{ - Use: "", - Select: nil, - From: "", - Where: nil, - Limit: nil, - Offset: nil, - Aggregations: nil, - }) - result := gr.GormClient.WithContext(ctx). - Table(tableName). - Where(models.OriginBase{ - UserID: currentUser.ID, - }). - Count(&count) - if result.Error != nil { - return nil, result.Error - } - if count == 0 { - continue //don't add resource counts if the count is 0 + for qndx, _ := range queries { + results, err := gr.QueryResources(ctx, queries[qndx]) + if err != nil { + return nil, err + } + + resultsList := results.([]models.ResourceBase) + + //TODO: generate resource narrative + summarySectionResources[sectionName] = append(summarySectionResources[sectionName], resultsList...) } - resourceCountResults = append(resourceCountResults, map[string]interface{}{ - "resource_type": resourceType, - "count": count, - }) } - // we want a list of all sources (when they were last updated) - sources, err := gr.GetSources(ctx) - if err != nil { - return nil, err - } + return summarySectionResources, nil +} - // we want the main Patient for each source - patients, err := gr.GetPatientForSources(ctx) +func generateIPSCompositionSection(sectionType pkg.IPSSections, resources []models.ResourceBase) (*fhir401.CompositionSection, error) { + sectionTitle, sectionCode, err := generateIPSSectionHeaderInfo(sectionType) if err != nil { return nil, err } - if resourceCountResults == nil { - resourceCountResults = []map[string]interface{}{} - } - summary := &models.Summary{ - Sources: sources, - ResourceTypeCounts: resourceCountResults, - Patients: patients, + section := &fhir401.CompositionSection{ + Title: §ionTitle, + Code: §ionCode, } + if len(resources) == 0 { + section.EmptyReason = &fhir401.CodeableConcept{ + Text: stringPtr("No data available"), + Coding: []fhir401.Coding{ + { + System: stringPtr("http://terminology.hl7.org/CodeSystem/list-empty-reason"), + Code: stringPtr("unavailable"), + }, + }, + } + } else { + section.Entry = []fhir401.Reference{} + for _, resource := range resources { + reference := fhir401.Reference{ + Reference: stringPtr(fmt.Sprintf("%s/%s", resource.SourceResourceType, resource.SourceID)), + } + if err != nil { + return nil, err + } + section.Entry = append(section.Entry, reference) + } + + //TODO: Add the section narrative summary + section.Text = &fhir401.Narrative{ + Status: fhir401.NarrativeStatusGenerated, + Div: "PLACEHOLDER NARRATIVE SUMMARY FOR SECTION", + } - return summary, nil + } + return section, nil } // https://github.com/jddamore/fhir-ips-server/blob/main/docs/Summary_Creation_Steps.md +// Generate Resource Queries for each IPS Section func generateIPSSectionQueries(sectionType pkg.IPSSections) ([]models.QueryResource, error) { queries := []models.QueryResource{} @@ -180,22 +329,24 @@ func generateIPSSectionQueries(sectionType pkg.IPSSections) ([]models.QueryResou }) break case pkg.IPSSectionsAdvanceDirectives: - queries = append(queries, models.QueryResource{ - Select: nil, - From: "Consent", - Where: map[string]interface{}{ - "status": "active", - }, - }) + //queries = append(queries, models.QueryResource{ + // Select: nil, + // From: "Consent", + // Where: map[string]interface{}{ + // "status": "active", + // }, + //}) + log.Printf("warning: Consent FHIR resources are not supported yet. Skipping") break case pkg.IPSSectionsFunctionalStatus: - queries = append(queries, models.QueryResource{ - Select: nil, - From: "ClinicalImpression", - Where: map[string]interface{}{ - "status": "in-progress,completed", - }, - }) + //queries = append(queries, models.QueryResource{ + // Select: nil, + // From: "ClinicalImpression", + // Where: map[string]interface{}{ + // "status": "in-progress,completed", + // }, + //}) + log.Printf("warning: ClinicalImpression FHIR resources are not supported yet. Skipping") break case pkg.IPSSectionsMedicalDevices: queries = append(queries, models.QueryResource{ @@ -206,7 +357,7 @@ func generateIPSSectionQueries(sectionType pkg.IPSSections) ([]models.QueryResou }, }) break - case pkg.IPSSectionsHistoryOfIllnesses: + case pkg.IPSSectionsHistoryOfIllness: //TODO: last updated date should be older than 5 years (dateTime or period.high) //TODO: check if where clause with multiple modifiers for the same field works as expected queries = append(queries, models.QueryResource{ @@ -235,7 +386,168 @@ func generateIPSSectionQueries(sectionType pkg.IPSSections) ([]models.QueryResou "status:not": []string{"entered-in-error", "not-done"}, }, }) + break + default: + return nil, fmt.Errorf("unsupported section type: %s", sectionType) } return queries, nil } + +// generate header information for Composition Sections. Title & Code for each section +func generateIPSSectionHeaderInfo(sectionType pkg.IPSSections) (string, fhir401.CodeableConcept, error) { + switch sectionType { + case pkg.IPSSectionsMedicationSummary: + return "Medication Summary", fhir401.CodeableConcept{ + Coding: []fhir401.Coding{ + { + System: stringPtr("http://loinc.org"), + Code: stringPtr("10160-0"), + Display: stringPtr("Medication Summary"), + }, + }, + }, nil + case pkg.IPSSectionsAllergiesIntolerances: + return "Allergies and Intolerances", fhir401.CodeableConcept{ + Coding: []fhir401.Coding{ + { + System: stringPtr("http://loinc.org"), + Code: stringPtr("48765-2"), + Display: stringPtr("Allergies and Intolerances"), + }, + }, + }, nil + case pkg.IPSSectionsProblemList: + return "Problem List", fhir401.CodeableConcept{ + Coding: []fhir401.Coding{ + { + System: stringPtr("http://loinc.org"), + Code: stringPtr("11450-4"), + Display: stringPtr("Problem List"), + }, + }, + }, nil + case pkg.IPSSectionsImmunizations: + return "Immunizations", fhir401.CodeableConcept{ + Coding: []fhir401.Coding{ + { + System: stringPtr("http://loinc.org"), + Code: stringPtr("11369-6"), + Display: stringPtr("Immunizations"), + }, + }, + }, nil + case pkg.IPSSectionsHistoryOfProcedures: + return "History of Procedures", fhir401.CodeableConcept{ + Coding: []fhir401.Coding{ + { + System: stringPtr("http://loinc.org"), + Code: stringPtr("47519-4"), + Display: stringPtr("History of Procedures"), + }, + }, + }, nil + case pkg.IPSSectionsMedicalDevices: + return "Medical Devices", fhir401.CodeableConcept{ + Coding: []fhir401.Coding{ + { + System: stringPtr("http://loinc.org"), + Code: stringPtr("46264-8"), + Display: stringPtr("Medical Devices"), + }, + }, + }, nil + case pkg.IPSSectionsDiagnosticResults: + return "Diagnostic Results", fhir401.CodeableConcept{ + Coding: []fhir401.Coding{ + { + System: stringPtr("http://loinc.org"), + Code: stringPtr("30954-2"), + Display: stringPtr("Diagnostic Results"), + }, + }, + }, nil + case pkg.IPSSectionsVitalSigns: + return "Vital Signs", fhir401.CodeableConcept{ + Coding: []fhir401.Coding{ + { + System: stringPtr("http://loinc.org"), + Code: stringPtr("8716-3"), + Display: stringPtr("Vital Signs"), + }, + }, + }, nil + case pkg.IPSSectionsHistoryOfIllness: + return "Past History of Illness", fhir401.CodeableConcept{ + Coding: []fhir401.Coding{ + { + System: stringPtr("http://loinc.org"), + Code: stringPtr("11348-0"), + Display: stringPtr("History of Illness"), + }, + }, + }, nil + case pkg.IPSSectionsPregnancy: + return "Pregnancy History", fhir401.CodeableConcept{ + Coding: []fhir401.Coding{ + { + System: stringPtr("http://loinc.org"), + Code: stringPtr("10162-6"), + Display: stringPtr("Pregnancy History"), + }, + }, + }, nil + case pkg.IPSSectionsSocialHistory: + return "Social History", fhir401.CodeableConcept{ + Coding: []fhir401.Coding{ + { + System: stringPtr("http://loinc.org"), + Code: stringPtr("29762-2"), + Display: stringPtr("Social History"), + }, + }, + }, nil + case pkg.IPSSectionsPlanOfCare: + return "Plan of Care", fhir401.CodeableConcept{ + Coding: []fhir401.Coding{ + { + System: stringPtr("http://loinc.org"), + Code: stringPtr("18776-5"), + Display: stringPtr("Plan of Care"), + }, + }, + }, nil + case pkg.IPSSectionsFunctionalStatus: + return "Functional Status", fhir401.CodeableConcept{ + Coding: []fhir401.Coding{ + { + System: stringPtr("http://loinc.org"), + Code: stringPtr("47420-5"), + Display: stringPtr("Functional Status"), + }, + }, + }, nil + case pkg.IPSSectionsAdvanceDirectives: + return "Advance Directives", fhir401.CodeableConcept{ + Coding: []fhir401.Coding{ + { + System: stringPtr("http://loinc.org"), + Code: stringPtr("42348-3"), + Display: stringPtr("Advance Directives"), + }, + }, + }, nil + default: + return "", fhir401.CodeableConcept{}, fmt.Errorf("invalid section type: %s", sectionType) + } + +} + +func generateIPSSectionNarrative(sectionType pkg.IPSSections, resources []models.ResourceBase) string { + return "" +} + +// helper utility +func stringPtr(s string) *string { + return &s +} diff --git a/backend/pkg/database/interface.go b/backend/pkg/database/interface.go index 382ea01cc..27bed9d1a 100644 --- a/backend/pkg/database/interface.go +++ b/backend/pkg/database/interface.go @@ -21,6 +21,7 @@ type DatabaseRepository interface { //get a count of every resource type GetSummary(ctx context.Context) (*models.Summary, error) + GetInternationalPatientSummaryBundle(ctx context.Context) (interface{}, error) GetResourceByResourceTypeAndId(context.Context, string, string) (*models.ResourceBase, error) GetResourceBySourceId(context.Context, string, string) (*models.ResourceBase, error) diff --git a/backend/pkg/web/handler/summary.go b/backend/pkg/web/handler/summary.go index 068238bfd..9f37e350d 100644 --- a/backend/pkg/web/handler/summary.go +++ b/backend/pkg/web/handler/summary.go @@ -20,3 +20,16 @@ func GetSummary(c *gin.Context) { } c.JSON(http.StatusOK, gin.H{"success": true, "data": summary}) } + +func GetIPSSummary(c *gin.Context) { + logger := c.MustGet(pkg.ContextKeyTypeLogger).(*logrus.Entry) + databaseRepo := c.MustGet(pkg.ContextKeyTypeDatabase).(database.DatabaseRepository) + + summary, err := databaseRepo.GetInternationalPatientSummaryBundle(c) + if err != nil { + logger.Errorln("An error occurred while retrieving IPS summary", err) + c.JSON(http.StatusInternalServerError, gin.H{"success": false}) + return + } + c.JSON(http.StatusOK, gin.H{"success": true, "data": summary}) +} diff --git a/backend/pkg/web/server.go b/backend/pkg/web/server.go index 1d6eac818..93a6570d8 100644 --- a/backend/pkg/web/server.go +++ b/backend/pkg/web/server.go @@ -100,6 +100,7 @@ func (ae *AppEngine) Setup() (*gin.RouterGroup, *gin.Engine) { secure.DELETE("/account/me", handler.DeleteAccount) secure.GET("/summary", handler.GetSummary) + secure.GET("/summary/ips", handler.GetIPSSummary) secure.POST("/source", handler.CreateReconnectSource) secure.POST("/source/manual", handler.CreateManualSource) From 9466d2bbf39d72cc00ab03dc98fa58d015293aca Mon Sep 17 00:00:00 2001 From: Jason Kulatunga Date: Thu, 22 Feb 2024 17:03:51 -0800 Subject: [PATCH 07/29] move all IPS/narrative code into utils. --- backend/pkg/utils/ips/render.go | 139 ++++++++++ .../ips/templates/advance_directives.gohtml | 36 +++ .../templates/allergies_intolerances.gohtml | 52 ++++ .../utils/ips/templates/composition.gohtml | 19 ++ .../ips/templates/diagnostic_results.gohtml | 88 +++++++ .../ips/templates/functional_status.gohtml | 37 +++ .../ips/templates/history_of_illness.gohtml | 34 +++ .../templates/history_of_procedures.gohtml | 31 +++ .../utils/ips/templates/immunizations.gohtml | 43 +++ .../ips/templates/includes/footer.gohtml | 1 + .../ips/templates/includes/header.gohtml | 1 + .../utils/ips/templates/includes/toc.gohtml | 1 + .../includes/utility-fragments.gohtml | 249 ++++++++++++++++++ backend/pkg/utils/ips/templates/index.gohtml | 21 ++ .../ips/templates/medical_devices.gohtml | 34 +++ .../ips/templates/medication_summary.gohtml | 93 +++++++ .../utils/ips/templates/plan_of_care.gohtml | 37 +++ .../pkg/utils/ips/templates/pregnancy.gohtml | 34 +++ .../utils/ips/templates/problem_list.gohtml | 34 +++ .../utils/ips/templates/social_history.gohtml | 37 +++ .../utils/ips/templates/vital_signs.gohtml | 40 +++ 21 files changed, 1061 insertions(+) create mode 100644 backend/pkg/utils/ips/render.go create mode 100644 backend/pkg/utils/ips/templates/advance_directives.gohtml create mode 100644 backend/pkg/utils/ips/templates/allergies_intolerances.gohtml create mode 100644 backend/pkg/utils/ips/templates/composition.gohtml create mode 100644 backend/pkg/utils/ips/templates/diagnostic_results.gohtml create mode 100644 backend/pkg/utils/ips/templates/functional_status.gohtml create mode 100644 backend/pkg/utils/ips/templates/history_of_illness.gohtml create mode 100644 backend/pkg/utils/ips/templates/history_of_procedures.gohtml create mode 100644 backend/pkg/utils/ips/templates/immunizations.gohtml create mode 100644 backend/pkg/utils/ips/templates/includes/footer.gohtml create mode 100644 backend/pkg/utils/ips/templates/includes/header.gohtml create mode 100644 backend/pkg/utils/ips/templates/includes/toc.gohtml create mode 100644 backend/pkg/utils/ips/templates/includes/utility-fragments.gohtml create mode 100644 backend/pkg/utils/ips/templates/index.gohtml create mode 100644 backend/pkg/utils/ips/templates/medical_devices.gohtml create mode 100644 backend/pkg/utils/ips/templates/medication_summary.gohtml create mode 100644 backend/pkg/utils/ips/templates/plan_of_care.gohtml create mode 100644 backend/pkg/utils/ips/templates/pregnancy.gohtml create mode 100644 backend/pkg/utils/ips/templates/problem_list.gohtml create mode 100644 backend/pkg/utils/ips/templates/social_history.gohtml create mode 100644 backend/pkg/utils/ips/templates/vital_signs.gohtml diff --git a/backend/pkg/utils/ips/render.go b/backend/pkg/utils/ips/render.go new file mode 100644 index 000000000..683eb312e --- /dev/null +++ b/backend/pkg/utils/ips/render.go @@ -0,0 +1,139 @@ +package ips + +import ( + "bytes" + "embed" + "fmt" + "github.com/fastenhealth/fasten-onprem/backend/pkg" + "github.com/fastenhealth/fasten-onprem/backend/pkg/models/database" + "github.com/fastenhealth/gofhir-models/fhir401" + "html/template" +) + +//go:embed templates +var ipsTemplates embed.FS + +type Narrative struct { + Templates *template.Template +} + +// Ideally we'd do this with generics, however IntelliJ `gotype` type hints in Templates don't support generics correctly so we have this ugliness... +type NarrativeTemplateData struct { + Bundle *fhir401.Bundle + Composition *fhir401.Composition + + Consent []database.FhirConsent + AllergyIntolerance []database.FhirAllergyIntolerance + DiagnosticReport []database.FhirDiagnosticReport + //ClinicalImpression *database.FhirClinicalImpression + Procedure []database.FhirProcedure + Immunization []database.FhirImmunization + Device []database.FhirDevice + MedicationRequest []database.FhirMedicationRequest + MedicationStatement []database.FhirMedicationStatement + Condition []database.FhirCondition + CarePlan []database.FhirCarePlan + Observation []database.FhirObservation + Encounter []database.FhirEncounter + Patient []database.FhirPatient +} + +func NewNarrative() (*Narrative, error) { + narrative := &Narrative{} + + //parse templates + // https://stackoverflow.com/questions/50283370/include-template-from-another-directory + // https://www.digitalocean.com/community/tutorials/how-to-use-templates-in-go + tmpl, err := template.New("ips").Funcs(template.FuncMap{ + "safeHTML": func(s *string) template.HTML { + if s == nil { + return template.HTML("") + } + return template.HTML(*s) + }, + }).ParseFS(ipsTemplates, "templates/*.gohtml", "templates/includes/*.gohtml") + + if err != nil { + return nil, err + } + narrative.Templates = tmpl + return narrative, nil +} + +func (r *Narrative) GetTemplates() *template.Template { + return r.Templates +} + +func (r *Narrative) RenderTemplate(templateName string, data NarrativeTemplateData) (string, error) { + var b bytes.Buffer + err := r.Templates.ExecuteTemplate(&b, templateName, data) + if err != nil { + return "", err + } + return b.String(), nil +} + +func (r *Narrative) RenderSection(sectionType pkg.IPSSections, resources []database.IFhirResourceModel) (string, error) { + templateName := fmt.Sprintf("%s.gohtml", sectionType) + templateData := NarrativeTemplateData{ + Bundle: &fhir401.Bundle{}, + Composition: &fhir401.Composition{}, + + AllergyIntolerance: []database.FhirAllergyIntolerance{}, + CarePlan: []database.FhirCarePlan{}, + Condition: []database.FhirCondition{}, + Consent: []database.FhirConsent{}, + Device: []database.FhirDevice{}, + DiagnosticReport: []database.FhirDiagnosticReport{}, + Encounter: []database.FhirEncounter{}, + Immunization: []database.FhirImmunization{}, + MedicationRequest: []database.FhirMedicationRequest{}, + MedicationStatement: []database.FhirMedicationStatement{}, + Observation: []database.FhirObservation{}, + Patient: []database.FhirPatient{}, + Procedure: []database.FhirProcedure{}, + } + + //loop though the resources, cast them to the correct type, and then store them in the correct array + //this is a bit of a hack, but it's the best way to do it without generics + + for ndx, _ := range resources { + resource := resources[ndx] + switch resource.GetSourceResourceType() { + case "AllergyIntolerance": + templateData.AllergyIntolerance = append(templateData.AllergyIntolerance, *resource.(*database.FhirAllergyIntolerance)) + case "CarePlan": + templateData.CarePlan = append(templateData.CarePlan, *resource.(*database.FhirCarePlan)) + case "Condition": + templateData.Condition = append(templateData.Condition, *resource.(*database.FhirCondition)) + case "Consent": + templateData.Consent = append(templateData.Consent, *resource.(*database.FhirConsent)) + case "Device": + templateData.Device = append(templateData.Device, *resource.(*database.FhirDevice)) + case "DiagnosticReport": + templateData.DiagnosticReport = append(templateData.DiagnosticReport, *resource.(*database.FhirDiagnosticReport)) + case "Encounter": + templateData.Encounter = append(templateData.Encounter, *resource.(*database.FhirEncounter)) + case "Immunization": + templateData.Immunization = append(templateData.Immunization, *resource.(*database.FhirImmunization)) + case "MedicationRequest": + templateData.MedicationRequest = append(templateData.MedicationRequest, *resource.(*database.FhirMedicationRequest)) + case "MedicationStatement": + templateData.MedicationStatement = append(templateData.MedicationStatement, *resource.(*database.FhirMedicationStatement)) + case "Observation": + templateData.Observation = append(templateData.Observation, *resource.(*database.FhirObservation)) + case "Patient": + templateData.Patient = append(templateData.Patient, *resource.(*database.FhirPatient)) + case "Procedure": + templateData.Procedure = append(templateData.Procedure, *resource.(*database.FhirProcedure)) + } + + } + + var b bytes.Buffer + err := r.Templates.ExecuteTemplate(&b, templateName, resources) + if err != nil { + return "", err + } + return b.String(), nil +} diff --git a/backend/pkg/utils/ips/templates/advance_directives.gohtml b/backend/pkg/utils/ips/templates/advance_directives.gohtml new file mode 100644 index 000000000..1855612b6 --- /dev/null +++ b/backend/pkg/utils/ips/templates/advance_directives.gohtml @@ -0,0 +1,36 @@ + + +
+
Advance Directives
+ + + + + + + + + + + + + + + + + + + + + + + +
ScopeStatusAction ControlledDate
ScopeStatusAction ControlledDate
+
+ + diff --git a/backend/pkg/utils/ips/templates/allergies_intolerances.gohtml b/backend/pkg/utils/ips/templates/allergies_intolerances.gohtml new file mode 100644 index 000000000..728afbbd7 --- /dev/null +++ b/backend/pkg/utils/ips/templates/allergies_intolerances.gohtml @@ -0,0 +1,52 @@ + + +
+
Allergies And Intolerances
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AllergenStatusCategoryReactionSeverityCommentsOnset
AllergenStatusCategoryReactionSeverityCommentsOnsetOnset
+
+ + diff --git a/backend/pkg/utils/ips/templates/composition.gohtml b/backend/pkg/utils/ips/templates/composition.gohtml new file mode 100644 index 000000000..292073dc7 --- /dev/null +++ b/backend/pkg/utils/ips/templates/composition.gohtml @@ -0,0 +1,19 @@ + +
+ {{- /*gotype: github.com/fastenhealth/fasten-onprem/backend/pkg/utils/ips.NarrativeTemplateData */ -}} + {{range $index, $section := .Composition.Section }} +
+

{{$section.Title}}

+
+ {{if eq $section.Text nil }} + {{$section.EmptyReason.Text}} + {{else }} + {{$section.Text.Div | safeHTML}} + {{end}} +
+
+ {{end}} +
diff --git a/backend/pkg/utils/ips/templates/diagnostic_results.gohtml b/backend/pkg/utils/ips/templates/diagnostic_results.gohtml new file mode 100644 index 000000000..560007cd5 --- /dev/null +++ b/backend/pkg/utils/ips/templates/diagnostic_results.gohtml @@ -0,0 +1,88 @@ + + +
+ +
Diagnostic Results: Observations
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CodeResultUnitInterpretationReference RangeCommentsDate
Code + ResultUnit + Interpretation + + Reference + Range + CommentsDate
+
+ + +
Diagnostic Results: Diagnostic Reports
+ + + + + + + + + + + + + + + + + + + + + +
CodeDate
Device + Date
+
+
diff --git a/backend/pkg/utils/ips/templates/functional_status.gohtml b/backend/pkg/utils/ips/templates/functional_status.gohtml new file mode 100644 index 000000000..a569efadf --- /dev/null +++ b/backend/pkg/utils/ips/templates/functional_status.gohtml @@ -0,0 +1,37 @@ + + +
+
Functional Status
+ + + + + + + + + + + + + + + + + + + + + + + + + +
AssessmentStatusFindingCommentsDate
AssessmentStatusFindingCommentsDate
+
diff --git a/backend/pkg/utils/ips/templates/history_of_illness.gohtml b/backend/pkg/utils/ips/templates/history_of_illness.gohtml new file mode 100644 index 000000000..11f06d54b --- /dev/null +++ b/backend/pkg/utils/ips/templates/history_of_illness.gohtml @@ -0,0 +1,34 @@ + + +
+
Past History of Illnesses
+ + + + + + + + + + + + + + + + + + + + + + + +
Medical ProblemsStatusCommentsDate
Medical ProblemStatusCommentsOnset Date
+
diff --git a/backend/pkg/utils/ips/templates/history_of_procedures.gohtml b/backend/pkg/utils/ips/templates/history_of_procedures.gohtml new file mode 100644 index 000000000..9e4bfcc6a --- /dev/null +++ b/backend/pkg/utils/ips/templates/history_of_procedures.gohtml @@ -0,0 +1,31 @@ + + +
+
History Of Procedures
+ + + + + + + + + + + + + + + + + + + + + +
ProcedureCommentsDate
ProcedureCommentsDate
+
diff --git a/backend/pkg/utils/ips/templates/immunizations.gohtml b/backend/pkg/utils/ips/templates/immunizations.gohtml new file mode 100644 index 000000000..e21ca2e1a --- /dev/null +++ b/backend/pkg/utils/ips/templates/immunizations.gohtml @@ -0,0 +1,43 @@ + + +
+
Immunizations
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ImmunizationStatusDose NumberManufacturerLot NumberCommentsDate
ImmunizationStatusCommentsManufacturerLot NumberCommentsDate
+
diff --git a/backend/pkg/utils/ips/templates/includes/footer.gohtml b/backend/pkg/utils/ips/templates/includes/footer.gohtml new file mode 100644 index 000000000..06bc0176f --- /dev/null +++ b/backend/pkg/utils/ips/templates/includes/footer.gohtml @@ -0,0 +1 @@ +
footer hello world
diff --git a/backend/pkg/utils/ips/templates/includes/header.gohtml b/backend/pkg/utils/ips/templates/includes/header.gohtml new file mode 100644 index 000000000..3a28b092c --- /dev/null +++ b/backend/pkg/utils/ips/templates/includes/header.gohtml @@ -0,0 +1 @@ +
header hello world
diff --git a/backend/pkg/utils/ips/templates/includes/toc.gohtml b/backend/pkg/utils/ips/templates/includes/toc.gohtml new file mode 100644 index 000000000..e7fc41243 --- /dev/null +++ b/backend/pkg/utils/ips/templates/includes/toc.gohtml @@ -0,0 +1 @@ +
table of contents
diff --git a/backend/pkg/utils/ips/templates/includes/utility-fragments.gohtml b/backend/pkg/utils/ips/templates/includes/utility-fragments.gohtml new file mode 100644 index 000000000..3dea18d43 --- /dev/null +++ b/backend/pkg/utils/ips/templates/includes/utility-fragments.gohtml @@ -0,0 +1,249 @@ + + + + + + + + + Device + + + + + + + + + + Org Name + + + + + + + + + + Medication + + + Medication + + + + + + + + + Medication + + + + + + + Medication + + + + + + + + + Dose Number + Dose Number + + + + + + + + + + Result + Result + + Result + + Result + + + + + + + + Unit + + + + + + + + + + Date + Date + + + + + + + + Date + + Date + + Date + Date + + Date + + + + + + + + Date + + Date + + Date + Date + + Date + + + + + + + + Date + Date + + + + + + + + Date Recorded + + + + + + + + + + + + + + + + + + + + + + + Interpretation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + + + + + Reaction + + Reaction + + + + + + + + + + + + + + + + + + + + + + Dose Number + + + + + + + Reference Range + + Reference Range + + + + diff --git a/backend/pkg/utils/ips/templates/index.gohtml b/backend/pkg/utils/ips/templates/index.gohtml new file mode 100644 index 000000000..a98b798af --- /dev/null +++ b/backend/pkg/utils/ips/templates/index.gohtml @@ -0,0 +1,21 @@ + + + + + title + + + + + +{{template "header.gohtml" .}} +{{template "toc.gohtml" .}} + +{{template "composition.gohtml" .}} + +{{template "footer.gohtml" .}} + + + + + diff --git a/backend/pkg/utils/ips/templates/medical_devices.gohtml b/backend/pkg/utils/ips/templates/medical_devices.gohtml new file mode 100644 index 000000000..73902b88b --- /dev/null +++ b/backend/pkg/utils/ips/templates/medical_devices.gohtml @@ -0,0 +1,34 @@ + + +
+
Medical Devices
+ + + + + + + + + + + + + + + + + + + + + + + +
DeviceStatusCommentsDate Recorded
DeviceStatusCommentsDate Recorded
+
diff --git a/backend/pkg/utils/ips/templates/medication_summary.gohtml b/backend/pkg/utils/ips/templates/medication_summary.gohtml new file mode 100644 index 000000000..ed4a8f128 --- /dev/null +++ b/backend/pkg/utils/ips/templates/medication_summary.gohtml @@ -0,0 +1,93 @@ + + +
+ + +
Medication Summary: Medication Requests
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MedicationStatusRouteSigCommentsAuthored Date
+ Medication + Status + Route + + Sig + CommentsAuthored Date
+
+ + +
Medication Summary: Medication Statements
+ + + + + + + + + + + + + + + + + + + + + + + + + +
MedicationStatusRouteSigDate
+ Medication + StatusRouteSigDate
+
+
diff --git a/backend/pkg/utils/ips/templates/plan_of_care.gohtml b/backend/pkg/utils/ips/templates/plan_of_care.gohtml new file mode 100644 index 000000000..d87170fac --- /dev/null +++ b/backend/pkg/utils/ips/templates/plan_of_care.gohtml @@ -0,0 +1,37 @@ + + +
+
Plan of Care
+ + + + + + + + + + + + + + + + + + + + + + + + + +
ActivityIntentCommentsPlanned StartPlanned End
ActivityIntentCommentsPlanned StartPlanned End
+
diff --git a/backend/pkg/utils/ips/templates/pregnancy.gohtml b/backend/pkg/utils/ips/templates/pregnancy.gohtml new file mode 100644 index 000000000..d939053c3 --- /dev/null +++ b/backend/pkg/utils/ips/templates/pregnancy.gohtml @@ -0,0 +1,34 @@ + + +
+
Pregnancy
+ + + + + + + + + + + + + + + + + + + + + + + +
CodeResultCommentsDate
CodeResultCommentsDate
+
diff --git a/backend/pkg/utils/ips/templates/problem_list.gohtml b/backend/pkg/utils/ips/templates/problem_list.gohtml new file mode 100644 index 000000000..5c0e796bd --- /dev/null +++ b/backend/pkg/utils/ips/templates/problem_list.gohtml @@ -0,0 +1,34 @@ + + +
+
Problem List
+ + + + + + + + + + + + + + + + + + + + + + + +
Medical ProblemsStatusCommentsOnset Date
Medical ProblemsStatusCommentsOnset Date
+
diff --git a/backend/pkg/utils/ips/templates/social_history.gohtml b/backend/pkg/utils/ips/templates/social_history.gohtml new file mode 100644 index 000000000..de7ba86c8 --- /dev/null +++ b/backend/pkg/utils/ips/templates/social_history.gohtml @@ -0,0 +1,37 @@ + + +
+
Social History
+ + + + + + + + + + + + + + + + + + + + + + + + + +
CodeResultUnitCommentsDate
CodeResultUnitCommentsDate
+
diff --git a/backend/pkg/utils/ips/templates/vital_signs.gohtml b/backend/pkg/utils/ips/templates/vital_signs.gohtml new file mode 100644 index 000000000..f890ad6c2 --- /dev/null +++ b/backend/pkg/utils/ips/templates/vital_signs.gohtml @@ -0,0 +1,40 @@ + + +
+
Vital Signs
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
CodeResultUnitInterpretationCommentsDate
CodeResultUnitInterpretationCommentsDate
+
From c3184fa8c05e4bfbd13fc48314b6805293ee3b55 Mon Sep 17 00:00:00 2001 From: Jason Kulatunga Date: Thu, 22 Feb 2024 17:05:04 -0800 Subject: [PATCH 08/29] adding ability to generate slices of fhir resources. --- backend/pkg/models/database/generate.go | 16 +++ backend/pkg/models/database/interface.go | 1 + backend/pkg/models/database/utils.go | 118 +++++++++++++++++++++++ 3 files changed, 135 insertions(+) diff --git a/backend/pkg/models/database/generate.go b/backend/pkg/models/database/generate.go index 20e41d7b1..67593dd89 100644 --- a/backend/pkg/models/database/generate.go +++ b/backend/pkg/models/database/generate.go @@ -507,6 +507,22 @@ func main() { }) }) + //Similar to NewFhirResourceModelByType, this is a function which returns a slice corresponding FhirResource when provided the FhirResource type string + //uses a switch statement to return the correct type + utilsFile.Comment("Returns a map of all the resource names to their corresponding go struct") + utilsFile.Func().Id("NewFhirResourceModelSliceByType").Params(jen.Id("resourceType").String()).Params(jen.Interface(), jen.Error()).BlockFunc(func(g *jen.Group) { + g.Switch(jen.Id("resourceType")).BlockFunc(func(s *jen.Group) { + for _, resourceName := range AllowedResources { + s.Case(jen.Lit(resourceName)).BlockFunc(func(c *jen.Group) { + c.Return(jen.Index().Id("Fhir"+resourceName).Values(), jen.Nil()) + }) + } + s.Default().BlockFunc(func(d *jen.Group) { + d.Return(jen.Nil(), jen.Qual("fmt", "Errorf").Call(jen.Lit("Invalid resource type for model: %s"), jen.Id("resourceType"))) + }) + }) + }) + //A function which returns the GORM table name for a FHIRResource when provided the FhirResource type string //uses a switch statement to return the correct type utilsFile.Comment("Returns the GORM table name for a FHIRResource when provided the FhirResource type string") diff --git a/backend/pkg/models/database/interface.go b/backend/pkg/models/database/interface.go index 66be7f75f..6b541520b 100644 --- a/backend/pkg/models/database/interface.go +++ b/backend/pkg/models/database/interface.go @@ -11,6 +11,7 @@ type IFhirResourceModel interface { models.OriginBaser SetOriginBase(originBase models.OriginBase) SetResourceRaw(resourceRaw datatypes.JSON) + GetResourceRaw() datatypes.JSON SetSortTitle(sortTitle *string) SetSortDate(sortDate *time.Time) SetSourceUri(sourceUri *string) diff --git a/backend/pkg/models/database/utils.go b/backend/pkg/models/database/utils.go index 38e9c844f..39c9d2b28 100644 --- a/backend/pkg/models/database/utils.go +++ b/backend/pkg/models/database/utils.go @@ -139,6 +139,124 @@ func NewFhirResourceModelByType(resourceType string) (IFhirResourceModel, error) } } +// Returns a map of all the resource names to their corresponding go struct +func NewFhirResourceModelSliceByType(resourceType string) (interface{}, error) { + switch resourceType { + case "Account": + return []FhirAccount{}, nil + case "AdverseEvent": + return []FhirAdverseEvent{}, nil + case "AllergyIntolerance": + return []FhirAllergyIntolerance{}, nil + case "Appointment": + return []FhirAppointment{}, nil + case "Binary": + return []FhirBinary{}, nil + case "CarePlan": + return []FhirCarePlan{}, nil + case "CareTeam": + return []FhirCareTeam{}, nil + case "Claim": + return []FhirClaim{}, nil + case "ClaimResponse": + return []FhirClaimResponse{}, nil + case "Composition": + return []FhirComposition{}, nil + case "Condition": + return []FhirCondition{}, nil + case "Consent": + return []FhirConsent{}, nil + case "Coverage": + return []FhirCoverage{}, nil + case "CoverageEligibilityRequest": + return []FhirCoverageEligibilityRequest{}, nil + case "CoverageEligibilityResponse": + return []FhirCoverageEligibilityResponse{}, nil + case "Device": + return []FhirDevice{}, nil + case "DeviceRequest": + return []FhirDeviceRequest{}, nil + case "DiagnosticReport": + return []FhirDiagnosticReport{}, nil + case "DocumentManifest": + return []FhirDocumentManifest{}, nil + case "DocumentReference": + return []FhirDocumentReference{}, nil + case "Encounter": + return []FhirEncounter{}, nil + case "Endpoint": + return []FhirEndpoint{}, nil + case "EnrollmentRequest": + return []FhirEnrollmentRequest{}, nil + case "EnrollmentResponse": + return []FhirEnrollmentResponse{}, nil + case "ExplanationOfBenefit": + return []FhirExplanationOfBenefit{}, nil + case "FamilyMemberHistory": + return []FhirFamilyMemberHistory{}, nil + case "Goal": + return []FhirGoal{}, nil + case "ImagingStudy": + return []FhirImagingStudy{}, nil + case "Immunization": + return []FhirImmunization{}, nil + case "InsurancePlan": + return []FhirInsurancePlan{}, nil + case "Location": + return []FhirLocation{}, nil + case "Media": + return []FhirMedia{}, nil + case "Medication": + return []FhirMedication{}, nil + case "MedicationAdministration": + return []FhirMedicationAdministration{}, nil + case "MedicationDispense": + return []FhirMedicationDispense{}, nil + case "MedicationRequest": + return []FhirMedicationRequest{}, nil + case "MedicationStatement": + return []FhirMedicationStatement{}, nil + case "NutritionOrder": + return []FhirNutritionOrder{}, nil + case "Observation": + return []FhirObservation{}, nil + case "Organization": + return []FhirOrganization{}, nil + case "OrganizationAffiliation": + return []FhirOrganizationAffiliation{}, nil + case "Patient": + return []FhirPatient{}, nil + case "Person": + return []FhirPerson{}, nil + case "Practitioner": + return []FhirPractitioner{}, nil + case "PractitionerRole": + return []FhirPractitionerRole{}, nil + case "Procedure": + return []FhirProcedure{}, nil + case "Provenance": + return []FhirProvenance{}, nil + case "Questionnaire": + return []FhirQuestionnaire{}, nil + case "QuestionnaireResponse": + return []FhirQuestionnaireResponse{}, nil + case "RelatedPerson": + return []FhirRelatedPerson{}, nil + case "Schedule": + return []FhirSchedule{}, nil + case "ServiceRequest": + return []FhirServiceRequest{}, nil + case "Slot": + return []FhirSlot{}, nil + case "Specimen": + return []FhirSpecimen{}, nil + case "VisionPrescription": + return []FhirVisionPrescription{}, nil + default: + return nil, fmt.Errorf("Invalid resource type for model: %s", resourceType) + } +} + // Returns the GORM table name for a FHIRResource when provided the FhirResource type string func GetTableNameByResourceType(resourceType string) (string, error) { switch resourceType { From dd78494325b2468432c57d9569ae6ddf5014f9e6 Mon Sep 17 00:00:00 2001 From: Jason Kulatunga Date: Thu, 22 Feb 2024 17:06:19 -0800 Subject: [PATCH 09/29] generate IPS bundle and composition adding test when generating summary. --- backend/pkg/database/gorm_repository_query.go | 12 +- .../pkg/database/gorm_repository_summary.go | 104 +++++++++++++-- .../database/gorm_repository_summary_test.go | 122 ++++++++++++++++++ backend/pkg/database/interface.go | 2 +- backend/pkg/models/resource_base.go | 3 + backend/pkg/web/handler/summary.go | 42 +++++- 6 files changed, 265 insertions(+), 20 deletions(-) create mode 100644 backend/pkg/database/gorm_repository_summary_test.go diff --git a/backend/pkg/database/gorm_repository_query.go b/backend/pkg/database/gorm_repository_query.go index f329f1bb7..0b69a0851 100644 --- a/backend/pkg/database/gorm_repository_query.go +++ b/backend/pkg/database/gorm_repository_query.go @@ -67,9 +67,15 @@ func (gr *GormRepository) QueryResources(ctx context.Context, query models.Query return results, clientResp.Error } else { - results := []models.ResourceBase{} - clientResp := sqlQuery.Find(&results) - return results, clientResp.Error + + //find the associated Gorm Model for this query + queryModelSlice, err := databaseModel.NewFhirResourceModelSliceByType(query.From) + if err != nil { + return nil, err + } + + clientResp := sqlQuery.Find(&queryModelSlice) + return queryModelSlice, clientResp.Error } } diff --git a/backend/pkg/database/gorm_repository_summary.go b/backend/pkg/database/gorm_repository_summary.go index de284bf00..74df41ef7 100644 --- a/backend/pkg/database/gorm_repository_summary.go +++ b/backend/pkg/database/gorm_repository_summary.go @@ -6,16 +6,23 @@ import ( "fmt" "github.com/fastenhealth/fasten-onprem/backend/pkg" "github.com/fastenhealth/fasten-onprem/backend/pkg/models" + "github.com/fastenhealth/fasten-onprem/backend/pkg/models/database" + "github.com/fastenhealth/fasten-onprem/backend/pkg/utils/ips" "github.com/fastenhealth/gofhir-models/fhir401" "github.com/google/uuid" "log" "time" ) -func (gr *GormRepository) GetInternationalPatientSummaryBundle(ctx context.Context) (interface{}, error) { +func (gr *GormRepository) GetInternationalPatientSummaryBundle(ctx context.Context) (interface{}, interface{}, error) { summaryTime := time.Now() timestamp := summaryTime.Format(time.RFC3339) + narrativeEngine, err := ips.NewNarrative() + if err != nil { + return nil, nil, fmt.Errorf("error creating narrative engine: %w", err) + } + //Algorithm to create the IPS bundle // 1. Generate the IPS Section Lists (GetInternationalPatientSummarySectionResources) // - Process each resource, generating a Markdown narrative in the text field for each resource @@ -34,15 +41,15 @@ func (gr *GormRepository) GetInternationalPatientSummaryBundle(ctx context.Conte //Step 1. Generate the IPS Section Lists summarySectionResources, err := gr.GetInternationalPatientSummarySectionResources(ctx) if err != nil { - return nil, err + return nil, nil, err } //Step 2. Create the Composition Section compositionSections := []fhir401.CompositionSection{} for sectionType, sectionResources := range summarySectionResources { - compositionSection, err := generateIPSCompositionSection(sectionType, sectionResources) + compositionSection, err := generateIPSCompositionSection(narrativeEngine, sectionType, sectionResources) if err != nil { - return nil, err + return nil, nil, err } compositionSections = append(compositionSections, *compositionSection) } @@ -115,6 +122,7 @@ func (gr *GormRepository) GetInternationalPatientSummaryBundle(ctx context.Conte }, }, } + ipsComposition.Section = compositionSections // Step 6. Create the IPS Bundle bundleUUID := uuid.New().String() @@ -129,7 +137,7 @@ func (gr *GormRepository) GetInternationalPatientSummaryBundle(ctx context.Conte // Add the Composition to the bundle ipsCompositionJson, err := json.Marshal(ipsComposition) if err != nil { - return nil, err + return nil, nil, err } ipsBundle.Entry = append(ipsBundle.Entry, fhir401.BundleEntry{ Resource: json.RawMessage(ipsCompositionJson), @@ -142,28 +150,28 @@ func (gr *GormRepository) GetInternationalPatientSummaryBundle(ctx context.Conte for _, sectionResources := range summarySectionResources { for _, resource := range sectionResources { ipsBundle.Entry = append(ipsBundle.Entry, fhir401.BundleEntry{ - Resource: json.RawMessage(resource.ResourceRaw), + Resource: json.RawMessage(resource.GetResourceRaw()), }) } } - return ipsBundle, nil + return ipsBundle, ipsComposition, nil } // GetInternationalPatientSummary will generate an IPS bundle, which can then be used to generate a IPS QR code, PDF or JSON bundle // The IPS bundle will contain a summary of all the data in the system, including a list of all sources, and the main Patient // See: https://github.com/fastenhealth/fasten-onprem/issues/170 // See: https://github.com/jddamore/fhir-ips-server/blob/main/docs/Summary_Creation_Steps.md -func (gr *GormRepository) GetInternationalPatientSummarySectionResources(ctx context.Context) (map[pkg.IPSSections][]models.ResourceBase, error) { +func (gr *GormRepository) GetInternationalPatientSummarySectionResources(ctx context.Context) (map[pkg.IPSSections][]database.IFhirResourceModel, error) { - summarySectionResources := map[pkg.IPSSections][]models.ResourceBase{} + summarySectionResources := map[pkg.IPSSections][]database.IFhirResourceModel{} // generate queries for each IPS Section for ndx, _ := range pkg.IPSSectionsList { sectionName := pkg.IPSSectionsList[ndx] //initialize the section - summarySectionResources[sectionName] = []models.ResourceBase{} + summarySectionResources[sectionName] = []database.IFhirResourceModel{} queries, err := generateIPSSectionQueries(sectionName) if err != nil { @@ -176,7 +184,7 @@ func (gr *GormRepository) GetInternationalPatientSummarySectionResources(ctx con return nil, err } - resultsList := results.([]models.ResourceBase) + resultsList := convertUnknownInterfaceToFhirSlice(results) //TODO: generate resource narrative summarySectionResources[sectionName] = append(summarySectionResources[sectionName], resultsList...) @@ -186,7 +194,7 @@ func (gr *GormRepository) GetInternationalPatientSummarySectionResources(ctx con return summarySectionResources, nil } -func generateIPSCompositionSection(sectionType pkg.IPSSections, resources []models.ResourceBase) (*fhir401.CompositionSection, error) { +func generateIPSCompositionSection(narrativeEngine *ips.Narrative, sectionType pkg.IPSSections, resources []database.IFhirResourceModel) (*fhir401.CompositionSection, error) { sectionTitle, sectionCode, err := generateIPSSectionHeaderInfo(sectionType) if err != nil { return nil, err @@ -210,7 +218,7 @@ func generateIPSCompositionSection(sectionType pkg.IPSSections, resources []mode section.Entry = []fhir401.Reference{} for _, resource := range resources { reference := fhir401.Reference{ - Reference: stringPtr(fmt.Sprintf("%s/%s", resource.SourceResourceType, resource.SourceID)), + Reference: stringPtr(fmt.Sprintf("%s/%s", resource.GetSourceResourceType(), resource.GetSourceResourceID())), } if err != nil { return nil, err @@ -219,9 +227,17 @@ func generateIPSCompositionSection(sectionType pkg.IPSSections, resources []mode } //TODO: Add the section narrative summary + rendered, err := narrativeEngine.RenderSection( + sectionType, + resources, + ) + if err != nil { + return nil, fmt.Errorf("error rendering narrative for section %s: %w", sectionType, err) + } + section.Text = &fhir401.Narrative{ Status: fhir401.NarrativeStatusGenerated, - Div: "PLACEHOLDER NARRATIVE SUMMARY FOR SECTION", + Div: rendered, } } @@ -543,6 +559,66 @@ func generateIPSSectionHeaderInfo(sectionType pkg.IPSSections) (string, fhir401. } +// QueryResources returns an interface{} which is actually a slice of the appropriate FHIR resource type +// we use this function to "cast" the results to a slice of the IFhirResourceModel interface (so we can use the same code to handle the results) +// TODO: there has to be a better way to do this :/ +func convertUnknownInterfaceToFhirSlice(unknown interface{}) []database.IFhirResourceModel { + results := []database.IFhirResourceModel{} + + switch fhirSlice := unknown.(type) { + case []database.FhirAllergyIntolerance: + for ndx, _ := range fhirSlice { + results = append(results, &fhirSlice[ndx]) + } + case []database.FhirCarePlan: + for ndx, _ := range fhirSlice { + results = append(results, &fhirSlice[ndx]) + } + case []database.FhirCondition: + for ndx, _ := range fhirSlice { + results = append(results, &fhirSlice[ndx]) + } + case []database.FhirDevice: + for ndx, _ := range fhirSlice { + results = append(results, &fhirSlice[ndx]) + } + case []database.FhirDiagnosticReport: + for ndx, _ := range fhirSlice { + results = append(results, &fhirSlice[ndx]) + } + case []database.FhirEncounter: + for ndx, _ := range fhirSlice { + results = append(results, &fhirSlice[ndx]) + } + case []database.FhirImmunization: + for ndx, _ := range fhirSlice { + results = append(results, &fhirSlice[ndx]) + } + case []database.FhirMedicationRequest: + for ndx, _ := range fhirSlice { + results = append(results, &fhirSlice[ndx]) + } + case []database.FhirMedicationStatement: + for ndx, _ := range fhirSlice { + results = append(results, &fhirSlice[ndx]) + } + case []database.FhirObservation: + for ndx, _ := range fhirSlice { + results = append(results, &fhirSlice[ndx]) + } + case []database.FhirPatient: + for ndx, _ := range fhirSlice { + results = append(results, &fhirSlice[ndx]) + } + case []database.FhirProcedure: + for ndx, _ := range fhirSlice { + results = append(results, &fhirSlice[ndx]) + } + } + + return results +} + func generateIPSSectionNarrative(sectionType pkg.IPSSections, resources []models.ResourceBase) string { return "" } diff --git a/backend/pkg/database/gorm_repository_summary_test.go b/backend/pkg/database/gorm_repository_summary_test.go new file mode 100644 index 000000000..8a809b08c --- /dev/null +++ b/backend/pkg/database/gorm_repository_summary_test.go @@ -0,0 +1,122 @@ +package database + +import ( + "context" + "fmt" + "github.com/fastenhealth/fasten-onprem/backend/pkg" + mock_config "github.com/fastenhealth/fasten-onprem/backend/pkg/config/mock" + "github.com/fastenhealth/fasten-onprem/backend/pkg/event_bus" + "github.com/fastenhealth/fasten-onprem/backend/pkg/models" + sourceFactory "github.com/fastenhealth/fasten-sources/clients/factory" + sourcePkg "github.com/fastenhealth/fasten-sources/pkg" + "github.com/fastenhealth/gofhir-models/fhir401" + "github.com/golang/mock/gomock" + "github.com/google/uuid" + "github.com/sirupsen/logrus" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + "io/ioutil" + "log" + "os" + "testing" +) + +// Define the suite, and absorb the built-in basic suite +// functionality from testify - including a T() method which +// returns the current testing context +type RepositorySummaryTestSuite struct { + suite.Suite + MockCtrl *gomock.Controller + TestDatabase *os.File +} + +// BeforeTest has a function to be executed right before the test starts and receives the suite and test names as input +func (suite *RepositorySummaryTestSuite) BeforeTest(suiteName, testName string) { + suite.MockCtrl = gomock.NewController(suite.T()) + + dbFile, err := ioutil.TempFile("", fmt.Sprintf("%s.*.db", testName)) + if err != nil { + log.Fatal(err) + } + suite.TestDatabase = dbFile + +} + +// AfterTest has a function to be executed right after the test finishes and receives the suite and test names as input +func (suite *RepositorySummaryTestSuite) AfterTest(suiteName, testName string) { + suite.MockCtrl.Finish() + os.Remove(suite.TestDatabase.Name()) + os.Remove(suite.TestDatabase.Name() + "-shm") + os.Remove(suite.TestDatabase.Name() + "-wal") +} + +// In order for 'go test' to run this suite, we need to create +// a normal test function and pass our suite to suite.Run +func TestRepositorySummaryTestSuiteSuite(t *testing.T) { + suite.Run(t, new(RepositorySummaryTestSuite)) +} + +func (suite *RepositorySummaryTestSuite) TestGetInternationalPatientSummaryBundle() { + //setup + fakeConfig := mock_config.NewMockInterface(suite.MockCtrl) + fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes() + fakeConfig.EXPECT().GetString("database.type").Return("sqlite").AnyTimes() + fakeConfig.EXPECT().IsSet("database.encryption.key").Return(false).AnyTimes() + fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes() + dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer()) + require.NoError(suite.T(), err) + + userModel := &models.User{ + Username: "test_username", + Password: "testpassword", + Email: "test@test.com", + } + err = dbRepo.CreateUser(context.Background(), userModel) + require.NoError(suite.T(), err) + require.NotEmpty(suite.T(), userModel.ID) + require.NotEqual(suite.T(), uuid.Nil, userModel.ID) + authContext := context.WithValue(context.Background(), pkg.ContextKeyTypeAuthUsername, "test_username") + + testSourceCredential := models.SourceCredential{ + ModelBase: models.ModelBase{ + ID: uuid.New(), + }, + UserID: userModel.ID, + Patient: uuid.New().String(), + PlatformType: sourcePkg.PlatformTypeManual, + } + err = dbRepo.CreateSource(authContext, &testSourceCredential) + require.NoError(suite.T(), err) + + bundleFile, err := os.Open("./testdata/Abraham100_Heller342_262b819a-5193-404a-9787-b7f599358035.json") + require.NoError(suite.T(), err) + + testLogger := logrus.WithFields(logrus.Fields{ + "type": "test", + }) + + manualClient, err := sourceFactory.GetSourceClient(sourcePkg.FastenLighthouseEnvSandbox, authContext, testLogger, &testSourceCredential) + + summary, err := manualClient.SyncAllBundle(dbRepo, bundleFile, sourcePkg.FhirVersion401) + require.NoError(suite.T(), err) + require.Equal(suite.T(), 198, summary.TotalResources) + require.Equal(suite.T(), 234, len(summary.UpdatedResources)) + + //test + bundle, composition, err := dbRepo.GetInternationalPatientSummaryBundle(authContext) + require.NoError(suite.T(), err) + + //case bundle and composition + fhirBundle := bundle.(*fhir401.Bundle) + fhirComposition := composition.(*fhir401.Composition) + + require.NotNil(suite.T(), fhirBundle) + require.NotNil(suite.T(), fhirComposition) + + require.Equal(suite.T(), 211, len(fhirBundle.Entry)) + require.Equal(suite.T(), 14, len(fhirComposition.Section)) + + //require.Equal(suite.T(), "", fhirComposition.Section[0].Title) + //require.Equal(suite.T(), "", fhirComposition.Section[0].Text.Div) + +} diff --git a/backend/pkg/database/interface.go b/backend/pkg/database/interface.go index 27bed9d1a..6291e2543 100644 --- a/backend/pkg/database/interface.go +++ b/backend/pkg/database/interface.go @@ -21,7 +21,7 @@ type DatabaseRepository interface { //get a count of every resource type GetSummary(ctx context.Context) (*models.Summary, error) - GetInternationalPatientSummaryBundle(ctx context.Context) (interface{}, error) + GetInternationalPatientSummaryBundle(ctx context.Context) (interface{}, interface{}, error) GetResourceByResourceTypeAndId(context.Context, string, string) (*models.ResourceBase, error) GetResourceBySourceId(context.Context, string, string) (*models.ResourceBase, error) diff --git a/backend/pkg/models/resource_base.go b/backend/pkg/models/resource_base.go index a0f3c75a3..7195a9cb4 100644 --- a/backend/pkg/models/resource_base.go +++ b/backend/pkg/models/resource_base.go @@ -33,6 +33,9 @@ func (s *ResourceBase) SetSortDate(sortDate *time.Time) { func (s *ResourceBase) SetResourceRaw(resourceRaw datatypes.JSON) { s.ResourceRaw = resourceRaw } +func (s *ResourceBase) GetResourceRaw() datatypes.JSON { + return s.ResourceRaw +} func (s *ResourceBase) SetSourceUri(sourceUri *string) { s.SourceUri = sourceUri diff --git a/backend/pkg/web/handler/summary.go b/backend/pkg/web/handler/summary.go index 9f37e350d..b4a844c36 100644 --- a/backend/pkg/web/handler/summary.go +++ b/backend/pkg/web/handler/summary.go @@ -1,8 +1,11 @@ package handler import ( + _ "embed" "github.com/fastenhealth/fasten-onprem/backend/pkg" "github.com/fastenhealth/fasten-onprem/backend/pkg/database" + "github.com/fastenhealth/fasten-onprem/backend/pkg/utils/ips" + "github.com/fastenhealth/gofhir-models/fhir401" "github.com/gin-gonic/gin" "github.com/sirupsen/logrus" "net/http" @@ -25,11 +28,46 @@ func GetIPSSummary(c *gin.Context) { logger := c.MustGet(pkg.ContextKeyTypeLogger).(*logrus.Entry) databaseRepo := c.MustGet(pkg.ContextKeyTypeDatabase).(database.DatabaseRepository) - summary, err := databaseRepo.GetInternationalPatientSummaryBundle(c) + ipsBundle, ipsComposititon, err := databaseRepo.GetInternationalPatientSummaryBundle(c) if err != nil { logger.Errorln("An error occurred while retrieving IPS summary", err) c.JSON(http.StatusInternalServerError, gin.H{"success": false}) return } - c.JSON(http.StatusOK, gin.H{"success": true, "data": summary}) + + if c.Query("format") == "" { + c.JSON(http.StatusOK, gin.H{"success": true, "data": ipsBundle}) + return + } + + narrative, err := ips.NewNarrative() + if err != nil { + logger.Errorln("An error occurred while parsing template", err) + c.JSON(http.StatusInternalServerError, gin.H{"success": false}) + return + } + + composititon := ipsComposititon.(*fhir401.Composition) + + if c.Query("format") == "html" { + + logger.Debugln("Rendering HTML") + //create string writer + content, err := narrative.RenderTemplate("index.gohtml", ips.NarrativeTemplateData{Composition: composititon}) + if err != nil { + logger.Errorln("An error occurred while executing template", err) + c.JSON(http.StatusInternalServerError, gin.H{"success": false}) + return + } + c.Header("Content-Type", "text/html; charset=utf-8") + c.String(http.StatusOK, content) + return + } + //} else if c.Query("format") == "pdf" { + // + // c.Header("Content-Disposition", "attachment; filename=ips_summary.pdf") + // c.Header("Content-Type", "application/pdf") + // c.String(http.StatusOK, b.String()) + // return + //} } From 0664f20ef9ef083a7bf1e9e44026e71d6dd8f378 Mon Sep 17 00:00:00 2001 From: Jason Kulatunga Date: Fri, 23 Feb 2024 16:50:29 -0800 Subject: [PATCH 10/29] generating IPS render test. --- backend/pkg/utils/ips/render.go | 20 +++++-- backend/pkg/utils/ips/render_test.go | 54 +++++++++++++++++++ .../templates/allergies_intolerances.gohtml | 36 +++++-------- go.mod | 8 +++ go.sum | 23 ++++++++ 5 files changed, 115 insertions(+), 26 deletions(-) create mode 100644 backend/pkg/utils/ips/render_test.go diff --git a/backend/pkg/utils/ips/render.go b/backend/pkg/utils/ips/render.go index 683eb312e..3f69c5b4e 100644 --- a/backend/pkg/utils/ips/render.go +++ b/backend/pkg/utils/ips/render.go @@ -3,10 +3,13 @@ package ips import ( "bytes" "embed" + "encoding/json" "fmt" + sprig "github.com/Masterminds/sprig/v3" "github.com/fastenhealth/fasten-onprem/backend/pkg" "github.com/fastenhealth/fasten-onprem/backend/pkg/models/database" "github.com/fastenhealth/gofhir-models/fhir401" + "gorm.io/datatypes" "html/template" ) @@ -51,7 +54,19 @@ func NewNarrative() (*Narrative, error) { } return template.HTML(*s) }, - }).ParseFS(ipsTemplates, "templates/*.gohtml", "templates/includes/*.gohtml") + "parseList": func(data datatypes.JSON) []map[string]interface{} { + var parsed []map[string]interface{} + _ = json.Unmarshal(data, &parsed) + return parsed + }, + "pluckList": func(key string, data []map[string]interface{}) []interface{} { + values := []interface{}{} + for _, item := range data { + values = append(values, item[key]) + } + return values + }, + }).Funcs(sprig.FuncMap()).ParseFS(ipsTemplates, "templates/*.gohtml", "templates/includes/*.gohtml") if err != nil { return nil, err @@ -127,11 +142,10 @@ func (r *Narrative) RenderSection(sectionType pkg.IPSSections, resources []datab case "Procedure": templateData.Procedure = append(templateData.Procedure, *resource.(*database.FhirProcedure)) } - } var b bytes.Buffer - err := r.Templates.ExecuteTemplate(&b, templateName, resources) + err := r.Templates.ExecuteTemplate(&b, templateName, templateData) if err != nil { return "", err } diff --git a/backend/pkg/utils/ips/render_test.go b/backend/pkg/utils/ips/render_test.go new file mode 100644 index 000000000..60acff028 --- /dev/null +++ b/backend/pkg/utils/ips/render_test.go @@ -0,0 +1,54 @@ +package ips + +import ( + "github.com/fastenhealth/fasten-onprem/backend/pkg" + "github.com/fastenhealth/fasten-onprem/backend/pkg/models" + "github.com/fastenhealth/fasten-onprem/backend/pkg/models/database" + "github.com/stretchr/testify/require" + "testing" +) + +func TestNarrative_RenderSection(t *testing.T) { + tests := []struct { + name string + sectionType pkg.IPSSections + resources []database.IFhirResourceModel + + want string + wantErr bool + }{ + { + name: "Test Narrative_RenderSection", + sectionType: pkg.IPSSectionsAllergiesIntolerances, + resources: []database.IFhirResourceModel{ + &database.FhirAllergyIntolerance{ + ResourceBase: models.ResourceBase{ + OriginBase: models.OriginBase{ + SourceResourceType: "AllergyIntolerance", + SourceResourceID: "1", + }, + }, + Code: []byte(`[ + {"code":"891830","system":"http://www.nlm.nih.gov/research/umls/rxnorm","text":"banana (May be Banana (Diagnostic))"}, + {"code":"93174","system":"urn:oid:2.16.840.1.113883.13.80","text":"banana (May be Banana (Diagnostic))"} + ]`), + ClinicalStatus: []byte(`[{"code":"active","system":"http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical","text":"Active"}]`), + Category: []byte(`[{"code":"environment"}]`), + }, + }, + want: "", + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + n, err := NewNarrative() + require.NoError(t, err) + got, err := n.RenderSection(tt.sectionType, tt.resources) + require.NoError(t, err, "RenderSection() error = %v, wantErr %v", err, tt.wantErr) + if got != tt.want { + t.Errorf("RenderSection() got = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/backend/pkg/utils/ips/templates/allergies_intolerances.gohtml b/backend/pkg/utils/ips/templates/allergies_intolerances.gohtml index 728afbbd7..4d0dda7fc 100644 --- a/backend/pkg/utils/ips/templates/allergies_intolerances.gohtml +++ b/backend/pkg/utils/ips/templates/allergies_intolerances.gohtml @@ -7,7 +7,7 @@ Reaction: AllergyIntolerance.reaction.manifestation.description || AllergyIntole Severity: AllergyIntolerance.reaction.severity[x].code (separated by
) Comments: AllergyIntolerance.note[x].text (separated by
) */--> -
+
Allergies And Intolerances
@@ -22,29 +22,19 @@ Comments: AllergyIntolerance.note[x].text (separated by
) - - - - - - - - - - - - - - - - - - - - - - + {{- /*gotype: github.com/fastenhealth/fasten-onprem/backend/pkg/utils/ips.NarrativeTemplateData*/ -}} + {{range $index, $entry := .AllergyIntolerance }} + + {{/* Allergen */}} + {{/* Status */}} + {{/* Category */}} + {{/* Reaction */}} + {{/* Severity */}} + {{/* Comments - TODO: use FHIRPath */}} + {{/* Onset */}} + + {{end}}
AllergenStatusCategoryReactionSeverityCommentsOnsetOnset
{{pluckList "text" ($entry.Code | parseList) | uniq | join "," }}{{pluckList "code" ($entry.ClinicalStatus | parseList) | uniq | join "," }}{{pluckList "code" ($entry.Category | parseList) | uniq | join "," }}{{pluckList "text" ($entry.Manifestation | parseList) | uniq | join "," }}{{pluckList "code" ($entry.Criticality | parseList) | uniq | join ","}}Comments{{$entry.Onset | date "2006-01-02"}}
diff --git a/go.mod b/go.mod index a5ea287a1..f6410d2ce 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ replace github.com/mattn/go-sqlite3 v1.14.17 => github.com/jgiannuzzi/go-sqlite3 //replace gorm.io/driver/sqlite v1.5.4 => github.com/jgiannuzzi/gorm-sqlite v1.4.4-0.20221215225833-42389ad31305 require ( + github.com/Masterminds/sprig/v3 v3.2.3 github.com/analogj/go-util v0.0.0-20210417161720-39b497cca03b github.com/dave/jennifer v1.6.1 github.com/dominikbraun/graph v0.15.0 @@ -40,11 +41,18 @@ require ( ) require ( + github.com/Masterminds/goutils v1.1.1 // indirect + github.com/Masterminds/semver/v3 v3.2.0 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect + github.com/huandu/xstrings v1.3.3 // indirect + github.com/imdario/mergo v0.3.11 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect github.com/jackc/pgx/v5 v5.4.3 // indirect github.com/mattn/go-sqlite3 v1.14.17 // indirect + github.com/mitchellh/copystructure v1.0.0 // indirect + github.com/mitchellh/reflectwalk v1.0.0 // indirect + github.com/shopspring/decimal v1.2.0 // indirect ) require ( diff --git a/go.sum b/go.sum index a991b63cc..d1644b109 100644 --- a/go.sum +++ b/go.sum @@ -41,7 +41,13 @@ github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJc github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= +github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= +github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= +github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 h1:wPbRQzjjwFc0ih8puEVAOFGELsn1zoIIYdxvML7mDxA= github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g= github.com/analogj/go-util v0.0.0-20210417161720-39b497cca03b h1:Y/+MfmdKPPpVY7C6ggt/FpltFSitlpUtyJEdcQyFXQg= @@ -210,6 +216,7 @@ github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U= github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -220,11 +227,15 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4= +github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= +github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= +github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= @@ -333,10 +344,14 @@ github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp9 github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= +github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -370,6 +385,7 @@ github.com/seborama/govcr v4.5.0+incompatible/go.mod h1:EgcISudCCYDLzbiAImJ8i7kk github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys= github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= +github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -377,6 +393,7 @@ github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0 github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo= github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= @@ -456,6 +473,7 @@ golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= @@ -535,6 +553,7 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= @@ -617,6 +636,7 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -625,6 +645,7 @@ golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= @@ -638,6 +659,7 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= @@ -809,6 +831,7 @@ gopkg.in/ini.v1 v1.66.4 h1:SsAcf+mM7mRZo2nJNGt8mZCjG8ZRaNGMURJw7BsIST4= gopkg.in/ini.v1 v1.66.4/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 907c9be8e2a5a03c992a1d9c1a4309d65aa5c3ec Mon Sep 17 00:00:00 2001 From: Jason Kulatunga Date: Sat, 24 Feb 2024 10:18:59 -0800 Subject: [PATCH 11/29] working on rendering resources --- .../ips/templates/history_of_illness.gohtml | 21 ++++++-------- .../templates/history_of_procedures.gohtml | 21 +++++++------- .../utils/ips/templates/immunizations.gohtml | 29 +++++++++---------- .../ips/templates/medical_devices.gohtml | 21 ++++++-------- 4 files changed, 42 insertions(+), 50 deletions(-) diff --git a/backend/pkg/utils/ips/templates/history_of_illness.gohtml b/backend/pkg/utils/ips/templates/history_of_illness.gohtml index 11f06d54b..ec96b3463 100644 --- a/backend/pkg/utils/ips/templates/history_of_illness.gohtml +++ b/backend/pkg/utils/ips/templates/history_of_illness.gohtml @@ -17,18 +17,15 @@ Onset Date: Condition.onsetDateTime || Condition.onsetPeriod.start && “-“ && - - - - - Medical Problem - Status - Comments - Onset Date - - - - + {{- /*gotype: github.com/fastenhealth/fasten-onprem/backend/pkg/utils/ips.NarrativeTemplateData*/ -}} + {{range $index, $entry := .Condition }} + + {{pluckList "text" ($entry.Code | parseList) | uniq | join "," }} {{/* Medical Problem */}} + {{pluckList "code" ($entry.ClinicalStatus | parseList) | uniq | join "," }} {{/* Status */}} + Comments {{/* Comments - TODO: use FHIRPath */}} + {{$entry.OnsetDate | date "2006-01-02"}} {{/* Onset */}} + + {{end}}
diff --git a/backend/pkg/utils/ips/templates/history_of_procedures.gohtml b/backend/pkg/utils/ips/templates/history_of_procedures.gohtml index 9e4bfcc6a..29eadf369 100644 --- a/backend/pkg/utils/ips/templates/history_of_procedures.gohtml +++ b/backend/pkg/utils/ips/templates/history_of_procedures.gohtml @@ -15,17 +15,16 @@ Date: Procedure.performedDateTime || Procedure.performedPeriod.start && “-“ - - - - - Procedure - Comments - Date - - - - + + {{- /*gotype: github.com/fastenhealth/fasten-onprem/backend/pkg/utils/ips.NarrativeTemplateData*/ -}} + {{range $index, $entry := .Procedure }} + + {{pluckList "text" ($entry.Code | parseList) | uniq | join "," }} {{/* Procedure */}} + Comments {{/* Comments - TODO: use FHIRPath */}} + {{$entry.Date | date "2006-01-02"}} {{/* Performed Date */}} + + {{end}} + diff --git a/backend/pkg/utils/ips/templates/immunizations.gohtml b/backend/pkg/utils/ips/templates/immunizations.gohtml index e21ca2e1a..9161f09aa 100644 --- a/backend/pkg/utils/ips/templates/immunizations.gohtml +++ b/backend/pkg/utils/ips/templates/immunizations.gohtml @@ -23,21 +23,20 @@ Date: Immunization.occurrenceDateTime || Immunization.occurrenceString - - - - - Immunization - Status - Comments - Manufacturer - Lot Number - Comments - Date - - - - + + {{- /*gotype: github.com/fastenhealth/fasten-onprem/backend/pkg/utils/ips.NarrativeTemplateData*/ -}} + {{range $index, $entry := .Immunization }} + + {{pluckList "text" ($entry.VaccineCode | parseList) | uniq | join "," }} {{/* Immunization */}} + {{pluckList "code" ($entry.Status | parseList) | uniq | join "," }} {{/* Status */}} + Dose Number {{/* Comments - TODO: use FHIRPath */}} + Manufacturer {{/* Manufacturer - TODO: use FHIRPath */}} + {{$entry.LotNumber}} {{/* Lot Number */}} + Comments + {{$entry.Date | date "2006-01-02"}} {{/* Performed Date */}} + + {{end}} + diff --git a/backend/pkg/utils/ips/templates/medical_devices.gohtml b/backend/pkg/utils/ips/templates/medical_devices.gohtml index 73902b88b..d237d73e7 100644 --- a/backend/pkg/utils/ips/templates/medical_devices.gohtml +++ b/backend/pkg/utils/ips/templates/medical_devices.gohtml @@ -17,18 +17,15 @@ Date Recorded: DeviceUseStatement.recordedDateTime - - - - - Device - Status - Comments - Date Recorded - - - - + {{- /*gotype: github.com/fastenhealth/fasten-onprem/backend/pkg/utils/ips.NarrativeTemplateData*/ -}} + {{range $index, $entry := .Device }} + + {{pluckList "text" ($entry.Type | parseList) | uniq | join "," }} {{/* Device */}} + {{pluckList "code" ($entry.Status | parseList) | uniq | join "," }} {{/* Status */}} + Comments + {{/* Date Recorded */}} + + {{end}} From 55509c9a9211c26846d6d27e798e63761898ea34 Mon Sep 17 00:00:00 2001 From: Jason Kulatunga Date: Sat, 24 Feb 2024 11:38:35 -0800 Subject: [PATCH 12/29] expand export summary. --- .../utils/ips/templates/plan_of_care.gohtml | 23 ++++++------- .../pkg/utils/ips/templates/pregnancy.gohtml | 31 ++++++++++------- .../utils/ips/templates/problem_list.gohtml | 21 +++++------- .../utils/ips/templates/social_history.gohtml | 33 +++++++++++-------- .../utils/ips/templates/vital_signs.gohtml | 22 +++++++++++++ 5 files changed, 80 insertions(+), 50 deletions(-) diff --git a/backend/pkg/utils/ips/templates/plan_of_care.gohtml b/backend/pkg/utils/ips/templates/plan_of_care.gohtml index d87170fac..22d6f84bf 100644 --- a/backend/pkg/utils/ips/templates/plan_of_care.gohtml +++ b/backend/pkg/utils/ips/templates/plan_of_care.gohtml @@ -19,19 +19,16 @@ Planned End: CarePlan.period.end - - - - - Activity - Intent - Comments - Planned Start - Planned End - - - - + {{- /*gotype: github.com/fastenhealth/fasten-onprem/backend/pkg/utils/ips.NarrativeTemplateData*/ -}} + {{range $index, $entry := .CarePlan }} + + Activity + {{pluckList "code" ($entry.Intent | parseList) | uniq | join "," }} {{/* Intent */}} + Comments + {{.$entry.Date}}{{/* Planned Start */}} + Planned End + + {{end}} diff --git a/backend/pkg/utils/ips/templates/pregnancy.gohtml b/backend/pkg/utils/ips/templates/pregnancy.gohtml index d939053c3..92b42bfe2 100644 --- a/backend/pkg/utils/ips/templates/pregnancy.gohtml +++ b/backend/pkg/utils/ips/templates/pregnancy.gohtml @@ -17,18 +17,25 @@ Date: Observation.effectiveDateTime || Observation.effectivePeriod.start - - - - - Code - Result - Comments - Date - - - - + {{- /*gotype: github.com/fastenhealth/fasten-onprem/backend/pkg/utils/ips.NarrativeTemplateData*/ -}} + {{range $index, $entry := .Observation }} + + {{pluckList "text" ($entry.Code | parseList) | uniq | join "," }} {{/* Code */}} + + {{if gt (len $entry.ValueString) 0 }} + {{$entry.ValueString}} + {{else if gt (len ($entry.ValueQuantity | parseList)) 0 }} + {{$entry.ValueQuantity}} + {{else if gt (len $entry.ValueDateTime) 0 }} + {{$entry.ValueDateTime | date "2006-01-02" }} + {{else if gt (len ($entry.ValueCodeableConcept | parseList)) 0 }} + {{$entry.ValueCodeableConcept}} + {{end}} + {{/* Result */}} + Comments + {{$entry.Date | date "2006-01-02"}} {{/* Date */}} + + {{end}} diff --git a/backend/pkg/utils/ips/templates/problem_list.gohtml b/backend/pkg/utils/ips/templates/problem_list.gohtml index 5c0e796bd..8abae8091 100644 --- a/backend/pkg/utils/ips/templates/problem_list.gohtml +++ b/backend/pkg/utils/ips/templates/problem_list.gohtml @@ -17,18 +17,15 @@ Onset Date: Condition.onsetDateTime || Condition.onsetPeriod.start && “-“ && - - - - - Medical Problems - Status - Comments - Onset Date - - - - + {{- /*gotype: github.com/fastenhealth/fasten-onprem/backend/pkg/utils/ips.NarrativeTemplateData*/ -}} + {{range $index, $entry := .Condition }} + + {{pluckList "text" ($entry.Code | parseList) | uniq | join "," }} {{/* Medical Problems */}} + {{pluckList "code" ($entry.ClinicalStatus | parseList) | uniq | join "," }} {{/* Status */}} + Comments + {{$entry.OnsetDate | date "2006-01-02"}} {{/* Onset */}} + + {{end}} diff --git a/backend/pkg/utils/ips/templates/social_history.gohtml b/backend/pkg/utils/ips/templates/social_history.gohtml index de7ba86c8..20f76be4b 100644 --- a/backend/pkg/utils/ips/templates/social_history.gohtml +++ b/backend/pkg/utils/ips/templates/social_history.gohtml @@ -19,19 +19,26 @@ Date: Observation.effectiveDateTime || Observation.effectivePeriod.start - - - - - Code - Result - Unit - Comments - Date - - - - + {{- /*gotype: github.com/fastenhealth/fasten-onprem/backend/pkg/utils/ips.NarrativeTemplateData*/ -}} + {{range $index, $entry := .Observation }} + + {{pluckList "text" ($entry.Code | parseList) | uniq | join "," }} {{/* Code */}} + + {{if gt (len $entry.ValueString) 0 }} + {{$entry.ValueString}} + {{else if gt (len ($entry.ValueQuantity | parseList)) 0 }} + {{$entry.ValueQuantity}} + {{else if gt (len $entry.ValueDateTime) 0 }} + {{$entry.ValueDateTime | date "2006-01-02" }} + {{else if gt (len ($entry.ValueCodeableConcept | parseList)) 0 }} + {{$entry.ValueCodeableConcept}} + {{end}} + {{/* Result */}} + Unit + Comments + {{$entry.Date | date "2006-01-02"}} {{/* Date */}} + + {{end}} diff --git a/backend/pkg/utils/ips/templates/vital_signs.gohtml b/backend/pkg/utils/ips/templates/vital_signs.gohtml index f890ad6c2..b43a4efff 100644 --- a/backend/pkg/utils/ips/templates/vital_signs.gohtml +++ b/backend/pkg/utils/ips/templates/vital_signs.gohtml @@ -35,6 +35,28 @@ Date: Observation.effectiveDateTime || Observation.effectivePeriod.start
+ + {{- /*gotype: github.com/fastenhealth/fasten-onprem/backend/pkg/utils/ips.NarrativeTemplateData*/ -}} + {{range $index, $entry := .Observation }} + + {{pluckList "text" ($entry.Code | parseList) | uniq | join "," }} {{/* Code */}} + + {{if gt (len $entry.ValueString) 0 }} + {{$entry.ValueString}} + {{else if gt (len ($entry.ValueQuantity | parseList)) 0 }} + {{$entry.ValueQuantity}} + {{else if gt (len $entry.ValueDateTime) 0 }} + {{$entry.ValueDateTime | date "2006-01-02" }} + {{else if gt (len ($entry.ValueCodeableConcept | parseList)) 0 }} + {{$entry.ValueCodeableConcept}} + {{end}} + {{/* Result */}} + Unit + Interpretation + Comments + {{$entry.Date | date "2006-01-02"}} {{/* Date */}} + + {{end}} From da8e9e594428e7f15e3378678d3789212d31882b Mon Sep 17 00:00:00 2001 From: Jason Kulatunga Date: Sat, 24 Feb 2024 11:46:55 -0800 Subject: [PATCH 13/29] updated IPS generation. --- backend/pkg/utils/ips/templates/vital_signs.gohtml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/backend/pkg/utils/ips/templates/vital_signs.gohtml b/backend/pkg/utils/ips/templates/vital_signs.gohtml index b43a4efff..254554f2f 100644 --- a/backend/pkg/utils/ips/templates/vital_signs.gohtml +++ b/backend/pkg/utils/ips/templates/vital_signs.gohtml @@ -21,20 +21,6 @@ Date: Observation.effectiveDateTime || Observation.effectivePeriod.start - - - - - Code - Result - Unit - Interpretation - Comments - Date - - - - {{- /*gotype: github.com/fastenhealth/fasten-onprem/backend/pkg/utils/ips.NarrativeTemplateData*/ -}} {{range $index, $entry := .Observation }} From 7c9d59cb86c6de92c11b0d963ecab857fc05bd63 Mon Sep 17 00:00:00 2001 From: Jason Kulatunga Date: Sat, 24 Feb 2024 12:07:59 -0800 Subject: [PATCH 14/29] fixed IPS generation. --- backend/pkg/utils/ips/templates/plan_of_care.gohtml | 2 +- backend/pkg/utils/ips/templates/pregnancy.gohtml | 12 ++++++------ .../pkg/utils/ips/templates/social_history.gohtml | 12 ++++++------ backend/pkg/utils/ips/templates/vital_signs.gohtml | 12 ++++++------ 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/backend/pkg/utils/ips/templates/plan_of_care.gohtml b/backend/pkg/utils/ips/templates/plan_of_care.gohtml index 22d6f84bf..8acc170aa 100644 --- a/backend/pkg/utils/ips/templates/plan_of_care.gohtml +++ b/backend/pkg/utils/ips/templates/plan_of_care.gohtml @@ -25,7 +25,7 @@ Planned End: CarePlan.period.end Activity {{pluckList "code" ($entry.Intent | parseList) | uniq | join "," }} {{/* Intent */}} Comments - {{.$entry.Date}}{{/* Planned Start */}} + {{$entry.Date}}{{/* Planned Start */}} Planned End {{end}} diff --git a/backend/pkg/utils/ips/templates/pregnancy.gohtml b/backend/pkg/utils/ips/templates/pregnancy.gohtml index 92b42bfe2..ccb6f6427 100644 --- a/backend/pkg/utils/ips/templates/pregnancy.gohtml +++ b/backend/pkg/utils/ips/templates/pregnancy.gohtml @@ -22,14 +22,14 @@ Date: Observation.effectiveDateTime || Observation.effectivePeriod.start {{pluckList "text" ($entry.Code | parseList) | uniq | join "," }} {{/* Code */}} - {{if gt (len $entry.ValueString) 0 }} + {{if not (empty $entry.ValueString) }} {{$entry.ValueString}} - {{else if gt (len ($entry.ValueQuantity | parseList)) 0 }} + {{else if not (empty ($entry.ValueQuantity | parseList)) }} {{$entry.ValueQuantity}} - {{else if gt (len $entry.ValueDateTime) 0 }} - {{$entry.ValueDateTime | date "2006-01-02" }} - {{else if gt (len ($entry.ValueCodeableConcept | parseList)) 0 }} - {{$entry.ValueCodeableConcept}} + {{else if not (empty $entry.ValueDate) }} + {{$entry.ValueDate | date "2006-01-02" }} + {{else if not (empty ($entry.ValueConcept | parseList)) }} + {{$entry.ValueConcept}} {{end}} {{/* Result */}} Comments diff --git a/backend/pkg/utils/ips/templates/social_history.gohtml b/backend/pkg/utils/ips/templates/social_history.gohtml index 20f76be4b..17bab7825 100644 --- a/backend/pkg/utils/ips/templates/social_history.gohtml +++ b/backend/pkg/utils/ips/templates/social_history.gohtml @@ -24,14 +24,14 @@ Date: Observation.effectiveDateTime || Observation.effectivePeriod.start {{pluckList "text" ($entry.Code | parseList) | uniq | join "," }} {{/* Code */}} - {{if gt (len $entry.ValueString) 0 }} + {{if not (empty $entry.ValueString) }} {{$entry.ValueString}} - {{else if gt (len ($entry.ValueQuantity | parseList)) 0 }} + {{else if not (empty ($entry.ValueQuantity | parseList)) }} {{$entry.ValueQuantity}} - {{else if gt (len $entry.ValueDateTime) 0 }} - {{$entry.ValueDateTime | date "2006-01-02" }} - {{else if gt (len ($entry.ValueCodeableConcept | parseList)) 0 }} - {{$entry.ValueCodeableConcept}} + {{else if not (empty $entry.ValueDate) }} + {{$entry.ValueDate | date "2006-01-02" }} + {{else if not (empty ($entry.ValueConcept | parseList)) }} + {{$entry.ValueConcept}} {{end}} {{/* Result */}} Unit diff --git a/backend/pkg/utils/ips/templates/vital_signs.gohtml b/backend/pkg/utils/ips/templates/vital_signs.gohtml index 254554f2f..2950a5d8d 100644 --- a/backend/pkg/utils/ips/templates/vital_signs.gohtml +++ b/backend/pkg/utils/ips/templates/vital_signs.gohtml @@ -27,14 +27,14 @@ Date: Observation.effectiveDateTime || Observation.effectivePeriod.start {{pluckList "text" ($entry.Code | parseList) | uniq | join "," }} {{/* Code */}} - {{if gt (len $entry.ValueString) 0 }} + {{if not (empty $entry.ValueString) }} {{$entry.ValueString}} - {{else if gt (len ($entry.ValueQuantity | parseList)) 0 }} + {{else if not (empty ($entry.ValueQuantity | parseList)) }} {{$entry.ValueQuantity}} - {{else if gt (len $entry.ValueDateTime) 0 }} - {{$entry.ValueDateTime | date "2006-01-02" }} - {{else if gt (len ($entry.ValueCodeableConcept | parseList)) 0 }} - {{$entry.ValueCodeableConcept}} + {{else if not (empty $entry.ValueDate) }} + {{$entry.ValueDate | date "2006-01-02" }} + {{else if not (empty ($entry.ValueConcept | parseList)) }} + {{$entry.ValueConcept}} {{end}} {{/* Result */}} Unit From 492fc27de394ebe2087325e25da471029f1db13e Mon Sep 17 00:00:00 2001 From: Jason Kulatunga Date: Sat, 24 Feb 2024 16:25:52 -0800 Subject: [PATCH 15/29] better date extraction during PopulateAndExtractSearchParameters adding allergy_intolerance tests --- backend/pkg/models/database/fhir_account.go | 28 +-- .../pkg/models/database/fhir_adverse_event.go | 28 +-- .../database/fhir_allergy_intolerance.go | 56 +++--- .../database/fhir_allergy_intolerance_test.go | 190 ++++++++++++++++++ .../pkg/models/database/fhir_appointment.go | 28 +-- backend/pkg/models/database/fhir_binary.go | 14 +- backend/pkg/models/database/fhir_care_plan.go | 42 ++-- backend/pkg/models/database/fhir_care_team.go | 28 +-- backend/pkg/models/database/fhir_claim.go | 28 +-- .../models/database/fhir_claim_response.go | 42 ++-- .../pkg/models/database/fhir_composition.go | 42 ++-- backend/pkg/models/database/fhir_condition.go | 56 +++--- backend/pkg/models/database/fhir_consent.go | 42 ++-- backend/pkg/models/database/fhir_coverage.go | 14 +- .../fhir_coverage_eligibility_request.go | 28 +-- .../fhir_coverage_eligibility_response.go | 28 +-- backend/pkg/models/database/fhir_device.go | 14 +- .../models/database/fhir_device_request.go | 42 ++-- .../models/database/fhir_diagnostic_report.go | 42 ++-- .../models/database/fhir_document_manifest.go | 28 +-- .../database/fhir_document_reference.go | 42 ++-- backend/pkg/models/database/fhir_encounter.go | 42 ++-- backend/pkg/models/database/fhir_endpoint.go | 14 +- .../database/fhir_enrollment_request.go | 14 +- .../database/fhir_enrollment_response.go | 14 +- .../database/fhir_explanation_of_benefit.go | 28 +-- .../database/fhir_family_member_history.go | 28 +-- backend/pkg/models/database/fhir_goal.go | 42 ++-- .../pkg/models/database/fhir_imaging_study.go | 28 +-- .../pkg/models/database/fhir_immunization.go | 42 ++-- .../models/database/fhir_insurance_plan.go | 14 +- backend/pkg/models/database/fhir_location.go | 14 +- backend/pkg/models/database/fhir_media.go | 28 +-- .../pkg/models/database/fhir_medication.go | 28 +-- .../fhir_medication_administration.go | 28 +-- .../database/fhir_medication_dispense.go | 42 ++-- .../database/fhir_medication_request.go | 42 ++-- .../database/fhir_medication_statement.go | 28 +-- .../models/database/fhir_nutrition_order.go | 28 +-- .../pkg/models/database/fhir_observation.go | 42 ++-- .../pkg/models/database/fhir_organization.go | 14 +- .../database/fhir_organization_affiliation.go | 28 +-- backend/pkg/models/database/fhir_patient.go | 42 ++-- backend/pkg/models/database/fhir_person.go | 28 +-- .../pkg/models/database/fhir_practitioner.go | 14 +- .../models/database/fhir_practitioner_role.go | 28 +-- backend/pkg/models/database/fhir_procedure.go | 28 +-- .../pkg/models/database/fhir_provenance.go | 42 ++-- .../pkg/models/database/fhir_questionnaire.go | 42 ++-- .../database/fhir_questionnaire_response.go | 28 +-- .../models/database/fhir_related_person.go | 28 +-- backend/pkg/models/database/fhir_schedule.go | 28 +-- .../models/database/fhir_service_request.go | 42 ++-- backend/pkg/models/database/fhir_slot.go | 28 +-- backend/pkg/models/database/fhir_specimen.go | 28 +-- .../database/fhir_vision_prescription.go | 28 +-- backend/pkg/models/database/generate.go | 28 ++- 57 files changed, 1057 insertions(+), 855 deletions(-) create mode 100644 backend/pkg/models/database/fhir_allergy_intolerance_test.go diff --git a/backend/pkg/models/database/fhir_account.go b/backend/pkg/models/database/fhir_account.go index 1367e3606..83f8e3c49 100644 --- a/backend/pkg/models/database/fhir_account.go +++ b/backend/pkg/models/database/fhir_account.go @@ -129,14 +129,14 @@ func (s *FhirAccount) PopulateAndExtractSearchParameters(resourceRaw json.RawMes // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile @@ -167,14 +167,14 @@ func (s *FhirAccount) PopulateAndExtractSearchParameters(resourceRaw json.RawMes // extracting Period periodResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'Account.servicePeriod')") if err == nil && periodResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, periodResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, periodResult.String()); err == nil { + s.Period = &t + } else if t, err = time.Parse("2006-01-02", periodResult.String()); err == nil { + s.Period = &t + } else if t, err = time.Parse("2006-01", periodResult.String()); err == nil { + s.Period = &t + } else if t, err = time.Parse("2006", periodResult.String()); err == nil { s.Period = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", periodResult.String()) - if err == nil { - s.Period = &d - } } } // extracting Status diff --git a/backend/pkg/models/database/fhir_adverse_event.go b/backend/pkg/models/database/fhir_adverse_event.go index c07d8e98b..407f332d3 100644 --- a/backend/pkg/models/database/fhir_adverse_event.go +++ b/backend/pkg/models/database/fhir_adverse_event.go @@ -153,14 +153,14 @@ func (s *FhirAdverseEvent) PopulateAndExtractSearchParameters(resourceRaw json.R // extracting Date dateResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'AdverseEvent.date')") if err == nil && dateResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, dateResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01-02", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006", dateResult.String()); err == nil { s.Date = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", dateResult.String()) - if err == nil { - s.Date = &d - } } } // extracting Event @@ -181,14 +181,14 @@ func (s *FhirAdverseEvent) PopulateAndExtractSearchParameters(resourceRaw json.R // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_allergy_intolerance.go b/backend/pkg/models/database/fhir_allergy_intolerance.go index 6e1f922d0..58915282e 100644 --- a/backend/pkg/models/database/fhir_allergy_intolerance.go +++ b/backend/pkg/models/database/fhir_allergy_intolerance.go @@ -246,14 +246,14 @@ func (s *FhirAllergyIntolerance) PopulateAndExtractSearchParameters(resourceRaw // extracting Date dateResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'AllergyIntolerance.recordedDate | CarePlan.period | CareTeam.period | ClinicalImpression.date | Composition.date | Consent.dateTime | DiagnosticReport.effectiveDateTime | DiagnosticReport.effectivePeriod | Encounter.period | EpisodeOfCare.period | FamilyMemberHistory.date | Flag.period | (Immunization.occurrenceDateTime) | List.date | Observation.effectiveDateTime | Observation.effectivePeriod | Observation.effectiveTiming | Observation.effectiveInstant | Procedure.performedDateTime | Procedure.performedPeriod | Procedure.performedString | Procedure.performedAge | Procedure.performedRange | (RiskAssessment.occurrenceDateTime) | SupplyRequest.authoredOn')") if err == nil && dateResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, dateResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01-02", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006", dateResult.String()); err == nil { s.Date = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", dateResult.String()) - if err == nil { - s.Date = &d - } } } // extracting Identifier @@ -269,14 +269,14 @@ func (s *FhirAllergyIntolerance) PopulateAndExtractSearchParameters(resourceRaw // extracting LastDate lastDateResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'AllergyIntolerance.lastOccurrence')") if err == nil && lastDateResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, lastDateResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, lastDateResult.String()); err == nil { + s.LastDate = &t + } else if t, err = time.Parse("2006-01-02", lastDateResult.String()); err == nil { + s.LastDate = &t + } else if t, err = time.Parse("2006-01", lastDateResult.String()); err == nil { + s.LastDate = &t + } else if t, err = time.Parse("2006", lastDateResult.String()); err == nil { s.LastDate = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", lastDateResult.String()) - if err == nil { - s.LastDate = &d - } } } // extracting Manifestation @@ -287,14 +287,14 @@ func (s *FhirAllergyIntolerance) PopulateAndExtractSearchParameters(resourceRaw // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile @@ -315,14 +315,14 @@ func (s *FhirAllergyIntolerance) PopulateAndExtractSearchParameters(resourceRaw // extracting Onset onsetResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'AllergyIntolerance.reaction.onset')") if err == nil && onsetResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, onsetResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, onsetResult.String()); err == nil { + s.Onset = &t + } else if t, err = time.Parse("2006-01-02", onsetResult.String()); err == nil { + s.Onset = &t + } else if t, err = time.Parse("2006-01", onsetResult.String()); err == nil { + s.Onset = &t + } else if t, err = time.Parse("2006", onsetResult.String()); err == nil { s.Onset = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", onsetResult.String()) - if err == nil { - s.Onset = &d - } } } // extracting Recorder diff --git a/backend/pkg/models/database/fhir_allergy_intolerance_test.go b/backend/pkg/models/database/fhir_allergy_intolerance_test.go new file mode 100644 index 000000000..a764dd67c --- /dev/null +++ b/backend/pkg/models/database/fhir_allergy_intolerance_test.go @@ -0,0 +1,190 @@ +package database + +import ( + "encoding/json" + "github.com/stretchr/testify/require" + "os" + "testing" + "time" +) + +func TestFhirAllergyIntolerance_ExtractSearchParameters(t *testing.T) { + t.Parallel() + //setup + //var observationJson map[string]interface{} + allergyIntoleranceBytes, err := os.ReadFile("../../../../frontend/src/lib/fixtures/r4/resources/allergyIntolerance/example1.json") + require.NoError(t, err) + //err = json.Unmarshal(allergyIntoleranceBytes, &observationJson) + //require.NoError(t, err) + + //test + allergyIntoleranceModel := FhirAllergyIntolerance{} + err = allergyIntoleranceModel.PopulateAndExtractSearchParameters(allergyIntoleranceBytes) + + //assert + + var testClinicalStatus SearchParameterTokenType + require.NoError(t, err) + err = json.Unmarshal(json.RawMessage(allergyIntoleranceModel.ClinicalStatus), &testClinicalStatus) + require.NoError(t, err) + require.Equal(t, SearchParameterTokenType{ + { + Code: "active", + Text: "Active", + System: "http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical", + }, + }, testClinicalStatus) + + var testVerificationStatus SearchParameterTokenType + require.NoError(t, err) + err = json.Unmarshal(json.RawMessage(allergyIntoleranceModel.VerificationStatus), &testVerificationStatus) + require.NoError(t, err) + require.Equal(t, SearchParameterTokenType{ + { + Code: "confirmed", + Text: "Confirmed", + System: "http://terminology.hl7.org/CodeSystem/allergyintolerance-verification", + }, + }, testVerificationStatus) + + //TODO: Special field, ignoring + //require.Equal(t, "allergy", allergyIntoleranceModel.Type) + + var testCategory SearchParameterTokenType + require.NoError(t, err) + err = json.Unmarshal(json.RawMessage(allergyIntoleranceModel.Category), &testCategory) + require.NoError(t, err) + require.Equal(t, SearchParameterTokenType{ + { + Code: "food", + }, + }, testCategory) + + var testCriticality SearchParameterTokenType + require.NoError(t, err) + err = json.Unmarshal(json.RawMessage(allergyIntoleranceModel.Criticality), &testCriticality) + require.NoError(t, err) + require.Equal(t, SearchParameterTokenType{ + { + Code: "high", + }, + }, testCriticality) + + var testCodeSystem SearchParameterTokenType + require.NoError(t, err) + err = json.Unmarshal(json.RawMessage(allergyIntoleranceModel.Code), &testCodeSystem) + require.NoError(t, err) + require.Equal(t, SearchParameterTokenType{ + { + Code: "227493005", + System: "http://snomed.info/sct", + Text: "Cashew nuts", + }, + { + System: "http://www.nlm.nih.gov/research/umls/rxnorm", + Code: "1160593", + Text: "cashew nut allergenic extract Injectable Product", + }, + }, testCodeSystem) + + //var testPatient SearchParameterTokenType + //require.NoError(t, err) + //err = json.Unmarshal(json.RawMessage(allergyIntoleranceModel.Code), &testCodeSystem) + //require.NoError(t, err) + //require.Equal(t, SearchParameterTokenType{ + // { + // Code: "39065001", + // System: "http://snomed.info/sct", + // Text: "Burn of ear", + // }, + //}, testCodeSystem) + + require.Equal(t, "2012-06-12T00:00:00Z", allergyIntoleranceModel.Onset.Format(time.RFC3339)) + //TODO: require.Equal(t, "2004", allergyIntoleranceModel.Recorder) + //require.Equal(t, "2004", allergyIntoleranceModel.Asserter) + require.Equal(t, "2012-06", allergyIntoleranceModel.LastDate.Format("2006-01")) + + var testSeverity SearchParameterTokenType + require.NoError(t, err) + err = json.Unmarshal(json.RawMessage(allergyIntoleranceModel.Severity), &testSeverity) + require.NoError(t, err) + require.Equal(t, SearchParameterTokenType{ + { + Code: "severe", + }, + { + Code: "moderate", + }, + }, testSeverity) + + //TODO: Manifestation +} + +//func TestFhirAllergyIntolerance2_ExtractSearchParameters(t *testing.T) { +// t.Parallel() +// //setup +// //var observationJson map[string]interface{} +// conditionBytes, err := os.ReadFile("../../../../frontend/src/lib/fixtures/r4/resources/allergyIntolerance/example2.json") +// require.NoError(t, err) +// //err = json.Unmarshal(conditionBytes, &observationJson) +// //require.NoError(t, err) +// +// //test +// conditionModel := FhirCondition{} +// err = conditionModel.PopulateAndExtractSearchParameters(conditionBytes) +// +// //assert +// +// var testClinicalStatus SearchParameterTokenType +// require.NoError(t, err) +// err = json.Unmarshal(json.RawMessage(conditionModel.ClinicalStatus), &testClinicalStatus) +// require.NoError(t, err) +// require.Equal(t, SearchParameterTokenType{ +// { +// Code: "active", +// System: "http://terminology.hl7.org/CodeSystem/condition-clinical", +// }, +// }, testClinicalStatus) +// +// var testVerificationStatus SearchParameterTokenType +// require.NoError(t, err) +// err = json.Unmarshal(json.RawMessage(conditionModel.VerificationStatus), &testVerificationStatus) +// require.NoError(t, err) +// require.Equal(t, SearchParameterTokenType{ +// { +// Code: "confirmed", +// System: "http://terminology.hl7.org/CodeSystem/condition-ver-status", +// }, +// }, testVerificationStatus) +// +// var testCategory SearchParameterTokenType +// require.NoError(t, err) +// err = json.Unmarshal(json.RawMessage(conditionModel.Category), &testCategory) +// require.NoError(t, err) +// require.Equal(t, SearchParameterTokenType{ +// { +// Code: "problem-list-item", +// System: "http://terminology.hl7.org/CodeSystem/condition-category", +// Text: "Problem List Item", +// }, +// }, testCategory) +// +// var testSeverity SearchParameterTokenType +// require.NoError(t, err) +// err = json.Unmarshal(json.RawMessage(conditionModel.Severity), &testSeverity) +// require.NoError(t, err) +// require.Equal(t, SearchParameterTokenType{ +// { +// Code: "255604002", +// System: "http://snomed.info/sct", +// Text: "Mild", +// }, +// }, testSeverity) +// +// var testOnsetInfo SearchParameterStringType +// err = json.Unmarshal(json.RawMessage(conditionModel.OnsetInfo), &testOnsetInfo) +// require.NoError(t, err) +// +// require.Equal(t, SearchParameterStringType{"approximately November 2012"}, testOnsetInfo) +// +//} diff --git a/backend/pkg/models/database/fhir_appointment.go b/backend/pkg/models/database/fhir_appointment.go index 43712266a..27428bcea 100644 --- a/backend/pkg/models/database/fhir_appointment.go +++ b/backend/pkg/models/database/fhir_appointment.go @@ -174,14 +174,14 @@ func (s *FhirAppointment) PopulateAndExtractSearchParameters(resourceRaw json.Ra // extracting Date dateResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'Appointment.start')") if err == nil && dateResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, dateResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01-02", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006", dateResult.String()); err == nil { s.Date = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", dateResult.String()) - if err == nil { - s.Date = &d - } } } // extracting Identifier @@ -202,14 +202,14 @@ func (s *FhirAppointment) PopulateAndExtractSearchParameters(resourceRaw json.Ra // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_binary.go b/backend/pkg/models/database/fhir_binary.go index ca8bb93b3..4c90594b9 100644 --- a/backend/pkg/models/database/fhir_binary.go +++ b/backend/pkg/models/database/fhir_binary.go @@ -100,14 +100,14 @@ func (s *FhirBinary) PopulateAndExtractSearchParameters(resourceRaw json.RawMess // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_care_plan.go b/backend/pkg/models/database/fhir_care_plan.go index 147ae955d..f7b328b75 100644 --- a/backend/pkg/models/database/fhir_care_plan.go +++ b/backend/pkg/models/database/fhir_care_plan.go @@ -229,14 +229,14 @@ func (s *FhirCarePlan) PopulateAndExtractSearchParameters(resourceRaw json.RawMe // extracting ActivityDate activityDateResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'CarePlan.activity.detail.scheduledTiming | CarePlan.activity.detail.scheduledPeriod | CarePlan.activity.detail.scheduledString')") if err == nil && activityDateResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, activityDateResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, activityDateResult.String()); err == nil { + s.ActivityDate = &t + } else if t, err = time.Parse("2006-01-02", activityDateResult.String()); err == nil { + s.ActivityDate = &t + } else if t, err = time.Parse("2006-01", activityDateResult.String()); err == nil { + s.ActivityDate = &t + } else if t, err = time.Parse("2006", activityDateResult.String()); err == nil { s.ActivityDate = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", activityDateResult.String()) - if err == nil { - s.ActivityDate = &d - } } } // extracting ActivityReference @@ -267,14 +267,14 @@ func (s *FhirCarePlan) PopulateAndExtractSearchParameters(resourceRaw json.RawMe // extracting Date dateResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'AllergyIntolerance.recordedDate | CarePlan.period | CareTeam.period | ClinicalImpression.date | Composition.date | Consent.dateTime | DiagnosticReport.effectiveDateTime | DiagnosticReport.effectivePeriod | Encounter.period | EpisodeOfCare.period | FamilyMemberHistory.date | Flag.period | (Immunization.occurrenceDateTime) | List.date | Observation.effectiveDateTime | Observation.effectivePeriod | Observation.effectiveTiming | Observation.effectiveInstant | Procedure.performedDateTime | Procedure.performedPeriod | Procedure.performedString | Procedure.performedAge | Procedure.performedRange | (RiskAssessment.occurrenceDateTime) | SupplyRequest.authoredOn')") if err == nil && dateResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, dateResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01-02", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006", dateResult.String()); err == nil { s.Date = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", dateResult.String()) - if err == nil { - s.Date = &d - } } } // extracting Encounter @@ -315,14 +315,14 @@ func (s *FhirCarePlan) PopulateAndExtractSearchParameters(resourceRaw json.RawMe // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_care_team.go b/backend/pkg/models/database/fhir_care_team.go index 621f7ab06..4f6500fec 100644 --- a/backend/pkg/models/database/fhir_care_team.go +++ b/backend/pkg/models/database/fhir_care_team.go @@ -181,14 +181,14 @@ func (s *FhirCareTeam) PopulateAndExtractSearchParameters(resourceRaw json.RawMe // extracting Date dateResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'AllergyIntolerance.recordedDate | CarePlan.period | CareTeam.period | ClinicalImpression.date | Composition.date | Consent.dateTime | DiagnosticReport.effectiveDateTime | DiagnosticReport.effectivePeriod | Encounter.period | EpisodeOfCare.period | FamilyMemberHistory.date | Flag.period | (Immunization.occurrenceDateTime) | List.date | Observation.effectiveDateTime | Observation.effectivePeriod | Observation.effectiveTiming | Observation.effectiveInstant | Procedure.performedDateTime | Procedure.performedPeriod | Procedure.performedString | Procedure.performedAge | Procedure.performedRange | (RiskAssessment.occurrenceDateTime) | SupplyRequest.authoredOn')") if err == nil && dateResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, dateResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01-02", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006", dateResult.String()); err == nil { s.Date = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", dateResult.String()) - if err == nil { - s.Date = &d - } } } // extracting Encounter @@ -209,14 +209,14 @@ func (s *FhirCareTeam) PopulateAndExtractSearchParameters(resourceRaw json.RawMe // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_claim.go b/backend/pkg/models/database/fhir_claim.go index 5db75b896..fbcfd7441 100644 --- a/backend/pkg/models/database/fhir_claim.go +++ b/backend/pkg/models/database/fhir_claim.go @@ -164,14 +164,14 @@ func (s *FhirClaim) PopulateAndExtractSearchParameters(resourceRaw json.RawMessa // extracting Created createdResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'Claim.created')") if err == nil && createdResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, createdResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, createdResult.String()); err == nil { + s.Created = &t + } else if t, err = time.Parse("2006-01-02", createdResult.String()); err == nil { + s.Created = &t + } else if t, err = time.Parse("2006-01", createdResult.String()); err == nil { + s.Created = &t + } else if t, err = time.Parse("2006", createdResult.String()); err == nil { s.Created = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", createdResult.String()) - if err == nil { - s.Created = &d - } } } // extracting DetailUdi @@ -217,14 +217,14 @@ func (s *FhirClaim) PopulateAndExtractSearchParameters(resourceRaw json.RawMessa // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_claim_response.go b/backend/pkg/models/database/fhir_claim_response.go index ae5cfae3d..74bc2dc39 100644 --- a/backend/pkg/models/database/fhir_claim_response.go +++ b/backend/pkg/models/database/fhir_claim_response.go @@ -135,14 +135,14 @@ func (s *FhirClaimResponse) PopulateAndExtractSearchParameters(resourceRaw json. // extracting Created createdResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'ClaimResponse.created')") if err == nil && createdResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, createdResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, createdResult.String()); err == nil { + s.Created = &t + } else if t, err = time.Parse("2006-01-02", createdResult.String()); err == nil { + s.Created = &t + } else if t, err = time.Parse("2006-01", createdResult.String()); err == nil { + s.Created = &t + } else if t, err = time.Parse("2006", createdResult.String()); err == nil { s.Created = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", createdResult.String()) - if err == nil { - s.Created = &d - } } } // extracting Disposition @@ -168,14 +168,14 @@ func (s *FhirClaimResponse) PopulateAndExtractSearchParameters(resourceRaw json. // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile @@ -201,14 +201,14 @@ func (s *FhirClaimResponse) PopulateAndExtractSearchParameters(resourceRaw json. // extracting PaymentDate paymentDateResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'ClaimResponse.payment.date')") if err == nil && paymentDateResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, paymentDateResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, paymentDateResult.String()); err == nil { + s.PaymentDate = &t + } else if t, err = time.Parse("2006-01-02", paymentDateResult.String()); err == nil { + s.PaymentDate = &t + } else if t, err = time.Parse("2006-01", paymentDateResult.String()); err == nil { + s.PaymentDate = &t + } else if t, err = time.Parse("2006", paymentDateResult.String()); err == nil { s.PaymentDate = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", paymentDateResult.String()) - if err == nil { - s.PaymentDate = &d - } } } // extracting Request diff --git a/backend/pkg/models/database/fhir_composition.go b/backend/pkg/models/database/fhir_composition.go index 983294142..70d1ec5e4 100644 --- a/backend/pkg/models/database/fhir_composition.go +++ b/backend/pkg/models/database/fhir_composition.go @@ -252,14 +252,14 @@ func (s *FhirComposition) PopulateAndExtractSearchParameters(resourceRaw json.Ra // extracting Date dateResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'AllergyIntolerance.recordedDate | CarePlan.period | CareTeam.period | ClinicalImpression.date | Composition.date | Consent.dateTime | DiagnosticReport.effectiveDateTime | DiagnosticReport.effectivePeriod | Encounter.period | EpisodeOfCare.period | FamilyMemberHistory.date | Flag.period | (Immunization.occurrenceDateTime) | List.date | Observation.effectiveDateTime | Observation.effectivePeriod | Observation.effectiveTiming | Observation.effectiveInstant | Procedure.performedDateTime | Procedure.performedPeriod | Procedure.performedString | Procedure.performedAge | Procedure.performedRange | (RiskAssessment.occurrenceDateTime) | SupplyRequest.authoredOn')") if err == nil && dateResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, dateResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01-02", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006", dateResult.String()); err == nil { s.Date = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", dateResult.String()) - if err == nil { - s.Date = &d - } } } // extracting Encounter @@ -285,14 +285,14 @@ func (s *FhirComposition) PopulateAndExtractSearchParameters(resourceRaw json.Ra // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile @@ -313,14 +313,14 @@ func (s *FhirComposition) PopulateAndExtractSearchParameters(resourceRaw json.Ra // extracting Period periodResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'Composition.event.period')") if err == nil && periodResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, periodResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, periodResult.String()); err == nil { + s.Period = &t + } else if t, err = time.Parse("2006-01-02", periodResult.String()); err == nil { + s.Period = &t + } else if t, err = time.Parse("2006-01", periodResult.String()); err == nil { + s.Period = &t + } else if t, err = time.Parse("2006", periodResult.String()); err == nil { s.Period = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", periodResult.String()) - if err == nil { - s.Period = &d - } } } // extracting RelatedId diff --git a/backend/pkg/models/database/fhir_condition.go b/backend/pkg/models/database/fhir_condition.go index 12a01068a..14e769df3 100644 --- a/backend/pkg/models/database/fhir_condition.go +++ b/backend/pkg/models/database/fhir_condition.go @@ -230,14 +230,14 @@ func (s *FhirCondition) PopulateAndExtractSearchParameters(resourceRaw json.RawM // extracting AbatementDate abatementDateResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'Condition.abatementDateTime | Condition.abatementPeriod')") if err == nil && abatementDateResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, abatementDateResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, abatementDateResult.String()); err == nil { + s.AbatementDate = &t + } else if t, err = time.Parse("2006-01-02", abatementDateResult.String()); err == nil { + s.AbatementDate = &t + } else if t, err = time.Parse("2006-01", abatementDateResult.String()); err == nil { + s.AbatementDate = &t + } else if t, err = time.Parse("2006", abatementDateResult.String()); err == nil { s.AbatementDate = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", abatementDateResult.String()) - if err == nil { - s.AbatementDate = &d - } } } // extracting AbatementString @@ -298,14 +298,14 @@ func (s *FhirCondition) PopulateAndExtractSearchParameters(resourceRaw json.RawM // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile @@ -331,14 +331,14 @@ func (s *FhirCondition) PopulateAndExtractSearchParameters(resourceRaw json.RawM // extracting OnsetDate onsetDateResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'Condition.onsetDateTime | Condition.onsetPeriod')") if err == nil && onsetDateResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, onsetDateResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, onsetDateResult.String()); err == nil { + s.OnsetDate = &t + } else if t, err = time.Parse("2006-01-02", onsetDateResult.String()); err == nil { + s.OnsetDate = &t + } else if t, err = time.Parse("2006-01", onsetDateResult.String()); err == nil { + s.OnsetDate = &t + } else if t, err = time.Parse("2006", onsetDateResult.String()); err == nil { s.OnsetDate = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", onsetDateResult.String()) - if err == nil { - s.OnsetDate = &d - } } } // extracting OnsetInfo @@ -349,14 +349,14 @@ func (s *FhirCondition) PopulateAndExtractSearchParameters(resourceRaw json.RawM // extracting RecordedDate recordedDateResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'Condition.recordedDate')") if err == nil && recordedDateResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, recordedDateResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, recordedDateResult.String()); err == nil { + s.RecordedDate = &t + } else if t, err = time.Parse("2006-01-02", recordedDateResult.String()); err == nil { + s.RecordedDate = &t + } else if t, err = time.Parse("2006-01", recordedDateResult.String()); err == nil { + s.RecordedDate = &t + } else if t, err = time.Parse("2006", recordedDateResult.String()); err == nil { s.RecordedDate = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", recordedDateResult.String()) - if err == nil { - s.RecordedDate = &d - } } } // extracting Severity diff --git a/backend/pkg/models/database/fhir_consent.go b/backend/pkg/models/database/fhir_consent.go index 9136b58c4..70cda6d26 100644 --- a/backend/pkg/models/database/fhir_consent.go +++ b/backend/pkg/models/database/fhir_consent.go @@ -229,14 +229,14 @@ func (s *FhirConsent) PopulateAndExtractSearchParameters(resourceRaw json.RawMes // extracting Date dateResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'AllergyIntolerance.recordedDate | CarePlan.period | CareTeam.period | ClinicalImpression.date | Composition.date | Consent.dateTime | DiagnosticReport.effectiveDateTime | DiagnosticReport.effectivePeriod | Encounter.period | EpisodeOfCare.period | FamilyMemberHistory.date | Flag.period | (Immunization.occurrenceDateTime) | List.date | Observation.effectiveDateTime | Observation.effectivePeriod | Observation.effectiveTiming | Observation.effectiveInstant | Procedure.performedDateTime | Procedure.performedPeriod | Procedure.performedString | Procedure.performedAge | Procedure.performedRange | (RiskAssessment.occurrenceDateTime) | SupplyRequest.authoredOn')") if err == nil && dateResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, dateResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01-02", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006", dateResult.String()); err == nil { s.Date = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", dateResult.String()) - if err == nil { - s.Date = &d - } } } // extracting Identifier @@ -252,14 +252,14 @@ func (s *FhirConsent) PopulateAndExtractSearchParameters(resourceRaw json.RawMes // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile @@ -285,14 +285,14 @@ func (s *FhirConsent) PopulateAndExtractSearchParameters(resourceRaw json.RawMes // extracting Period periodResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'Consent.provision.period')") if err == nil && periodResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, periodResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, periodResult.String()); err == nil { + s.Period = &t + } else if t, err = time.Parse("2006-01-02", periodResult.String()); err == nil { + s.Period = &t + } else if t, err = time.Parse("2006-01", periodResult.String()); err == nil { + s.Period = &t + } else if t, err = time.Parse("2006", periodResult.String()); err == nil { s.Period = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", periodResult.String()) - if err == nil { - s.Period = &d - } } } // extracting Purpose diff --git a/backend/pkg/models/database/fhir_coverage.go b/backend/pkg/models/database/fhir_coverage.go index 2cf3d493d..650ebf4f6 100644 --- a/backend/pkg/models/database/fhir_coverage.go +++ b/backend/pkg/models/database/fhir_coverage.go @@ -161,14 +161,14 @@ func (s *FhirCoverage) PopulateAndExtractSearchParameters(resourceRaw json.RawMe // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_coverage_eligibility_request.go b/backend/pkg/models/database/fhir_coverage_eligibility_request.go index 2e52f7025..3f15963bb 100644 --- a/backend/pkg/models/database/fhir_coverage_eligibility_request.go +++ b/backend/pkg/models/database/fhir_coverage_eligibility_request.go @@ -119,14 +119,14 @@ func (s *FhirCoverageEligibilityRequest) PopulateAndExtractSearchParameters(reso // extracting Created createdResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'CoverageEligibilityRequest.created')") if err == nil && createdResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, createdResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, createdResult.String()); err == nil { + s.Created = &t + } else if t, err = time.Parse("2006-01-02", createdResult.String()); err == nil { + s.Created = &t + } else if t, err = time.Parse("2006-01", createdResult.String()); err == nil { + s.Created = &t + } else if t, err = time.Parse("2006", createdResult.String()); err == nil { s.Created = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", createdResult.String()) - if err == nil { - s.Created = &d - } } } // extracting Enterer @@ -152,14 +152,14 @@ func (s *FhirCoverageEligibilityRequest) PopulateAndExtractSearchParameters(reso // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_coverage_eligibility_response.go b/backend/pkg/models/database/fhir_coverage_eligibility_response.go index afb6dcbec..fa98c74b1 100644 --- a/backend/pkg/models/database/fhir_coverage_eligibility_response.go +++ b/backend/pkg/models/database/fhir_coverage_eligibility_response.go @@ -127,14 +127,14 @@ func (s *FhirCoverageEligibilityResponse) PopulateAndExtractSearchParameters(res // extracting Created createdResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'CoverageEligibilityResponse.created')") if err == nil && createdResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, createdResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, createdResult.String()); err == nil { + s.Created = &t + } else if t, err = time.Parse("2006-01-02", createdResult.String()); err == nil { + s.Created = &t + } else if t, err = time.Parse("2006-01", createdResult.String()); err == nil { + s.Created = &t + } else if t, err = time.Parse("2006", createdResult.String()); err == nil { s.Created = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", createdResult.String()) - if err == nil { - s.Created = &d - } } } // extracting Disposition @@ -160,14 +160,14 @@ func (s *FhirCoverageEligibilityResponse) PopulateAndExtractSearchParameters(res // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_device.go b/backend/pkg/models/database/fhir_device.go index f765bb05e..5d3eb49a3 100644 --- a/backend/pkg/models/database/fhir_device.go +++ b/backend/pkg/models/database/fhir_device.go @@ -160,14 +160,14 @@ func (s *FhirDevice) PopulateAndExtractSearchParameters(resourceRaw json.RawMess // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_device_request.go b/backend/pkg/models/database/fhir_device_request.go index 0633c5cf7..2106d5af0 100644 --- a/backend/pkg/models/database/fhir_device_request.go +++ b/backend/pkg/models/database/fhir_device_request.go @@ -228,14 +228,14 @@ func (s *FhirDeviceRequest) PopulateAndExtractSearchParameters(resourceRaw json. // extracting AuthoredOn authoredOnResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'DeviceRequest.authoredOn')") if err == nil && authoredOnResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, authoredOnResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, authoredOnResult.String()); err == nil { + s.AuthoredOn = &t + } else if t, err = time.Parse("2006-01-02", authoredOnResult.String()); err == nil { + s.AuthoredOn = &t + } else if t, err = time.Parse("2006-01", authoredOnResult.String()); err == nil { + s.AuthoredOn = &t + } else if t, err = time.Parse("2006", authoredOnResult.String()); err == nil { s.AuthoredOn = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", authoredOnResult.String()) - if err == nil { - s.AuthoredOn = &d - } } } // extracting BasedOn @@ -261,14 +261,14 @@ func (s *FhirDeviceRequest) PopulateAndExtractSearchParameters(resourceRaw json. // extracting EventDate eventDateResult, err := vm.RunString("extractDateSearchParameters(fhirResource, '(DeviceRequest.occurrenceDateTime) | (DeviceRequest.occurrencePeriod)')") if err == nil && eventDateResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, eventDateResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, eventDateResult.String()); err == nil { + s.EventDate = &t + } else if t, err = time.Parse("2006-01-02", eventDateResult.String()); err == nil { + s.EventDate = &t + } else if t, err = time.Parse("2006-01", eventDateResult.String()); err == nil { + s.EventDate = &t + } else if t, err = time.Parse("2006", eventDateResult.String()); err == nil { s.EventDate = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", eventDateResult.String()) - if err == nil { - s.EventDate = &d - } } } // extracting GroupIdentifier @@ -309,14 +309,14 @@ func (s *FhirDeviceRequest) PopulateAndExtractSearchParameters(resourceRaw json. // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_diagnostic_report.go b/backend/pkg/models/database/fhir_diagnostic_report.go index 36fee3576..a5ec9581e 100644 --- a/backend/pkg/models/database/fhir_diagnostic_report.go +++ b/backend/pkg/models/database/fhir_diagnostic_report.go @@ -260,14 +260,14 @@ func (s *FhirDiagnosticReport) PopulateAndExtractSearchParameters(resourceRaw js // extracting Date dateResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'AllergyIntolerance.recordedDate | CarePlan.period | CareTeam.period | ClinicalImpression.date | Composition.date | Consent.dateTime | DiagnosticReport.effectiveDateTime | DiagnosticReport.effectivePeriod | Encounter.period | EpisodeOfCare.period | FamilyMemberHistory.date | Flag.period | (Immunization.occurrenceDateTime) | List.date | Observation.effectiveDateTime | Observation.effectivePeriod | Observation.effectiveTiming | Observation.effectiveInstant | Procedure.performedDateTime | Procedure.performedPeriod | Procedure.performedString | Procedure.performedAge | Procedure.performedRange | (RiskAssessment.occurrenceDateTime) | SupplyRequest.authoredOn')") if err == nil && dateResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, dateResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01-02", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006", dateResult.String()); err == nil { s.Date = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", dateResult.String()) - if err == nil { - s.Date = &d - } } } // extracting Encounter @@ -283,14 +283,14 @@ func (s *FhirDiagnosticReport) PopulateAndExtractSearchParameters(resourceRaw js // extracting Issued issuedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'DiagnosticReport.issued')") if err == nil && issuedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, issuedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, issuedResult.String()); err == nil { + s.Issued = &t + } else if t, err = time.Parse("2006-01-02", issuedResult.String()); err == nil { + s.Issued = &t + } else if t, err = time.Parse("2006-01", issuedResult.String()); err == nil { + s.Issued = &t + } else if t, err = time.Parse("2006", issuedResult.String()); err == nil { s.Issued = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", issuedResult.String()) - if err == nil { - s.Issued = &d - } } } // extracting Language @@ -306,14 +306,14 @@ func (s *FhirDiagnosticReport) PopulateAndExtractSearchParameters(resourceRaw js // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_document_manifest.go b/backend/pkg/models/database/fhir_document_manifest.go index 92ae48fa4..e8b2a3743 100644 --- a/backend/pkg/models/database/fhir_document_manifest.go +++ b/backend/pkg/models/database/fhir_document_manifest.go @@ -177,14 +177,14 @@ func (s *FhirDocumentManifest) PopulateAndExtractSearchParameters(resourceRaw js // extracting Created createdResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'DocumentManifest.created')") if err == nil && createdResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, createdResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, createdResult.String()); err == nil { + s.Created = &t + } else if t, err = time.Parse("2006-01-02", createdResult.String()); err == nil { + s.Created = &t + } else if t, err = time.Parse("2006-01", createdResult.String()); err == nil { + s.Created = &t + } else if t, err = time.Parse("2006", createdResult.String()); err == nil { s.Created = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", createdResult.String()) - if err == nil { - s.Created = &d - } } } // extracting Description @@ -210,14 +210,14 @@ func (s *FhirDocumentManifest) PopulateAndExtractSearchParameters(resourceRaw js // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_document_reference.go b/backend/pkg/models/database/fhir_document_reference.go index a9f9e42fb..a33706a01 100644 --- a/backend/pkg/models/database/fhir_document_reference.go +++ b/backend/pkg/models/database/fhir_document_reference.go @@ -252,14 +252,14 @@ func (s *FhirDocumentReference) PopulateAndExtractSearchParameters(resourceRaw j // extracting Date dateResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'DocumentReference.date')") if err == nil && dateResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, dateResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01-02", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006", dateResult.String()); err == nil { s.Date = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", dateResult.String()) - if err == nil { - s.Date = &d - } } } // extracting Description @@ -305,14 +305,14 @@ func (s *FhirDocumentReference) PopulateAndExtractSearchParameters(resourceRaw j // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile @@ -333,14 +333,14 @@ func (s *FhirDocumentReference) PopulateAndExtractSearchParameters(resourceRaw j // extracting Period periodResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'DocumentReference.context.period')") if err == nil && periodResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, periodResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, periodResult.String()); err == nil { + s.Period = &t + } else if t, err = time.Parse("2006-01-02", periodResult.String()); err == nil { + s.Period = &t + } else if t, err = time.Parse("2006-01", periodResult.String()); err == nil { + s.Period = &t + } else if t, err = time.Parse("2006", periodResult.String()); err == nil { s.Period = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", periodResult.String()) - if err == nil { - s.Period = &d - } } } // extracting Related diff --git a/backend/pkg/models/database/fhir_encounter.go b/backend/pkg/models/database/fhir_encounter.go index 430202af9..811654baf 100644 --- a/backend/pkg/models/database/fhir_encounter.go +++ b/backend/pkg/models/database/fhir_encounter.go @@ -252,14 +252,14 @@ func (s *FhirEncounter) PopulateAndExtractSearchParameters(resourceRaw json.RawM // extracting Date dateResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'AllergyIntolerance.recordedDate | CarePlan.period | CareTeam.period | ClinicalImpression.date | Composition.date | Consent.dateTime | DiagnosticReport.effectiveDateTime | DiagnosticReport.effectivePeriod | Encounter.period | EpisodeOfCare.period | FamilyMemberHistory.date | Flag.period | (Immunization.occurrenceDateTime) | List.date | Observation.effectiveDateTime | Observation.effectivePeriod | Observation.effectiveTiming | Observation.effectiveInstant | Procedure.performedDateTime | Procedure.performedPeriod | Procedure.performedString | Procedure.performedAge | Procedure.performedRange | (RiskAssessment.occurrenceDateTime) | SupplyRequest.authoredOn')") if err == nil && dateResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, dateResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01-02", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006", dateResult.String()); err == nil { s.Date = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", dateResult.String()) - if err == nil { - s.Date = &d - } } } // extracting Diagnosis @@ -295,27 +295,27 @@ func (s *FhirEncounter) PopulateAndExtractSearchParameters(resourceRaw json.RawM // extracting LocationPeriod locationPeriodResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'Encounter.location.period')") if err == nil && locationPeriodResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, locationPeriodResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, locationPeriodResult.String()); err == nil { + s.LocationPeriod = &t + } else if t, err = time.Parse("2006-01-02", locationPeriodResult.String()); err == nil { + s.LocationPeriod = &t + } else if t, err = time.Parse("2006-01", locationPeriodResult.String()); err == nil { + s.LocationPeriod = &t + } else if t, err = time.Parse("2006", locationPeriodResult.String()); err == nil { s.LocationPeriod = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", locationPeriodResult.String()) - if err == nil { - s.LocationPeriod = &d - } } } // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_endpoint.go b/backend/pkg/models/database/fhir_endpoint.go index 372951146..c9bcb3420 100644 --- a/backend/pkg/models/database/fhir_endpoint.go +++ b/backend/pkg/models/database/fhir_endpoint.go @@ -134,14 +134,14 @@ func (s *FhirEndpoint) PopulateAndExtractSearchParameters(resourceRaw json.RawMe // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_enrollment_request.go b/backend/pkg/models/database/fhir_enrollment_request.go index 36aa152be..e8f327599 100644 --- a/backend/pkg/models/database/fhir_enrollment_request.go +++ b/backend/pkg/models/database/fhir_enrollment_request.go @@ -117,14 +117,14 @@ func (s *FhirEnrollmentRequest) PopulateAndExtractSearchParameters(resourceRaw j // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_enrollment_response.go b/backend/pkg/models/database/fhir_enrollment_response.go index 1aae1f250..d3d9528a9 100644 --- a/backend/pkg/models/database/fhir_enrollment_response.go +++ b/backend/pkg/models/database/fhir_enrollment_response.go @@ -117,14 +117,14 @@ func (s *FhirEnrollmentResponse) PopulateAndExtractSearchParameters(resourceRaw // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_explanation_of_benefit.go b/backend/pkg/models/database/fhir_explanation_of_benefit.go index a4a0c23d8..237dc6f58 100644 --- a/backend/pkg/models/database/fhir_explanation_of_benefit.go +++ b/backend/pkg/models/database/fhir_explanation_of_benefit.go @@ -174,14 +174,14 @@ func (s *FhirExplanationOfBenefit) PopulateAndExtractSearchParameters(resourceRa // extracting Created createdResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'ExplanationOfBenefit.created')") if err == nil && createdResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, createdResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, createdResult.String()); err == nil { + s.Created = &t + } else if t, err = time.Parse("2006-01-02", createdResult.String()); err == nil { + s.Created = &t + } else if t, err = time.Parse("2006-01", createdResult.String()); err == nil { + s.Created = &t + } else if t, err = time.Parse("2006", createdResult.String()); err == nil { s.Created = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", createdResult.String()) - if err == nil { - s.Created = &d - } } } // extracting DetailUdi @@ -227,14 +227,14 @@ func (s *FhirExplanationOfBenefit) PopulateAndExtractSearchParameters(resourceRa // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_family_member_history.go b/backend/pkg/models/database/fhir_family_member_history.go index fe2a17bff..562282219 100644 --- a/backend/pkg/models/database/fhir_family_member_history.go +++ b/backend/pkg/models/database/fhir_family_member_history.go @@ -202,14 +202,14 @@ func (s *FhirFamilyMemberHistory) PopulateAndExtractSearchParameters(resourceRaw // extracting Date dateResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'AllergyIntolerance.recordedDate | CarePlan.period | CareTeam.period | ClinicalImpression.date | Composition.date | Consent.dateTime | DiagnosticReport.effectiveDateTime | DiagnosticReport.effectivePeriod | Encounter.period | EpisodeOfCare.period | FamilyMemberHistory.date | Flag.period | (Immunization.occurrenceDateTime) | List.date | Observation.effectiveDateTime | Observation.effectivePeriod | Observation.effectiveTiming | Observation.effectiveInstant | Procedure.performedDateTime | Procedure.performedPeriod | Procedure.performedString | Procedure.performedAge | Procedure.performedRange | (RiskAssessment.occurrenceDateTime) | SupplyRequest.authoredOn')") if err == nil && dateResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, dateResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01-02", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006", dateResult.String()); err == nil { s.Date = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", dateResult.String()) - if err == nil { - s.Date = &d - } } } // extracting Identifier @@ -235,14 +235,14 @@ func (s *FhirFamilyMemberHistory) PopulateAndExtractSearchParameters(resourceRaw // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_goal.go b/backend/pkg/models/database/fhir_goal.go index e01165f6d..48003bd26 100644 --- a/backend/pkg/models/database/fhir_goal.go +++ b/backend/pkg/models/database/fhir_goal.go @@ -181,14 +181,14 @@ func (s *FhirGoal) PopulateAndExtractSearchParameters(resourceRaw json.RawMessag // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile @@ -209,14 +209,14 @@ func (s *FhirGoal) PopulateAndExtractSearchParameters(resourceRaw json.RawMessag // extracting StartDate startDateResult, err := vm.RunString("extractDateSearchParameters(fhirResource, '(Goal.startDate)')") if err == nil && startDateResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, startDateResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, startDateResult.String()); err == nil { + s.StartDate = &t + } else if t, err = time.Parse("2006-01-02", startDateResult.String()); err == nil { + s.StartDate = &t + } else if t, err = time.Parse("2006-01", startDateResult.String()); err == nil { + s.StartDate = &t + } else if t, err = time.Parse("2006", startDateResult.String()); err == nil { s.StartDate = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", startDateResult.String()) - if err == nil { - s.StartDate = &d - } } } // extracting Subject @@ -227,14 +227,14 @@ func (s *FhirGoal) PopulateAndExtractSearchParameters(resourceRaw json.RawMessag // extracting TargetDate targetDateResult, err := vm.RunString("extractDateSearchParameters(fhirResource, '(Goal.target.dueDate)')") if err == nil && targetDateResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, targetDateResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, targetDateResult.String()); err == nil { + s.TargetDate = &t + } else if t, err = time.Parse("2006-01-02", targetDateResult.String()); err == nil { + s.TargetDate = &t + } else if t, err = time.Parse("2006-01", targetDateResult.String()); err == nil { + s.TargetDate = &t + } else if t, err = time.Parse("2006", targetDateResult.String()); err == nil { s.TargetDate = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", targetDateResult.String()) - if err == nil { - s.TargetDate = &d - } } } // extracting Text diff --git a/backend/pkg/models/database/fhir_imaging_study.go b/backend/pkg/models/database/fhir_imaging_study.go index b2127e354..5703b85d4 100644 --- a/backend/pkg/models/database/fhir_imaging_study.go +++ b/backend/pkg/models/database/fhir_imaging_study.go @@ -237,14 +237,14 @@ func (s *FhirImagingStudy) PopulateAndExtractSearchParameters(resourceRaw json.R // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile @@ -290,14 +290,14 @@ func (s *FhirImagingStudy) PopulateAndExtractSearchParameters(resourceRaw json.R // extracting Started startedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'ImagingStudy.started')") if err == nil && startedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, startedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, startedResult.String()); err == nil { + s.Started = &t + } else if t, err = time.Parse("2006-01-02", startedResult.String()); err == nil { + s.Started = &t + } else if t, err = time.Parse("2006-01", startedResult.String()); err == nil { + s.Started = &t + } else if t, err = time.Parse("2006", startedResult.String()); err == nil { s.Started = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", startedResult.String()) - if err == nil { - s.Started = &d - } } } // extracting Status diff --git a/backend/pkg/models/database/fhir_immunization.go b/backend/pkg/models/database/fhir_immunization.go index 3e4494992..2474785e9 100644 --- a/backend/pkg/models/database/fhir_immunization.go +++ b/backend/pkg/models/database/fhir_immunization.go @@ -208,14 +208,14 @@ func (s *FhirImmunization) PopulateAndExtractSearchParameters(resourceRaw json.R // extracting Date dateResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'AllergyIntolerance.recordedDate | CarePlan.period | CareTeam.period | ClinicalImpression.date | Composition.date | Consent.dateTime | DiagnosticReport.effectiveDateTime | DiagnosticReport.effectivePeriod | Encounter.period | EpisodeOfCare.period | FamilyMemberHistory.date | Flag.period | (Immunization.occurrenceDateTime) | List.date | Observation.effectiveDateTime | Observation.effectivePeriod | Observation.effectiveTiming | Observation.effectiveInstant | Procedure.performedDateTime | Procedure.performedPeriod | Procedure.performedString | Procedure.performedAge | Procedure.performedRange | (RiskAssessment.occurrenceDateTime) | SupplyRequest.authoredOn')") if err == nil && dateResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, dateResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01-02", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006", dateResult.String()); err == nil { s.Date = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", dateResult.String()) - if err == nil { - s.Date = &d - } } } // extracting Identifier @@ -246,14 +246,14 @@ func (s *FhirImmunization) PopulateAndExtractSearchParameters(resourceRaw json.R // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile @@ -284,14 +284,14 @@ func (s *FhirImmunization) PopulateAndExtractSearchParameters(resourceRaw json.R // extracting ReactionDate reactionDateResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'Immunization.reaction.date')") if err == nil && reactionDateResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, reactionDateResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, reactionDateResult.String()); err == nil { + s.ReactionDate = &t + } else if t, err = time.Parse("2006-01-02", reactionDateResult.String()); err == nil { + s.ReactionDate = &t + } else if t, err = time.Parse("2006-01", reactionDateResult.String()); err == nil { + s.ReactionDate = &t + } else if t, err = time.Parse("2006", reactionDateResult.String()); err == nil { s.ReactionDate = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", reactionDateResult.String()) - if err == nil { - s.ReactionDate = &d - } } } // extracting ReasonCode diff --git a/backend/pkg/models/database/fhir_insurance_plan.go b/backend/pkg/models/database/fhir_insurance_plan.go index ad21de1a1..a36732728 100644 --- a/backend/pkg/models/database/fhir_insurance_plan.go +++ b/backend/pkg/models/database/fhir_insurance_plan.go @@ -197,14 +197,14 @@ func (s *FhirInsurancePlan) PopulateAndExtractSearchParameters(resourceRaw json. // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_location.go b/backend/pkg/models/database/fhir_location.go index b3d78a223..66cc2c0df 100644 --- a/backend/pkg/models/database/fhir_location.go +++ b/backend/pkg/models/database/fhir_location.go @@ -192,14 +192,14 @@ func (s *FhirLocation) PopulateAndExtractSearchParameters(resourceRaw json.RawMe // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_media.go b/backend/pkg/models/database/fhir_media.go index 378d32a53..64df835a4 100644 --- a/backend/pkg/models/database/fhir_media.go +++ b/backend/pkg/models/database/fhir_media.go @@ -144,14 +144,14 @@ func (s *FhirMedia) PopulateAndExtractSearchParameters(resourceRaw json.RawMessa // extracting Created createdResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'Media.createdDateTime | Media.createdPeriod')") if err == nil && createdResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, createdResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, createdResult.String()); err == nil { + s.Created = &t + } else if t, err = time.Parse("2006-01-02", createdResult.String()); err == nil { + s.Created = &t + } else if t, err = time.Parse("2006-01", createdResult.String()); err == nil { + s.Created = &t + } else if t, err = time.Parse("2006", createdResult.String()); err == nil { s.Created = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", createdResult.String()) - if err == nil { - s.Created = &d - } } } // extracting Device @@ -177,14 +177,14 @@ func (s *FhirMedia) PopulateAndExtractSearchParameters(resourceRaw json.RawMessa // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_medication.go b/backend/pkg/models/database/fhir_medication.go index 78d8914f5..e035aa04b 100644 --- a/backend/pkg/models/database/fhir_medication.go +++ b/backend/pkg/models/database/fhir_medication.go @@ -153,14 +153,14 @@ func (s *FhirMedication) PopulateAndExtractSearchParameters(resourceRaw json.Raw // extracting ExpirationDate expirationDateResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'Medication.batch.expirationDate')") if err == nil && expirationDateResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, expirationDateResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, expirationDateResult.String()); err == nil { + s.ExpirationDate = &t + } else if t, err = time.Parse("2006-01-02", expirationDateResult.String()); err == nil { + s.ExpirationDate = &t + } else if t, err = time.Parse("2006-01", expirationDateResult.String()); err == nil { + s.ExpirationDate = &t + } else if t, err = time.Parse("2006", expirationDateResult.String()); err == nil { s.ExpirationDate = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", expirationDateResult.String()) - if err == nil { - s.ExpirationDate = &d - } } } // extracting Form @@ -201,14 +201,14 @@ func (s *FhirMedication) PopulateAndExtractSearchParameters(resourceRaw json.Raw // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_medication_administration.go b/backend/pkg/models/database/fhir_medication_administration.go index d9534b8c7..198781b9c 100644 --- a/backend/pkg/models/database/fhir_medication_administration.go +++ b/backend/pkg/models/database/fhir_medication_administration.go @@ -222,14 +222,14 @@ func (s *FhirMedicationAdministration) PopulateAndExtractSearchParameters(resour // extracting EffectiveTime effectiveTimeResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'MedicationAdministration.effectiveDateTime | MedicationAdministration.effectivePeriod')") if err == nil && effectiveTimeResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, effectiveTimeResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, effectiveTimeResult.String()); err == nil { + s.EffectiveTime = &t + } else if t, err = time.Parse("2006-01-02", effectiveTimeResult.String()); err == nil { + s.EffectiveTime = &t + } else if t, err = time.Parse("2006-01", effectiveTimeResult.String()); err == nil { + s.EffectiveTime = &t + } else if t, err = time.Parse("2006", effectiveTimeResult.String()); err == nil { s.EffectiveTime = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", effectiveTimeResult.String()) - if err == nil { - s.EffectiveTime = &d - } } } // extracting Identifier @@ -250,14 +250,14 @@ func (s *FhirMedicationAdministration) PopulateAndExtractSearchParameters(resour // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_medication_dispense.go b/backend/pkg/models/database/fhir_medication_dispense.go index 7cf72bf38..f18d881bd 100644 --- a/backend/pkg/models/database/fhir_medication_dispense.go +++ b/backend/pkg/models/database/fhir_medication_dispense.go @@ -245,14 +245,14 @@ func (s *FhirMedicationDispense) PopulateAndExtractSearchParameters(resourceRaw // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile @@ -308,27 +308,27 @@ func (s *FhirMedicationDispense) PopulateAndExtractSearchParameters(resourceRaw // extracting Whenhandedover whenhandedoverResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'MedicationDispense.whenHandedOver')") if err == nil && whenhandedoverResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, whenhandedoverResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, whenhandedoverResult.String()); err == nil { + s.Whenhandedover = &t + } else if t, err = time.Parse("2006-01-02", whenhandedoverResult.String()); err == nil { + s.Whenhandedover = &t + } else if t, err = time.Parse("2006-01", whenhandedoverResult.String()); err == nil { + s.Whenhandedover = &t + } else if t, err = time.Parse("2006", whenhandedoverResult.String()); err == nil { s.Whenhandedover = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", whenhandedoverResult.String()) - if err == nil { - s.Whenhandedover = &d - } } } // extracting Whenprepared whenpreparedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'MedicationDispense.whenPrepared')") if err == nil && whenpreparedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, whenpreparedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, whenpreparedResult.String()); err == nil { + s.Whenprepared = &t + } else if t, err = time.Parse("2006-01-02", whenpreparedResult.String()); err == nil { + s.Whenprepared = &t + } else if t, err = time.Parse("2006-01", whenpreparedResult.String()); err == nil { + s.Whenprepared = &t + } else if t, err = time.Parse("2006", whenpreparedResult.String()); err == nil { s.Whenprepared = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", whenpreparedResult.String()) - if err == nil { - s.Whenprepared = &d - } } } return nil diff --git a/backend/pkg/models/database/fhir_medication_request.go b/backend/pkg/models/database/fhir_medication_request.go index 9be6515a8..867093c83 100644 --- a/backend/pkg/models/database/fhir_medication_request.go +++ b/backend/pkg/models/database/fhir_medication_request.go @@ -227,14 +227,14 @@ func (s *FhirMedicationRequest) PopulateAndExtractSearchParameters(resourceRaw j // extracting Authoredon authoredonResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'MedicationRequest.authoredOn')") if err == nil && authoredonResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, authoredonResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, authoredonResult.String()); err == nil { + s.Authoredon = &t + } else if t, err = time.Parse("2006-01-02", authoredonResult.String()); err == nil { + s.Authoredon = &t + } else if t, err = time.Parse("2006-01", authoredonResult.String()); err == nil { + s.Authoredon = &t + } else if t, err = time.Parse("2006", authoredonResult.String()); err == nil { s.Authoredon = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", authoredonResult.String()) - if err == nil { - s.Authoredon = &d - } } } // extracting Category @@ -250,14 +250,14 @@ func (s *FhirMedicationRequest) PopulateAndExtractSearchParameters(resourceRaw j // extracting Date dateResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'MedicationRequest.dosageInstruction.timing.event')") if err == nil && dateResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, dateResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01-02", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006", dateResult.String()); err == nil { s.Date = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", dateResult.String()) - if err == nil { - s.Date = &d - } } } // extracting Encounter @@ -303,14 +303,14 @@ func (s *FhirMedicationRequest) PopulateAndExtractSearchParameters(resourceRaw j // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_medication_statement.go b/backend/pkg/models/database/fhir_medication_statement.go index 54dc931c7..c15a0ba47 100644 --- a/backend/pkg/models/database/fhir_medication_statement.go +++ b/backend/pkg/models/database/fhir_medication_statement.go @@ -214,14 +214,14 @@ func (s *FhirMedicationStatement) PopulateAndExtractSearchParameters(resourceRaw // extracting Effective effectiveResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'MedicationStatement.effectiveDateTime | MedicationStatement.effectivePeriod')") if err == nil && effectiveResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, effectiveResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, effectiveResult.String()); err == nil { + s.Effective = &t + } else if t, err = time.Parse("2006-01-02", effectiveResult.String()); err == nil { + s.Effective = &t + } else if t, err = time.Parse("2006-01", effectiveResult.String()); err == nil { + s.Effective = &t + } else if t, err = time.Parse("2006", effectiveResult.String()); err == nil { s.Effective = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", effectiveResult.String()) - if err == nil { - s.Effective = &d - } } } // extracting Identifier @@ -242,14 +242,14 @@ func (s *FhirMedicationStatement) PopulateAndExtractSearchParameters(resourceRaw // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_nutrition_order.go b/backend/pkg/models/database/fhir_nutrition_order.go index 20cd82fa4..15bef5490 100644 --- a/backend/pkg/models/database/fhir_nutrition_order.go +++ b/backend/pkg/models/database/fhir_nutrition_order.go @@ -192,14 +192,14 @@ func (s *FhirNutritionOrder) PopulateAndExtractSearchParameters(resourceRaw json // extracting Datetime datetimeResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'NutritionOrder.dateTime')") if err == nil && datetimeResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, datetimeResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, datetimeResult.String()); err == nil { + s.Datetime = &t + } else if t, err = time.Parse("2006-01-02", datetimeResult.String()); err == nil { + s.Datetime = &t + } else if t, err = time.Parse("2006-01", datetimeResult.String()); err == nil { + s.Datetime = &t + } else if t, err = time.Parse("2006", datetimeResult.String()); err == nil { s.Datetime = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", datetimeResult.String()) - if err == nil { - s.Datetime = &d - } } } // extracting Encounter @@ -235,14 +235,14 @@ func (s *FhirNutritionOrder) PopulateAndExtractSearchParameters(resourceRaw json // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_observation.go b/backend/pkg/models/database/fhir_observation.go index 61afb41ed..261aaa4cb 100644 --- a/backend/pkg/models/database/fhir_observation.go +++ b/backend/pkg/models/database/fhir_observation.go @@ -356,14 +356,14 @@ func (s *FhirObservation) PopulateAndExtractSearchParameters(resourceRaw json.Ra // extracting Date dateResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'AllergyIntolerance.recordedDate | CarePlan.period | CareTeam.period | ClinicalImpression.date | Composition.date | Consent.dateTime | DiagnosticReport.effectiveDateTime | DiagnosticReport.effectivePeriod | Encounter.period | EpisodeOfCare.period | FamilyMemberHistory.date | Flag.period | (Immunization.occurrenceDateTime) | List.date | Observation.effectiveDateTime | Observation.effectivePeriod | Observation.effectiveTiming | Observation.effectiveInstant | Procedure.performedDateTime | Procedure.performedPeriod | Procedure.performedString | Procedure.performedAge | Procedure.performedRange | (RiskAssessment.occurrenceDateTime) | SupplyRequest.authoredOn')") if err == nil && dateResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, dateResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01-02", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006", dateResult.String()); err == nil { s.Date = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", dateResult.String()) - if err == nil { - s.Date = &d - } } } // extracting DerivedFrom @@ -404,14 +404,14 @@ func (s *FhirObservation) PopulateAndExtractSearchParameters(resourceRaw json.Ra // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile @@ -472,14 +472,14 @@ func (s *FhirObservation) PopulateAndExtractSearchParameters(resourceRaw json.Ra // extracting ValueDate valueDateResult, err := vm.RunString("extractDateSearchParameters(fhirResource, '(Observation.valueDateTime) | (Observation.valuePeriod)')") if err == nil && valueDateResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, valueDateResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, valueDateResult.String()); err == nil { + s.ValueDate = &t + } else if t, err = time.Parse("2006-01-02", valueDateResult.String()); err == nil { + s.ValueDate = &t + } else if t, err = time.Parse("2006-01", valueDateResult.String()); err == nil { + s.ValueDate = &t + } else if t, err = time.Parse("2006", valueDateResult.String()); err == nil { s.ValueDate = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", valueDateResult.String()) - if err == nil { - s.ValueDate = &d - } } } // extracting ValueQuantity diff --git a/backend/pkg/models/database/fhir_organization.go b/backend/pkg/models/database/fhir_organization.go index 990dde240..8253fa063 100644 --- a/backend/pkg/models/database/fhir_organization.go +++ b/backend/pkg/models/database/fhir_organization.go @@ -193,14 +193,14 @@ func (s *FhirOrganization) PopulateAndExtractSearchParameters(resourceRaw json.R // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_organization_affiliation.go b/backend/pkg/models/database/fhir_organization_affiliation.go index 095dfcf36..dd44b3a2b 100644 --- a/backend/pkg/models/database/fhir_organization_affiliation.go +++ b/backend/pkg/models/database/fhir_organization_affiliation.go @@ -156,14 +156,14 @@ func (s *FhirOrganizationAffiliation) PopulateAndExtractSearchParameters(resourc // extracting Date dateResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'OrganizationAffiliation.period')") if err == nil && dateResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, dateResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01-02", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006", dateResult.String()); err == nil { s.Date = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", dateResult.String()) - if err == nil { - s.Date = &d - } } } // extracting Email @@ -194,14 +194,14 @@ func (s *FhirOrganizationAffiliation) PopulateAndExtractSearchParameters(resourc // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_patient.go b/backend/pkg/models/database/fhir_patient.go index 71ceb6b5b..561a7eafc 100644 --- a/backend/pkg/models/database/fhir_patient.go +++ b/backend/pkg/models/database/fhir_patient.go @@ -314,27 +314,27 @@ func (s *FhirPatient) PopulateAndExtractSearchParameters(resourceRaw json.RawMes // extracting Birthdate birthdateResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'Patient.birthDate | Person.birthDate | RelatedPerson.birthDate')") if err == nil && birthdateResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, birthdateResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, birthdateResult.String()); err == nil { + s.Birthdate = &t + } else if t, err = time.Parse("2006-01-02", birthdateResult.String()); err == nil { + s.Birthdate = &t + } else if t, err = time.Parse("2006-01", birthdateResult.String()); err == nil { + s.Birthdate = &t + } else if t, err = time.Parse("2006", birthdateResult.String()); err == nil { s.Birthdate = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", birthdateResult.String()) - if err == nil { - s.Birthdate = &d - } } } // extracting DeathDate deathDateResult, err := vm.RunString("extractDateSearchParameters(fhirResource, '(Patient.deceasedDateTime)')") if err == nil && deathDateResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, deathDateResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, deathDateResult.String()); err == nil { + s.DeathDate = &t + } else if t, err = time.Parse("2006-01-02", deathDateResult.String()); err == nil { + s.DeathDate = &t + } else if t, err = time.Parse("2006-01", deathDateResult.String()); err == nil { + s.DeathDate = &t + } else if t, err = time.Parse("2006", deathDateResult.String()); err == nil { s.DeathDate = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", deathDateResult.String()) - if err == nil { - s.DeathDate = &d - } } } // extracting Deceased @@ -385,14 +385,14 @@ func (s *FhirPatient) PopulateAndExtractSearchParameters(resourceRaw json.RawMes // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_person.go b/backend/pkg/models/database/fhir_person.go index f41d335f4..356e55b14 100644 --- a/backend/pkg/models/database/fhir_person.go +++ b/backend/pkg/models/database/fhir_person.go @@ -283,14 +283,14 @@ func (s *FhirPerson) PopulateAndExtractSearchParameters(resourceRaw json.RawMess // extracting Birthdate birthdateResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'Patient.birthDate | Person.birthDate | RelatedPerson.birthDate')") if err == nil && birthdateResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, birthdateResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, birthdateResult.String()); err == nil { + s.Birthdate = &t + } else if t, err = time.Parse("2006-01-02", birthdateResult.String()); err == nil { + s.Birthdate = &t + } else if t, err = time.Parse("2006-01", birthdateResult.String()); err == nil { + s.Birthdate = &t + } else if t, err = time.Parse("2006", birthdateResult.String()); err == nil { s.Birthdate = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", birthdateResult.String()) - if err == nil { - s.Birthdate = &d - } } } // extracting Email @@ -321,14 +321,14 @@ func (s *FhirPerson) PopulateAndExtractSearchParameters(resourceRaw json.RawMess // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_practitioner.go b/backend/pkg/models/database/fhir_practitioner.go index 46540dbfc..897cfd253 100644 --- a/backend/pkg/models/database/fhir_practitioner.go +++ b/backend/pkg/models/database/fhir_practitioner.go @@ -323,14 +323,14 @@ func (s *FhirPractitioner) PopulateAndExtractSearchParameters(resourceRaw json.R // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_practitioner_role.go b/backend/pkg/models/database/fhir_practitioner_role.go index 703a43fb8..1aa4b33da 100644 --- a/backend/pkg/models/database/fhir_practitioner_role.go +++ b/backend/pkg/models/database/fhir_practitioner_role.go @@ -176,14 +176,14 @@ func (s *FhirPractitionerRole) PopulateAndExtractSearchParameters(resourceRaw js // extracting Date dateResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'PractitionerRole.period')") if err == nil && dateResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, dateResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01-02", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006", dateResult.String()); err == nil { s.Date = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", dateResult.String()) - if err == nil { - s.Date = &d - } } } // extracting Email @@ -214,14 +214,14 @@ func (s *FhirPractitionerRole) PopulateAndExtractSearchParameters(resourceRaw js // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_procedure.go b/backend/pkg/models/database/fhir_procedure.go index 09774e846..6dd048d9c 100644 --- a/backend/pkg/models/database/fhir_procedure.go +++ b/backend/pkg/models/database/fhir_procedure.go @@ -255,14 +255,14 @@ func (s *FhirProcedure) PopulateAndExtractSearchParameters(resourceRaw json.RawM // extracting Date dateResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'AllergyIntolerance.recordedDate | CarePlan.period | CareTeam.period | ClinicalImpression.date | Composition.date | Consent.dateTime | DiagnosticReport.effectiveDateTime | DiagnosticReport.effectivePeriod | Encounter.period | EpisodeOfCare.period | FamilyMemberHistory.date | Flag.period | (Immunization.occurrenceDateTime) | List.date | Observation.effectiveDateTime | Observation.effectivePeriod | Observation.effectiveTiming | Observation.effectiveInstant | Procedure.performedDateTime | Procedure.performedPeriod | Procedure.performedString | Procedure.performedAge | Procedure.performedRange | (RiskAssessment.occurrenceDateTime) | SupplyRequest.authoredOn')") if err == nil && dateResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, dateResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01-02", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006", dateResult.String()); err == nil { s.Date = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", dateResult.String()) - if err == nil { - s.Date = &d - } } } // extracting Encounter @@ -298,14 +298,14 @@ func (s *FhirProcedure) PopulateAndExtractSearchParameters(resourceRaw json.RawM // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_provenance.go b/backend/pkg/models/database/fhir_provenance.go index ea9a3a6c8..ab61b7c72 100644 --- a/backend/pkg/models/database/fhir_provenance.go +++ b/backend/pkg/models/database/fhir_provenance.go @@ -161,14 +161,14 @@ func (s *FhirProvenance) PopulateAndExtractSearchParameters(resourceRaw json.Raw // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile @@ -189,14 +189,14 @@ func (s *FhirProvenance) PopulateAndExtractSearchParameters(resourceRaw json.Raw // extracting Recorded recordedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'Provenance.recorded')") if err == nil && recordedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, recordedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, recordedResult.String()); err == nil { + s.Recorded = &t + } else if t, err = time.Parse("2006-01-02", recordedResult.String()); err == nil { + s.Recorded = &t + } else if t, err = time.Parse("2006-01", recordedResult.String()); err == nil { + s.Recorded = &t + } else if t, err = time.Parse("2006", recordedResult.String()); err == nil { s.Recorded = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", recordedResult.String()) - if err == nil { - s.Recorded = &d - } } } // extracting SignatureType @@ -217,14 +217,14 @@ func (s *FhirProvenance) PopulateAndExtractSearchParameters(resourceRaw json.Raw // extracting When whenResult, err := vm.RunString("extractDateSearchParameters(fhirResource, '(Provenance.occurredDateTime)')") if err == nil && whenResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, whenResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, whenResult.String()); err == nil { + s.When = &t + } else if t, err = time.Parse("2006-01-02", whenResult.String()); err == nil { + s.When = &t + } else if t, err = time.Parse("2006-01", whenResult.String()); err == nil { + s.When = &t + } else if t, err = time.Parse("2006", whenResult.String()); err == nil { s.When = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", whenResult.String()) - if err == nil { - s.When = &d - } } } return nil diff --git a/backend/pkg/models/database/fhir_questionnaire.go b/backend/pkg/models/database/fhir_questionnaire.go index 0cb652fe3..08b2d8562 100644 --- a/backend/pkg/models/database/fhir_questionnaire.go +++ b/backend/pkg/models/database/fhir_questionnaire.go @@ -183,14 +183,14 @@ func (s *FhirQuestionnaire) PopulateAndExtractSearchParameters(resourceRaw json. // extracting Date dateResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'Questionnaire.date')") if err == nil && dateResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, dateResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01-02", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006", dateResult.String()); err == nil { s.Date = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", dateResult.String()) - if err == nil { - s.Date = &d - } } } // extracting Definition @@ -206,14 +206,14 @@ func (s *FhirQuestionnaire) PopulateAndExtractSearchParameters(resourceRaw json. // extracting Effective effectiveResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'Questionnaire.effectivePeriod')") if err == nil && effectiveResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, effectiveResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, effectiveResult.String()); err == nil { + s.Effective = &t + } else if t, err = time.Parse("2006-01-02", effectiveResult.String()); err == nil { + s.Effective = &t + } else if t, err = time.Parse("2006-01", effectiveResult.String()); err == nil { + s.Effective = &t + } else if t, err = time.Parse("2006", effectiveResult.String()); err == nil { s.Effective = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", effectiveResult.String()) - if err == nil { - s.Effective = &d - } } } // extracting Identifier @@ -234,14 +234,14 @@ func (s *FhirQuestionnaire) PopulateAndExtractSearchParameters(resourceRaw json. // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_questionnaire_response.go b/backend/pkg/models/database/fhir_questionnaire_response.go index 9b3fa91c2..513acc19b 100644 --- a/backend/pkg/models/database/fhir_questionnaire_response.go +++ b/backend/pkg/models/database/fhir_questionnaire_response.go @@ -140,14 +140,14 @@ func (s *FhirQuestionnaireResponse) PopulateAndExtractSearchParameters(resourceR // extracting Authored authoredResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'QuestionnaireResponse.authored')") if err == nil && authoredResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, authoredResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, authoredResult.String()); err == nil { + s.Authored = &t + } else if t, err = time.Parse("2006-01-02", authoredResult.String()); err == nil { + s.Authored = &t + } else if t, err = time.Parse("2006-01", authoredResult.String()); err == nil { + s.Authored = &t + } else if t, err = time.Parse("2006", authoredResult.String()); err == nil { s.Authored = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", authoredResult.String()) - if err == nil { - s.Authored = &d - } } } // extracting BasedOn @@ -173,14 +173,14 @@ func (s *FhirQuestionnaireResponse) PopulateAndExtractSearchParameters(resourceR // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_related_person.go b/backend/pkg/models/database/fhir_related_person.go index ade88f29a..4b4f9ea11 100644 --- a/backend/pkg/models/database/fhir_related_person.go +++ b/backend/pkg/models/database/fhir_related_person.go @@ -280,14 +280,14 @@ func (s *FhirRelatedPerson) PopulateAndExtractSearchParameters(resourceRaw json. // extracting Birthdate birthdateResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'Patient.birthDate | Person.birthDate | RelatedPerson.birthDate')") if err == nil && birthdateResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, birthdateResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, birthdateResult.String()); err == nil { + s.Birthdate = &t + } else if t, err = time.Parse("2006-01-02", birthdateResult.String()); err == nil { + s.Birthdate = &t + } else if t, err = time.Parse("2006-01", birthdateResult.String()); err == nil { + s.Birthdate = &t + } else if t, err = time.Parse("2006", birthdateResult.String()); err == nil { s.Birthdate = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", birthdateResult.String()) - if err == nil { - s.Birthdate = &d - } } } // extracting Email @@ -313,14 +313,14 @@ func (s *FhirRelatedPerson) PopulateAndExtractSearchParameters(resourceRaw json. // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_schedule.go b/backend/pkg/models/database/fhir_schedule.go index fd7b45603..4874b04c1 100644 --- a/backend/pkg/models/database/fhir_schedule.go +++ b/backend/pkg/models/database/fhir_schedule.go @@ -133,14 +133,14 @@ func (s *FhirSchedule) PopulateAndExtractSearchParameters(resourceRaw json.RawMe // extracting Date dateResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'Schedule.planningHorizon')") if err == nil && dateResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, dateResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01-02", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006-01", dateResult.String()); err == nil { + s.Date = &t + } else if t, err = time.Parse("2006", dateResult.String()); err == nil { s.Date = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", dateResult.String()) - if err == nil { - s.Date = &d - } } } // extracting Identifier @@ -156,14 +156,14 @@ func (s *FhirSchedule) PopulateAndExtractSearchParameters(resourceRaw json.RawMe // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_service_request.go b/backend/pkg/models/database/fhir_service_request.go index 535d4628c..0900cd540 100644 --- a/backend/pkg/models/database/fhir_service_request.go +++ b/backend/pkg/models/database/fhir_service_request.go @@ -240,14 +240,14 @@ func (s *FhirServiceRequest) PopulateAndExtractSearchParameters(resourceRaw json // extracting Authored authoredResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'ServiceRequest.authoredOn')") if err == nil && authoredResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, authoredResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, authoredResult.String()); err == nil { + s.Authored = &t + } else if t, err = time.Parse("2006-01-02", authoredResult.String()); err == nil { + s.Authored = &t + } else if t, err = time.Parse("2006-01", authoredResult.String()); err == nil { + s.Authored = &t + } else if t, err = time.Parse("2006", authoredResult.String()); err == nil { s.Authored = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", authoredResult.String()) - if err == nil { - s.Authored = &d - } } } // extracting BasedOn @@ -303,14 +303,14 @@ func (s *FhirServiceRequest) PopulateAndExtractSearchParameters(resourceRaw json // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile @@ -331,14 +331,14 @@ func (s *FhirServiceRequest) PopulateAndExtractSearchParameters(resourceRaw json // extracting Occurrence occurrenceResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'ServiceRequest.occurrenceDateTime | ServiceRequest.occurrencePeriod | ServiceRequest.occurrenceTiming')") if err == nil && occurrenceResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, occurrenceResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, occurrenceResult.String()); err == nil { + s.Occurrence = &t + } else if t, err = time.Parse("2006-01-02", occurrenceResult.String()); err == nil { + s.Occurrence = &t + } else if t, err = time.Parse("2006-01", occurrenceResult.String()); err == nil { + s.Occurrence = &t + } else if t, err = time.Parse("2006", occurrenceResult.String()); err == nil { s.Occurrence = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", occurrenceResult.String()) - if err == nil { - s.Occurrence = &d - } } } // extracting Performer diff --git a/backend/pkg/models/database/fhir_slot.go b/backend/pkg/models/database/fhir_slot.go index 4d5701b6a..5d1d00863 100644 --- a/backend/pkg/models/database/fhir_slot.go +++ b/backend/pkg/models/database/fhir_slot.go @@ -142,14 +142,14 @@ func (s *FhirSlot) PopulateAndExtractSearchParameters(resourceRaw json.RawMessag // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile @@ -190,14 +190,14 @@ func (s *FhirSlot) PopulateAndExtractSearchParameters(resourceRaw json.RawMessag // extracting Start startResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'Slot.start')") if err == nil && startResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, startResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, startResult.String()); err == nil { + s.Start = &t + } else if t, err = time.Parse("2006-01-02", startResult.String()); err == nil { + s.Start = &t + } else if t, err = time.Parse("2006-01", startResult.String()); err == nil { + s.Start = &t + } else if t, err = time.Parse("2006", startResult.String()); err == nil { s.Start = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", startResult.String()) - if err == nil { - s.Start = &d - } } } // extracting Status diff --git a/backend/pkg/models/database/fhir_specimen.go b/backend/pkg/models/database/fhir_specimen.go index 992aca68b..8e9dc0c86 100644 --- a/backend/pkg/models/database/fhir_specimen.go +++ b/backend/pkg/models/database/fhir_specimen.go @@ -145,14 +145,14 @@ func (s *FhirSpecimen) PopulateAndExtractSearchParameters(resourceRaw json.RawMe // extracting Collected collectedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'Specimen.collection.collectedDateTime | Specimen.collection.collectedPeriod')") if err == nil && collectedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, collectedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, collectedResult.String()); err == nil { + s.Collected = &t + } else if t, err = time.Parse("2006-01-02", collectedResult.String()); err == nil { + s.Collected = &t + } else if t, err = time.Parse("2006-01", collectedResult.String()); err == nil { + s.Collected = &t + } else if t, err = time.Parse("2006", collectedResult.String()); err == nil { s.Collected = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", collectedResult.String()) - if err == nil { - s.Collected = &d - } } } // extracting Collector @@ -183,14 +183,14 @@ func (s *FhirSpecimen) PopulateAndExtractSearchParameters(resourceRaw json.RawMe // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/fhir_vision_prescription.go b/backend/pkg/models/database/fhir_vision_prescription.go index 902578eb6..2e3933368 100644 --- a/backend/pkg/models/database/fhir_vision_prescription.go +++ b/backend/pkg/models/database/fhir_vision_prescription.go @@ -163,14 +163,14 @@ func (s *FhirVisionPrescription) PopulateAndExtractSearchParameters(resourceRaw // extracting Datewritten datewrittenResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'VisionPrescription.dateWritten')") if err == nil && datewrittenResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, datewrittenResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, datewrittenResult.String()); err == nil { + s.Datewritten = &t + } else if t, err = time.Parse("2006-01-02", datewrittenResult.String()); err == nil { + s.Datewritten = &t + } else if t, err = time.Parse("2006-01", datewrittenResult.String()); err == nil { + s.Datewritten = &t + } else if t, err = time.Parse("2006", datewrittenResult.String()); err == nil { s.Datewritten = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", datewrittenResult.String()) - if err == nil { - s.Datewritten = &d - } } } // extracting Encounter @@ -191,14 +191,14 @@ func (s *FhirVisionPrescription) PopulateAndExtractSearchParameters(resourceRaw // extracting MetaLastUpdated metaLastUpdatedResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'meta.lastUpdated')") if err == nil && metaLastUpdatedResult.String() != "undefined" { - t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()) - if err == nil { + if t, err := time.Parse(time.RFC3339, metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01-02", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006-01", metaLastUpdatedResult.String()); err == nil { + s.MetaLastUpdated = &t + } else if t, err = time.Parse("2006", metaLastUpdatedResult.String()); err == nil { s.MetaLastUpdated = &t - } else if err != nil { - d, err := time.Parse("2006-01-02", metaLastUpdatedResult.String()) - if err == nil { - s.MetaLastUpdated = &d - } } } // extracting MetaProfile diff --git a/backend/pkg/models/database/generate.go b/backend/pkg/models/database/generate.go index 67593dd89..0e5dbad83 100644 --- a/backend/pkg/models/database/generate.go +++ b/backend/pkg/models/database/generate.go @@ -409,15 +409,27 @@ func main() { break case "date": //parse RFC3339 date - i.List(jen.Id("t"), jen.Id("err")).Op(":=").Qual("time", "Parse").Call(jen.Qual("time", "RFC3339"), jen.Id(fieldNameVar).Dot("String").Call()) - i.If(jen.Err().Op("==").Nil()).BlockFunc(func(e *jen.Group) { + + i.If( + jen.List(jen.Id("t"), jen.Err()).Op(":=").Qual("time", "Parse").Call(jen.Qual("time", "RFC3339"), jen.Id(fieldNameVar).Dot("String").Call()), + jen.Err().Op("==").Nil(), + ).BlockFunc(func(e *jen.Group) { + e.Id("s").Dot(fieldName).Op("=").Op("&").Id("t") + }).Else().If( + jen.List(jen.Id("t"), jen.Err()).Op("=").Qual("time", "Parse").Call(jen.Lit("2006-01-02"), jen.Id(fieldNameVar).Dot("String").Call()), + jen.Err().Op("==").Nil(), + ).BlockFunc(func(e *jen.Group) { + e.Id("s").Dot(fieldName).Op("=").Op("&").Id("t") + }).Else().If( + jen.List(jen.Id("t"), jen.Err()).Op("=").Qual("time", "Parse").Call(jen.Lit("2006-01"), jen.Id(fieldNameVar).Dot("String").Call()), + jen.Err().Op("==").Nil(), + ).BlockFunc(func(e *jen.Group) { + e.Id("s").Dot(fieldName).Op("=").Op("&").Id("t") + }).Else().If( + jen.List(jen.Id("t"), jen.Err()).Op("=").Qual("time", "Parse").Call(jen.Lit("2006"), jen.Id(fieldNameVar).Dot("String").Call()), + jen.Err().Op("==").Nil(), + ).BlockFunc(func(e *jen.Group) { e.Id("s").Dot(fieldName).Op("=").Op("&").Id("t") - }).Else().If(jen.Err().Op("!=").Nil()).BlockFunc(func(e *jen.Group) { - //parse date only - e.List(jen.Id("d"), jen.Id("err")).Op(":=").Qual("time", "Parse").Call(jen.Lit("2006-01-02"), jen.Id(fieldNameVar).Dot("String").Call()) - e.If(jen.Err().Op("==").Nil()).BlockFunc(func(f *jen.Group) { - f.Id("s").Dot(fieldName).Op("=").Op("&").Id("d") - }) }) case "uri": i.Id("s").Dot(fieldName).Op("=").Id(fieldNameVar).Dot("String").Call() From 4255fa64b2fc750011fad91c7d2fde43a5b4a68f Mon Sep 17 00:00:00 2001 From: Jason Kulatunga Date: Sat, 24 Feb 2024 17:12:14 -0800 Subject: [PATCH 16/29] removed the unnecessary/unused default "type" column. Correctly allowed the Type column defined in search-parameters.json to be available on multiple (5) resource types. --- backend/pkg/models/database/fhir_account.go | 11 +++- .../pkg/models/database/fhir_adverse_event.go | 4 -- .../database/fhir_allergy_intolerance.go | 20 +++++- .../database/fhir_allergy_intolerance_test.go | 65 ++++++++++++++----- .../pkg/models/database/fhir_appointment.go | 4 -- backend/pkg/models/database/fhir_binary.go | 4 -- backend/pkg/models/database/fhir_care_plan.go | 4 -- backend/pkg/models/database/fhir_care_team.go | 4 -- backend/pkg/models/database/fhir_claim.go | 4 -- .../models/database/fhir_claim_response.go | 4 -- .../pkg/models/database/fhir_composition.go | 20 +++++- backend/pkg/models/database/fhir_condition.go | 4 -- backend/pkg/models/database/fhir_consent.go | 4 -- backend/pkg/models/database/fhir_coverage.go | 11 +++- .../fhir_coverage_eligibility_request.go | 4 -- .../fhir_coverage_eligibility_response.go | 4 -- backend/pkg/models/database/fhir_device.go | 11 +++- .../models/database/fhir_device_request.go | 4 -- .../models/database/fhir_diagnostic_report.go | 4 -- .../models/database/fhir_document_manifest.go | 20 +++++- .../database/fhir_document_reference.go | 20 +++++- backend/pkg/models/database/fhir_encounter.go | 20 +++++- backend/pkg/models/database/fhir_endpoint.go | 4 -- .../database/fhir_enrollment_request.go | 4 -- .../database/fhir_enrollment_response.go | 4 -- .../database/fhir_explanation_of_benefit.go | 4 -- .../database/fhir_family_member_history.go | 4 -- backend/pkg/models/database/fhir_goal.go | 4 -- .../pkg/models/database/fhir_imaging_study.go | 4 -- .../pkg/models/database/fhir_immunization.go | 4 -- .../models/database/fhir_insurance_plan.go | 11 +++- backend/pkg/models/database/fhir_location.go | 11 +++- backend/pkg/models/database/fhir_media.go | 11 +++- .../pkg/models/database/fhir_medication.go | 4 -- .../fhir_medication_administration.go | 4 -- .../database/fhir_medication_dispense.go | 11 +++- .../database/fhir_medication_request.go | 4 -- .../database/fhir_medication_statement.go | 4 -- .../models/database/fhir_nutrition_order.go | 4 -- .../pkg/models/database/fhir_observation.go | 4 -- .../pkg/models/database/fhir_organization.go | 11 +++- .../database/fhir_organization_affiliation.go | 4 -- backend/pkg/models/database/fhir_patient.go | 4 -- backend/pkg/models/database/fhir_person.go | 4 -- .../pkg/models/database/fhir_practitioner.go | 4 -- .../models/database/fhir_practitioner_role.go | 4 -- backend/pkg/models/database/fhir_procedure.go | 4 -- .../pkg/models/database/fhir_provenance.go | 4 -- .../pkg/models/database/fhir_questionnaire.go | 4 -- .../database/fhir_questionnaire_response.go | 4 -- .../models/database/fhir_related_person.go | 4 -- backend/pkg/models/database/fhir_schedule.go | 4 -- .../models/database/fhir_service_request.go | 4 -- backend/pkg/models/database/fhir_slot.go | 4 -- backend/pkg/models/database/fhir_specimen.go | 11 +++- .../database/fhir_vision_prescription.go | 4 -- backend/pkg/models/database/generate.go | 4 -- backend/pkg/models/database/interface.go | 4 ++ 58 files changed, 209 insertions(+), 227 deletions(-) diff --git a/backend/pkg/models/database/fhir_account.go b/backend/pkg/models/database/fhir_account.go index 83f8e3c49..473d0eb91 100644 --- a/backend/pkg/models/database/fhir_account.go +++ b/backend/pkg/models/database/fhir_account.go @@ -50,8 +50,8 @@ type FhirAccount struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special + // E.g. patient, expense, depreciation + // https://hl7.org/fhir/r4/search.html#token Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } @@ -75,7 +75,7 @@ func (s *FhirAccount) GetSearchParameters() map[string]string { "status": "token", "subject": "reference", "text": "keyword", - "type": "special", + "type": "token", } return searchParameters } @@ -192,6 +192,11 @@ func (s *FhirAccount) PopulateAndExtractSearchParameters(resourceRaw json.RawMes if err == nil && textResult.String() != "undefined" { s.Text = textResult.String() } + // extracting Type + typeResult, err := vm.RunString("extractTokenSearchParameters(fhirResource, 'Account.type')") + if err == nil && typeResult.String() != "undefined" { + s.Type = []byte(typeResult.String()) + } return nil } diff --git a/backend/pkg/models/database/fhir_adverse_event.go b/backend/pkg/models/database/fhir_adverse_event.go index 407f332d3..426b09b89 100644 --- a/backend/pkg/models/database/fhir_adverse_event.go +++ b/backend/pkg/models/database/fhir_adverse_event.go @@ -68,9 +68,6 @@ type FhirAdverseEvent struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } func (s *FhirAdverseEvent) GetSearchParameters() map[string]string { @@ -99,7 +96,6 @@ func (s *FhirAdverseEvent) GetSearchParameters() map[string]string { "subject": "reference", "substance": "reference", "text": "keyword", - "type": "special", } return searchParameters } diff --git a/backend/pkg/models/database/fhir_allergy_intolerance.go b/backend/pkg/models/database/fhir_allergy_intolerance.go index 58915282e..cec522d38 100644 --- a/backend/pkg/models/database/fhir_allergy_intolerance.go +++ b/backend/pkg/models/database/fhir_allergy_intolerance.go @@ -141,8 +141,17 @@ type FhirAllergyIntolerance struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special + /* + Multiple Resources: + + * [AllergyIntolerance](allergyintolerance.html): allergy | intolerance - Underlying mechanism (if known) + * [Composition](composition.html): Kind of composition (LOINC if possible) + * [DocumentManifest](documentmanifest.html): Kind of document set + * [DocumentReference](documentreference.html): Kind of document (LOINC if possible) + * [Encounter](encounter.html): Specific type of encounter + * [EpisodeOfCare](episodeofcare.html): Type/class - e.g. specialist referral, disease management + */ + // https://hl7.org/fhir/r4/search.html#token Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` // unconfirmed | confirmed | refuted | entered-in-error // https://hl7.org/fhir/r4/search.html#token @@ -176,7 +185,7 @@ func (s *FhirAllergyIntolerance) GetSearchParameters() map[string]string { "source_resource_type": "keyword", "source_uri": "keyword", "text": "keyword", - "type": "special", + "type": "token", "verificationStatus": "token", } return searchParameters @@ -345,6 +354,11 @@ func (s *FhirAllergyIntolerance) PopulateAndExtractSearchParameters(resourceRaw if err == nil && textResult.String() != "undefined" { s.Text = textResult.String() } + // extracting Type + typeResult, err := vm.RunString("extractTokenSearchParameters(fhirResource, 'AllergyIntolerance.type | Composition.type | DocumentManifest.type | DocumentReference.type | Encounter.type | EpisodeOfCare.type')") + if err == nil && typeResult.String() != "undefined" { + s.Type = []byte(typeResult.String()) + } // extracting VerificationStatus verificationStatusResult, err := vm.RunString("extractTokenSearchParameters(fhirResource, 'AllergyIntolerance.verificationStatus')") if err == nil && verificationStatusResult.String() != "undefined" { diff --git a/backend/pkg/models/database/fhir_allergy_intolerance_test.go b/backend/pkg/models/database/fhir_allergy_intolerance_test.go index a764dd67c..584ba2588 100644 --- a/backend/pkg/models/database/fhir_allergy_intolerance_test.go +++ b/backend/pkg/models/database/fhir_allergy_intolerance_test.go @@ -47,8 +47,17 @@ func TestFhirAllergyIntolerance_ExtractSearchParameters(t *testing.T) { }, }, testVerificationStatus) - //TODO: Special field, ignoring - //require.Equal(t, "allergy", allergyIntoleranceModel.Type) + require.NotEmpty(t, allergyIntoleranceModel.Type) + + var testType SearchParameterTokenType + require.NoError(t, err) + err = json.Unmarshal(json.RawMessage(allergyIntoleranceModel.Type), &testType) + require.NoError(t, err) + require.Equal(t, SearchParameterTokenType{ + { + Code: "allergy", + }, + }, testType) var testCategory SearchParameterTokenType require.NoError(t, err) @@ -87,21 +96,28 @@ func TestFhirAllergyIntolerance_ExtractSearchParameters(t *testing.T) { }, }, testCodeSystem) - //var testPatient SearchParameterTokenType - //require.NoError(t, err) - //err = json.Unmarshal(json.RawMessage(allergyIntoleranceModel.Code), &testCodeSystem) - //require.NoError(t, err) - //require.Equal(t, SearchParameterTokenType{ - // { - // Code: "39065001", - // System: "http://snomed.info/sct", - // Text: "Burn of ear", - // }, - //}, testCodeSystem) - require.Equal(t, "2012-06-12T00:00:00Z", allergyIntoleranceModel.Onset.Format(time.RFC3339)) - //TODO: require.Equal(t, "2004", allergyIntoleranceModel.Recorder) - //require.Equal(t, "2004", allergyIntoleranceModel.Asserter) + + var testRecorder SearchParameterReferenceType + require.NoError(t, err) + err = json.Unmarshal(json.RawMessage(allergyIntoleranceModel.Recorder), &testRecorder) + require.NoError(t, err) + require.Equal(t, SearchParameterReferenceType{ + { + Reference: "Practitioner/example", + }, + }, testRecorder) + + var testAsserter SearchParameterReferenceType + require.NoError(t, err) + err = json.Unmarshal(json.RawMessage(allergyIntoleranceModel.Asserter), &testAsserter) + require.NoError(t, err) + require.Equal(t, SearchParameterReferenceType{ + { + Reference: "Patient/example", + }, + }, testAsserter) + require.Equal(t, "2012-06", allergyIntoleranceModel.LastDate.Format("2006-01")) var testSeverity SearchParameterTokenType @@ -117,7 +133,22 @@ func TestFhirAllergyIntolerance_ExtractSearchParameters(t *testing.T) { }, }, testSeverity) - //TODO: Manifestation + var testManifestation SearchParameterTokenType + require.NoError(t, err) + err = json.Unmarshal(json.RawMessage(allergyIntoleranceModel.Manifestation), &testManifestation) + require.NoError(t, err) + require.Equal(t, SearchParameterTokenType{ + { + System: "http://snomed.info/sct", + Code: "39579001", + Text: "Anaphylactic reaction", + }, + { + System: "http://snomed.info/sct", + Code: "64305001", + Text: "Urticaria", + }, + }, testManifestation) } //func TestFhirAllergyIntolerance2_ExtractSearchParameters(t *testing.T) { diff --git a/backend/pkg/models/database/fhir_appointment.go b/backend/pkg/models/database/fhir_appointment.go index 27428bcea..c832a0f86 100644 --- a/backend/pkg/models/database/fhir_appointment.go +++ b/backend/pkg/models/database/fhir_appointment.go @@ -80,9 +80,6 @@ type FhirAppointment struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } func (s *FhirAppointment) GetSearchParameters() map[string]string { @@ -115,7 +112,6 @@ func (s *FhirAppointment) GetSearchParameters() map[string]string { "status": "token", "supportingInfo": "reference", "text": "keyword", - "type": "special", } return searchParameters } diff --git a/backend/pkg/models/database/fhir_binary.go b/backend/pkg/models/database/fhir_binary.go index 4c90594b9..16ec0da03 100644 --- a/backend/pkg/models/database/fhir_binary.go +++ b/backend/pkg/models/database/fhir_binary.go @@ -32,9 +32,6 @@ type FhirBinary struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } func (s *FhirBinary) GetSearchParameters() map[string]string { @@ -51,7 +48,6 @@ func (s *FhirBinary) GetSearchParameters() map[string]string { "source_resource_type": "keyword", "source_uri": "keyword", "text": "keyword", - "type": "special", } return searchParameters } diff --git a/backend/pkg/models/database/fhir_care_plan.go b/backend/pkg/models/database/fhir_care_plan.go index f7b328b75..bca545e51 100644 --- a/backend/pkg/models/database/fhir_care_plan.go +++ b/backend/pkg/models/database/fhir_care_plan.go @@ -142,9 +142,6 @@ type FhirCarePlan struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } func (s *FhirCarePlan) GetSearchParameters() map[string]string { @@ -180,7 +177,6 @@ func (s *FhirCarePlan) GetSearchParameters() map[string]string { "status": "token", "subject": "reference", "text": "keyword", - "type": "special", } return searchParameters } diff --git a/backend/pkg/models/database/fhir_care_team.go b/backend/pkg/models/database/fhir_care_team.go index 4f6500fec..4c0808f92 100644 --- a/backend/pkg/models/database/fhir_care_team.go +++ b/backend/pkg/models/database/fhir_care_team.go @@ -106,9 +106,6 @@ type FhirCareTeam struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } func (s *FhirCareTeam) GetSearchParameters() map[string]string { @@ -132,7 +129,6 @@ func (s *FhirCareTeam) GetSearchParameters() map[string]string { "status": "token", "subject": "reference", "text": "keyword", - "type": "special", } return searchParameters } diff --git a/backend/pkg/models/database/fhir_claim.go b/backend/pkg/models/database/fhir_claim.go index fbcfd7441..4e931816f 100644 --- a/backend/pkg/models/database/fhir_claim.go +++ b/backend/pkg/models/database/fhir_claim.go @@ -77,9 +77,6 @@ type FhirClaim struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` // The kind of financial resource // https://hl7.org/fhir/r4/search.html#token Use datatypes.JSON `gorm:"column:use;type:text;serializer:json" json:"use,omitempty"` @@ -114,7 +111,6 @@ func (s *FhirClaim) GetSearchParameters() map[string]string { "status": "token", "subdetailUdi": "reference", "text": "keyword", - "type": "special", "use": "token", } return searchParameters diff --git a/backend/pkg/models/database/fhir_claim_response.go b/backend/pkg/models/database/fhir_claim_response.go index 74bc2dc39..b43ba8826 100644 --- a/backend/pkg/models/database/fhir_claim_response.go +++ b/backend/pkg/models/database/fhir_claim_response.go @@ -59,9 +59,6 @@ type FhirClaimResponse struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` // The type of claim // https://hl7.org/fhir/r4/search.html#token Use datatypes.JSON `gorm:"column:use;type:text;serializer:json" json:"use,omitempty"` @@ -90,7 +87,6 @@ func (s *FhirClaimResponse) GetSearchParameters() map[string]string { "source_uri": "keyword", "status": "token", "text": "keyword", - "type": "special", "use": "token", } return searchParameters diff --git a/backend/pkg/models/database/fhir_composition.go b/backend/pkg/models/database/fhir_composition.go index 70d1ec5e4..9983f162b 100644 --- a/backend/pkg/models/database/fhir_composition.go +++ b/backend/pkg/models/database/fhir_composition.go @@ -148,8 +148,17 @@ type FhirComposition struct { // Human Readable name/title // https://hl7.org/fhir/r4/search.html#string Title datatypes.JSON `gorm:"column:title;type:text;serializer:json" json:"title,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special + /* + Multiple Resources: + + * [AllergyIntolerance](allergyintolerance.html): allergy | intolerance - Underlying mechanism (if known) + * [Composition](composition.html): Kind of composition (LOINC if possible) + * [DocumentManifest](documentmanifest.html): Kind of document set + * [DocumentReference](documentreference.html): Kind of document (LOINC if possible) + * [Encounter](encounter.html): Specific type of encounter + * [EpisodeOfCare](episodeofcare.html): Type/class - e.g. specialist referral, disease management + */ + // https://hl7.org/fhir/r4/search.html#token Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } @@ -183,7 +192,7 @@ func (s *FhirComposition) GetSearchParameters() map[string]string { "subject": "reference", "text": "keyword", "title": "string", - "type": "special", + "type": "token", } return searchParameters } @@ -358,6 +367,11 @@ func (s *FhirComposition) PopulateAndExtractSearchParameters(resourceRaw json.Ra if err == nil && titleResult.String() != "undefined" { s.Title = []byte(titleResult.String()) } + // extracting Type + typeResult, err := vm.RunString("extractTokenSearchParameters(fhirResource, 'AllergyIntolerance.type | Composition.type | DocumentManifest.type | DocumentReference.type | Encounter.type | EpisodeOfCare.type')") + if err == nil && typeResult.String() != "undefined" { + s.Type = []byte(typeResult.String()) + } return nil } diff --git a/backend/pkg/models/database/fhir_condition.go b/backend/pkg/models/database/fhir_condition.go index 14e769df3..622659ce0 100644 --- a/backend/pkg/models/database/fhir_condition.go +++ b/backend/pkg/models/database/fhir_condition.go @@ -139,9 +139,6 @@ type FhirCondition struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` // unconfirmed | provisional | differential | confirmed | refuted | entered-in-error // https://hl7.org/fhir/r4/search.html#token VerificationStatus datatypes.JSON `gorm:"column:verificationStatus;type:text;serializer:json" json:"verificationStatus,omitempty"` @@ -180,7 +177,6 @@ func (s *FhirCondition) GetSearchParameters() map[string]string { "stage": "token", "subject": "reference", "text": "keyword", - "type": "special", "verificationStatus": "token", } return searchParameters diff --git a/backend/pkg/models/database/fhir_consent.go b/backend/pkg/models/database/fhir_consent.go index 70cda6d26..e08abcfc2 100644 --- a/backend/pkg/models/database/fhir_consent.go +++ b/backend/pkg/models/database/fhir_consent.go @@ -127,9 +127,6 @@ type FhirConsent struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } func (s *FhirConsent) GetSearchParameters() map[string]string { @@ -160,7 +157,6 @@ func (s *FhirConsent) GetSearchParameters() map[string]string { "source_uri": "keyword", "status": "token", "text": "keyword", - "type": "special", } return searchParameters } diff --git a/backend/pkg/models/database/fhir_coverage.go b/backend/pkg/models/database/fhir_coverage.go index 650ebf4f6..c5d8900cd 100644 --- a/backend/pkg/models/database/fhir_coverage.go +++ b/backend/pkg/models/database/fhir_coverage.go @@ -59,8 +59,8 @@ type FhirCoverage struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special + // The kind of coverage (health plan, auto, Workers Compensation) + // https://hl7.org/fhir/r4/search.html#token Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } @@ -87,7 +87,7 @@ func (s *FhirCoverage) GetSearchParameters() map[string]string { "status": "token", "subscriber": "reference", "text": "keyword", - "type": "special", + "type": "token", } return searchParameters } @@ -211,6 +211,11 @@ func (s *FhirCoverage) PopulateAndExtractSearchParameters(resourceRaw json.RawMe if err == nil && textResult.String() != "undefined" { s.Text = textResult.String() } + // extracting Type + typeResult, err := vm.RunString("extractTokenSearchParameters(fhirResource, 'Coverage.type')") + if err == nil && typeResult.String() != "undefined" { + s.Type = []byte(typeResult.String()) + } return nil } diff --git a/backend/pkg/models/database/fhir_coverage_eligibility_request.go b/backend/pkg/models/database/fhir_coverage_eligibility_request.go index 3f15963bb..de1f4d707 100644 --- a/backend/pkg/models/database/fhir_coverage_eligibility_request.go +++ b/backend/pkg/models/database/fhir_coverage_eligibility_request.go @@ -50,9 +50,6 @@ type FhirCoverageEligibilityRequest struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } func (s *FhirCoverageEligibilityRequest) GetSearchParameters() map[string]string { @@ -75,7 +72,6 @@ func (s *FhirCoverageEligibilityRequest) GetSearchParameters() map[string]string "source_uri": "keyword", "status": "token", "text": "keyword", - "type": "special", } return searchParameters } diff --git a/backend/pkg/models/database/fhir_coverage_eligibility_response.go b/backend/pkg/models/database/fhir_coverage_eligibility_response.go index fa98c74b1..fe8b650b8 100644 --- a/backend/pkg/models/database/fhir_coverage_eligibility_response.go +++ b/backend/pkg/models/database/fhir_coverage_eligibility_response.go @@ -56,9 +56,6 @@ type FhirCoverageEligibilityResponse struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } func (s *FhirCoverageEligibilityResponse) GetSearchParameters() map[string]string { @@ -83,7 +80,6 @@ func (s *FhirCoverageEligibilityResponse) GetSearchParameters() map[string]strin "source_uri": "keyword", "status": "token", "text": "keyword", - "type": "special", } return searchParameters } diff --git a/backend/pkg/models/database/fhir_device.go b/backend/pkg/models/database/fhir_device.go index 5d3eb49a3..11bc48d08 100644 --- a/backend/pkg/models/database/fhir_device.go +++ b/backend/pkg/models/database/fhir_device.go @@ -53,8 +53,8 @@ type FhirDevice struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special + // The type of the device + // https://hl7.org/fhir/r4/search.html#token Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` // UDI Barcode (RFID or other technology) string in *HRF* format. // https://hl7.org/fhir/r4/search.html#string @@ -88,7 +88,7 @@ func (s *FhirDevice) GetSearchParameters() map[string]string { "source_uri": "keyword", "status": "token", "text": "keyword", - "type": "special", + "type": "token", "udiCarrier": "string", "udiDi": "string", "url": "uri", @@ -205,6 +205,11 @@ func (s *FhirDevice) PopulateAndExtractSearchParameters(resourceRaw json.RawMess if err == nil && textResult.String() != "undefined" { s.Text = textResult.String() } + // extracting Type + typeResult, err := vm.RunString("extractTokenSearchParameters(fhirResource, 'Device.type')") + if err == nil && typeResult.String() != "undefined" { + s.Type = []byte(typeResult.String()) + } // extracting UdiCarrier udiCarrierResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'Device.udiCarrier.carrierHRF')") if err == nil && udiCarrierResult.String() != "undefined" { diff --git a/backend/pkg/models/database/fhir_device_request.go b/backend/pkg/models/database/fhir_device_request.go index 2106d5af0..201aff511 100644 --- a/backend/pkg/models/database/fhir_device_request.go +++ b/backend/pkg/models/database/fhir_device_request.go @@ -148,9 +148,6 @@ type FhirDeviceRequest struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } func (s *FhirDeviceRequest) GetSearchParameters() map[string]string { @@ -184,7 +181,6 @@ func (s *FhirDeviceRequest) GetSearchParameters() map[string]string { "status": "token", "subject": "reference", "text": "keyword", - "type": "special", } return searchParameters } diff --git a/backend/pkg/models/database/fhir_diagnostic_report.go b/backend/pkg/models/database/fhir_diagnostic_report.go index a5ec9581e..752164cd8 100644 --- a/backend/pkg/models/database/fhir_diagnostic_report.go +++ b/backend/pkg/models/database/fhir_diagnostic_report.go @@ -162,9 +162,6 @@ type FhirDiagnosticReport struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } func (s *FhirDiagnosticReport) GetSearchParameters() map[string]string { @@ -196,7 +193,6 @@ func (s *FhirDiagnosticReport) GetSearchParameters() map[string]string { "status": "token", "subject": "reference", "text": "keyword", - "type": "special", } return searchParameters } diff --git a/backend/pkg/models/database/fhir_document_manifest.go b/backend/pkg/models/database/fhir_document_manifest.go index e8b2a3743..e9d8f88e0 100644 --- a/backend/pkg/models/database/fhir_document_manifest.go +++ b/backend/pkg/models/database/fhir_document_manifest.go @@ -98,8 +98,17 @@ type FhirDocumentManifest struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special + /* + Multiple Resources: + + * [AllergyIntolerance](allergyintolerance.html): allergy | intolerance - Underlying mechanism (if known) + * [Composition](composition.html): Kind of composition (LOINC if possible) + * [DocumentManifest](documentmanifest.html): Kind of document set + * [DocumentReference](documentreference.html): Kind of document (LOINC if possible) + * [Encounter](encounter.html): Specific type of encounter + * [EpisodeOfCare](episodeofcare.html): Type/class - e.g. specialist referral, disease management + */ + // https://hl7.org/fhir/r4/search.html#token Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } @@ -128,7 +137,7 @@ func (s *FhirDocumentManifest) GetSearchParameters() map[string]string { "status": "token", "subject": "reference", "text": "keyword", - "type": "special", + "type": "token", } return searchParameters } @@ -270,6 +279,11 @@ func (s *FhirDocumentManifest) PopulateAndExtractSearchParameters(resourceRaw js if err == nil && textResult.String() != "undefined" { s.Text = textResult.String() } + // extracting Type + typeResult, err := vm.RunString("extractTokenSearchParameters(fhirResource, 'AllergyIntolerance.type | Composition.type | DocumentManifest.type | DocumentReference.type | Encounter.type | EpisodeOfCare.type')") + if err == nil && typeResult.String() != "undefined" { + s.Type = []byte(typeResult.String()) + } return nil } diff --git a/backend/pkg/models/database/fhir_document_reference.go b/backend/pkg/models/database/fhir_document_reference.go index a33706a01..71dbe37a4 100644 --- a/backend/pkg/models/database/fhir_document_reference.go +++ b/backend/pkg/models/database/fhir_document_reference.go @@ -143,8 +143,17 @@ type FhirDocumentReference struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special + /* + Multiple Resources: + + * [AllergyIntolerance](allergyintolerance.html): allergy | intolerance - Underlying mechanism (if known) + * [Composition](composition.html): Kind of composition (LOINC if possible) + * [DocumentManifest](documentmanifest.html): Kind of document set + * [DocumentReference](documentreference.html): Kind of document (LOINC if possible) + * [Encounter](encounter.html): Specific type of encounter + * [EpisodeOfCare](episodeofcare.html): Type/class - e.g. specialist referral, disease management + */ + // https://hl7.org/fhir/r4/search.html#token Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } @@ -183,7 +192,7 @@ func (s *FhirDocumentReference) GetSearchParameters() map[string]string { "status": "token", "subject": "reference", "text": "keyword", - "type": "special", + "type": "token", } return searchParameters } @@ -383,6 +392,11 @@ func (s *FhirDocumentReference) PopulateAndExtractSearchParameters(resourceRaw j if err == nil && textResult.String() != "undefined" { s.Text = textResult.String() } + // extracting Type + typeResult, err := vm.RunString("extractTokenSearchParameters(fhirResource, 'AllergyIntolerance.type | Composition.type | DocumentManifest.type | DocumentReference.type | Encounter.type | EpisodeOfCare.type')") + if err == nil && typeResult.String() != "undefined" { + s.Type = []byte(typeResult.String()) + } return nil } diff --git a/backend/pkg/models/database/fhir_encounter.go b/backend/pkg/models/database/fhir_encounter.go index 811654baf..defe56baa 100644 --- a/backend/pkg/models/database/fhir_encounter.go +++ b/backend/pkg/models/database/fhir_encounter.go @@ -148,8 +148,17 @@ type FhirEncounter struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special + /* + Multiple Resources: + + * [AllergyIntolerance](allergyintolerance.html): allergy | intolerance - Underlying mechanism (if known) + * [Composition](composition.html): Kind of composition (LOINC if possible) + * [DocumentManifest](documentmanifest.html): Kind of document set + * [DocumentReference](documentreference.html): Kind of document (LOINC if possible) + * [Encounter](encounter.html): Specific type of encounter + * [EpisodeOfCare](episodeofcare.html): Type/class - e.g. specialist referral, disease management + */ + // https://hl7.org/fhir/r4/search.html#token Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } @@ -188,7 +197,7 @@ func (s *FhirEncounter) GetSearchParameters() map[string]string { "status": "token", "subject": "reference", "text": "keyword", - "type": "special", + "type": "token", } return searchParameters } @@ -388,6 +397,11 @@ func (s *FhirEncounter) PopulateAndExtractSearchParameters(resourceRaw json.RawM if err == nil && textResult.String() != "undefined" { s.Text = textResult.String() } + // extracting Type + typeResult, err := vm.RunString("extractTokenSearchParameters(fhirResource, 'AllergyIntolerance.type | Composition.type | DocumentManifest.type | DocumentReference.type | Encounter.type | EpisodeOfCare.type')") + if err == nil && typeResult.String() != "undefined" { + s.Type = []byte(typeResult.String()) + } return nil } diff --git a/backend/pkg/models/database/fhir_endpoint.go b/backend/pkg/models/database/fhir_endpoint.go index c9bcb3420..644622460 100644 --- a/backend/pkg/models/database/fhir_endpoint.go +++ b/backend/pkg/models/database/fhir_endpoint.go @@ -50,9 +50,6 @@ type FhirEndpoint struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } func (s *FhirEndpoint) GetSearchParameters() map[string]string { @@ -75,7 +72,6 @@ func (s *FhirEndpoint) GetSearchParameters() map[string]string { "source_uri": "keyword", "status": "token", "text": "keyword", - "type": "special", } return searchParameters } diff --git a/backend/pkg/models/database/fhir_enrollment_request.go b/backend/pkg/models/database/fhir_enrollment_request.go index e8f327599..7bbe82b10 100644 --- a/backend/pkg/models/database/fhir_enrollment_request.go +++ b/backend/pkg/models/database/fhir_enrollment_request.go @@ -41,9 +41,6 @@ type FhirEnrollmentRequest struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } func (s *FhirEnrollmentRequest) GetSearchParameters() map[string]string { @@ -63,7 +60,6 @@ func (s *FhirEnrollmentRequest) GetSearchParameters() map[string]string { "status": "token", "subject": "reference", "text": "keyword", - "type": "special", } return searchParameters } diff --git a/backend/pkg/models/database/fhir_enrollment_response.go b/backend/pkg/models/database/fhir_enrollment_response.go index d3d9528a9..7259b6db2 100644 --- a/backend/pkg/models/database/fhir_enrollment_response.go +++ b/backend/pkg/models/database/fhir_enrollment_response.go @@ -41,9 +41,6 @@ type FhirEnrollmentResponse struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } func (s *FhirEnrollmentResponse) GetSearchParameters() map[string]string { @@ -63,7 +60,6 @@ func (s *FhirEnrollmentResponse) GetSearchParameters() map[string]string { "source_uri": "keyword", "status": "token", "text": "keyword", - "type": "special", } return searchParameters } diff --git a/backend/pkg/models/database/fhir_explanation_of_benefit.go b/backend/pkg/models/database/fhir_explanation_of_benefit.go index 237dc6f58..ed95a2f8b 100644 --- a/backend/pkg/models/database/fhir_explanation_of_benefit.go +++ b/backend/pkg/models/database/fhir_explanation_of_benefit.go @@ -80,9 +80,6 @@ type FhirExplanationOfBenefit struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } func (s *FhirExplanationOfBenefit) GetSearchParameters() map[string]string { @@ -115,7 +112,6 @@ func (s *FhirExplanationOfBenefit) GetSearchParameters() map[string]string { "status": "token", "subdetailUdi": "reference", "text": "keyword", - "type": "special", } return searchParameters } diff --git a/backend/pkg/models/database/fhir_family_member_history.go b/backend/pkg/models/database/fhir_family_member_history.go index 562282219..3e70eea76 100644 --- a/backend/pkg/models/database/fhir_family_member_history.go +++ b/backend/pkg/models/database/fhir_family_member_history.go @@ -126,9 +126,6 @@ type FhirFamilyMemberHistory struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } func (s *FhirFamilyMemberHistory) GetSearchParameters() map[string]string { @@ -153,7 +150,6 @@ func (s *FhirFamilyMemberHistory) GetSearchParameters() map[string]string { "source_uri": "keyword", "status": "token", "text": "keyword", - "type": "special", } return searchParameters } diff --git a/backend/pkg/models/database/fhir_goal.go b/backend/pkg/models/database/fhir_goal.go index 48003bd26..cc7f3f2a9 100644 --- a/backend/pkg/models/database/fhir_goal.go +++ b/backend/pkg/models/database/fhir_goal.go @@ -86,9 +86,6 @@ type FhirGoal struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } func (s *FhirGoal) GetSearchParameters() map[string]string { @@ -112,7 +109,6 @@ func (s *FhirGoal) GetSearchParameters() map[string]string { "subject": "reference", "targetDate": "date", "text": "keyword", - "type": "special", } return searchParameters } diff --git a/backend/pkg/models/database/fhir_imaging_study.go b/backend/pkg/models/database/fhir_imaging_study.go index 5703b85d4..9e264afe1 100644 --- a/backend/pkg/models/database/fhir_imaging_study.go +++ b/backend/pkg/models/database/fhir_imaging_study.go @@ -113,9 +113,6 @@ type FhirImagingStudy struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } func (s *FhirImagingStudy) GetSearchParameters() map[string]string { @@ -148,7 +145,6 @@ func (s *FhirImagingStudy) GetSearchParameters() map[string]string { "status": "token", "subject": "reference", "text": "keyword", - "type": "special", } return searchParameters } diff --git a/backend/pkg/models/database/fhir_immunization.go b/backend/pkg/models/database/fhir_immunization.go index 2474785e9..75dff0dd7 100644 --- a/backend/pkg/models/database/fhir_immunization.go +++ b/backend/pkg/models/database/fhir_immunization.go @@ -127,9 +127,6 @@ type FhirImmunization struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` // Vaccine Product Administered // https://hl7.org/fhir/r4/search.html#token VaccineCode datatypes.JSON `gorm:"column:vaccineCode;type:text;serializer:json" json:"vaccineCode,omitempty"` @@ -163,7 +160,6 @@ func (s *FhirImmunization) GetSearchParameters() map[string]string { "statusReason": "token", "targetDisease": "token", "text": "keyword", - "type": "special", "vaccineCode": "token", } return searchParameters diff --git a/backend/pkg/models/database/fhir_insurance_plan.go b/backend/pkg/models/database/fhir_insurance_plan.go index a36732728..99bd28d51 100644 --- a/backend/pkg/models/database/fhir_insurance_plan.go +++ b/backend/pkg/models/database/fhir_insurance_plan.go @@ -71,8 +71,8 @@ type FhirInsurancePlan struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special + // A code for the type of organization + // https://hl7.org/fhir/r4/search.html#token Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } @@ -103,7 +103,7 @@ func (s *FhirInsurancePlan) GetSearchParameters() map[string]string { "source_uri": "keyword", "status": "token", "text": "keyword", - "type": "special", + "type": "token", } return searchParameters } @@ -247,6 +247,11 @@ func (s *FhirInsurancePlan) PopulateAndExtractSearchParameters(resourceRaw json. if err == nil && textResult.String() != "undefined" { s.Text = textResult.String() } + // extracting Type + typeResult, err := vm.RunString("extractTokenSearchParameters(fhirResource, 'InsurancePlan.type')") + if err == nil && typeResult.String() != "undefined" { + s.Type = []byte(typeResult.String()) + } return nil } diff --git a/backend/pkg/models/database/fhir_location.go b/backend/pkg/models/database/fhir_location.go index 66cc2c0df..09c747d15 100644 --- a/backend/pkg/models/database/fhir_location.go +++ b/backend/pkg/models/database/fhir_location.go @@ -71,8 +71,8 @@ type FhirLocation struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special + // A code for the type of location + // https://hl7.org/fhir/r4/search.html#token Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } @@ -103,7 +103,7 @@ func (s *FhirLocation) GetSearchParameters() map[string]string { "source_uri": "keyword", "status": "token", "text": "keyword", - "type": "special", + "type": "token", } return searchParameters } @@ -247,6 +247,11 @@ func (s *FhirLocation) PopulateAndExtractSearchParameters(resourceRaw json.RawMe if err == nil && textResult.String() != "undefined" { s.Text = textResult.String() } + // extracting Type + typeResult, err := vm.RunString("extractTokenSearchParameters(fhirResource, 'Location.type')") + if err == nil && typeResult.String() != "undefined" { + s.Type = []byte(typeResult.String()) + } return nil } diff --git a/backend/pkg/models/database/fhir_media.go b/backend/pkg/models/database/fhir_media.go index 64df835a4..710fffde7 100644 --- a/backend/pkg/models/database/fhir_media.go +++ b/backend/pkg/models/database/fhir_media.go @@ -62,8 +62,8 @@ type FhirMedia struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special + // Classification of media as image, video, or audio + // https://hl7.org/fhir/r4/search.html#token Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` // Imaging view, e.g. Lateral or Antero-posterior // https://hl7.org/fhir/r4/search.html#token @@ -94,7 +94,7 @@ func (s *FhirMedia) GetSearchParameters() map[string]string { "status": "token", "subject": "reference", "text": "keyword", - "type": "special", + "type": "token", "view": "token", } return searchParameters @@ -232,6 +232,11 @@ func (s *FhirMedia) PopulateAndExtractSearchParameters(resourceRaw json.RawMessa if err == nil && textResult.String() != "undefined" { s.Text = textResult.String() } + // extracting Type + typeResult, err := vm.RunString("extractTokenSearchParameters(fhirResource, 'Media.type')") + if err == nil && typeResult.String() != "undefined" { + s.Type = []byte(typeResult.String()) + } // extracting View viewResult, err := vm.RunString("extractTokenSearchParameters(fhirResource, 'Media.view')") if err == nil && viewResult.String() != "undefined" { diff --git a/backend/pkg/models/database/fhir_medication.go b/backend/pkg/models/database/fhir_medication.go index e035aa04b..8df00a328 100644 --- a/backend/pkg/models/database/fhir_medication.go +++ b/backend/pkg/models/database/fhir_medication.go @@ -76,9 +76,6 @@ type FhirMedication struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } func (s *FhirMedication) GetSearchParameters() map[string]string { @@ -104,7 +101,6 @@ func (s *FhirMedication) GetSearchParameters() map[string]string { "source_uri": "keyword", "status": "token", "text": "keyword", - "type": "special", } return searchParameters } diff --git a/backend/pkg/models/database/fhir_medication_administration.go b/backend/pkg/models/database/fhir_medication_administration.go index 198781b9c..2e7e77ead 100644 --- a/backend/pkg/models/database/fhir_medication_administration.go +++ b/backend/pkg/models/database/fhir_medication_administration.go @@ -132,9 +132,6 @@ type FhirMedicationAdministration struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } func (s *FhirMedicationAdministration) GetSearchParameters() map[string]string { @@ -163,7 +160,6 @@ func (s *FhirMedicationAdministration) GetSearchParameters() map[string]string { "status": "token", "subject": "reference", "text": "keyword", - "type": "special", } return searchParameters } diff --git a/backend/pkg/models/database/fhir_medication_dispense.go b/backend/pkg/models/database/fhir_medication_dispense.go index f18d881bd..7b51a08b2 100644 --- a/backend/pkg/models/database/fhir_medication_dispense.go +++ b/backend/pkg/models/database/fhir_medication_dispense.go @@ -133,8 +133,8 @@ type FhirMedicationDispense struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special + // Returns dispenses of a specific type + // https://hl7.org/fhir/r4/search.html#token Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` // Returns dispenses handed over on this date // https://hl7.org/fhir/r4/search.html#date @@ -169,7 +169,7 @@ func (s *FhirMedicationDispense) GetSearchParameters() map[string]string { "status": "token", "subject": "reference", "text": "keyword", - "type": "special", + "type": "token", "whenhandedover": "date", "whenprepared": "date", } @@ -305,6 +305,11 @@ func (s *FhirMedicationDispense) PopulateAndExtractSearchParameters(resourceRaw if err == nil && textResult.String() != "undefined" { s.Text = textResult.String() } + // extracting Type + typeResult, err := vm.RunString("extractTokenSearchParameters(fhirResource, 'MedicationDispense.type')") + if err == nil && typeResult.String() != "undefined" { + s.Type = []byte(typeResult.String()) + } // extracting Whenhandedover whenhandedoverResult, err := vm.RunString("extractDateSearchParameters(fhirResource, 'MedicationDispense.whenHandedOver')") if err == nil && whenhandedoverResult.String() != "undefined" { diff --git a/backend/pkg/models/database/fhir_medication_request.go b/backend/pkg/models/database/fhir_medication_request.go index 867093c83..79f33c570 100644 --- a/backend/pkg/models/database/fhir_medication_request.go +++ b/backend/pkg/models/database/fhir_medication_request.go @@ -149,9 +149,6 @@ type FhirMedicationRequest struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } func (s *FhirMedicationRequest) GetSearchParameters() map[string]string { @@ -183,7 +180,6 @@ func (s *FhirMedicationRequest) GetSearchParameters() map[string]string { "status": "token", "subject": "reference", "text": "keyword", - "type": "special", } return searchParameters } diff --git a/backend/pkg/models/database/fhir_medication_statement.go b/backend/pkg/models/database/fhir_medication_statement.go index c15a0ba47..51f7b5266 100644 --- a/backend/pkg/models/database/fhir_medication_statement.go +++ b/backend/pkg/models/database/fhir_medication_statement.go @@ -126,9 +126,6 @@ type FhirMedicationStatement struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } func (s *FhirMedicationStatement) GetSearchParameters() map[string]string { @@ -155,7 +152,6 @@ func (s *FhirMedicationStatement) GetSearchParameters() map[string]string { "status": "token", "subject": "reference", "text": "keyword", - "type": "special", } return searchParameters } diff --git a/backend/pkg/models/database/fhir_nutrition_order.go b/backend/pkg/models/database/fhir_nutrition_order.go index 15bef5490..c21cf7857 100644 --- a/backend/pkg/models/database/fhir_nutrition_order.go +++ b/backend/pkg/models/database/fhir_nutrition_order.go @@ -113,9 +113,6 @@ type FhirNutritionOrder struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } func (s *FhirNutritionOrder) GetSearchParameters() map[string]string { @@ -143,7 +140,6 @@ func (s *FhirNutritionOrder) GetSearchParameters() map[string]string { "status": "token", "supplement": "token", "text": "keyword", - "type": "special", } return searchParameters } diff --git a/backend/pkg/models/database/fhir_observation.go b/backend/pkg/models/database/fhir_observation.go index 261aaa4cb..7e8ac83de 100644 --- a/backend/pkg/models/database/fhir_observation.go +++ b/backend/pkg/models/database/fhir_observation.go @@ -192,9 +192,6 @@ type FhirObservation struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` // The value of the observation, if the value is a CodeableConcept // https://hl7.org/fhir/r4/search.html#token ValueConcept datatypes.JSON `gorm:"column:valueConcept;type:text;serializer:json" json:"valueConcept,omitempty"` @@ -248,7 +245,6 @@ func (s *FhirObservation) GetSearchParameters() map[string]string { "status": "token", "subject": "reference", "text": "keyword", - "type": "special", "valueConcept": "token", "valueDate": "date", "valueQuantity": "quantity", diff --git a/backend/pkg/models/database/fhir_organization.go b/backend/pkg/models/database/fhir_organization.go index 8253fa063..c8293920e 100644 --- a/backend/pkg/models/database/fhir_organization.go +++ b/backend/pkg/models/database/fhir_organization.go @@ -68,8 +68,8 @@ type FhirOrganization struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special + // A code for the type of organization + // https://hl7.org/fhir/r4/search.html#token Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } @@ -99,7 +99,7 @@ func (s *FhirOrganization) GetSearchParameters() map[string]string { "source_resource_type": "keyword", "source_uri": "keyword", "text": "keyword", - "type": "special", + "type": "token", } return searchParameters } @@ -238,6 +238,11 @@ func (s *FhirOrganization) PopulateAndExtractSearchParameters(resourceRaw json.R if err == nil && textResult.String() != "undefined" { s.Text = textResult.String() } + // extracting Type + typeResult, err := vm.RunString("extractTokenSearchParameters(fhirResource, 'Organization.type')") + if err == nil && typeResult.String() != "undefined" { + s.Type = []byte(typeResult.String()) + } return nil } diff --git a/backend/pkg/models/database/fhir_organization_affiliation.go b/backend/pkg/models/database/fhir_organization_affiliation.go index dd44b3a2b..57e7667cd 100644 --- a/backend/pkg/models/database/fhir_organization_affiliation.go +++ b/backend/pkg/models/database/fhir_organization_affiliation.go @@ -74,9 +74,6 @@ type FhirOrganizationAffiliation struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } func (s *FhirOrganizationAffiliation) GetSearchParameters() map[string]string { @@ -107,7 +104,6 @@ func (s *FhirOrganizationAffiliation) GetSearchParameters() map[string]string { "specialty": "token", "telecom": "token", "text": "keyword", - "type": "special", } return searchParameters } diff --git a/backend/pkg/models/database/fhir_patient.go b/backend/pkg/models/database/fhir_patient.go index 561a7eafc..0d51eaead 100644 --- a/backend/pkg/models/database/fhir_patient.go +++ b/backend/pkg/models/database/fhir_patient.go @@ -194,9 +194,6 @@ type FhirPatient struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } func (s *FhirPatient) GetSearchParameters() map[string]string { @@ -235,7 +232,6 @@ func (s *FhirPatient) GetSearchParameters() map[string]string { "source_uri": "keyword", "telecom": "token", "text": "keyword", - "type": "special", } return searchParameters } diff --git a/backend/pkg/models/database/fhir_person.go b/backend/pkg/models/database/fhir_person.go index 356e55b14..ec880a31c 100644 --- a/backend/pkg/models/database/fhir_person.go +++ b/backend/pkg/models/database/fhir_person.go @@ -172,9 +172,6 @@ type FhirPerson struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } func (s *FhirPerson) GetSearchParameters() map[string]string { @@ -209,7 +206,6 @@ func (s *FhirPerson) GetSearchParameters() map[string]string { "source_uri": "keyword", "telecom": "token", "text": "keyword", - "type": "special", } return searchParameters } diff --git a/backend/pkg/models/database/fhir_practitioner.go b/backend/pkg/models/database/fhir_practitioner.go index 897cfd253..0835f5127 100644 --- a/backend/pkg/models/database/fhir_practitioner.go +++ b/backend/pkg/models/database/fhir_practitioner.go @@ -173,9 +173,6 @@ type FhirPractitioner struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } func (s *FhirPractitioner) GetSearchParameters() map[string]string { @@ -209,7 +206,6 @@ func (s *FhirPractitioner) GetSearchParameters() map[string]string { "source_uri": "keyword", "telecom": "token", "text": "keyword", - "type": "special", } return searchParameters } diff --git a/backend/pkg/models/database/fhir_practitioner_role.go b/backend/pkg/models/database/fhir_practitioner_role.go index 1aa4b33da..f39ce3359 100644 --- a/backend/pkg/models/database/fhir_practitioner_role.go +++ b/backend/pkg/models/database/fhir_practitioner_role.go @@ -95,9 +95,6 @@ type FhirPractitionerRole struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } func (s *FhirPractitionerRole) GetSearchParameters() map[string]string { @@ -127,7 +124,6 @@ func (s *FhirPractitionerRole) GetSearchParameters() map[string]string { "specialty": "token", "telecom": "token", "text": "keyword", - "type": "special", } return searchParameters } diff --git a/backend/pkg/models/database/fhir_procedure.go b/backend/pkg/models/database/fhir_procedure.go index 6dd048d9c..312d32790 100644 --- a/backend/pkg/models/database/fhir_procedure.go +++ b/backend/pkg/models/database/fhir_procedure.go @@ -162,9 +162,6 @@ type FhirProcedure struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } func (s *FhirProcedure) GetSearchParameters() map[string]string { @@ -196,7 +193,6 @@ func (s *FhirProcedure) GetSearchParameters() map[string]string { "status": "token", "subject": "reference", "text": "keyword", - "type": "special", } return searchParameters } diff --git a/backend/pkg/models/database/fhir_provenance.go b/backend/pkg/models/database/fhir_provenance.go index ab61b7c72..4eb36c361 100644 --- a/backend/pkg/models/database/fhir_provenance.go +++ b/backend/pkg/models/database/fhir_provenance.go @@ -56,9 +56,6 @@ type FhirProvenance struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` // When the activity occurred // https://hl7.org/fhir/r4/search.html#date When *time.Time `gorm:"column:when;type:datetime" json:"when,omitempty"` @@ -86,7 +83,6 @@ func (s *FhirProvenance) GetSearchParameters() map[string]string { "source_uri": "keyword", "target": "reference", "text": "keyword", - "type": "special", "when": "date", } return searchParameters diff --git a/backend/pkg/models/database/fhir_questionnaire.go b/backend/pkg/models/database/fhir_questionnaire.go index 08b2d8562..d6d10ee47 100644 --- a/backend/pkg/models/database/fhir_questionnaire.go +++ b/backend/pkg/models/database/fhir_questionnaire.go @@ -77,9 +77,6 @@ type FhirQuestionnaire struct { // The human-friendly name of the questionnaire // https://hl7.org/fhir/r4/search.html#string Title datatypes.JSON `gorm:"column:title;type:text;serializer:json" json:"title,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` // The uri that identifies the questionnaire // https://hl7.org/fhir/r4/search.html#uri Url string `gorm:"column:url;type:text" json:"url,omitempty"` @@ -117,7 +114,6 @@ func (s *FhirQuestionnaire) GetSearchParameters() map[string]string { "subjectType": "token", "text": "keyword", "title": "string", - "type": "special", "url": "uri", "version": "token", } diff --git a/backend/pkg/models/database/fhir_questionnaire_response.go b/backend/pkg/models/database/fhir_questionnaire_response.go index 513acc19b..ef51d8160 100644 --- a/backend/pkg/models/database/fhir_questionnaire_response.go +++ b/backend/pkg/models/database/fhir_questionnaire_response.go @@ -62,9 +62,6 @@ type FhirQuestionnaireResponse struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } func (s *FhirQuestionnaireResponse) GetSearchParameters() map[string]string { @@ -91,7 +88,6 @@ func (s *FhirQuestionnaireResponse) GetSearchParameters() map[string]string { "status": "token", "subject": "reference", "text": "keyword", - "type": "special", } return searchParameters } diff --git a/backend/pkg/models/database/fhir_related_person.go b/backend/pkg/models/database/fhir_related_person.go index 4b4f9ea11..9345f2825 100644 --- a/backend/pkg/models/database/fhir_related_person.go +++ b/backend/pkg/models/database/fhir_related_person.go @@ -166,9 +166,6 @@ type FhirRelatedPerson struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } func (s *FhirRelatedPerson) GetSearchParameters() map[string]string { @@ -201,7 +198,6 @@ func (s *FhirRelatedPerson) GetSearchParameters() map[string]string { "source_uri": "keyword", "telecom": "token", "text": "keyword", - "type": "special", } return searchParameters } diff --git a/backend/pkg/models/database/fhir_schedule.go b/backend/pkg/models/database/fhir_schedule.go index 4874b04c1..b45ddcff3 100644 --- a/backend/pkg/models/database/fhir_schedule.go +++ b/backend/pkg/models/database/fhir_schedule.go @@ -53,9 +53,6 @@ type FhirSchedule struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } func (s *FhirSchedule) GetSearchParameters() map[string]string { @@ -79,7 +76,6 @@ func (s *FhirSchedule) GetSearchParameters() map[string]string { "source_uri": "keyword", "specialty": "token", "text": "keyword", - "type": "special", } return searchParameters } diff --git a/backend/pkg/models/database/fhir_service_request.go b/backend/pkg/models/database/fhir_service_request.go index 0900cd540..d332b8426 100644 --- a/backend/pkg/models/database/fhir_service_request.go +++ b/backend/pkg/models/database/fhir_service_request.go @@ -157,9 +157,6 @@ type FhirServiceRequest struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } func (s *FhirServiceRequest) GetSearchParameters() map[string]string { @@ -196,7 +193,6 @@ func (s *FhirServiceRequest) GetSearchParameters() map[string]string { "status": "token", "subject": "reference", "text": "keyword", - "type": "special", } return searchParameters } diff --git a/backend/pkg/models/database/fhir_slot.go b/backend/pkg/models/database/fhir_slot.go index 5d1d00863..e45b222cb 100644 --- a/backend/pkg/models/database/fhir_slot.go +++ b/backend/pkg/models/database/fhir_slot.go @@ -56,9 +56,6 @@ type FhirSlot struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } func (s *FhirSlot) GetSearchParameters() map[string]string { @@ -83,7 +80,6 @@ func (s *FhirSlot) GetSearchParameters() map[string]string { "start": "date", "status": "token", "text": "keyword", - "type": "special", } return searchParameters } diff --git a/backend/pkg/models/database/fhir_specimen.go b/backend/pkg/models/database/fhir_specimen.go index 8e9dc0c86..13a67c11a 100644 --- a/backend/pkg/models/database/fhir_specimen.go +++ b/backend/pkg/models/database/fhir_specimen.go @@ -62,8 +62,8 @@ type FhirSpecimen struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special + // The specimen type + // https://hl7.org/fhir/r4/search.html#token Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } @@ -91,7 +91,7 @@ func (s *FhirSpecimen) GetSearchParameters() map[string]string { "status": "token", "subject": "reference", "text": "keyword", - "type": "special", + "type": "token", } return searchParameters } @@ -228,6 +228,11 @@ func (s *FhirSpecimen) PopulateAndExtractSearchParameters(resourceRaw json.RawMe if err == nil && textResult.String() != "undefined" { s.Text = textResult.String() } + // extracting Type + typeResult, err := vm.RunString("extractTokenSearchParameters(fhirResource, 'Specimen.type')") + if err == nil && typeResult.String() != "undefined" { + s.Type = []byte(typeResult.String()) + } return nil } diff --git a/backend/pkg/models/database/fhir_vision_prescription.go b/backend/pkg/models/database/fhir_vision_prescription.go index 2e3933368..38cb0b3f7 100644 --- a/backend/pkg/models/database/fhir_vision_prescription.go +++ b/backend/pkg/models/database/fhir_vision_prescription.go @@ -95,9 +95,6 @@ type FhirVisionPrescription struct { // Text search against the narrative // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific Text string `gorm:"column:text;type:text" json:"text,omitempty"` - // A resource type filter - // https://hl7.org/fhir/r4/search.html#special - Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` } func (s *FhirVisionPrescription) GetSearchParameters() map[string]string { @@ -119,7 +116,6 @@ func (s *FhirVisionPrescription) GetSearchParameters() map[string]string { "source_uri": "keyword", "status": "token", "text": "keyword", - "type": "special", } return searchParameters } diff --git a/backend/pkg/models/database/generate.go b/backend/pkg/models/database/generate.go index 0e5dbad83..282679b1c 100644 --- a/backend/pkg/models/database/generate.go +++ b/backend/pkg/models/database/generate.go @@ -170,10 +170,6 @@ func main() { Description: "Text search against the narrative", FHIRPathExpression: "text", } - fieldMap["Type"] = DBField{ - FieldType: "special", - Description: "A resource type filter", - } resourceFieldMap[resourceName] = fieldMap } diff --git a/backend/pkg/models/database/interface.go b/backend/pkg/models/database/interface.go index 6b541520b..2a70705b2 100644 --- a/backend/pkg/models/database/interface.go +++ b/backend/pkg/models/database/interface.go @@ -27,6 +27,10 @@ type SearchParameterTokenType []struct { Text string `json:"text"` } +type SearchParameterReferenceType []struct { + Reference string `json:"reference"` +} + type SearchParameterStringType []string type SearchParameterDateType []struct { From 30149c4aef2ec8e14288d65527f420d6be3910da Mon Sep 17 00:00:00 2001 From: Jason Kulatunga Date: Sat, 24 Feb 2024 17:56:08 -0800 Subject: [PATCH 17/29] working on care plan tests. --- .../models/database/fhir_care_plan_test.go | 80 +++++++++++++++++++ backend/pkg/models/database/interface.go | 1 + 2 files changed, 81 insertions(+) create mode 100644 backend/pkg/models/database/fhir_care_plan_test.go diff --git a/backend/pkg/models/database/fhir_care_plan_test.go b/backend/pkg/models/database/fhir_care_plan_test.go new file mode 100644 index 000000000..a9ad23321 --- /dev/null +++ b/backend/pkg/models/database/fhir_care_plan_test.go @@ -0,0 +1,80 @@ +package database + +import ( + "encoding/json" + "github.com/stretchr/testify/require" + "os" + "testing" + "time" +) + +func TestFhirCarePlan_ExtractSearchParameters(t *testing.T) { + t.Parallel() + //setup + carePlanBytes, err := os.ReadFile("../../../../frontend/src/lib/fixtures/r4/resources/carePlan/heartOperationPlan.json") + require.NoError(t, err) + //test + carePlanModel := FhirCarePlan{} + err = carePlanModel.PopulateAndExtractSearchParameters(carePlanBytes) + + //assert + + var testActivityCode SearchParameterTokenType + require.NoError(t, err) + err = json.Unmarshal(json.RawMessage(carePlanModel.ActivityCode), &testActivityCode) + require.NoError(t, err) + require.Equal(t, SearchParameterTokenType{ + { + System: "http://snomed.info/sct", + Code: "64915003", + Text: "Operation on heart", + }, + }, testActivityCode) + + require.Equal(t, "2011-06-27T09:30:10+01:00", carePlanModel.ActivityDate.Format(time.RFC3339)) + + var testCareTeam SearchParameterReferenceType + require.NoError(t, err) + err = json.Unmarshal(json.RawMessage(carePlanModel.CareTeam), &testCareTeam) + require.NoError(t, err) + require.Equal(t, SearchParameterReferenceType{ + { + Reference: "#careteam", + }, + }, testCareTeam) + + require.Nil(t, carePlanModel.Category) + + var testCondition SearchParameterReferenceType + require.NoError(t, err) + err = json.Unmarshal(json.RawMessage(carePlanModel.Condition), &testCondition) + require.NoError(t, err) + require.Equal(t, SearchParameterReferenceType{ + { + Reference: "Condition/f201", + Display: "?????", + }, + }, testCondition) + + require.Equal(t, "2011-06-26T00:00:00Z", carePlanModel.Date.Format(time.RFC3339)) //TODO date periods are not handled correctly + + var testGoal SearchParameterReferenceType + require.NoError(t, err) + err = json.Unmarshal(json.RawMessage(carePlanModel.Goal), &testGoal) + require.NoError(t, err) + require.Equal(t, SearchParameterReferenceType{ + { + Reference: "#goal", + }, + }, testGoal) + + var testIntent SearchParameterTokenType + require.NoError(t, err) + err = json.Unmarshal(json.RawMessage(carePlanModel.Intent), &testIntent) + require.NoError(t, err) + require.Equal(t, SearchParameterTokenType{ + { + Code: "plan", + }, + }, testIntent) +} diff --git a/backend/pkg/models/database/interface.go b/backend/pkg/models/database/interface.go index 2a70705b2..d513c6df4 100644 --- a/backend/pkg/models/database/interface.go +++ b/backend/pkg/models/database/interface.go @@ -29,6 +29,7 @@ type SearchParameterTokenType []struct { type SearchParameterReferenceType []struct { Reference string `json:"reference"` + Display string `json:"display"` } type SearchParameterStringType []string From 2e5b84dbebb742b0dbda2ea73ce391764c6fc9d1 Mon Sep 17 00:00:00 2001 From: Jason Kulatunga Date: Sat, 24 Feb 2024 20:45:21 -0800 Subject: [PATCH 18/29] working IPS export open in new window. --- .../report-header.component.html | 2 +- .../report-header/report-header.component.ts | 4 ++ .../src/app/services/fasten-api.service.ts | 50 +++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/components/report-header/report-header.component.html b/frontend/src/app/components/report-header/report-header.component.html index 58723ec34..148fcd645 100644 --- a/frontend/src/app/components/report-header/report-header.component.html +++ b/frontend/src/app/components/report-header/report-header.component.html @@ -33,7 +33,7 @@
All Sources
diff --git a/frontend/src/app/components/report-header/report-header.component.ts b/frontend/src/app/components/report-header/report-header.component.ts index b77053c0b..86db49a75 100644 --- a/frontend/src/app/components/report-header/report-header.component.ts +++ b/frontend/src/app/components/report-header/report-header.component.ts @@ -41,5 +41,9 @@ export class ReportHeaderComponent implements OnInit { } }) } + getIPSExport(event: Event){ + event.preventDefault() + return this.fastenApi.getIPSExport() + } } diff --git a/frontend/src/app/services/fasten-api.service.ts b/frontend/src/app/services/fasten-api.service.ts index acf5bccbe..8b6d2944e 100644 --- a/frontend/src/app/services/fasten-api.service.ts +++ b/frontend/src/app/services/fasten-api.service.ts @@ -368,4 +368,54 @@ export class FastenApiService { ); } + getIPSExport(exportType?: string) { + // // PDF + // + // // function openPdf($event) { + // // Prevent default behavior when clicking a link + // $event.preventDefault(); + // + // // Get filename from href + // var filename = $event.target.href; + // + // $http.get('/api/secure/summary/ips?format=html', {responseType: 'arraybuffer'}) + // .success(function (data) { + // var file = new Blob([data], {type: 'application/pdf'}); + // var fileURL = URL.createObjectURL(file); + // + // // Open new windows and show PDF + // window.open(fileURL); + // }); + // + // $vent. + // // } + + let httpHeaders = new HttpHeaders(); + //.set('Content-Type' + httpHeaders.set('Accept', 'text/html'); + + + let queryParams = { + "format": exportType || "html" + } + console.log("requesting", `${GetEndpointAbsolutePath(globalThis.location, environment.fasten_api_endpoint_base)}/secure/summary/ips`) + return this._httpClient.get(`${GetEndpointAbsolutePath(globalThis.location, environment.fasten_api_endpoint_base)}/secure/summary/ips`, { + params: queryParams, + headers: httpHeaders, + // observe: 'response', + // @ts-ignore + responseType: 'arraybuffer' + }) + .subscribe((data) => { + + var file = new Blob([data]); + var fileURL = URL.createObjectURL(file); + + // Open new windows and show PDF or HTML file + window.open(fileURL, "_blank"); + + }); + + } + } From 9608e07b8545fbaa78c09ae3b304214f28bc8baa Mon Sep 17 00:00:00 2001 From: Jason Kulatunga Date: Sat, 24 Feb 2024 20:52:03 -0800 Subject: [PATCH 19/29] working IPS export using github markdown. --- backend/pkg/utils/ips/templates/index.gohtml | 22 +++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/backend/pkg/utils/ips/templates/index.gohtml b/backend/pkg/utils/ips/templates/index.gohtml index a98b798af..d34ccc2bf 100644 --- a/backend/pkg/utils/ips/templates/index.gohtml +++ b/backend/pkg/utils/ips/templates/index.gohtml @@ -5,13 +5,33 @@ title + + + + {{template "header.gohtml" .}} {{template "toc.gohtml" .}} -{{template "composition.gohtml" .}} +
+ {{template "composition.gohtml" .}} +
{{template "footer.gohtml" .}} From 7900ccfeb61c566c9cb6c39150d6737ea86a7e54 Mon Sep 17 00:00:00 2001 From: Jason Kulatunga Date: Sat, 2 Mar 2024 21:13:30 -0800 Subject: [PATCH 20/29] better Observation value export & unit export - centralized in single include. Added support for value rounding. --- backend/pkg/utils/ips/render.go | 14 ++++++++++++++ .../ips/templates/allergies_intolerances.gohtml | 2 +- .../ips/templates/includes/observation-unit.gohtml | 9 +++++++++ .../templates/includes/observation-value.gohtml | 12 ++++++++++++ backend/pkg/utils/ips/templates/pregnancy.gohtml | 12 +----------- .../pkg/utils/ips/templates/social_history.gohtml | 12 +----------- backend/pkg/utils/ips/templates/vital_signs.gohtml | 14 ++------------ 7 files changed, 40 insertions(+), 35 deletions(-) create mode 100644 backend/pkg/utils/ips/templates/includes/observation-unit.gohtml create mode 100644 backend/pkg/utils/ips/templates/includes/observation-value.gohtml diff --git a/backend/pkg/utils/ips/render.go b/backend/pkg/utils/ips/render.go index 3f69c5b4e..fb1d855c8 100644 --- a/backend/pkg/utils/ips/render.go +++ b/backend/pkg/utils/ips/render.go @@ -11,6 +11,7 @@ import ( "github.com/fastenhealth/gofhir-models/fhir401" "gorm.io/datatypes" "html/template" + "math" ) //go:embed templates @@ -66,6 +67,19 @@ func NewNarrative() (*Narrative, error) { } return values }, + "roundList": func(precision uint, listVals []interface{}) []interface{} { + results := []interface{}{} + for ndx, _ := range listVals { + switch listVal := listVals[ndx].(type) { + case float64: + ratio := math.Pow(10, float64(precision)) + results = append(results, math.Round(listVal*ratio)/ratio) + default: + results = append(results, listVal) + } + } + return results + }, }).Funcs(sprig.FuncMap()).ParseFS(ipsTemplates, "templates/*.gohtml", "templates/includes/*.gohtml") if err != nil { diff --git a/backend/pkg/utils/ips/templates/allergies_intolerances.gohtml b/backend/pkg/utils/ips/templates/allergies_intolerances.gohtml index 4d0dda7fc..9f2d7b43e 100644 --- a/backend/pkg/utils/ips/templates/allergies_intolerances.gohtml +++ b/backend/pkg/utils/ips/templates/allergies_intolerances.gohtml @@ -32,7 +32,7 @@ Comments: AllergyIntolerance.note[x].text (separated by
) {{pluckList "text" ($entry.Manifestation | parseList) | uniq | join "," }} {{/* Reaction */}} {{pluckList "code" ($entry.Criticality | parseList) | uniq | join ","}} {{/* Severity */}} Comments {{/* Comments - TODO: use FHIRPath */}} - {{$entry.Onset | date "2006-01-02"}} {{/* Onset */}} + {{default "unknown" $entry.Onset }} {{/* Onset */}} {{end}} diff --git a/backend/pkg/utils/ips/templates/includes/observation-unit.gohtml b/backend/pkg/utils/ips/templates/includes/observation-unit.gohtml new file mode 100644 index 000000000..d6dac18d6 --- /dev/null +++ b/backend/pkg/utils/ips/templates/includes/observation-unit.gohtml @@ -0,0 +1,9 @@ +{{if not (empty .ValueString) }} + {{.ValueString}} +{{else if not (empty (.ValueQuantity | parseList)) }} + {{.ValueQuantity | parseList | pluckList "unit" | join "," }} +{{else if not (empty .ValueDate) }} + {{.ValueDate | date "2006-01-02" }} +{{else if not (empty (.ValueConcept | parseList)) }} + {{.ValueConcept}} +{{end}} diff --git a/backend/pkg/utils/ips/templates/includes/observation-value.gohtml b/backend/pkg/utils/ips/templates/includes/observation-value.gohtml new file mode 100644 index 000000000..409f62e91 --- /dev/null +++ b/backend/pkg/utils/ips/templates/includes/observation-value.gohtml @@ -0,0 +1,12 @@ +{{if not (empty .entry.ValueString) }} + {{.ValueString}} +{{else if not (empty (.entry.ValueQuantity | parseList)) }} + {{.entry.ValueQuantity | parseList | pluckList "value" | roundList 2 | join "," }} + {{if (get . "include_unit")}} + {{.entry.ValueQuantity | parseList | pluckList "unit" | join "," }} + {{end}} +{{else if not (empty .entry.ValueDate) }} + {{.entry.ValueDate | date "2006-01-02" }} +{{else if not (empty (.entry.ValueConcept | parseList)) }} + {{.entry.ValueConcept}} +{{end}} diff --git a/backend/pkg/utils/ips/templates/pregnancy.gohtml b/backend/pkg/utils/ips/templates/pregnancy.gohtml index ccb6f6427..8e9dd53a0 100644 --- a/backend/pkg/utils/ips/templates/pregnancy.gohtml +++ b/backend/pkg/utils/ips/templates/pregnancy.gohtml @@ -21,17 +21,7 @@ Date: Observation.effectiveDateTime || Observation.effectivePeriod.start {{range $index, $entry := .Observation }} {{pluckList "text" ($entry.Code | parseList) | uniq | join "," }} {{/* Code */}} - - {{if not (empty $entry.ValueString) }} - {{$entry.ValueString}} - {{else if not (empty ($entry.ValueQuantity | parseList)) }} - {{$entry.ValueQuantity}} - {{else if not (empty $entry.ValueDate) }} - {{$entry.ValueDate | date "2006-01-02" }} - {{else if not (empty ($entry.ValueConcept | parseList)) }} - {{$entry.ValueConcept}} - {{end}} - {{/* Result */}} + {{template "observation-value.gohtml" (dict "entry" $entry "include_unit" true)}} {{/* Result */}} Comments {{$entry.Date | date "2006-01-02"}} {{/* Date */}} diff --git a/backend/pkg/utils/ips/templates/social_history.gohtml b/backend/pkg/utils/ips/templates/social_history.gohtml index 17bab7825..842806f9d 100644 --- a/backend/pkg/utils/ips/templates/social_history.gohtml +++ b/backend/pkg/utils/ips/templates/social_history.gohtml @@ -23,17 +23,7 @@ Date: Observation.effectiveDateTime || Observation.effectivePeriod.start {{range $index, $entry := .Observation }} {{pluckList "text" ($entry.Code | parseList) | uniq | join "," }} {{/* Code */}} - - {{if not (empty $entry.ValueString) }} - {{$entry.ValueString}} - {{else if not (empty ($entry.ValueQuantity | parseList)) }} - {{$entry.ValueQuantity}} - {{else if not (empty $entry.ValueDate) }} - {{$entry.ValueDate | date "2006-01-02" }} - {{else if not (empty ($entry.ValueConcept | parseList)) }} - {{$entry.ValueConcept}} - {{end}} - {{/* Result */}} + {{template "observation-value.gohtml" (dict "entry" $entry "include_unit" false)}} {{/* Result */}} Unit Comments {{$entry.Date | date "2006-01-02"}} {{/* Date */}} diff --git a/backend/pkg/utils/ips/templates/vital_signs.gohtml b/backend/pkg/utils/ips/templates/vital_signs.gohtml index 2950a5d8d..3176f2809 100644 --- a/backend/pkg/utils/ips/templates/vital_signs.gohtml +++ b/backend/pkg/utils/ips/templates/vital_signs.gohtml @@ -26,18 +26,8 @@ Date: Observation.effectiveDateTime || Observation.effectivePeriod.start {{range $index, $entry := .Observation }} {{pluckList "text" ($entry.Code | parseList) | uniq | join "," }} {{/* Code */}} - - {{if not (empty $entry.ValueString) }} - {{$entry.ValueString}} - {{else if not (empty ($entry.ValueQuantity | parseList)) }} - {{$entry.ValueQuantity}} - {{else if not (empty $entry.ValueDate) }} - {{$entry.ValueDate | date "2006-01-02" }} - {{else if not (empty ($entry.ValueConcept | parseList)) }} - {{$entry.ValueConcept}} - {{end}} - {{/* Result */}} - Unit + {{template "observation-value.gohtml" (dict "entry" $entry "include_unit" false)}} {{/* Result */}} + {{template "observation-unit.gohtml" $entry}} Interpretation Comments {{$entry.Date | date "2006-01-02"}} {{/* Date */}} From 0f6e735e3a1d53e826c8a8296b07e02f3b5cb3ff Mon Sep 17 00:00:00 2001 From: Jason Kulatunga Date: Sun, 3 Mar 2024 10:04:43 -0800 Subject: [PATCH 21/29] update inteface{} usage in query with `any` for clarity. --- backend/pkg/database/gorm_repository_query.go | 8 +++++++- backend/pkg/models/query_resource.go | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/backend/pkg/database/gorm_repository_query.go b/backend/pkg/database/gorm_repository_query.go index 0b69a0851..4a29090b8 100644 --- a/backend/pkg/database/gorm_repository_query.go +++ b/backend/pkg/database/gorm_repository_query.go @@ -41,6 +41,10 @@ const TABLE_ALIAS = "fhir" // Can generate simple or complex queries, depending on the SearchParameter type: // // eg. Simple +// SELECT fhir.* +// FROM fhir_observation as fhir, json_each(fhir.code) as codeJson +// +// result = inteface{} ([]database.IFhirResource) // // eg. Complex // SELECT fhir.* @@ -54,6 +58,8 @@ const TABLE_ALIAS = "fhir" // ) // AND (user_id = "6efcd7c5-3f29-4f0d-926d-a66ff68bbfc2") // GROUP BY `fhir`.`id` +// +// results = []map[string]any{} func (gr *GormRepository) QueryResources(ctx context.Context, query models.QueryResource) (interface{}, error) { sqlQuery, err := gr.sqlQueryResources(ctx, query) @@ -62,7 +68,7 @@ func (gr *GormRepository) QueryResources(ctx context.Context, query models.Query } if query.Aggregations != nil && (query.Aggregations.GroupBy != nil || query.Aggregations.CountBy != nil) { - results := []map[string]interface{}{} + results := []map[string]any{} clientResp := sqlQuery.Find(&results) return results, clientResp.Error diff --git a/backend/pkg/models/query_resource.go b/backend/pkg/models/query_resource.go index 88c3f5848..bf099c10b 100644 --- a/backend/pkg/models/query_resource.go +++ b/backend/pkg/models/query_resource.go @@ -27,7 +27,7 @@ type QueryResourceAggregations struct { type QueryResourceAggregation struct { Field string `json:"field"` - Function string `json:"fn"` + Function string `json:"fn"` //built-in SQL aggregation functions (eg. Count, min, max, etc). } func (q *QueryResource) Validate() error { From 441c8ab964105779ad133cb4d8c4e87a73b0c518 Mon Sep 17 00:00:00 2001 From: Jason Kulatunga Date: Sun, 3 Mar 2024 14:02:01 -0800 Subject: [PATCH 22/29] when querying vital signs, use vital-signs category to find a list of all codes, which are then used to find the last 3 results for this code. --- .../gorm_repository_query_sql_test.go | 42 ++++++ .../pkg/database/gorm_repository_summary.go | 120 +++++++++++++++--- .../utils/ips/templates/immunizations.gohtml | 2 +- 3 files changed, 142 insertions(+), 22 deletions(-) diff --git a/backend/pkg/database/gorm_repository_query_sql_test.go b/backend/pkg/database/gorm_repository_query_sql_test.go index 756b8569d..e40709509 100644 --- a/backend/pkg/database/gorm_repository_query_sql_test.go +++ b/backend/pkg/database/gorm_repository_query_sql_test.go @@ -706,3 +706,45 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenMultipleMod "test_code", "test_code2", "test_code3", "test_code4", "test_code5", "test_code6", "00000000-0000-0000-0000-000000000000", }) } + +// Section Vital Signs Codes Lookup + +func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_SectionVitalSigns_WithTokenGroupByNoModifier() { + //setup + sqliteRepo := suite.TestRepository.(*GormRepository) + sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true}) + + //test + authContext := context.WithValue(context.Background(), pkg.ContextKeyTypeAuthUsername, "test_username") + + sqlQuery, err := sqliteRepo.sqlQueryResources(authContext, models.QueryResource{ + Select: []string{}, + Where: map[string]interface{}{ + "category": "vital-signs", + }, + From: "Observation", + Aggregations: &models.QueryResourceAggregations{ + GroupBy: &models.QueryResourceAggregation{Field: "code:code"}, + }, + }) + require.NoError(suite.T(), err) + var results []map[string]interface{} + statement := sqlQuery.Find(&results).Statement + sqlString := statement.SQL.String() + sqlParams := statement.Vars + + //assert + require.NoError(suite.T(), err) + require.Equal(suite.T(), + strings.Join([]string{ + "SELECT (codeJson.value ->> '$.code') as label, count(*) as value", + "FROM fhir_observation as fhir, json_each(fhir.category) as categoryJson, json_each(fhir.code) as codeJson", + "WHERE ((categoryJson.value ->> '$.code' = ?)) AND (user_id = ?)", + "GROUP BY (codeJson.value ->> '$.code')", + "ORDER BY count(*) DESC", + }, " "), sqlString) + require.Equal(suite.T(), sqlParams, []interface{}{ + "vital-signs", + "00000000-0000-0000-0000-000000000000", + }) +} diff --git a/backend/pkg/database/gorm_repository_summary.go b/backend/pkg/database/gorm_repository_summary.go index 74df41ef7..deac59bbf 100644 --- a/backend/pkg/database/gorm_repository_summary.go +++ b/backend/pkg/database/gorm_repository_summary.go @@ -10,6 +10,7 @@ import ( "github.com/fastenhealth/fasten-onprem/backend/pkg/utils/ips" "github.com/fastenhealth/gofhir-models/fhir401" "github.com/google/uuid" + "github.com/samber/lo" "log" "time" ) @@ -39,15 +40,15 @@ func (gr *GormRepository) GetInternationalPatientSummaryBundle(ctx context.Conte // 6. Create the IPS Bundle //Step 1. Generate the IPS Section Lists - summarySectionResources, err := gr.GetInternationalPatientSummarySectionResources(ctx) + summarySectionQueryResults, err := gr.getInternationalPatientSummarySectionResources(ctx) if err != nil { return nil, nil, err } //Step 2. Create the Composition Section compositionSections := []fhir401.CompositionSection{} - for sectionType, sectionResources := range summarySectionResources { - compositionSection, err := generateIPSCompositionSection(narrativeEngine, sectionType, sectionResources) + for sectionType, sectionQueryResultsList := range summarySectionQueryResults { + compositionSection, err := generateIPSCompositionSection(narrativeEngine, sectionType, sectionQueryResultsList) if err != nil { return nil, nil, err } @@ -146,14 +147,14 @@ func (gr *GormRepository) GetInternationalPatientSummaryBundle(ctx context.Conte // TODO: Add the Patient to the bundle // TODO: Add the Fasten Health Organization to the bundle - // Add all the resources to the bundle - for _, sectionResources := range summarySectionResources { - for _, resource := range sectionResources { - ipsBundle.Entry = append(ipsBundle.Entry, fhir401.BundleEntry{ - Resource: json.RawMessage(resource.GetResourceRaw()), - }) - } - } + // TODO: Add all the resources to the bundle + //for _, sectionResources := range summarySectionResources { + // for _, resource := range sectionResources { + // ipsBundle.Entry = append(ipsBundle.Entry, fhir401.BundleEntry{ + // Resource: json.RawMessage(resource.GetResourceRaw()), + // }) + // } + //} return ipsBundle, ipsComposition, nil } @@ -162,18 +163,18 @@ func (gr *GormRepository) GetInternationalPatientSummaryBundle(ctx context.Conte // The IPS bundle will contain a summary of all the data in the system, including a list of all sources, and the main Patient // See: https://github.com/fastenhealth/fasten-onprem/issues/170 // See: https://github.com/jddamore/fhir-ips-server/blob/main/docs/Summary_Creation_Steps.md -func (gr *GormRepository) GetInternationalPatientSummarySectionResources(ctx context.Context) (map[pkg.IPSSections][]database.IFhirResourceModel, error) { +func (gr *GormRepository) getInternationalPatientSummarySectionResources(ctx context.Context) (map[pkg.IPSSections][]any, error) { - summarySectionResources := map[pkg.IPSSections][]database.IFhirResourceModel{} + summarySectionResources := map[pkg.IPSSections][]any{} // generate queries for each IPS Section for ndx, _ := range pkg.IPSSectionsList { sectionName := pkg.IPSSectionsList[ndx] //initialize the section - summarySectionResources[sectionName] = []database.IFhirResourceModel{} + summarySectionResources[sectionName] = []any{} - queries, err := generateIPSSectionQueries(sectionName) + queries, err := gr.generateIPSSectionQueries(ctx, sectionName) if err != nil { return nil, err } @@ -184,17 +185,17 @@ func (gr *GormRepository) GetInternationalPatientSummarySectionResources(ctx con return nil, err } - resultsList := convertUnknownInterfaceToFhirSlice(results) + //resultsList := convertUnknownInterfaceToFhirSlice(results) //TODO: generate resource narrative - summarySectionResources[sectionName] = append(summarySectionResources[sectionName], resultsList...) + summarySectionResources[sectionName] = append(summarySectionResources[sectionName], results) } } return summarySectionResources, nil } -func generateIPSCompositionSection(narrativeEngine *ips.Narrative, sectionType pkg.IPSSections, resources []database.IFhirResourceModel) (*fhir401.CompositionSection, error) { +func generateIPSCompositionSection(narrativeEngine *ips.Narrative, sectionType pkg.IPSSections, queryResultsList []any) (*fhir401.CompositionSection, error) { sectionTitle, sectionCode, err := generateIPSSectionHeaderInfo(sectionType) if err != nil { return nil, err @@ -204,6 +205,11 @@ func generateIPSCompositionSection(narrativeEngine *ips.Narrative, sectionType p Title: §ionTitle, Code: §ionCode, } + + //database.IFhirResourceModel + + resources := flattenQueryResultsToResourcesList(queryResultsList) + if len(resources) == 0 { section.EmptyReason = &fhir401.CodeableConcept{ Text: stringPtr("No data available"), @@ -246,7 +252,7 @@ func generateIPSCompositionSection(narrativeEngine *ips.Narrative, sectionType p // https://github.com/jddamore/fhir-ips-server/blob/main/docs/Summary_Creation_Steps.md // Generate Resource Queries for each IPS Section -func generateIPSSectionQueries(sectionType pkg.IPSSections) ([]models.QueryResource, error) { +func (gr *GormRepository) generateIPSSectionQueries(ctx context.Context, sectionType pkg.IPSSections) ([]models.QueryResource, error) { queries := []models.QueryResource{} switch sectionType { @@ -306,14 +312,59 @@ func generateIPSSectionQueries(sectionType pkg.IPSSections) ([]models.QueryResou }) break case pkg.IPSSectionsVitalSigns: - //TODO: group by code, sort by date, limit to the most recent 3 - queries = append(queries, models.QueryResource{ + //lets query the database for this user, getting a list of unique codes, associated with this category ('vital-signs'). + //our goal is to retrieve the 3 most recent values for each code. + vitalSignsGrouped, err := gr.QueryResources(ctx, models.QueryResource{ Select: nil, From: "Observation", Where: map[string]interface{}{ "category": "vital-signs", }, + Aggregations: &models.QueryResourceAggregations{ + GroupBy: &models.QueryResourceAggregation{Field: "code:code"}, + }, }) + + if err != nil { + return nil, err + } + + vitalSignsGroupedByCodeList, ok := vitalSignsGrouped.([]map[string]any) + if !ok { + return nil, fmt.Errorf("could not decode vital signs grouped by code") + } + + //known codes related to vital signs: https://www.hl7.org/fhir/R4/valueset-observation-vitalsignresult.html#definition + vitalSignCodes := []string{ + "85353-1", "9279-1", "8867-4", "2708-6", "8310-5", "8302-2", "9843-4", "29463-7", "39156-5", "85354-9", "8480-6", "8462-4", "8478-0", + } + + for ndx, _ := range vitalSignsGroupedByCodeList { + //now that we have a list of codes that are tagged as vital-signs. + if labelValue, labelValueOk := vitalSignsGroupedByCodeList[ndx]["label"]; labelValueOk { + if labelValueStr, labeValueStrOk := labelValue.(*interface{}); labeValueStrOk { + vitalSignCodes = append(vitalSignCodes, (*labelValueStr).(string)) + } else { + gr.Logger.Warnf("could not cast vital-sign codes to string") + } + } else { + gr.Logger.Warnf("could not retrieve vital-sign group-by clause label value") + } + } + vitalSignCodes = lo.Uniq(vitalSignCodes) + + limit := 3 + //group by code, sort by date, limit to the most recent 3 + for ndx, _ := range vitalSignCodes { + queries = append(queries, models.QueryResource{ + Select: nil, + From: "Observation", + Where: map[string]interface{}{ + "code": vitalSignCodes[ndx], + }, + Limit: &limit, + }) + } break case pkg.IPSSectionsSocialHistory: queries = append(queries, models.QueryResource{ @@ -614,11 +665,38 @@ func convertUnknownInterfaceToFhirSlice(unknown interface{}) []database.IFhirRes for ndx, _ := range fhirSlice { results = append(results, &fhirSlice[ndx]) } + default: + log.Panicf("could not detect type for query results fhir resource list: %v", fhirSlice) } return results } +// query results may be a list of database.IFhirResourceModel or a map[string][]database.IFhirResourceModel (if we're using aggregations/grouping) +func flattenQueryResultsToResourcesList(queryResultsList []any) []database.IFhirResourceModel { + resources := []database.IFhirResourceModel{} + + for ndx, _ := range queryResultsList { + queryResults := queryResultsList[ndx] + switch queryResultsTyped := queryResults.(type) { + case []map[string]any: + //aggregated resources + for andx, _ := range queryResultsTyped { + queryResultsGrouped := queryResultsTyped[andx] + resources = append(resources, convertUnknownInterfaceToFhirSlice(queryResultsGrouped)...) + } + + case interface{}: + //list of resources + resources = append(resources, convertUnknownInterfaceToFhirSlice(queryResultsTyped)...) + default: + log.Panicf("Unknown Resource Structure: %v", queryResultsTyped) + } + } + + return resources +} + func generateIPSSectionNarrative(sectionType pkg.IPSSections, resources []models.ResourceBase) string { return "" } diff --git a/backend/pkg/utils/ips/templates/immunizations.gohtml b/backend/pkg/utils/ips/templates/immunizations.gohtml index 9161f09aa..748ad7300 100644 --- a/backend/pkg/utils/ips/templates/immunizations.gohtml +++ b/backend/pkg/utils/ips/templates/immunizations.gohtml @@ -30,7 +30,7 @@ Date: Immunization.occurrenceDateTime || Immunization.occurrenceString {{pluckList "text" ($entry.VaccineCode | parseList) | uniq | join "," }} {{/* Immunization */}} {{pluckList "code" ($entry.Status | parseList) | uniq | join "," }} {{/* Status */}} Dose Number {{/* Comments - TODO: use FHIRPath */}} - Manufacturer {{/* Manufacturer - TODO: use FHIRPath */}} + {{pluckList "display" ($entry.Manufacturer | parseList) | uniq | join "," }} {{/* Manufacturer */}} {{$entry.LotNumber}} {{/* Lot Number */}} Comments {{$entry.Date | date "2006-01-02"}} {{/* Performed Date */}} From 83d6cdea08faef591a7dc4a7695c3d8eb7cbb92d Mon Sep 17 00:00:00 2001 From: Jason Kulatunga Date: Sun, 3 Mar 2024 14:52:14 -0800 Subject: [PATCH 23/29] correctly handle complex Observations (ComponentValueQuantity - used by Blood Pressure - Diastolic vs Systolic) --- .../ips/templates/includes/observation-unit.gohtml | 2 ++ .../ips/templates/includes/observation-value.gohtml | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/backend/pkg/utils/ips/templates/includes/observation-unit.gohtml b/backend/pkg/utils/ips/templates/includes/observation-unit.gohtml index d6dac18d6..10a0de7c5 100644 --- a/backend/pkg/utils/ips/templates/includes/observation-unit.gohtml +++ b/backend/pkg/utils/ips/templates/includes/observation-unit.gohtml @@ -6,4 +6,6 @@ {{.ValueDate | date "2006-01-02" }} {{else if not (empty (.ValueConcept | parseList)) }} {{.ValueConcept}} +{{else if not (empty (.ComponentValueQuantity | parseList)) }} + {{.ComponentValueQuantity | parseList | pluckList "unit" | join "," }} {{end}} diff --git a/backend/pkg/utils/ips/templates/includes/observation-value.gohtml b/backend/pkg/utils/ips/templates/includes/observation-value.gohtml index 409f62e91..c57d17bbf 100644 --- a/backend/pkg/utils/ips/templates/includes/observation-value.gohtml +++ b/backend/pkg/utils/ips/templates/includes/observation-value.gohtml @@ -9,4 +9,15 @@ {{.entry.ValueDate | date "2006-01-02" }} {{else if not (empty (.entry.ValueConcept | parseList)) }} {{.entry.ValueConcept}} +{{else if not (empty (.entry.ComponentValueQuantity | parseList)) }} + {{$componentCodeText := $.entry.ComponentCode | parseList | pluckList "text" }} + {{$componentValueQuantity := $.entry.ComponentValueQuantity | parseList | pluckList "value" | roundList 2 }} + + {{range $index, $text := $componentCodeText }} + {{$text}} - {{index $componentValueQuantity $index}} + {{end}} + + {{if (get . "include_unit")}} + {{.ComponentValueQuantity | parseList | pluckList "unit" | join "," }} + {{end}} {{end}} From 08f87228260b983ef83eb4e8de9480bf45ee1d71 Mon Sep 17 00:00:00 2001 From: Jason Kulatunga Date: Sun, 3 Mar 2024 15:09:06 -0800 Subject: [PATCH 24/29] working Observation components with/without units. --- backend/pkg/utils/ips/render.go | 7 ++++- .../templates/allergies_intolerances.gohtml | 10 +++---- .../ips/templates/history_of_illness.gohtml | 4 +-- .../templates/history_of_procedures.gohtml | 2 +- .../utils/ips/templates/immunizations.gohtml | 6 ++-- .../includes/observation-unit.gohtml | 12 ++++---- .../includes/observation-value.gohtml | 28 +++++++++++-------- .../ips/templates/medical_devices.gohtml | 4 +-- .../utils/ips/templates/plan_of_care.gohtml | 2 +- .../pkg/utils/ips/templates/pregnancy.gohtml | 2 +- .../utils/ips/templates/problem_list.gohtml | 4 +-- .../utils/ips/templates/social_history.gohtml | 2 +- .../utils/ips/templates/vital_signs.gohtml | 2 +- 13 files changed, 47 insertions(+), 38 deletions(-) diff --git a/backend/pkg/utils/ips/render.go b/backend/pkg/utils/ips/render.go index fb1d855c8..add170b88 100644 --- a/backend/pkg/utils/ips/render.go +++ b/backend/pkg/utils/ips/render.go @@ -55,7 +55,12 @@ func NewNarrative() (*Narrative, error) { } return template.HTML(*s) }, - "parseList": func(data datatypes.JSON) []map[string]interface{} { + "parseStringList": func(data datatypes.JSON) []string { + var parsed []string + _ = json.Unmarshal(data, &parsed) + return parsed + }, + "parseMapList": func(data datatypes.JSON) []map[string]interface{} { var parsed []map[string]interface{} _ = json.Unmarshal(data, &parsed) return parsed diff --git a/backend/pkg/utils/ips/templates/allergies_intolerances.gohtml b/backend/pkg/utils/ips/templates/allergies_intolerances.gohtml index 9f2d7b43e..1c2625eee 100644 --- a/backend/pkg/utils/ips/templates/allergies_intolerances.gohtml +++ b/backend/pkg/utils/ips/templates/allergies_intolerances.gohtml @@ -26,11 +26,11 @@ Comments: AllergyIntolerance.note[x].text (separated by
) {{- /*gotype: github.com/fastenhealth/fasten-onprem/backend/pkg/utils/ips.NarrativeTemplateData*/ -}} {{range $index, $entry := .AllergyIntolerance }} - {{pluckList "text" ($entry.Code | parseList) | uniq | join "," }} {{/* Allergen */}} - {{pluckList "code" ($entry.ClinicalStatus | parseList) | uniq | join "," }} {{/* Status */}} - {{pluckList "code" ($entry.Category | parseList) | uniq | join "," }} {{/* Category */}} - {{pluckList "text" ($entry.Manifestation | parseList) | uniq | join "," }} {{/* Reaction */}} - {{pluckList "code" ($entry.Criticality | parseList) | uniq | join ","}} {{/* Severity */}} + {{pluckList "text" ($entry.Code | parseMapList) | uniq | join "," }} {{/* Allergen */}} + {{pluckList "code" ($entry.ClinicalStatus | parseMapList) | uniq | join "," }} {{/* Status */}} + {{pluckList "code" ($entry.Category | parseMapList) | uniq | join "," }} {{/* Category */}} + {{pluckList "text" ($entry.Manifestation | parseMapList) | uniq | join "," }} {{/* Reaction */}} + {{pluckList "code" ($entry.Criticality | parseMapList) | uniq | join ","}} {{/* Severity */}} Comments {{/* Comments - TODO: use FHIRPath */}} {{default "unknown" $entry.Onset }} {{/* Onset */}} diff --git a/backend/pkg/utils/ips/templates/history_of_illness.gohtml b/backend/pkg/utils/ips/templates/history_of_illness.gohtml index ec96b3463..4e83b4650 100644 --- a/backend/pkg/utils/ips/templates/history_of_illness.gohtml +++ b/backend/pkg/utils/ips/templates/history_of_illness.gohtml @@ -20,8 +20,8 @@ Onset Date: Condition.onsetDateTime || Condition.onsetPeriod.start && “-“ && {{- /*gotype: github.com/fastenhealth/fasten-onprem/backend/pkg/utils/ips.NarrativeTemplateData*/ -}} {{range $index, $entry := .Condition }} - {{pluckList "text" ($entry.Code | parseList) | uniq | join "," }} {{/* Medical Problem */}} - {{pluckList "code" ($entry.ClinicalStatus | parseList) | uniq | join "," }} {{/* Status */}} + {{pluckList "text" ($entry.Code | parseMapList) | uniq | join "," }} {{/* Medical Problem */}} + {{pluckList "code" ($entry.ClinicalStatus | parseMapList) | uniq | join "," }} {{/* Status */}} Comments {{/* Comments - TODO: use FHIRPath */}} {{$entry.OnsetDate | date "2006-01-02"}} {{/* Onset */}} diff --git a/backend/pkg/utils/ips/templates/history_of_procedures.gohtml b/backend/pkg/utils/ips/templates/history_of_procedures.gohtml index 29eadf369..e985b792c 100644 --- a/backend/pkg/utils/ips/templates/history_of_procedures.gohtml +++ b/backend/pkg/utils/ips/templates/history_of_procedures.gohtml @@ -19,7 +19,7 @@ Date: Procedure.performedDateTime || Procedure.performedPeriod.start && “-“ {{- /*gotype: github.com/fastenhealth/fasten-onprem/backend/pkg/utils/ips.NarrativeTemplateData*/ -}} {{range $index, $entry := .Procedure }} - {{pluckList "text" ($entry.Code | parseList) | uniq | join "," }} {{/* Procedure */}} + {{pluckList "text" ($entry.Code | parseMapList) | uniq | join "," }} {{/* Procedure */}} Comments {{/* Comments - TODO: use FHIRPath */}} {{$entry.Date | date "2006-01-02"}} {{/* Performed Date */}} diff --git a/backend/pkg/utils/ips/templates/immunizations.gohtml b/backend/pkg/utils/ips/templates/immunizations.gohtml index 748ad7300..e782ce87d 100644 --- a/backend/pkg/utils/ips/templates/immunizations.gohtml +++ b/backend/pkg/utils/ips/templates/immunizations.gohtml @@ -27,10 +27,10 @@ Date: Immunization.occurrenceDateTime || Immunization.occurrenceString {{- /*gotype: github.com/fastenhealth/fasten-onprem/backend/pkg/utils/ips.NarrativeTemplateData*/ -}} {{range $index, $entry := .Immunization }} - {{pluckList "text" ($entry.VaccineCode | parseList) | uniq | join "," }} {{/* Immunization */}} - {{pluckList "code" ($entry.Status | parseList) | uniq | join "," }} {{/* Status */}} + {{pluckList "text" ($entry.VaccineCode | parseMapList) | uniq | join "," }} {{/* Immunization */}} + {{pluckList "code" ($entry.Status | parseMapList) | uniq | join "," }} {{/* Status */}} Dose Number {{/* Comments - TODO: use FHIRPath */}} - {{pluckList "display" ($entry.Manufacturer | parseList) | uniq | join "," }} {{/* Manufacturer */}} + {{pluckList "display" ($entry.Manufacturer | parseMapList) | uniq | join "," }} {{/* Manufacturer */}} {{$entry.LotNumber}} {{/* Lot Number */}} Comments {{$entry.Date | date "2006-01-02"}} {{/* Performed Date */}} diff --git a/backend/pkg/utils/ips/templates/includes/observation-unit.gohtml b/backend/pkg/utils/ips/templates/includes/observation-unit.gohtml index 10a0de7c5..b40409039 100644 --- a/backend/pkg/utils/ips/templates/includes/observation-unit.gohtml +++ b/backend/pkg/utils/ips/templates/includes/observation-unit.gohtml @@ -1,11 +1,11 @@ -{{if not (empty .ValueString) }} +{{if not (empty (.ValueString | parseMapList)) }} {{.ValueString}} -{{else if not (empty (.ValueQuantity | parseList)) }} - {{.ValueQuantity | parseList | pluckList "unit" | join "," }} +{{else if not (empty (.ValueQuantity | parseMapList)) }} + {{.ValueQuantity | parseMapList | pluckList "unit" | join "," }} {{else if not (empty .ValueDate) }} {{.ValueDate | date "2006-01-02" }} -{{else if not (empty (.ValueConcept | parseList)) }} +{{else if not (empty (.ValueConcept | parseMapList)) }} {{.ValueConcept}} -{{else if not (empty (.ComponentValueQuantity | parseList)) }} - {{.ComponentValueQuantity | parseList | pluckList "unit" | join "," }} +{{else if not (empty (.ComponentValueQuantity | parseMapList)) }} + {{.ComponentValueQuantity | parseMapList | pluckList "unit" | join "," }} {{end}} diff --git a/backend/pkg/utils/ips/templates/includes/observation-value.gohtml b/backend/pkg/utils/ips/templates/includes/observation-value.gohtml index c57d17bbf..c92aa81f5 100644 --- a/backend/pkg/utils/ips/templates/includes/observation-value.gohtml +++ b/backend/pkg/utils/ips/templates/includes/observation-value.gohtml @@ -1,23 +1,27 @@ -{{if not (empty .entry.ValueString) }} - {{.ValueString}} -{{else if not (empty (.entry.ValueQuantity | parseList)) }} - {{.entry.ValueQuantity | parseList | pluckList "value" | roundList 2 | join "," }} +{{if not (empty (.entry.ValueString | parseMapList)) }} + {{.entry.ValueString | parseStringList | join ","}} +{{else if not (empty (.entry.ValueQuantity | parseMapList)) }} + {{.entry.ValueQuantity | parseMapList | pluckList "value" | roundList 2 | join "," }} {{if (get . "include_unit")}} - {{.entry.ValueQuantity | parseList | pluckList "unit" | join "," }} + {{.entry.ValueQuantity | parseMapList | pluckList "unit" | join "," }} {{end}} {{else if not (empty .entry.ValueDate) }} {{.entry.ValueDate | date "2006-01-02" }} -{{else if not (empty (.entry.ValueConcept | parseList)) }} +{{else if not (empty (.entry.ValueConcept | parseMapList)) }} {{.entry.ValueConcept}} -{{else if not (empty (.entry.ComponentValueQuantity | parseList)) }} - {{$componentCodeText := $.entry.ComponentCode | parseList | pluckList "text" }} - {{$componentValueQuantity := $.entry.ComponentValueQuantity | parseList | pluckList "value" | roundList 2 }} +{{else if not (empty (.entry.ComponentValueQuantity | parseMapList)) }} + {{$componentCodeText := .entry.ComponentCode | parseMapList | pluckList "text" }} + {{$componentValueQuantity := .entry.ComponentValueQuantity | parseMapList | pluckList "value" | roundList 2 }} + {{$componentValueQuantityUnit := .entry.ComponentValueQuantity | parseMapList | pluckList "unit" }} + {{range $index, $text := $componentCodeText }} {{$text}} - {{index $componentValueQuantity $index}} + {{if (get $ "include_unit")}} + {{index $componentValueQuantityUnit $index}} + {{end}} +
{{end}} - {{if (get . "include_unit")}} - {{.ComponentValueQuantity | parseList | pluckList "unit" | join "," }} - {{end}} + {{end}} diff --git a/backend/pkg/utils/ips/templates/medical_devices.gohtml b/backend/pkg/utils/ips/templates/medical_devices.gohtml index d237d73e7..86421f7e5 100644 --- a/backend/pkg/utils/ips/templates/medical_devices.gohtml +++ b/backend/pkg/utils/ips/templates/medical_devices.gohtml @@ -20,8 +20,8 @@ Date Recorded: DeviceUseStatement.recordedDateTime {{- /*gotype: github.com/fastenhealth/fasten-onprem/backend/pkg/utils/ips.NarrativeTemplateData*/ -}} {{range $index, $entry := .Device }} - {{pluckList "text" ($entry.Type | parseList) | uniq | join "," }} {{/* Device */}} - {{pluckList "code" ($entry.Status | parseList) | uniq | join "," }} {{/* Status */}} + {{pluckList "text" ($entry.Type | parseMapList) | uniq | join "," }} {{/* Device */}} + {{pluckList "code" ($entry.Status | parseMapList) | uniq | join "," }} {{/* Status */}} Comments {{/* Date Recorded */}} diff --git a/backend/pkg/utils/ips/templates/plan_of_care.gohtml b/backend/pkg/utils/ips/templates/plan_of_care.gohtml index 8acc170aa..a88e45d34 100644 --- a/backend/pkg/utils/ips/templates/plan_of_care.gohtml +++ b/backend/pkg/utils/ips/templates/plan_of_care.gohtml @@ -23,7 +23,7 @@ Planned End: CarePlan.period.end {{range $index, $entry := .CarePlan }} Activity - {{pluckList "code" ($entry.Intent | parseList) | uniq | join "," }} {{/* Intent */}} + {{pluckList "code" ($entry.Intent | parseMapList) | uniq | join "," }} {{/* Intent */}} Comments {{$entry.Date}}{{/* Planned Start */}} Planned End diff --git a/backend/pkg/utils/ips/templates/pregnancy.gohtml b/backend/pkg/utils/ips/templates/pregnancy.gohtml index 8e9dd53a0..01cc7fd6f 100644 --- a/backend/pkg/utils/ips/templates/pregnancy.gohtml +++ b/backend/pkg/utils/ips/templates/pregnancy.gohtml @@ -20,7 +20,7 @@ Date: Observation.effectiveDateTime || Observation.effectivePeriod.start {{- /*gotype: github.com/fastenhealth/fasten-onprem/backend/pkg/utils/ips.NarrativeTemplateData*/ -}} {{range $index, $entry := .Observation }} - {{pluckList "text" ($entry.Code | parseList) | uniq | join "," }} {{/* Code */}} + {{pluckList "text" ($entry.Code | parseMapList) | uniq | join "," }} {{/* Code */}} {{template "observation-value.gohtml" (dict "entry" $entry "include_unit" true)}} {{/* Result */}} Comments {{$entry.Date | date "2006-01-02"}} {{/* Date */}} diff --git a/backend/pkg/utils/ips/templates/problem_list.gohtml b/backend/pkg/utils/ips/templates/problem_list.gohtml index 8abae8091..42f5055ee 100644 --- a/backend/pkg/utils/ips/templates/problem_list.gohtml +++ b/backend/pkg/utils/ips/templates/problem_list.gohtml @@ -20,8 +20,8 @@ Onset Date: Condition.onsetDateTime || Condition.onsetPeriod.start && “-“ && {{- /*gotype: github.com/fastenhealth/fasten-onprem/backend/pkg/utils/ips.NarrativeTemplateData*/ -}} {{range $index, $entry := .Condition }} - {{pluckList "text" ($entry.Code | parseList) | uniq | join "," }} {{/* Medical Problems */}} - {{pluckList "code" ($entry.ClinicalStatus | parseList) | uniq | join "," }} {{/* Status */}} + {{pluckList "text" ($entry.Code | parseMapList) | uniq | join "," }} {{/* Medical Problems */}} + {{pluckList "code" ($entry.ClinicalStatus | parseMapList) | uniq | join "," }} {{/* Status */}} Comments {{$entry.OnsetDate | date "2006-01-02"}} {{/* Onset */}} diff --git a/backend/pkg/utils/ips/templates/social_history.gohtml b/backend/pkg/utils/ips/templates/social_history.gohtml index 842806f9d..a7c482c75 100644 --- a/backend/pkg/utils/ips/templates/social_history.gohtml +++ b/backend/pkg/utils/ips/templates/social_history.gohtml @@ -22,7 +22,7 @@ Date: Observation.effectiveDateTime || Observation.effectivePeriod.start {{- /*gotype: github.com/fastenhealth/fasten-onprem/backend/pkg/utils/ips.NarrativeTemplateData*/ -}} {{range $index, $entry := .Observation }} - {{pluckList "text" ($entry.Code | parseList) | uniq | join "," }} {{/* Code */}} + {{pluckList "text" ($entry.Code | parseMapList) | uniq | join "," }} {{/* Code */}} {{template "observation-value.gohtml" (dict "entry" $entry "include_unit" false)}} {{/* Result */}} Unit Comments diff --git a/backend/pkg/utils/ips/templates/vital_signs.gohtml b/backend/pkg/utils/ips/templates/vital_signs.gohtml index 3176f2809..7870aca8f 100644 --- a/backend/pkg/utils/ips/templates/vital_signs.gohtml +++ b/backend/pkg/utils/ips/templates/vital_signs.gohtml @@ -25,7 +25,7 @@ Date: Observation.effectiveDateTime || Observation.effectivePeriod.start {{- /*gotype: github.com/fastenhealth/fasten-onprem/backend/pkg/utils/ips.NarrativeTemplateData*/ -}} {{range $index, $entry := .Observation }} - {{pluckList "text" ($entry.Code | parseList) | uniq | join "," }} {{/* Code */}} + {{pluckList "text" ($entry.Code | parseMapList) | uniq | join "," }} {{/* Code */}} {{template "observation-value.gohtml" (dict "entry" $entry "include_unit" false)}} {{/* Result */}} {{template "observation-unit.gohtml" $entry}} Interpretation From 99317bc71c4b62812cfe9efb89f5c2b2a0ec8b41 Mon Sep 17 00:00:00 2001 From: Jason Kulatunga Date: Sun, 3 Mar 2024 15:37:40 -0800 Subject: [PATCH 25/29] safer handling of componentValueQuantity. --- .../ips/templates/includes/observation-value.gohtml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/backend/pkg/utils/ips/templates/includes/observation-value.gohtml b/backend/pkg/utils/ips/templates/includes/observation-value.gohtml index c92aa81f5..cdfc74632 100644 --- a/backend/pkg/utils/ips/templates/includes/observation-value.gohtml +++ b/backend/pkg/utils/ips/templates/includes/observation-value.gohtml @@ -16,9 +16,14 @@ {{range $index, $text := $componentCodeText }} - {{$text}} - {{index $componentValueQuantity $index}} + {{$text}} + {{if lt $index (len $componentValueQuantity)}} + - {{index $componentValueQuantity $index}} + {{end}} {{if (get $ "include_unit")}} - {{index $componentValueQuantityUnit $index}} + {{if lt $index (len $componentValueQuantityUnit)}} + {{index $componentValueQuantityUnit $index}} + {{end}} {{end}}
{{end}} From 182d56fb8817132a0818c9ef75c6f1a04f235dc3 Mon Sep 17 00:00:00 2001 From: Jason Kulatunga Date: Tue, 5 Mar 2024 15:32:17 -0800 Subject: [PATCH 26/29] correctly extract existing Text field data. --- backend/pkg/models/database/fhir_account.go | 10 +++++----- backend/pkg/models/database/fhir_adverse_event.go | 10 +++++----- .../pkg/models/database/fhir_allergy_intolerance.go | 10 +++++----- backend/pkg/models/database/fhir_appointment.go | 10 +++++----- backend/pkg/models/database/fhir_binary.go | 10 +++++----- backend/pkg/models/database/fhir_care_plan.go | 10 +++++----- backend/pkg/models/database/fhir_care_team.go | 10 +++++----- backend/pkg/models/database/fhir_claim.go | 10 +++++----- backend/pkg/models/database/fhir_claim_response.go | 10 +++++----- backend/pkg/models/database/fhir_composition.go | 10 +++++----- backend/pkg/models/database/fhir_condition.go | 10 +++++----- backend/pkg/models/database/fhir_consent.go | 10 +++++----- backend/pkg/models/database/fhir_coverage.go | 10 +++++----- .../database/fhir_coverage_eligibility_request.go | 10 +++++----- .../database/fhir_coverage_eligibility_response.go | 10 +++++----- backend/pkg/models/database/fhir_device.go | 10 +++++----- backend/pkg/models/database/fhir_device_request.go | 10 +++++----- backend/pkg/models/database/fhir_diagnostic_report.go | 10 +++++----- backend/pkg/models/database/fhir_document_manifest.go | 10 +++++----- backend/pkg/models/database/fhir_document_reference.go | 10 +++++----- backend/pkg/models/database/fhir_encounter.go | 10 +++++----- backend/pkg/models/database/fhir_endpoint.go | 10 +++++----- backend/pkg/models/database/fhir_enrollment_request.go | 10 +++++----- .../pkg/models/database/fhir_enrollment_response.go | 10 +++++----- .../pkg/models/database/fhir_explanation_of_benefit.go | 10 +++++----- .../pkg/models/database/fhir_family_member_history.go | 10 +++++----- backend/pkg/models/database/fhir_goal.go | 10 +++++----- backend/pkg/models/database/fhir_imaging_study.go | 10 +++++----- backend/pkg/models/database/fhir_immunization.go | 10 +++++----- backend/pkg/models/database/fhir_insurance_plan.go | 10 +++++----- backend/pkg/models/database/fhir_location.go | 10 +++++----- backend/pkg/models/database/fhir_media.go | 10 +++++----- backend/pkg/models/database/fhir_medication.go | 10 +++++----- .../models/database/fhir_medication_administration.go | 10 +++++----- .../pkg/models/database/fhir_medication_dispense.go | 10 +++++----- backend/pkg/models/database/fhir_medication_request.go | 10 +++++----- .../pkg/models/database/fhir_medication_statement.go | 10 +++++----- backend/pkg/models/database/fhir_nutrition_order.go | 10 +++++----- backend/pkg/models/database/fhir_observation.go | 10 +++++----- backend/pkg/models/database/fhir_organization.go | 10 +++++----- .../models/database/fhir_organization_affiliation.go | 10 +++++----- backend/pkg/models/database/fhir_patient.go | 10 +++++----- backend/pkg/models/database/fhir_person.go | 10 +++++----- backend/pkg/models/database/fhir_practitioner.go | 10 +++++----- backend/pkg/models/database/fhir_practitioner_role.go | 10 +++++----- backend/pkg/models/database/fhir_procedure.go | 10 +++++----- backend/pkg/models/database/fhir_provenance.go | 10 +++++----- backend/pkg/models/database/fhir_questionnaire.go | 10 +++++----- .../pkg/models/database/fhir_questionnaire_response.go | 10 +++++----- backend/pkg/models/database/fhir_related_person.go | 10 +++++----- backend/pkg/models/database/fhir_schedule.go | 10 +++++----- backend/pkg/models/database/fhir_service_request.go | 10 +++++----- backend/pkg/models/database/fhir_slot.go | 10 +++++----- backend/pkg/models/database/fhir_specimen.go | 10 +++++----- .../pkg/models/database/fhir_vision_prescription.go | 10 +++++----- backend/pkg/models/database/generate.go | 2 +- .../pkg/models/database/searchParameterExtractor.js | 3 +++ 57 files changed, 279 insertions(+), 276 deletions(-) diff --git a/backend/pkg/models/database/fhir_account.go b/backend/pkg/models/database/fhir_account.go index 473d0eb91..e66523222 100644 --- a/backend/pkg/models/database/fhir_account.go +++ b/backend/pkg/models/database/fhir_account.go @@ -48,8 +48,8 @@ type FhirAccount struct { // https://hl7.org/fhir/r4/search.html#reference Subject datatypes.JSON `gorm:"column:subject;type:text;serializer:json" json:"subject,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` // E.g. patient, expense, depreciation // https://hl7.org/fhir/r4/search.html#token Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` @@ -74,7 +74,7 @@ func (s *FhirAccount) GetSearchParameters() map[string]string { "source_uri": "keyword", "status": "token", "subject": "reference", - "text": "keyword", + "text": "string", "type": "token", } return searchParameters @@ -188,9 +188,9 @@ func (s *FhirAccount) PopulateAndExtractSearchParameters(resourceRaw json.RawMes s.Subject = []byte(subjectResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } // extracting Type typeResult, err := vm.RunString("extractTokenSearchParameters(fhirResource, 'Account.type')") diff --git a/backend/pkg/models/database/fhir_adverse_event.go b/backend/pkg/models/database/fhir_adverse_event.go index 426b09b89..d675c3565 100644 --- a/backend/pkg/models/database/fhir_adverse_event.go +++ b/backend/pkg/models/database/fhir_adverse_event.go @@ -66,8 +66,8 @@ type FhirAdverseEvent struct { // https://hl7.org/fhir/r4/search.html#reference Substance datatypes.JSON `gorm:"column:substance;type:text;serializer:json" json:"substance,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` } func (s *FhirAdverseEvent) GetSearchParameters() map[string]string { @@ -95,7 +95,7 @@ func (s *FhirAdverseEvent) GetSearchParameters() map[string]string { "study": "reference", "subject": "reference", "substance": "reference", - "text": "keyword", + "text": "string", } return searchParameters } @@ -238,9 +238,9 @@ func (s *FhirAdverseEvent) PopulateAndExtractSearchParameters(resourceRaw json.R s.Substance = []byte(substanceResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } return nil } diff --git a/backend/pkg/models/database/fhir_allergy_intolerance.go b/backend/pkg/models/database/fhir_allergy_intolerance.go index cec522d38..10fde6c04 100644 --- a/backend/pkg/models/database/fhir_allergy_intolerance.go +++ b/backend/pkg/models/database/fhir_allergy_intolerance.go @@ -139,8 +139,8 @@ type FhirAllergyIntolerance struct { // https://hl7.org/fhir/r4/search.html#token Severity datatypes.JSON `gorm:"column:severity;type:text;serializer:json" json:"severity,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` /* Multiple Resources: @@ -184,7 +184,7 @@ func (s *FhirAllergyIntolerance) GetSearchParameters() map[string]string { "source_resource_id": "keyword", "source_resource_type": "keyword", "source_uri": "keyword", - "text": "keyword", + "text": "string", "type": "token", "verificationStatus": "token", } @@ -350,9 +350,9 @@ func (s *FhirAllergyIntolerance) PopulateAndExtractSearchParameters(resourceRaw s.Severity = []byte(severityResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } // extracting Type typeResult, err := vm.RunString("extractTokenSearchParameters(fhirResource, 'AllergyIntolerance.type | Composition.type | DocumentManifest.type | DocumentReference.type | Encounter.type | EpisodeOfCare.type')") diff --git a/backend/pkg/models/database/fhir_appointment.go b/backend/pkg/models/database/fhir_appointment.go index c832a0f86..8b38a3974 100644 --- a/backend/pkg/models/database/fhir_appointment.go +++ b/backend/pkg/models/database/fhir_appointment.go @@ -78,8 +78,8 @@ type FhirAppointment struct { // https://hl7.org/fhir/r4/search.html#reference SupportingInfo datatypes.JSON `gorm:"column:supportingInfo;type:text;serializer:json" json:"supportingInfo,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` } func (s *FhirAppointment) GetSearchParameters() map[string]string { @@ -111,7 +111,7 @@ func (s *FhirAppointment) GetSearchParameters() map[string]string { "specialty": "token", "status": "token", "supportingInfo": "reference", - "text": "keyword", + "text": "string", } return searchParameters } @@ -274,9 +274,9 @@ func (s *FhirAppointment) PopulateAndExtractSearchParameters(resourceRaw json.Ra s.SupportingInfo = []byte(supportingInfoResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } return nil } diff --git a/backend/pkg/models/database/fhir_binary.go b/backend/pkg/models/database/fhir_binary.go index 16ec0da03..b1128462f 100644 --- a/backend/pkg/models/database/fhir_binary.go +++ b/backend/pkg/models/database/fhir_binary.go @@ -30,8 +30,8 @@ type FhirBinary struct { // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific MetaVersionId string `gorm:"column:metaVersionId;type:text" json:"metaVersionId,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` } func (s *FhirBinary) GetSearchParameters() map[string]string { @@ -47,7 +47,7 @@ func (s *FhirBinary) GetSearchParameters() map[string]string { "source_resource_id": "keyword", "source_resource_type": "keyword", "source_uri": "keyword", - "text": "keyword", + "text": "string", } return searchParameters } @@ -122,9 +122,9 @@ func (s *FhirBinary) PopulateAndExtractSearchParameters(resourceRaw json.RawMess s.MetaVersionId = metaVersionIdResult.String() } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } return nil } diff --git a/backend/pkg/models/database/fhir_care_plan.go b/backend/pkg/models/database/fhir_care_plan.go index bca545e51..a03c4ca3c 100644 --- a/backend/pkg/models/database/fhir_care_plan.go +++ b/backend/pkg/models/database/fhir_care_plan.go @@ -140,8 +140,8 @@ type FhirCarePlan struct { // https://hl7.org/fhir/r4/search.html#reference Subject datatypes.JSON `gorm:"column:subject;type:text;serializer:json" json:"subject,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` } func (s *FhirCarePlan) GetSearchParameters() map[string]string { @@ -176,7 +176,7 @@ func (s *FhirCarePlan) GetSearchParameters() map[string]string { "source_uri": "keyword", "status": "token", "subject": "reference", - "text": "keyword", + "text": "string", } return searchParameters } @@ -362,9 +362,9 @@ func (s *FhirCarePlan) PopulateAndExtractSearchParameters(resourceRaw json.RawMe s.Subject = []byte(subjectResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } return nil } diff --git a/backend/pkg/models/database/fhir_care_team.go b/backend/pkg/models/database/fhir_care_team.go index 4c0808f92..c0e2e63cd 100644 --- a/backend/pkg/models/database/fhir_care_team.go +++ b/backend/pkg/models/database/fhir_care_team.go @@ -104,8 +104,8 @@ type FhirCareTeam struct { // https://hl7.org/fhir/r4/search.html#reference Subject datatypes.JSON `gorm:"column:subject;type:text;serializer:json" json:"subject,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` } func (s *FhirCareTeam) GetSearchParameters() map[string]string { @@ -128,7 +128,7 @@ func (s *FhirCareTeam) GetSearchParameters() map[string]string { "source_uri": "keyword", "status": "token", "subject": "reference", - "text": "keyword", + "text": "string", } return searchParameters } @@ -246,9 +246,9 @@ func (s *FhirCareTeam) PopulateAndExtractSearchParameters(resourceRaw json.RawMe s.Subject = []byte(subjectResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } return nil } diff --git a/backend/pkg/models/database/fhir_claim.go b/backend/pkg/models/database/fhir_claim.go index 4e931816f..e04c25062 100644 --- a/backend/pkg/models/database/fhir_claim.go +++ b/backend/pkg/models/database/fhir_claim.go @@ -75,8 +75,8 @@ type FhirClaim struct { // https://hl7.org/fhir/r4/search.html#reference SubdetailUdi datatypes.JSON `gorm:"column:subdetailUdi;type:text;serializer:json" json:"subdetailUdi,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` // The kind of financial resource // https://hl7.org/fhir/r4/search.html#token Use datatypes.JSON `gorm:"column:use;type:text;serializer:json" json:"use,omitempty"` @@ -110,7 +110,7 @@ func (s *FhirClaim) GetSearchParameters() map[string]string { "source_uri": "keyword", "status": "token", "subdetailUdi": "reference", - "text": "keyword", + "text": "string", "use": "token", } return searchParameters @@ -269,9 +269,9 @@ func (s *FhirClaim) PopulateAndExtractSearchParameters(resourceRaw json.RawMessa s.SubdetailUdi = []byte(subdetailUdiResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } // extracting Use useResult, err := vm.RunString("extractTokenSearchParameters(fhirResource, 'Claim.use')") diff --git a/backend/pkg/models/database/fhir_claim_response.go b/backend/pkg/models/database/fhir_claim_response.go index b43ba8826..0d5f096d5 100644 --- a/backend/pkg/models/database/fhir_claim_response.go +++ b/backend/pkg/models/database/fhir_claim_response.go @@ -57,8 +57,8 @@ type FhirClaimResponse struct { // https://hl7.org/fhir/r4/search.html#token Status datatypes.JSON `gorm:"column:status;type:text;serializer:json" json:"status,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` // The type of claim // https://hl7.org/fhir/r4/search.html#token Use datatypes.JSON `gorm:"column:use;type:text;serializer:json" json:"use,omitempty"` @@ -86,7 +86,7 @@ func (s *FhirClaimResponse) GetSearchParameters() map[string]string { "source_resource_type": "keyword", "source_uri": "keyword", "status": "token", - "text": "keyword", + "text": "string", "use": "token", } return searchParameters @@ -223,9 +223,9 @@ func (s *FhirClaimResponse) PopulateAndExtractSearchParameters(resourceRaw json. s.Status = []byte(statusResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } // extracting Use useResult, err := vm.RunString("extractTokenSearchParameters(fhirResource, 'ClaimResponse.use')") diff --git a/backend/pkg/models/database/fhir_composition.go b/backend/pkg/models/database/fhir_composition.go index 9983f162b..482175d73 100644 --- a/backend/pkg/models/database/fhir_composition.go +++ b/backend/pkg/models/database/fhir_composition.go @@ -143,8 +143,8 @@ type FhirComposition struct { // https://hl7.org/fhir/r4/search.html#reference Subject datatypes.JSON `gorm:"column:subject;type:text;serializer:json" json:"subject,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` // Human Readable name/title // https://hl7.org/fhir/r4/search.html#string Title datatypes.JSON `gorm:"column:title;type:text;serializer:json" json:"title,omitempty"` @@ -190,7 +190,7 @@ func (s *FhirComposition) GetSearchParameters() map[string]string { "source_uri": "keyword", "status": "token", "subject": "reference", - "text": "keyword", + "text": "string", "title": "string", "type": "token", } @@ -358,9 +358,9 @@ func (s *FhirComposition) PopulateAndExtractSearchParameters(resourceRaw json.Ra s.Subject = []byte(subjectResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } // extracting Title titleResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'Composition.title')") diff --git a/backend/pkg/models/database/fhir_condition.go b/backend/pkg/models/database/fhir_condition.go index 622659ce0..30285808b 100644 --- a/backend/pkg/models/database/fhir_condition.go +++ b/backend/pkg/models/database/fhir_condition.go @@ -137,8 +137,8 @@ type FhirCondition struct { // https://hl7.org/fhir/r4/search.html#reference Subject datatypes.JSON `gorm:"column:subject;type:text;serializer:json" json:"subject,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` // unconfirmed | provisional | differential | confirmed | refuted | entered-in-error // https://hl7.org/fhir/r4/search.html#token VerificationStatus datatypes.JSON `gorm:"column:verificationStatus;type:text;serializer:json" json:"verificationStatus,omitempty"` @@ -176,7 +176,7 @@ func (s *FhirCondition) GetSearchParameters() map[string]string { "source_uri": "keyword", "stage": "token", "subject": "reference", - "text": "keyword", + "text": "string", "verificationStatus": "token", } return searchParameters @@ -371,9 +371,9 @@ func (s *FhirCondition) PopulateAndExtractSearchParameters(resourceRaw json.RawM s.Subject = []byte(subjectResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } // extracting VerificationStatus verificationStatusResult, err := vm.RunString("extractTokenSearchParameters(fhirResource, 'Condition.verificationStatus')") diff --git a/backend/pkg/models/database/fhir_consent.go b/backend/pkg/models/database/fhir_consent.go index e08abcfc2..d85668c6b 100644 --- a/backend/pkg/models/database/fhir_consent.go +++ b/backend/pkg/models/database/fhir_consent.go @@ -125,8 +125,8 @@ type FhirConsent struct { // https://hl7.org/fhir/r4/search.html#token Status datatypes.JSON `gorm:"column:status;type:text;serializer:json" json:"status,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` } func (s *FhirConsent) GetSearchParameters() map[string]string { @@ -156,7 +156,7 @@ func (s *FhirConsent) GetSearchParameters() map[string]string { "source_resource_type": "keyword", "source_uri": "keyword", "status": "token", - "text": "keyword", + "text": "string", } return searchParameters } @@ -317,9 +317,9 @@ func (s *FhirConsent) PopulateAndExtractSearchParameters(resourceRaw json.RawMes s.Status = []byte(statusResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } return nil } diff --git a/backend/pkg/models/database/fhir_coverage.go b/backend/pkg/models/database/fhir_coverage.go index c5d8900cd..d34c3ed9e 100644 --- a/backend/pkg/models/database/fhir_coverage.go +++ b/backend/pkg/models/database/fhir_coverage.go @@ -57,8 +57,8 @@ type FhirCoverage struct { // https://hl7.org/fhir/r4/search.html#reference Subscriber datatypes.JSON `gorm:"column:subscriber;type:text;serializer:json" json:"subscriber,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` // The kind of coverage (health plan, auto, Workers Compensation) // https://hl7.org/fhir/r4/search.html#token Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` @@ -86,7 +86,7 @@ func (s *FhirCoverage) GetSearchParameters() map[string]string { "source_uri": "keyword", "status": "token", "subscriber": "reference", - "text": "keyword", + "text": "string", "type": "token", } return searchParameters @@ -207,9 +207,9 @@ func (s *FhirCoverage) PopulateAndExtractSearchParameters(resourceRaw json.RawMe s.Subscriber = []byte(subscriberResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } // extracting Type typeResult, err := vm.RunString("extractTokenSearchParameters(fhirResource, 'Coverage.type')") diff --git a/backend/pkg/models/database/fhir_coverage_eligibility_request.go b/backend/pkg/models/database/fhir_coverage_eligibility_request.go index de1f4d707..fdec2eb5e 100644 --- a/backend/pkg/models/database/fhir_coverage_eligibility_request.go +++ b/backend/pkg/models/database/fhir_coverage_eligibility_request.go @@ -48,8 +48,8 @@ type FhirCoverageEligibilityRequest struct { // https://hl7.org/fhir/r4/search.html#token Status datatypes.JSON `gorm:"column:status;type:text;serializer:json" json:"status,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` } func (s *FhirCoverageEligibilityRequest) GetSearchParameters() map[string]string { @@ -71,7 +71,7 @@ func (s *FhirCoverageEligibilityRequest) GetSearchParameters() map[string]string "source_resource_type": "keyword", "source_uri": "keyword", "status": "token", - "text": "keyword", + "text": "string", } return searchParameters } @@ -184,9 +184,9 @@ func (s *FhirCoverageEligibilityRequest) PopulateAndExtractSearchParameters(reso s.Status = []byte(statusResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } return nil } diff --git a/backend/pkg/models/database/fhir_coverage_eligibility_response.go b/backend/pkg/models/database/fhir_coverage_eligibility_response.go index fe8b650b8..139e708fd 100644 --- a/backend/pkg/models/database/fhir_coverage_eligibility_response.go +++ b/backend/pkg/models/database/fhir_coverage_eligibility_response.go @@ -54,8 +54,8 @@ type FhirCoverageEligibilityResponse struct { // https://hl7.org/fhir/r4/search.html#token Status datatypes.JSON `gorm:"column:status;type:text;serializer:json" json:"status,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` } func (s *FhirCoverageEligibilityResponse) GetSearchParameters() map[string]string { @@ -79,7 +79,7 @@ func (s *FhirCoverageEligibilityResponse) GetSearchParameters() map[string]strin "source_resource_type": "keyword", "source_uri": "keyword", "status": "token", - "text": "keyword", + "text": "string", } return searchParameters } @@ -202,9 +202,9 @@ func (s *FhirCoverageEligibilityResponse) PopulateAndExtractSearchParameters(res s.Status = []byte(statusResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } return nil } diff --git a/backend/pkg/models/database/fhir_device.go b/backend/pkg/models/database/fhir_device.go index 11bc48d08..c07443642 100644 --- a/backend/pkg/models/database/fhir_device.go +++ b/backend/pkg/models/database/fhir_device.go @@ -51,8 +51,8 @@ type FhirDevice struct { // https://hl7.org/fhir/r4/search.html#token Status datatypes.JSON `gorm:"column:status;type:text;serializer:json" json:"status,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` // The type of the device // https://hl7.org/fhir/r4/search.html#token Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` @@ -87,7 +87,7 @@ func (s *FhirDevice) GetSearchParameters() map[string]string { "source_resource_type": "keyword", "source_uri": "keyword", "status": "token", - "text": "keyword", + "text": "string", "type": "token", "udiCarrier": "string", "udiDi": "string", @@ -201,9 +201,9 @@ func (s *FhirDevice) PopulateAndExtractSearchParameters(resourceRaw json.RawMess s.Status = []byte(statusResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } // extracting Type typeResult, err := vm.RunString("extractTokenSearchParameters(fhirResource, 'Device.type')") diff --git a/backend/pkg/models/database/fhir_device_request.go b/backend/pkg/models/database/fhir_device_request.go index 201aff511..c4ae5eef4 100644 --- a/backend/pkg/models/database/fhir_device_request.go +++ b/backend/pkg/models/database/fhir_device_request.go @@ -146,8 +146,8 @@ type FhirDeviceRequest struct { // https://hl7.org/fhir/r4/search.html#reference Subject datatypes.JSON `gorm:"column:subject;type:text;serializer:json" json:"subject,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` } func (s *FhirDeviceRequest) GetSearchParameters() map[string]string { @@ -180,7 +180,7 @@ func (s *FhirDeviceRequest) GetSearchParameters() map[string]string { "source_uri": "keyword", "status": "token", "subject": "reference", - "text": "keyword", + "text": "string", } return searchParameters } @@ -356,9 +356,9 @@ func (s *FhirDeviceRequest) PopulateAndExtractSearchParameters(resourceRaw json. s.Subject = []byte(subjectResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } return nil } diff --git a/backend/pkg/models/database/fhir_diagnostic_report.go b/backend/pkg/models/database/fhir_diagnostic_report.go index 752164cd8..f9a4e34bf 100644 --- a/backend/pkg/models/database/fhir_diagnostic_report.go +++ b/backend/pkg/models/database/fhir_diagnostic_report.go @@ -160,8 +160,8 @@ type FhirDiagnosticReport struct { // https://hl7.org/fhir/r4/search.html#reference Subject datatypes.JSON `gorm:"column:subject;type:text;serializer:json" json:"subject,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` } func (s *FhirDiagnosticReport) GetSearchParameters() map[string]string { @@ -192,7 +192,7 @@ func (s *FhirDiagnosticReport) GetSearchParameters() map[string]string { "specimen": "reference", "status": "token", "subject": "reference", - "text": "keyword", + "text": "string", } return searchParameters } @@ -358,9 +358,9 @@ func (s *FhirDiagnosticReport) PopulateAndExtractSearchParameters(resourceRaw js s.Subject = []byte(subjectResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } return nil } diff --git a/backend/pkg/models/database/fhir_document_manifest.go b/backend/pkg/models/database/fhir_document_manifest.go index e9d8f88e0..0d3612522 100644 --- a/backend/pkg/models/database/fhir_document_manifest.go +++ b/backend/pkg/models/database/fhir_document_manifest.go @@ -96,8 +96,8 @@ type FhirDocumentManifest struct { // https://hl7.org/fhir/r4/search.html#reference Subject datatypes.JSON `gorm:"column:subject;type:text;serializer:json" json:"subject,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` /* Multiple Resources: @@ -136,7 +136,7 @@ func (s *FhirDocumentManifest) GetSearchParameters() map[string]string { "source_uri": "keyword", "status": "token", "subject": "reference", - "text": "keyword", + "text": "string", "type": "token", } return searchParameters @@ -275,9 +275,9 @@ func (s *FhirDocumentManifest) PopulateAndExtractSearchParameters(resourceRaw js s.Subject = []byte(subjectResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } // extracting Type typeResult, err := vm.RunString("extractTokenSearchParameters(fhirResource, 'AllergyIntolerance.type | Composition.type | DocumentManifest.type | DocumentReference.type | Encounter.type | EpisodeOfCare.type')") diff --git a/backend/pkg/models/database/fhir_document_reference.go b/backend/pkg/models/database/fhir_document_reference.go index 71dbe37a4..4fe59ef0f 100644 --- a/backend/pkg/models/database/fhir_document_reference.go +++ b/backend/pkg/models/database/fhir_document_reference.go @@ -141,8 +141,8 @@ type FhirDocumentReference struct { // https://hl7.org/fhir/r4/search.html#reference Subject datatypes.JSON `gorm:"column:subject;type:text;serializer:json" json:"subject,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` /* Multiple Resources: @@ -191,7 +191,7 @@ func (s *FhirDocumentReference) GetSearchParameters() map[string]string { "source_uri": "keyword", "status": "token", "subject": "reference", - "text": "keyword", + "text": "string", "type": "token", } return searchParameters @@ -388,9 +388,9 @@ func (s *FhirDocumentReference) PopulateAndExtractSearchParameters(resourceRaw j s.Subject = []byte(subjectResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } // extracting Type typeResult, err := vm.RunString("extractTokenSearchParameters(fhirResource, 'AllergyIntolerance.type | Composition.type | DocumentManifest.type | DocumentReference.type | Encounter.type | EpisodeOfCare.type')") diff --git a/backend/pkg/models/database/fhir_encounter.go b/backend/pkg/models/database/fhir_encounter.go index defe56baa..0ebdc0429 100644 --- a/backend/pkg/models/database/fhir_encounter.go +++ b/backend/pkg/models/database/fhir_encounter.go @@ -146,8 +146,8 @@ type FhirEncounter struct { // https://hl7.org/fhir/r4/search.html#reference Subject datatypes.JSON `gorm:"column:subject;type:text;serializer:json" json:"subject,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` /* Multiple Resources: @@ -196,7 +196,7 @@ func (s *FhirEncounter) GetSearchParameters() map[string]string { "specialArrangement": "token", "status": "token", "subject": "reference", - "text": "keyword", + "text": "string", "type": "token", } return searchParameters @@ -393,9 +393,9 @@ func (s *FhirEncounter) PopulateAndExtractSearchParameters(resourceRaw json.RawM s.Subject = []byte(subjectResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } // extracting Type typeResult, err := vm.RunString("extractTokenSearchParameters(fhirResource, 'AllergyIntolerance.type | Composition.type | DocumentManifest.type | DocumentReference.type | Encounter.type | EpisodeOfCare.type')") diff --git a/backend/pkg/models/database/fhir_endpoint.go b/backend/pkg/models/database/fhir_endpoint.go index 644622460..fcd1f3fc5 100644 --- a/backend/pkg/models/database/fhir_endpoint.go +++ b/backend/pkg/models/database/fhir_endpoint.go @@ -48,8 +48,8 @@ type FhirEndpoint struct { // https://hl7.org/fhir/r4/search.html#token Status datatypes.JSON `gorm:"column:status;type:text;serializer:json" json:"status,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` } func (s *FhirEndpoint) GetSearchParameters() map[string]string { @@ -71,7 +71,7 @@ func (s *FhirEndpoint) GetSearchParameters() map[string]string { "source_resource_type": "keyword", "source_uri": "keyword", "status": "token", - "text": "keyword", + "text": "string", } return searchParameters } @@ -176,9 +176,9 @@ func (s *FhirEndpoint) PopulateAndExtractSearchParameters(resourceRaw json.RawMe s.Status = []byte(statusResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } return nil } diff --git a/backend/pkg/models/database/fhir_enrollment_request.go b/backend/pkg/models/database/fhir_enrollment_request.go index 7bbe82b10..e8bae5209 100644 --- a/backend/pkg/models/database/fhir_enrollment_request.go +++ b/backend/pkg/models/database/fhir_enrollment_request.go @@ -39,8 +39,8 @@ type FhirEnrollmentRequest struct { // https://hl7.org/fhir/r4/search.html#reference Subject datatypes.JSON `gorm:"column:subject;type:text;serializer:json" json:"subject,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` } func (s *FhirEnrollmentRequest) GetSearchParameters() map[string]string { @@ -59,7 +59,7 @@ func (s *FhirEnrollmentRequest) GetSearchParameters() map[string]string { "source_uri": "keyword", "status": "token", "subject": "reference", - "text": "keyword", + "text": "string", } return searchParameters } @@ -149,9 +149,9 @@ func (s *FhirEnrollmentRequest) PopulateAndExtractSearchParameters(resourceRaw j s.Subject = []byte(subjectResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } return nil } diff --git a/backend/pkg/models/database/fhir_enrollment_response.go b/backend/pkg/models/database/fhir_enrollment_response.go index 7259b6db2..411b19584 100644 --- a/backend/pkg/models/database/fhir_enrollment_response.go +++ b/backend/pkg/models/database/fhir_enrollment_response.go @@ -39,8 +39,8 @@ type FhirEnrollmentResponse struct { // https://hl7.org/fhir/r4/search.html#token Status datatypes.JSON `gorm:"column:status;type:text;serializer:json" json:"status,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` } func (s *FhirEnrollmentResponse) GetSearchParameters() map[string]string { @@ -59,7 +59,7 @@ func (s *FhirEnrollmentResponse) GetSearchParameters() map[string]string { "source_resource_type": "keyword", "source_uri": "keyword", "status": "token", - "text": "keyword", + "text": "string", } return searchParameters } @@ -149,9 +149,9 @@ func (s *FhirEnrollmentResponse) PopulateAndExtractSearchParameters(resourceRaw s.Status = []byte(statusResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } return nil } diff --git a/backend/pkg/models/database/fhir_explanation_of_benefit.go b/backend/pkg/models/database/fhir_explanation_of_benefit.go index ed95a2f8b..4beee3eb9 100644 --- a/backend/pkg/models/database/fhir_explanation_of_benefit.go +++ b/backend/pkg/models/database/fhir_explanation_of_benefit.go @@ -78,8 +78,8 @@ type FhirExplanationOfBenefit struct { // https://hl7.org/fhir/r4/search.html#reference SubdetailUdi datatypes.JSON `gorm:"column:subdetailUdi;type:text;serializer:json" json:"subdetailUdi,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` } func (s *FhirExplanationOfBenefit) GetSearchParameters() map[string]string { @@ -111,7 +111,7 @@ func (s *FhirExplanationOfBenefit) GetSearchParameters() map[string]string { "source_uri": "keyword", "status": "token", "subdetailUdi": "reference", - "text": "keyword", + "text": "string", } return searchParameters } @@ -274,9 +274,9 @@ func (s *FhirExplanationOfBenefit) PopulateAndExtractSearchParameters(resourceRa s.SubdetailUdi = []byte(subdetailUdiResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } return nil } diff --git a/backend/pkg/models/database/fhir_family_member_history.go b/backend/pkg/models/database/fhir_family_member_history.go index 3e70eea76..b165f9ef3 100644 --- a/backend/pkg/models/database/fhir_family_member_history.go +++ b/backend/pkg/models/database/fhir_family_member_history.go @@ -124,8 +124,8 @@ type FhirFamilyMemberHistory struct { // https://hl7.org/fhir/r4/search.html#token Status datatypes.JSON `gorm:"column:status;type:text;serializer:json" json:"status,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` } func (s *FhirFamilyMemberHistory) GetSearchParameters() map[string]string { @@ -149,7 +149,7 @@ func (s *FhirFamilyMemberHistory) GetSearchParameters() map[string]string { "source_resource_type": "keyword", "source_uri": "keyword", "status": "token", - "text": "keyword", + "text": "string", } return searchParameters } @@ -272,9 +272,9 @@ func (s *FhirFamilyMemberHistory) PopulateAndExtractSearchParameters(resourceRaw s.Status = []byte(statusResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } return nil } diff --git a/backend/pkg/models/database/fhir_goal.go b/backend/pkg/models/database/fhir_goal.go index cc7f3f2a9..1a33e70f4 100644 --- a/backend/pkg/models/database/fhir_goal.go +++ b/backend/pkg/models/database/fhir_goal.go @@ -84,8 +84,8 @@ type FhirGoal struct { // https://hl7.org/fhir/r4/search.html#date TargetDate *time.Time `gorm:"column:targetDate;type:datetime" json:"targetDate,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` } func (s *FhirGoal) GetSearchParameters() map[string]string { @@ -108,7 +108,7 @@ func (s *FhirGoal) GetSearchParameters() map[string]string { "startDate": "date", "subject": "reference", "targetDate": "date", - "text": "keyword", + "text": "string", } return searchParameters } @@ -234,9 +234,9 @@ func (s *FhirGoal) PopulateAndExtractSearchParameters(resourceRaw json.RawMessag } } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } return nil } diff --git a/backend/pkg/models/database/fhir_imaging_study.go b/backend/pkg/models/database/fhir_imaging_study.go index 9e264afe1..fd7de4b20 100644 --- a/backend/pkg/models/database/fhir_imaging_study.go +++ b/backend/pkg/models/database/fhir_imaging_study.go @@ -111,8 +111,8 @@ type FhirImagingStudy struct { // https://hl7.org/fhir/r4/search.html#reference Subject datatypes.JSON `gorm:"column:subject;type:text;serializer:json" json:"subject,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` } func (s *FhirImagingStudy) GetSearchParameters() map[string]string { @@ -144,7 +144,7 @@ func (s *FhirImagingStudy) GetSearchParameters() map[string]string { "started": "date", "status": "token", "subject": "reference", - "text": "keyword", + "text": "string", } return searchParameters } @@ -307,9 +307,9 @@ func (s *FhirImagingStudy) PopulateAndExtractSearchParameters(resourceRaw json.R s.Subject = []byte(subjectResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } return nil } diff --git a/backend/pkg/models/database/fhir_immunization.go b/backend/pkg/models/database/fhir_immunization.go index 75dff0dd7..bda82559c 100644 --- a/backend/pkg/models/database/fhir_immunization.go +++ b/backend/pkg/models/database/fhir_immunization.go @@ -125,8 +125,8 @@ type FhirImmunization struct { // https://hl7.org/fhir/r4/search.html#token TargetDisease datatypes.JSON `gorm:"column:targetDisease;type:text;serializer:json" json:"targetDisease,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` // Vaccine Product Administered // https://hl7.org/fhir/r4/search.html#token VaccineCode datatypes.JSON `gorm:"column:vaccineCode;type:text;serializer:json" json:"vaccineCode,omitempty"` @@ -159,7 +159,7 @@ func (s *FhirImmunization) GetSearchParameters() map[string]string { "status": "token", "statusReason": "token", "targetDisease": "token", - "text": "keyword", + "text": "string", "vaccineCode": "token", } return searchParameters @@ -321,9 +321,9 @@ func (s *FhirImmunization) PopulateAndExtractSearchParameters(resourceRaw json.R s.TargetDisease = []byte(targetDiseaseResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } // extracting VaccineCode vaccineCodeResult, err := vm.RunString("extractTokenSearchParameters(fhirResource, 'Immunization.vaccineCode')") diff --git a/backend/pkg/models/database/fhir_insurance_plan.go b/backend/pkg/models/database/fhir_insurance_plan.go index 99bd28d51..4ad00b815 100644 --- a/backend/pkg/models/database/fhir_insurance_plan.go +++ b/backend/pkg/models/database/fhir_insurance_plan.go @@ -69,8 +69,8 @@ type FhirInsurancePlan struct { // https://hl7.org/fhir/r4/search.html#token Status datatypes.JSON `gorm:"column:status;type:text;serializer:json" json:"status,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` // A code for the type of organization // https://hl7.org/fhir/r4/search.html#token Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` @@ -102,7 +102,7 @@ func (s *FhirInsurancePlan) GetSearchParameters() map[string]string { "source_resource_type": "keyword", "source_uri": "keyword", "status": "token", - "text": "keyword", + "text": "string", "type": "token", } return searchParameters @@ -243,9 +243,9 @@ func (s *FhirInsurancePlan) PopulateAndExtractSearchParameters(resourceRaw json. s.Status = []byte(statusResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } // extracting Type typeResult, err := vm.RunString("extractTokenSearchParameters(fhirResource, 'InsurancePlan.type')") diff --git a/backend/pkg/models/database/fhir_location.go b/backend/pkg/models/database/fhir_location.go index 09c747d15..a812c99d2 100644 --- a/backend/pkg/models/database/fhir_location.go +++ b/backend/pkg/models/database/fhir_location.go @@ -69,8 +69,8 @@ type FhirLocation struct { // https://hl7.org/fhir/r4/search.html#token Status datatypes.JSON `gorm:"column:status;type:text;serializer:json" json:"status,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` // A code for the type of location // https://hl7.org/fhir/r4/search.html#token Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` @@ -102,7 +102,7 @@ func (s *FhirLocation) GetSearchParameters() map[string]string { "source_resource_type": "keyword", "source_uri": "keyword", "status": "token", - "text": "keyword", + "text": "string", "type": "token", } return searchParameters @@ -243,9 +243,9 @@ func (s *FhirLocation) PopulateAndExtractSearchParameters(resourceRaw json.RawMe s.Status = []byte(statusResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } // extracting Type typeResult, err := vm.RunString("extractTokenSearchParameters(fhirResource, 'Location.type')") diff --git a/backend/pkg/models/database/fhir_media.go b/backend/pkg/models/database/fhir_media.go index 710fffde7..0bb44964b 100644 --- a/backend/pkg/models/database/fhir_media.go +++ b/backend/pkg/models/database/fhir_media.go @@ -60,8 +60,8 @@ type FhirMedia struct { // https://hl7.org/fhir/r4/search.html#reference Subject datatypes.JSON `gorm:"column:subject;type:text;serializer:json" json:"subject,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` // Classification of media as image, video, or audio // https://hl7.org/fhir/r4/search.html#token Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` @@ -93,7 +93,7 @@ func (s *FhirMedia) GetSearchParameters() map[string]string { "source_uri": "keyword", "status": "token", "subject": "reference", - "text": "keyword", + "text": "string", "type": "token", "view": "token", } @@ -228,9 +228,9 @@ func (s *FhirMedia) PopulateAndExtractSearchParameters(resourceRaw json.RawMessa s.Subject = []byte(subjectResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } // extracting Type typeResult, err := vm.RunString("extractTokenSearchParameters(fhirResource, 'Media.type')") diff --git a/backend/pkg/models/database/fhir_medication.go b/backend/pkg/models/database/fhir_medication.go index 8df00a328..ced57a7c9 100644 --- a/backend/pkg/models/database/fhir_medication.go +++ b/backend/pkg/models/database/fhir_medication.go @@ -74,8 +74,8 @@ type FhirMedication struct { // https://hl7.org/fhir/r4/search.html#token Status datatypes.JSON `gorm:"column:status;type:text;serializer:json" json:"status,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` } func (s *FhirMedication) GetSearchParameters() map[string]string { @@ -100,7 +100,7 @@ func (s *FhirMedication) GetSearchParameters() map[string]string { "source_resource_type": "keyword", "source_uri": "keyword", "status": "token", - "text": "keyword", + "text": "string", } return searchParameters } @@ -228,9 +228,9 @@ func (s *FhirMedication) PopulateAndExtractSearchParameters(resourceRaw json.Raw s.Status = []byte(statusResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } return nil } diff --git a/backend/pkg/models/database/fhir_medication_administration.go b/backend/pkg/models/database/fhir_medication_administration.go index 2e7e77ead..c79460db2 100644 --- a/backend/pkg/models/database/fhir_medication_administration.go +++ b/backend/pkg/models/database/fhir_medication_administration.go @@ -130,8 +130,8 @@ type FhirMedicationAdministration struct { // https://hl7.org/fhir/r4/search.html#reference Subject datatypes.JSON `gorm:"column:subject;type:text;serializer:json" json:"subject,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` } func (s *FhirMedicationAdministration) GetSearchParameters() map[string]string { @@ -159,7 +159,7 @@ func (s *FhirMedicationAdministration) GetSearchParameters() map[string]string { "source_uri": "keyword", "status": "token", "subject": "reference", - "text": "keyword", + "text": "string", } return searchParameters } @@ -302,9 +302,9 @@ func (s *FhirMedicationAdministration) PopulateAndExtractSearchParameters(resour s.Subject = []byte(subjectResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } return nil } diff --git a/backend/pkg/models/database/fhir_medication_dispense.go b/backend/pkg/models/database/fhir_medication_dispense.go index 7b51a08b2..368c4ea69 100644 --- a/backend/pkg/models/database/fhir_medication_dispense.go +++ b/backend/pkg/models/database/fhir_medication_dispense.go @@ -131,8 +131,8 @@ type FhirMedicationDispense struct { // https://hl7.org/fhir/r4/search.html#reference Subject datatypes.JSON `gorm:"column:subject;type:text;serializer:json" json:"subject,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` // Returns dispenses of a specific type // https://hl7.org/fhir/r4/search.html#token Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` @@ -168,7 +168,7 @@ func (s *FhirMedicationDispense) GetSearchParameters() map[string]string { "source_uri": "keyword", "status": "token", "subject": "reference", - "text": "keyword", + "text": "string", "type": "token", "whenhandedover": "date", "whenprepared": "date", @@ -301,9 +301,9 @@ func (s *FhirMedicationDispense) PopulateAndExtractSearchParameters(resourceRaw s.Subject = []byte(subjectResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } // extracting Type typeResult, err := vm.RunString("extractTokenSearchParameters(fhirResource, 'MedicationDispense.type')") diff --git a/backend/pkg/models/database/fhir_medication_request.go b/backend/pkg/models/database/fhir_medication_request.go index 79f33c570..d0dca3f67 100644 --- a/backend/pkg/models/database/fhir_medication_request.go +++ b/backend/pkg/models/database/fhir_medication_request.go @@ -147,8 +147,8 @@ type FhirMedicationRequest struct { // https://hl7.org/fhir/r4/search.html#reference Subject datatypes.JSON `gorm:"column:subject;type:text;serializer:json" json:"subject,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` } func (s *FhirMedicationRequest) GetSearchParameters() map[string]string { @@ -179,7 +179,7 @@ func (s *FhirMedicationRequest) GetSearchParameters() map[string]string { "source_uri": "keyword", "status": "token", "subject": "reference", - "text": "keyword", + "text": "string", } return searchParameters } @@ -345,9 +345,9 @@ func (s *FhirMedicationRequest) PopulateAndExtractSearchParameters(resourceRaw j s.Subject = []byte(subjectResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } return nil } diff --git a/backend/pkg/models/database/fhir_medication_statement.go b/backend/pkg/models/database/fhir_medication_statement.go index 51f7b5266..80627aca0 100644 --- a/backend/pkg/models/database/fhir_medication_statement.go +++ b/backend/pkg/models/database/fhir_medication_statement.go @@ -124,8 +124,8 @@ type FhirMedicationStatement struct { // https://hl7.org/fhir/r4/search.html#reference Subject datatypes.JSON `gorm:"column:subject;type:text;serializer:json" json:"subject,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` } func (s *FhirMedicationStatement) GetSearchParameters() map[string]string { @@ -151,7 +151,7 @@ func (s *FhirMedicationStatement) GetSearchParameters() map[string]string { "source_uri": "keyword", "status": "token", "subject": "reference", - "text": "keyword", + "text": "string", } return searchParameters } @@ -284,9 +284,9 @@ func (s *FhirMedicationStatement) PopulateAndExtractSearchParameters(resourceRaw s.Subject = []byte(subjectResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } return nil } diff --git a/backend/pkg/models/database/fhir_nutrition_order.go b/backend/pkg/models/database/fhir_nutrition_order.go index c21cf7857..98583e532 100644 --- a/backend/pkg/models/database/fhir_nutrition_order.go +++ b/backend/pkg/models/database/fhir_nutrition_order.go @@ -111,8 +111,8 @@ type FhirNutritionOrder struct { // https://hl7.org/fhir/r4/search.html#token Supplement datatypes.JSON `gorm:"column:supplement;type:text;serializer:json" json:"supplement,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` } func (s *FhirNutritionOrder) GetSearchParameters() map[string]string { @@ -139,7 +139,7 @@ func (s *FhirNutritionOrder) GetSearchParameters() map[string]string { "source_uri": "keyword", "status": "token", "supplement": "token", - "text": "keyword", + "text": "string", } return searchParameters } @@ -277,9 +277,9 @@ func (s *FhirNutritionOrder) PopulateAndExtractSearchParameters(resourceRaw json s.Supplement = []byte(supplementResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } return nil } diff --git a/backend/pkg/models/database/fhir_observation.go b/backend/pkg/models/database/fhir_observation.go index 7e8ac83de..3dc75e3ff 100644 --- a/backend/pkg/models/database/fhir_observation.go +++ b/backend/pkg/models/database/fhir_observation.go @@ -190,8 +190,8 @@ type FhirObservation struct { // https://hl7.org/fhir/r4/search.html#reference Subject datatypes.JSON `gorm:"column:subject;type:text;serializer:json" json:"subject,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` // The value of the observation, if the value is a CodeableConcept // https://hl7.org/fhir/r4/search.html#token ValueConcept datatypes.JSON `gorm:"column:valueConcept;type:text;serializer:json" json:"valueConcept,omitempty"` @@ -244,7 +244,7 @@ func (s *FhirObservation) GetSearchParameters() map[string]string { "specimen": "reference", "status": "token", "subject": "reference", - "text": "keyword", + "text": "string", "valueConcept": "token", "valueDate": "date", "valueQuantity": "quantity", @@ -456,9 +456,9 @@ func (s *FhirObservation) PopulateAndExtractSearchParameters(resourceRaw json.Ra s.Subject = []byte(subjectResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } // extracting ValueConcept valueConceptResult, err := vm.RunString("extractTokenSearchParameters(fhirResource, '(Observation.valueCodeableConcept)')") diff --git a/backend/pkg/models/database/fhir_organization.go b/backend/pkg/models/database/fhir_organization.go index c8293920e..772e0ea95 100644 --- a/backend/pkg/models/database/fhir_organization.go +++ b/backend/pkg/models/database/fhir_organization.go @@ -66,8 +66,8 @@ type FhirOrganization struct { // https://hl7.org/fhir/r4/search.html#string Phonetic datatypes.JSON `gorm:"column:phonetic;type:text;serializer:json" json:"phonetic,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` // A code for the type of organization // https://hl7.org/fhir/r4/search.html#token Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` @@ -98,7 +98,7 @@ func (s *FhirOrganization) GetSearchParameters() map[string]string { "source_resource_id": "keyword", "source_resource_type": "keyword", "source_uri": "keyword", - "text": "keyword", + "text": "string", "type": "token", } return searchParameters @@ -234,9 +234,9 @@ func (s *FhirOrganization) PopulateAndExtractSearchParameters(resourceRaw json.R s.Phonetic = []byte(phoneticResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } // extracting Type typeResult, err := vm.RunString("extractTokenSearchParameters(fhirResource, 'Organization.type')") diff --git a/backend/pkg/models/database/fhir_organization_affiliation.go b/backend/pkg/models/database/fhir_organization_affiliation.go index 57e7667cd..f3c0d5973 100644 --- a/backend/pkg/models/database/fhir_organization_affiliation.go +++ b/backend/pkg/models/database/fhir_organization_affiliation.go @@ -72,8 +72,8 @@ type FhirOrganizationAffiliation struct { // https://hl7.org/fhir/r4/search.html#token Telecom datatypes.JSON `gorm:"column:telecom;type:text;serializer:json" json:"telecom,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` } func (s *FhirOrganizationAffiliation) GetSearchParameters() map[string]string { @@ -103,7 +103,7 @@ func (s *FhirOrganizationAffiliation) GetSearchParameters() map[string]string { "source_uri": "keyword", "specialty": "token", "telecom": "token", - "text": "keyword", + "text": "string", } return searchParameters } @@ -256,9 +256,9 @@ func (s *FhirOrganizationAffiliation) PopulateAndExtractSearchParameters(resourc s.Telecom = []byte(telecomResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } return nil } diff --git a/backend/pkg/models/database/fhir_patient.go b/backend/pkg/models/database/fhir_patient.go index 0d51eaead..3742e9f74 100644 --- a/backend/pkg/models/database/fhir_patient.go +++ b/backend/pkg/models/database/fhir_patient.go @@ -192,8 +192,8 @@ type FhirPatient struct { // https://hl7.org/fhir/r4/search.html#token Telecom datatypes.JSON `gorm:"column:telecom;type:text;serializer:json" json:"telecom,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` } func (s *FhirPatient) GetSearchParameters() map[string]string { @@ -231,7 +231,7 @@ func (s *FhirPatient) GetSearchParameters() map[string]string { "source_resource_type": "keyword", "source_uri": "keyword", "telecom": "token", - "text": "keyword", + "text": "string", } return searchParameters } @@ -432,9 +432,9 @@ func (s *FhirPatient) PopulateAndExtractSearchParameters(resourceRaw json.RawMes s.Telecom = []byte(telecomResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } return nil } diff --git a/backend/pkg/models/database/fhir_person.go b/backend/pkg/models/database/fhir_person.go index ec880a31c..19568c802 100644 --- a/backend/pkg/models/database/fhir_person.go +++ b/backend/pkg/models/database/fhir_person.go @@ -170,8 +170,8 @@ type FhirPerson struct { // https://hl7.org/fhir/r4/search.html#token Telecom datatypes.JSON `gorm:"column:telecom;type:text;serializer:json" json:"telecom,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` } func (s *FhirPerson) GetSearchParameters() map[string]string { @@ -205,7 +205,7 @@ func (s *FhirPerson) GetSearchParameters() map[string]string { "source_resource_type": "keyword", "source_uri": "keyword", "telecom": "token", - "text": "keyword", + "text": "string", } return searchParameters } @@ -378,9 +378,9 @@ func (s *FhirPerson) PopulateAndExtractSearchParameters(resourceRaw json.RawMess s.Telecom = []byte(telecomResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } return nil } diff --git a/backend/pkg/models/database/fhir_practitioner.go b/backend/pkg/models/database/fhir_practitioner.go index 0835f5127..21c33aa8a 100644 --- a/backend/pkg/models/database/fhir_practitioner.go +++ b/backend/pkg/models/database/fhir_practitioner.go @@ -171,8 +171,8 @@ type FhirPractitioner struct { // https://hl7.org/fhir/r4/search.html#token Telecom datatypes.JSON `gorm:"column:telecom;type:text;serializer:json" json:"telecom,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` } func (s *FhirPractitioner) GetSearchParameters() map[string]string { @@ -205,7 +205,7 @@ func (s *FhirPractitioner) GetSearchParameters() map[string]string { "source_resource_type": "keyword", "source_uri": "keyword", "telecom": "token", - "text": "keyword", + "text": "string", } return searchParameters } @@ -365,9 +365,9 @@ func (s *FhirPractitioner) PopulateAndExtractSearchParameters(resourceRaw json.R s.Telecom = []byte(telecomResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } return nil } diff --git a/backend/pkg/models/database/fhir_practitioner_role.go b/backend/pkg/models/database/fhir_practitioner_role.go index f39ce3359..0d4c06da2 100644 --- a/backend/pkg/models/database/fhir_practitioner_role.go +++ b/backend/pkg/models/database/fhir_practitioner_role.go @@ -93,8 +93,8 @@ type FhirPractitionerRole struct { // https://hl7.org/fhir/r4/search.html#token Telecom datatypes.JSON `gorm:"column:telecom;type:text;serializer:json" json:"telecom,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` } func (s *FhirPractitionerRole) GetSearchParameters() map[string]string { @@ -123,7 +123,7 @@ func (s *FhirPractitionerRole) GetSearchParameters() map[string]string { "source_uri": "keyword", "specialty": "token", "telecom": "token", - "text": "keyword", + "text": "string", } return searchParameters } @@ -271,9 +271,9 @@ func (s *FhirPractitionerRole) PopulateAndExtractSearchParameters(resourceRaw js s.Telecom = []byte(telecomResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } return nil } diff --git a/backend/pkg/models/database/fhir_procedure.go b/backend/pkg/models/database/fhir_procedure.go index 312d32790..9e6382637 100644 --- a/backend/pkg/models/database/fhir_procedure.go +++ b/backend/pkg/models/database/fhir_procedure.go @@ -160,8 +160,8 @@ type FhirProcedure struct { // https://hl7.org/fhir/r4/search.html#reference Subject datatypes.JSON `gorm:"column:subject;type:text;serializer:json" json:"subject,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` } func (s *FhirProcedure) GetSearchParameters() map[string]string { @@ -192,7 +192,7 @@ func (s *FhirProcedure) GetSearchParameters() map[string]string { "source_uri": "keyword", "status": "token", "subject": "reference", - "text": "keyword", + "text": "string", } return searchParameters } @@ -350,9 +350,9 @@ func (s *FhirProcedure) PopulateAndExtractSearchParameters(resourceRaw json.RawM s.Subject = []byte(subjectResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } return nil } diff --git a/backend/pkg/models/database/fhir_provenance.go b/backend/pkg/models/database/fhir_provenance.go index 4eb36c361..d98b824d3 100644 --- a/backend/pkg/models/database/fhir_provenance.go +++ b/backend/pkg/models/database/fhir_provenance.go @@ -54,8 +54,8 @@ type FhirProvenance struct { // https://hl7.org/fhir/r4/search.html#reference Target datatypes.JSON `gorm:"column:target;type:text;serializer:json" json:"target,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` // When the activity occurred // https://hl7.org/fhir/r4/search.html#date When *time.Time `gorm:"column:when;type:datetime" json:"when,omitempty"` @@ -82,7 +82,7 @@ func (s *FhirProvenance) GetSearchParameters() map[string]string { "source_resource_type": "keyword", "source_uri": "keyword", "target": "reference", - "text": "keyword", + "text": "string", "when": "date", } return searchParameters @@ -206,9 +206,9 @@ func (s *FhirProvenance) PopulateAndExtractSearchParameters(resourceRaw json.Raw s.Target = []byte(targetResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } // extracting When whenResult, err := vm.RunString("extractDateSearchParameters(fhirResource, '(Provenance.occurredDateTime)')") diff --git a/backend/pkg/models/database/fhir_questionnaire.go b/backend/pkg/models/database/fhir_questionnaire.go index d6d10ee47..b436b76fd 100644 --- a/backend/pkg/models/database/fhir_questionnaire.go +++ b/backend/pkg/models/database/fhir_questionnaire.go @@ -72,8 +72,8 @@ type FhirQuestionnaire struct { // https://hl7.org/fhir/r4/search.html#token SubjectType datatypes.JSON `gorm:"column:subjectType;type:text;serializer:json" json:"subjectType,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` // The human-friendly name of the questionnaire // https://hl7.org/fhir/r4/search.html#string Title datatypes.JSON `gorm:"column:title;type:text;serializer:json" json:"title,omitempty"` @@ -112,7 +112,7 @@ func (s *FhirQuestionnaire) GetSearchParameters() map[string]string { "source_uri": "keyword", "status": "token", "subjectType": "token", - "text": "keyword", + "text": "string", "title": "string", "url": "uri", "version": "token", @@ -276,9 +276,9 @@ func (s *FhirQuestionnaire) PopulateAndExtractSearchParameters(resourceRaw json. s.SubjectType = []byte(subjectTypeResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } // extracting Title titleResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'Questionnaire.title')") diff --git a/backend/pkg/models/database/fhir_questionnaire_response.go b/backend/pkg/models/database/fhir_questionnaire_response.go index ef51d8160..6a50a2d0b 100644 --- a/backend/pkg/models/database/fhir_questionnaire_response.go +++ b/backend/pkg/models/database/fhir_questionnaire_response.go @@ -60,8 +60,8 @@ type FhirQuestionnaireResponse struct { // https://hl7.org/fhir/r4/search.html#reference Subject datatypes.JSON `gorm:"column:subject;type:text;serializer:json" json:"subject,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` } func (s *FhirQuestionnaireResponse) GetSearchParameters() map[string]string { @@ -87,7 +87,7 @@ func (s *FhirQuestionnaireResponse) GetSearchParameters() map[string]string { "source_uri": "keyword", "status": "token", "subject": "reference", - "text": "keyword", + "text": "string", } return searchParameters } @@ -220,9 +220,9 @@ func (s *FhirQuestionnaireResponse) PopulateAndExtractSearchParameters(resourceR s.Subject = []byte(subjectResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } return nil } diff --git a/backend/pkg/models/database/fhir_related_person.go b/backend/pkg/models/database/fhir_related_person.go index 9345f2825..256f52dd5 100644 --- a/backend/pkg/models/database/fhir_related_person.go +++ b/backend/pkg/models/database/fhir_related_person.go @@ -164,8 +164,8 @@ type FhirRelatedPerson struct { // https://hl7.org/fhir/r4/search.html#token Telecom datatypes.JSON `gorm:"column:telecom;type:text;serializer:json" json:"telecom,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` } func (s *FhirRelatedPerson) GetSearchParameters() map[string]string { @@ -197,7 +197,7 @@ func (s *FhirRelatedPerson) GetSearchParameters() map[string]string { "source_resource_type": "keyword", "source_uri": "keyword", "telecom": "token", - "text": "keyword", + "text": "string", } return searchParameters } @@ -360,9 +360,9 @@ func (s *FhirRelatedPerson) PopulateAndExtractSearchParameters(resourceRaw json. s.Telecom = []byte(telecomResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } return nil } diff --git a/backend/pkg/models/database/fhir_schedule.go b/backend/pkg/models/database/fhir_schedule.go index b45ddcff3..6c109521a 100644 --- a/backend/pkg/models/database/fhir_schedule.go +++ b/backend/pkg/models/database/fhir_schedule.go @@ -51,8 +51,8 @@ type FhirSchedule struct { // https://hl7.org/fhir/r4/search.html#token Specialty datatypes.JSON `gorm:"column:specialty;type:text;serializer:json" json:"specialty,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` } func (s *FhirSchedule) GetSearchParameters() map[string]string { @@ -75,7 +75,7 @@ func (s *FhirSchedule) GetSearchParameters() map[string]string { "source_resource_type": "keyword", "source_uri": "keyword", "specialty": "token", - "text": "keyword", + "text": "string", } return searchParameters } @@ -193,9 +193,9 @@ func (s *FhirSchedule) PopulateAndExtractSearchParameters(resourceRaw json.RawMe s.Specialty = []byte(specialtyResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } return nil } diff --git a/backend/pkg/models/database/fhir_service_request.go b/backend/pkg/models/database/fhir_service_request.go index d332b8426..f77683c01 100644 --- a/backend/pkg/models/database/fhir_service_request.go +++ b/backend/pkg/models/database/fhir_service_request.go @@ -155,8 +155,8 @@ type FhirServiceRequest struct { // https://hl7.org/fhir/r4/search.html#reference Subject datatypes.JSON `gorm:"column:subject;type:text;serializer:json" json:"subject,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` } func (s *FhirServiceRequest) GetSearchParameters() map[string]string { @@ -192,7 +192,7 @@ func (s *FhirServiceRequest) GetSearchParameters() map[string]string { "specimen": "reference", "status": "token", "subject": "reference", - "text": "keyword", + "text": "string", } return searchParameters } @@ -383,9 +383,9 @@ func (s *FhirServiceRequest) PopulateAndExtractSearchParameters(resourceRaw json s.Subject = []byte(subjectResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } return nil } diff --git a/backend/pkg/models/database/fhir_slot.go b/backend/pkg/models/database/fhir_slot.go index e45b222cb..b77d47bbc 100644 --- a/backend/pkg/models/database/fhir_slot.go +++ b/backend/pkg/models/database/fhir_slot.go @@ -54,8 +54,8 @@ type FhirSlot struct { // https://hl7.org/fhir/r4/search.html#token Status datatypes.JSON `gorm:"column:status;type:text;serializer:json" json:"status,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` } func (s *FhirSlot) GetSearchParameters() map[string]string { @@ -79,7 +79,7 @@ func (s *FhirSlot) GetSearchParameters() map[string]string { "specialty": "token", "start": "date", "status": "token", - "text": "keyword", + "text": "string", } return searchParameters } @@ -202,9 +202,9 @@ func (s *FhirSlot) PopulateAndExtractSearchParameters(resourceRaw json.RawMessag s.Status = []byte(statusResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } return nil } diff --git a/backend/pkg/models/database/fhir_specimen.go b/backend/pkg/models/database/fhir_specimen.go index 13a67c11a..e8e500534 100644 --- a/backend/pkg/models/database/fhir_specimen.go +++ b/backend/pkg/models/database/fhir_specimen.go @@ -60,8 +60,8 @@ type FhirSpecimen struct { // https://hl7.org/fhir/r4/search.html#reference Subject datatypes.JSON `gorm:"column:subject;type:text;serializer:json" json:"subject,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` // The specimen type // https://hl7.org/fhir/r4/search.html#token Type datatypes.JSON `gorm:"column:type;type:text;serializer:json" json:"type,omitempty"` @@ -90,7 +90,7 @@ func (s *FhirSpecimen) GetSearchParameters() map[string]string { "source_uri": "keyword", "status": "token", "subject": "reference", - "text": "keyword", + "text": "string", "type": "token", } return searchParameters @@ -224,9 +224,9 @@ func (s *FhirSpecimen) PopulateAndExtractSearchParameters(resourceRaw json.RawMe s.Subject = []byte(subjectResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } // extracting Type typeResult, err := vm.RunString("extractTokenSearchParameters(fhirResource, 'Specimen.type')") diff --git a/backend/pkg/models/database/fhir_vision_prescription.go b/backend/pkg/models/database/fhir_vision_prescription.go index 38cb0b3f7..fa4b115df 100644 --- a/backend/pkg/models/database/fhir_vision_prescription.go +++ b/backend/pkg/models/database/fhir_vision_prescription.go @@ -93,8 +93,8 @@ type FhirVisionPrescription struct { // https://hl7.org/fhir/r4/search.html#token Status datatypes.JSON `gorm:"column:status;type:text;serializer:json" json:"status,omitempty"` // Text search against the narrative - // This is a primitive string literal (`keyword` type). It is not a recognized SearchParameter type from https://hl7.org/fhir/r4/search.html, it's Fasten Health-specific - Text string `gorm:"column:text;type:text" json:"text,omitempty"` + // https://hl7.org/fhir/r4/search.html#string + Text datatypes.JSON `gorm:"column:text;type:text;serializer:json" json:"text,omitempty"` } func (s *FhirVisionPrescription) GetSearchParameters() map[string]string { @@ -115,7 +115,7 @@ func (s *FhirVisionPrescription) GetSearchParameters() map[string]string { "source_resource_type": "keyword", "source_uri": "keyword", "status": "token", - "text": "keyword", + "text": "string", } return searchParameters } @@ -223,9 +223,9 @@ func (s *FhirVisionPrescription) PopulateAndExtractSearchParameters(resourceRaw s.Status = []byte(statusResult.String()) } // extracting Text - textResult, err := vm.RunString("extractSimpleSearchParameters(fhirResource, 'text')") + textResult, err := vm.RunString("extractStringSearchParameters(fhirResource, 'text')") if err == nil && textResult.String() != "undefined" { - s.Text = textResult.String() + s.Text = []byte(textResult.String()) } return nil } diff --git a/backend/pkg/models/database/generate.go b/backend/pkg/models/database/generate.go index 282679b1c..9b686a3e2 100644 --- a/backend/pkg/models/database/generate.go +++ b/backend/pkg/models/database/generate.go @@ -166,7 +166,7 @@ func main() { FHIRPathExpression: "Resource.meta.tag", } fieldMap["Text"] = DBField{ - FieldType: "keyword", + FieldType: "string", Description: "Text search against the narrative", FHIRPathExpression: "text", } diff --git a/backend/pkg/models/database/searchParameterExtractor.js b/backend/pkg/models/database/searchParameterExtractor.js index d15fa8e5f..1f399e06c 100644 --- a/backend/pkg/models/database/searchParameterExtractor.js +++ b/backend/pkg/models/database/searchParameterExtractor.js @@ -49,6 +49,9 @@ function extractStringSearchParameters(fhirResource, expression){ addressParts.push(currentValue.country) } accumulator.push(addressParts.join(" ")) + } else if (currentValue.status && currentValue.div) { + // Text (Narrative - http://hl7.org/fhir/R4/narrative.html#Narrative) + accumulator.push(currentValue.div) } else { //string, boolean accumulator.push(currentValue) From af1c033a5cc674bcfce5dc6fc7c2ce565fc54b9d Mon Sep 17 00:00:00 2001 From: Jason Kulatunga Date: Fri, 8 Mar 2024 15:09:47 -0800 Subject: [PATCH 27/29] working Patient record merge. Fixing IPS Export Data model for more flexibility. --- .../pkg/database/gorm_repository_summary.go | 98 ++++++- backend/pkg/database/interface.go | 3 +- backend/pkg/utils/ips/ips_export_data.go | 17 ++ backend/pkg/utils/ips/render.go | 12 +- .../utils/ips/templates/composition.gohtml | 2 +- .../ips/templates/includes/header.gohtml | 102 ++++++- .../ips/templates/includes/styles.gohtml | 275 ++++++++++++++++++ backend/pkg/utils/ips/templates/index.gohtml | 20 +- backend/pkg/web/handler/summary.go | 9 +- .../src/assets/banner/banner-transparent.svg | 49 ++++ go.mod | 5 +- go.sum | 6 + 12 files changed, 556 insertions(+), 42 deletions(-) create mode 100644 backend/pkg/utils/ips/ips_export_data.go create mode 100644 backend/pkg/utils/ips/templates/includes/styles.gohtml create mode 100644 frontend/src/assets/banner/banner-transparent.svg diff --git a/backend/pkg/database/gorm_repository_summary.go b/backend/pkg/database/gorm_repository_summary.go index deac59bbf..39f49b775 100644 --- a/backend/pkg/database/gorm_repository_summary.go +++ b/backend/pkg/database/gorm_repository_summary.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "github.com/TwiN/deepmerge" "github.com/fastenhealth/fasten-onprem/backend/pkg" "github.com/fastenhealth/fasten-onprem/backend/pkg/models" "github.com/fastenhealth/fasten-onprem/backend/pkg/models/database" @@ -15,13 +16,33 @@ import ( "time" ) -func (gr *GormRepository) GetInternationalPatientSummaryBundle(ctx context.Context) (interface{}, interface{}, error) { +// returns IPSBundle and IPSComposition +func (gr *GormRepository) GetInternationalPatientSummaryExport(ctx context.Context) (*ips.InternationalPatientSummaryExportData, error) { + exportData := &ips.InternationalPatientSummaryExportData{} + summaryTime := time.Now() timestamp := summaryTime.Format(time.RFC3339) + exportData.GenerationDate = summaryTime + + //get a list of all Patients associated with this user (we'll be creating a pseudo Patient for referencing in this Bundle + patient, err := gr.GetPatientMerged(ctx) + if err != nil { + //TODO: determine if we should error out here. If only manually entered records were entered, we wont have a Patient record, + return exportData, err + } + exportData.Patient = patient + + //get a list of all Sources associated with this user + sources, err := gr.GetSources(ctx) + if err != nil { + return exportData, err + } + exportData.Sources = sources + narrativeEngine, err := ips.NewNarrative() if err != nil { - return nil, nil, fmt.Errorf("error creating narrative engine: %w", err) + return exportData, fmt.Errorf("error creating narrative engine: %w", err) } //Algorithm to create the IPS bundle @@ -42,7 +63,7 @@ func (gr *GormRepository) GetInternationalPatientSummaryBundle(ctx context.Conte //Step 1. Generate the IPS Section Lists summarySectionQueryResults, err := gr.getInternationalPatientSummarySectionResources(ctx) if err != nil { - return nil, nil, err + return exportData, err } //Step 2. Create the Composition Section @@ -50,7 +71,7 @@ func (gr *GormRepository) GetInternationalPatientSummaryBundle(ctx context.Conte for sectionType, sectionQueryResultsList := range summarySectionQueryResults { compositionSection, err := generateIPSCompositionSection(narrativeEngine, sectionType, sectionQueryResultsList) if err != nil { - return nil, nil, err + return exportData, err } compositionSections = append(compositionSections, *compositionSection) } @@ -60,6 +81,7 @@ func (gr *GormRepository) GetInternationalPatientSummaryBundle(ctx context.Conte //TODO: Step 4. Create a Fasten Health Organization resource. compositionUUID := uuid.New().String() + patientReference := fmt.Sprintf("%s/%s", exportData.Patient.GetSourceResourceType(), exportData.Patient.GetSourceResourceID()) //Step 5. Create the IPS Composition ipsComposition := &fhir401.Composition{ @@ -83,7 +105,7 @@ func (gr *GormRepository) GetInternationalPatientSummaryBundle(ctx context.Conte }, }, Subject: &fhir401.Reference{ - Reference: stringPtr("Patient/123"), //TODO + Reference: stringPtr(patientReference), //TODO }, Date: timestamp, Author: []fhir401.Reference{ @@ -97,7 +119,7 @@ func (gr *GormRepository) GetInternationalPatientSummaryBundle(ctx context.Conte Mode: fhir401.CompositionAttestationModePersonal, Time: ×tamp, Party: &fhir401.Reference{ - Reference: stringPtr("Patient/123"), + Reference: stringPtr(patientReference), }, }, }, @@ -138,7 +160,7 @@ func (gr *GormRepository) GetInternationalPatientSummaryBundle(ctx context.Conte // Add the Composition to the bundle ipsCompositionJson, err := json.Marshal(ipsComposition) if err != nil { - return nil, nil, err + return exportData, err } ipsBundle.Entry = append(ipsBundle.Entry, fhir401.BundleEntry{ Resource: json.RawMessage(ipsCompositionJson), @@ -156,7 +178,10 @@ func (gr *GormRepository) GetInternationalPatientSummaryBundle(ctx context.Conte // } //} - return ipsBundle, ipsComposition, nil + exportData.Bundle = ipsBundle + exportData.Composition = ipsComposition + + return exportData, nil } // GetInternationalPatientSummary will generate an IPS bundle, which can then be used to generate a IPS QR code, PDF or JSON bundle @@ -697,11 +722,64 @@ func flattenQueryResultsToResourcesList(queryResultsList []any) []database.IFhir return resources } -func generateIPSSectionNarrative(sectionType pkg.IPSSections, resources []models.ResourceBase) string { - return "" +// When given a list of Patient database records, we need to merge them together to a Patient record that's usable by the +func (gr *GormRepository) GetPatientMerged(ctx context.Context) (*database.FhirPatient, error) { + currentUser, currentUserErr := gr.GetCurrentUser(ctx) + if currentUserErr != nil { + return nil, currentUserErr + } + + tableName, err := database.GetTableNameByResourceType("Patient") + if err != nil { + return nil, err + } + + var wrappedFhirPatients []database.FhirPatient + results := gr.GormClient.WithContext(ctx). + //Group("source_id"). //broken in Postgres. + Where(models.OriginBase{ + UserID: currentUser.ID, + SourceResourceType: "Patient", + }). + Order("sort_date DESC"). + Table(tableName). + Find(&wrappedFhirPatients) + + if results.Error != nil { + return nil, results.Error + } + + return mergePatients(wrappedFhirPatients) } // helper utility func stringPtr(s string) *string { return &s } + +func mergePatients(patients []database.FhirPatient) (*database.FhirPatient, error) { + if len(patients) == 0 { + log.Printf("no patients to merge, ignoring") + return nil, fmt.Errorf("no patients to merge, ignoring") + } + mergedPatientResource := `{}` + for ndx, _ := range patients { + patient := patients[ndx] + mergedPatientResourceBytes, err := deepmerge.JSON([]byte(mergedPatientResource), []byte(patient.ResourceRaw)) + if err != nil { + return nil, err + } + mergedPatientResource = string(mergedPatientResourceBytes) + } + + mergedPatient := &database.FhirPatient{ + ResourceBase: models.ResourceBase{ + OriginBase: patients[len(patients)-1].OriginBase, + }, + } + err := mergedPatient.PopulateAndExtractSearchParameters([]byte(mergedPatientResource)) + if err != nil { + return nil, fmt.Errorf("error occurred while extracting fields from merged Patient") + } + return mergedPatient, nil +} diff --git a/backend/pkg/database/interface.go b/backend/pkg/database/interface.go index 6291e2543..c77d96398 100644 --- a/backend/pkg/database/interface.go +++ b/backend/pkg/database/interface.go @@ -4,6 +4,7 @@ import ( "context" "github.com/fastenhealth/fasten-onprem/backend/pkg" "github.com/fastenhealth/fasten-onprem/backend/pkg/models" + "github.com/fastenhealth/fasten-onprem/backend/pkg/utils/ips" sourcePkg "github.com/fastenhealth/fasten-sources/clients/models" "github.com/google/uuid" ) @@ -21,7 +22,7 @@ type DatabaseRepository interface { //get a count of every resource type GetSummary(ctx context.Context) (*models.Summary, error) - GetInternationalPatientSummaryBundle(ctx context.Context) (interface{}, interface{}, error) + GetInternationalPatientSummaryExport(ctx context.Context) (*ips.InternationalPatientSummaryExportData, error) GetResourceByResourceTypeAndId(context.Context, string, string) (*models.ResourceBase, error) GetResourceBySourceId(context.Context, string, string) (*models.ResourceBase, error) diff --git a/backend/pkg/utils/ips/ips_export_data.go b/backend/pkg/utils/ips/ips_export_data.go new file mode 100644 index 000000000..de492dd02 --- /dev/null +++ b/backend/pkg/utils/ips/ips_export_data.go @@ -0,0 +1,17 @@ +package ips + +import ( + "github.com/fastenhealth/fasten-onprem/backend/pkg/models" + "github.com/fastenhealth/fasten-onprem/backend/pkg/models/database" + "github.com/fastenhealth/gofhir-models/fhir401" + "time" +) + +type InternationalPatientSummaryExportData struct { + GenerationDate time.Time + Bundle *fhir401.Bundle + Composition *fhir401.Composition + + Patient *database.FhirPatient + Sources []models.SourceCredential +} diff --git a/backend/pkg/utils/ips/render.go b/backend/pkg/utils/ips/render.go index add170b88..4092ab78c 100644 --- a/backend/pkg/utils/ips/render.go +++ b/backend/pkg/utils/ips/render.go @@ -39,7 +39,7 @@ type NarrativeTemplateData struct { CarePlan []database.FhirCarePlan Observation []database.FhirObservation Encounter []database.FhirEncounter - Patient []database.FhirPatient + Patient database.FhirPatient } func NewNarrative() (*Narrative, error) { @@ -49,12 +49,15 @@ func NewNarrative() (*Narrative, error) { // https://stackoverflow.com/questions/50283370/include-template-from-another-directory // https://www.digitalocean.com/community/tutorials/how-to-use-templates-in-go tmpl, err := template.New("ips").Funcs(template.FuncMap{ - "safeHTML": func(s *string) template.HTML { + "safeHTMLPtr": func(s *string) template.HTML { if s == nil { return template.HTML("") } return template.HTML(*s) }, + "safeHTML": func(s string) template.HTML { + return template.HTML(s) + }, "parseStringList": func(data datatypes.JSON) []string { var parsed []string _ = json.Unmarshal(data, &parsed) @@ -124,8 +127,9 @@ func (r *Narrative) RenderSection(sectionType pkg.IPSSections, resources []datab MedicationRequest: []database.FhirMedicationRequest{}, MedicationStatement: []database.FhirMedicationStatement{}, Observation: []database.FhirObservation{}, - Patient: []database.FhirPatient{}, Procedure: []database.FhirProcedure{}, + + Patient: database.FhirPatient{}, } //loop though the resources, cast them to the correct type, and then store them in the correct array @@ -156,8 +160,6 @@ func (r *Narrative) RenderSection(sectionType pkg.IPSSections, resources []datab templateData.MedicationStatement = append(templateData.MedicationStatement, *resource.(*database.FhirMedicationStatement)) case "Observation": templateData.Observation = append(templateData.Observation, *resource.(*database.FhirObservation)) - case "Patient": - templateData.Patient = append(templateData.Patient, *resource.(*database.FhirPatient)) case "Procedure": templateData.Procedure = append(templateData.Procedure, *resource.(*database.FhirProcedure)) } diff --git a/backend/pkg/utils/ips/templates/composition.gohtml b/backend/pkg/utils/ips/templates/composition.gohtml index 292073dc7..65547445b 100644 --- a/backend/pkg/utils/ips/templates/composition.gohtml +++ b/backend/pkg/utils/ips/templates/composition.gohtml @@ -11,7 +11,7 @@ all of the section narratives into a single narrative. {{if eq $section.Text nil }} {{$section.EmptyReason.Text}} {{else }} - {{$section.Text.Div | safeHTML}} + {{$section.Text.Div | safeHTMLPtr}} {{end}} diff --git a/backend/pkg/utils/ips/templates/includes/header.gohtml b/backend/pkg/utils/ips/templates/includes/header.gohtml index 3a28b092c..cd58842d8 100644 --- a/backend/pkg/utils/ips/templates/includes/header.gohtml +++ b/backend/pkg/utils/ips/templates/includes/header.gohtml @@ -1 +1,101 @@ -
header hello world
+{{- /*gotype: github.com/fastenhealth/fasten-onprem/backend/pkg/utils/ips.NarrativeTemplateData*/ -}} +
+
+
+

{{.Patient.Name | parseStringList | uniq | first}}

+
Patient Health Summary; Generated: {{.Composition.Date | date "2006-01-02"}}
+
+ ID: {{.Composition.Identifier.Value}}
+
+
+
+
+
+ + + + + + + + + + + +
+
+ Author: {{.Composition.Identifier.System}}
+
+
+
+ + +
+ + + + + + + + + + + + + + + + + + + +
BornLanguageRace/EthnicityAddressPhone
+ {{default "Unknown" (.Patient.Birthdate | date "2006-01-02")}} + + {{default "Unknown" (.Patient.Language | parseMapList | pluckList "text" | join ",")}} + + Unknown / Unknown + + {{default "Unknown" (.Patient.Address | parseStringList | uniq | join "
" | safeHTML)}} +
+ {{default "Unknown" (.Patient.Phone | parseStringList | uniq | join ", ")}} +
+
+ + diff --git a/backend/pkg/utils/ips/templates/includes/styles.gohtml b/backend/pkg/utils/ips/templates/includes/styles.gohtml new file mode 100644 index 000000000..6a0b38900 --- /dev/null +++ b/backend/pkg/utils/ips/templates/includes/styles.gohtml @@ -0,0 +1,275 @@ + + + + + + + diff --git a/backend/pkg/utils/ips/templates/index.gohtml b/backend/pkg/utils/ips/templates/index.gohtml index d34ccc2bf..b3f149fb6 100644 --- a/backend/pkg/utils/ips/templates/index.gohtml +++ b/backend/pkg/utils/ips/templates/index.gohtml @@ -1,28 +1,12 @@ +{{- /*gotype: github.com/fastenhealth/fasten-onprem/backend/pkg/utils/ips.NarrativeTemplateData*/ -}} title - - - - + {{template "styles.gohtml" .}} diff --git a/backend/pkg/web/handler/summary.go b/backend/pkg/web/handler/summary.go index b4a844c36..e17770743 100644 --- a/backend/pkg/web/handler/summary.go +++ b/backend/pkg/web/handler/summary.go @@ -5,7 +5,6 @@ import ( "github.com/fastenhealth/fasten-onprem/backend/pkg" "github.com/fastenhealth/fasten-onprem/backend/pkg/database" "github.com/fastenhealth/fasten-onprem/backend/pkg/utils/ips" - "github.com/fastenhealth/gofhir-models/fhir401" "github.com/gin-gonic/gin" "github.com/sirupsen/logrus" "net/http" @@ -28,7 +27,7 @@ func GetIPSSummary(c *gin.Context) { logger := c.MustGet(pkg.ContextKeyTypeLogger).(*logrus.Entry) databaseRepo := c.MustGet(pkg.ContextKeyTypeDatabase).(database.DatabaseRepository) - ipsBundle, ipsComposititon, err := databaseRepo.GetInternationalPatientSummaryBundle(c) + ipsExport, err := databaseRepo.GetInternationalPatientSummaryExport(c) if err != nil { logger.Errorln("An error occurred while retrieving IPS summary", err) c.JSON(http.StatusInternalServerError, gin.H{"success": false}) @@ -36,7 +35,7 @@ func GetIPSSummary(c *gin.Context) { } if c.Query("format") == "" { - c.JSON(http.StatusOK, gin.H{"success": true, "data": ipsBundle}) + c.JSON(http.StatusOK, gin.H{"success": true, "data": ipsExport.Bundle}) return } @@ -47,13 +46,13 @@ func GetIPSSummary(c *gin.Context) { return } - composititon := ipsComposititon.(*fhir401.Composition) + composititon := ipsExport.Composition if c.Query("format") == "html" { logger.Debugln("Rendering HTML") //create string writer - content, err := narrative.RenderTemplate("index.gohtml", ips.NarrativeTemplateData{Composition: composititon}) + content, err := narrative.RenderTemplate("index.gohtml", ips.NarrativeTemplateData{Composition: composititon, Patient: *ipsExport.Patient}) if err != nil { logger.Errorln("An error occurred while executing template", err) c.JSON(http.StatusInternalServerError, gin.H{"success": false}) diff --git a/frontend/src/assets/banner/banner-transparent.svg b/frontend/src/assets/banner/banner-transparent.svg new file mode 100644 index 000000000..addab89ae --- /dev/null +++ b/frontend/src/assets/banner/banner-transparent.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + diff --git a/go.mod b/go.mod index f6410d2ce..e34fe7c72 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,8 @@ module github.com/fastenhealth/fasten-onprem -go 1.18 +go 1.21 + +toolchain go1.21.1 //replace github.com/fastenhealth/fasten-sources => ../fasten-sources @@ -12,6 +14,7 @@ replace github.com/mattn/go-sqlite3 v1.14.17 => github.com/jgiannuzzi/go-sqlite3 require ( github.com/Masterminds/sprig/v3 v3.2.3 + github.com/TwiN/deepmerge v0.2.1 github.com/analogj/go-util v0.0.0-20210417161720-39b497cca03b github.com/dave/jennifer v1.6.1 github.com/dominikbraun/graph v0.15.0 diff --git a/go.sum b/go.sum index d1644b109..709df94bc 100644 --- a/go.sum +++ b/go.sum @@ -50,6 +50,8 @@ github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 h1:wPbRQzjjwFc0ih8puEVAOFGELsn1zoIIYdxvML7mDxA= github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g= +github.com/TwiN/deepmerge v0.2.1 h1:GowJr9O4THTVW4awX63x1BVg1hgr4q+35XKKCYbwsSs= +github.com/TwiN/deepmerge v0.2.1/go.mod h1:LVBmCEBQvibYSF8Gyl/NqhHXH7yIiT7Ozqf9dHxGPW0= github.com/analogj/go-util v0.0.0-20210417161720-39b497cca03b h1:Y/+MfmdKPPpVY7C6ggt/FpltFSitlpUtyJEdcQyFXQg= github.com/analogj/go-util v0.0.0-20210417161720-39b497cca03b/go.mod h1:bRSzJXgXnT5+Ihah7RSC7Cvp16UmoLn3wq6ROciS1Ow= github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= @@ -115,6 +117,7 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= +github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= @@ -131,6 +134,7 @@ github.com/go-gormigrate/gormigrate/v2 v2.1.1/go.mod h1:L7nJ620PFDKei9QOhJzqA8kR github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= @@ -195,6 +199,7 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github/v54 v54.0.0 h1:OZdXwow4EAD5jEo5qg+dGFH2DpkyZvVsAehjvJuUL/c= github.com/google/go-github/v54 v54.0.0/go.mod h1:Sw1LXWHhXRZtzJ9LI5fyJg9wbQzYvFhW8W5P2yaAQ7s= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= @@ -422,6 +427,7 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl github.com/subosito/gotenv v1.3.0 h1:mjC+YW8QpAdXibNi+vNWgzmgBH4+5l5dCXv8cNysBLI= github.com/subosito/gotenv v1.3.0/go.mod h1:YzJjq/33h7nrwdY+iHMhEOEEbW0ovIz0tB6t6PwAXzs= github.com/thoas/go-funk v0.9.1 h1:O549iLZqPpTUQ10ykd26sZhzD+rmR5pWhuElrhbC20M= +github.com/thoas/go-funk v0.9.1/go.mod h1:+IWnUfUmFO1+WVYQWQtIJHeRRdaIyyYglZN7xzUPe4Q= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= From d700a1e4e09cf404f2eb548f020a970c2519ed63 Mon Sep 17 00:00:00 2001 From: Jason Kulatunga Date: Tue, 19 Mar 2024 21:24:10 -0700 Subject: [PATCH 28/29] make sure the patient summary is exported in a specific order. --- backend/pkg/constants.go | 28 ++++++++++++ .../pkg/database/gorm_repository_summary.go | 43 ++++++++++++++++--- 2 files changed, 66 insertions(+), 5 deletions(-) diff --git a/backend/pkg/constants.go b/backend/pkg/constants.go index db8a6d754..e09ca457a 100644 --- a/backend/pkg/constants.go +++ b/backend/pkg/constants.go @@ -11,6 +11,7 @@ type InstallationVerificationStatus string type InstallationQuotaStatus string type IPSSections string +type IPSSectionGroups string const ( ResourceListPageSize int = 20 @@ -67,6 +68,10 @@ const ( IPSSectionsPlanOfCare IPSSections = "plan_of_care" IPSSectionsFunctionalStatus IPSSections = "functional_status" IPSSectionsAdvanceDirectives IPSSections = "advance_directives" + + IPSSectionGroupsRequired IPSSectionGroups = "required" + IPSSectionGroupsRecommended IPSSectionGroups = "recommended" + IPSSectionGroupsOptional IPSSectionGroups = "optional" ) var IPSSectionsList = []IPSSections{ @@ -85,3 +90,26 @@ var IPSSectionsList = []IPSSections{ IPSSectionsFunctionalStatus, IPSSectionsAdvanceDirectives, } + +var IPSSectionGroupsOrdered = map[IPSSectionGroups][]IPSSections{ + IPSSectionGroupsRequired: []IPSSections{ + IPSSectionsMedicationSummary, + IPSSectionsAllergiesIntolerances, + IPSSectionsProblemList, + }, + IPSSectionGroupsRecommended: []IPSSections{ + IPSSectionsImmunizations, + IPSSectionsHistoryOfProcedures, + IPSSectionsMedicalDevices, + IPSSectionsDiagnosticResults, + }, + IPSSectionGroupsOptional: []IPSSections{ + IPSSectionsVitalSigns, + IPSSectionsHistoryOfIllness, + IPSSectionsPregnancy, + IPSSectionsSocialHistory, + IPSSectionsPlanOfCare, + IPSSectionsFunctionalStatus, + IPSSectionsAdvanceDirectives, + }, +} diff --git a/backend/pkg/database/gorm_repository_summary.go b/backend/pkg/database/gorm_repository_summary.go index 39f49b775..7c599dce8 100644 --- a/backend/pkg/database/gorm_repository_summary.go +++ b/backend/pkg/database/gorm_repository_summary.go @@ -68,13 +68,46 @@ func (gr *GormRepository) GetInternationalPatientSummaryExport(ctx context.Conte //Step 2. Create the Composition Section compositionSections := []fhir401.CompositionSection{} - for sectionType, sectionQueryResultsList := range summarySectionQueryResults { - compositionSection, err := generateIPSCompositionSection(narrativeEngine, sectionType, sectionQueryResultsList) - if err != nil { - return exportData, err + + //loop though the various section groups in order (required, recommended, optional) + for ndx, _ := range pkg.IPSSectionGroupsOrdered[pkg.IPSSectionGroupsRequired] { + section := pkg.IPSSectionGroupsOrdered[pkg.IPSSectionGroupsRequired][ndx] + if sectionQueryResultsList, ok := summarySectionQueryResults[section]; ok { + compositionSection, err := generateIPSCompositionSection(narrativeEngine, section, sectionQueryResultsList) + if err != nil { + return exportData, err + } + compositionSections = append(compositionSections, *compositionSection) + } + } + for ndx, _ := range pkg.IPSSectionGroupsOrdered[pkg.IPSSectionGroupsRecommended] { + section := pkg.IPSSectionGroupsOrdered[pkg.IPSSectionGroupsRecommended][ndx] + if sectionQueryResultsList, ok := summarySectionQueryResults[section]; ok { + compositionSection, err := generateIPSCompositionSection(narrativeEngine, section, sectionQueryResultsList) + if err != nil { + return exportData, err + } + compositionSections = append(compositionSections, *compositionSection) } - compositionSections = append(compositionSections, *compositionSection) } + for ndx, _ := range pkg.IPSSectionGroupsOrdered[pkg.IPSSectionGroupsOptional] { + section := pkg.IPSSectionGroupsOrdered[pkg.IPSSectionGroupsOptional][ndx] + if sectionQueryResultsList, ok := summarySectionQueryResults[section]; ok { + compositionSection, err := generateIPSCompositionSection(narrativeEngine, section, sectionQueryResultsList) + if err != nil { + return exportData, err + } + compositionSections = append(compositionSections, *compositionSection) + } + } + + //for sectionType, sectionQueryResultsList := range summarySectionQueryResults { + // compositionSection, err := generateIPSCompositionSection(narrativeEngine, sectionType, sectionQueryResultsList) + // if err != nil { + // return exportData, err + // } + // compositionSections = append(compositionSections, *compositionSection) + //} //TODO: Step 3. Query all the Patient Resources & merge them together From d99da608970e14e8042f2ce7b0eae2a2906fa202 Mon Sep 17 00:00:00 2001 From: Jason Kulatunga Date: Wed, 20 Mar 2024 08:54:05 -0700 Subject: [PATCH 29/29] update logos --- .../04cee620-af39-4d39-8f39-a083e66c2575.png | Bin 11178 -> 11172 bytes .../0818eba3-9dde-4715-9240-d6f43e24602d.png | Bin 8579 -> 8571 bytes .../1010c410-9cde-46b4-b497-30a49d7c52f9.png | Bin 21073 -> 21067 bytes .../15ff9fe5-57eb-4483-ab1a-f75ed9204556.png | Bin 20278 -> 20262 bytes .../1ac27911-47ab-4768-8f3b-9c4dd20efbed.png | Bin 36148 -> 36132 bytes .../20ac8143-daac-4c68-8f37-b518351f6e75.png | Bin 3900 -> 3892 bytes .../2e7caeeb-5b3d-421c-9fb9-2f5453547f13.png | Bin 26160 -> 26144 bytes .../3aa0125e-1b02-49f9-a287-da4a320017ee.png | Bin 16258 -> 16256 bytes .../41dd89d6-276c-41ac-ae6c-71c6e9df9910.png | Bin 10740 -> 10736 bytes .../4d544584-e166-4cdf-9030-68b68a47e95d.png | Bin 45523 -> 45503 bytes .../595c488a-6f16-470a-b795-dede8b0dbdc9.png | Bin 20428 -> 20422 bytes .../5be6c92b-ae9c-4ad5-9db6-341981072313.png | Bin 10907 -> 10897 bytes .../68d3119a-61d8-4086-a564-1033f8dd39b1.png | Bin 17414 -> 17406 bytes .../7321fe44-7967-4544-bc9a-38c1e6bff97f.png | Bin 14784 -> 14778 bytes .../7b5c9f5e-9750-4394-a07c-f2c707b11960.png | Bin 12049 -> 12043 bytes .../7cd62665-7458-436f-b19e-5f55f42b1887.png | Bin 10046 -> 10038 bytes .../8c99ab4c-b467-4454-957a-98f2f025a130.png | Bin 25791 -> 25783 bytes .../92b014ed-8f8a-4ebc-844c-967368286cd0.png | Bin 10084 -> 10078 bytes .../940b2b83-e259-4fa5-b601-a7608d078e92.png | Bin 0 -> 4971 bytes .../9532878a-4850-45ee-bd58-1d6422021b9c.png | Bin 51425 -> 51415 bytes .../966e70b6-eb51-40f8-ad63-89bd77d28927.png | Bin 79822 -> 79806 bytes .../986139aa-d14b-4215-bdd1-f25f812741b0.png | Bin 14862 -> 14854 bytes .../a0dcfff4-b168-4766-b7f3-5269a1eb6b2b.png | Bin 12118 -> 12110 bytes .../a5c6977a-00e2-4c12-8ccd-587105bd17c9.png | Bin 15948 -> 15940 bytes .../ab4c5504-d780-4da6-b512-4fbb0ab05d7e.png | Bin 26036 -> 26022 bytes .../b470d7c9-b7e4-4d7a-9973-e490ff4a880f.png | Bin 23235 -> 23219 bytes .../bbc89f13-66bb-4e96-812f-70f1f64d7604.png | Bin 19583 -> 19577 bytes .../c8f4312f-ac8f-4118-8b80-81d5076e8d32.png | Bin 5110 -> 5104 bytes .../cc311773-48ac-4fb7-bb8b-b5e9f4c77785.png | Bin 18549 -> 18543 bytes .../cd4082b0-48db-402b-88c3-18e4d3388fbd.png | Bin 47088 -> 47072 bytes .../d90af467-72dd-4082-b45e-5883e418bdc1.png | Bin 10297 -> 10281 bytes .../db607b32-d7f9-48df-a659-fdcba3945c35.png | Bin 25246 -> 25230 bytes .../dbdf1511-ed54-449b-9882-2abfd6a98d29.png | Bin 8372 -> 8366 bytes .../e0bdaf29-5213-439e-ba79-66bcbe602ed8.png | Bin 4902 -> 4894 bytes .../e342250a-e9fb-49f4-ad2b-3edea496e8e5.png | Bin 18661 -> 18635 bytes .../e3f229a1-8637-49b1-abaa-84d228aff34a.png | Bin 10030 -> 10014 bytes .../f12e6c9c-f38d-4468-b158-656c096e21b8.png | Bin 23297 -> 23295 bytes 37 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 frontend/src/assets/sources/940b2b83-e259-4fa5-b601-a7608d078e92.png diff --git a/frontend/src/assets/sources/04cee620-af39-4d39-8f39-a083e66c2575.png b/frontend/src/assets/sources/04cee620-af39-4d39-8f39-a083e66c2575.png index 6eb2f215e06f7f0315096b50fd465e863a950446..125f942b7227ef929b1b8eb71a1fc58e30a955be 100644 GIT binary patch delta 56 zcmZ1#z9f7@fEJ_BFG>Y+Bq!@B%9`*TUiS#dktlJE tC`qlzOtT8etVqp?bji$3%`48#&tot#GI_D~Xf{v{gQu&X%Q~loCIJ2G9B%*s delta 94 zcmezE)a<BopT!DmtT3T^x34@WDjzaR4 t@FhTb>B(A(vRpa}atpj}1G!R@{S{?|bQJU&P1Au~22WQ%mvv4FO#qm08)5(e diff --git a/frontend/src/assets/sources/1010c410-9cde-46b4-b497-30a49d7c52f9.png b/frontend/src/assets/sources/1010c410-9cde-46b4-b497-30a49d7c52f9.png index f0d51d5b9121082c859759b9707119b05dcb22f2..a3fa0fada4466ae922248da7cdf590b3f4e392e3 100644 GIT binary patch delta 91 zcmcb(gz@we#tmNsT!czoBT7;$GSjSFfrNirT5)O#gSo}YE7j@@3=EQR*?`Q7)SL*H m%-qzx;>`R!215fAi?y12Hvtt%OtuY_VVS9%-7q;m@Dl(tEFlR1 delta 97 zcmX@Tgz@4M#tmNsJVZ)dBT7;$GSjSFfrNirT5)O#gSmx{Lfn+DISdR8(s22J%!<^U r2$#&<)V$)%{5%Fj0~4S!g{9wj1C>clwhWYE(@|KI`ap4VWZ)+N)wv>D diff --git a/frontend/src/assets/sources/15ff9fe5-57eb-4483-ab1a-f75ed9204556.png b/frontend/src/assets/sources/15ff9fe5-57eb-4483-ab1a-f75ed9204556.png index 341895c8ba13bdbea7e1da5221252db8cfd160c3..64af2a61756624e4c6766492e606898db10a9a15 100644 GIT binary patch delta 331 zcmdlsk8#;N#toc4j8c=ie56z@bQCOv-rA`%Ffa&~xJHzuR%E7GIp^o(7X=q2CZ{qO z^3P`Sob2vn5G@Rsb_J^OPfIIKEnzUUH1O&BdUl&rAVIn_5^(yj=Wa@(mwNMwQ8me!`PQeFb?yZc>o`5)9NO0}>Q<&d)6< zN-ZwV%+F&m`_@|{6r#K>{uxkXezM6XBAXo0?agnV-jCVqq@kGFKO*W^!(~3`?r3 zZ29E=ZYNC{xR#QP(%huH#LOI^-MIxtsl{N8WJWE%^30yu0M#Ey?EnA( delta 245 zcmZ27i)qU&rVTf`WQ0pxBT7;$GSjS_^K*NlOIK?<%SAhRMhC&DE&H#M&~Ge3{P#KK%h;jPfG)0nCv zkyV-MC^-DvZvs?h3^yw{Kdq!Zv1sz_Zaqf1$)~y%xO5brRZ0Z|6=_da@6q6AFfla% sIwI|9ks?sc5GZC0R3dyVu>iM-rw4L;l%Jo(v2OLU2h}pbG!AwBpnf v1|zdz=|!nPS;@)I`D8h!`DvR0ITDlk_+4Lmh=4bY6e$EfH-iq0htx4Igu`zxv6=@nfZAPMh2D^n@?{4Ir&ZnUW5*~yxz|pbWetBr^5k`PR{&;22>}2A delta 24 gcmZpuZ>rzWW5*~txz|pbO-JFuJHJbl*VtVF0DK?{p8x;= diff --git a/frontend/src/assets/sources/41dd89d6-276c-41ac-ae6c-71c6e9df9910.png b/frontend/src/assets/sources/41dd89d6-276c-41ac-ae6c-71c6e9df9910.png index d6a8c253192d4e8de27f6aaa733c9a0ce6dde292..85e37a600034c58093b74cb51d11e9b5405de41e 100644 GIT binary patch delta 41 vcmewo{2_Qlye6agKQE)+Gaw>x%|7<4D$y3%DBnZQ$U4bU~r==CAmM|Dv8u;{mJ_OV)3YYfGO-xVq zNzF?y$zU)vFf!RVT|@?`0HGhOAUrb#C~szL`r&PdBT!m$vetT8j;|{wv4J^(>t$KK zKR16rxn#X2qsrvQ4Z^Zm-L4@0B^and2Bc#0-Sxa2KT`|BfdX=10rn02903Ie%s>HI zkboGH)rO`Pxj!0#spUY^tN+*?va}s6ZNSMnGmoYEFbp zW^QU;ab|uV10T>Jpk3T|f8GbFo9w+_mQ6=N>F$%D$vNva85JfwZV;Zla=jqOz25yG z*T{hdZm#F$(ouL;DHRM90;`ckcASx^nT~>AQC1sJRvxTDdjlU(Lv5Xx5Ku@9D5L}A zUej{F0OT41xf+w_Zr}zAHC*$13l!1;YdX9^8YuMd*zHW9kP=wv=LSKb^PaJ9o;#Uu j<75SHkiSavvh(uG^FX0`n^(XRsFuOg)z4*}Q$iB}zpYhmy#tlV&&O#-w5hbY=nQ2z8K*B#QtvI!W!QA5Hm1=bc1_lYZY(Qp3YEFbp kW^QU;ab|uVgSm;>`3*7eKx!uM^pjypbCUfy`L^Fj0Q9FJ#sB~S delta 96 zcmX>$pYhCm#tlV&iXtVh5hbY=nQ2z8K*B#QtvI!W!Q4VeA#O_790mpksmT-lWOQ^C q9xe-=0^-7z2V_>H=0v(==BDNqXXfWI7@3*rDCnv;|C@Z(?;`+aY$7E9 diff --git a/frontend/src/assets/sources/5be6c92b-ae9c-4ad5-9db6-341981072313.png b/frontend/src/assets/sources/5be6c92b-ae9c-4ad5-9db6-341981072313.png index 29bc081fe1c4b051457a4a232f2480d49be07d18..ebcca7ee2229aca2d60f8fd37075e2bebae87d01 100644 GIT binary patch delta 127 zcmbOoIx%!ZwkD(K&7UOD$yvf~~`ZB^Lt`Q}v6`5&Pu0X;+Ev-1Ugu&3jsMtw! z`Q#g#o~jaX1p%2AsW}lYnYpQX#hLke43=gV0t@UC85kHOCVObfaNMkxcLH+6C+BHN V3#{R9NCt8kJYD@<);T3K0RU9mCmR3& delta 159 zcmbOjIy-bjwkD(a&HXVf>KXgt{?$p$m6D@I#C`qlzOtW$Y68>pv#i=C>h6YAD z3J;2A%$$5h)00tZvYeJotd7DzM!pgT1_mj(j)2UH)SO6{%-qzx;>`R!1|tIl9R;3) t3nl_fJmH^dc=A|XQELeI`Do|DeE*p?pk(v|Xl9`*DSDcxj$6#t;;As6~BS_8U8_qHU(fS7;067ev Lu6{1-oD!Mbjdc`0&StIws$%eT L^>bP0l+XkK?@lE) diff --git a/frontend/src/assets/sources/7321fe44-7967-4544-bc9a-38c1e6bff97f.png b/frontend/src/assets/sources/7321fe44-7967-4544-bc9a-38c1e6bff97f.png index bd0e485cb8b2d245057f12e7ae7c4edcd2d8ecba..55934b74aac28a699aa939f5ef13381e2a83acf0 100644 GIT binary patch delta 88 zcmX?5ysLOanuW7aiEBhjYDH$6l`D|&PfIIKEnzUXIC-U7oq>Tt0xlbnS&^C(;gXq~ inpd2epT}TnX)yEgsyQGvlh<0vusjKwe{}MBi;n=qlp)Rl delta 94 zcmdm0e4uzknuWVaiEBhjYDH$6l`D|&PfIIKEnzUX&{2q+(lv*Hfk6r`ACOs*niJuY onVXtdoSC1;U}3aPdpcB9N-dw{>OMbQBJAJw3hox2^yq07%RsW&i*H diff --git a/frontend/src/assets/sources/7cd62665-7458-436f-b19e-5f55f42b1887.png b/frontend/src/assets/sources/7cd62665-7458-436f-b19e-5f55f42b1887.png index 4d3de6059915b268d01505029fa934bafdd69a07..8f84cd47fc57eb4774c837890f94fae69abccab5 100644 GIT binary patch delta 102 zcmdnzx6N4L;l%Jo(v2OLU2h}pbG!AwBpnf s1|zdz=|!nPS&7N7)MPjutzT>ea|G071oBGKtAQK_Pgg&ebxsLQ0M33NUjP6A delta 133 zcmdnyx6g0GDz!A>64!{5)QZeBE9d;2{G#B3#N<>4Lmh=4pF_@T|EPoTcX7bb& FEdYs3DM|nU delta 104 zcmdmfl5zh@#tpnF4#Fj_5hbY=nQ2ze`8oMT!3BxQsSJiX3O&Y$lNcBnMBvh{KsEkp wX~n4}43-8u3L7HUhy&%NCVQsHaOo%rbiNe?b8}N<*mM*&hw^0Wvr^Gd)B()+l%_<+UZ*CbqoWWz-Om}sEpd$~Nv+6CvkJ(p fNX?0K$;?g7E6&W%V=y)_&`~g4*r_o2lUfb{&te%j diff --git a/frontend/src/assets/sources/940b2b83-e259-4fa5-b601-a7608d078e92.png b/frontend/src/assets/sources/940b2b83-e259-4fa5-b601-a7608d078e92.png new file mode 100644 index 0000000000000000000000000000000000000000..8f24cf8968fda6ff1b763231cf74229cd6b42f44 GIT binary patch literal 4971 zcmY*dcQ_kf_m6}K5?VE)O2nv9t-UuPwo>y;QKhz0irTCF8a1k^z165ql~`?*7O|`L ztQm^Ls#)H=zrWt!xzD-hKKDN7&d)jbo*Q@H5DlZfNech~U^?0;6SC|jvpEDz&f_Jg ztI2}vv9^f;01$K=0EmbI0M5u&5d;9>xhMdzWe)(zX8-`K-Z`ztisS~cgB}_MxcYA@ z=qP(juA%YPw(-ifipX~p&6#*p*<>d9J|}CT=PlM>aapZ z%AWGLv>v#Wu?ESLyR&*(&n?xB5wR1$iTPd;CpIeiUC4_4rHSsD%eW9#ZpxCXFoO_- z$Y&;+{bh)sp7%=}cD{zL&6hZovxC@>*`9yopV_7$(f0LJc~~Hrs6^Zd9wHtqeDS4+ z{|}kc^XwyHcFLLEVyW-s-AK3>u{vk}MBt9&Ey{~meN)Eop5545$;z+e_yqL&x}QCy z+=~(aT&PtTq!7g=VHX~(h(8N1$pDPxep0m(kOGPqU|!-04V7McD*cuMd`E@CreM>i zvar^*bN$vWlEiq)>_b61aYszUEzHpylUu4*#7eI$)9*8h4o@el-Kr^lzWO)PV-fJ* z5(E}YC7HF-dB%+m)1`A9JYQ`RbdZ45nM(Qx*Bq%AQu+(PP&S8ZP|dNUuDQtAE7sfE zh7r4Xw8~^uuAHfrn=b>hBiIQ|6?F7}(zcK>oPX;He+L>=1r6YXG1oittyB?%WryK5 z1u&N;pqnr6dX;~+?c&Ji<$a}+-B`|_x?P5QZ1*U~IHOS?4kWlfhtrp|4Jv!V+Ut9=h}g$6L*4aK#B|(!X9Y;tWwEx0W}jZ^_`Ht z#uD5|Wyk3sW5pdWlVAzPxz(Y)mjmED26C66`V%-D8p{Rf`)<#V4}wq0O1i!6?@a99 zoH<_@#d~v-Our{BFf~36)d+8wc}CN85e+lQ36cck@nSQ5%@rq-zX?nR)tW!qA}lSn z%4RZTQ!~m_&gIt^j~N`?gtBNRH^k`;PlbPb+B{DuNkK90d6eYZsiZWUM+}2W z)&g4QX3l7KmZwyFNmONLA((MxXEV6vx7eE33R?^wri?oHx&#QRS=StI-Po26uL(<~!(6-c6W zBV{>OpgE?d;!mY5uq3M}hz>oC&cr!1NZGs8)hqgO7MFTzD7V|EQ;0dW&F$=HC^TM6 zjqh*OIfJ=TYlwwse=z@PeAVNta^*#*F>|fw)Z++GS6Zk#U+IOWF@Lj&$%v_MJq2b%a`R^uzp@s2-$as zVLh|cNflR(MSo^zML5I?j^Z%cvgD~IMD`0VR7kO906ZiHy+j3~3Yr7+d;?EltQkLBzySF#@>mo!u>tjIFjh11T=fr z(|!D}hR*#INjJD?PM!ynzx_2&O5g7744p0AU}JC?-_WlEHKFMkKj_|G=o;5k|qrLib2iv z``QS5|EAl*^rG_(lI2i5>ZUB=L20cRd9OksMNC6OiGE(TUB=R?W-E&v-D(K7O|*sR z`8bTMD}MLjO`p@L_KdB zYZWpqJp1n>n)ey;Ty>kEk-d3S8scw8IVSwPdk5m+<(G2#C6qdbpx1!$Xsyi4eg6lSazvOv|IEWP%b zVw+=CFmY@zfPF`Klo<*Iqf?Gp|1On8WLp~JH_I^rasTePz_CLcP%PC+wCl5IwPV-K z-V!OR){+)(tEAlz)TL+j2*4fkIy|%H>|HR2_+NfYZ70@Tb9yDa(qf{NY(gvTmy=yI7r(#RA`KMkKdH1^1VBnrgdhvl+V^|0U*65O${!^r|`Ux1^ z16D&_uccC^3weOqkMt;=0S(B==(Cx|aIJ8q)E7%R;n8=`pyfuue9%3uw$vCfyo^p5 zf{jc3KcAUGzSzaj>Ie#v6^t8&S$PSHXo-{171}^HOGg{Bf0v3zMIidimFMcIumKVD zDPZuw#+a|{O~u8L!K3cix;P97zh?%J2>)S|S)+~8M*2(Z0@oY#t!D5YSG zZzQ}ccq~ah``H(&c8}gi_pfuHa)99w{hQyN2$X362D~R0OxD+)s%aWcZ!toYz8H?p z+k=y$=Azu~?|)!(oYCYSp6yD3D@1IJQY&qXalcd3q+y&WtGa@OGS7OCiv2T^UA;`` zcY}&Sg^W__Yz42Zm)emz$kq`H_H8uL%Z6@(y};j08*|gE`vG&T9jqYt)q~8oJ5tdx zBNns+m7;?3F-+mAPm`4Z+jQ8tKeRQknv0&cRUEO^$SvJ&#i!(V;O0+`g{R)t7guB$ zxCzP>e)T_eU8<(=TYBb+w2V_O>Ju4Aa|8V^ML%Zd(dBr=yPgyO*=w4vtU^8;-)dIf z*V6eq#DZFXprgkDz56gS&_tC*R`b&9X{N;@#+o{Azy~N$T0o?8)sqGXTUqQcAl{_C zm$}}7;QRL>`O*$X_(U{S?dVE_6_g%H;D#I@i{`R=aR&vgVr^vYeH+9AV@hs&psVj| zgwW0$S6kSw%{w-}8|-vI_pcn`4?>Z*tPo;l;EdNz4u2~2jPm$5HVRcanAB@R!lM>u z-*zs~w~OmjerKwvje1^C?esQYM`ju>ytzC2%%kP6bkKu$teYOKTN?Hnyz9bW9d5*n zl0-~M=1hy~N$c15FK&1v&+t(S@70KJPqNfud+a8OYCFLtaJq}^?oYfP=%>U_vE}UN zDiM3CwBJ4jCLx)V*W_?^x9BNU04#ya847zpWWBE;1Xq({gV90 zk}-2dauo()1%1KLW1Y5hN+wG=<&kTG?l4la3wqqZ#I9OEORp_w+~~Y4!o9?>2IyaW zA~XWMmc`M0e~w`w#d&nDO?iup=7NtT`*$%aNB!yGf-Qc?hW_}-SUhW@Pun8F_KgZ1 zmf13XIY>Bbq=tL^M?EpNJ7<)!M}Mhb9N!MEN+mwq%LC1^WUd6#DF3rC9`mHqfa8VjRzLCH~Gq##{jpZ#WYcjb{bSj2yrHS-|SxTnM)+ zpf@_~PEVejSXJ4FK6|XVXu*1NlxJ|1%d^5a&@$~e&Pw}UqBL2Nl5c3H{i)l*k2|H% z$7gKseSaBY!v68a_@Rwwa%-G;wCSq}poJREbHBUkZ+w9yK>V1~&v4DpUw~L{M&Iwn zxxDU<6=Cmjjjj|jg;?By{tNEfPL*c%13LnwbJdeUZdzNXS=s|1?iDpRf&vPYLpvyX zbMcG9sa?-;0sGD|j7#>mtu2~^e^VEp;|6iNCIQRO^4ykz?x~5LJ3owBK`QU89J##> z`rFT_${f9hAK7EQKE6SOn*ONc2ZfWtl1*3~TvE*Rk&leg-^m{;t-J@c zB}7l95md%B2jt9_`wA?Y`425fWE*)MYa^Aq3$hd@5$vw0e)6(MS8M)!Y{2V(VoKU7 zZnU~nS0VC)#^($7@@wGpCxH4J%=5gwkl*ubMwqDg>wJNeH9>4H|i&QY&xIdin z`Rt+D^NHy{BQ)+xn+vI9nvvsVtDUYfu9>P=A(z~F*DoqxS0I<>?rY3_cYww7Yf@uX zR~G>By)^VnA!(N z@MlwYjzkRdn2uWJuj#rmf}0mF}uf^RN+9cq0zRZq1(8!4;77_I<`MZ15WxXbmT`&eQnat;Gu;4L+k;$IG z2L$uwd8(%j1M;cE9xO{gO{XZEAKSPm=)j`<8Nv3By(RC_ zvnc2H`OKLsRRZZAg3&O=$B-h0nJMjoQ%JeSbxp+OwG>@zdB_Wy6c1<< z+F@we=_eiQ$$H3=$7%Ch=P1AT8mn4^>HGV+EF3OrJ^C#y2}-j`0{~9%N6UT z05-y?pv8kB@OMoI!<|R3h6KX}iT+i39ODV2b->eS|9VvB9 z_#|-2kum?fr3quhvy2*&%p7>Yh+s;!LAb@%3Z)FmXG)dE1~w|n$z;TJCxz+Mgf#aS zTjWv;GyCv!`Ah)#H64a_7MRb~mOYkAJX-PYw=eG_F`Y>3V5YWZ)Knh27HW20txgpUdo8T8pz&q`Dt2`ECS1P;%8gDjyb4y=yN@a zwIjw64y}wQ_&2VLMrcZG)u}I{hH3UR$E_N~uy+`Jz0e{o>rYy|^9XyKCG$}8Yzqdt zjy3MgyPxX6I#}gd4sm&&M04)F?W z&dLN<_mN$M>r!-=_@DN(hlQ_BZY6J$I2soxfN|~*$Ue=MwYhnqa*@0*i~PA-eaBxI zx!*@btAFO_wbK!%Uwu~_ou|N%jt`*zW|Gd+XZGQ_6LeM)L+I%el4Q= z#(g;b^*lHeebmMuIo=Y2|M-%dkwrb>=cLAdKoM@Kk-5XyCkLaa^OxCV>fzF{i}9w8 zYdXu)ReO+8Ir6f~5;nWK5qg{xo9+2R!m3bS+iA>O%z;Snf{MW1M{U_(~y8kjbTa*?IZp Qc?>42ycd3++;t)x0NGzLc>n+a delta 151 zcmcaUk@?|7<_$-W$%&S@MwFyhWTsiU0tx@LwBpnf216rL9R+_Ax9O7~9t+TxgDWY? zD9ugEOU%r%a?Z~!C`v6Z&dkqaFw;?ZRw)(Cz`&q2x$n3JAA_->v5rDS*RBmfAw!^$ tF`JG;oA-{U$sdl3Prh?}k_b1*#L~R%y!`S!1`{2HyT>kFn%rcR` J{@aZ4G63d)H3t9y delta 216 zcmdn@p5@$omWC~i=B5hbC9V-AsTG-NR?hi3`9;A6iOH!9W~QdbraB5ce(0Q@9%{;H z;3*1Mkkh1BgOc`a_bQHE3HJ7#kYs vC`6rMc?lFV0*RRb)vzyqUkl_bPCsJCs0=hF)nVGV=?Bah#iuiwGwuNZfLBAv diff --git a/frontend/src/assets/sources/986139aa-d14b-4215-bdd1-f25f812741b0.png b/frontend/src/assets/sources/986139aa-d14b-4215-bdd1-f25f812741b0.png index a12d1a5b177e37c907a6130ad6798695230403f2..e57ec1c6f1bce172bed4bdb90e540438c2084008 100644 GIT binary patch delta 102 zcmeAxX)D=KWoaW=;u=wsT9KJ%<(!|BUld%Bn4HRB$UmFOlYxOj2rlUgRNi;u=wsT9KJ%<(!|BUld%Bn4HRBsH4zhd^m}Lfk6Z=?Fv-mpO#jf zTEbv%p`#EtrE3mQUJ5QBkXezM6XBAXo0?agnV-jCX>6vWaMcP?&&pB|&&WPd$T4*uCpo(v2OLX-3K#5gXT_eukDBqsOi$!N6Jhg<@2N?apK lQY$jktO7DCQgb3*GILY&iZk=`7>rDfyqLPQCtuTR0026~8hHQ! delta 86 zcmX>XcP(y%pB|&|WPd$TEggj(0N8y>q l+n+#rsmWb>GF&4L;l%Jo(v2OLU2h}pbG!AwBpnf t1|zdz=|!nPS&7L%Y-Kq1?>n*t%#pK`5x8x;P#VZ#@O1TaS?83{1OO~iAtnF- delta 133 zcmX?7bEam)4%;;064!{5)QZeBE9d;2{G#B3#N<>4Lmh=4H`OW4T>=_q(7 S-f{qP89ZJ6T-G@yGywoYEh|p| diff --git a/frontend/src/assets/sources/ab4c5504-d780-4da6-b512-4fbb0ab05d7e.png b/frontend/src/assets/sources/ab4c5504-d780-4da6-b512-4fbb0ab05d7e.png index 693c187dffe77c9a9075d07f3767bb42307426e9..37a7ec46ae6329daf68bb32a647dee314a782179 100644 GIT binary patch delta 245 zcmdmTnsM1_#tn0m7^No9OOoQT&{41udTXc7z`!6l`9P8=3;%2;&&juw3>1V*Tq8BopT!DmtT3T^x34@`z#hq(mbwJf3lXa6NIL`0Yt^sm{C;KOhv#d>g`)qPfvL>U- z3$HqTNZ delta 253 zcmZ2>nsLi%#tn0m7{w;fOOjHa;h){az`!6};u=wsT9KJ%<(!|BUld%Bn4HRBsH4zh zd^l(aC(t;#@ik1xBjhfa=92>n2M8xj7pm=K;B*lYNuL*>n`9O4@}_&Pdjr z{4hmi^3r5Mj(ffPYk~4|lM7RXg`M+r3yM;Ui!<}{7|e7Oo>fW(PrjETKKXAlKhUU# zYS&jlrSc%9lhsrBfIBs~PepAB`|@5r!*q z1*-E;ODj$-VK6kaIC?hSo`Hcu0xlhpS&^C(;gXq~npd2epT}TqY}WoG=_^RhWZOs? zmfN-qr6t<8 delta 271 zcmdnImGSUa#tlm&6vRthBT7;$GSjS_^Kej`FRY+#%4MSogYuX z#Z(oEP-SRfprhcOc*_B(N(XLMaDG}zd16uO`F*4YAA_+0Na(M;9Z<*+C}hl~qp(EJ#|g+)oU9e4%%-D|>M-rw IejbCFk%5lFUxj!tkgCZU-ZE@D3JMcGEtuTl{Sg3rWg%?< diff --git a/frontend/src/assets/sources/c8f4312f-ac8f-4118-8b80-81d5076e8d32.png b/frontend/src/assets/sources/c8f4312f-ac8f-4118-8b80-81d5076e8d32.png index 19bced574a0add3dbcf6135c31cfcb6c58aa0c68..d6295ef3119e17b1b3aa8871dd283c3fcaa90bd6 100644 GIT binary patch delta 48 zcmeyS{y}|%f-s}dWJO^yj$r9UsSFGZl9L^UWjO*@6lVZA5|cB8WmrxaS@=xu63zht DL8T1d delta 77 zcmeyM{!M*@f-s}VWJO^yE**vBE8$BR7#O4{+Y8I;=qRYKJ1GI=N|m@ql%!T zCiiVq;P{zZ5Dt{nocw;9#^eXvSULQeyG{cI^nn7#EG4%}ohLVJ7oTjuU4TW^A?`Am Ile4`A0ExIhy#N3J delta 182 zcmaFxp6SDTrVW#~$_SUZMwFyhWTsg;=jY@X1s5bHr!pAoDD)T~PMW-Ss{y0fr&c~0h0HDDB;Y^y5H!5Ja>n}LBrVsf0SjE0Az;8hT( z#5JNMwIVakDj>5WH7C*~GdDG_I5R(w!Pvmy#?I2x$;*KHWhOJK2~U2d%FFRHwICd* yO#>*P!%^cdCkEu`067|yn_oj1MPG=2A6K5-o9!C`qlzOtW$Y68>pv#i=C>hNfmZ z3Ky0hC}&_`keVE&D#N9taJ7;_0L-mZl>r)HxUf@U@;p@oM!Cu7RTY5p&nl&Yf%00D zwbeBE7>q1UbQG2fuFV1p=>dfdfGQNE+xG*xij$Molz}FsI!yaEIbKbC^Fp-_MgUE# BEw%sv diff --git a/frontend/src/assets/sources/db607b32-d7f9-48df-a659-fdcba3945c35.png b/frontend/src/assets/sources/db607b32-d7f9-48df-a659-fdcba3945c35.png index 76449cb60d29b8fbe11dcb6c45fba279a03bd0cc..47e8e032e5f6c1238dbaae2bcad47c966ba6e8ee 100644 GIT binary patch delta 146 zcmbPtl(Fw9;|9J2M$yUq36dvm!Mo(j_xDHLo}`KaauKz~ugwjX9G~B-k*@OlD0~;P{zZ5DwI$ uFgE1<;kZLF9QH)k1yT; delta 143 zcmeA>$~f;R;|9J2M)Aq~36g9&3Oj!2oSv+cV8AFkIW|F@OGn{EpVMRp1_r6gH3>36 zuEc~>C1CD?1R0=mvlWVeCLc(!VU(NvH$ed?|Ey9f7$~nbIWkd$kHOf$3@G$h-VP{a j2oy2~8TirK49HcSJS9;XXhN#Pv~QCqB#KYIl(+`~a$zj? diff --git a/frontend/src/assets/sources/dbdf1511-ed54-449b-9882-2abfd6a98d29.png b/frontend/src/assets/sources/dbdf1511-ed54-449b-9882-2abfd6a98d29.png index aa1485c865ce3c54c4e27fb8139f8371985c7e10..9fd8c6dc4e6f5918c201274f107b691a880b1042 100644 GIT binary patch delta 89 zcmdnuxXy9IM0ppX64!{5)QZeBD_0=lpO#jfTEbvy5ZQBYHUk5LBwRKivm!Mo!X+~| kHLo}`KaauC)Y3B3+pr0!NMiC$c^Q_H*G(alf6MO#0HmTH;Q#;t delta 94 zcmZ4IxW#e9M0rJ#64!{5)QZeBD_0=lpO#jfTEbvyprf!MVvRTh1B3MB4f3)&IttQn pPbmVqQgGz~nH8xykuI6Jsd>ej`FRY+M&>#S^PY$6P5vss69C^QATC$+v`LSa#SfV4M6$NDBb^ CK_+ql delta 125 zcmbQIwoGk9iI9VEiEBhjYDH$6m2-Yheo=5iVsa{jp^ie2@!=!}1_lwhv@1}Je_C2` zY6*j-fsVq4h&AFsd8x@8gk*Gd6s}e>2!Ob7z=YTR-Xi!&Gu&2l(TMo(_Eb!3#EeArf*@d9r}R9Y*2FZym&0 OGUmPx-OS~9n;ih@FK=W3 delta 293 zcmX>-k@4w7#trwZ8O0~xx0YnnQBc^?b#w9`>)CRmC9V-AsTG-NR<1z8KP{~|wS>XQ z(m+SyW?bdk$(wDw7)2-lvk~XgQJ7ujD9pgXATe3iRtjiD)c@CvldWylB>3S*xaA}k zXD}F==_vdtJS{!B+}4p%aq>=EWuWTt%eMTRAK3CR0*!lXCk_;exTIJ+nZsU>QF*et zy(-XrkE;g(x7h)Pabk@C diff --git a/frontend/src/assets/sources/e3f229a1-8637-49b1-abaa-84d228aff34a.png b/frontend/src/assets/sources/e3f229a1-8637-49b1-abaa-84d228aff34a.png index 4c128a7f36b758836a653f844ad128b655197817..4ce1917b80197e2d2a46c9817cf04cd5dd582133 100644 GIT binary patch delta 167 zcmZ4IH_vZ_z6zt@WCImZ7XH~xo|C;*3>1V*Tq8BopT!DmtT3T^x34@`T$(d?x z5e5bZiOF+SWHbso<6=P^xY~fsiqxD)m(1MMyyDFKJO*PU^ODz1A(Nk~STV{>R!~*o z_?cP|4%DJCxj|Kfhr!su$WVE_)2v*9gnwFEacT*Jp_z$} z!oexKzcVl}NKKxpBEzMlaKNGL7nr+OMFwcVyyxM1lkcinG0IJrP*niRKdY1q2Fhzq zc2Ly;avy%#{s_o51adVd&r#(D3LTAJ`~)bZIC;IQGSGxnhiTs?GpdPieyeK82msEW BG3x*T diff --git a/frontend/src/assets/sources/f12e6c9c-f38d-4468-b158-656c096e21b8.png b/frontend/src/assets/sources/f12e6c9c-f38d-4468-b158-656c096e21b8.png index 9b4a998aa5abc062c3cb77f5cdbf2ae6ec62f941..e25d830fbb769551b6e3d8df4718e1658499efd2 100644 GIT binary patch delta 23 fcmZqN#`u3LF#wbF3xogw