Merge branch 'fix/anything-moko' of github.com:dikstub-rssa/simrs-be into migration
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
m "simrs-vx/internal/interface/migration"
|
||||
)
|
||||
|
||||
func main() {
|
||||
m.Migrate(m.Main)
|
||||
}
|
||||
package main
|
||||
|
||||
import (
|
||||
m "simrs-vx/internal/interface/migration"
|
||||
)
|
||||
|
||||
func main() {
|
||||
m.Migrate(m.Main)
|
||||
}
|
||||
|
||||
@@ -6,9 +6,8 @@ import (
|
||||
)
|
||||
|
||||
type CreateDto struct {
|
||||
Encounter_Id *uint `json:"encounter_id"`
|
||||
Class_Code ere.AmbulatoryClassCode `json:"class_code" validate:"maxLength=10"`
|
||||
VisitMode_Code ere.VisitModeCode `json:"visitMode_code"`
|
||||
Encounter_Id *uint `json:"encounter_id"`
|
||||
Class_Code ere.AmbulatoryClassCode `json:"class_code" validate:"maxLength=10"`
|
||||
}
|
||||
|
||||
type ReadListDto struct {
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
package encounter
|
||||
|
||||
import (
|
||||
eam "simrs-vx/internal/domain/main-entities/ambulatory"
|
||||
edc "simrs-vx/internal/domain/main-entities/death-cause"
|
||||
eem "simrs-vx/internal/domain/main-entities/emergency"
|
||||
eip "simrs-vx/internal/domain/main-entities/inpatient"
|
||||
eir "simrs-vx/internal/domain/main-entities/internal-reference"
|
||||
er "simrs-vx/internal/domain/main-entities/rehab/base"
|
||||
|
||||
// std
|
||||
"time"
|
||||
|
||||
@@ -19,7 +26,6 @@ import (
|
||||
ea "simrs-vx/internal/domain/main-entities/appointment"
|
||||
ed "simrs-vx/internal/domain/main-entities/doctor"
|
||||
ee "simrs-vx/internal/domain/main-entities/employee"
|
||||
eir "simrs-vx/internal/domain/main-entities/internal-reference"
|
||||
ep "simrs-vx/internal/domain/main-entities/patient"
|
||||
es "simrs-vx/internal/domain/main-entities/specialist"
|
||||
ess "simrs-vx/internal/domain/main-entities/subspecialist"
|
||||
@@ -48,8 +54,10 @@ type CreateDto struct {
|
||||
Appointment_Id *uint `json:"appointment_id"`
|
||||
RefTypeCode ere.RefTypeCode `json:"refTypeCode"`
|
||||
NewStatus bool `json:"newStatus"`
|
||||
VisitMode_Code *ere.VisitModeCode `json:"visitMode_code"` // if subClass_Code is rehab
|
||||
AllocatedVisitCount *int `json:"allocatedVisitCount"` // if subClass_Code is rehab and VisitMode_Code is "adm"
|
||||
|
||||
Id uint `json:"-"`
|
||||
RecentEncounterAdm *Encounter `json:"-"` // if subClass_Code is rehab
|
||||
VisitMode_Code ere.VisitModeCode `json:"-"` // if subClass_Code is rehab
|
||||
|
||||
pa.AuthInfo
|
||||
}
|
||||
@@ -114,7 +122,6 @@ type DischargeDto struct {
|
||||
AdmDischargeEducation *string `json:"admDischargeEducation"`
|
||||
DischargeReason *string `json:"dischargeReason"`
|
||||
DeathCause *string `json:"deathCause"`
|
||||
InternalReferences *[]eir.CreateDto `json:"internalReferences,omitempty"`
|
||||
}
|
||||
|
||||
type CheckinDto struct {
|
||||
@@ -125,6 +132,17 @@ type CheckinDto struct {
|
||||
FinishedAt *time.Time `json:"finishedAt"`
|
||||
}
|
||||
|
||||
type SwitchUnitDto struct {
|
||||
Id uint `json:"id"`
|
||||
PolySwitchCode *ere.PolySwitchCode `json:"polySwitchCode"`
|
||||
InternalReferences *[]eir.CreateDto `json:"internalReferences" validate:"required"`
|
||||
}
|
||||
|
||||
type ApproveUnitDto struct {
|
||||
Id uint `json:"id"`
|
||||
InternalReferences_Id uint16 `json:"internalReferences_id" validate:"required"`
|
||||
}
|
||||
|
||||
type ResponseDto struct {
|
||||
ecore.Main
|
||||
Patient_Id *uint `json:"patient_id"`
|
||||
@@ -159,6 +177,17 @@ type ResponseDto struct {
|
||||
DischargeReason *string `json:"dischargeReason"`
|
||||
Status_Code erc.DataStatusCode `json:"status_code"`
|
||||
VclaimSep *evs.VclaimSep `json:"vclaimSep,omitempty"`
|
||||
StartedAt *time.Time `json:"startedAt"`
|
||||
FinishedAt *time.Time `json:"finishedAt"`
|
||||
Discharge_Date *time.Time `json:"discharge_date"`
|
||||
InternalReferences *[]eir.InternalReference `json:"internalReferences,omitempty"`
|
||||
DeathCause *edc.DeathCause `json:"deathCause,omitempty"`
|
||||
NewStatus bool `json:"newStatus"`
|
||||
Ambulatory *eam.Ambulatory `json:"ambulatory,omitempty"`
|
||||
Emergency *eem.Emergency `json:"emergency,omitempty"`
|
||||
Inpatient *eip.Inpatient `json:"inpatient,omitempty"`
|
||||
Rehab *er.Basic `json:"rehab,omitempty"`
|
||||
RehabChildren *[]er.Basic `json:"rehabChildren,omitempty"`
|
||||
}
|
||||
|
||||
func (d Encounter) ToResponse() ResponseDto {
|
||||
@@ -195,6 +224,16 @@ func (d Encounter) ToResponse() ResponseDto {
|
||||
DischargeReason: d.DischargeReason,
|
||||
Status_Code: d.Status_Code,
|
||||
VclaimSep: d.VclaimSep,
|
||||
StartedAt: d.StartedAt,
|
||||
FinishedAt: d.FinishedAt,
|
||||
Discharge_Date: d.Discharge_Date,
|
||||
InternalReferences: d.InternalReferences,
|
||||
DeathCause: d.DeathCause,
|
||||
NewStatus: d.NewStatus,
|
||||
Emergency: d.Emergency,
|
||||
Inpatient: d.Inpatient,
|
||||
Rehab: d.Rehab,
|
||||
RehabChildren: d.RehabChildren,
|
||||
}
|
||||
resp.Main = d.Main
|
||||
return resp
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
package internal_reference
|
||||
|
||||
import (
|
||||
erc "simrs-vx/internal/domain/references/common"
|
||||
|
||||
ecore "simrs-vx/internal/domain/base-entities/core"
|
||||
ed "simrs-vx/internal/domain/main-entities/doctor"
|
||||
eu "simrs-vx/internal/domain/main-entities/unit"
|
||||
)
|
||||
|
||||
type CreateDto struct {
|
||||
Encounter_Id *uint `json:"-"`
|
||||
Unit_Id *uint16 `json:"unit_id"`
|
||||
Doctor_Id *uint `json:"doctor_Id"`
|
||||
Encounter_Id *uint `json:"-"`
|
||||
Unit_Id *uint16 `json:"unit_id"`
|
||||
Doctor_Id *uint `json:"doctor_Id"`
|
||||
Status_Code erc.DataApprovalCode `json:"status_code"`
|
||||
}
|
||||
|
||||
type ReadListDto struct {
|
||||
@@ -19,9 +22,10 @@ type ReadListDto struct {
|
||||
}
|
||||
|
||||
type FilterDto struct {
|
||||
Encounter_Id *uint `json:"encounter-id"`
|
||||
Unit_Id *uint `json:"unit-id"`
|
||||
Doctor_Id *uint `json:"doctor-id"`
|
||||
Encounter_Id *uint `json:"encounter-id"`
|
||||
Unit_Id *uint `json:"unit-id"`
|
||||
Doctor_Id *uint `json:"doctor-id"`
|
||||
Status_Code erc.DataApprovalCode `json:"status-code"`
|
||||
}
|
||||
|
||||
type ReadDetailDto struct {
|
||||
@@ -46,11 +50,12 @@ type MetaDto struct {
|
||||
|
||||
type ResponseDto struct {
|
||||
ecore.Main
|
||||
Encounter_Id *uint `json:"encounter_id"`
|
||||
Unit_Id *uint16 `json:"unit_id"`
|
||||
Unit *eu.Unit `json:"unit,omitempty"`
|
||||
Doctor_Id *uint `json:"doctor_id"`
|
||||
Doctor *ed.Doctor `json:"doctor,omitempty"`
|
||||
Encounter_Id *uint `json:"encounter_id"`
|
||||
Unit_Id *uint16 `json:"unit_id"`
|
||||
Unit *eu.Unit `json:"unit,omitempty"`
|
||||
Doctor_Id *uint `json:"doctor_id"`
|
||||
Doctor *ed.Doctor `json:"doctor,omitempty"`
|
||||
Status_Code *erc.DataApprovalCode `json:"status_code"`
|
||||
}
|
||||
|
||||
func (d InternalReference) ToResponse() ResponseDto {
|
||||
@@ -60,6 +65,7 @@ func (d InternalReference) ToResponse() ResponseDto {
|
||||
Unit: d.Unit,
|
||||
Doctor_Id: d.Doctor_Id,
|
||||
Doctor: d.Doctor,
|
||||
Status_Code: d.Status_Code,
|
||||
}
|
||||
resp.Main = d.Main
|
||||
return resp
|
||||
|
||||
@@ -1,14 +1,20 @@
|
||||
package rehab
|
||||
|
||||
import (
|
||||
erc "simrs-vx/internal/domain/references/common"
|
||||
ere "simrs-vx/internal/domain/references/encounter"
|
||||
|
||||
ecore "simrs-vx/internal/domain/base-entities/core"
|
||||
ed "simrs-vx/internal/domain/main-entities/doctor"
|
||||
"time"
|
||||
)
|
||||
|
||||
type CreateDto struct {
|
||||
Encounter_Id *uint `json:"encounter_id"`
|
||||
Doctor_Id *uint `json:"doctor_id"`
|
||||
AllocatedVisitCount *int `json:"allocatedVisitCount"`
|
||||
Encounter_Id *uint `json:"encounter_id"`
|
||||
Parent_Encounter_Id *uint `json:"parent_encounter_id"`
|
||||
AllocatedVisitCount *int `json:"allocatedVisitCount"`
|
||||
ExpiredAt *time.Time `json:"expiredAt"`
|
||||
VisitMode_Code ere.VisitModeCode `json:"visitMode_code"`
|
||||
Status_Code erc.DataStatusCode `json:"status_code"`
|
||||
}
|
||||
|
||||
type ReadListDto struct {
|
||||
@@ -18,8 +24,9 @@ type ReadListDto struct {
|
||||
}
|
||||
|
||||
type FilterDto struct {
|
||||
Encounter_Id *uint `json:"encounter-id"`
|
||||
Doctor_Id *uint `json:"doctor-id"`
|
||||
Encounter_Id *uint `json:"encounter-id"`
|
||||
Parent_Encounter_Id *uint `json:"parent-encounter-id"`
|
||||
VisitMode_Code ere.VisitModeCode `json:"visitMode-code"`
|
||||
}
|
||||
|
||||
type ReadDetailDto struct {
|
||||
@@ -44,16 +51,22 @@ type MetaDto struct {
|
||||
|
||||
type ResponseDto struct {
|
||||
ecore.Main
|
||||
Encounter_Id *uint `json:"encounter_id"`
|
||||
Doctor_Id *uint `json:"doctor_id"`
|
||||
Doctor *ed.Doctor `json:"doctor,omitempty"`
|
||||
AllocatedVisitCount *int `json:"allocatedVisitCount"`
|
||||
Encounter_Id *uint `json:"encounter_id"`
|
||||
Parent_Encounter_Id *uint `json:"parent_encounter_id"`
|
||||
AllocatedVisitCount *int `json:"allocatedVisitCount"`
|
||||
ExpiredAt *time.Time `json:"expiredAt"`
|
||||
VisitMode_Code *ere.VisitModeCode `json:"visitMode_code"`
|
||||
Status_Code *erc.DataStatusCode `json:"status_code"`
|
||||
}
|
||||
|
||||
func (d Rehab) ToResponse() ResponseDto {
|
||||
resp := ResponseDto{
|
||||
Encounter_Id: d.Encounter_Id,
|
||||
Parent_Encounter_Id: d.Parent_Encounter_Id,
|
||||
AllocatedVisitCount: d.AllocatedVisitCount,
|
||||
ExpiredAt: d.ExpiredAt,
|
||||
VisitMode_Code: d.VisitMode_Code,
|
||||
Status_Code: d.Status_Code,
|
||||
}
|
||||
resp.Main = d.Main
|
||||
return resp
|
||||
|
||||
@@ -9,7 +9,7 @@ type (
|
||||
InstructionCode string
|
||||
HeadToToeCode string
|
||||
McuUrgencyLevelCode string
|
||||
McuScopeCode string
|
||||
McuScopeCode string
|
||||
SoapiTypeCode string
|
||||
MedicalActionTypeCode string
|
||||
VehicleTypeCode string
|
||||
|
||||
@@ -3,18 +3,17 @@ package encounter
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
pa "simrs-vx/internal/lib/auth"
|
||||
|
||||
d "github.com/karincake/dodol"
|
||||
rw "github.com/karincake/risoles"
|
||||
sf "github.com/karincake/semprit"
|
||||
|
||||
// ua "github.com/karincake/tumpeng/auth/svc"
|
||||
erc "simrs-vx/internal/domain/references/common"
|
||||
|
||||
e "simrs-vx/internal/domain/main-entities/encounter"
|
||||
u "simrs-vx/internal/use-case/main-use-case/encounter"
|
||||
|
||||
erc "simrs-vx/internal/domain/references/common"
|
||||
pa "simrs-vx/internal/lib/auth"
|
||||
|
||||
d "github.com/karincake/dodol"
|
||||
)
|
||||
|
||||
type myBase struct{}
|
||||
@@ -31,7 +30,13 @@ func (obj myBase) Create(w http.ResponseWriter, r *http.Request) {
|
||||
if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res {
|
||||
return
|
||||
}
|
||||
if valid := validateRequestCreate(w, dto); !valid {
|
||||
|
||||
// validate SubClass
|
||||
if err := verifyClassCode(dto); err != nil {
|
||||
rw.DataResponse(w, nil, d.FieldError{
|
||||
Code: dataValidationFail,
|
||||
Message: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -192,3 +197,40 @@ func (obj myBase) Skip(w http.ResponseWriter, r *http.Request) {
|
||||
res, err := u.UpdateStatusCode(dto)
|
||||
rw.DataResponse(w, res, err)
|
||||
}
|
||||
|
||||
func (obj myBase) RequestSwitchUnit(w http.ResponseWriter, r *http.Request) {
|
||||
dto := e.SwitchUnitDto{}
|
||||
id := rw.ValidateInt(w, "id", r.PathValue("id"))
|
||||
if id <= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res {
|
||||
return
|
||||
}
|
||||
|
||||
// validate request body
|
||||
if valid := validateRequestSwitchUnit(w, dto); !valid {
|
||||
return
|
||||
}
|
||||
|
||||
dto.Id = uint(id)
|
||||
res, err := u.RequestSwitchUnit(dto)
|
||||
rw.DataResponse(w, res, err)
|
||||
}
|
||||
|
||||
func (obj myBase) ApproveSwitchUnit(w http.ResponseWriter, r *http.Request) {
|
||||
dto := e.ApproveUnitDto{}
|
||||
id := rw.ValidateInt(w, "id", r.PathValue("id"))
|
||||
if id <= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res {
|
||||
return
|
||||
}
|
||||
|
||||
dto.Id = uint(id)
|
||||
res, err := u.ApproveSwitchUnit(dto)
|
||||
rw.DataResponse(w, res, err)
|
||||
}
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
package encounter
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
e "simrs-vx/internal/domain/main-entities/encounter"
|
||||
ere "simrs-vx/internal/domain/references/encounter"
|
||||
ua "simrs-vx/internal/use-case/main-use-case/ambulatory"
|
||||
ue "simrs-vx/internal/use-case/main-use-case/emergency"
|
||||
ui "simrs-vx/internal/use-case/main-use-case/inpatient"
|
||||
|
||||
d "github.com/karincake/dodol"
|
||||
rw "github.com/karincake/risoles"
|
||||
@@ -11,6 +16,25 @@ import (
|
||||
|
||||
const dataValidationFail = "data-validation-fail"
|
||||
|
||||
func verifyClassCode(input e.CreateDto) (err error) {
|
||||
switch input.Class_Code {
|
||||
case ere.ECAmbulatory:
|
||||
_, err = ua.CheckClassCode(input.SubClass_Code)
|
||||
case ere.ECEmergency:
|
||||
_, err = ue.CheckClassCode(input.SubClass_Code)
|
||||
case ere.ECInpatient:
|
||||
_, err = ui.CheckClassCode(input.SubClass_Code)
|
||||
default:
|
||||
return errors.New("invalid encounter class code")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateRequestCheckout(w http.ResponseWriter, i e.DischargeDto) (valid bool) {
|
||||
if *i.Discharge_Method_Code == ere.DMCDeath && i.DeathCause == nil {
|
||||
rw.DataResponse(w, nil, d.FieldError{
|
||||
@@ -19,7 +43,6 @@ func validateRequestCheckout(w http.ResponseWriter, i e.DischargeDto) (valid boo
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -35,18 +58,30 @@ func validateRequestCheckIn(w http.ResponseWriter, i e.CheckinDto) (valid bool)
|
||||
return true
|
||||
}
|
||||
|
||||
func validateRequestCreate(w http.ResponseWriter, i e.CreateDto) (valid bool) {
|
||||
switch {
|
||||
case i.Class_Code == ere.ECAmbulatory:
|
||||
// field allocatedVisitCount required if ambulatory visitMode_Code is adm
|
||||
if ere.AmbulatoryClassCode(*i.SubClass_Code) == ere.ACCRehab && *i.VisitMode_Code == ere.VMCAdm {
|
||||
if *i.AllocatedVisitCount == 0 {
|
||||
rw.DataResponse(w, nil, d.FieldError{
|
||||
Code: dataValidationFail,
|
||||
Message: "allocatedVisitCount required",
|
||||
})
|
||||
return
|
||||
}
|
||||
func validateRequestSwitchUnit(w http.ResponseWriter, i e.SwitchUnitDto) (valid bool) {
|
||||
if i.InternalReferences == nil {
|
||||
rw.DataResponse(w, nil, d.FieldError{
|
||||
Code: dataValidationFail,
|
||||
Message: fmt.Sprintf("internalReferences required"),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
for _, v := range *i.InternalReferences {
|
||||
if v.Unit_Id == nil {
|
||||
rw.DataResponse(w, nil, d.FieldError{
|
||||
Code: dataValidationFail,
|
||||
Message: "internalReferences.unit_id required",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if v.Doctor_Id == nil {
|
||||
rw.DataResponse(w, nil, d.FieldError{
|
||||
Code: dataValidationFail,
|
||||
Message: "internalReferences.doctor_id required",
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -145,17 +145,19 @@ func SetRoutes() http.Handler {
|
||||
hc.RegCrud(r, "/v1/material-order-item", materialorderitem.O)
|
||||
|
||||
hk.GroupRoutes("/v1/encounter", r, auth.GuardMW, hk.MapHandlerFunc{
|
||||
"GET /": encounter.O.GetList,
|
||||
"GET /{id}": encounter.O.GetDetail,
|
||||
"POST /": encounter.O.Create,
|
||||
"PATCH /{id}": encounter.O.Update,
|
||||
"DELETE /{id}": encounter.O.Delete,
|
||||
"PATCH /{id}/check-out": encounter.O.CheckOut,
|
||||
"PATCH /{id}/check-in": encounter.O.CheckIn,
|
||||
"PATCH /{id}/proccess": encounter.O.Process,
|
||||
"PATCH /{id}/cancel": encounter.O.Cancel,
|
||||
"PATCH /{id}/reject": encounter.O.Reject,
|
||||
"PATCH /{id}/skip": encounter.O.Skip,
|
||||
"GET /": encounter.O.GetList,
|
||||
"GET /{id}": encounter.O.GetDetail,
|
||||
"POST /": encounter.O.Create,
|
||||
"PATCH /{id}": encounter.O.Update,
|
||||
"DELETE /{id}": encounter.O.Delete,
|
||||
"PATCH /{id}/check-out": encounter.O.CheckOut,
|
||||
"PATCH /{id}/check-in": encounter.O.CheckIn,
|
||||
"PATCH /{id}/proccess": encounter.O.Process,
|
||||
"PATCH /{id}/cancel": encounter.O.Cancel,
|
||||
"PATCH /{id}/reject": encounter.O.Reject,
|
||||
"PATCH /{id}/skip": encounter.O.Skip,
|
||||
"PATCH /{id}/req-switch-unit": encounter.O.RequestSwitchUnit,
|
||||
"PATCH /{id}/approve-switch-unit": encounter.O.ApproveSwitchUnit,
|
||||
})
|
||||
hk.GroupRoutes("/v1/mcu-order", r, auth.GuardMW, hk.MapHandlerFunc{
|
||||
"GET /": mcuorder.O.GetList,
|
||||
|
||||
@@ -22,7 +22,6 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Ambulatory) {
|
||||
|
||||
data.Encounter_Id = inputSrc.Encounter_Id
|
||||
data.Class_Code = inputSrc.Class_Code
|
||||
data.VisitMode_Code = inputSrc.VisitMode_Code
|
||||
}
|
||||
|
||||
func CheckClassCode(input *string) (ere.AmbulatoryClassCode, error) {
|
||||
|
||||
@@ -313,12 +313,12 @@ func ExtractToken(r *http.Request, tokenType TokenType) (data *pa.AuthInfo, err
|
||||
|
||||
data.User_ContractPosition_code = checkStrClaims(claims, "contractPosition_code")
|
||||
data.Employee_Position_Code = checkStrPtrClaims(claims, "employee_position_code")
|
||||
data.Doctor_Code = checkStrPtrClaims(claims, "doctor_string")
|
||||
data.Nurse_Code = checkStrPtrClaims(claims, "nurse_string")
|
||||
data.Midwife_Code = checkStrPtrClaims(claims, "midwife_string")
|
||||
data.Nutritionist_Code = checkStrPtrClaims(claims, "nutritionist_string")
|
||||
data.Laborant_Code = checkStrPtrClaims(claims, "laborant_string")
|
||||
data.Pharmachist_Code = checkStrPtrClaims(claims, "pharmachist_string")
|
||||
data.Doctor_Code = checkStrPtrClaims(claims, "doctor_code")
|
||||
data.Nurse_Code = checkStrPtrClaims(claims, "nurse_code")
|
||||
data.Midwife_Code = checkStrPtrClaims(claims, "midwife_code")
|
||||
data.Nutritionist_Code = checkStrPtrClaims(claims, "nutritionist_code")
|
||||
data.Laborant_Code = checkStrPtrClaims(claims, "laborant_code")
|
||||
data.Pharmachist_Code = checkStrPtrClaims(claims, "pharmachist_code")
|
||||
data.Intern_Position_Code = checkStrPtrClaims(claims, "intern_position_code")
|
||||
data.Employee_Id = checkUntPtrClaims(claims, "employee_id")
|
||||
return
|
||||
|
||||
@@ -2,7 +2,7 @@ package encounter
|
||||
|
||||
import (
|
||||
"errors"
|
||||
authhelper "simrs-vx/internal/lib/auth"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
@@ -17,28 +17,18 @@ import (
|
||||
ere "simrs-vx/internal/domain/references/encounter"
|
||||
|
||||
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"
|
||||
edc "simrs-vx/internal/domain/main-entities/death-cause"
|
||||
ed "simrs-vx/internal/domain/main-entities/doctor"
|
||||
ee "simrs-vx/internal/domain/main-entities/emergency"
|
||||
eem "simrs-vx/internal/domain/main-entities/employee"
|
||||
e "simrs-vx/internal/domain/main-entities/encounter"
|
||||
ei "simrs-vx/internal/domain/main-entities/inpatient"
|
||||
er "simrs-vx/internal/domain/main-entities/rehab"
|
||||
eir "simrs-vx/internal/domain/main-entities/internal-reference"
|
||||
erdh "simrs-vx/internal/domain/main-entities/responsible-doctor-hist"
|
||||
es "simrs-vx/internal/domain/main-entities/soapi"
|
||||
|
||||
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"
|
||||
udc "simrs-vx/internal/use-case/main-use-case/death-cause"
|
||||
ud "simrs-vx/internal/use-case/main-use-case/doctor"
|
||||
ue "simrs-vx/internal/use-case/main-use-case/emergency"
|
||||
uem "simrs-vx/internal/use-case/main-use-case/employee"
|
||||
ui "simrs-vx/internal/use-case/main-use-case/inpatient"
|
||||
ur "simrs-vx/internal/use-case/main-use-case/rehab"
|
||||
us "simrs-vx/internal/use-case/main-use-case/soapi"
|
||||
uir "simrs-vx/internal/use-case/main-use-case/internal-reference"
|
||||
urdh "simrs-vx/internal/use-case/main-use-case/responsible-doctor-hist"
|
||||
)
|
||||
|
||||
const source = "encounter"
|
||||
@@ -46,8 +36,11 @@ const source = "encounter"
|
||||
var now = time.Now()
|
||||
|
||||
func Create(input e.CreateDto) (*d.Data, error) {
|
||||
data := e.Encounter{}
|
||||
createSoapi := []es.CreateDto{}
|
||||
var (
|
||||
data e.Encounter
|
||||
recentSoapiDataforCopy []es.CreateDto
|
||||
err error
|
||||
)
|
||||
|
||||
event := pl.Event{
|
||||
Feature: "Create",
|
||||
@@ -57,51 +50,36 @@ func Create(input e.CreateDto) (*d.Data, error) {
|
||||
// Start log
|
||||
pl.SetLogInfo(&event, input, "started", "create")
|
||||
|
||||
// validate SubClass
|
||||
var subCode interface{}
|
||||
subCode, err := verifyClassCode(input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// verify whether the allocated visit count has not exceeded the limit
|
||||
if input.Class_Code == ere.ECAmbulatory && subCode.(ere.AmbulatoryClassCode) == ere.ACCRehab &&
|
||||
*input.VisitMode_Code == ere.VMCSeries {
|
||||
|
||||
dataEncounter, valid, err := verifyAllocatedVisitCount(input, &event)
|
||||
// validate rehab bpjs
|
||||
if input.RefTypeCode == ere.RTCBpjs && input.Class_Code == ere.ECAmbulatory && ere.AmbulatoryClassCode(*input.SubClass_Code) == ere.ACCRehab {
|
||||
// get latest rehab data
|
||||
recentRehabData, err := getLatestRehabData(input, &event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !valid {
|
||||
event.Status = "failed"
|
||||
event.ErrInfo = pl.ErrorInfo{
|
||||
Code: "visit-limit-exceeded",
|
||||
Detail: "Encounter has exceeded the allowed number of visits",
|
||||
Raw: errors.New("visit count exceeds allowed limit"),
|
||||
if recentRehabData != nil {
|
||||
// determine VisitModeCode
|
||||
input.VisitMode_Code, input.RecentEncounterAdm, err = determineVisitMode(recentRehabData, input, &event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, pl.SetLogError(&event, input)
|
||||
} else {
|
||||
input.VisitMode_Code = ere.VMCAdm
|
||||
}
|
||||
|
||||
// get data soapi
|
||||
createSoapi, err = getSoapiEncounterAdm(dataEncounter, &event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// if visitMode_Code is series, then get data soapi for copy
|
||||
if input.VisitMode_Code == ere.VMCSeries {
|
||||
// get data soapi
|
||||
recentSoapiDataforCopy, err = getSoapiEncounterAdm(*input.RecentEncounterAdm, &event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check if patient is new in the hospital
|
||||
dataPatient, err := ReadList(e.ReadListDto{
|
||||
FilterDto: e.FilterDto{Patient_Id: input.Patient_Id},
|
||||
AuthInfo: authhelper.AuthInfo{User_Id: input.User_Id}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if list, ok := dataPatient.Data.([]e.ResponseDto); ok {
|
||||
if len(list) < 1 {
|
||||
input.NewStatus = true
|
||||
}
|
||||
}
|
||||
input.NewStatus, err = identifyPatientStatus(input)
|
||||
|
||||
err = dg.I.Transaction(func(tx *gorm.DB) error {
|
||||
mwRunner := newMiddlewareRunner(&event, tx)
|
||||
@@ -122,74 +100,18 @@ func Create(input e.CreateDto) (*d.Data, error) {
|
||||
return err
|
||||
} else {
|
||||
data = *resData
|
||||
input.Id = data.Id
|
||||
}
|
||||
|
||||
switch input.Class_Code {
|
||||
case ere.ECAmbulatory:
|
||||
subCodeAmbulatory := subCode.(ere.AmbulatoryClassCode)
|
||||
ambCreate := ea.CreateDto{
|
||||
Encounter_Id: &data.Id,
|
||||
Class_Code: subCodeAmbulatory,
|
||||
VisitMode_Code: *input.VisitMode_Code,
|
||||
}
|
||||
_, err = ua.CreateData(ambCreate, &event, tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if subCodeAmbulatory == ere.ACCChemo {
|
||||
chemoCreate := ec.CreateDto{
|
||||
Encounter_Id: &data.Id,
|
||||
Status_Code: erc.DVCNew,
|
||||
SrcUnit_Id: input.Unit_Id,
|
||||
}
|
||||
_, err = uc.CreateData(chemoCreate, &event, tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if subCodeAmbulatory == ere.ACCRehab && *input.VisitMode_Code == ere.VMCAdm {
|
||||
// create data rehab
|
||||
if _, err = ur.CreateData(er.CreateDto{
|
||||
Encounter_Id: &data.Id,
|
||||
Doctor_Id: input.Appointment_Doctor_Id,
|
||||
AllocatedVisitCount: input.AllocatedVisitCount}, &event, tx); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if subCodeAmbulatory == ere.ACCRehab && *input.VisitMode_Code == ere.VMCSeries {
|
||||
// Insert Soapi
|
||||
if err = us.CreateBulkData(createSoapi, data.Id, &event, tx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
case ere.ECEmergency:
|
||||
emerCreate := ee.CreateDto{
|
||||
Encounter_Id: &data.Id,
|
||||
Class_Code: subCode.(ere.EmergencyClassCode),
|
||||
}
|
||||
_, err = ue.CreateData(emerCreate, &event, tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case ere.ECInpatient:
|
||||
inpCreate := ei.CreateDto{
|
||||
Encounter_Id: &data.Id,
|
||||
Class_Code: subCode.(ere.InpatientClassCode),
|
||||
Infra_Id: input.Infra_Id,
|
||||
}
|
||||
_, err = ui.CreateData(inpCreate, &event, tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
return errors.New("invalid encounter class code")
|
||||
// insert ambulatory/emergency/inpatient
|
||||
err = insertdataClassCode(input, recentSoapiDataforCopy, &event, tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// insert adm_employee_hist
|
||||
if _, err := uaeh.CreateData(eaeh.CreateDto{
|
||||
Encounter_Id: &data.Main.Id,
|
||||
Encounter_Id: &data.Id,
|
||||
Employee_Id: data.Adm_Employee_Id,
|
||||
StartedAt: &now}, &event, tx); err != nil {
|
||||
return err
|
||||
@@ -441,7 +363,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) {
|
||||
}
|
||||
|
||||
func CheckOut(input e.DischargeDto) (*d.Data, error) {
|
||||
rdDto := e.ReadDetailDto{Id: uint16(input.Id), Includes: "Ambulatory"}
|
||||
rdDto := e.ReadDetailDto{Id: uint16(input.Id), Includes: "Ambulatory,Rehab"}
|
||||
var data *e.Encounter
|
||||
var err error
|
||||
|
||||
@@ -471,10 +393,16 @@ func CheckOut(input e.DischargeDto) (*d.Data, error) {
|
||||
|
||||
if data.Ambulatory != nil && (data.Ambulatory.Class_Code == ere.ACCReg || data.Ambulatory.Class_Code == ere.ACCRehab) {
|
||||
// validate if soapi exist
|
||||
err = getSoapiByTypeCode(input.Id, *data.Ambulatory, &event, "check-out")
|
||||
if err != nil {
|
||||
if err = getSoapiByTypeCode(data, &event, "check-out"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if data.Ambulatory.Class_Code == ere.ACCRehab {
|
||||
// verify and update rehabData if visit count has reached the allowed limit
|
||||
if err = verifyRehabLimit(data, &event, tx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// chemo TBC
|
||||
if err := checkSoapiByDocExists(data.Id, &event, tx); err != nil {
|
||||
@@ -497,17 +425,17 @@ func CheckOut(input e.DischargeDto) (*d.Data, error) {
|
||||
}
|
||||
|
||||
// update finishedAt in latest responsible_doctor_hist
|
||||
if err = updateLatestResponsibleDoctorHist(e.CheckinDto{Id: input.Id, StartedAt: &now}, &event, tx); err != nil {
|
||||
if err = updateLatestResponsibleDoctorHist(e.CheckinDto{Id: input.Id, FinishedAt: &now}, &event, tx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// update finishedAt in latest adm_employee_hist
|
||||
if err = updateLatestAdmEmployeeHist(e.CheckinDto{Id: input.Id, StartedAt: &now}, &event, tx); err != nil {
|
||||
if err = updateLatestAdmEmployeeHist(e.CheckinDto{Id: input.Id, FinishedAt: &now}, &event, tx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// insert data death-cause
|
||||
if *input.Discharge_Method_Code == ere.DMCDeath {
|
||||
// insert data death-cause
|
||||
if _, err = udc.CreateData(edc.CreateDto{Encounter_Id: &input.Id, Value: input.DeathCause}, &event, tx); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -639,13 +567,13 @@ func CheckIn(input e.CheckinDto) (*d.Data, error) {
|
||||
|
||||
// validate if soapi exist
|
||||
if data.Ambulatory != nil && (data.Ambulatory.Class_Code == ere.ACCReg || data.Ambulatory.Class_Code == ere.ACCRehab) {
|
||||
err = getSoapiByTypeCode(input.Id, *data.Ambulatory, &event, "check-in")
|
||||
err = getSoapiByTypeCode(data, &event, "check-in")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Insert responsible_doctor_hist if responsible_doctor_id has changed && update latest history
|
||||
// Upsert responsible_doctor_hist if responsible_doctor_id has changed
|
||||
if data.Responsible_Doctor_Id == nil || *input.Responsible_Doctor_Id != *data.Responsible_Doctor_Id {
|
||||
// upsert responsibleDoctorHist
|
||||
if err = upsertResponsibleDoctorHist(erdh.CreateDto{
|
||||
@@ -657,7 +585,7 @@ func CheckIn(input e.CheckinDto) (*d.Data, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// Insert adm_employee_hist if adm_employee_id has changed && update latest history
|
||||
// Upsert adm_employee_hist if adm_employee_id has changed
|
||||
if input.Adm_Employee_Id != nil && *input.Adm_Employee_Id != *data.Adm_Employee_Id {
|
||||
// upsert admEmployeeHist
|
||||
if err = upsertAdmEmployeeHist(eaeh.CreateDto{
|
||||
@@ -674,15 +602,6 @@ func CheckIn(input e.CheckinDto) (*d.Data, error) {
|
||||
return err
|
||||
}
|
||||
|
||||
if data.Ambulatory.Class_Code == ere.ACCRehab {
|
||||
if err := updateRehabDoctor(er.UpdateDto{CreateDto: er.CreateDto{
|
||||
Encounter_Id: &data.Id,
|
||||
Doctor_Id: input.Responsible_Doctor_Id,
|
||||
}}, &event, tx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
pl.SetLogInfo(&event, nil, "complete")
|
||||
|
||||
return nil
|
||||
@@ -702,43 +621,205 @@ func CheckIn(input e.CheckinDto) (*d.Data, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func validateForeignKey(input e.CheckinDto) error {
|
||||
// validate employee_Id
|
||||
if input.Adm_Employee_Id != nil {
|
||||
if _, err := uem.ReadDetail(eem.ReadDetailDto{Id: uint16(*input.Adm_Employee_Id)}); err != nil {
|
||||
func RequestSwitchUnit(input e.SwitchUnitDto) (*d.Data, error) {
|
||||
rdDto := e.ReadDetailDto{Id: uint16(input.Id), Includes: "Responsible_Doctor"}
|
||||
var data *e.Encounter
|
||||
var err error
|
||||
|
||||
event := pl.Event{
|
||||
Feature: "RequestSwitchUnit",
|
||||
Source: source,
|
||||
}
|
||||
|
||||
// Start log
|
||||
pl.SetLogInfo(&event, input, "started", "checkOut")
|
||||
|
||||
unitIDs := make(map[uint16]struct{})
|
||||
doctorIDs := make(map[uint]struct{})
|
||||
for _, ref := range *input.InternalReferences {
|
||||
if ref.Unit_Id != nil {
|
||||
unitIDs[*ref.Unit_Id] = struct{}{}
|
||||
}
|
||||
if ref.Doctor_Id != nil {
|
||||
doctorIDs[*ref.Doctor_Id] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
// validate unit
|
||||
if err = validateUnitIds(unitIDs, &event); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// validate doctor
|
||||
if err = validateDoctorIds(doctorIDs, &event); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = dg.I.Transaction(func(tx *gorm.DB) error {
|
||||
pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail")
|
||||
if data, err = ReadDetailData(rdDto, &event, tx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// validate doctor_id
|
||||
if input.Responsible_Doctor_Id != nil {
|
||||
if _, err := ud.ReadDetail(ed.ReadDetailDto{Id: uint16(*input.Responsible_Doctor_Id)}); err != nil {
|
||||
//if data.IsDone() {
|
||||
// event.Status = "failed"
|
||||
// event.ErrInfo = pl.ErrorInfo{
|
||||
// Code: "data-state-mismatch",
|
||||
// Detail: "encounter is done",
|
||||
// Raw: errors.New("encounter is done"),
|
||||
// }
|
||||
// return pl.SetLogError(&event, input)
|
||||
//}
|
||||
|
||||
// verify Soapi exist for current responsible doctor
|
||||
dataSoapi, err := getSoapiByResponsibleDoctor(*data, &event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(dataSoapi) < 1 {
|
||||
event.Status = "failed"
|
||||
event.ErrInfo = pl.ErrorInfo{
|
||||
Code: "missing-soapi",
|
||||
Detail: fmt.Sprintf("Missing soapi from latest responsible doctor"),
|
||||
}
|
||||
return pl.SetLogError(&event, input)
|
||||
}
|
||||
|
||||
// bulk internal references
|
||||
if err := uir.CreateBulkData(*input.InternalReferences, input.Id, &event, tx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pl.SetLogInfo(&event, nil, "complete")
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil
|
||||
return &d.Data{
|
||||
Meta: d.IS{
|
||||
"source": source,
|
||||
"structure": "single-data",
|
||||
"status": "requestSwitchUnit",
|
||||
},
|
||||
Data: data.ToResponse(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func verifyClassCode(input e.CreateDto) (subCode interface{}, err error) {
|
||||
switch input.Class_Code {
|
||||
case ere.ECAmbulatory:
|
||||
subCode, err = ua.CheckClassCode(input.SubClass_Code)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case ere.ECEmergency:
|
||||
subCode, err = ue.CheckClassCode(input.SubClass_Code)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case ere.ECInpatient:
|
||||
subCode, err = ui.CheckClassCode(input.SubClass_Code)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
default:
|
||||
return nil, errors.New("invalid encounter class code")
|
||||
func ApproveSwitchUnit(input e.ApproveUnitDto) (*d.Data, error) {
|
||||
rdDto := e.ReadDetailDto{Id: uint16(input.Id), Includes: "Responsible_Doctor"}
|
||||
var data *e.Encounter
|
||||
var err error
|
||||
|
||||
event := pl.Event{
|
||||
Feature: "ApproveSwitchUnit",
|
||||
Source: source,
|
||||
}
|
||||
return
|
||||
|
||||
// Start log
|
||||
pl.SetLogInfo(&event, input, "started", "approveSwitchUnit")
|
||||
|
||||
err = dg.I.Transaction(func(tx *gorm.DB) error {
|
||||
pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail")
|
||||
if data, err = ReadDetailData(rdDto, &event, tx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// get internal reference
|
||||
irData, err := uir.ReadDetailData(eir.ReadDetailDto{
|
||||
Id: input.InternalReferences_Id, Includes: "Doctor"}, &event, tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if *irData.Status_Code != erc.DACNew {
|
||||
event.Status = "failed"
|
||||
event.ErrInfo = pl.ErrorInfo{
|
||||
Code: "data-state-mismatch",
|
||||
Detail: "internal references is approve",
|
||||
Raw: errors.New("internal references is approve"),
|
||||
}
|
||||
return pl.SetLogError(&event, input)
|
||||
}
|
||||
|
||||
//if data.IsDone() {
|
||||
// event.Status = "failed"
|
||||
// event.ErrInfo = pl.ErrorInfo{
|
||||
// Code: "data-state-mismatch",
|
||||
// Detail: "encounter is done",
|
||||
// Raw: errors.New("encounter is done"),
|
||||
// }
|
||||
// return pl.SetLogError(&event, input)
|
||||
//}
|
||||
|
||||
// verify Soapi exist for current responsible doctor
|
||||
dataSoapi, err := getSoapiByResponsibleDoctor(*data, &event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(dataSoapi) < 1 {
|
||||
event.Status = "failed"
|
||||
event.ErrInfo = pl.ErrorInfo{
|
||||
Code: "missing-soapi",
|
||||
Detail: fmt.Sprintf("Missing soapi from latest responsible doctor"),
|
||||
}
|
||||
return pl.SetLogError(&event, input)
|
||||
}
|
||||
|
||||
// update internal reference
|
||||
if err = uir.UpdateData(eir.UpdateDto{
|
||||
Id: input.InternalReferences_Id,
|
||||
CreateDto: eir.CreateDto{
|
||||
Encounter_Id: &input.Id,
|
||||
Doctor_Id: irData.Doctor_Id,
|
||||
Unit_Id: irData.Unit_Id,
|
||||
Status_Code: erc.DACApproved,
|
||||
}}, irData, &event, tx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// update encounter
|
||||
if err = updateEncounterApproveSwitchUnit(*irData, &event, tx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// update latest responsible doctor hist
|
||||
if err = updateLatestResponsibleDoctorHist(e.CheckinDto{Id: input.Id, FinishedAt: &now}, &event, tx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// create responsible doctor based on internal reference data
|
||||
if _, err = urdh.CreateData(erdh.CreateDto{
|
||||
Encounter_Id: &input.Id,
|
||||
Doctor_Id: irData.Doctor_Id,
|
||||
StartedAt: &now,
|
||||
}, &event, tx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// update data response
|
||||
data.Responsible_Doctor_Id = irData.Doctor_Id
|
||||
data.Unit = irData.Unit
|
||||
data.Specialist_Id = irData.Doctor.Specialist_Id
|
||||
data.Subspecialist_Id = irData.Doctor.Subspecialist_Id
|
||||
|
||||
pl.SetLogInfo(&event, nil, "complete")
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &d.Data{
|
||||
Meta: d.IS{
|
||||
"source": source,
|
||||
"structure": "single-data",
|
||||
"status": "updated",
|
||||
},
|
||||
Data: data.ToResponse(),
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
authhelper "simrs-vx/internal/lib/auth"
|
||||
|
||||
dg "github.com/karincake/apem/db-gorm-pg"
|
||||
"gorm.io/gorm"
|
||||
|
||||
@@ -23,9 +25,13 @@ import (
|
||||
|
||||
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"
|
||||
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"
|
||||
eem "simrs-vx/internal/domain/main-entities/employee"
|
||||
e "simrs-vx/internal/domain/main-entities/encounter"
|
||||
ei "simrs-vx/internal/domain/main-entities/inpatient"
|
||||
emo "simrs-vx/internal/domain/main-entities/material-order"
|
||||
emco "simrs-vx/internal/domain/main-entities/mcu-order"
|
||||
em "simrs-vx/internal/domain/main-entities/medication"
|
||||
@@ -36,19 +42,26 @@ import (
|
||||
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"
|
||||
eu "simrs-vx/internal/domain/main-entities/unit"
|
||||
|
||||
// udo "simrs-vx/internal/use-case/main-use-case/device-order"
|
||||
es "simrs-vx/internal/domain/main-entities/soapi"
|
||||
uaeh "simrs-vx/internal/use-case/main-use-case/adm-employee-hist"
|
||||
uir "simrs-vx/internal/use-case/main-use-case/internal-reference"
|
||||
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"
|
||||
ue "simrs-vx/internal/use-case/main-use-case/emergency"
|
||||
uem "simrs-vx/internal/use-case/main-use-case/employee"
|
||||
ui "simrs-vx/internal/use-case/main-use-case/inpatient"
|
||||
um "simrs-vx/internal/use-case/main-use-case/medication"
|
||||
umei "simrs-vx/internal/use-case/main-use-case/medication-item"
|
||||
umi "simrs-vx/internal/use-case/main-use-case/medicine-mix"
|
||||
ummi "simrs-vx/internal/use-case/main-use-case/medicine-mix-item"
|
||||
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"
|
||||
)
|
||||
|
||||
func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Encounter) {
|
||||
@@ -104,6 +117,19 @@ func setDataDischarge(src e.DischargeDto, dst *e.Encounter) {
|
||||
dst.FinishedAt = &now
|
||||
}
|
||||
|
||||
func setDataUpdateStatus(src e.UpdateStatusDto, dst *e.Encounter) {
|
||||
dst.Status_Code = src.StatusCode
|
||||
}
|
||||
|
||||
func setDataCheckIn(src e.CheckinDto, dst *e.Encounter) {
|
||||
if src.Adm_Employee_Id != nil {
|
||||
dst.Adm_Employee_Id = src.Adm_Employee_Id
|
||||
}
|
||||
|
||||
dst.Responsible_Doctor_Id = src.Responsible_Doctor_Id
|
||||
dst.StartedAt = src.StartedAt
|
||||
}
|
||||
|
||||
func checkSoapiByDocExists(encounter_id uint, event *pl.Event, tx *gorm.DB) error {
|
||||
pl.SetLogInfo(event, nil, "started", "checkSoapiByDocExists")
|
||||
var soapies []es.Soapi
|
||||
@@ -335,113 +361,6 @@ func getMcuOrders(encounter_id uint, event *pl.Event, tx *gorm.DB) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func setDataUpdateStatus(src e.UpdateStatusDto, dst *e.Encounter) {
|
||||
dst.Status_Code = src.StatusCode
|
||||
}
|
||||
|
||||
func setDataCheckIn(src e.CheckinDto, dst *e.Encounter) {
|
||||
if src.Adm_Employee_Id != nil {
|
||||
dst.Adm_Employee_Id = src.Adm_Employee_Id
|
||||
}
|
||||
|
||||
dst.Responsible_Doctor_Id = src.Responsible_Doctor_Id
|
||||
dst.StartedAt = src.StartedAt
|
||||
}
|
||||
|
||||
func createInternalReferences(input e.DischargeDto, event *pl.Event, tx *gorm.DB) error {
|
||||
unitIDs := make(map[uint16]struct{})
|
||||
doctorIDs := make(map[uint]struct{})
|
||||
|
||||
for _, ref := range *input.InternalReferences {
|
||||
if ref.Unit_Id != nil {
|
||||
unitIDs[*ref.Unit_Id] = struct{}{}
|
||||
}
|
||||
if ref.Doctor_Id != nil {
|
||||
doctorIDs[*ref.Doctor_Id] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
// validate unitIds
|
||||
if len(unitIDs) > 0 {
|
||||
var ids []uint16
|
||||
for id := range unitIDs {
|
||||
ids = append(ids, id)
|
||||
}
|
||||
|
||||
units, err := getUnits(ids, event, tx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to fetch units: %w", err)
|
||||
}
|
||||
if len(units) != len(ids) {
|
||||
event.Status = "failed"
|
||||
event.ErrInfo = pl.ErrorInfo{
|
||||
Code: "data-validation-fail",
|
||||
Detail: "unit_id not found",
|
||||
}
|
||||
return pl.SetLogError(event, nil)
|
||||
}
|
||||
}
|
||||
|
||||
// validate doctorIds
|
||||
if len(doctorIDs) > 0 {
|
||||
var ids []uint
|
||||
for id := range doctorIDs {
|
||||
ids = append(ids, id)
|
||||
}
|
||||
|
||||
doctors, err := getDoctors(ids, event, tx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to fetch doctors: %w", err)
|
||||
}
|
||||
if len(doctors) != len(ids) {
|
||||
event.Status = "failed"
|
||||
event.ErrInfo = pl.ErrorInfo{
|
||||
Code: "data-validation-fail",
|
||||
Detail: "doctor_id not found",
|
||||
}
|
||||
return pl.SetLogError(event, nil)
|
||||
}
|
||||
}
|
||||
|
||||
if err := uir.CreateBulkData(*input.InternalReferences, input.Id, event, tx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getUnits(unitIds []uint16, event *pl.Event, tx *gorm.DB) ([]eu.Unit, error) {
|
||||
pl.SetLogInfo(event, nil, "started", "getUnits")
|
||||
var units []eu.Unit
|
||||
err := tx.Where("\"Id\" IN ?", unitIds).Find(&units).Error
|
||||
if err != nil {
|
||||
event.Status = "failed"
|
||||
event.ErrInfo = pl.ErrorInfo{
|
||||
Code: "data-get-fail",
|
||||
Detail: "get units",
|
||||
Raw: err,
|
||||
}
|
||||
return nil, pl.SetLogError(event, nil)
|
||||
}
|
||||
return units, nil
|
||||
}
|
||||
|
||||
func getDoctors(doctorIds []uint, event *pl.Event, tx *gorm.DB) ([]ed.Doctor, error) {
|
||||
pl.SetLogInfo(event, nil, "started", "getDoctors")
|
||||
var doctors []ed.Doctor
|
||||
err := tx.Where("\"Id\" IN ?", doctorIds).Find(&doctors).Error
|
||||
if err != nil {
|
||||
event.Status = "failed"
|
||||
event.ErrInfo = pl.ErrorInfo{
|
||||
Code: "data-get-fail",
|
||||
Detail: "get doctors",
|
||||
Raw: err,
|
||||
}
|
||||
return nil, pl.SetLogError(event, nil)
|
||||
}
|
||||
return doctors, nil
|
||||
}
|
||||
|
||||
func upsertResponsibleDoctorHist(input erdh.CreateDto, event *pl.Event, dbx ...*gorm.DB) error {
|
||||
pl.SetLogInfo(event, nil, "started", "DBCreate")
|
||||
|
||||
@@ -566,7 +485,7 @@ func updateLatestResponsibleDoctorHist(input e.CheckinDto, event *pl.Event, dbx
|
||||
result := tx.
|
||||
Model(&erdh.ResponsibleDoctorHist{}).
|
||||
Where("\"Id\" = (?)", subQuery).
|
||||
Update("\"FinishedAt\"", input.StartedAt)
|
||||
Update("\"FinishedAt\"", input.FinishedAt)
|
||||
|
||||
if result.Error != nil {
|
||||
event.Status = "failed"
|
||||
@@ -607,7 +526,7 @@ func updateLatestAdmEmployeeHist(input e.CheckinDto, event *pl.Event, dbx ...*go
|
||||
result := tx.
|
||||
Model(&eaeh.AdmEmployeeHist{}).
|
||||
Where("\"Id\" = (?)", subQuery).
|
||||
Update("\"FinishedAt\"", input.StartedAt)
|
||||
Update("\"FinishedAt\"", input.FinishedAt)
|
||||
|
||||
if result.Error != nil {
|
||||
event.Status = "failed"
|
||||
@@ -628,9 +547,7 @@ func updateLatestAdmEmployeeHist(input e.CheckinDto, event *pl.Event, dbx ...*go
|
||||
return nil
|
||||
}
|
||||
|
||||
func getSoapiEncounterAdm(enc e.Encounter, event *pl.Event) (dataSoapi []es.CreateDto, err error) {
|
||||
var data []es.Soapi
|
||||
|
||||
func getSoapiByResponsibleDoctor(enc e.Encounter, event *pl.Event) (data []es.Soapi, err error) {
|
||||
pl.SetLogInfo(event, enc, "started", "DBReadList")
|
||||
|
||||
if enc.Responsible_Doctor == nil {
|
||||
@@ -642,6 +559,7 @@ func getSoapiEncounterAdm(enc e.Encounter, event *pl.Event) (dataSoapi []es.Crea
|
||||
}
|
||||
|
||||
err = dg.I.
|
||||
Debug().
|
||||
Model(&es.Soapi{}).
|
||||
Joins("JOIN \"Employee\" ON \"Employee\".\"Id\" = \"Soapi\".\"Employee_Id\"").
|
||||
Where("\"Encounter_Id\" = ?", enc.Id).
|
||||
@@ -653,21 +571,22 @@ func getSoapiEncounterAdm(enc e.Encounter, event *pl.Event) (dataSoapi []es.Crea
|
||||
if err != nil {
|
||||
event.Status = "failed"
|
||||
event.ErrInfo = pl.ErrorInfo{
|
||||
Raw: err,
|
||||
Raw: err,
|
||||
Code: "read-fail",
|
||||
Detail: "Database read failed",
|
||||
}
|
||||
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
event.ErrInfo.Code = "data-not-found"
|
||||
event.ErrInfo.Detail = "Data not found"
|
||||
return nil, pl.SetLogError(event, enc)
|
||||
}
|
||||
|
||||
event.ErrInfo.Code = "read-fail"
|
||||
event.ErrInfo.Detail = "Database read failed"
|
||||
return nil, pl.SetLogError(event, enc)
|
||||
}
|
||||
|
||||
pl.SetLogInfo(event, nil, "complete")
|
||||
return
|
||||
}
|
||||
|
||||
func getSoapiEncounterAdm(enc e.Encounter, event *pl.Event) (dataSoapi []es.CreateDto, err error) {
|
||||
data, err := getSoapiByResponsibleDoctor(enc, event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, s := range data {
|
||||
// set data soapi for copy
|
||||
@@ -690,39 +609,46 @@ func getSoapiEncounterAdm(enc e.Encounter, event *pl.Event) (dataSoapi []es.Crea
|
||||
return
|
||||
}
|
||||
|
||||
func getSoapiByTypeCode(encounterId uint, dataAmbulatory ea.Ambulatory, event *pl.Event, mode string) (err error) {
|
||||
pl.SetLogInfo(event, encounterId, "started", "DBReadList")
|
||||
func getSoapiByTypeCode(encounter *e.Encounter, event *pl.Event, mode string) (err error) {
|
||||
pl.SetLogInfo(event, encounter, "started", "DBReadList")
|
||||
|
||||
var (
|
||||
dataSoapi []es.Soapi
|
||||
amb = encounter.Ambulatory
|
||||
rehab = encounter.Rehab
|
||||
)
|
||||
|
||||
// Set Query for get data Soapi
|
||||
tx := dg.I.
|
||||
Model(&es.Soapi{}).
|
||||
Joins("JOIN \"Employee\" ON \"Employee\".\"Id\" = \"Soapi\".\"Employee_Id\"").
|
||||
Where("\"Encounter_Id\" = ?", encounterId).
|
||||
Where("\"Encounter_Id\" = ?", encounter.Id).
|
||||
Where("\"Employee\".\"Position_Code\" = ?", erg.EPCDoc)
|
||||
|
||||
// Set Case
|
||||
switch {
|
||||
case dataAmbulatory.Class_Code == ere.ACCReg:
|
||||
case amb.Class_Code == ere.ACCReg:
|
||||
tx = tx.Where("\"Soapi\".\"TypeCode\" = ?", ercl.STCEEarlyMedic)
|
||||
case dataAmbulatory.Class_Code == ere.ACCRehab && dataAmbulatory.VisitMode_Code == ere.VMCAdm:
|
||||
case amb.Class_Code == ere.ACCRehab && *rehab.VisitMode_Code == ere.VMCAdm:
|
||||
tx = tx.Where("\"Soapi\".\"TypeCode\" IN ?", []ercl.SoapiTypeCode{ercl.STCEEarlyMedic, ercl.STCFunc, ercl.STCEarlyRehab})
|
||||
case dataAmbulatory.Class_Code == ere.ACCRehab && dataAmbulatory.VisitMode_Code == ere.VMCSeries:
|
||||
case amb.Class_Code == ere.ACCRehab && *rehab.VisitMode_Code == ere.VMCSeries:
|
||||
tx = tx.Where("\"Soapi\".\"TypeCode\" = ?", ercl.STCEarlyRehab)
|
||||
}
|
||||
|
||||
if err = tx.Find(&dataSoapi).Error; err != nil {
|
||||
return setDBError(event, err, encounterId)
|
||||
return setDBError(event, err, encounter)
|
||||
}
|
||||
|
||||
pl.SetLogInfo(event, nil, "complete")
|
||||
return validateExistedSoapi(dataSoapi, &dataAmbulatory, event, mode)
|
||||
return validateExistedSoapi(dataSoapi, encounter, event, mode)
|
||||
}
|
||||
|
||||
func validateExistedSoapi(dataSoapi []es.Soapi, dataAmbulatory *ea.Ambulatory, event *pl.Event, mode string) error {
|
||||
func validateExistedSoapi(dataSoapi []es.Soapi, dataEncounter *e.Encounter, event *pl.Event, mode string) error {
|
||||
var (
|
||||
amb = dataEncounter.Ambulatory
|
||||
rehab = dataEncounter.Rehab
|
||||
)
|
||||
|
||||
typeExist := make(map[ercl.SoapiTypeCode]bool)
|
||||
for _, s := range dataSoapi {
|
||||
typeExist[s.TypeCode] = true
|
||||
@@ -731,11 +657,11 @@ func validateExistedSoapi(dataSoapi []es.Soapi, dataAmbulatory *ea.Ambulatory, e
|
||||
required := []ercl.SoapiTypeCode{}
|
||||
|
||||
switch {
|
||||
case dataAmbulatory.Class_Code == ere.ACCReg:
|
||||
case amb.Class_Code == ere.ACCReg:
|
||||
required = []ercl.SoapiTypeCode{ercl.STCEEarlyMedic}
|
||||
case dataAmbulatory.Class_Code == ere.ACCRehab && dataAmbulatory.VisitMode_Code == ere.VMCAdm:
|
||||
case amb.Class_Code == ere.ACCRehab && *rehab.VisitMode_Code == ere.VMCAdm:
|
||||
required = []ercl.SoapiTypeCode{ercl.STCEEarlyMedic, ercl.STCFunc, ercl.STCEarlyRehab}
|
||||
case dataAmbulatory.Class_Code == ere.ACCRehab && dataAmbulatory.VisitMode_Code == ere.VMCSeries:
|
||||
case amb.Class_Code == ere.ACCRehab && *rehab.VisitMode_Code == ere.VMCSeries:
|
||||
required = []ercl.SoapiTypeCode{ercl.STCEarlyRehab}
|
||||
}
|
||||
|
||||
@@ -762,6 +688,231 @@ func validateExistedSoapi(dataSoapi []es.Soapi, dataAmbulatory *ea.Ambulatory, e
|
||||
return nil
|
||||
}
|
||||
|
||||
func identifyPatientStatus(input e.CreateDto) (isNewPatient bool, err error) {
|
||||
dataPatient, err := ReadList(e.ReadListDto{
|
||||
FilterDto: e.FilterDto{Patient_Id: input.Patient_Id},
|
||||
AuthInfo: authhelper.AuthInfo{User_Id: input.User_Id}})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if list, ok := dataPatient.Data.([]e.ResponseDto); ok {
|
||||
if len(list) < 1 {
|
||||
isNewPatient = true
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func determineVisitMode(recentRehabData *er.Rehab, input e.CreateDto, event *pl.Event) (ere.VisitModeCode, *e.Encounter, error) {
|
||||
var (
|
||||
visitModeCode ere.VisitModeCode
|
||||
recentAdmEncounterData e.Encounter
|
||||
isQuotaValid bool
|
||||
err error
|
||||
)
|
||||
|
||||
switch *recentRehabData.Status_Code {
|
||||
case erc.DSCProcess:
|
||||
visitModeCode = ere.VMCSeries
|
||||
|
||||
// verify whether the allocated visit count has not exceeded the limit
|
||||
recentAdmEncounterData, isQuotaValid, err = verifyAllocatedVisitCount(input, event)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
if !isQuotaValid || recentRehabData.ExpiredAt.Before(*pu.GetTimeNow()) {
|
||||
event.Status = "failed"
|
||||
event.ErrInfo = pl.ErrorInfo{
|
||||
Code: "visit-limit-exceeded",
|
||||
Detail: "Encounter has exceeded the allowed number of visits or expired",
|
||||
Raw: errors.New("visit count exceeds allowed limit"),
|
||||
}
|
||||
return "", nil, pl.SetLogError(event, input)
|
||||
}
|
||||
|
||||
case erc.DSCDone:
|
||||
visitModeCode = ere.VMCAdm
|
||||
|
||||
default:
|
||||
event.Status = "failed"
|
||||
event.ErrInfo = pl.ErrorInfo{
|
||||
Code: "invalid-status",
|
||||
Detail: fmt.Sprintf("Unknown rehab status: %v", *recentRehabData.Status_Code),
|
||||
Raw: errors.New("unsupported rehab status"),
|
||||
}
|
||||
return "", nil, pl.SetLogError(event, input)
|
||||
}
|
||||
|
||||
return visitModeCode, &recentAdmEncounterData, nil
|
||||
}
|
||||
|
||||
func insertdataClassCode(input e.CreateDto, soapiData []es.CreateDto, event *pl.Event, tx *gorm.DB) (err error) {
|
||||
switch input.Class_Code {
|
||||
case ere.ECAmbulatory:
|
||||
subCode := ere.AmbulatoryClassCode(*input.SubClass_Code)
|
||||
ambCreate := ea.CreateDto{
|
||||
Encounter_Id: &input.Id,
|
||||
Class_Code: subCode,
|
||||
}
|
||||
|
||||
// create data Ambulatory
|
||||
_, err = ua.CreateData(ambCreate, event, tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// insert chemo/rehab
|
||||
err = insertDataSubClassAmbulatory(input, soapiData, event, tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case ere.ECEmergency:
|
||||
subCode := ere.EmergencyClassCode(*input.SubClass_Code)
|
||||
emerCreate := ee.CreateDto{
|
||||
Encounter_Id: &input.Id,
|
||||
Class_Code: subCode,
|
||||
}
|
||||
|
||||
// create data emergency
|
||||
_, err = ue.CreateData(emerCreate, event, tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case ere.ECInpatient:
|
||||
subCode := ere.InpatientClassCode(*input.SubClass_Code)
|
||||
inpCreate := ei.CreateDto{
|
||||
Encounter_Id: &input.Id,
|
||||
Class_Code: subCode,
|
||||
Infra_Id: input.Infra_Id,
|
||||
}
|
||||
|
||||
// create data inpatient
|
||||
_, err = ui.CreateData(inpCreate, event, tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
return errors.New("invalid encounter class code")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func insertDataSubClassAmbulatory(input e.CreateDto, soapiData []es.CreateDto, event *pl.Event, tx *gorm.DB) (err error) {
|
||||
subCode := ere.AmbulatoryClassCode(*input.SubClass_Code)
|
||||
|
||||
switch {
|
||||
case subCode == ere.ACCChemo:
|
||||
chemoCreate := ec.CreateDto{
|
||||
Encounter_Id: &input.Id,
|
||||
Status_Code: erc.DVCNew,
|
||||
SrcUnit_Id: input.Unit_Id,
|
||||
}
|
||||
|
||||
// create data chemo
|
||||
_, err = uc.CreateData(chemoCreate, event, tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case subCode == ere.ACCRehab:
|
||||
rehabData := er.CreateDto{
|
||||
Encounter_Id: &input.Id,
|
||||
VisitMode_Code: input.VisitMode_Code,
|
||||
Status_Code: erc.DSCProcess,
|
||||
}
|
||||
|
||||
// if visitMode_code is series, then bulk insert soapi
|
||||
if input.VisitMode_Code == ere.VMCSeries {
|
||||
rehabData.Parent_Encounter_Id = &input.RecentEncounterAdm.Id
|
||||
|
||||
// Insert Soapi
|
||||
if err = us.CreateBulkData(soapiData, input.Id, event, tx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// create rehab
|
||||
if _, err = ur.CreateData(rehabData, event, tx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func verifyRehabLimit(data *e.Encounter, event *pl.Event, tx *gorm.DB) error {
|
||||
// get data encounter adm
|
||||
encounterAdmData, _, err := verifyAllocatedVisitCount(e.CreateDto{Patient_Id: data.Patient_Id}, event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check if the visit count has reached the allowed limit
|
||||
// Mark latest rehab status as 'done' if exceeded.
|
||||
if len(*encounterAdmData.RehabChildren) >= *encounterAdmData.Rehab.AllocatedVisitCount {
|
||||
err = updateRehabStatus(er.UpdateDto{
|
||||
Id: uint16(data.Rehab.Id),
|
||||
CreateDto: er.CreateDto{Status_Code: erc.DSCDone}}, event, tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateRehabStatus(input er.UpdateDto, 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
|
||||
}
|
||||
|
||||
result := tx.
|
||||
Model(&er.Rehab{}).
|
||||
Where("\"Id\" = (?)", input.Id).
|
||||
Update("\"Status_Code\"", input.Status_Code)
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
pl.SetLogInfo(event, nil, "complete")
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateForeignKey(input e.CheckinDto) error {
|
||||
// validate employee_Id
|
||||
if input.Adm_Employee_Id != nil {
|
||||
if _, err := uem.ReadDetail(eem.ReadDetailDto{Id: uint16(*input.Adm_Employee_Id)}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// validate doctor_id
|
||||
if input.Responsible_Doctor_Id != nil {
|
||||
if _, err := ud.ReadDetail(ed.ReadDetailDto{Id: uint16(*input.Responsible_Doctor_Id)}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func setSoapiError(event *pl.Event, detail string) error {
|
||||
event.Status = "failed"
|
||||
event.ErrInfo = pl.ErrorInfo{
|
||||
@@ -781,31 +932,82 @@ func setDBError(event *pl.Event, err error, ctx any) error {
|
||||
return pl.SetLogError(event, ctx)
|
||||
}
|
||||
|
||||
func updateRehabDoctor(input er.UpdateDto, 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
|
||||
}
|
||||
|
||||
result := tx.
|
||||
Model(&er.Rehab{}).
|
||||
Where("\"Encounter_Id\" = (?)", input.Encounter_Id).
|
||||
Update("\"Doctor_Id\"", input.Doctor_Id)
|
||||
|
||||
if result.Error != nil {
|
||||
func getUnits(unitIds []uint16, event *pl.Event) ([]eu.Unit, error) {
|
||||
pl.SetLogInfo(event, nil, "started", "getUnits")
|
||||
var units []eu.Unit
|
||||
err := dg.I.Where("\"Id\" IN ?", unitIds).Find(&units).Error
|
||||
if err != nil {
|
||||
event.Status = "failed"
|
||||
event.ErrInfo = pl.ErrorInfo{
|
||||
Code: "data-update-fail",
|
||||
Detail: "Database update failed",
|
||||
Raw: result.Error,
|
||||
Code: "data-get-fail",
|
||||
Detail: "get units",
|
||||
Raw: err,
|
||||
}
|
||||
return nil, pl.SetLogError(event, nil)
|
||||
}
|
||||
return units, nil
|
||||
}
|
||||
|
||||
func getDoctors(doctorIds []uint, event *pl.Event) ([]ed.Doctor, error) {
|
||||
pl.SetLogInfo(event, nil, "started", "getDoctors")
|
||||
var doctors []ed.Doctor
|
||||
err := dg.I.Where("\"Id\" IN ?", doctorIds).Find(&doctors).Error
|
||||
if err != nil {
|
||||
event.Status = "failed"
|
||||
event.ErrInfo = pl.ErrorInfo{
|
||||
Code: "data-get-fail",
|
||||
Detail: "get doctors",
|
||||
Raw: err,
|
||||
}
|
||||
return nil, pl.SetLogError(event, nil)
|
||||
}
|
||||
return doctors, nil
|
||||
}
|
||||
|
||||
func validateUnitIds(unitIDs map[uint16]struct{}, event *pl.Event) error {
|
||||
if len(unitIDs) > 0 {
|
||||
var ids []uint16
|
||||
for id := range unitIDs {
|
||||
ids = append(ids, id)
|
||||
}
|
||||
|
||||
units, err := getUnits(ids, event)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to fetch units: %w", err)
|
||||
}
|
||||
if len(units) != len(ids) {
|
||||
event.Status = "failed"
|
||||
event.ErrInfo = pl.ErrorInfo{
|
||||
Code: "data-validation-fail",
|
||||
Detail: "unit_id not found",
|
||||
}
|
||||
return pl.SetLogError(event, nil)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateDoctorIds(doctorIDs map[uint]struct{}, event *pl.Event) error {
|
||||
if len(doctorIDs) > 0 {
|
||||
var ids []uint
|
||||
for id := range doctorIDs {
|
||||
ids = append(ids, id)
|
||||
}
|
||||
|
||||
doctors, err := getDoctors(ids, event)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to fetch doctors: %w", err)
|
||||
}
|
||||
if len(doctors) != len(ids) {
|
||||
event.Status = "failed"
|
||||
event.ErrInfo = pl.ErrorInfo{
|
||||
Code: "data-validation-fail",
|
||||
Detail: "doctor_id not found",
|
||||
}
|
||||
return pl.SetLogError(event, nil)
|
||||
}
|
||||
return pl.SetLogError(event, input)
|
||||
}
|
||||
|
||||
pl.SetLogInfo(event, nil, "complete")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -3,8 +3,7 @@ package encounter
|
||||
import (
|
||||
// std
|
||||
"errors"
|
||||
ere "simrs-vx/internal/domain/references/encounter"
|
||||
|
||||
eir "simrs-vx/internal/domain/main-entities/internal-reference"
|
||||
// external
|
||||
dg "github.com/karincake/apem/db-gorm-pg"
|
||||
gh "github.com/karincake/getuk"
|
||||
@@ -15,9 +14,14 @@ import (
|
||||
pl "simrs-vx/pkg/logger"
|
||||
pu "simrs-vx/pkg/use-case-helper"
|
||||
|
||||
ere "simrs-vx/internal/domain/references/encounter"
|
||||
|
||||
e "simrs-vx/internal/domain/main-entities/encounter"
|
||||
er "simrs-vx/internal/domain/main-entities/rehab"
|
||||
)
|
||||
|
||||
const ErrorReadFailed = "Database read failed"
|
||||
|
||||
func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.Encounter, error) {
|
||||
pl.SetLogInfo(event, nil, "started", "DBCreate")
|
||||
|
||||
@@ -251,20 +255,49 @@ func updateCheckInData(input e.CheckinDto, data *e.Encounter, event *pl.Event, d
|
||||
return nil
|
||||
}
|
||||
|
||||
func getLatestRehabData(i e.CreateDto, event *pl.Event) (recentRehabData *er.Rehab, err error) {
|
||||
pl.SetLogInfo(event, nil, "started", "DBGetLatestRehab")
|
||||
|
||||
var (
|
||||
tx = dg.I
|
||||
)
|
||||
|
||||
err = tx.
|
||||
Joins("JOIN \"Encounter\" ON \"Encounter\".\"Id\" = \"Rehab\".\"Encounter_Id\"").
|
||||
Where("\"Encounter\".\"Patient_Id\" = ?", i.Patient_Id).
|
||||
Order("\"CreatedAt\" DESC").
|
||||
First(&recentRehabData).Error
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
event.Status = "failed"
|
||||
event.ErrInfo = pl.ErrorInfo{
|
||||
Code: "read-recentRehab-fail",
|
||||
Detail: ErrorReadFailed,
|
||||
Raw: err,
|
||||
}
|
||||
return nil, pl.SetLogError(event, i)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func verifyAllocatedVisitCount(i e.CreateDto, event *pl.Event) (e.Encounter, bool, error) {
|
||||
pl.SetLogInfo(event, nil, "started", "DBGetRecentEncounterAdm")
|
||||
|
||||
var (
|
||||
tx = dg.I
|
||||
recentEncounterAdm e.Encounter
|
||||
countEncounterSeries int64
|
||||
tx = dg.I
|
||||
recentEncounterAdm e.Encounter
|
||||
valid = true
|
||||
)
|
||||
|
||||
err := tx.
|
||||
Scopes(gh.Preload("Rehab,Responsible_Doctor")).
|
||||
Joins("JOIN \"Ambulatory\" ON \"Ambulatory\".\"Encounter_Id\" = \"Encounter\".\"Id\"").
|
||||
Where("\"Patient_Id\" = ?", i.Patient_Id).
|
||||
Where("\"Ambulatory\".\"Class_Code\" = ? AND \"Ambulatory\".\"VisitMode_Code\" = ?", ere.ACCRehab, ere.VMCAdm).
|
||||
Scopes(gh.Preload("RehabChildren,Rehab,Responsible_Doctor")).
|
||||
Joins("JOIN \"Rehab\" ON \"Rehab\".\"Encounter_Id\" = \"Encounter\".\"Id\"").
|
||||
Where("\"Encounter\".\"Patient_Id\" = ?", i.Patient_Id).
|
||||
Where("\"Rehab\".\"VisitMode_Code\" = ?", ere.VMCAdm).
|
||||
Order("\"CreatedAt\" DESC").
|
||||
First(&recentEncounterAdm).Error
|
||||
if err != nil {
|
||||
@@ -277,22 +310,41 @@ func verifyAllocatedVisitCount(i e.CreateDto, event *pl.Event) (e.Encounter, boo
|
||||
return e.Encounter{}, false, pl.SetLogError(event, i)
|
||||
}
|
||||
|
||||
err = tx.
|
||||
Model(&e.Encounter{}).
|
||||
Joins("JOIN \"Ambulatory\" ON \"Ambulatory\".\"Encounter_Id\" = \"Encounter\".\"Id\"").
|
||||
Where("\"Patient_Id\" = ?", i.Patient_Id).
|
||||
Where("\"Ambulatory\".\"Class_Code\" = ? AND \"Ambulatory\".\"VisitMode_Code\" = ?", ere.ACCRehab, ere.VMCSeries).
|
||||
Where("\"Encounter\".\"CreatedAt\" > ?", recentEncounterAdm.CreatedAt).
|
||||
Count(&countEncounterSeries).Error
|
||||
if err != nil {
|
||||
event.Status = "failed"
|
||||
event.ErrInfo = pl.ErrorInfo{
|
||||
Code: "read-countEncounter-fail",
|
||||
Detail: "Database read failed",
|
||||
Raw: err,
|
||||
}
|
||||
return e.Encounter{}, false, pl.SetLogError(event, i)
|
||||
// validate count rehab children
|
||||
if recentEncounterAdm.RehabChildren != nil {
|
||||
valid = len(*recentEncounterAdm.RehabChildren) < *recentEncounterAdm.Rehab.AllocatedVisitCount
|
||||
}
|
||||
|
||||
return recentEncounterAdm, countEncounterSeries < int64(*recentEncounterAdm.Rehab.AllocatedVisitCount), nil
|
||||
return recentEncounterAdm, valid, nil
|
||||
}
|
||||
|
||||
func updateEncounterApproveSwitchUnit(input eir.InternalReference, event *pl.Event, dbx ...*gorm.DB) (err error) {
|
||||
pl.SetLogInfo(event, nil, "started", "DBCreate")
|
||||
|
||||
var tx *gorm.DB
|
||||
if len(dbx) > 0 {
|
||||
tx = dbx[0]
|
||||
} else {
|
||||
tx = dg.I
|
||||
}
|
||||
|
||||
if err := tx.Model(&e.Encounter{}).
|
||||
Where("\"Id\" = ?", input.Encounter_Id).
|
||||
Updates(map[string]interface{}{
|
||||
"Responsible_Doctor_Id": input.Doctor_Id,
|
||||
"Unit_Id": input.Unit_Id,
|
||||
"Specialist_Id": input.Doctor.Specialist_Id,
|
||||
"Subspecialist_Id": input.Doctor.Subspecialist_Id,
|
||||
}).Error; err != nil {
|
||||
event.Status = "failed"
|
||||
event.ErrInfo = pl.ErrorInfo{
|
||||
Code: "update-fail",
|
||||
Detail: "Failed to update encounter approve switch unit",
|
||||
Raw: err,
|
||||
}
|
||||
return pl.SetLogError(event, input)
|
||||
}
|
||||
|
||||
pl.SetLogInfo(event, input, "complete")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ package internal_reference
|
||||
|
||||
import (
|
||||
ir "simrs-vx/internal/domain/main-entities/internal-reference"
|
||||
erc "simrs-vx/internal/domain/references/common"
|
||||
)
|
||||
|
||||
func setData[T *ir.CreateDto | *ir.UpdateDto](input T, data *ir.InternalReference) {
|
||||
@@ -20,16 +21,19 @@ func setData[T *ir.CreateDto | *ir.UpdateDto](input T, data *ir.InternalReferenc
|
||||
data.Encounter_Id = inputSrc.Encounter_Id
|
||||
data.Unit_Id = inputSrc.Unit_Id
|
||||
data.Doctor_Id = inputSrc.Doctor_Id
|
||||
data.Status_Code = &inputSrc.Status_Code
|
||||
}
|
||||
|
||||
func setBulkData(input []ir.CreateDto, encounterId uint) []ir.InternalReference {
|
||||
var data []ir.InternalReference
|
||||
|
||||
for _, v := range input {
|
||||
statusCode := erc.DACNew
|
||||
data = append(data, ir.InternalReference{
|
||||
Encounter_Id: &encounterId,
|
||||
Unit_Id: v.Unit_Id,
|
||||
Doctor_Id: v.Doctor_Id,
|
||||
Status_Code: &statusCode,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,9 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Rehab) {
|
||||
}
|
||||
|
||||
data.Encounter_Id = inputSrc.Encounter_Id
|
||||
data.Doctor_Id = inputSrc.Doctor_Id
|
||||
data.Parent_Encounter_Id = inputSrc.Parent_Encounter_Id
|
||||
data.AllocatedVisitCount = inputSrc.AllocatedVisitCount
|
||||
data.ExpiredAt = inputSrc.ExpiredAt
|
||||
data.VisitMode_Code = &inputSrc.VisitMode_Code
|
||||
data.Status_Code = &inputSrc.Status_Code
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user