Merge pull request #208 from dikstub-rssa/fix/anything-moko

Fix/anything moko
This commit is contained in:
Dwi Atmoko Purbo Sakti
2025-12-11 15:52:43 +07:00
committed by GitHub
7 changed files with 218 additions and 10 deletions
@@ -297,3 +297,8 @@ func ToResponseList(data []Encounter) []ResponseDto {
}
return resp
}
type CreateWithPatientDto struct {
Encounter CreateDto `json:"encounter"`
Patient ep.CreateDto `json:"patient"`
}
@@ -312,3 +312,29 @@ func (obj myBase) CancelSwitchUnit(w http.ResponseWriter, r *http.Request) {
res, err := u.CancelSwitchUnit(dto)
rw.DataResponse(w, res, err)
}
func (obj myBase) CreateWithPatient(w http.ResponseWriter, r *http.Request) {
authInfo, err := pa.GetAuthInfo(r)
if err != nil {
rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil)
}
dto := e.CreateWithPatientDto{}
if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res {
return
}
// validate SubClass
if err := verifyClassCode(dto.Encounter); err != nil {
rw.DataResponse(w, nil, d.FieldError{
Code: dataValidationFail,
Message: err.Error(),
})
return
}
dto.Encounter.AuthInfo = *authInfo
dto.Patient.AuthInfo = *authInfo
res, err := u.CreateWithPatient(dto)
rw.DataResponse(w, res, err)
}
@@ -197,6 +197,7 @@ func SetRoutes() http.Handler {
"PATCH /{id}/req-switch-unit": encounter.O.RequestSwitchUnit,
"PATCH /{id}/approve-switch-unit": encounter.O.ApproveSwitchUnit,
"PATCH /{id}/cancel-switch-unit": encounter.O.CancelSwitchUnit,
"POST /create-with-patient": encounter.O.CreateWithPatient,
})
hk.GroupRoutes("/v1/mcu-order", r, auth.GuardMW, hk.MapHandlerFunc{
"GET /": mcuorder.O.GetList,
@@ -22,12 +22,14 @@ import (
edc "simrs-vx/internal/domain/main-entities/death-cause"
e "simrs-vx/internal/domain/main-entities/encounter"
eir "simrs-vx/internal/domain/main-entities/internal-reference"
ep "simrs-vx/internal/domain/main-entities/patient"
es "simrs-vx/internal/domain/main-entities/soapi"
esync "simrs-vx/internal/domain/sync-entities/log"
uv "simrs-vx/internal/use-case/bpjs-use-case/vclaim-reference"
udc "simrs-vx/internal/use-case/main-use-case/death-cause"
uir "simrs-vx/internal/use-case/main-use-case/internal-reference"
up "simrs-vx/internal/use-case/main-use-case/patient"
us "simrs-vx/internal/use-case/main-use-case/soapi"
)
@@ -1075,3 +1077,144 @@ func validateAuth(a auth.AuthInfo, roleAllowed []string, action string, event *p
return nil
}
func CreateWithPatient(input e.CreateWithPatientDto) (*d.Data, error) {
var (
data e.Encounter
recentSoapiDataforCopy []es.CreateDto
err error
)
event := pl.Event{
Feature: "Create",
Source: source,
}
// Start log
pl.SetLogInfo(&event, input, "started", "create")
roleAllowed := []string{string(erg.EPCReg)}
err = validateAuth(input.Encounter.AuthInfo, roleAllowed, "create-encounter", &event)
if err != nil {
return nil, err
}
// validate rehab by bpjs
if input.Encounter.RefTypeCode == ere.RTCBpjs &&
input.Encounter.Class_Code == ere.ECAmbulatory &&
ere.AmbulatoryClassCode(*input.Encounter.SubClass_Code) == ere.ACCRehab {
// get latest rehab data
recentRehabData, err := getLatestRehabData(input.Encounter, &event)
if err != nil {
return nil, err
}
// If recentRehabData is nil, then visitMode_Code = "adm"
if recentRehabData != nil {
// If recentRehabData is not nil, determine the visitMode_Code:
// If the mode is "series", verify whether the visit count still remains
// and whether the series has not expired.
// If visitMode is "series", then get encounterAdm
input.Encounter.VisitMode_Code, input.Encounter.RecentEncounterAdm, err = determineVisitMode(recentRehabData, input.Encounter, &event)
if err != nil {
return nil, err
}
} else {
input.Encounter.VisitMode_Code = ere.VMCAdm
}
// When visitMode_Code is "series", load the associated SOAPI record to copy its values.
if input.Encounter.VisitMode_Code == ere.VMCSeries {
// get data soapi
recentSoapiDataforCopy, err = getSoapiEncounterAdm(*input.Encounter.RecentEncounterAdm, &event)
if err != nil {
return nil, err
}
}
}
// check if patient is new in the hospital
input.Encounter.NewStatus, err = identifyPatientStatus(input.Encounter)
if err != nil {
return nil, err
}
input.Encounter.Adm_Employee_Id = input.Encounter.AuthInfo.Employee_Id
mwRunner := newMiddlewareRunner(&event, input.Encounter.Sync)
err = dg.I.Transaction(func(tx *gorm.DB) error {
// create patient
var patientId uint
patientData, err := up.Create(input.Patient, tx)
if err != nil {
return err
}
if patientData != nil {
patientId = patientData.Data.(ep.ResponseDto).Id
}
// create encounter
input.Encounter.Patient_Id = &patientId
if resData, err := CreateData(input.Encounter, &event, tx); err != nil {
return err
} else {
data = *resData
input.Encounter.Id = data.Id
}
// insert ambulatory/emergency/inpatient
err = insertdataClassCode(input.Encounter, recentSoapiDataforCopy, &event, tx)
if err != nil {
return err
}
// insert vclaimReference
if vr := input.Encounter.VclaimReference; vr != nil {
t, _ := time.Parse("2006-01-02", vr.TglRujukan)
_, err = uv.CreateData(ev.CreateDto{
Encounter_Id: &data.Id,
Date: &t,
SrcCode: input.Encounter.Ref_Number,
SrcName: input.Encounter.RefSource_Name,
Number: &vr.NoSep}, &event, tx)
if err != nil {
return err
}
}
dataEncounter, err := ReadDetailData(e.ReadDetailDto{
Id: data.Id,
Includes: "Adm_Employee.User,Adm_Employee.Person," +
"Patient.Person.Relatives," +
"Patient.Person.VclaimMember,VclaimReference," +
"Patient.Person.Contacts,Patient.Person.Addresses"},
&event, tx)
if err != nil {
return err
}
mwRunner.setMwType(pu.MWTPre)
// Run pre-middleware
if err := mwRunner.RunCreateWithPatientMiddleware(createWithPatientPreMw, dataEncounter); err != nil {
return err
}
return nil
})
if err = runLogMiddleware(err, input, mwRunner); err != nil {
return nil, err
}
pl.SetLogInfo(&event, nil, "complete")
return &d.Data{
Meta: d.II{
"source": source,
"structure": "single-data",
"status": "created",
},
Data: data.ToResponse(),
}, nil
}
@@ -259,3 +259,22 @@ func (me *middlewareRunner) RunCancelSwitchUnitMiddleware(middleware cancelSwitc
func (me *middlewareRunner) setMwType(mwType pu.MWType) {
me.MwType = mwType
}
func (me *middlewareRunner) RunCreateWithPatientMiddleware(middlewares []createWithPatientMw, input *e.Encounter) error {
if !me.SyncOn {
return nil
}
for _, middleware := range middlewares {
logData := pu.GetLogData(input, nil)
pl.SetLogInfo(me.Event, logData, "started", middleware.Name)
if err := middleware.Func(input); err != nil {
return pu.HandleMiddlewareError(me.Event, string(me.MwType), middleware.Name, logData, err)
}
pl.SetLogInfo(me.Event, nil, "complete")
}
return nil
}
@@ -74,6 +74,11 @@ type cancelSwitchUnitMw struct {
Func func(input *e.ApproveCancelUnitDto) error
}
type createWithPatientMw struct {
Name string
Func func(input *e.Encounter) error
}
type UpdateMw = updateMw
type DeleteMw = deleteMw
@@ -94,3 +99,5 @@ var updatestatusEncounter []updateStatusMw
var requestSwitchEncounter requestSwitchUnitMw
var approveSwitchEncounter approveSwitchUnitMw
var cancelSwitchEncounter cancelSwitchUnitMw
var createWithPatientPreMw []createWithPatientMw
var createWithPatientPostMw []createWithPatientMw
+17 -10
View File
@@ -27,7 +27,7 @@ import (
const source = "patient"
func Create(input e.CreateDto) (*d.Data, error) {
func Create(input e.CreateDto, dbx ...*gorm.DB) (*d.Data, error) {
data := e.Patient{}
event := pl.Event{
@@ -35,6 +35,13 @@ func Create(input e.CreateDto) (*d.Data, error) {
Source: source,
}
var tx *gorm.DB
if len(dbx) > 0 {
tx = dbx[0]
} else {
tx = dg.I
}
// Start log
pl.SetLogInfo(&event, input, "started", "create")
mwRunner := newMiddlewareRunner(&event, input.Sync)
@@ -51,7 +58,7 @@ func Create(input e.CreateDto) (*d.Data, error) {
input.RegisteredBy_User_Name = &input.AuthInfo.User_Name
err := dg.I.Transaction(func(tx *gorm.DB) error {
err := tx.Transaction(func(tx1 *gorm.DB) error {
mwRunner.setMwType(pu.MWTPre)
// Run pre-middleware
if err := mwRunner.RunCreateMiddleware(createPreMw, &input, &data); err != nil {
@@ -65,14 +72,14 @@ func Create(input e.CreateDto) (*d.Data, error) {
}
input.Number = nomr
if person_id, err := upe.CreateOrUpdatePerson(input.Person, &event, tx); err != nil {
if person_id, err := upe.CreateOrUpdatePerson(input.Person, &event, tx1); err != nil {
return err
} else {
input.Person_Id = person_id
}
if input.Person.VclaimMember_CardNumber != nil && input.Person.ResidentIdentityNumber != nil {
if err := uvm.CreateOrUpdateData(evm.CreateDto{CardNumber: input.Person.VclaimMember_CardNumber, Person_Id: input.Person_Id}, &event, tx); err != nil {
if err := uvm.CreateOrUpdateData(evm.CreateDto{CardNumber: input.Person.VclaimMember_CardNumber, Person_Id: input.Person_Id}, &event, tx1); err != nil {
return err
}
}
@@ -80,38 +87,38 @@ func Create(input e.CreateDto) (*d.Data, error) {
for idx := range input.PersonAddresses {
input.PersonAddresses[idx].Person_Id = *input.Person_Id
}
if err := upa.CreateOrUpdateBatch(input.PersonAddresses, &event, tx); err != nil {
if err := upa.CreateOrUpdateBatch(input.PersonAddresses, &event, tx1); err != nil {
return err
}
for idx := range input.PersonContacts {
input.PersonContacts[idx].Person_Id = *input.Person_Id
}
if err := upc.CreateOrUpdateBatch(input.PersonContacts, &event, tx); err != nil {
if err := upc.CreateOrUpdateBatch(input.PersonContacts, &event, tx1); err != nil {
return err
}
for idx := range input.PersonRelatives {
input.PersonRelatives[idx].Person_Id = *input.Person_Id
}
if err := upr.CreateOrUpdateBatch(input.PersonRelatives, &event, tx); err != nil {
if err := upr.CreateOrUpdateBatch(input.PersonRelatives, &event, tx1); err != nil {
return err
}
for idx := range input.PersonInsurances {
input.PersonInsurances[idx].Person_Id = *input.Person_Id
}
if err := upi.CreateOrUpdateBatch(input.PersonInsurances, &event, tx); err != nil {
if err := upi.CreateOrUpdateBatch(input.PersonInsurances, &event, tx1); err != nil {
return err
}
if resData, err := CreateData(input, &event, tx); err != nil {
if resData, err := CreateData(input, &event, tx1); err != nil {
return err
} else {
data = *resData
}
dataPatient, err := ReadDetailData(e.ReadDetailDto{Id: uint16(data.Id)}, &event, tx)
dataPatient, err := ReadDetailData(e.ReadDetailDto{Id: uint16(data.Id)}, &event, tx1)
if err != nil {
return err
}