diff --git a/internal/domain/main-entities/soapi/dto.go b/internal/domain/main-entities/soapi/dto.go index 94094df7..bc847b3b 100644 --- a/internal/domain/main-entities/soapi/dto.go +++ b/internal/domain/main-entities/soapi/dto.go @@ -37,16 +37,19 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id uint `json:"id"` + Includes string `json:"includes"` } type UpdateDto struct { - Id uint16 `json:"id"` + Id uint `json:"id"` CreateDto + pa.AuthInfo } type DeleteDto struct { - Id uint16 `json:"id"` + Id uint `json:"id"` + pa.AuthInfo } type MetaDto struct { diff --git a/internal/domain/references/clinical/clinical.go b/internal/domain/references/clinical/clinical.go index a9d3fc2b..2cfdb3a5 100644 --- a/internal/domain/references/clinical/clinical.go +++ b/internal/domain/references/clinical/clinical.go @@ -396,8 +396,8 @@ type SoapiSrc struct { type EarlyMedicValue struct { Vaccinated bool `json:"vaccinated,omitempty"` - CaseStatus string `json:"case-status,omitempty"` - EncounterStatus string `json:"encounter-status,omitempty"` + CaseStatus int `json:"case-status,omitempty"` + EncounterStatus int `json:"encounter-status,omitempty"` PrimaryComplain string `json:"pri-complain,omitempty"` CurrentDiseaseHistory string `json:"cur-disea-hist,omitempty"` SpO2 int `json:"spo2,omitempty"` diff --git a/internal/domain/simgos-entities/t-rekammedik/entity.go b/internal/domain/simgos-entities/t-rekammedik/entity.go index 5df0ec83..8599db5d 100644 --- a/internal/domain/simgos-entities/t-rekammedik/entity.go +++ b/internal/domain/simgos-entities/t-rekammedik/entity.go @@ -5,14 +5,14 @@ import "time" type TRekammedik struct { TglKirim *time.Time `json:"tgl_kirim" gorm:"column:tgl_kirim"` TglTerima *time.Time `json:"tgl_terima" gorm:"column:tgl_terima"` - Idxdaftar int `json:"idxdaftar" gorm:"column:idxdaftar"` - Kdpoly int `json:"kdpoly" gorm:"column:kdpoly"` + Idxdaftar uint `json:"idxdaftar" gorm:"column:idxdaftar"` + Kdpoly uint `json:"kdpoly" gorm:"column:kdpoly"` Pengirim string `json:"pengirim" gorm:"column:pengirim"` Penerima string `json:"penerima" gorm:"column:penerima"` - Statusrm int `json:"statusrm" gorm:"column:statusrm"` + Statusrm uint `json:"statusrm" gorm:"column:statusrm"` PenerimaPoly string `json:"penerima_poly" gorm:"column:penerima_poly"` - JamKirimRm string `json:"jam_kirim_rm" gorm:"column:jam_kirim_rm"` - JamTerimaRm string `json:"jam_terima_rm" gorm:"column:jam_terima_rm"` + JamKirimRm *time.Time `json:"jam_kirim_rm" gorm:"column:jam_kirim_rm"` + JamTerimaRm *time.Time `json:"jam_terima_rm" gorm:"column:jam_terima_rm"` PjBerkasRm string `json:"pj_berkas_rm" gorm:"column:pj_berkas_rm"` StatusFisikBerkas string `json:"status_fisik_berkas" gorm:"column:status_fisik_berkas"` } diff --git a/internal/interface/main-handler/soapi/handler.go b/internal/interface/main-handler/soapi/handler.go index fe50b7d2..3683bb23 100644 --- a/internal/interface/main-handler/soapi/handler.go +++ b/internal/interface/main-handler/soapi/handler.go @@ -47,7 +47,7 @@ func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { return } dto := e.ReadDetailDto{} - dto.Id = uint16(id) + dto.Id = uint(id) res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } @@ -62,7 +62,7 @@ func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { return } - dto.Id = uint16(id) + dto.Id = uint(id) res, err := u.Update(dto) rw.DataResponse(w, res, err) } @@ -74,7 +74,7 @@ func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { } dto := e.DeleteDto{} - dto.Id = uint16(id) + dto.Id = uint(id) res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/simgos-sync-handler/new/soapi/handler.go b/internal/interface/simgos-sync-handler/new/soapi/handler.go new file mode 100644 index 00000000..3a52a581 --- /dev/null +++ b/internal/interface/simgos-sync-handler/new/soapi/handler.go @@ -0,0 +1,58 @@ +package soapi + +import ( + "net/http" + + rw "github.com/karincake/risoles" + // ua "github.com/karincake/tumpeng/auth/svc" + + e "simrs-vx/internal/domain/main-entities/soapi" + esync "simrs-vx/internal/domain/sync-entities/log" + + u "simrs-vx/internal/use-case/simgos-sync-use-case/new/soapi" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.Soapi{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) CreateLog(w http.ResponseWriter, r *http.Request) { + dto := esync.SimxLogDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.CreateSimxLog(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + dto := e.Soapi{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + + res, err := u.Update(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.DeleteDto{} + dto.Id = uint(id) + + res, err := u.Delete(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/simgos-sync-handler/simgos-sync-handler.go b/internal/interface/simgos-sync-handler/simgos-sync-handler.go index f120b1cb..62e3e615 100644 --- a/internal/interface/simgos-sync-handler/simgos-sync-handler.go +++ b/internal/interface/simgos-sync-handler/simgos-sync-handler.go @@ -25,6 +25,7 @@ import ( "simrs-vx/internal/interface/simgos-sync-handler/new/encounter" "simrs-vx/internal/interface/simgos-sync-handler/new/installation" "simrs-vx/internal/interface/simgos-sync-handler/new/patient" + "simrs-vx/internal/interface/simgos-sync-handler/new/soapi" "simrs-vx/internal/interface/simgos-sync-handler/new/specialist" "simrs-vx/internal/interface/simgos-sync-handler/new/subspecialist" "simrs-vx/internal/interface/simgos-sync-handler/new/unit" @@ -71,6 +72,7 @@ func SetRoutes() http.Handler { "PATCH /{id}/approve-switch-unit": encounter.O.ApproveSwitchUnit, "PATCH /{id}/cancel-switch-unit": encounter.O.CancelSwitchUnit, }) + hc.SyncCrud(r, prefixnew+"/v1/soapi", soapi.O) /******************** SvcToNew ******************/ prefixold := "/old-to-new" diff --git a/internal/use-case/main-use-case/encounter/case.go b/internal/use-case/main-use-case/encounter/case.go index 19c9da70..1ff2eb11 100644 --- a/internal/use-case/main-use-case/encounter/case.go +++ b/internal/use-case/main-use-case/encounter/case.go @@ -525,7 +525,6 @@ func UpdateStatusCode(input e.UpdateStatusDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "update") - // TODO: Only "supervisi pendaftaran" could cancel encounter roleAllowed := []string{string(erg.EPCReg), string(erg.EPCNur), string(erg.EPCDoc)} err = validateAuth(input.AuthInfo, roleAllowed, "update-status-encounter", &event) if err != nil { @@ -575,9 +574,14 @@ func UpdateStatusCode(input e.UpdateStatusDto) (*d.Data, error) { return err } - if input.StatusCode == erc.DSCProcess || input.StatusCode == erc.DSCCancel { - data.Status_Code = input.StatusCode + // get data encounter + if data, err = ReadDetailData(e.ReadDetailDto{ + Id: input.Id, + Includes: "Adm_Employee.User"}, &event, tx); err != nil { + return err + } + if input.StatusCode == erc.DSCProcess || input.StatusCode == erc.DSCCancel { mwRunner.setMwType(pu.MWTPre) // Run pre-middleware if err := mwRunner.RunUpdateStatusMiddleware(updatestatusEncounter, data); err != nil { diff --git a/internal/use-case/main-use-case/encounter/lib.go b/internal/use-case/main-use-case/encounter/lib.go index 4a02973a..adf447ac 100644 --- a/internal/use-case/main-use-case/encounter/lib.go +++ b/internal/use-case/main-use-case/encounter/lib.go @@ -221,7 +221,10 @@ func UpdateStatusData(input e.UpdateStatusDto, event *pl.Event, dbx ...*gorm.DB) if err := tx.Model(&e.Encounter{}). Where("\"Id\" = ?", input.Id). - Update("Status_Code", input.StatusCode).Error; err != nil { + Updates(map[string]interface{}{ + "Status_Code": input.StatusCode, + "Adm_Employee_Id": input.Employee_Id, + }).Error; err != nil { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ Code: "update-fail", diff --git a/internal/use-case/main-use-case/soapi/case.go b/internal/use-case/main-use-case/soapi/case.go index 3dc8e195..8f4d29e2 100644 --- a/internal/use-case/main-use-case/soapi/case.go +++ b/internal/use-case/main-use-case/soapi/case.go @@ -2,6 +2,8 @@ package soapi import ( "errors" + erc "simrs-vx/internal/domain/references/common" + esync "simrs-vx/internal/domain/sync-entities/log" "strconv" e "simrs-vx/internal/domain/main-entities/soapi" @@ -27,53 +29,50 @@ func Create(input e.CreateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") + mwRunner := newMiddlewareRunner(&event, input.Sync) + + if !input.AuthInfo.IsDoctor() && !input.AuthInfo.IsNurse() { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "auth-forbidden", + Detail: "user position is not allowed", + Raw: errors.New("authentication failed"), + } + return nil, pl.SetLogError(&event, input) + } err := dg.I.Transaction(func(tx *gorm.DB) error { - mwRunner := newMiddlewareRunner(&event, tx) - mwRunner.setMwType(pu.MWTPre) - // Run pre-middleware - if err := mwRunner.RunCreateMiddleware(createPreMw, &input, &data); err != nil { - return err - } - - if !input.AuthInfo.IsDoctor() && !input.AuthInfo.IsNurse() { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "auth-forbidden", - Detail: "user position is not allowed", - Raw: errors.New("authentication failed"), - } - return pl.SetLogError(&event, input) - } - - if input.AuthInfo.Employee_Id != nil { - v := uint(*input.AuthInfo.Employee_Id) - input.Employee_Id = &v - } else { - input.Employee_Id = nil - } - if resData, err := CreateData(input, &event, tx); err != nil { return err } else { data = *resData } - mwRunner.setMwType(pu.MWTPost) - // Run post-middleware - if err := mwRunner.RunCreateMiddleware(createPostMw, &input, &data); err != nil { + // get detail for sync + soapiData, err := ReadDetailData(e.ReadDetailDto{ + Id: data.Id, + Includes: "Encounter,Employee"}, &event) + if err != nil { return err } - pl.SetLogInfo(&event, nil, "complete") + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err = mwRunner.ExecuteIfSyncOn(func() error { + return mwRunner.RunCreateMiddleware(createPostMw, soapiData) + }); err != nil { + return err + } return nil }) - if err != nil { + if err = runLogMiddleware(err, input, erc.CCCreate, mwRunner); err != nil { return nil, err } + pl.SetLogInfo(&event, nil, "complete") + return &d.Data{ Meta: d.II{ "source": source, @@ -85,7 +84,6 @@ func Create(input e.CreateDto) (*d.Data, error) { } func ReadList(input e.ReadListDto) (*d.Data, error) { - var data *e.Soapi var dataList []e.Soapi var metaList *e.MetaDto var err error @@ -99,23 +97,9 @@ func ReadList(input e.ReadListDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "readList") err = dg.I.Transaction(func(tx *gorm.DB) error { - mwRunner := newMiddlewareRunner(&event, tx) - mwRunner.setMwType(pu.MWTPre) - // Run pre-middleware - if err := mwRunner.RunReadListMiddleware(readListPreMw, &input, data); err != nil { - return err - } - if dataList, metaList, err = ReadListData(input, &event, tx); err != nil { return err } - - mwRunner.setMwType(pu.MWTPost) - // Run post-middleware - if err := mwRunner.RunReadListMiddleware(readListPostMw, &input, data); err != nil { - return err - } - return nil }) @@ -150,23 +134,9 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "readDetail") err = dg.I.Transaction(func(tx *gorm.DB) error { - mwRunner := newMiddlewareRunner(&event, tx) - mwRunner.setMwType(pu.MWTPre) - // Run pre-middleware - if err := mwRunner.RunReadDetailMiddleware(readDetailPreMw, &input, data); err != nil { - return err - } - if data, err = ReadDetailData(input, &event, tx); err != nil { return err } - - mwRunner.setMwType(pu.MWTPost) - // Run post-middleware - if err := mwRunner.RunReadDetailMiddleware(readDetailPostMw, &input, data); err != nil { - return err - } - return nil }) @@ -196,6 +166,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "update") + mwRunner := newMiddlewareRunner(&event, input.Sync) err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") @@ -203,32 +174,35 @@ func Update(input e.UpdateDto) (*d.Data, error) { return err } - mwRunner := newMiddlewareRunner(&event, tx) - mwRunner.setMwType(pu.MWTPre) - // Run pre-middleware - if err := mwRunner.RunUpdateMiddleware(readDetailPreMw, &rdDto, data); err != nil { - return err - } - if err := UpdateData(input, data, &event, tx); err != nil { return err } - pl.SetLogInfo(&event, nil, "complete") + // get detail for sync + soapiData, err := ReadDetailData(e.ReadDetailDto{ + Id: data.Id, + Includes: "Encounter,Employee"}, &event) + if err != nil { + return err + } - mwRunner.setMwType(pu.MWTPost) - // Run post-middleware - if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err = mwRunner.ExecuteIfSyncOn(func() error { + return mwRunner.RunUpdateMiddleware(updatePreMw, soapiData) + }); err != nil { return err } return nil }) - if err != nil { + if err = runLogMiddleware(err, input, erc.CCUpdate, mwRunner); err != nil { return nil, err } + pl.SetLogInfo(&event, nil, "complete") + return &d.Data{ Meta: d.IS{ "source": source, @@ -252,6 +226,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "delete") + mwRunner := newMiddlewareRunner(&event, input.Sync) err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") @@ -259,30 +234,27 @@ func Delete(input e.DeleteDto) (*d.Data, error) { return err } - mwRunner := newMiddlewareRunner(&event, tx) - mwRunner.setMwType(pu.MWTPre) - // Run pre-middleware - if err := mwRunner.RunDeleteMiddleware(readDetailPreMw, &rdDto, data); err != nil { - return err - } - if err := DeleteData(data, &event, tx); err != nil { return err } - mwRunner.setMwType(pu.MWTPost) - // Run post-middleware - if err := mwRunner.RunDeleteMiddleware(readDetailPostMw, &rdDto, data); err != nil { + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err = mwRunner.ExecuteIfSyncOn(func() error { + return mwRunner.RunDeleteMiddleware(deletePreMw, &input) + }); err != nil { return err } return nil }) - if err != nil { + if err = runLogMiddleware(err, input, erc.CCDelete, mwRunner); err != nil { return nil, err } + pl.SetLogInfo(&event, nil, "complete") + return &d.Data{ Meta: d.IS{ "source": source, @@ -293,3 +265,39 @@ func Delete(input e.DeleteDto) (*d.Data, error) { }, nil } + +func runLogMiddleware(err error, input any, method erc.CrudCode, mwRunner *middlewareRunner) error { + var errMsg string + inputLog := esync.SimxLogDto{ + Payload: input, + Method: method, + } + + if err != nil { + // Run log-middleware + errMsg = err.Error() + inputLog.ErrMessage = &errMsg + inputLog.IsSuccess = false + + // create log failed + if errMiddleware := mwRunner.ExecuteIfSyncOn(func() error { + return mwRunner.RunCreateLogMiddleware(createSimxLogMw, &inputLog) + }); errMiddleware != nil { + return errMiddleware + } + + return err + } + + // create log success + inputLog.IsSuccess = true + err = mwRunner.ExecuteIfSyncOn(func() error { + return mwRunner.RunCreateLogMiddleware(createSimxLogMw, &inputLog) + }) + + if err != nil { + return err + } + + return nil +} diff --git a/internal/use-case/main-use-case/soapi/helper.go b/internal/use-case/main-use-case/soapi/helper.go index ae396270..c42b95d0 100644 --- a/internal/use-case/main-use-case/soapi/helper.go +++ b/internal/use-case/main-use-case/soapi/helper.go @@ -18,7 +18,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Soapi) { } data.Encounter_Id = inputSrc.Encounter_Id - data.Employee_Id = inputSrc.Employee_Id + data.Employee_Id = inputSrc.AuthInfo.Employee_Id data.Time = inputSrc.Time data.TypeCode = inputSrc.TypeCode data.Value = inputSrc.Value diff --git a/internal/use-case/main-use-case/soapi/lib.go b/internal/use-case/main-use-case/soapi/lib.go index 57bb5d23..85e94800 100644 --- a/internal/use-case/main-use-case/soapi/lib.go +++ b/internal/use-case/main-use-case/soapi/lib.go @@ -81,7 +81,9 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e tx = dg.I } - if err := tx.First(&data, input.Id).Error; err != nil { + if err := tx. + Scopes(gh.Preload(input.Includes)). + First(&data, input.Id).Error; err != nil { if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { return nil, processedErr } diff --git a/internal/use-case/main-use-case/soapi/middleware-runner.go b/internal/use-case/main-use-case/soapi/middleware-runner.go index a840a33a..ffc49745 100644 --- a/internal/use-case/main-use-case/soapi/middleware-runner.go +++ b/internal/use-case/main-use-case/soapi/middleware-runner.go @@ -2,6 +2,8 @@ package soapi import ( e "simrs-vx/internal/domain/main-entities/soapi" + esync "simrs-vx/internal/domain/sync-entities/log" + sync "simrs-vx/internal/infra/sync-cfg" pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" @@ -12,24 +14,45 @@ type middlewareRunner struct { Event *pl.Event Tx *gorm.DB MwType pu.MWType + SyncOn bool } // NewMiddlewareExecutor creates a new middleware executor -func newMiddlewareRunner(event *pl.Event, tx *gorm.DB) *middlewareRunner { +func newMiddlewareRunner(event *pl.Event, syncFromOldSource bool) *middlewareRunner { + activateSync := sync.O.Enable + if syncFromOldSource { + activateSync = false + } + return &middlewareRunner{ - Event: event, - Tx: tx, + Event: event, + SyncOn: activateSync, } } // ExecuteCreateMiddleware executes create middleware -func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e.CreateDto, data *e.Soapi) error { +func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e.Soapi) error { for _, middleware := range middlewares { - logData := pu.GetLogData(input, data) + logData := pu.GetLogData(input, nil) pl.SetLogInfo(me.Event, logData, "started", middleware.Name) - if err := middleware.Func(input, data, me.Tx); err != nil { + 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 +} + +func (me *middlewareRunner) RunCreateLogMiddleware(middlewares []createLogMw, input *esync.SimxLogDto) error { + 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) } @@ -68,13 +91,13 @@ func (me *middlewareRunner) RunReadDetailMiddleware(middlewares []readDetailMw, return nil } -func (me *middlewareRunner) RunUpdateMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.Soapi) error { +func (me *middlewareRunner) RunUpdateMiddleware(middlewares []updateMw, input *e.Soapi) error { for _, middleware := range middlewares { - logData := pu.GetLogData(input, data) + logData := pu.GetLogData(input, nil) pl.SetLogInfo(me.Event, logData, "started", middleware.Name) - if err := middleware.Func(input, data, me.Tx); err != nil { + if err := middleware.Func(input); err != nil { return pu.HandleMiddlewareError(me.Event, string(me.MwType), middleware.Name, logData, err) } @@ -83,13 +106,13 @@ func (me *middlewareRunner) RunUpdateMiddleware(middlewares []readDetailMw, inpu return nil } -func (me *middlewareRunner) RunDeleteMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.Soapi) error { +func (me *middlewareRunner) RunDeleteMiddleware(middlewares []deleteMw, input *e.DeleteDto) error { for _, middleware := range middlewares { - logData := pu.GetLogData(input, data) + logData := pu.GetLogData(input, nil) pl.SetLogInfo(me.Event, logData, "started", middleware.Name) - if err := middleware.Func(input, data, me.Tx); err != nil { + if err := middleware.Func(input); err != nil { return pu.HandleMiddlewareError(me.Event, string(me.MwType), middleware.Name, logData, err) } @@ -101,3 +124,10 @@ func (me *middlewareRunner) RunDeleteMiddleware(middlewares []readDetailMw, inpu func (me *middlewareRunner) setMwType(mwType pu.MWType) { me.MwType = mwType } + +func (me *middlewareRunner) ExecuteIfSyncOn(fn func() error) error { + if !me.SyncOn { + return nil + } + return fn() +} diff --git a/internal/use-case/main-use-case/soapi/middleware.go b/internal/use-case/main-use-case/soapi/middleware.go index f2fecda5..049b0415 100644 --- a/internal/use-case/main-use-case/soapi/middleware.go +++ b/internal/use-case/main-use-case/soapi/middleware.go @@ -1,9 +1,17 @@ package soapi -// example of middleware -// func init() { -// createPreMw = append(createPreMw, -// CreateMw{Name: "modif-input", Func: pm.ModifInput}, -// CreateMw{Name: "check-data", Func: pm.CheckData}, -// ) -// } +import plugin "simrs-vx/internal/use-case/simgos-sync-plugin/new/soapi" + +func init() { + createPreMw = append(createPreMw, + createMw{Name: "sync-update-soapi", Func: plugin.Create}) + + createSimxLogMw = append(createSimxLogMw, + createLogMw{Name: "create-sync-log", Func: plugin.CreateLog}) + + updatePreMw = append(updatePreMw, + updateMw{Name: "sync-update-soapi", Func: plugin.Update}) + + deletePreMw = append(deletePreMw, + deleteMw{Name: "sync-delete-soapi", Func: plugin.Delete}) +} diff --git a/internal/use-case/main-use-case/soapi/tycovar.go b/internal/use-case/main-use-case/soapi/tycovar.go index 956193a4..aece45a5 100644 --- a/internal/use-case/main-use-case/soapi/tycovar.go +++ b/internal/use-case/main-use-case/soapi/tycovar.go @@ -12,11 +12,27 @@ import ( "gorm.io/gorm" e "simrs-vx/internal/domain/main-entities/soapi" + elog "simrs-vx/internal/domain/sync-entities/log" ) type createMw struct { Name string - Func func(input *e.CreateDto, data *e.Soapi, tx *gorm.DB) error + Func func(input *e.Soapi) error +} + +type createLogMw struct { + Name string + Func func(input *elog.SimxLogDto) error +} + +type updateMw struct { + Name string + Func func(input *e.Soapi) error +} + +type deleteMw struct { + Name string + Func func(input *e.DeleteDto) error } type readListMw struct { @@ -29,8 +45,8 @@ type readDetailMw struct { Func func(input *e.ReadDetailDto, data *e.Soapi, tx *gorm.DB) error } -type UpdateMw = readDetailMw -type DeleteMw = readDetailMw +type UpdateMw = updateMw +type DeleteMw = deleteMw var createPreMw []createMw // preprocess middleware var createPostMw []createMw // postprocess middleware @@ -38,7 +54,8 @@ var readListPreMw []readListMw // .. var readListPostMw []readListMw // .. var readDetailPreMw []readDetailMw var readDetailPostMw []readDetailMw -var updatePreMw []readDetailMw +var updatePreMw []updateMw var updatePostMw []readDetailMw -var deletePreMw []readDetailMw +var deletePreMw []deleteMw var deletePostMw []readDetailMw +var createSimxLogMw []createLogMw diff --git a/internal/use-case/simgos-sync-plugin/new/soapi/plugin.go b/internal/use-case/simgos-sync-plugin/new/soapi/plugin.go new file mode 100644 index 00000000..469384b7 --- /dev/null +++ b/internal/use-case/simgos-sync-plugin/new/soapi/plugin.go @@ -0,0 +1,36 @@ +package soapi + +import ( + "fmt" + sync "simrs-vx/internal/infra/sync-cfg" + helper "simrs-vx/internal/use-case/simgos-sync-plugin/new" + + e "simrs-vx/internal/domain/main-entities/soapi" + elog "simrs-vx/internal/domain/sync-entities/log" +) + +func Create(input *e.Soapi) error { + return helper.DoJsonRequest(input, "POST", getPrefixEndpoint()) +} + +func CreateLog(input *elog.SimxLogDto) error { + prefixEndpoint := getPrefixEndpoint() + endpoint := prefixEndpoint + "/log" + return helper.DoJsonRequest(input, "POST", endpoint) +} + +func Update(input *e.Soapi) error { + prefixEndpoint := getPrefixEndpoint() + endpoint := fmt.Sprintf("%s/%v", prefixEndpoint, input.Id) + return helper.DoJsonRequest(input, "PATCH", endpoint) +} + +func Delete(input *e.DeleteDto) error { + prefixEndpoint := getPrefixEndpoint() + endpoint := fmt.Sprintf("%s/%v", prefixEndpoint, input.Id) + return helper.DoJsonRequest(input, "DELETE", endpoint) +} + +func getPrefixEndpoint() string { + return fmt.Sprintf("%s%s/v1/encounter", sync.O.TargetHost, sync.O.Prefix) +} diff --git a/internal/use-case/simgos-sync-use-case/new/encounter/case.go b/internal/use-case/simgos-sync-use-case/new/encounter/case.go index 59e7e345..55c0a912 100644 --- a/internal/use-case/simgos-sync-use-case/new/encounter/case.go +++ b/internal/use-case/simgos-sync-use-case/new/encounter/case.go @@ -1,6 +1,7 @@ package encounter import ( + erc "simrs-vx/internal/domain/references/common" pl "simrs-vx/pkg/logger" d "github.com/karincake/dodol" @@ -9,7 +10,6 @@ import ( db "simrs-vx/pkg/dualtrx-helper" e "simrs-vx/internal/domain/main-entities/encounter" - etp "simrs-vx/internal/domain/simgos-entities/t-pendaftaran" synce "simrs-vx/internal/domain/sync-entities/encounter" syncir "simrs-vx/internal/domain/sync-entities/internal-reference" elog "simrs-vx/internal/domain/sync-entities/log" @@ -21,9 +21,7 @@ const source = "encounter" func Create(input e.Encounter) (*d.Data, error) { var ( - sgData *etp.TPendaftaran syncLink *synce.EncounterLink - err error ) event := pl.Event{ @@ -34,21 +32,27 @@ func Create(input e.Encounter) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") - err = db.WithDualTx(func(tx *db.Dualtx) error { - // STEP 1: Insert to simgos - sgData, err = CreateTPendaftaranData(input, &event, tx.Simgos) + err := db.WithDualTx(func(tx *db.Dualtx) error { + // STEP 1: Insert TPendaftaran + tPendaftaran, err := CreateTPendaftaranData(input, &event, tx.Simgos) if err != nil { return err } - // STEP 2: Insert to Link - syncLink, err = CreateLinkData(input.Id, sgData.Idxdaftar, &event, tx.Sync) + // STEP 2: Insert TRekammedik + err = CreateTRekammedik(tPendaftaran, &event, tx.Simgos) if err != nil { return err } // STEP 3: Update MPasien - err = updatePatientCaraBayar(*sgData, &event, tx.Simgos) + err = updatePatientCaraBayar(*tPendaftaran, &event, tx.Simgos) + if err != nil { + return err + } + + // STEP 4: Insert to Link + syncLink, err = CreateLinkData(input.Id, tPendaftaran.Idxdaftar, &event, tx.Sync) if err != nil { return err } @@ -281,8 +285,6 @@ func CheckOut(input e.Encounter) (*d.Data, error) { return err } - // TODO: Update TPemeriksaanHistory end_konsul if internal reference exist - return nil }) @@ -299,12 +301,12 @@ func CheckOut(input e.Encounter) (*d.Data, error) { func UpdateStatus(input e.Encounter) (*d.Data, error) { event := pl.Event{ - Feature: "Cancel", + Feature: "Update Status", Source: source, } // Start log - pl.SetLogInfo(&event, input, "started", "cancel") + pl.SetLogInfo(&event, input, "started", "update-status") // STEP 1: Get Link syncLink, err := ReadDetailLinkData(input.Id, &event) @@ -320,11 +322,18 @@ func UpdateStatus(input e.Encounter) (*d.Data, error) { tx := db.NewTx() err = tx.Simgos.Transaction(func(tx *gorm.DB) error { - // Step 2: Update Simgos + // Step 2: Update TPendaftaran if err = UpdateTPendaftaranData(input, simgos, "update-status", &event, tx); err != nil { return err } + // Step 3: Update TDiagnosadanterapi + if input.Status_Code == erc.DSCCancel { + if err = updateCancelTDiagnosaTherapy(simgos.Idxdaftar, input, &event, tx); err != nil { + return err + } + } + return nil }) diff --git a/internal/use-case/simgos-sync-use-case/new/encounter/helper.go b/internal/use-case/simgos-sync-use-case/new/encounter/helper.go index 3a190d56..8baa5a6f 100644 --- a/internal/use-case/simgos-sync-use-case/new/encounter/helper.go +++ b/internal/use-case/simgos-sync-use-case/new/encounter/helper.go @@ -6,25 +6,29 @@ package encounter import ( "encoding/json" + pl "simrs-vx/pkg/logger" + "strconv" + + dg "github.com/karincake/apem/db-gorm-pg" + "gorm.io/gorm" + "gorm.io/gorm/clause" + erc "simrs-vx/internal/domain/references/common" ere "simrs-vx/internal/domain/references/encounter" erp "simrs-vx/internal/domain/references/person" - pl "simrs-vx/pkg/logger" - "strconv" e "simrs-vx/internal/domain/main-entities/encounter" epa "simrs-vx/internal/domain/main-entities/person-address" epc "simrs-vx/internal/domain/main-entities/person-contact" epr "simrs-vx/internal/domain/main-entities/person-relative" + ep "simrs-vx/internal/domain/simgos-entities/m-pasien" - etph "simrs-vx/internal/domain/simgos-entities/t-pemeriksaan-hist" + etdt "simrs-vx/internal/domain/simgos-entities/t-diagnosadanterapi" etp "simrs-vx/internal/domain/simgos-entities/t-pendaftaran" + etrm "simrs-vx/internal/domain/simgos-entities/t-rekammedik" + esync "simrs-vx/internal/domain/sync-entities/encounter" esyncLog "simrs-vx/internal/domain/sync-entities/log" - - dg "github.com/karincake/apem/db-gorm-pg" - "gorm.io/gorm" - "gorm.io/gorm/clause" ) func setDataCreateTPendaftaran(input *e.Encounter) (data etp.TPendaftaran, err error) { @@ -188,34 +192,6 @@ func setDataCheckOut(input e.Encounter, data *etp.TPendaftaran) { return } -func setDataRequestSwitchUnit(input e.Encounter, data *etp.TPendaftaran) (hist []etph.TPemeriksaanHist) { - if enc := input.InternalReferences; enc != nil { - for i, ref := range *enc { - hist = append(hist, etph.TPemeriksaanHist{ - Idxdaftar: &data.Idxdaftar, - Kdpoly: stringtouint(*ref.Unit_Code), - DokterPengonsul: stringtouint(*ref.SrcDoctor_Code), - DokterPenerima: stringtouint(*ref.Doctor_Code), - StartKonsul: &now, - }) - - // set user konsul - if n := input.Responsible_Nurse; n != nil { - if emp := n.Employee; emp != nil { - if u := emp.User; u != nil { - hist[i].UserKonsul = &u.Name - } - } - } - - // setaktif - aktif := uint16(1) - hist[i].StAktif = &aktif - } - } - return -} - func setKdrujuk(input *ere.RefTypeCode, data *etp.TPendaftaran) { switch *input { case ere.RTCGov: @@ -363,12 +339,6 @@ func generateNoKunjung() (int, error) { return lastNumber + 1, nil } -func stringtouint(v string) *uint { - u, _ := strconv.Atoi(v) - point := uint(u) - return &point -} - func updatePatientCaraBayar(input etp.TPendaftaran, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, nil, "started", "DBUpdate") @@ -415,3 +385,52 @@ func mapAddress(addresses *[]epa.PersonAddress, data *etp.TPendaftaran) { a := (*addresses)[0] data.PenanggungjawabAlamat = a.Address } + +func setDataTRekammedik(input *etp.TPendaftaran) (data etrm.TRekammedik) { + data.TglKirim = input.Tglreg + data.Idxdaftar = input.Idxdaftar + data.Kdpoly = input.Kdpoly + data.Pengirim = input.Nip + data.JamKirimRm = input.Tglreg + + return +} + +func updateCancelTDiagnosaTherapy(idxdaftar uint, enc e.Encounter, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, nil, "started", "DBUpdate") + + var ( + tx *gorm.DB + userBatal string + ) + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.IS["simrs"] + } + + if a := enc.Adm_Employee; a != nil { + if u := a.User; u != nil { + userBatal = u.Name + } + } + + if err := tx.Model(&etdt.TDiagnosaDanTerapi{}). + Where("idxdaftar = ?", idxdaftar). + Updates(map[string]interface{}{ + "status": "BATAL", + "user_batal": userBatal, + "tgl_batal": &now, + }).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "update-fail", + Detail: "Failed to update patient", + Raw: err, + } + return pl.SetLogError(event, idxdaftar) + } + + pl.SetLogInfo(event, idxdaftar, "complete") + return nil +} diff --git a/internal/use-case/simgos-sync-use-case/new/encounter/lib.go b/internal/use-case/simgos-sync-use-case/new/encounter/lib.go index 47d50802..35bf86ac 100644 --- a/internal/use-case/simgos-sync-use-case/new/encounter/lib.go +++ b/internal/use-case/simgos-sync-use-case/new/encounter/lib.go @@ -1,7 +1,6 @@ package encounter import ( - etph "simrs-vx/internal/domain/simgos-entities/t-pemeriksaan-hist" plh "simrs-vx/pkg/lib-helper" pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" @@ -138,25 +137,6 @@ func CreateLinkData(simxId, simgosId uint, event *pl.Event, dbx ...*gorm.DB) (*e return &data, nil } -func CreateBulkLinkData(simxId, simgosId uint, event *pl.Event, dbx ...*gorm.DB) (*esync.EncounterLink, error) { - pl.SetLogInfo(event, nil, "started", "DBCreate") - data := setDataSimxLink(simxId, simgosId) - - var tx *gorm.DB - if len(dbx) > 0 { - tx = dbx[0] - } else { - tx = dg.I - } - - if err := tx.Create(&data).Error; err != nil { - return nil, plh.HandleCreateError(data, event, err) - } - - pl.SetLogInfo(event, nil, "complete") - return &data, nil -} - func ReadDetailLinkData(simxId uint, event *pl.Event) (*esync.EncounterLink, error) { pl.SetLogInfo(event, simxId, "started", "DBReadDetail") data := esync.EncounterLink{} @@ -218,10 +198,9 @@ func CreateLogData(input esynclog.SimxLogDto, event *pl.Event, dbx ...*gorm.DB) return nil } -func CreateBulkTPemeriksaanHistData(input e.Encounter, data *etp.TPendaftaran, event *pl.Event, dbx ...*gorm.DB) (hist []etph.TPemeriksaanHist, err error) { +func CreateTRekammedik(input *etp.TPendaftaran, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, nil, "started", "DBCreate") - - hist = setDataRequestSwitchUnit(input, data) + data := setDataTRekammedik(input) var tx *gorm.DB if len(dbx) > 0 { @@ -230,32 +209,8 @@ func CreateBulkTPemeriksaanHistData(input e.Encounter, data *etp.TPendaftaran, e tx = dg.IS["simrs"] } - if err := tx.Create(&hist).Error; err != nil { - return nil, plh.HandleCreateError(input, event, err) - } - - pl.SetLogInfo(event, nil, "complete") - return hist, nil -} - -func UpdateTPemeriksaanHistData(input e.ApproveCancelUnitDto, data *etph.TPemeriksaanHist, event *pl.Event, dbx ...*gorm.DB) error { - pl.SetLogInfo(event, input, "started", "DBUpdateTPemeriksaanHist") - - var tx *gorm.DB - if len(dbx) > 0 { - tx = dbx[0] - } else { - tx = dg.IS["simrs"] - } - - if err := tx.Save(&data).Error; err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-update-fail", - Detail: "Database update failed", - Raw: err, - } - return pl.SetLogError(event, input) + if err := tx.Create(&data).Error; err != nil { + return plh.HandleCreateError(input, event, err) } pl.SetLogInfo(event, nil, "complete") diff --git a/internal/use-case/simgos-sync-use-case/new/soapi/case.go b/internal/use-case/simgos-sync-use-case/new/soapi/case.go new file mode 100644 index 00000000..d7e9bcc4 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/new/soapi/case.go @@ -0,0 +1,274 @@ +package soapi + +import ( + pl "simrs-vx/pkg/logger" + + d "github.com/karincake/dodol" + "gorm.io/gorm" + + db "simrs-vx/pkg/dualtrx-helper" + + e "simrs-vx/internal/domain/main-entities/soapi" + + elog "simrs-vx/internal/domain/sync-entities/log" + esync "simrs-vx/internal/domain/sync-entities/soapi" + + ue "simrs-vx/internal/use-case/simgos-sync-use-case/new/encounter" +) + +const source = "soapi" + +func Create(input e.Soapi) (*d.Data, error) { + var ( + syncLink *esync.SoapiLink + err error + ) + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + // get encounter Link + eLink, err := ue.ReadDetailLinkData(*input.Encounter_Id, &event) + if err != nil { + return nil, err + } + + // get Tpendaftaran + tPendaftaran, err := ue.ReadTPendaftaranDetailData(eLink.Simgos_Id, &event) + if err != nil { + return nil, err + } + + err = db.WithDualTx(func(tx *db.Dualtx) error { + // STEP 1: Insert to TDiagnosaDanTerapi + tDiagTherapy, err := CreateTDiagnosaDanTerapi(input, tPendaftaran, &event, tx.Simgos) + if err != nil { + return err + } + + // STEP 2: Insert to TICD + _, err = CreateTIcd(input, tPendaftaran, &event, tx.Simgos) + if err != nil { + return err + } + + // STEP 3: Insert to TICD-CM + _, err = CreateTIcdCm(input, tPendaftaran, &event, tx.Simgos) + if err != nil { + return err + } + + // STEP 4: Insert to Link + syncLink, err = CreateLinkData(input.Id, tDiagTherapy.Idxterapi, &event, tx.Sync) + if err != nil { + return err + } + + return nil + }) + + if err != nil { + if syncLink != nil { + go func() { _ = DeleteLinkData(syncLink, &event) }() + } + return nil, err + } + + pl.SetLogInfo(&event, nil, "complete") + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + }, nil +} + +func CreateSimxLog(input elog.SimxLogDto) (*d.Data, error) { + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + tx := db.NewTx() + err := tx.Sync.Transaction(func(tx *gorm.DB) error { + // Insert to Log + if err := CreateLogData(input, &event, tx); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + pl.SetLogInfo(&event, nil, "complete") + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + }, nil +} + +func Update(input e.Soapi) (*d.Data, error) { + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + // Get Soapi Link + sLink, err := ReadDetailLinkData(input.Id, &event) + if err != nil { + return nil, err + } + + // Get TDiagnosadanTerapi + tDiagTherapy, err := ReadDetailTDiagnosaDanTerapi(sLink.Simgos_Id, &event) + if err != nil { + return nil, err + } + + // Get Encounter Link + eLink, err := ue.ReadDetailLinkData(*input.Encounter_Id, &event) + if err != nil { + return nil, err + } + + // Get TPendaftaran + tPendaftaran, err := ue.ReadTPendaftaranDetailData(eLink.Simgos_Id, &event) + if err != nil { + return nil, err + } + + tx := db.NewTx() + err = tx.Simgos.Transaction(func(tx *gorm.DB) error { + // SET LOCAL + if err = tx.Exec(`SET LOCAL simx.sync_source = 'new'`).Error; err != nil { + return err + } + + // Step 1: Update TDiagnosaDanTerapi + if err = UpdateTDiagnosaDanTerapi(input, tDiagTherapy, &event, tx); err != nil { + return err + } + + // STEP 2: Delete TIcd + if err = HardDeleteTIcd(tDiagTherapy.Idxdaftar, &event, tx); err != nil { + return err + } + + // STEP 3: Delete TIcdCm + if err = HardDeleteTIcdCm(tDiagTherapy.Idxdaftar, &event, tx); err != nil { + return err + } + + // STEP 4: Insert TIcd + if _, err = CreateTIcd(input, tPendaftaran, &event, tx); err != nil { + return err + } + + // STEP 5: Insert TIcd-cm + if _, err = CreateTIcdCm(input, tPendaftaran, &event, tx); err != nil { + return err + } + + return nil + }) + + pl.SetLogInfo(&event, nil, "complete") + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + }, nil +} + +func Delete(input e.DeleteDto) (*d.Data, error) { + var isLinkDeleted bool + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + // Get Soapi Link + syncLink, err := ReadDetailLinkData(input.Id, &event) + if err != nil { + return nil, err + } + + // Get TDiagnosa&Terapi + tDiagTh, err := ReadDetailTDiagnosaDanTerapi(syncLink.Simgos_Id, &event) + if err != nil { + return nil, err + } + + err = db.WithDualTx(func(tx *db.Dualtx) error { + // STEP 1: Delete TDiagnosa&Terapi Simgos + if err = HardDeleteTDiagnosaDanTerapi(tDiagTh, &event, tx.Simgos); err != nil { + return err + } + + // STEP 2: Delete TIcd + if err = HardDeleteTIcd(tDiagTh.Idxdaftar, &event, tx.Simgos); err != nil { + return err + } + + // STEP 3: Delete TIcdCm + if err = HardDeleteTIcdCm(tDiagTh.Idxdaftar, &event, tx.Simgos); err != nil { + return err + } + + // STEP 4: Delete Link + err = DeleteLinkData(syncLink, &event, tx.Sync) + if err != nil { + return err + } + + isLinkDeleted = true + return nil + }) + + if err != nil { + if isLinkDeleted { + go func() { + _, _ = CreateLinkData(input.Id, tDiagTh.Idxterapi, &event) + }() + } + return nil, err + } + + pl.SetLogInfo(&event, nil, "complete") + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + }, nil + +} diff --git a/internal/use-case/simgos-sync-use-case/new/soapi/helper.go b/internal/use-case/simgos-sync-use-case/new/soapi/helper.go new file mode 100644 index 00000000..65213761 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/new/soapi/helper.go @@ -0,0 +1,199 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package soapi + +import ( + "encoding/json" + "fmt" + ere "simrs-vx/internal/domain/references/encounter" + "strconv" + "time" + + ercl "simrs-vx/internal/domain/references/clinical" + erc "simrs-vx/internal/domain/references/common" + + es "simrs-vx/internal/domain/main-entities/soapi" + + etdt "simrs-vx/internal/domain/simgos-entities/t-diagnosadanterapi" + eicd "simrs-vx/internal/domain/simgos-entities/t-icd" + eicdcm "simrs-vx/internal/domain/simgos-entities/t-icd-cm" + etp "simrs-vx/internal/domain/simgos-entities/t-pendaftaran" + + esyncLog "simrs-vx/internal/domain/sync-entities/log" + esync "simrs-vx/internal/domain/sync-entities/soapi" +) + +func setDataCreateTDiagnosaDanTerapi(input es.Soapi, enc *etp.TPendaftaran) (data etdt.TDiagnosaDanTerapi) { + switch input.TypeCode { + case ercl.STCEEarlyMedic: + data.Idxdaftar = enc.Idxdaftar + data.Nomr = enc.Nomr + data.Kdpoly = enc.Kdpoly + data.Kddokter = enc.Kddokter + + if e := input.Encounter; e != nil { + data.Tanggal = e.VisitDate + if e.Class_Code == ere.ECAmbulatory { + data.Rajal = 1 + } + + } + + if e := input.Employee; e != nil { + if u := e.User; u != nil { + data.Nip = u.Name + } + } + + setEarlyMedicTDT(input, &data) + return + } + + return +} + +func setEarlyMedicTDT(input es.Soapi, data *etdt.TDiagnosaDanTerapi) { + value := ercl.EarlyMedicValue{} + _ = json.Unmarshal([]byte(*input.Value), &value) + + data.TekananDarah = fmt.Sprintf("%v/%v", value.SystolicBloodPressure, value.DiastolicBloodPressure) + data.GolonganDarah = value.BloodType + if value.BloodType == "" { + data.GolonganDarah = "X" + } + + data.TinggiBadan = float64(value.Height) + data.BeratBadan = float64(value.Weight) + data.Diagnosa = value.EarlyMedicDiagnose + data.Terapi = value.Therapy + data.Anamnesa = value.PrimaryComplain + + // TODO : status, tindakan_mdeis (?) + data.KunjunganBl = uint(value.EncounterStatus) + data.KasusBl = uint(value.CaseStatus) + + data.PemeriksaanFisik = value.PhysicalExamination + data.RiwayatPasien = value.CurrentDiseaseHistory + + if value.Vaccinated { + data.SudahVaksin = "YA" + } else { + data.SudahVaksin = "TIDAK" + } + + data.DenyutJantung = strconv.Itoa(value.Pulse) + data.Pernapasan = strconv.Itoa(value.RespiratoryRate) + data.Suhu = strconv.Itoa(value.Temperature) + data.Sp02 = strconv.Itoa(value.SpO2) + + if o := value.ExpectedOutcome; len(o) > 0 { + expectedOutput := []string{} + for _, v := range o { + expectedOutput = append(expectedOutput, v.Name) + } + jsonData, _ := json.MarshalIndent(value.ExpectedOutcome, "", " ") + data.TargetCapaian = string(jsonData) + } + return +} + +func setDataIcd(input es.Soapi, enc *etp.TPendaftaran) (data []eicd.TIcd) { + value := ercl.EarlyMedicValue{} + _ = json.Unmarshal([]byte(*input.Value), &value) + + var ( + visitDate time.Time + ambulatory uint16 + ) + + if e := input.Encounter; e != nil { + visitDate = e.VisitDate + if e.Class_Code == ere.ECAmbulatory { + ambulatory = 1 + } + + } + + if d := value.DiagnoseSrc; len(d) > 0 { + for _, v := range d { + data = append(data, eicd.TIcd{ + Nomr: enc.Nomr, + Idxdaftar: enc.Idxdaftar, + Kddokter: enc.Kddokter, + Icd: v.Code, + StatusRajal: ambulatory, + Tanggal: visitDate, + }) + } + } + + return +} + +func setDataIcdCm(input es.Soapi, enc *etp.TPendaftaran) (data []eicdcm.TIcdCm) { + value := ercl.EarlyMedicValue{} + _ = json.Unmarshal([]byte(*input.Value), &value) + + var ( + visitDate time.Time + ambulatory uint16 + ) + + if e := input.Encounter; e != nil { + visitDate = e.VisitDate + if e.Class_Code == ere.ECAmbulatory { + ambulatory = 1 + } + + } + + if p := value.ProcedureSrc; len(p) > 0 { + for _, v := range p { + data = append(data, eicdcm.TIcdCm{ + Nomr: enc.Nomr, + Idxdaftar: enc.Idxdaftar, + Kddokter: enc.Kddokter, + Icd: v.Code, + StatusRajal: ambulatory, + Tanggal: visitDate, + }) + } + } + + return +} + +func setDataSimxLog(input *esyncLog.SimxLogDto) (data esync.SoapiSimxLog) { + // encode to JSON + jsonData, _ := json.MarshalIndent(input.Payload, "", " ") + jsonString := string(jsonData) + + var status erc.ProcessStatusCode + if input.IsSuccess { + status = erc.PSCSuccess + } else { + status = erc.PSCFailed + if input.ErrMessage != nil { + data.ErrMessage = input.ErrMessage + } + } + + data.Value = &jsonString + data.Date = &now + data.Status = status + + return +} + +func setDataSimxLink(simxId, simgosId uint) (data esync.SoapiLink) { + data.Simx_Id = simxId + data.Simgos_Id = simgosId + return +} + +func stringtouint(v string) uint { + u, _ := strconv.Atoi(v) + return uint(u) +} diff --git a/internal/use-case/simgos-sync-use-case/new/soapi/lib.go b/internal/use-case/simgos-sync-use-case/new/soapi/lib.go new file mode 100644 index 00000000..af27a791 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/new/soapi/lib.go @@ -0,0 +1,334 @@ +package soapi + +import ( + "errors" + plh "simrs-vx/pkg/lib-helper" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + "time" + + dg "github.com/karincake/apem/db-gorm-pg" + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/soapi" + + etdt "simrs-vx/internal/domain/simgos-entities/t-diagnosadanterapi" + eicd "simrs-vx/internal/domain/simgos-entities/t-icd" + eicdcm "simrs-vx/internal/domain/simgos-entities/t-icd-cm" + ep "simrs-vx/internal/domain/simgos-entities/t-pendaftaran" + + esynclog "simrs-vx/internal/domain/sync-entities/log" + esync "simrs-vx/internal/domain/sync-entities/soapi" +) + +var now = time.Now() + +func CreateTDiagnosaDanTerapi(input e.Soapi, tdaftar *ep.TPendaftaran, event *pl.Event, dbx ...*gorm.DB) (*etdt.TDiagnosaDanTerapi, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + data := setDataCreateTDiagnosaDanTerapi(input, tdaftar) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.IS["simrs"] + } + + if err := tx.Create(&data).Error; err != nil { + return nil, plh.HandleCreateError(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadDetailTDiagnosaDanTerapi(simgosId uint, event *pl.Event) (*etdt.TDiagnosaDanTerapi, error) { + pl.SetLogInfo(event, simgosId, "started", "DBReadDetail") + data := etdt.TDiagnosaDanTerapi{} + + var tx = dg.IS["simrs"] + + if err := tx. + Where("\"idxterapi\" = ?", simgosId). + First(&data).Error; err != nil { + if processedErr := pu.HandleReadError(err, event, source, simgosId, data); processedErr != nil { + return nil, processedErr + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateTDiagnosaDanTerapi(input e.Soapi, data *etdt.TDiagnosaDanTerapi, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, input, "started", "DBUpdate") + + setEarlyMedicTDT(input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.IS["simrs"] + } + + if err := tx.Save(&data).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-update-fail", + Detail: "Database update failed", + Raw: err, + } + return pl.SetLogError(event, input) + } + + pl.SetLogInfo(event, nil, "complete") + return nil +} + +func HardDeleteTDiagnosaDanTerapi(data *etdt.TDiagnosaDanTerapi, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBDelete") + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.IS["simrs"] + } + + if err := tx. + Delete(&data).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-delete-fail", + Detail: "Database delete failed", + Raw: err, + } + return pl.SetLogError(event, data) + } + + pl.SetLogInfo(event, nil, "complete") + return nil +} + +func CreateTIcd(input e.Soapi, tdaftar *ep.TPendaftaran, event *pl.Event, dbx ...*gorm.DB) (*[]eicd.TIcd, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + data := setDataIcd(input, tdaftar) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.IS["simrs"] + } + + if err := tx.Create(&data).Error; err != nil { + return nil, plh.HandleCreateError(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListTIcd(idxdaftar string, event *pl.Event, dbx ...*gorm.DB) ([]eicd.TIcd, error) { + pl.SetLogInfo(event, idxdaftar, "started", "DBReadList") + data := []eicd.TIcd{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&eicd.TIcd{}). + Where("idxdaftar = ?", idxdaftar) + + if err := tx.Find(&data).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } + return nil, plh.HandleListError(idxdaftar, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return data, nil +} + +func HardDeleteTIcd(idxdaftar uint, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, idxdaftar, "started", "DBDelete") + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.IS["simrs"] + } + + if err := tx. + Where("idxdaftar = ?", idxdaftar). + Delete(&eicd.TIcd{}).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-delete-fail", + Detail: "Database delete failed", + Raw: err, + } + return pl.SetLogError(event, idxdaftar) + } + + pl.SetLogInfo(event, nil, "complete") + return nil +} + +func CreateTIcdCm(input e.Soapi, tdaftar *ep.TPendaftaran, event *pl.Event, dbx ...*gorm.DB) (*[]eicdcm.TIcdCm, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + data := setDataIcdCm(input, tdaftar) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.IS["simrs"] + } + + if err := tx.Create(&data).Error; err != nil { + return nil, plh.HandleCreateError(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListTIcdCm(idxdaftar string, event *pl.Event, dbx ...*gorm.DB) ([]eicdcm.TIcdCm, error) { + pl.SetLogInfo(event, idxdaftar, "started", "DBReadList") + data := []eicdcm.TIcdCm{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&eicdcm.TIcdCm{}). + Where("idxdaftar = ?", idxdaftar) + + if err := tx.Find(&data).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } + return nil, plh.HandleListError(idxdaftar, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return data, nil +} + +func HardDeleteTIcdCm(idxdaftar uint, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, idxdaftar, "started", "DBDelete") + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.IS["simrs"] + } + + if err := tx. + Where("idxdaftar = ?", idxdaftar). + Delete(&eicdcm.TIcdCm{}).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-delete-fail", + Detail: "Database delete failed", + Raw: err, + } + return pl.SetLogError(event, idxdaftar) + } + + pl.SetLogInfo(event, nil, "complete") + return nil +} + +func CreateLinkData(simxId, simgosId uint, event *pl.Event, dbx ...*gorm.DB) (*esync.SoapiLink, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + data := setDataSimxLink(simxId, simgosId) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if err := tx.Create(&data).Error; err != nil { + return nil, plh.HandleCreateError(data, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadDetailLinkData(simxId uint, event *pl.Event) (*esync.SoapiLink, error) { + pl.SetLogInfo(event, simxId, "started", "DBReadDetail") + data := esync.SoapiLink{} + + var tx = dg.I + + if err := tx. + Where("\"Simx_Id\" = ?", simxId). + First(&data).Error; err != nil { + if processedErr := pu.HandleReadError(err, event, source, simxId, data); processedErr != nil { + return nil, processedErr + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func DeleteLinkData(data *esync.SoapiLink, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBDelete") + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if err := tx.Delete(&data).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-delete-fail", + Detail: "Database delete failed", + Raw: err, + } + return pl.SetLogError(event, data) + } + + pl.SetLogInfo(event, nil, "complete") + return nil +} + +func CreateLogData(input esynclog.SimxLogDto, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, nil, "started", "DBCreate") + data := setDataSimxLog(&input) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if err := tx.Create(&data).Error; err != nil { + return plh.HandleCreateError(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return nil +} diff --git a/internal/use-case/simgos-sync-use-case/new/soapi/middleware-runner.go b/internal/use-case/simgos-sync-use-case/new/soapi/middleware-runner.go new file mode 100644 index 00000000..74d8b1a8 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/new/soapi/middleware-runner.go @@ -0,0 +1,104 @@ +package soapi + +import ( + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/soapi" +) + +type middlewareRunner struct { + Event *pl.Event + Tx *gorm.DB + MwType pu.MWType +} + +// NewMiddlewareExecutor creates a new middleware executor +func newMiddlewareRunner(event *pl.Event, tx *gorm.DB) *middlewareRunner { + return &middlewareRunner{ + Event: event, + Tx: tx, + } +} + +// ExecuteCreateMiddleware executes create middleware +func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e.CreateDto, data *e.Soapi) error { + for _, middleware := range middlewares { + logData := pu.GetLogData(input, data) + + pl.SetLogInfo(me.Event, logData, "started", middleware.Name) + + if err := middleware.Func(input, data, me.Tx); err != nil { + return pu.HandleMiddlewareError(me.Event, string(me.MwType), middleware.Name, logData, err) + } + + pl.SetLogInfo(me.Event, nil, "complete") + } + return nil +} + +func (me *middlewareRunner) RunReadListMiddleware(middlewares []readListMw, input *e.ReadListDto, data *e.Soapi) error { + for _, middleware := range middlewares { + logData := pu.GetLogData(input, data) + + pl.SetLogInfo(me.Event, logData, "started", middleware.Name) + + if err := middleware.Func(input, data, me.Tx); err != nil { + return pu.HandleMiddlewareError(me.Event, string(me.MwType), middleware.Name, logData, err) + } + + pl.SetLogInfo(me.Event, nil, "complete") + } + return nil +} + +func (me *middlewareRunner) RunReadDetailMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.Soapi) error { + for _, middleware := range middlewares { + logData := pu.GetLogData(input, data) + + pl.SetLogInfo(me.Event, logData, "started", middleware.Name) + + if err := middleware.Func(input, data, me.Tx); err != nil { + return pu.HandleMiddlewareError(me.Event, string(me.MwType), middleware.Name, logData, err) + } + + pl.SetLogInfo(me.Event, nil, "complete") + } + return nil +} + +func (me *middlewareRunner) RunUpdateMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.Soapi) error { + for _, middleware := range middlewares { + logData := pu.GetLogData(input, data) + + pl.SetLogInfo(me.Event, logData, "started", middleware.Name) + + if err := middleware.Func(input, data, me.Tx); err != nil { + return pu.HandleMiddlewareError(me.Event, string(me.MwType), middleware.Name, logData, err) + } + + pl.SetLogInfo(me.Event, nil, "complete") + } + return nil +} + +func (me *middlewareRunner) RunDeleteMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.Soapi) error { + for _, middleware := range middlewares { + logData := pu.GetLogData(input, data) + + pl.SetLogInfo(me.Event, logData, "started", middleware.Name) + + if err := middleware.Func(input, data, me.Tx); err != nil { + return pu.HandleMiddlewareError(me.Event, string(me.MwType), middleware.Name, logData, err) + } + + pl.SetLogInfo(me.Event, nil, "complete") + } + return nil +} + +func (me *middlewareRunner) setMwType(mwType pu.MWType) { + me.MwType = mwType +} diff --git a/internal/use-case/simgos-sync-use-case/new/soapi/middleware.go b/internal/use-case/simgos-sync-use-case/new/soapi/middleware.go new file mode 100644 index 00000000..1fa07628 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/new/soapi/middleware.go @@ -0,0 +1 @@ +package soapi diff --git a/internal/use-case/simgos-sync-use-case/new/soapi/tycovar.go b/internal/use-case/simgos-sync-use-case/new/soapi/tycovar.go new file mode 100644 index 00000000..956193a4 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/new/soapi/tycovar.go @@ -0,0 +1,44 @@ +/* +DESCRIPTION: +A sample, part of the package that contains type, constants, and/or variables. + +In this sample it also provides type and variable regarding the needs of the +middleware to separate from main use-case which has the basic CRUD +functionality. The purpose of this is to make the code more maintainable. +*/ +package soapi + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/soapi" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.Soapi, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.Soapi, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.Soapi, tx *gorm.DB) error +} + +type UpdateMw = readDetailMw +type DeleteMw = readDetailMw + +var createPreMw []createMw // preprocess middleware +var createPostMw []createMw // postprocess middleware +var readListPreMw []readListMw // .. +var readListPostMw []readListMw // .. +var readDetailPreMw []readDetailMw +var readDetailPostMw []readDetailMw +var updatePreMw []readDetailMw +var updatePostMw []readDetailMw +var deletePreMw []readDetailMw +var deletePostMw []readDetailMw