From cfdfac223f9b9c6b08769abc745daa8975e544e8 Mon Sep 17 00:00:00 2001 From: vanilia Date: Fri, 12 Dec 2025 13:48:34 +0700 Subject: [PATCH] protocol chemo finish --- .../domain/main-entities/chemo-plan/dto.go | 43 ++++----- .../domain/main-entities/chemo-plan/entity.go | 22 ++--- internal/domain/main-entities/chemo/dto.go | 1 + .../main-handler/chemo-plan/handler.go | 88 +++++++++++++++++++ .../main-handler/chemo-protocol/handler.go | 5 +- .../interface/main-handler/main-handler.go | 4 + .../use-case/main-use-case/chemo-plan/case.go | 6 +- .../main-use-case/chemo-plan/helper.go | 18 ++-- .../use-case/main-use-case/chemo-plan/lib.go | 12 ++- .../use-case/main-use-case/chemo/helper.go | 1 + internal/use-case/main-use-case/chemo/lib.go | 5 ++ .../main-use-case/encounter/helper.go | 86 ++++++++++++++---- internal/use-case/main-use-case/soapi/case.go | 16 +++- .../use-case/main-use-case/soapi/helper.go | 74 ++++------------ 14 files changed, 261 insertions(+), 120 deletions(-) create mode 100644 internal/interface/main-handler/chemo-plan/handler.go diff --git a/internal/domain/main-entities/chemo-plan/dto.go b/internal/domain/main-entities/chemo-plan/dto.go index c5e9cb11..29f47a70 100644 --- a/internal/domain/main-entities/chemo-plan/dto.go +++ b/internal/domain/main-entities/chemo-plan/dto.go @@ -11,14 +11,14 @@ import ( ) type CreateDto struct { - Parent_Id *uint `json:"parent_id"` - SeriesNumber *uint16 `json:"seriesNumber"` - CycleNumber *uint `json:"cycleNumber"` - PlanDate *time.Time `json:"planDate"` - RealizationDate *time.Time `json:"realizationDate"` - Notes *string `json:"notes"` - Status ere.StatusProtocolChemo `json:"status"` - Encounter_Id *uint `json:"encounter_id"` + Parent_Id *uint `json:"parent_id"` + SeriesNumber *uint16 `json:"seriesNumber"` + CycleNumber *uint `json:"cycleNumber"` + PlanDate *time.Time `json:"planDate"` + RealizationDate *time.Time `json:"realizationDate"` + Notes *string `json:"notes"` + Status *ere.StatusProtocolChemo `json:"status"` + Encounter_Id *uint `json:"encounter_id"` } type ReadListDto struct { @@ -47,12 +47,13 @@ type DeleteDto struct { } type FailDto struct { - Id uint `json:"id"` - Reasons *string `json:"reason"` + Id uint `json:"id"` + Reasons string `json:"reasons" validate:"required"` } type FailReason struct { - Date *time.Time `json:"date"` - FailReason *string `json:"failReason"` + Date *time.Time `json:"date"` + FailReason string `json:"failReason"` + Encounter_Id *uint `json:"encounter_id"` } type MetaDto struct { @@ -63,15 +64,15 @@ type MetaDto struct { type ResponseDto struct { ecore.Main - Parent_Id *uint `json:"parent_id"` // chemo.Id - Protocol_Id *uint `json:"protocol_id"` - SeriesNumber *uint16 `json:"seriesNumber"` // series ke - - CycleNumber *uint `json:"cycleNumber"` // cycle ke - - PlanDate *time.Time `json:"planDate"` - RealizationDate *time.Time `json:"realizationDate"` - Notes *string `json:"notes"` - Status ere.StatusProtocolChemo `json:"status"` - Reasons *string `json:"reasons"` + Parent_Id *uint `json:"parent_id"` // chemo.Id + Protocol_Id *uint `json:"protocol_id"` + SeriesNumber *uint16 `json:"seriesNumber"` // series ke - + CycleNumber *uint `json:"cycleNumber"` // cycle ke - + PlanDate *time.Time `json:"planDate"` + RealizationDate *time.Time `json:"realizationDate"` + Notes *string `json:"notes"` + Status *ere.StatusProtocolChemo `json:"status"` + Reasons *string `json:"reasons"` } func (d ChemoPlan) ToResponse() ResponseDto { diff --git a/internal/domain/main-entities/chemo-plan/entity.go b/internal/domain/main-entities/chemo-plan/entity.go index 1fef099e..3698039f 100644 --- a/internal/domain/main-entities/chemo-plan/entity.go +++ b/internal/domain/main-entities/chemo-plan/entity.go @@ -11,15 +11,15 @@ import ( type ChemoPlan struct { ecore.Main - Parent_Id *uint `json:"parent_id"` // chemo.Id - Protocol_Id *uint `json:"protocol_id"` - SeriesNumber *uint16 `json:"seriesNumber"` // series ke - - CycleNumber *uint `json:"cycleNumber"` // cycle ke - - PlanDate *time.Time `json:"planDate"` - RealizationDate *time.Time `json:"realizationDate"` - Notes *string `json:"notes"` - Status ere.StatusProtocolChemo `json:"status"` - Encounter_Id *uint `json:"encounter_id"` - Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` - Reasons *string `json:"reasons"` // json + Parent_Id *uint `json:"parent_id"` // chemo.Id + Protocol_Id *uint `json:"protocol_id"` + SeriesNumber *uint16 `json:"seriesNumber"` // series ke - + CycleNumber *uint `json:"cycleNumber"` // cycle ke - + PlanDate *time.Time `json:"planDate"` + RealizationDate *time.Time `json:"realizationDate"` + Notes *string `json:"notes"` + Status *ere.StatusProtocolChemo `json:"status"` + Encounter_Id *uint `json:"encounter_id"` + Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` + Reasons *string `json:"reasons"` // json } diff --git a/internal/domain/main-entities/chemo/dto.go b/internal/domain/main-entities/chemo/dto.go index 737027fb..7a74acf6 100644 --- a/internal/domain/main-entities/chemo/dto.go +++ b/internal/domain/main-entities/chemo/dto.go @@ -39,6 +39,7 @@ type FilterDto struct { VerifiedBy_User_Id *uint `json:"verifiedBy-user-id"` Specialist_Code *string `json:"specialist-code"` Patient_Id *uint `json:"patient-id"` + Class_Code ere.ChemoClassCode `json:"class-code"` } type ReadDetailDto struct { diff --git a/internal/interface/main-handler/chemo-plan/handler.go b/internal/interface/main-handler/chemo-plan/handler.go new file mode 100644 index 00000000..215797b0 --- /dev/null +++ b/internal/interface/main-handler/chemo-plan/handler.go @@ -0,0 +1,88 @@ +package chemo_protocol + +import ( + "net/http" + + rw "github.com/karincake/risoles" + sf "github.com/karincake/semprit" + + e "simrs-vx/internal/domain/main-entities/chemo-plan" + ep "simrs-vx/internal/domain/main-entities/chemo-protocol" + u "simrs-vx/internal/use-case/main-use-case/chemo-plan" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := ep.CreateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + sf.UrlQueryParam(&dto, *r.URL) + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + dto := e.ReadDetailDto{} + sf.UrlQueryParam(&dto, *r.URL) + + dto.Id = uint(id) + res, err := u.ReadDetail(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Id = uint(id) + res, err := u.Update(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.DeleteDto{} + dto.Id = uint(id) + res, err := u.Delete(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Fail(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.FailDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + + dto.Id = uint(id) + res, err := u.Fail(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/main-handler/chemo-protocol/handler.go b/internal/interface/main-handler/chemo-protocol/handler.go index 92410188..4ac8d90f 100644 --- a/internal/interface/main-handler/chemo-protocol/handler.go +++ b/internal/interface/main-handler/chemo-protocol/handler.go @@ -81,11 +81,8 @@ func (obj myBase) Verify(w http.ResponseWriter, r *http.Request) { } dto := e.VerifyDto{} - if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { - return - } - dto.Id = uint(id) + authInfo, err := pa.GetAuthInfo(r) if err != nil { rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil) diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index 937246fb..be90705d 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -81,6 +81,7 @@ import ( /******************** sources ********************/ antibioticsrc "simrs-vx/internal/interface/main-handler/antibiotic-src" antibioticsrccat "simrs-vx/internal/interface/main-handler/antibiotic-src-category" + chemoplan "simrs-vx/internal/interface/main-handler/chemo-plan" chemoprotocol "simrs-vx/internal/interface/main-handler/chemo-protocol" device "simrs-vx/internal/interface/main-handler/device" diagnosesrc "simrs-vx/internal/interface/main-handler/diagnose-src" @@ -323,6 +324,9 @@ func SetRoutes() http.Handler { "PATCH /{id}/verify": chemoprotocol.O.Verify, "PATCH /{id}/reject": chemoprotocol.O.Reject, }) + hk.GroupRoutes("/v1/chemo-plan", r, auth.GuardMW, hk.MapHandlerFunc{ + "PATCH /{id}/fail": chemoplan.O.Fail, + }) hc.RegCrud(r, "/v1/upload-file", uploadfile.O) hc.RegCrud(r, "/v1/encounter-document", encounterdocument.O) hc.RegCrud(r, "/v1/general-consent", generalconsent.O) diff --git a/internal/use-case/main-use-case/chemo-plan/case.go b/internal/use-case/main-use-case/chemo-plan/case.go index 7f74b6f7..eff45b46 100644 --- a/internal/use-case/main-use-case/chemo-plan/case.go +++ b/internal/use-case/main-use-case/chemo-plan/case.go @@ -176,7 +176,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { return err } - if err := UpdateData(data, &event, tx); err != nil { + if err := UpdateData(data, "", &event, tx); err != nil { return err } @@ -284,7 +284,7 @@ func Fail(input e.FailDto) (*d.Data, error) { return nil, pl.SetLogError(&event, data) } - if data.Status != ere.SPCPlanned { + if *data.Status != ere.SPCPlanned { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ Code: "invalid-chemo-status", @@ -293,7 +293,7 @@ func Fail(input e.FailDto) (*d.Data, error) { } err = dg.I.Transaction(func(tx *gorm.DB) error { - if err := UpdateData(data, &event, tx); err != nil { + if err := UpdateFailData(input, data, &event, tx); err != nil { return err } diff --git a/internal/use-case/main-use-case/chemo-plan/helper.go b/internal/use-case/main-use-case/chemo-plan/helper.go index 5cf7ffd5..4d62f819 100644 --- a/internal/use-case/main-use-case/chemo-plan/helper.go +++ b/internal/use-case/main-use-case/chemo-plan/helper.go @@ -34,16 +34,23 @@ func setDataCreate(input *ep.CreateDto) (data []e.ChemoPlan) { return } -func setDataUpdate(data *e.ChemoPlan) { +func setDataCreateSoapi(data *e.ChemoPlan) { data.RealizationDate = &now status := ere.SPCComplete - data.Status = status + data.Status = &status +} + +func setDataDeleteSoapi(data *e.ChemoPlan) { + status := ere.SPCPlanned + data.Status = &status } func setDatafail(input e.FailDto, data *e.ChemoPlan) { data.RealizationDate = nil - data.Status = ere.SPCSchedule + + status := ere.SPCSchedule + data.Status = &status var reasons []e.FailReason @@ -52,8 +59,9 @@ func setDatafail(input e.FailDto, data *e.ChemoPlan) { } reasons = append(reasons, e.FailReason{ - FailReason: input.Reasons, - Date: &now, + FailReason: input.Reasons, + Date: &now, + Encounter_Id: data.Encounter_Id, }) if b, err := json.Marshal(reasons); err == nil { diff --git a/internal/use-case/main-use-case/chemo-plan/lib.go b/internal/use-case/main-use-case/chemo-plan/lib.go index 92d7c8eb..22d6259b 100644 --- a/internal/use-case/main-use-case/chemo-plan/lib.go +++ b/internal/use-case/main-use-case/chemo-plan/lib.go @@ -98,9 +98,15 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e return &data, nil } -func UpdateData(data *e.ChemoPlan, event *pl.Event, dbx ...*gorm.DB) error { +func UpdateData(data *e.ChemoPlan, method string, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, data, "started", "DBUpdate") - setDataUpdate(data) + + switch method { + case "c": + setDataCreateSoapi(data) + case "d": + setDataDeleteSoapi(data) + } var tx *gorm.DB if len(dbx) > 0 { @@ -148,7 +154,7 @@ func DeleteData(data *e.ChemoPlan, event *pl.Event, dbx ...*gorm.DB) error { func UpdateFailData(input e.FailDto, data *e.ChemoPlan, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, data, "started", "DBUpdate") - setDataUpdate(data) + setDatafail(input, data) var tx *gorm.DB if len(dbx) > 0 { diff --git a/internal/use-case/main-use-case/chemo/helper.go b/internal/use-case/main-use-case/chemo/helper.go index c241bce3..96012228 100644 --- a/internal/use-case/main-use-case/chemo/helper.go +++ b/internal/use-case/main-use-case/chemo/helper.go @@ -20,4 +20,5 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Chemo) { data.Encounter_Id = inputSrc.Encounter_Id data.Status_Code = inputSrc.Status_Code data.Specialist_Code = inputSrc.Specialist_Code + data.Class_Code = inputSrc.Class_Code } diff --git a/internal/use-case/main-use-case/chemo/lib.go b/internal/use-case/main-use-case/chemo/lib.go index 4b049c13..8b848d8f 100644 --- a/internal/use-case/main-use-case/chemo/lib.go +++ b/internal/use-case/main-use-case/chemo/lib.go @@ -47,6 +47,11 @@ func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.Ch tx = dg.I } + if input.Class_Code != "" { + tx = tx.Where(`"Chemo"."Class_Code" = ?`, input.Class_Code) + input.Class_Code = "" + } + tx = tx. Model(&e.Chemo{}). Joins(`LEFT JOIN "Encounter" "e" ON "e"."Id" = "Chemo"."Encounter_Id"`). diff --git a/internal/use-case/main-use-case/encounter/helper.go b/internal/use-case/main-use-case/encounter/helper.go index 0d822768..29d7fa9b 100644 --- a/internal/use-case/main-use-case/encounter/helper.go +++ b/internal/use-case/main-use-case/encounter/helper.go @@ -660,21 +660,24 @@ func insertdataClassCode(input e.CreateDto, soapiData []es.CreateDto, event *pl. func insertDataSubClassAmbulatory(input e.CreateDto, soapiData []es.CreateDto, event *pl.Event, tx *gorm.DB) (err error) { subCode := ere.AmbulatoryClassCode(*input.SubClass_Code) + var chemoPlan *ecpl.ChemoPlan switch { case subCode == ere.ACCChemo: // validate if encounter Chemo valid - chemoProtoc, err := validateChemoAdm(*input.Patient_Id, event) + chemoPlan, err = validateChemo(*input.Patient_Id, event) if err != nil { return err } - if chemoProtoc == nil { + if chemoPlan == nil { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ Code: "data-not-found", Detail: "chemo plan not found", } + + return pl.SetLogError(event, input) } chemoCreate := ec.CreateDto{ @@ -691,7 +694,8 @@ func insertDataSubClassAmbulatory(input e.CreateDto, soapiData []es.CreateDto, e } // set chemo-plan to planned - err = updateChemoPlan(chemoProtoc, event, tx) + chemoPlan.Encounter_Id = &input.Id + err = updateChemoPlan(chemoPlan, event, tx) if err != nil { return err } @@ -898,7 +902,10 @@ func updateChemoPlan(data *ecpl.ChemoPlan, event *pl.Event, dbx ...*gorm.DB) err tx = dg.I } - if err := tx.Model(&data).Update(`"Status"`, ere.SPCPlanned).Error; err != nil { + err := tx.Model(&data).Updates(map[string]interface{}{ + `"Status"`: ere.SPCPlanned, + `"Encounter_Id"`: data.Encounter_Id}).Error + if err != nil { return err } @@ -913,11 +920,15 @@ func getChemoProtocol(patientId uint, event *pl.Event) (*ecp.ChemoProtocol, erro var tx = dg.I tx = tx.Model(&ecp.ChemoProtocol{}). - Joins(`"ChemoPlan" cp ON cp."Protocol_Id" = "ChemoProtocol"."Id"`). - Where(`"Patient.Id" = ? AND cp."Status" IS NULL`, patientId). + Joins(`LEFT JOIN "ChemoPlan" cp ON cp."Protocol_Id" = "ChemoProtocol"."Id"`). + Where(`"ChemoProtocol"."Patient_Id" = ?`, patientId). Preload("ChemoPlans", func(db *gorm.DB) *gorm.DB { - return tx.Order(`"Id" ASC`).Limit(1) + return db. + Where(`"Status" IS NULL OR "Status" = ?`, ere.SPCSchedule). + Order(`"Id" ASC`). + Limit(1) }). + Order(`"CreatedAt" DESC`). First(&data) if err := tx.Error; err != nil { @@ -928,35 +939,80 @@ func getChemoProtocol(patientId uint, event *pl.Event) (*ecp.ChemoProtocol, erro return &data, nil } -func validateChemoAdm(patientId uint, event *pl.Event) (*ecpl.ChemoPlan, error) { +func validateChemo(patientId uint, event *pl.Event) (*ecpl.ChemoPlan, error) { + // get chemo adm + chemoAdm, err := getChemoAdm(patientId, event) + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-not-found", + Detail: "patient doesn't have active chemo", + } + + return nil, pl.SetLogError(event, patientId) + } + return nil, err + } + + // validate is chemo verified + if chemoAdm.Status_Code != erc.DVCVerified { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-not-match", + Detail: fmt.Sprintf("chemo not yet verified"), + } + return nil, pl.SetLogError(event, chemoAdm) + } + // get chemo protocol - chemo, err := getChemoProtocol(patientId, event) + chemoProtocol, err := getChemoProtocol(patientId, event) if err != nil { return nil, err } - if chemo.Status_Code != erc.DVCVerified { + if chemoProtocol.Status_Code != erc.DVCVerified { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ Code: "data-not-match", Detail: fmt.Sprintf("protocol chemo not yet verified"), } - return nil, pl.SetLogError(event, chemo) + return nil, pl.SetLogError(event, chemoProtocol) } - if now.Before(*chemo.StartDate) || now.After(*chemo.EndDate) { + if now.Before(*chemoProtocol.StartDate) || now.After(*chemoProtocol.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 nil, pl.SetLogError(event, chemo) + return nil, pl.SetLogError(event, chemoProtocol) } - if chemo.ChemoPlans == nil || len(*chemo.ChemoPlans) == 0 { + if chemoProtocol.ChemoPlans == nil || len(*chemoProtocol.ChemoPlans) == 0 { return nil, nil } // Return the first chemo plan - return &(*chemo.ChemoPlans)[0], nil + return &(*chemoProtocol.ChemoPlans)[0], nil +} + +func getChemoAdm(patientId uint, event *pl.Event) (*ec.Chemo, error) { + pl.SetLogInfo(event, nil, "started", "getChemoProtocol") + data := ec.Chemo{} + + var tx = dg.I + + tx = tx.Model(&ec.Chemo{}). + Joins(`LEFT JOIN "Encounter" e ON e."Id" = "Chemo"."Encounter_Id"`). + Where(`e."Patient_Id" = ? AND "Chemo"."Class_Code" = ?`, patientId, ere.CCCAdm). + Order(`"CreatedAt" DESC`). + First(&data) + + if err := tx.Error; err != nil { + return nil, err + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil } diff --git a/internal/use-case/main-use-case/soapi/case.go b/internal/use-case/main-use-case/soapi/case.go index 6b93fd8a..f74ef594 100644 --- a/internal/use-case/main-use-case/soapi/case.go +++ b/internal/use-case/main-use-case/soapi/case.go @@ -42,7 +42,7 @@ func Create(input e.CreateDto) (*d.Data, error) { return nil, pl.SetLogError(&event, input) } - chemoPlan, err := validateIfEncounterIsChemo(*input.Encounter_Id, &event) + chemoPlan, err := validateIfEncounterIsChemo(*input.Encounter_Id, "c", &event) if err != nil { return nil, err } @@ -57,7 +57,7 @@ func Create(input e.CreateDto) (*d.Data, error) { // update chemoPlan if chemoPlan != nil { chemoPlan.Encounter_Id = input.Encounter_Id - if err = ucp.UpdateData(chemoPlan, &event, tx); err != nil { + if err = ucp.UpdateData(chemoPlan, "c", &event, tx); err != nil { return err } } @@ -252,6 +252,18 @@ func Delete(input e.DeleteDto) (*d.Data, error) { return err } + // update chemoPlan + chemoPlan, err := validateIfEncounterIsChemo(*data.Encounter_Id, "d", &event) + if err != nil { + return err + } + + if chemoPlan != nil { + if err = ucp.UpdateData(chemoPlan, "d", &event, tx); err != nil { + return err + } + } + mwRunner.setMwType(pu.MWTPre) // Run pre-middleware if err = mwRunner.ExecuteIfSyncOn(func() error { diff --git a/internal/use-case/main-use-case/soapi/helper.go b/internal/use-case/main-use-case/soapi/helper.go index 24f87465..74a63b80 100644 --- a/internal/use-case/main-use-case/soapi/helper.go +++ b/internal/use-case/main-use-case/soapi/helper.go @@ -6,11 +6,7 @@ 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" @@ -55,7 +51,7 @@ func setBulkData(input []e.CreateDto, encounterId uint) []e.Soapi { return data } -func validateIfEncounterIsChemo(encounterId uint, event *pl.Event) (*ecpl.ChemoPlan, error) { +func validateIfEncounterIsChemo(encounterId uint, method string, event *pl.Event) (*ecpl.ChemoPlan, error) { // get encounter enc, err := getEncounter(encounterId, event) if err != nil { @@ -64,12 +60,12 @@ func validateIfEncounterIsChemo(encounterId uint, event *pl.Event) (*ecpl.ChemoP // Encounter must be Ambulatory and NOT Rehab a := enc.Ambulatory - if enc.Class_Code != ere.ECAmbulatory || a == nil || a.Class_Code == ere.ACCRehab { + if a == nil || a.Class_Code == ere.ACCRehab { return nil, nil } // get chemo protocol - chemo, err := getChemo(*enc.Patient_Id, event) + chemo, err := getChemo(*enc.Patient_Id, enc.Id, event) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, nil @@ -77,10 +73,6 @@ func validateIfEncounterIsChemo(encounterId uint, event *pl.Event) (*ecpl.ChemoP return nil, pl.SetLogError(event, nil) } - if err = chemoProtocoValidation(chemo, event); err != nil { - - } - if chemo.ChemoPlans == nil || len(*chemo.ChemoPlans) == 0 { return nil, nil } @@ -89,69 +81,39 @@ func validateIfEncounterIsChemo(encounterId uint, event *pl.Event) (*ecpl.ChemoP 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 - } + err := tx.Model(&ee.Encounter{}). + Joins(`LEFT JOIN "Ambulatory" a ON a."Encounter_Id" = "Encounter"."Id"`). + Where(`"Encounter"."Id" = ?`, encounterId). + Where(`"Encounter"."Class_Code" = ?`, ere.ECAmbulatory). + Preload("Ambulatory"). + First(&data).Error + + if err != nil { + return nil, err } 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") +func getChemo(patientId, encounterId uint, event *pl.Event) (*ecp.ChemoProtocol, error) { + pl.SetLogInfo(event, nil, "started", "getChemo") 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). + Joins(`LEFT JOIN "ChemoPlan" cp ON cp."Protocol_Id" = "ChemoProtocol"."Id"`). + Where(`"ChemoProtocol"."Patient_Id" = ?`, patientId). Preload("ChemoPlans", func(db *gorm.DB) *gorm.DB { - return tx.Order(`"Id" ASC`).Limit(1) + return db. + Where(`"Encounter_Id" = ?`, encounterId) }). First(&data)