Merge pull request #215 from dikstub-rssa/feat/chemo-plan
Feat/chemo plan
This commit is contained in:
No files matched your search
@@ -7,7 +7,6 @@ package encounter
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
un "simrs-vx/internal/use-case/main-use-case/nurse"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -24,9 +23,10 @@ import (
|
||||
ere "simrs-vx/internal/domain/references/encounter"
|
||||
erg "simrs-vx/internal/domain/references/organization"
|
||||
|
||||
eaeh "simrs-vx/internal/domain/main-entities/adm-employee-hist"
|
||||
ea "simrs-vx/internal/domain/main-entities/ambulatory"
|
||||
ec "simrs-vx/internal/domain/main-entities/chemo"
|
||||
ecpl "simrs-vx/internal/domain/main-entities/chemo-plan"
|
||||
ecp "simrs-vx/internal/domain/main-entities/chemo-protocol"
|
||||
edo "simrs-vx/internal/domain/main-entities/device-order"
|
||||
ed "simrs-vx/internal/domain/main-entities/doctor"
|
||||
ee "simrs-vx/internal/domain/main-entities/emergency"
|
||||
@@ -42,12 +42,9 @@ import (
|
||||
ep "simrs-vx/internal/domain/main-entities/prescription"
|
||||
epi "simrs-vx/internal/domain/main-entities/prescription-item"
|
||||
er "simrs-vx/internal/domain/main-entities/rehab"
|
||||
erdh "simrs-vx/internal/domain/main-entities/responsible-doctor-hist"
|
||||
es "simrs-vx/internal/domain/main-entities/soapi"
|
||||
esp "simrs-vx/internal/domain/main-entities/specialist"
|
||||
|
||||
// udo "simrs-vx/internal/use-case/main-use-case/device-order"
|
||||
uaeh "simrs-vx/internal/use-case/main-use-case/adm-employee-hist"
|
||||
ua "simrs-vx/internal/use-case/main-use-case/ambulatory"
|
||||
uc "simrs-vx/internal/use-case/main-use-case/chemo"
|
||||
ud "simrs-vx/internal/use-case/main-use-case/doctor"
|
||||
@@ -58,10 +55,10 @@ import (
|
||||
umi "simrs-vx/internal/use-case/main-use-case/medicine-mix"
|
||||
ummi "simrs-vx/internal/use-case/main-use-case/medicine-mix-item"
|
||||
_ "simrs-vx/internal/use-case/main-use-case/nurse"
|
||||
un "simrs-vx/internal/use-case/main-use-case/nurse"
|
||||
up "simrs-vx/internal/use-case/main-use-case/prescription"
|
||||
upi "simrs-vx/internal/use-case/main-use-case/prescription-item"
|
||||
ur "simrs-vx/internal/use-case/main-use-case/rehab"
|
||||
urdh "simrs-vx/internal/use-case/main-use-case/responsible-doctor-hist"
|
||||
us "simrs-vx/internal/use-case/main-use-case/soapi"
|
||||
)
|
||||
|
||||
@@ -396,192 +393,6 @@ func getMcuOrders(encounter_id uint, event *pl.Event, tx *gorm.DB) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func upsertResponsibleDoctorHist(input erdh.CreateDto, event *pl.Event, dbx ...*gorm.DB) error {
|
||||
pl.SetLogInfo(event, nil, "started", "DBCreate")
|
||||
|
||||
var tx *gorm.DB
|
||||
if len(dbx) > 0 {
|
||||
tx = dbx[0]
|
||||
} else {
|
||||
tx = dg.I
|
||||
}
|
||||
|
||||
var latest erdh.ResponsibleDoctorHist
|
||||
err := tx.
|
||||
Where("\"Encounter_Id\" = ?", input.Encounter_Id).
|
||||
Order("\"CreatedAt\" DESC").
|
||||
Limit(1).
|
||||
First(&latest).Error
|
||||
|
||||
switch {
|
||||
case errors.Is(err, gorm.ErrRecordNotFound):
|
||||
// Insert
|
||||
if _, err = urdh.CreateData(input, event, tx); err != nil {
|
||||
return err
|
||||
}
|
||||
case err != nil:
|
||||
event.Status = "failed"
|
||||
event.ErrInfo = pl.ErrorInfo{
|
||||
Code: "read-fail",
|
||||
Detail: "Failed to read responsible doctor history",
|
||||
Raw: err,
|
||||
}
|
||||
return pl.SetLogError(event, input)
|
||||
default:
|
||||
// Update
|
||||
if err := tx.Model(&latest).Updates(map[string]interface{}{
|
||||
"Doctor_Code": input.Doctor_Code,
|
||||
"StartedAt": input.StartedAt,
|
||||
"UpdatedAt": time.Now(),
|
||||
}).Error; err != nil {
|
||||
event.Status = "failed"
|
||||
event.ErrInfo = pl.ErrorInfo{
|
||||
Code: "update-fail",
|
||||
Detail: "Failed to update responsible doctor history",
|
||||
Raw: err,
|
||||
}
|
||||
return pl.SetLogError(event, input)
|
||||
}
|
||||
}
|
||||
pl.SetLogInfo(event, input, "complete")
|
||||
return nil
|
||||
}
|
||||
|
||||
func upsertAdmEmployeeHist(input eaeh.CreateDto, event *pl.Event, dbx ...*gorm.DB) error {
|
||||
pl.SetLogInfo(event, nil, "started", "DBCreate")
|
||||
|
||||
var tx *gorm.DB
|
||||
if len(dbx) > 0 {
|
||||
tx = dbx[0]
|
||||
} else {
|
||||
tx = dg.I
|
||||
}
|
||||
|
||||
var latest eaeh.AdmEmployeeHist
|
||||
err := tx.
|
||||
Where("\"Encounter_Id\" = ?", input.Encounter_Id).
|
||||
Order("\"CreatedAt\" DESC").
|
||||
Limit(1).
|
||||
First(&latest).Error
|
||||
|
||||
switch {
|
||||
case errors.Is(err, gorm.ErrRecordNotFound):
|
||||
// Insert
|
||||
if _, err = uaeh.CreateData(input, event, tx); err != nil {
|
||||
return err
|
||||
}
|
||||
case err != nil:
|
||||
event.Status = "failed"
|
||||
event.ErrInfo = pl.ErrorInfo{
|
||||
Code: "read-fail",
|
||||
Detail: "Failed to read responsible doctor history",
|
||||
Raw: err,
|
||||
}
|
||||
return pl.SetLogError(event, input)
|
||||
|
||||
default:
|
||||
// Update
|
||||
if err := tx.Model(&latest).Updates(map[string]interface{}{
|
||||
"Employee_Id": input.Employee_Id,
|
||||
"StartedAt": input.StartedAt,
|
||||
"UpdatedAt": time.Now(),
|
||||
}).Error; err != nil {
|
||||
event.Status = "failed"
|
||||
event.ErrInfo = pl.ErrorInfo{
|
||||
Code: "update-fail",
|
||||
Detail: "Failed to update responsible doctor history",
|
||||
Raw: err,
|
||||
}
|
||||
return pl.SetLogError(event, input)
|
||||
}
|
||||
}
|
||||
pl.SetLogInfo(event, input, "complete")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateLatestResponsibleDoctorHist(input e.CheckinDto, event *pl.Event, dbx ...*gorm.DB) error {
|
||||
pl.SetLogInfo(event, "started", "DBUpdate")
|
||||
|
||||
var tx *gorm.DB
|
||||
if len(dbx) > 0 {
|
||||
tx = dbx[0]
|
||||
} else {
|
||||
tx = dg.I
|
||||
}
|
||||
|
||||
subQuery := tx.
|
||||
Select("\"Id\"").
|
||||
Model(&erdh.ResponsibleDoctorHist{}).
|
||||
Where("\"Encounter_Id\" = ?", input.Id).
|
||||
Order("\"CreatedAt\" DESC").
|
||||
Limit(1)
|
||||
|
||||
result := tx.
|
||||
Model(&erdh.ResponsibleDoctorHist{}).
|
||||
Where("\"Id\" = (?)", subQuery).
|
||||
Update("\"FinishedAt\"", input.FinishedAt)
|
||||
|
||||
if result.Error != nil {
|
||||
event.Status = "failed"
|
||||
event.ErrInfo = pl.ErrorInfo{
|
||||
Code: "data-update-fail",
|
||||
Detail: "Database update failed",
|
||||
Raw: result.Error,
|
||||
}
|
||||
return pl.SetLogError(event, input)
|
||||
}
|
||||
|
||||
if result.RowsAffected == 0 {
|
||||
pl.SetLogInfo(event, input, "no previous data found to update")
|
||||
return nil
|
||||
}
|
||||
|
||||
pl.SetLogInfo(event, nil, "complete")
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateLatestAdmEmployeeHist(input e.CheckinDto, event *pl.Event, dbx ...*gorm.DB) error {
|
||||
pl.SetLogInfo(event, "started", "DBUpdate")
|
||||
|
||||
var tx *gorm.DB
|
||||
if len(dbx) > 0 {
|
||||
tx = dbx[0]
|
||||
} else {
|
||||
tx = dg.I
|
||||
}
|
||||
|
||||
subQuery := tx.
|
||||
Select("\"Id\"").
|
||||
Model(&eaeh.AdmEmployeeHist{}).
|
||||
Where("\"Encounter_Id\" = ?", input.Id).
|
||||
Order("\"CreatedAt\" DESC").
|
||||
Limit(1)
|
||||
|
||||
result := tx.
|
||||
Model(&eaeh.AdmEmployeeHist{}).
|
||||
Where("\"Id\" = (?)", subQuery).
|
||||
Update("\"FinishedAt\"", input.FinishedAt)
|
||||
|
||||
if result.Error != nil {
|
||||
event.Status = "failed"
|
||||
event.ErrInfo = pl.ErrorInfo{
|
||||
Code: "data-update-fail",
|
||||
Detail: "Database update failed",
|
||||
Raw: result.Error,
|
||||
}
|
||||
return pl.SetLogError(event, input)
|
||||
}
|
||||
|
||||
if result.RowsAffected == 0 {
|
||||
pl.SetLogInfo(event, input, "no previous data found to update")
|
||||
return nil
|
||||
}
|
||||
|
||||
pl.SetLogInfo(event, nil, "complete")
|
||||
return nil
|
||||
}
|
||||
|
||||
func getSoapiByResponsibleDoctor(enc e.Encounter, event *pl.Event) (data []es.Soapi, err error) {
|
||||
pl.SetLogInfo(event, enc, "started", "DBReadList")
|
||||
|
||||
@@ -849,13 +660,31 @@ 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
|
||||
chemoPlan, err = validateChemo(*input.Patient_Id, event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
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{
|
||||
Encounter_Id: &input.Id,
|
||||
Status_Code: erc.DVCNew,
|
||||
Status_Code: erc.DVCVerified,
|
||||
Specialist_Code: input.Specialist_Code,
|
||||
Class_Code: ere.CCCAct,
|
||||
}
|
||||
|
||||
// create data chemo
|
||||
@@ -864,6 +693,13 @@ func insertDataSubClassAmbulatory(input e.CreateDto, soapiData []es.CreateDto, e
|
||||
return err
|
||||
}
|
||||
|
||||
// set chemo-plan to planned
|
||||
chemoPlan.Encounter_Id = &input.Id
|
||||
err = updateChemoPlan(chemoPlan, event, tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case subCode == ere.ACCRehab:
|
||||
rehabData := er.CreateDto{
|
||||
Encounter_Id: &input.Id,
|
||||
@@ -1009,18 +845,18 @@ func getDoctors(doctorIds []string, event *pl.Event) ([]ed.Doctor, error) {
|
||||
return doctors, nil
|
||||
}
|
||||
|
||||
func validateSpecialistCodes(unitCodes map[string]struct{}, event *pl.Event) error {
|
||||
if len(unitCodes) > 0 {
|
||||
func validateSpecialistCodes(speCodes map[string]struct{}, event *pl.Event) error {
|
||||
if len(speCodes) > 0 {
|
||||
var codes []string
|
||||
for code := range unitCodes {
|
||||
for code := range speCodes {
|
||||
codes = append(codes, code)
|
||||
}
|
||||
|
||||
units, err := getSpecialists(codes, event)
|
||||
specialists, err := getSpecialists(codes, event)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to fetch units: %w", err)
|
||||
}
|
||||
if len(units) != len(codes) {
|
||||
if len(specialists) != len(codes) {
|
||||
event.Status = "failed"
|
||||
event.ErrInfo = pl.ErrorInfo{
|
||||
Code: "data-validation-fail",
|
||||
@@ -1056,3 +892,127 @@ func validateDoctorCodes(doctorCodes map[string]struct{}, event *pl.Event) error
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateChemoPlan(data *ecpl.ChemoPlan, event *pl.Event, dbx ...*gorm.DB) error {
|
||||
pl.SetLogInfo(event, nil, "started", "getChemoFromEncounter")
|
||||
var tx *gorm.DB
|
||||
if len(dbx) > 0 {
|
||||
tx = dbx[0]
|
||||
} else {
|
||||
tx = dg.I
|
||||
}
|
||||
|
||||
err := tx.Model(&data).Updates(map[string]interface{}{
|
||||
`"Status"`: ere.SPCPlanned,
|
||||
`"Encounter_Id"`: data.Encounter_Id}).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pl.SetLogInfo(event, nil, "complete")
|
||||
return nil
|
||||
}
|
||||
|
||||
func getChemoProtocol(patientId uint, event *pl.Event) (*ecp.ChemoProtocol, error) {
|
||||
pl.SetLogInfo(event, nil, "started", "getChemoProtocol")
|
||||
data := ecp.ChemoProtocol{}
|
||||
|
||||
var tx = dg.I
|
||||
|
||||
tx = tx.Model(&ecp.ChemoProtocol{}).
|
||||
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 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 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pl.SetLogInfo(event, nil, "complete")
|
||||
return &data, nil
|
||||
}
|
||||
|
||||
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
|
||||
chemoProtocol, err := getChemoProtocol(patientId, event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
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, chemoProtocol)
|
||||
}
|
||||
|
||||
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, chemoProtocol)
|
||||
}
|
||||
|
||||
if chemoProtocol.ChemoPlans == nil || len(*chemoProtocol.ChemoPlans) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Return the first chemo plan
|
||||
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
|
||||
}
|
||||
@@ -59,10 +59,11 @@ func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.En
|
||||
} else {
|
||||
tx = dg.I
|
||||
}
|
||||
|
||||
tx = tx.Model(&e.Encounter{})
|
||||
|
||||
if input.AuthInfo.Doctor_Code != nil {
|
||||
tx.Where("\"Responsible_Doctor_Code\" = ?", *input.AuthInfo.Doctor_Code) //
|
||||
tx = tx.Where("\"Responsible_Doctor_Code\" = ?", *input.AuthInfo.Doctor_Code) //
|
||||
}
|
||||
|
||||
if input.StartDate != nil && input.EndDate != nil {
|
||||
@@ -75,7 +76,8 @@ func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.En
|
||||
|
||||
if input.Patient_Identifier != nil {
|
||||
tx = tx.Joins("JOIN \"Patient\" ON \"Patient\".\"Id\" = \"Encounter\".\"Patient_Id\"").
|
||||
Joins("JOIN \"Person\" ON \"Person\".\"Id\" = \"Patient\".\"Person_Id\"").Where("\"Person\".\"Name\" ILIKE ? OR \"Patient\".\"Number\" = ?", "%"+*input.Patient_Identifier+"%", *input.Patient_Identifier)
|
||||
Joins("JOIN \"Person\" ON \"Person\".\"Id\" = \"Patient\".\"Person_Id\"").
|
||||
Where("\"Person\".\"Name\" ILIKE ? OR \"Patient\".\"Number\" = ?", "%"+*input.Patient_Identifier+"%", *input.Patient_Identifier)
|
||||
}
|
||||
|
||||
// TODO: getuk lib need to be updated to support this
|
||||
@@ -83,20 +85,23 @@ func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.En
|
||||
tx = tx.Where("\"Encounter\".\"Status_Code\" = ?", *input.Status_Code)
|
||||
}
|
||||
|
||||
// if input.Specialist_Code != nil {
|
||||
// tx = tx.Where("\"Encounter\".\"Specialist_Code\" = ?", *input.Specialist_Code)
|
||||
// }
|
||||
if input.Specialist_Code != nil {
|
||||
tx = tx.Where("\"Encounter\".\"Specialist_Code\" = ?", *input.Specialist_Code)
|
||||
}
|
||||
|
||||
if input.PaymentMethod_Code != nil {
|
||||
tx = tx.Where("\"Encounter\".\"PaymentMethod_Code\" = ?", *input.PaymentMethod_Code)
|
||||
}
|
||||
|
||||
tx = tx.Debug().
|
||||
Scopes(gh.Filter(input.FilterDto)).
|
||||
Scopes(gh.Preload(input.Includes)).
|
||||
Count(&count).
|
||||
Scopes(gh.Paginate(input, &pagination)).
|
||||
Order("\"CreatedAt\" DESC")
|
||||
if input.ChemoClass != nil {
|
||||
tx = tx.Joins(`RIGHT JOIN "Chemo" "c" ON "c"."Encounter_Id" = "Encounter"."Id"`).
|
||||
Where(`"c"."Class_Code" = ?`, *input.ChemoClass)
|
||||
}
|
||||
|
||||
// count
|
||||
if err := tx.Count(&count).Error; err != nil {
|
||||
return nil, nil, plh.HandleListError(input, event, err)
|
||||
}
|
||||
|
||||
// tx.Debug().Scopes(gh.Preload(input.Includes)).
|
||||
// Scopes(gh.Filter(input.FilterDto)).
|
||||
@@ -104,7 +109,11 @@ func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.En
|
||||
// Scopes(gh.Paginate(input, &pagination)).
|
||||
// Order("\"CreatedAt\" DESC")
|
||||
|
||||
if err := tx.Find(&data).Error; err != nil {
|
||||
if err := tx.
|
||||
Scopes(gh.Preload(input.Includes)).
|
||||
Scopes(gh.Paginate(input, &pagination)).
|
||||
Order("\"CreatedAt\" DESC").
|
||||
Find(&data).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, &meta, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user