diff --git a/internal/domain/main-entities/death-cause/dto.go b/internal/domain/main-entities/death-cause/dto.go new file mode 100644 index 00000000..8781ace8 --- /dev/null +++ b/internal/domain/main-entities/death-cause/dto.go @@ -0,0 +1,62 @@ +package death_cause + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" +) + +type CreateDto struct { + Encounter_Id *uint `json:"-"` + Value *string `json:"value"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Encounter_Id *uint `json:"encounter-id"` +} + +type ReadDetailDto struct { + Id uint16 `json:"id"` +} + +type UpdateDto struct { + Id uint16 `json:"id"` + CreateDto +} + +type DeleteDto struct { + Id uint16 `json:"id"` +} + +type MetaDto struct { + PageNumber int `json:"page_number"` + PageSize int `json:"page_size"` + Count int `json:"count"` +} + +type ResponseDto struct { + ecore.Main + Encounter_Id *uint `json:"encounter_id"` + Value *string `json:"value"` +} + +func (d DeathCause) ToResponse() ResponseDto { + resp := ResponseDto{ + Encounter_Id: d.Encounter_Id, + Value: d.Value, + } + resp.Main = d.Main + return resp +} + +func ToResponseList(data []DeathCause) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/encounter/dto.go b/internal/domain/main-entities/encounter/dto.go index 7fc15284..4a30281d 100644 --- a/internal/domain/main-entities/encounter/dto.go +++ b/internal/domain/main-entities/encounter/dto.go @@ -96,7 +96,7 @@ type MetaDto struct { } type DischargeDto struct { Id uint `json:"id"` - DischargeMethod_Code *ere.DischargeMethodCode `json:"dischargeMethod_code" validate:"maxLength=16"` + Discharge_Method_Code *ere.DischargeMethodCode `json:"discharge_method_code" validate:"maxLength=16"` EarlyEducation *string `json:"earlyEducation"` MedicalDischargeEducation *string `json:"medicalDischargeEducation"` AdmDischargeEducation *string `json:"admDischargeEducation"` diff --git a/internal/interface/main-handler/encounter/handler.go b/internal/interface/main-handler/encounter/handler.go index acbb5e08..6cf91832 100644 --- a/internal/interface/main-handler/encounter/handler.go +++ b/internal/interface/main-handler/encounter/handler.go @@ -1,6 +1,7 @@ package encounter import ( + "fmt" "net/http" rw "github.com/karincake/risoles" @@ -84,6 +85,8 @@ func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { } func (obj myBase) CheckOut(w http.ResponseWriter, r *http.Request) { + const dataValidationVail = "data-validation-fail" + dto := e.DischargeDto{} id := rw.ValidateInt(w, "id", r.PathValue("id")) if id <= 0 { @@ -95,7 +98,44 @@ func (obj myBase) CheckOut(w http.ResponseWriter, r *http.Request) { } // validate request body - if dto.DischargeMethod_Code == ere. + { + switch *dto.Discharge_Method_Code { + case ere.DMCDeath: + if dto.DeathCause == nil { + rw.DataResponse(w, nil, d.FieldError{ + Code: dataValidationVail, + Message: "deathCause required if discharge_method_code is death", + }) + return + } + case ere.DMCConsulPoly, ere.DMCConsulExecutive: + if dto.InternalReferences == nil { + rw.DataResponse(w, nil, d.FieldError{ + Code: dataValidationVail, + Message: fmt.Sprintf("internalReferences required if discharge_method_code is %s", *dto.Discharge_Method_Code), + }) + return + } + + for _, v := range *dto.InternalReferences { + if v.Unit_Id == nil { + rw.DataResponse(w, nil, d.FieldError{ + Code: dataValidationVail, + Message: "internalReferences.unit_id required", + }) + return + } + + if v.Doctor_Id == nil { + rw.DataResponse(w, nil, d.FieldError{ + Code: dataValidationVail, + Message: "internalReferences.doctor_id required", + }) + return + } + } + } + } dto.Id = uint(id) res, err := u.CheckOut(dto) diff --git a/internal/use-case/main-use-case/ambulance-transport-req/case.go b/internal/use-case/main-use-case/ambulance-transport-req/case.go index 712d6241..6810fe83 100644 --- a/internal/use-case/main-use-case/ambulance-transport-req/case.go +++ b/internal/use-case/main-use-case/ambulance-transport-req/case.go @@ -1,4 +1,4 @@ -package ambulancetransport +package ambulance_transport_req import ( "errors" diff --git a/internal/use-case/main-use-case/ambulance-transport-req/helper.go b/internal/use-case/main-use-case/ambulance-transport-req/helper.go index 3c739eb0..9ad4122d 100644 --- a/internal/use-case/main-use-case/ambulance-transport-req/helper.go +++ b/internal/use-case/main-use-case/ambulance-transport-req/helper.go @@ -2,7 +2,7 @@ DESCRIPTION: Any functions that are used internally by the use-case */ -package ambulancetransport +package ambulance_transport_req import ( "errors" diff --git a/internal/use-case/main-use-case/ambulance-transport-req/lib.go b/internal/use-case/main-use-case/ambulance-transport-req/lib.go index e8555a6f..eca1c5b9 100644 --- a/internal/use-case/main-use-case/ambulance-transport-req/lib.go +++ b/internal/use-case/main-use-case/ambulance-transport-req/lib.go @@ -1,4 +1,4 @@ -package ambulancetransport +package ambulance_transport_req import ( "errors" diff --git a/internal/use-case/main-use-case/ambulance-transport-req/middleware-runner.go b/internal/use-case/main-use-case/ambulance-transport-req/middleware-runner.go index b98c497d..18937f5c 100644 --- a/internal/use-case/main-use-case/ambulance-transport-req/middleware-runner.go +++ b/internal/use-case/main-use-case/ambulance-transport-req/middleware-runner.go @@ -1,4 +1,4 @@ -package ambulancetransport +package ambulance_transport_req import ( atr "simrs-vx/internal/domain/main-entities/ambulance-transport-req" diff --git a/internal/use-case/main-use-case/ambulance-transport-req/middleware.go b/internal/use-case/main-use-case/ambulance-transport-req/middleware.go index 847aa3dd..cc1f7c3e 100644 --- a/internal/use-case/main-use-case/ambulance-transport-req/middleware.go +++ b/internal/use-case/main-use-case/ambulance-transport-req/middleware.go @@ -1,4 +1,4 @@ -package ambulancetransport +package ambulance_transport_req // example of middleware // func init() { diff --git a/internal/use-case/main-use-case/ambulance-transport-req/tycovar.go b/internal/use-case/main-use-case/ambulance-transport-req/tycovar.go index 5d3ac027..54f8f604 100644 --- a/internal/use-case/main-use-case/ambulance-transport-req/tycovar.go +++ b/internal/use-case/main-use-case/ambulance-transport-req/tycovar.go @@ -6,7 +6,7 @@ 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 ambulancetransport +package ambulance_transport_req import ( "gorm.io/gorm" diff --git a/internal/use-case/main-use-case/death-cause/case.go b/internal/use-case/main-use-case/death-cause/case.go new file mode 100644 index 00000000..484c0f66 --- /dev/null +++ b/internal/use-case/main-use-case/death-cause/case.go @@ -0,0 +1,228 @@ +package deathcause + +import ( + + // main entities + edc "simrs-vx/internal/domain/main-entities/death-cause" + "strconv" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + "gorm.io/gorm" +) + +const source = "death-cause" + +func Create(input edc.CreateDto) (*d.Data, error) { + data := edc.DeathCause{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + 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 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 { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: data.ToResponse(), + }, nil +} + +func ReadList(input edc.ReadListDto) (*d.Data, error) { + var data *edc.DeathCause + var dataList []edc.DeathCause + var metaList *edc.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: edc.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input edc.ReadDetailDto) (*d.Data, error) { + var data *edc.DeathCause + var err error + + event := pl.Event{ + Feature: "ReadDetail", + Source: source, + } + + // Start log + 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "fetched", + }, + Data: data.ToResponse(), + }, nil +} + +func Update(input edc.UpdateDto) (*d.Data, error) { + rdDto := edc.ReadDetailDto{Id: input.Id} + var data *edc.DeathCause + var err error + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + 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 + } + + 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 + } + + // Get Updated Data + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + 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 + +} diff --git a/internal/use-case/main-use-case/death-cause/helper.go b/internal/use-case/main-use-case/death-cause/helper.go new file mode 100644 index 00000000..c655a966 --- /dev/null +++ b/internal/use-case/main-use-case/death-cause/helper.go @@ -0,0 +1,22 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package deathcause + +import ( + e "simrs-vx/internal/domain/main-entities/death-cause" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.DeathCause) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.Encounter_Id = inputSrc.Encounter_Id + data.Value = inputSrc.Value +} diff --git a/internal/use-case/main-use-case/death-cause/lib.go b/internal/use-case/main-use-case/death-cause/lib.go new file mode 100644 index 00000000..9f1d548b --- /dev/null +++ b/internal/use-case/main-use-case/death-cause/lib.go @@ -0,0 +1,140 @@ +package deathcause + +import ( + "errors" + e "simrs-vx/internal/domain/main-entities/death-cause" + plh "simrs-vx/pkg/lib-helper" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + gh "github.com/karincake/getuk" + "gorm.io/gorm" +) + +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.DeathCause, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.DeathCause{} + setData(&input, &data) + + 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(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.DeathCause, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.DeathCause{} + pagination := gh.Pagination{} + count := int64(0) + meta := e.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&e.DeathCause{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Order("\"CreatedAt\" DESC") + + if err := tx.Find(&data).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, &meta, nil + } + return nil, nil, plh.HandleListError(input, event, err) + } + + meta.Count = int(count) + meta.PageNumber = pagination.PageNumber + meta.PageSize = pagination.PageSize + + pl.SetLogInfo(event, nil, "complete") + return data, &meta, nil +} + +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.DeathCause, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.DeathCause{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if err := tx.First(&data, input.Id).Error; err != nil { + if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { + return nil, processedErr + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateData(input e.UpdateDto, data *e.DeathCause, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBUpdate") + setData(&input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 DeleteData(data *e.DeathCause, 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 +} diff --git a/internal/use-case/main-use-case/death-cause/middleware-runner.go b/internal/use-case/main-use-case/death-cause/middleware-runner.go new file mode 100644 index 00000000..3b0b1aa0 --- /dev/null +++ b/internal/use-case/main-use-case/death-cause/middleware-runner.go @@ -0,0 +1,103 @@ +package deathcause + +import ( + e "simrs-vx/internal/domain/main-entities/death-cause" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +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.DeathCause) 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.DeathCause) 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.DeathCause) 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.DeathCause) 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.DeathCause) 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/main-use-case/death-cause/middleware.go b/internal/use-case/main-use-case/death-cause/middleware.go new file mode 100644 index 00000000..845ec256 --- /dev/null +++ b/internal/use-case/main-use-case/death-cause/middleware.go @@ -0,0 +1,9 @@ +package deathcause + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } diff --git a/internal/use-case/main-use-case/death-cause/tycovar.go b/internal/use-case/main-use-case/death-cause/tycovar.go new file mode 100644 index 00000000..9cfe21a6 --- /dev/null +++ b/internal/use-case/main-use-case/death-cause/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 deathcause + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/death-cause" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.DeathCause, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.DeathCause, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.DeathCause, 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 diff --git a/internal/use-case/main-use-case/encounter/case.go b/internal/use-case/main-use-case/encounter/case.go index fad183f6..43ce3cbf 100644 --- a/internal/use-case/main-use-case/encounter/case.go +++ b/internal/use-case/main-use-case/encounter/case.go @@ -2,10 +2,13 @@ package encounter import ( "errors" + "fmt" + uir "simrs-vx/internal/use-case/main-use-case/internal-reference" "strconv" 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" ee "simrs-vx/internal/domain/main-entities/emergency" eem "simrs-vx/internal/domain/main-entities/employee" e "simrs-vx/internal/domain/main-entities/encounter" @@ -13,6 +16,7 @@ import ( 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" 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" @@ -20,12 +24,12 @@ import ( erc "simrs-vx/internal/domain/references/common" ere "simrs-vx/internal/domain/references/encounter" - dg "github.com/karincake/apem/db-gorm-pg" - d "github.com/karincake/dodol" - pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + "gorm.io/gorm" ) @@ -411,6 +415,66 @@ func CheckOut(input e.DischargeDto) (*d.Data, error) { } } + switch *input.Discharge_Method_Code { + case 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 + } + + case ere.DMCConsulPoly, ere.DMCConsulExecutive: + 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) { + return fmt.Errorf("some unit_id not found") + } + } + + // 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) { + return fmt.Errorf("some doctor_id not found") + } + } + + if err := uir.CreateBulkData(*input.InternalReferences, input.Id, &event, tx); err != nil { + return err + } + } + pl.SetLogInfo(&event, nil, "complete") return nil diff --git a/internal/use-case/main-use-case/encounter/helper.go b/internal/use-case/main-use-case/encounter/helper.go index 7cb72938..36244f83 100644 --- a/internal/use-case/main-use-case/encounter/helper.go +++ b/internal/use-case/main-use-case/encounter/helper.go @@ -8,6 +8,7 @@ import ( "errors" "fmt" "strings" + "time" "gorm.io/gorm" @@ -15,6 +16,7 @@ import ( pu "simrs-vx/pkg/use-case-helper" edo "simrs-vx/internal/domain/main-entities/device-order" + ed "simrs-vx/internal/domain/main-entities/doctor" 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" @@ -23,6 +25,7 @@ import ( emmi "simrs-vx/internal/domain/main-entities/medicine-mix-item" ep "simrs-vx/internal/domain/main-entities/prescription" epi "simrs-vx/internal/domain/main-entities/prescription-item" + 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" @@ -77,12 +80,15 @@ func setDataUpdate(src e.UpdateDto, dst *e.Encounter) { } func setDataDischarge(src e.DischargeDto, dst *e.Encounter) { - dst.DischargeMethod_Code = src.DischargeMethod_Code + dst.Discharge_Method_Code = src.Discharge_Method_Code dst.EarlyEducation = src.EarlyEducation dst.MedicalDischargeEducation = src.MedicalDischargeEducation dst.AdmDischargeEducation = src.AdmDischargeEducation dst.DischargeReason = src.DischargeReason dst.Status_Code = erc.DSCDone + + now := time.Now() + dst.Discharge_Date = &now } func checkSoapiByDocExists(encounter_id uint, event *pl.Event, tx *gorm.DB) error { @@ -317,3 +323,35 @@ func getMcuOrders(encounter_id uint, event *pl.Event, tx *gorm.DB) error { func setDataUpdateStatus(src e.UpdateStatusDto, dst *e.Encounter) { dst.Status_Code = src.StatusCode } + +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 +} diff --git a/internal/use-case/main-use-case/internal-reference/case.go b/internal/use-case/main-use-case/internal-reference/case.go index 1681bf26..bfd9550f 100644 --- a/internal/use-case/main-use-case/internal-reference/case.go +++ b/internal/use-case/main-use-case/internal-reference/case.go @@ -1,19 +1,9 @@ package internal_reference import ( - - // main entities - ed "simrs-vx/internal/domain/main-entities/doctor" - ee "simrs-vx/internal/domain/main-entities/encounter" eir "simrs-vx/internal/domain/main-entities/internal-reference" - eu "simrs-vx/internal/domain/main-entities/unit" "strconv" - // main use case - ud "simrs-vx/internal/use-case/main-use-case/doctor" - ue "simrs-vx/internal/use-case/main-use-case/encounter" - uu "simrs-vx/internal/use-case/main-use-case/unit" - pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" @@ -43,11 +33,6 @@ func Create(input eir.CreateDto) (*d.Data, error) { return err } - // Validate Request - if err := validateRequest(input); err != nil { - return err - } - if resData, err := CreateData(input, &event, tx); err != nil { return err } else { @@ -179,29 +164,6 @@ func ReadDetail(input eir.ReadDetailDto) (*d.Data, error) { }, nil } -func validateRequest(input eir.CreateDto) (err error) { - - // Validate Encounter Id - _, err = ue.ReadDetail(ee.ReadDetailDto{Id: uint16(*input.Encounter_Id)}) - if err != nil { - return err - } - - // Validate Unit Id - _, err = uu.ReadDetail(eu.ReadDetailDto{Id: *input.Unit_Id}) - if err != nil { - return err - } - - // Validate Doctor Id - _, err = ud.ReadDetail(ed.ReadDetailDto{Id: uint16(*input.Doctor_Id)}) - if err != nil { - return err - } - - return -} - func Update(input eir.UpdateDto) (*d.Data, error) { rdDto := eir.ReadDetailDto{Id: input.Id} var data *eir.InternalReference @@ -228,21 +190,10 @@ func Update(input eir.UpdateDto) (*d.Data, error) { return err } - // Validate Request - if err := validateRequest(input.CreateDto); err != nil { - return err - } - if err := UpdateData(input, data, &event, tx); err != nil { return err } - // Get Updated Data - rdDto.Includes = "encounter,unit,doctor" - if data, err = ReadDetailData(rdDto, &event, tx); err != nil { - return err - } - pl.SetLogInfo(&event, nil, "complete") mwRunner.setMwType(pu.MWTPost) diff --git a/internal/use-case/main-use-case/internal-reference/helper.go b/internal/use-case/main-use-case/internal-reference/helper.go index aaef382a..dbd92f73 100644 --- a/internal/use-case/main-use-case/internal-reference/helper.go +++ b/internal/use-case/main-use-case/internal-reference/helper.go @@ -21,3 +21,17 @@ func setData[T *ir.CreateDto | *ir.UpdateDto](input T, data *ir.InternalReferenc data.Unit_Id = inputSrc.Unit_Id data.Doctor_Id = inputSrc.Doctor_Id } + +func setBulkData(input []ir.CreateDto, encounterId uint) []ir.InternalReference { + var data []ir.InternalReference + + for _, v := range input { + data = append(data, ir.InternalReference{ + Encounter_Id: &encounterId, + Unit_Id: v.Unit_Id, + Doctor_Id: v.Doctor_Id, + }) + } + + return data +} diff --git a/internal/use-case/main-use-case/internal-reference/lib.go b/internal/use-case/main-use-case/internal-reference/lib.go index a50d594c..18215078 100644 --- a/internal/use-case/main-use-case/internal-reference/lib.go +++ b/internal/use-case/main-use-case/internal-reference/lib.go @@ -142,3 +142,24 @@ func DeleteData(data *eir.InternalReference, event *pl.Event, dbx ...*gorm.DB) e pl.SetLogInfo(event, nil, "complete") return nil } + +func CreateBulkData(input []eir.CreateDto, encounterId uint, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := []eir.InternalReference{} + setBulkData(input, encounterId) + + 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 +}