/* DESCRIPTION: Any functions that are used internally by the use-case */ package soapi import ( "errors" "fmt" erc "simrs-vx/internal/domain/references/common" pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" "time" dg "github.com/karincake/apem/db-gorm-pg" "gorm.io/gorm" ere "simrs-vx/internal/domain/references/encounter" ecpl "simrs-vx/internal/domain/main-entities/chemo-plan" ecp "simrs-vx/internal/domain/main-entities/chemo-protocol" ee "simrs-vx/internal/domain/main-entities/encounter" e "simrs-vx/internal/domain/main-entities/soapi" ) func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Soapi) { var inputSrc *e.CreateDto if inputT, ok := any(input).(*e.CreateDto); ok { inputSrc = inputT } else { inputTemp := any(input).(*e.UpdateDto) inputSrc = &inputTemp.CreateDto } data.Encounter_Id = inputSrc.Encounter_Id data.Employee_Id = inputSrc.AuthInfo.Employee_Id data.Time = inputSrc.Time data.TypeCode = inputSrc.TypeCode data.Value = inputSrc.Value } func setBulkData(input []e.CreateDto, encounterId uint) []e.Soapi { var data []e.Soapi for _, v := range input { data = append(data, e.Soapi{ Encounter_Id: &encounterId, Employee_Id: v.Employee_Id, Time: v.Time, TypeCode: v.TypeCode, Value: v.Value, }) } return data } func validateIfEncounterIsChemo(encounterId uint, event *pl.Event) (*ecpl.ChemoPlan, error) { // get encounter enc, err := getEncounter(encounterId, event) if err != nil { return nil, err } // Encounter must be Ambulatory and NOT Rehab a := enc.Ambulatory if enc.Class_Code != ere.ECAmbulatory || a == nil || a.Class_Code == ere.ACCRehab { return nil, nil } // get chemo protocol chemo, err := getChemo(*enc.Patient_Id, event) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, nil } return nil, pl.SetLogError(event, nil) } if err = chemoProtocoValidation(chemo, event); err != nil { } if chemo.ChemoPlans == nil || len(*chemo.ChemoPlans) == 0 { return nil, nil } // Return the first chemo plan return &(*chemo.ChemoPlans)[0], nil } func chemoProtocoValidation(chemo *ecp.ChemoProtocol, event *pl.Event) error { if chemo.Status_Code != erc.DVCVerified { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ Code: "data-not-match", Detail: fmt.Sprintf("protocol chemo not yet verified"), } return pl.SetLogError(event, chemo) } now := time.Now() if now.Before(*chemo.StartDate) || now.After(*chemo.EndDate) { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ Code: "invalid-date-range", Detail: "chemo cannot be performed because the current date is outside the allowed treatment window.", } return pl.SetLogError(event, chemo) } return nil } func getEncounter(encounterId uint, event *pl.Event) (*ee.Encounter, error) { pl.SetLogInfo(event, nil, "started", "getEncounter") data := ee.Encounter{} var tx = dg.I if err := tx.Model(&ee.Encounter{}). Where(`"Encounter_Id" = ?`, encounterId). Scopes(withConditionalAmbulatory()). First(&data).Error; err != nil { if processedErr := pu.HandleReadError(err, event, source, nil, encounterId); processedErr != nil { return nil, processedErr } } pl.SetLogInfo(event, nil, "complete") return &data, nil } func withConditionalAmbulatory() func(db *gorm.DB) *gorm.DB { return func(db *gorm.DB) *gorm.DB { return db.Preload(`"Ambulatory"`, func(db *gorm.DB) *gorm.DB { return db.Joins(`JOIN "Encounter" e ON "e"."Id" = "Ambulatory"."Encounter_Id"`) }) } } func getChemo(patientId uint, event *pl.Event) (*ecp.ChemoProtocol, error) { pl.SetLogInfo(event, nil, "started", "getChemoFromEncounter") data := ecp.ChemoProtocol{} var tx = dg.I tx = tx.Model(&ecp.ChemoProtocol{}). Joins(`"ChemoPlan" cp ON cp."Protocol_Id" = "ChemoProtocol"."Id"`). Where(`"Patient.Id" = ? AND cp."Status" = ?`, patientId, ere.SPCPlanned). Preload("ChemoPlans", func(db *gorm.DB) *gorm.DB { return tx.Order(`"Id" ASC`).Limit(1) }). First(&data) if err := tx.Error; err != nil { return nil, err } pl.SetLogInfo(event, nil, "complete") return &data, nil }