protocol chemo finish

This commit is contained in:
vanilia
2025-12-12 13:48:34 +07:00
parent f5568dfc61
commit cfdfac223f
14 changed files with 261 additions and 120 deletions

No files matched your search

+22 -21
View File
@@ -11,14 +11,14 @@ import (
) )
type CreateDto struct { type CreateDto struct {
Parent_Id *uint `json:"parent_id"` Parent_Id *uint `json:"parent_id"`
SeriesNumber *uint16 `json:"seriesNumber"` SeriesNumber *uint16 `json:"seriesNumber"`
CycleNumber *uint `json:"cycleNumber"` CycleNumber *uint `json:"cycleNumber"`
PlanDate *time.Time `json:"planDate"` PlanDate *time.Time `json:"planDate"`
RealizationDate *time.Time `json:"realizationDate"` RealizationDate *time.Time `json:"realizationDate"`
Notes *string `json:"notes"` Notes *string `json:"notes"`
Status ere.StatusProtocolChemo `json:"status"` Status *ere.StatusProtocolChemo `json:"status"`
Encounter_Id *uint `json:"encounter_id"` Encounter_Id *uint `json:"encounter_id"`
} }
type ReadListDto struct { type ReadListDto struct {
@@ -47,12 +47,13 @@ type DeleteDto struct {
} }
type FailDto struct { type FailDto struct {
Id uint `json:"id"` Id uint `json:"id"`
Reasons *string `json:"reason"` Reasons string `json:"reasons" validate:"required"`
} }
type FailReason struct { type FailReason struct {
Date *time.Time `json:"date"` Date *time.Time `json:"date"`
FailReason *string `json:"failReason"` FailReason string `json:"failReason"`
Encounter_Id *uint `json:"encounter_id"`
} }
type MetaDto struct { type MetaDto struct {
@@ -63,15 +64,15 @@ type MetaDto struct {
type ResponseDto struct { type ResponseDto struct {
ecore.Main ecore.Main
Parent_Id *uint `json:"parent_id"` // chemo.Id Parent_Id *uint `json:"parent_id"` // chemo.Id
Protocol_Id *uint `json:"protocol_id"` Protocol_Id *uint `json:"protocol_id"`
SeriesNumber *uint16 `json:"seriesNumber"` // series ke - SeriesNumber *uint16 `json:"seriesNumber"` // series ke -
CycleNumber *uint `json:"cycleNumber"` // cycle ke - CycleNumber *uint `json:"cycleNumber"` // cycle ke -
PlanDate *time.Time `json:"planDate"` PlanDate *time.Time `json:"planDate"`
RealizationDate *time.Time `json:"realizationDate"` RealizationDate *time.Time `json:"realizationDate"`
Notes *string `json:"notes"` Notes *string `json:"notes"`
Status ere.StatusProtocolChemo `json:"status"` Status *ere.StatusProtocolChemo `json:"status"`
Reasons *string `json:"reasons"` Reasons *string `json:"reasons"`
} }
func (d ChemoPlan) ToResponse() ResponseDto { func (d ChemoPlan) ToResponse() ResponseDto {
@@ -11,15 +11,15 @@ import (
type ChemoPlan struct { type ChemoPlan struct {
ecore.Main ecore.Main
Parent_Id *uint `json:"parent_id"` // chemo.Id Parent_Id *uint `json:"parent_id"` // chemo.Id
Protocol_Id *uint `json:"protocol_id"` Protocol_Id *uint `json:"protocol_id"`
SeriesNumber *uint16 `json:"seriesNumber"` // series ke - SeriesNumber *uint16 `json:"seriesNumber"` // series ke -
CycleNumber *uint `json:"cycleNumber"` // cycle ke - CycleNumber *uint `json:"cycleNumber"` // cycle ke -
PlanDate *time.Time `json:"planDate"` PlanDate *time.Time `json:"planDate"`
RealizationDate *time.Time `json:"realizationDate"` RealizationDate *time.Time `json:"realizationDate"`
Notes *string `json:"notes"` Notes *string `json:"notes"`
Status ere.StatusProtocolChemo `json:"status"` Status *ere.StatusProtocolChemo `json:"status"`
Encounter_Id *uint `json:"encounter_id"` Encounter_Id *uint `json:"encounter_id"`
Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"`
Reasons *string `json:"reasons"` // json Reasons *string `json:"reasons"` // json
} }
@@ -39,6 +39,7 @@ type FilterDto struct {
VerifiedBy_User_Id *uint `json:"verifiedBy-user-id"` VerifiedBy_User_Id *uint `json:"verifiedBy-user-id"`
Specialist_Code *string `json:"specialist-code"` Specialist_Code *string `json:"specialist-code"`
Patient_Id *uint `json:"patient-id"` Patient_Id *uint `json:"patient-id"`
Class_Code ere.ChemoClassCode `json:"class-code"`
} }
type ReadDetailDto struct { type ReadDetailDto struct {
@@ -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)
}
@@ -81,11 +81,8 @@ func (obj myBase) Verify(w http.ResponseWriter, r *http.Request) {
} }
dto := e.VerifyDto{} dto := e.VerifyDto{}
if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res {
return
}
dto.Id = uint(id) dto.Id = uint(id)
authInfo, err := pa.GetAuthInfo(r) authInfo, err := pa.GetAuthInfo(r)
if err != nil { if err != nil {
rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil) rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil)
@@ -81,6 +81,7 @@ import (
/******************** sources ********************/ /******************** sources ********************/
antibioticsrc "simrs-vx/internal/interface/main-handler/antibiotic-src" antibioticsrc "simrs-vx/internal/interface/main-handler/antibiotic-src"
antibioticsrccat "simrs-vx/internal/interface/main-handler/antibiotic-src-category" 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" chemoprotocol "simrs-vx/internal/interface/main-handler/chemo-protocol"
device "simrs-vx/internal/interface/main-handler/device" device "simrs-vx/internal/interface/main-handler/device"
diagnosesrc "simrs-vx/internal/interface/main-handler/diagnose-src" 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}/verify": chemoprotocol.O.Verify,
"PATCH /{id}/reject": chemoprotocol.O.Reject, "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/upload-file", uploadfile.O)
hc.RegCrud(r, "/v1/encounter-document", encounterdocument.O) hc.RegCrud(r, "/v1/encounter-document", encounterdocument.O)
hc.RegCrud(r, "/v1/general-consent", generalconsent.O) hc.RegCrud(r, "/v1/general-consent", generalconsent.O)
@@ -176,7 +176,7 @@ func Update(input e.UpdateDto) (*d.Data, error) {
return err return err
} }
if err := UpdateData(data, &event, tx); err != nil { if err := UpdateData(data, "", &event, tx); err != nil {
return err return err
} }
@@ -284,7 +284,7 @@ func Fail(input e.FailDto) (*d.Data, error) {
return nil, pl.SetLogError(&event, data) return nil, pl.SetLogError(&event, data)
} }
if data.Status != ere.SPCPlanned { if *data.Status != ere.SPCPlanned {
event.Status = "failed" event.Status = "failed"
event.ErrInfo = pl.ErrorInfo{ event.ErrInfo = pl.ErrorInfo{
Code: "invalid-chemo-status", 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 { 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 return err
} }
@@ -34,16 +34,23 @@ func setDataCreate(input *ep.CreateDto) (data []e.ChemoPlan) {
return return
} }
func setDataUpdate(data *e.ChemoPlan) { func setDataCreateSoapi(data *e.ChemoPlan) {
data.RealizationDate = &now data.RealizationDate = &now
status := ere.SPCComplete 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) { func setDatafail(input e.FailDto, data *e.ChemoPlan) {
data.RealizationDate = nil data.RealizationDate = nil
data.Status = ere.SPCSchedule
status := ere.SPCSchedule
data.Status = &status
var reasons []e.FailReason var reasons []e.FailReason
@@ -52,8 +59,9 @@ func setDatafail(input e.FailDto, data *e.ChemoPlan) {
} }
reasons = append(reasons, e.FailReason{ reasons = append(reasons, e.FailReason{
FailReason: input.Reasons, FailReason: input.Reasons,
Date: &now, Date: &now,
Encounter_Id: data.Encounter_Id,
}) })
if b, err := json.Marshal(reasons); err == nil { if b, err := json.Marshal(reasons); err == nil {
@@ -98,9 +98,15 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e
return &data, nil 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") pl.SetLogInfo(event, data, "started", "DBUpdate")
setDataUpdate(data)
switch method {
case "c":
setDataCreateSoapi(data)
case "d":
setDataDeleteSoapi(data)
}
var tx *gorm.DB var tx *gorm.DB
if len(dbx) > 0 { 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 { func UpdateFailData(input e.FailDto, data *e.ChemoPlan, event *pl.Event, dbx ...*gorm.DB) error {
pl.SetLogInfo(event, data, "started", "DBUpdate") pl.SetLogInfo(event, data, "started", "DBUpdate")
setDataUpdate(data) setDatafail(input, data)
var tx *gorm.DB var tx *gorm.DB
if len(dbx) > 0 { if len(dbx) > 0 {
@@ -20,4 +20,5 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Chemo) {
data.Encounter_Id = inputSrc.Encounter_Id data.Encounter_Id = inputSrc.Encounter_Id
data.Status_Code = inputSrc.Status_Code data.Status_Code = inputSrc.Status_Code
data.Specialist_Code = inputSrc.Specialist_Code data.Specialist_Code = inputSrc.Specialist_Code
data.Class_Code = inputSrc.Class_Code
} }
@@ -47,6 +47,11 @@ func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.Ch
tx = dg.I tx = dg.I
} }
if input.Class_Code != "" {
tx = tx.Where(`"Chemo"."Class_Code" = ?`, input.Class_Code)
input.Class_Code = ""
}
tx = tx. tx = tx.
Model(&e.Chemo{}). Model(&e.Chemo{}).
Joins(`LEFT JOIN "Encounter" "e" ON "e"."Id" = "Chemo"."Encounter_Id"`). Joins(`LEFT JOIN "Encounter" "e" ON "e"."Id" = "Chemo"."Encounter_Id"`).
@@ -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) { func insertDataSubClassAmbulatory(input e.CreateDto, soapiData []es.CreateDto, event *pl.Event, tx *gorm.DB) (err error) {
subCode := ere.AmbulatoryClassCode(*input.SubClass_Code) subCode := ere.AmbulatoryClassCode(*input.SubClass_Code)
var chemoPlan *ecpl.ChemoPlan
switch { switch {
case subCode == ere.ACCChemo: case subCode == ere.ACCChemo:
// validate if encounter Chemo valid // validate if encounter Chemo valid
chemoProtoc, err := validateChemoAdm(*input.Patient_Id, event) chemoPlan, err = validateChemo(*input.Patient_Id, event)
if err != nil { if err != nil {
return err return err
} }
if chemoProtoc == nil { if chemoPlan == nil {
event.Status = "failed" event.Status = "failed"
event.ErrInfo = pl.ErrorInfo{ event.ErrInfo = pl.ErrorInfo{
Code: "data-not-found", Code: "data-not-found",
Detail: "chemo plan not found", Detail: "chemo plan not found",
} }
return pl.SetLogError(event, input)
} }
chemoCreate := ec.CreateDto{ chemoCreate := ec.CreateDto{
@@ -691,7 +694,8 @@ func insertDataSubClassAmbulatory(input e.CreateDto, soapiData []es.CreateDto, e
} }
// set chemo-plan to planned // set chemo-plan to planned
err = updateChemoPlan(chemoProtoc, event, tx) chemoPlan.Encounter_Id = &input.Id
err = updateChemoPlan(chemoPlan, event, tx)
if err != nil { if err != nil {
return err return err
} }
@@ -898,7 +902,10 @@ func updateChemoPlan(data *ecpl.ChemoPlan, event *pl.Event, dbx ...*gorm.DB) err
tx = dg.I 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 return err
} }
@@ -913,11 +920,15 @@ func getChemoProtocol(patientId uint, event *pl.Event) (*ecp.ChemoProtocol, erro
var tx = dg.I var tx = dg.I
tx = tx.Model(&ecp.ChemoProtocol{}). tx = tx.Model(&ecp.ChemoProtocol{}).
Joins(`"ChemoPlan" cp ON cp."Protocol_Id" = "ChemoProtocol"."Id"`). Joins(`LEFT JOIN "ChemoPlan" cp ON cp."Protocol_Id" = "ChemoProtocol"."Id"`).
Where(`"Patient.Id" = ? AND cp."Status" IS NULL`, patientId). Where(`"ChemoProtocol"."Patient_Id" = ?`, patientId).
Preload("ChemoPlans", func(db *gorm.DB) *gorm.DB { 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) First(&data)
if err := tx.Error; err != nil { if err := tx.Error; err != nil {
@@ -928,35 +939,80 @@ func getChemoProtocol(patientId uint, event *pl.Event) (*ecp.ChemoProtocol, erro
return &data, nil 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 // get chemo protocol
chemo, err := getChemoProtocol(patientId, event) chemoProtocol, err := getChemoProtocol(patientId, event)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if chemo.Status_Code != erc.DVCVerified { if chemoProtocol.Status_Code != erc.DVCVerified {
event.Status = "failed" event.Status = "failed"
event.ErrInfo = pl.ErrorInfo{ event.ErrInfo = pl.ErrorInfo{
Code: "data-not-match", Code: "data-not-match",
Detail: fmt.Sprintf("protocol chemo not yet verified"), 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.Status = "failed"
event.ErrInfo = pl.ErrorInfo{ event.ErrInfo = pl.ErrorInfo{
Code: "invalid-date-range", Code: "invalid-date-range",
Detail: "chemo cannot be performed because the current date is outside the allowed treatment window.", 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 nil, nil
} }
// Return the first chemo plan // 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
} }
+14 -2
View File
@@ -42,7 +42,7 @@ func Create(input e.CreateDto) (*d.Data, error) {
return nil, pl.SetLogError(&event, input) return nil, pl.SetLogError(&event, input)
} }
chemoPlan, err := validateIfEncounterIsChemo(*input.Encounter_Id, &event) chemoPlan, err := validateIfEncounterIsChemo(*input.Encounter_Id, "c", &event)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -57,7 +57,7 @@ func Create(input e.CreateDto) (*d.Data, error) {
// update chemoPlan // update chemoPlan
if chemoPlan != nil { if chemoPlan != nil {
chemoPlan.Encounter_Id = input.Encounter_Id 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 return err
} }
} }
@@ -252,6 +252,18 @@ func Delete(input e.DeleteDto) (*d.Data, error) {
return err 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) mwRunner.setMwType(pu.MWTPre)
// Run pre-middleware // Run pre-middleware
if err = mwRunner.ExecuteIfSyncOn(func() error { if err = mwRunner.ExecuteIfSyncOn(func() error {
+18 -56
View File
@@ -6,11 +6,7 @@ package soapi
import ( import (
"errors" "errors"
"fmt"
erc "simrs-vx/internal/domain/references/common"
pl "simrs-vx/pkg/logger" pl "simrs-vx/pkg/logger"
pu "simrs-vx/pkg/use-case-helper"
"time"
dg "github.com/karincake/apem/db-gorm-pg" dg "github.com/karincake/apem/db-gorm-pg"
"gorm.io/gorm" "gorm.io/gorm"
@@ -55,7 +51,7 @@ func setBulkData(input []e.CreateDto, encounterId uint) []e.Soapi {
return data 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 // get encounter
enc, err := getEncounter(encounterId, event) enc, err := getEncounter(encounterId, event)
if err != nil { if err != nil {
@@ -64,12 +60,12 @@ func validateIfEncounterIsChemo(encounterId uint, event *pl.Event) (*ecpl.ChemoP
// Encounter must be Ambulatory and NOT Rehab // Encounter must be Ambulatory and NOT Rehab
a := enc.Ambulatory 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 return nil, nil
} }
// get chemo protocol // get chemo protocol
chemo, err := getChemo(*enc.Patient_Id, event) chemo, err := getChemo(*enc.Patient_Id, enc.Id, event)
if err != nil { if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) { if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, nil return nil, nil
@@ -77,10 +73,6 @@ func validateIfEncounterIsChemo(encounterId uint, event *pl.Event) (*ecpl.ChemoP
return nil, pl.SetLogError(event, nil) return nil, pl.SetLogError(event, nil)
} }
if err = chemoProtocoValidation(chemo, event); err != nil {
}
if chemo.ChemoPlans == nil || len(*chemo.ChemoPlans) == 0 { if chemo.ChemoPlans == nil || len(*chemo.ChemoPlans) == 0 {
return nil, nil return nil, nil
} }
@@ -89,69 +81,39 @@ func validateIfEncounterIsChemo(encounterId uint, event *pl.Event) (*ecpl.ChemoP
return &(*chemo.ChemoPlans)[0], nil 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) { func getEncounter(encounterId uint, event *pl.Event) (*ee.Encounter, error) {
pl.SetLogInfo(event, nil, "started", "getEncounter") pl.SetLogInfo(event, nil, "started", "getEncounter")
data := ee.Encounter{} data := ee.Encounter{}
var tx = dg.I var tx = dg.I
if err := tx.Model(&ee.Encounter{}). err := tx.Model(&ee.Encounter{}).
Where(`"Encounter_Id" = ?`, encounterId). Joins(`LEFT JOIN "Ambulatory" a ON a."Encounter_Id" = "Encounter"."Id"`).
Scopes(withConditionalAmbulatory()). Where(`"Encounter"."Id" = ?`, encounterId).
First(&data).Error; err != nil { Where(`"Encounter"."Class_Code" = ?`, ere.ECAmbulatory).
if processedErr := pu.HandleReadError(err, event, source, nil, encounterId); processedErr != nil { Preload("Ambulatory").
return nil, processedErr First(&data).Error
}
if err != nil {
return nil, err
} }
pl.SetLogInfo(event, nil, "complete") pl.SetLogInfo(event, nil, "complete")
return &data, nil return &data, nil
} }
func withConditionalAmbulatory() func(db *gorm.DB) *gorm.DB { func getChemo(patientId, encounterId uint, event *pl.Event) (*ecp.ChemoProtocol, error) {
return func(db *gorm.DB) *gorm.DB { pl.SetLogInfo(event, nil, "started", "getChemo")
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{} data := ecp.ChemoProtocol{}
var tx = dg.I var tx = dg.I
tx = tx.Model(&ecp.ChemoProtocol{}). tx = tx.Model(&ecp.ChemoProtocol{}).
Joins(`"ChemoPlan" cp ON cp."Protocol_Id" = "ChemoProtocol"."Id"`). Joins(`LEFT JOIN "ChemoPlan" cp ON cp."Protocol_Id" = "ChemoProtocol"."Id"`).
Where(`"Patient.Id" = ? AND cp."Status" = ?`, patientId, ere.SPCPlanned). Where(`"ChemoProtocol"."Patient_Id" = ?`, patientId).
Preload("ChemoPlans", func(db *gorm.DB) *gorm.DB { Preload("ChemoPlans", func(db *gorm.DB) *gorm.DB {
return tx.Order(`"Id" ASC`).Limit(1) return db.
Where(`"Encounter_Id" = ?`, encounterId)
}). }).
First(&data) First(&data)