From a4a0a4f672eae001f93f60f75bea154d569cc8ad Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Fri, 22 Aug 2025 15:18:25 +0700 Subject: [PATCH] refactor : adjust use case after mw refactored --- internal/domain/main-entities/user/dto.go | 2 +- .../use-case/main-use-case/district/case.go | 283 ++++------------- .../use-case/main-use-case/district/lib.go | 79 ++++- .../district/middleware-runner.go | 103 +++++++ .../main-use-case/district/middleware.go | 9 + .../main-use-case/district/tycovar.go | 22 +- .../main-use-case/division-position/case.go | 282 ++++------------- .../main-use-case/division-position/lib.go | 81 ++++- .../division-position/middleware-runner.go | 103 +++++++ .../division-position/middleware.go | 9 + .../division-position/tycovar.go | 22 +- .../use-case/main-use-case/division/case.go | 280 ++++------------- .../use-case/main-use-case/division/lib.go | 80 ++++- .../division/middleware-runner.go | 103 +++++++ .../main-use-case/division/middleware.go | 9 + .../main-use-case/division/tycovar.go | 22 +- .../main-use-case/installation/case.go | 280 ++++------------- .../main-use-case/installation/lib.go | 80 ++++- .../installation/middleware-runner.go | 103 +++++++ .../main-use-case/installation/middleware.go | 9 + .../main-use-case/installation/tycovar.go | 22 +- .../use-case/main-use-case/province/case.go | 280 ++++------------- .../use-case/main-use-case/province/lib.go | 79 ++++- .../province/middleware-runner.go | 105 +++++++ .../main-use-case/province/middleware.go | 9 + .../main-use-case/province/tycovar.go | 22 +- .../use-case/main-use-case/regency/case.go | 280 ++++------------- .../use-case/main-use-case/regency/lib.go | 79 ++++- .../regency/middleware-runner.go | 105 +++++++ .../main-use-case/regency/middleware.go | 9 + .../use-case/main-use-case/regency/tycovar.go | 22 +- internal/use-case/main-use-case/unit/case.go | 280 ++++------------- internal/use-case/main-use-case/unit/lib.go | 81 ++++- .../main-use-case/unit/middleware-runner.go | 103 +++++++ .../use-case/main-use-case/unit/middleware.go | 9 + .../use-case/main-use-case/unit/tycovar.go | 22 +- internal/use-case/main-use-case/user/case.go | 169 ++++------ .../use-case/main-use-case/user/helper.go | 107 +------ internal/use-case/main-use-case/user/lib.go | 79 ++++- .../main-use-case/user/middleware-runner.go | 103 +++++++ .../use-case/main-use-case/user/middleware.go | 160 +--------- .../use-case/main-use-case/user/tycovar.go | 22 +- .../use-case/main-use-case/village/case.go | 288 ++++-------------- .../use-case/main-use-case/village/lib.go | 79 ++++- .../village/middleware-runner.go | 103 +++++++ .../main-use-case/village/middleware.go | 9 + .../use-case/main-use-case/village/tycovar.go | 22 +- pkg/logger/logger.go | 2 +- pkg/use-case-helper/use-case-helper.go | 24 +- 49 files changed, 2331 insertions(+), 2304 deletions(-) create mode 100644 internal/use-case/main-use-case/district/middleware-runner.go create mode 100644 internal/use-case/main-use-case/district/middleware.go create mode 100644 internal/use-case/main-use-case/division-position/middleware-runner.go create mode 100644 internal/use-case/main-use-case/division-position/middleware.go create mode 100644 internal/use-case/main-use-case/division/middleware-runner.go create mode 100644 internal/use-case/main-use-case/division/middleware.go create mode 100644 internal/use-case/main-use-case/installation/middleware-runner.go create mode 100644 internal/use-case/main-use-case/installation/middleware.go create mode 100644 internal/use-case/main-use-case/province/middleware-runner.go create mode 100644 internal/use-case/main-use-case/province/middleware.go create mode 100644 internal/use-case/main-use-case/regency/middleware-runner.go create mode 100644 internal/use-case/main-use-case/regency/middleware.go create mode 100644 internal/use-case/main-use-case/unit/middleware-runner.go create mode 100644 internal/use-case/main-use-case/unit/middleware.go create mode 100644 internal/use-case/main-use-case/user/middleware-runner.go create mode 100644 internal/use-case/main-use-case/village/middleware-runner.go create mode 100644 internal/use-case/main-use-case/village/middleware.go diff --git a/internal/domain/main-entities/user/dto.go b/internal/domain/main-entities/user/dto.go index ab2bd7d2..87ce62d0 100644 --- a/internal/domain/main-entities/user/dto.go +++ b/internal/domain/main-entities/user/dto.go @@ -56,7 +56,7 @@ type ResponseDto struct { LastAllowdLogin *time.Time `json:"lastAllowdLogin,omitempty"` } -func (u User) ToResponse() ResponseDto { +func (u *User) ToResponse() ResponseDto { resp := ResponseDto{ Name: u.Name, Status_Code: u.Status_Code, diff --git a/internal/use-case/main-use-case/district/case.go b/internal/use-case/main-use-case/district/case.go index c5f16ca9..1770e6f2 100644 --- a/internal/use-case/main-use-case/district/case.go +++ b/internal/use-case/main-use-case/district/case.go @@ -1,7 +1,6 @@ package district import ( - "fmt" e "simrs-vx/internal/domain/main-entities/district" "strconv" @@ -19,8 +18,6 @@ const source = "district" func Create(input e.CreateDto) (*d.Data, error) { data := e.District{} - setData(&input, &data) - event := pl.Event{ Feature: "Create", Source: source, @@ -30,51 +27,23 @@ func Create(input e.CreateDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "create") err := dg.I.Transaction(func(tx *gorm.DB) error { - for i := range createPreMw { - mwName := fmt.Sprintf("createPreMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := createPreMw[i](&input, &data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunCreateMiddleware(createPreMw, &input, &data); err != nil { + return err } - pl.SetLogInfo(&event, data, "started", "DBCreate") - _, err := CreateData(&data, tx) - if err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-create-fail", - Detail: "Database insert failed", - Raw: err, - } - return pl.SetLogError(event, data) + if resData, err := CreateData(input, &event, tx); err != nil { + return err + } else { + data = *resData } - pl.SetLogInfo(&event, nil, "complete") - - for i := range createPostMw { - mwName := fmt.Sprintf("createPostMw[%d]", i) - - pl.SetLogInfo(&event, input, "started", mwName) - if err := createPostMw[i](&input, &data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunCreateMiddleware(createPostMw, &input, &data); err != nil { + return err } pl.SetLogInfo(&event, nil, "complete") @@ -111,54 +80,21 @@ func ReadList(input e.ReadListDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "readList") err = dg.I.Transaction(func(tx *gorm.DB) error { - for i := range readListPreMw { - mwName := fmt.Sprintf("readListPreMw[%d]", i) - - pl.SetLogInfo(&event, input, "started", mwName) - - if err := readListPreMw[i](&input, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, input) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadListMiddleware(readListPreMw, &input, data); err != nil { + return err } - pl.SetLogInfo(&event, input, "started", "DBReadList") - dataList, metaList, err = ReadListData(input, tx) - if err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-read-list-fail", - Detail: "Database read list failed", - Raw: err, - } - return pl.SetLogError(event, input) + if dataList, metaList, err = ReadListData(input, &event, tx); err != nil { + return err } - pl.SetLogInfo(&event, nil, "complete") - - for i := range readListPostMw { - mwName := fmt.Sprintf("readListPostMw[%d]", i) - - pl.SetLogInfo(&event, input, "started", mwName) - - if err := readListPostMw[i](&input, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, input) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadListMiddleware(readListPostMw, &input, data); err != nil { + return err } return nil @@ -194,46 +130,21 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "readDetail") err = dg.I.Transaction(func(tx *gorm.DB) error { - for i := range readDetailPreMw { - mwName := fmt.Sprintf("readDetailPreMw[%d]", i) - - pl.SetLogInfo(&event, input, "started", mwName) - - if err := readDetailPreMw[i](&input, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, input) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadDetailMiddleware(readDetailPreMw, &input, data); err != nil { + return err } - pl.SetLogInfo(&event, input, "started", "DBReadDetail") - data, err = ReadDetailData(input, tx) - if processedErr := pu.HandleReadError(err, &event, source, input.Id, data); processedErr != nil { - return processedErr + if data, err = ReadDetailData(input, &event, tx); err != nil { + return err } - for i := range readDetailPostMw { - mwName := fmt.Sprintf("readDetailPostMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := readDetailPostMw[i](&input, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadDetailMiddleware(readDetailPostMw, &input, data); err != nil { + return err } return nil @@ -249,7 +160,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { "structure": "single-data", "status": "fetched", }, - Data: pu.SafeToResponse(data), + Data: data.ToResponse(), }, nil } @@ -268,60 +179,27 @@ func Update(input e.UpdateDto) (*d.Data, error) { err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") - data, err = ReadDetailData(rdDto, tx) - if processedErr := pu.HandleReadError(err, &event, source, input.Id, data); processedErr != nil { - return processedErr - } - pl.SetLogInfo(&event, input, "started", "setUpdate") - setData(&input, data) - - for i := range updatePreMw { - mwName := fmt.Sprintf("updatePreMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := updatePreMw[i](&rdDto, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + return err } - pl.SetLogInfo(&event, data, "started", "DBUpdate") - if err := UpdateData(*data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-update-fail", - Detail: "Database update failed", - Raw: err, - } - return pl.SetLogError(event, data) + 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") - for i := range updatePostMw { - mwName := fmt.Sprintf("updatePostMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := updatePostMw[i](&rdDto, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - 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 @@ -357,58 +235,25 @@ func Delete(input e.DeleteDto) (*d.Data, error) { err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") - data, err = ReadDetailData(rdDto, tx) - if processedErr := pu.HandleReadError(err, &event, source, input.Id, data); processedErr != nil { - return processedErr + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + return err } - for i := range deletePreMw { - mwName := fmt.Sprintf("deletePreMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := deletePreMw[i](&rdDto, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunDeleteMiddleware(readDetailPreMw, &rdDto, data); err != nil { + return err } - pl.SetLogInfo(&event, data, "started", "DBDelete") - if err := DeleteData(data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-delete-fail", - Detail: "Database delete failed", - Raw: err, - } - return pl.SetLogError(event, data) + if err := DeleteData(data, &event, tx); err != nil { + return err } - pl.SetLogInfo(&event, nil, "complete") - - for i := range deletePostMw { - mwName := fmt.Sprintf("deletePostMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := deletePostMw[i](&rdDto, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunDeleteMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err } return nil diff --git a/internal/use-case/main-use-case/district/lib.go b/internal/use-case/main-use-case/district/lib.go index 402cae63..0f199d86 100644 --- a/internal/use-case/main-use-case/district/lib.go +++ b/internal/use-case/main-use-case/district/lib.go @@ -2,13 +2,20 @@ package district import ( e "simrs-vx/internal/domain/main-entities/district" + 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.District, dbx ...*gorm.DB) (*e.District, error) { +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.District, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.District{} + setData(&input, &data) + var tx *gorm.DB if len(dbx) > 0 { tx = dbx[0] @@ -16,14 +23,22 @@ func CreateData(input *e.District, dbx ...*gorm.DB) (*e.District, error) { tx = dg.I } - if err := tx.Create(&input).Error; err != nil { - return nil, err + if err := tx.Create(&data).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-create-fail", + Detail: "Database insert failed", + Raw: err, + } + return nil, pl.SetLogError(event, input) } - return input, nil + pl.SetLogInfo(event, nil, "complete") + return &data, nil } -func ReadListData(input e.ReadListDto, dbx ...*gorm.DB) ([]e.District, *e.MetaDto, error) { +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.District, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") data := []e.District{} pagination := gh.Pagination{} count := int64(0) @@ -38,8 +53,6 @@ func ReadListData(input e.ReadListDto, dbx ...*gorm.DB) ([]e.District, *e.MetaDt tx = tx. Model(&e.District{}). - // Joins("Patient"). // if needed - // Preload("Patient"). // if needed Scopes(gh.Filter(input)). Count(&count). Scopes(gh.Paginate(input, &pagination)) @@ -48,16 +61,25 @@ func ReadListData(input e.ReadListDto, dbx ...*gorm.DB) ([]e.District, *e.MetaDt if err == gorm.ErrRecordNotFound { return nil, &meta, nil } - return nil, nil, err + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-create-fail", + Detail: "Database insert failed", + Raw: err, + } + return nil, nil, pl.SetLogError(event, input) } 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, dbx ...*gorm.DB) (*e.District, error) { +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.District, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") data := e.District{} var tx *gorm.DB @@ -68,13 +90,19 @@ func ReadDetailData(input e.ReadDetailDto, dbx ...*gorm.DB) (*e.District, error) } if err := tx.First(&data, input.Id).Error; err != nil { - return nil, err + 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.District, dbx ...*gorm.DB) error { +func UpdateData(input e.UpdateDto, data *e.District, 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] @@ -82,10 +110,22 @@ func UpdateData(input e.District, dbx ...*gorm.DB) error { tx = dg.I } - return tx.Save(&input).Error + 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(input *e.District, dbx ...*gorm.DB) error { +func DeleteData(data *e.District, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBDelete") var tx *gorm.DB if len(dbx) > 0 { tx = dbx[0] @@ -93,5 +133,16 @@ func DeleteData(input *e.District, dbx ...*gorm.DB) error { tx = dg.I } - return tx.Delete(input).Error + 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/district/middleware-runner.go b/internal/use-case/main-use-case/district/middleware-runner.go new file mode 100644 index 00000000..7906dccb --- /dev/null +++ b/internal/use-case/main-use-case/district/middleware-runner.go @@ -0,0 +1,103 @@ +package district + +import ( + e "simrs-vx/internal/domain/main-entities/district" + 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.District) 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.District) 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.District) 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.District) 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.District) 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/district/middleware.go b/internal/use-case/main-use-case/district/middleware.go new file mode 100644 index 00000000..3ad999c3 --- /dev/null +++ b/internal/use-case/main-use-case/district/middleware.go @@ -0,0 +1,9 @@ +package district + +// 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/district/tycovar.go b/internal/use-case/main-use-case/district/tycovar.go index 99670a00..f64d1a46 100644 --- a/internal/use-case/main-use-case/district/tycovar.go +++ b/internal/use-case/main-use-case/district/tycovar.go @@ -14,11 +14,23 @@ import ( e "simrs-vx/internal/domain/main-entities/district" ) -type createMw func(input *e.CreateDto, data *e.District, tx *gorm.DB) error -type readListMw func(input *e.ReadListDto, data *e.District, tx *gorm.DB) error -type readDetailMw func(input *e.ReadDetailDto, data *e.District, tx *gorm.DB) error -type updateMw func(input *e.ReadDetailDto, data *e.District, tx *gorm.DB) error -type deleteMw func(input *e.ReadDetailDto, data *e.District, tx *gorm.DB) error +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.District, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.District, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.District, tx *gorm.DB) error +} + +type UpdateMw = readDetailMw +type DeleteMw = readDetailMw var createPreMw []createMw // preprocess middleware var createPostMw []createMw // postprocess middleware diff --git a/internal/use-case/main-use-case/division-position/case.go b/internal/use-case/main-use-case/division-position/case.go index 7d00343e..bc088fcc 100644 --- a/internal/use-case/main-use-case/division-position/case.go +++ b/internal/use-case/main-use-case/division-position/case.go @@ -1,7 +1,6 @@ package divisionposition import ( - "fmt" e "simrs-vx/internal/domain/main-entities/division-position" "strconv" @@ -19,8 +18,6 @@ const source = "division-position" func Create(input e.CreateDto) (*d.Data, error) { data := e.DivisionPosition{} - setData(&input, &data) - event := pl.Event{ Feature: "Create", Source: source, @@ -30,51 +27,23 @@ func Create(input e.CreateDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "create") err := dg.I.Transaction(func(tx *gorm.DB) error { - for i := range createPreMw { - mwName := fmt.Sprintf("createPreMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := createPreMw[i](&input, &data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunCreateMiddleware(createPreMw, &input, &data); err != nil { + return err } - pl.SetLogInfo(&event, data, "started", "DBCreate") - _, err := CreateData(&data, tx) - if err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-create-fail", - Detail: "Database insert failed", - Raw: err, - } - return pl.SetLogError(event, data) + if resData, err := CreateData(input, &event, tx); err != nil { + return err + } else { + data = *resData } - pl.SetLogInfo(&event, nil, "complete") - - for i := range createPostMw { - mwName := fmt.Sprintf("createPostMw[%d]", i) - - pl.SetLogInfo(&event, input, "started", mwName) - if err := createPostMw[i](&input, &data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunCreateMiddleware(createPostMw, &input, &data); err != nil { + return err } pl.SetLogInfo(&event, nil, "complete") @@ -111,54 +80,21 @@ func ReadList(input e.ReadListDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "readList") err = dg.I.Transaction(func(tx *gorm.DB) error { - for i := range readListPreMw { - mwName := fmt.Sprintf("readListPreMw[%d]", i) - - pl.SetLogInfo(&event, input, "started", mwName) - - if err := readListPreMw[i](&input, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, input) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadListMiddleware(readListPreMw, &input, data); err != nil { + return err } - pl.SetLogInfo(&event, input, "started", "DBReadList") - dataList, metaList, err = ReadListData(input, tx) - if err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-read-list-fail", - Detail: "Database read list failed", - Raw: err, - } - return pl.SetLogError(event, input) + if dataList, metaList, err = ReadListData(input, &event, tx); err != nil { + return err } - pl.SetLogInfo(&event, nil, "complete") - - for i := range readListPostMw { - mwName := fmt.Sprintf("readListPostMw[%d]", i) - - pl.SetLogInfo(&event, input, "started", mwName) - - if err := readListPostMw[i](&input, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, input) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadListMiddleware(readListPostMw, &input, data); err != nil { + return err } return nil @@ -194,46 +130,21 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "readDetail") err = dg.I.Transaction(func(tx *gorm.DB) error { - for i := range readDetailPreMw { - mwName := fmt.Sprintf("readDetailPreMw[%d]", i) - - pl.SetLogInfo(&event, input, "started", mwName) - - if err := readDetailPreMw[i](&input, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, input) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadDetailMiddleware(readDetailPreMw, &input, data); err != nil { + return err } - pl.SetLogInfo(&event, input, "started", "DBReadDetail") - data, err = ReadDetailData(input, tx) - if processedErr := pu.HandleReadError(err, &event, source, input.Id, data); processedErr != nil { - return processedErr + if data, err = ReadDetailData(input, &event, tx); err != nil { + return err } - for i := range readDetailPostMw { - mwName := fmt.Sprintf("readDetailPostMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := readDetailPostMw[i](&input, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadDetailMiddleware(readDetailPostMw, &input, data); err != nil { + return err } return nil @@ -249,7 +160,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { "structure": "single-data", "status": "fetched", }, - Data: pu.SafeToResponse(data), + Data: data.ToResponse(), }, nil } @@ -268,59 +179,27 @@ func Update(input e.UpdateDto) (*d.Data, error) { err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") - data, err = ReadDetailData(rdDto, tx) - if processedErr := pu.HandleReadError(err, &event, source, input.Id, data); processedErr != nil { - return processedErr - } - setData(&input, data) - - for i := range updatePreMw { - mwName := fmt.Sprintf("updatePreMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := updatePreMw[i](&rdDto, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + return err } - pl.SetLogInfo(&event, data, "started", "DBUpdate") - if err := UpdateData(*data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-update-fail", - Detail: "Database update failed", - Raw: err, - } - return pl.SetLogError(event, data) + 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") - for i := range updatePostMw { - mwName := fmt.Sprintf("updatePostMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := updatePostMw[i](&rdDto, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - 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 @@ -356,58 +235,25 @@ func Delete(input e.DeleteDto) (*d.Data, error) { err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") - data, err = ReadDetailData(rdDto, tx) - if processedErr := pu.HandleReadError(err, &event, source, input.Id, data); processedErr != nil { - return processedErr + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + return err } - for i := range deletePreMw { - mwName := fmt.Sprintf("deletePreMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := deletePreMw[i](&rdDto, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunDeleteMiddleware(readDetailPreMw, &rdDto, data); err != nil { + return err } - pl.SetLogInfo(&event, data, "started", "DBDelete") - if err := DeleteData(data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-delete-fail", - Detail: "Database delete failed", - Raw: err, - } - return pl.SetLogError(event, data) + if err := DeleteData(data, &event, tx); err != nil { + return err } - pl.SetLogInfo(&event, nil, "complete") - - for i := range deletePostMw { - mwName := fmt.Sprintf("deletePostMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := deletePostMw[i](&rdDto, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunDeleteMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err } return nil diff --git a/internal/use-case/main-use-case/division-position/lib.go b/internal/use-case/main-use-case/division-position/lib.go index 7b4058a6..2f0444ae 100644 --- a/internal/use-case/main-use-case/division-position/lib.go +++ b/internal/use-case/main-use-case/division-position/lib.go @@ -2,13 +2,20 @@ package divisionposition import ( e "simrs-vx/internal/domain/main-entities/division-position" + 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.DivisionPosition, dbx ...*gorm.DB) (*e.DivisionPosition, error) { +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.DivisionPosition, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.DivisionPosition{} + setData(&input, &data) + var tx *gorm.DB if len(dbx) > 0 { tx = dbx[0] @@ -16,14 +23,22 @@ func CreateData(input *e.DivisionPosition, dbx ...*gorm.DB) (*e.DivisionPosition tx = dg.I } - if err := tx.Create(&input).Error; err != nil { - return nil, err + if err := tx.Create(&data).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-create-fail", + Detail: "Database insert failed", + Raw: err, + } + return nil, pl.SetLogError(event, input) } - return input, nil + pl.SetLogInfo(event, nil, "complete") + return &data, nil } -func ReadListData(input e.ReadListDto, dbx ...*gorm.DB) ([]e.DivisionPosition, *e.MetaDto, error) { +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.DivisionPosition, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") data := []e.DivisionPosition{} pagination := gh.Pagination{} count := int64(0) @@ -38,9 +53,7 @@ func ReadListData(input e.ReadListDto, dbx ...*gorm.DB) ([]e.DivisionPosition, * tx = tx. Model(&e.DivisionPosition{}). - // Joins("Patient"). // if needed - // Preload("Patient"). // if needed - Preload("Division"). // if needed + Preload("Division"). Scopes(gh.Filter(input)). Count(&count). Scopes(gh.Paginate(input, &pagination)). @@ -50,16 +63,25 @@ func ReadListData(input e.ReadListDto, dbx ...*gorm.DB) ([]e.DivisionPosition, * if err == gorm.ErrRecordNotFound { return nil, &meta, nil } - return nil, nil, err + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-create-fail", + Detail: "Database insert failed", + Raw: err, + } + return nil, nil, pl.SetLogError(event, input) } 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, dbx ...*gorm.DB) (*e.DivisionPosition, error) { +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.DivisionPosition, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") data := e.DivisionPosition{} var tx *gorm.DB @@ -70,13 +92,19 @@ func ReadDetailData(input e.ReadDetailDto, dbx ...*gorm.DB) (*e.DivisionPosition } if err := tx.First(&data, input.Id).Error; err != nil { - return nil, err + 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.DivisionPosition, dbx ...*gorm.DB) error { +func UpdateData(input e.UpdateDto, data *e.DivisionPosition, 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] @@ -84,10 +112,22 @@ func UpdateData(input e.DivisionPosition, dbx ...*gorm.DB) error { tx = dg.I } - return tx.Save(&input).Error + 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(input *e.DivisionPosition, dbx ...*gorm.DB) error { +func DeleteData(data *e.DivisionPosition, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBDelete") var tx *gorm.DB if len(dbx) > 0 { tx = dbx[0] @@ -95,5 +135,16 @@ func DeleteData(input *e.DivisionPosition, dbx ...*gorm.DB) error { tx = dg.I } - return tx.Delete(input).Error + 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/division-position/middleware-runner.go b/internal/use-case/main-use-case/division-position/middleware-runner.go new file mode 100644 index 00000000..2662a95f --- /dev/null +++ b/internal/use-case/main-use-case/division-position/middleware-runner.go @@ -0,0 +1,103 @@ +package divisionposition + +import ( + e "simrs-vx/internal/domain/main-entities/division-position" + 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.DivisionPosition) 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.DivisionPosition) 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.DivisionPosition) 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.DivisionPosition) 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.DivisionPosition) 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/division-position/middleware.go b/internal/use-case/main-use-case/division-position/middleware.go new file mode 100644 index 00000000..77a1c3dd --- /dev/null +++ b/internal/use-case/main-use-case/division-position/middleware.go @@ -0,0 +1,9 @@ +package divisionposition + +// 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/division-position/tycovar.go b/internal/use-case/main-use-case/division-position/tycovar.go index 0684de01..4b084e23 100644 --- a/internal/use-case/main-use-case/division-position/tycovar.go +++ b/internal/use-case/main-use-case/division-position/tycovar.go @@ -14,11 +14,23 @@ import ( e "simrs-vx/internal/domain/main-entities/division-position" ) -type createMw func(input *e.CreateDto, data *e.DivisionPosition, tx *gorm.DB) error -type readListMw func(input *e.ReadListDto, data *e.DivisionPosition, tx *gorm.DB) error -type readDetailMw func(input *e.ReadDetailDto, data *e.DivisionPosition, tx *gorm.DB) error -type updateMw func(input *e.ReadDetailDto, data *e.DivisionPosition, tx *gorm.DB) error -type deleteMw func(input *e.ReadDetailDto, data *e.DivisionPosition, tx *gorm.DB) error +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.DivisionPosition, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.DivisionPosition, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.DivisionPosition, tx *gorm.DB) error +} + +type UpdateMw = readDetailMw +type DeleteMw = readDetailMw var createPreMw []createMw // preprocess middleware var createPostMw []createMw // postprocess middleware diff --git a/internal/use-case/main-use-case/division/case.go b/internal/use-case/main-use-case/division/case.go index 3333d61b..bf1b94fe 100644 --- a/internal/use-case/main-use-case/division/case.go +++ b/internal/use-case/main-use-case/division/case.go @@ -1,7 +1,6 @@ package division import ( - "fmt" e "simrs-vx/internal/domain/main-entities/division" "strconv" @@ -19,8 +18,6 @@ const source = "division" func Create(input e.CreateDto) (*d.Data, error) { data := e.Division{} - setData(&input, &data) - event := pl.Event{ Feature: "Create", Source: source, @@ -30,51 +27,23 @@ func Create(input e.CreateDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "create") err := dg.I.Transaction(func(tx *gorm.DB) error { - for i := range createPreMw { - mwName := fmt.Sprintf("createPreMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := createPreMw[i](&input, &data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunCreateMiddleware(createPreMw, &input, &data); err != nil { + return err } - pl.SetLogInfo(&event, data, "started", "DBCreate") - _, err := CreateData(&data, tx) - if err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-create-fail", - Detail: "Database insert failed", - Raw: err, - } - return pl.SetLogError(event, data) + if resData, err := CreateData(input, &event, tx); err != nil { + return err + } else { + data = *resData } - pl.SetLogInfo(&event, nil, "complete") - - for i := range createPostMw { - mwName := fmt.Sprintf("createPostMw[%d]", i) - - pl.SetLogInfo(&event, input, "started", mwName) - if err := createPostMw[i](&input, &data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunCreateMiddleware(createPostMw, &input, &data); err != nil { + return err } pl.SetLogInfo(&event, nil, "complete") @@ -111,54 +80,21 @@ func ReadList(input e.ReadListDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "readList") err = dg.I.Transaction(func(tx *gorm.DB) error { - for i := range readListPreMw { - mwName := fmt.Sprintf("readListPreMw[%d]", i) - - pl.SetLogInfo(&event, input, "started", mwName) - - if err := readListPreMw[i](&input, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, input) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadListMiddleware(readListPreMw, &input, data); err != nil { + return err } - pl.SetLogInfo(&event, input, "started", "DBReadList") - dataList, metaList, err = ReadListData(input, tx) - if err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-read-list-fail", - Detail: "Database read list failed", - Raw: err, - } - return pl.SetLogError(event, input) + if dataList, metaList, err = ReadListData(input, &event, tx); err != nil { + return err } - pl.SetLogInfo(&event, nil, "complete") - - for i := range readListPostMw { - mwName := fmt.Sprintf("readListPostMw[%d]", i) - - pl.SetLogInfo(&event, input, "started", mwName) - - if err := readListPostMw[i](&input, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, input) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadListMiddleware(readListPostMw, &input, data); err != nil { + return err } return nil @@ -194,46 +130,21 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "readDetail") err = dg.I.Transaction(func(tx *gorm.DB) error { - for i := range readDetailPreMw { - mwName := fmt.Sprintf("readDetailPreMw[%d]", i) - - pl.SetLogInfo(&event, input, "started", mwName) - - if err := readDetailPreMw[i](&input, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, input) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadDetailMiddleware(readDetailPreMw, &input, data); err != nil { + return err } - pl.SetLogInfo(&event, input, "started", "DBReadDetail") - data, err = ReadDetailData(input, tx) - if processedErr := pu.HandleReadError(err, &event, source, input.Id, data); processedErr != nil { - return processedErr + if data, err = ReadDetailData(input, &event, tx); err != nil { + return err } - for i := range readDetailPostMw { - mwName := fmt.Sprintf("readDetailPostMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := readDetailPostMw[i](&input, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadDetailMiddleware(readDetailPostMw, &input, data); err != nil { + return err } return nil @@ -249,7 +160,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { "structure": "single-data", "status": "fetched", }, - Data: pu.SafeToResponse(data), + Data: data.ToResponse(), }, nil } @@ -268,61 +179,27 @@ func Update(input e.UpdateDto) (*d.Data, error) { err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") - data, err = ReadDetailData(rdDto, tx) - if processedErr := pu.HandleReadError(err, &event, source, input.Id, data); processedErr != nil { - return processedErr + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + return err } - pl.SetLogInfo(&event, input, "started", "setUpdate") - setData(&input, data) - - for i := range updatePreMw { - mwName := fmt.Sprintf("updatePreMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := updatePreMw[i](&rdDto, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPreMw, &rdDto, data); err != nil { + return err } - pl.SetLogInfo(&event, data, "started", "DBUpdate") - if err := UpdateData(*data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-update-fail", - Detail: "Database update failed", - Raw: err, - } - return pl.SetLogError(event, data) + if err := UpdateData(input, data, &event, tx); err != nil { + return err } pl.SetLogInfo(&event, nil, "complete") - for i := range updatePostMw { - mwName := fmt.Sprintf("updatePostMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := updatePostMw[i](&rdDto, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - 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 @@ -358,58 +235,25 @@ func Delete(input e.DeleteDto) (*d.Data, error) { err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") - data, err = ReadDetailData(rdDto, tx) - if processedErr := pu.HandleReadError(err, &event, source, input.Id, data); processedErr != nil { - return processedErr + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + return err } - for i := range deletePreMw { - mwName := fmt.Sprintf("deletePreMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := deletePreMw[i](&rdDto, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunDeleteMiddleware(readDetailPreMw, &rdDto, data); err != nil { + return err } - pl.SetLogInfo(&event, data, "started", "DBDelete") - if err := DeleteData(data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-delete-fail", - Detail: "Database delete failed", - Raw: err, - } - return pl.SetLogError(event, data) + if err := DeleteData(data, &event, tx); err != nil { + return err } - pl.SetLogInfo(&event, nil, "complete") - - for i := range deletePostMw { - mwName := fmt.Sprintf("deletePostMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := deletePostMw[i](&rdDto, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunDeleteMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err } return nil diff --git a/internal/use-case/main-use-case/division/lib.go b/internal/use-case/main-use-case/division/lib.go index 1b13bcf5..0acd085d 100644 --- a/internal/use-case/main-use-case/division/lib.go +++ b/internal/use-case/main-use-case/division/lib.go @@ -2,13 +2,20 @@ package division import ( e "simrs-vx/internal/domain/main-entities/division" + 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.Division, dbx ...*gorm.DB) (*e.Division, error) { +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.Division, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.Division{} + setData(&input, &data) + var tx *gorm.DB if len(dbx) > 0 { tx = dbx[0] @@ -16,14 +23,22 @@ func CreateData(input *e.Division, dbx ...*gorm.DB) (*e.Division, error) { tx = dg.I } - if err := tx.Create(&input).Error; err != nil { - return nil, err + if err := tx.Create(&data).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-create-fail", + Detail: "Database insert failed", + Raw: err, + } + return nil, pl.SetLogError(event, input) } - return input, nil + pl.SetLogInfo(event, nil, "complete") + return &data, nil } -func ReadListData(input e.ReadListDto, dbx ...*gorm.DB) ([]e.Division, *e.MetaDto, error) { +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.Division, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") data := []e.Division{} pagination := gh.Pagination{} count := int64(0) @@ -38,8 +53,7 @@ func ReadListData(input e.ReadListDto, dbx ...*gorm.DB) ([]e.Division, *e.MetaDt tx = tx. Model(&e.Division{}). - // Joins("Patient"). // if needed - // Preload("Patient"). // if needed + Preload("Installation"). Scopes(gh.Filter(input)). Count(&count). Scopes(gh.Paginate(input, &pagination)). @@ -49,16 +63,25 @@ func ReadListData(input e.ReadListDto, dbx ...*gorm.DB) ([]e.Division, *e.MetaDt if err == gorm.ErrRecordNotFound { return nil, &meta, nil } - return nil, nil, err + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-create-fail", + Detail: "Database insert failed", + Raw: err, + } + return nil, nil, pl.SetLogError(event, input) } 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, dbx ...*gorm.DB) (*e.Division, error) { +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.Division, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") data := e.Division{} var tx *gorm.DB @@ -69,13 +92,19 @@ func ReadDetailData(input e.ReadDetailDto, dbx ...*gorm.DB) (*e.Division, error) } if err := tx.First(&data, input.Id).Error; err != nil { - return nil, err + 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.Division, dbx ...*gorm.DB) error { +func UpdateData(input e.UpdateDto, data *e.Division, 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] @@ -83,10 +112,22 @@ func UpdateData(input e.Division, dbx ...*gorm.DB) error { tx = dg.I } - return tx.Save(&input).Error + 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(input *e.Division, dbx ...*gorm.DB) error { +func DeleteData(data *e.Division, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBDelete") var tx *gorm.DB if len(dbx) > 0 { tx = dbx[0] @@ -94,5 +135,16 @@ func DeleteData(input *e.Division, dbx ...*gorm.DB) error { tx = dg.I } - return tx.Delete(input).Error + 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/division/middleware-runner.go b/internal/use-case/main-use-case/division/middleware-runner.go new file mode 100644 index 00000000..915cce28 --- /dev/null +++ b/internal/use-case/main-use-case/division/middleware-runner.go @@ -0,0 +1,103 @@ +package division + +import ( + e "simrs-vx/internal/domain/main-entities/division" + 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.Division) 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.Division) 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.Division) 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.Division) 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.Division) 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/division/middleware.go b/internal/use-case/main-use-case/division/middleware.go new file mode 100644 index 00000000..f066ffb8 --- /dev/null +++ b/internal/use-case/main-use-case/division/middleware.go @@ -0,0 +1,9 @@ +package division + +// 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/division/tycovar.go b/internal/use-case/main-use-case/division/tycovar.go index ba4154f2..c7733117 100644 --- a/internal/use-case/main-use-case/division/tycovar.go +++ b/internal/use-case/main-use-case/division/tycovar.go @@ -14,11 +14,23 @@ import ( e "simrs-vx/internal/domain/main-entities/division" ) -type createMw func(input *e.CreateDto, data *e.Division, tx *gorm.DB) error -type readListMw func(input *e.ReadListDto, data *e.Division, tx *gorm.DB) error -type readDetailMw func(input *e.ReadDetailDto, data *e.Division, tx *gorm.DB) error -type updateMw func(input *e.ReadDetailDto, data *e.Division, tx *gorm.DB) error -type deleteMw func(input *e.ReadDetailDto, data *e.Division, tx *gorm.DB) error +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.Division, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.Division, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.Division, tx *gorm.DB) error +} + +type UpdateMw = readDetailMw +type DeleteMw = readDetailMw var createPreMw []createMw // preprocess middleware var createPostMw []createMw // postprocess middleware diff --git a/internal/use-case/main-use-case/installation/case.go b/internal/use-case/main-use-case/installation/case.go index e12186f6..6de77882 100644 --- a/internal/use-case/main-use-case/installation/case.go +++ b/internal/use-case/main-use-case/installation/case.go @@ -1,7 +1,6 @@ package installation import ( - "fmt" e "simrs-vx/internal/domain/main-entities/installation" "strconv" @@ -19,8 +18,6 @@ const source = "installation" func Create(input e.CreateDto) (*d.Data, error) { data := e.Installation{} - setData(&input, &data) - event := pl.Event{ Feature: "Create", Source: source, @@ -30,51 +27,23 @@ func Create(input e.CreateDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "create") err := dg.I.Transaction(func(tx *gorm.DB) error { - for i := range createPreMw { - mwName := fmt.Sprintf("createPreMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := createPreMw[i](&input, &data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunCreateMiddleware(createPreMw, &input, &data); err != nil { + return err } - pl.SetLogInfo(&event, data, "started", "DBCreate") - _, err := CreateData(&data, tx) - if err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-create-fail", - Detail: "Database insert failed", - Raw: err, - } - return pl.SetLogError(event, data) + if resData, err := CreateData(input, &event, tx); err != nil { + return err + } else { + data = *resData } - pl.SetLogInfo(&event, nil, "complete") - - for i := range createPostMw { - mwName := fmt.Sprintf("createPostMw[%d]", i) - - pl.SetLogInfo(&event, input, "started", mwName) - if err := createPostMw[i](&input, &data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunCreateMiddleware(createPostMw, &input, &data); err != nil { + return err } pl.SetLogInfo(&event, nil, "complete") @@ -111,54 +80,21 @@ func ReadList(input e.ReadListDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "readList") err = dg.I.Transaction(func(tx *gorm.DB) error { - for i := range readListPreMw { - mwName := fmt.Sprintf("readListPreMw[%d]", i) - - pl.SetLogInfo(&event, input, "started", mwName) - - if err := readListPreMw[i](&input, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, input) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadListMiddleware(readListPreMw, &input, data); err != nil { + return err } - pl.SetLogInfo(&event, input, "started", "DBReadList") - dataList, metaList, err = ReadListData(input, tx) - if err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-read-list-fail", - Detail: "Database read list failed", - Raw: err, - } - return pl.SetLogError(event, input) + if dataList, metaList, err = ReadListData(input, &event, tx); err != nil { + return err } - pl.SetLogInfo(&event, nil, "complete") - - for i := range readListPostMw { - mwName := fmt.Sprintf("readListPostMw[%d]", i) - - pl.SetLogInfo(&event, input, "started", mwName) - - if err := readListPostMw[i](&input, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, input) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadListMiddleware(readListPostMw, &input, data); err != nil { + return err } return nil @@ -194,46 +130,21 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "readDetail") err = dg.I.Transaction(func(tx *gorm.DB) error { - for i := range readDetailPreMw { - mwName := fmt.Sprintf("readDetailPreMw[%d]", i) - - pl.SetLogInfo(&event, input, "started", mwName) - - if err := readDetailPreMw[i](&input, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, input) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadDetailMiddleware(readDetailPreMw, &input, data); err != nil { + return err } - pl.SetLogInfo(&event, input, "started", "DBReadDetail") - data, err = ReadDetailData(input, tx) - if processedErr := pu.HandleReadError(err, &event, source, input.Id, data); processedErr != nil { - return processedErr + if data, err = ReadDetailData(input, &event, tx); err != nil { + return err } - for i := range readDetailPostMw { - mwName := fmt.Sprintf("readDetailPostMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := readDetailPostMw[i](&input, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadDetailMiddleware(readDetailPostMw, &input, data); err != nil { + return err } return nil @@ -249,7 +160,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { "structure": "single-data", "status": "fetched", }, - Data: pu.SafeToResponse(data), + Data: data.ToResponse(), }, nil } @@ -268,61 +179,27 @@ func Update(input e.UpdateDto) (*d.Data, error) { err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") - data, err = ReadDetailData(rdDto, tx) - if processedErr := pu.HandleReadError(err, &event, source, input.Id, data); processedErr != nil { - return processedErr + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + return err } - pl.SetLogInfo(&event, input, "started", "setUpdate") - setData(&input, data) - - for i := range updatePreMw { - mwName := fmt.Sprintf("updatePreMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := updatePreMw[i](&rdDto, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPreMw, &rdDto, data); err != nil { + return err } - pl.SetLogInfo(&event, data, "started", "DBUpdate") - if err := UpdateData(*data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-update-fail", - Detail: "Database update failed", - Raw: err, - } - return pl.SetLogError(event, data) + if err := UpdateData(input, data, &event, tx); err != nil { + return err } pl.SetLogInfo(&event, nil, "complete") - for i := range updatePostMw { - mwName := fmt.Sprintf("updatePostMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := updatePostMw[i](&rdDto, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - 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 @@ -358,58 +235,25 @@ func Delete(input e.DeleteDto) (*d.Data, error) { err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") - data, err = ReadDetailData(rdDto, tx) - if processedErr := pu.HandleReadError(err, &event, source, input.Id, data); processedErr != nil { - return processedErr + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + return err } - for i := range deletePreMw { - mwName := fmt.Sprintf("deletePreMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := deletePreMw[i](&rdDto, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunDeleteMiddleware(readDetailPreMw, &rdDto, data); err != nil { + return err } - pl.SetLogInfo(&event, data, "started", "DBDelete") - if err := DeleteData(data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-delete-fail", - Detail: "Database delete failed", - Raw: err, - } - return pl.SetLogError(event, data) + if err := DeleteData(data, &event, tx); err != nil { + return err } - pl.SetLogInfo(&event, nil, "complete") - - for i := range deletePostMw { - mwName := fmt.Sprintf("deletePostMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := deletePostMw[i](&rdDto, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunDeleteMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err } return nil diff --git a/internal/use-case/main-use-case/installation/lib.go b/internal/use-case/main-use-case/installation/lib.go index 30129aa3..05c8fac3 100644 --- a/internal/use-case/main-use-case/installation/lib.go +++ b/internal/use-case/main-use-case/installation/lib.go @@ -2,13 +2,20 @@ package installation import ( e "simrs-vx/internal/domain/main-entities/installation" + 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.Installation, dbx ...*gorm.DB) (*e.Installation, error) { +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.Installation, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.Installation{} + setData(&input, &data) + var tx *gorm.DB if len(dbx) > 0 { tx = dbx[0] @@ -16,14 +23,22 @@ func CreateData(input *e.Installation, dbx ...*gorm.DB) (*e.Installation, error) tx = dg.I } - if err := tx.Create(&input).Error; err != nil { - return nil, err + if err := tx.Create(&data).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-create-fail", + Detail: "Database insert failed", + Raw: err, + } + return nil, pl.SetLogError(event, input) } - return input, nil + pl.SetLogInfo(event, nil, "complete") + return &data, nil } -func ReadListData(input e.ReadListDto, dbx ...*gorm.DB) ([]e.Installation, *e.MetaDto, error) { +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.Installation, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") data := []e.Installation{} pagination := gh.Pagination{} count := int64(0) @@ -38,8 +53,7 @@ func ReadListData(input e.ReadListDto, dbx ...*gorm.DB) ([]e.Installation, *e.Me tx = tx. Model(&e.Installation{}). - // Joins("Patient"). // if needed - // Preload("Patient"). // if needed + Preload("Installation"). Scopes(gh.Filter(input)). Count(&count). Scopes(gh.Paginate(input, &pagination)). @@ -49,16 +63,25 @@ func ReadListData(input e.ReadListDto, dbx ...*gorm.DB) ([]e.Installation, *e.Me if err == gorm.ErrRecordNotFound { return nil, &meta, nil } - return nil, nil, err + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-create-fail", + Detail: "Database insert failed", + Raw: err, + } + return nil, nil, pl.SetLogError(event, input) } 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, dbx ...*gorm.DB) (*e.Installation, error) { +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.Installation, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") data := e.Installation{} var tx *gorm.DB @@ -69,13 +92,19 @@ func ReadDetailData(input e.ReadDetailDto, dbx ...*gorm.DB) (*e.Installation, er } if err := tx.First(&data, input.Id).Error; err != nil { - return nil, err + 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.Installation, dbx ...*gorm.DB) error { +func UpdateData(input e.UpdateDto, data *e.Installation, 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] @@ -83,10 +112,22 @@ func UpdateData(input e.Installation, dbx ...*gorm.DB) error { tx = dg.I } - return tx.Save(&input).Error + 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(input *e.Installation, dbx ...*gorm.DB) error { +func DeleteData(data *e.Installation, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBDelete") var tx *gorm.DB if len(dbx) > 0 { tx = dbx[0] @@ -94,5 +135,16 @@ func DeleteData(input *e.Installation, dbx ...*gorm.DB) error { tx = dg.I } - return tx.Delete(input).Error + 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/installation/middleware-runner.go b/internal/use-case/main-use-case/installation/middleware-runner.go new file mode 100644 index 00000000..fce572bb --- /dev/null +++ b/internal/use-case/main-use-case/installation/middleware-runner.go @@ -0,0 +1,103 @@ +package installation + +import ( + e "simrs-vx/internal/domain/main-entities/installation" + 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.Installation) 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.Installation) 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.Installation) 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.Installation) 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.Installation) 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/installation/middleware.go b/internal/use-case/main-use-case/installation/middleware.go new file mode 100644 index 00000000..3d414c9b --- /dev/null +++ b/internal/use-case/main-use-case/installation/middleware.go @@ -0,0 +1,9 @@ +package installation + +// 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/installation/tycovar.go b/internal/use-case/main-use-case/installation/tycovar.go index 072372e0..de8e9c9e 100644 --- a/internal/use-case/main-use-case/installation/tycovar.go +++ b/internal/use-case/main-use-case/installation/tycovar.go @@ -14,11 +14,23 @@ import ( e "simrs-vx/internal/domain/main-entities/installation" ) -type createMw func(input *e.CreateDto, data *e.Installation, tx *gorm.DB) error -type readListMw func(input *e.ReadListDto, data *e.Installation, tx *gorm.DB) error -type readDetailMw func(input *e.ReadDetailDto, data *e.Installation, tx *gorm.DB) error -type updateMw func(input *e.ReadDetailDto, data *e.Installation, tx *gorm.DB) error -type deleteMw func(input *e.ReadDetailDto, data *e.Installation, tx *gorm.DB) error +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.Installation, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.Installation, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.Installation, tx *gorm.DB) error +} + +type UpdateMw = readDetailMw +type DeleteMw = readDetailMw var createPreMw []createMw // preprocess middleware var createPostMw []createMw // postprocess middleware diff --git a/internal/use-case/main-use-case/province/case.go b/internal/use-case/main-use-case/province/case.go index 758f4c18..c8705614 100644 --- a/internal/use-case/main-use-case/province/case.go +++ b/internal/use-case/main-use-case/province/case.go @@ -1,7 +1,6 @@ package province import ( - "fmt" e "simrs-vx/internal/domain/main-entities/province" "strconv" @@ -19,8 +18,6 @@ const source = "province" func Create(input e.CreateDto) (*d.Data, error) { data := e.Province{} - setData(&input, &data) - event := pl.Event{ Feature: "Create", Source: source, @@ -30,51 +27,23 @@ func Create(input e.CreateDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "create") err := dg.I.Transaction(func(tx *gorm.DB) error { - for i := range createPreMw { - mwName := fmt.Sprintf("createPreMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := createPreMw[i](&input, &data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunCreateMiddleware(createPreMw, &input, &data); err != nil { + return err } - pl.SetLogInfo(&event, data, "started", "DBCreate") - _, err := CreateData(&data, tx) - if err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-create-fail", - Detail: "Database insert failed", - Raw: err, - } - return pl.SetLogError(event, data) + if resData, err := CreateData(input, &event, tx); err != nil { + return err + } else { + data = *resData } - pl.SetLogInfo(&event, nil, "complete") - - for i := range createPostMw { - mwName := fmt.Sprintf("createPostMw[%d]", i) - - pl.SetLogInfo(&event, input, "started", mwName) - if err := createPostMw[i](&input, &data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunCreateMiddleware(createPostMw, &input, &data); err != nil { + return err } pl.SetLogInfo(&event, nil, "complete") @@ -111,54 +80,21 @@ func ReadList(input e.ReadListDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "readList") err = dg.I.Transaction(func(tx *gorm.DB) error { - for i := range readListPreMw { - mwName := fmt.Sprintf("readListPreMw[%d]", i) - - pl.SetLogInfo(&event, input, "started", mwName) - - if err := readListPreMw[i](&input, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, input) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadListMiddleware(readListPreMw, &input, data); err != nil { + return err } - pl.SetLogInfo(&event, input, "started", "DBReadList") - dataList, metaList, err = ReadListData(input, tx) - if err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-read-list-fail", - Detail: "Database read list failed", - Raw: err, - } - return pl.SetLogError(event, input) + if dataList, metaList, err = ReadListData(input, &event, tx); err != nil { + return err } - pl.SetLogInfo(&event, nil, "complete") - - for i := range readListPostMw { - mwName := fmt.Sprintf("readListPostMw[%d]", i) - - pl.SetLogInfo(&event, input, "started", mwName) - - if err := readListPostMw[i](&input, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, input) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadListMiddleware(readListPostMw, &input, data); err != nil { + return err } return nil @@ -194,46 +130,21 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "readDetail") err = dg.I.Transaction(func(tx *gorm.DB) error { - for i := range readDetailPreMw { - mwName := fmt.Sprintf("readDetailPreMw[%d]", i) - - pl.SetLogInfo(&event, input, "started", mwName) - - if err := readDetailPreMw[i](&input, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, input) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadDetailMiddleware(readDetailPreMw, &input, data); err != nil { + return err } - pl.SetLogInfo(&event, input, "started", "DBReadDetail") - data, err = ReadDetailData(input, tx) - if processedErr := pu.HandleReadError(err, &event, source, input.Id, data); processedErr != nil { - return processedErr + if data, err = ReadDetailData(input, &event, tx); err != nil { + return err } - for i := range readDetailPostMw { - mwName := fmt.Sprintf("readDetailPostMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := readDetailPostMw[i](&input, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadDetailMiddleware(readDetailPostMw, &input, data); err != nil { + return err } return nil @@ -249,7 +160,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { "structure": "single-data", "status": "fetched", }, - Data: pu.SafeToResponse(data), + Data: data.ToResponse(), }, nil } @@ -268,61 +179,27 @@ func Update(input e.UpdateDto) (*d.Data, error) { err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") - data, err = ReadDetailData(rdDto, tx) - if processedErr := pu.HandleReadError(err, &event, source, input.Id, data); processedErr != nil { - return processedErr + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + return err } - pl.SetLogInfo(&event, input, "started", "setUpdate") - setData(&input, data) - - for i := range updatePreMw { - mwName := fmt.Sprintf("updatePreMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := updatePreMw[i](&rdDto, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPreMw, &rdDto, data); err != nil { + return err } - pl.SetLogInfo(&event, data, "started", "DBUpdate") - if err := UpdateData(*data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-update-fail", - Detail: "Database update failed", - Raw: err, - } - return pl.SetLogError(event, data) + if err := UpdateData(input, data, &event, tx); err != nil { + return err } pl.SetLogInfo(&event, nil, "complete") - for i := range updatePostMw { - mwName := fmt.Sprintf("updatePostMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := updatePostMw[i](&rdDto, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - 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 @@ -358,58 +235,25 @@ func Delete(input e.DeleteDto) (*d.Data, error) { err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") - data, err = ReadDetailData(rdDto, tx) - if processedErr := pu.HandleReadError(err, &event, source, input.Id, data); processedErr != nil { - return processedErr + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + return err } - for i := range deletePreMw { - mwName := fmt.Sprintf("deletePreMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := deletePreMw[i](&rdDto, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunDeleteMiddleware(readDetailPreMw, &rdDto, data); err != nil { + return err } - pl.SetLogInfo(&event, data, "started", "DBDelete") - if err := DeleteData(data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-delete-fail", - Detail: "Database delete failed", - Raw: err, - } - return pl.SetLogError(event, data) + if err := DeleteData(data, &event, tx); err != nil { + return err } - pl.SetLogInfo(&event, nil, "complete") - - for i := range deletePostMw { - mwName := fmt.Sprintf("deletePostMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := deletePostMw[i](&rdDto, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunDeleteMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err } return nil diff --git a/internal/use-case/main-use-case/province/lib.go b/internal/use-case/main-use-case/province/lib.go index df44515b..aaa53faa 100644 --- a/internal/use-case/main-use-case/province/lib.go +++ b/internal/use-case/main-use-case/province/lib.go @@ -2,13 +2,20 @@ package province import ( e "simrs-vx/internal/domain/main-entities/province" + 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.Province, dbx ...*gorm.DB) (*e.Province, error) { +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.Province, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.Province{} + setData(&input, &data) + var tx *gorm.DB if len(dbx) > 0 { tx = dbx[0] @@ -16,14 +23,22 @@ func CreateData(input *e.Province, dbx ...*gorm.DB) (*e.Province, error) { tx = dg.I } - if err := tx.Create(&input).Error; err != nil { - return nil, err + if err := tx.Create(&data).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-create-fail", + Detail: "Database insert failed", + Raw: err, + } + return nil, pl.SetLogError(event, input) } - return input, nil + pl.SetLogInfo(event, nil, "complete") + return &data, nil } -func ReadListData(input e.ReadListDto, dbx ...*gorm.DB) ([]e.Province, *e.MetaDto, error) { +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.Province, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") data := []e.Province{} pagination := gh.Pagination{} count := int64(0) @@ -38,8 +53,6 @@ func ReadListData(input e.ReadListDto, dbx ...*gorm.DB) ([]e.Province, *e.MetaDt tx = tx. Model(&e.Province{}). - // Joins("Patient"). // if needed - // Preload("Patient"). // if needed Scopes(gh.Filter(input)). Count(&count). Scopes(gh.Paginate(input, &pagination)) @@ -48,16 +61,25 @@ func ReadListData(input e.ReadListDto, dbx ...*gorm.DB) ([]e.Province, *e.MetaDt if err == gorm.ErrRecordNotFound { return nil, &meta, nil } - return nil, nil, err + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-create-fail", + Detail: "Database insert failed", + Raw: err, + } + return nil, nil, pl.SetLogError(event, input) } 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, dbx ...*gorm.DB) (*e.Province, error) { +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.Province, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") data := e.Province{} var tx *gorm.DB @@ -68,13 +90,19 @@ func ReadDetailData(input e.ReadDetailDto, dbx ...*gorm.DB) (*e.Province, error) } if err := tx.First(&data, input.Id).Error; err != nil { - return nil, err + 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.Province, dbx ...*gorm.DB) error { +func UpdateData(input e.UpdateDto, data *e.Province, 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] @@ -82,10 +110,22 @@ func UpdateData(input e.Province, dbx ...*gorm.DB) error { tx = dg.I } - return tx.Save(&input).Error + 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(input *e.Province, dbx ...*gorm.DB) error { +func DeleteData(data *e.Province, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBDelete") var tx *gorm.DB if len(dbx) > 0 { tx = dbx[0] @@ -93,5 +133,16 @@ func DeleteData(input *e.Province, dbx ...*gorm.DB) error { tx = dg.I } - return tx.Delete(input).Error + 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/province/middleware-runner.go b/internal/use-case/main-use-case/province/middleware-runner.go new file mode 100644 index 00000000..9f735d90 --- /dev/null +++ b/internal/use-case/main-use-case/province/middleware-runner.go @@ -0,0 +1,105 @@ +package province + +// pm "simrs-vx/internal/use-case/plugin/modifier" + +import ( + e "simrs-vx/internal/domain/main-entities/province" + 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.Province) 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.Province) 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.Province) 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.Province) 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.Province) 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/province/middleware.go b/internal/use-case/main-use-case/province/middleware.go new file mode 100644 index 00000000..0abd7dd9 --- /dev/null +++ b/internal/use-case/main-use-case/province/middleware.go @@ -0,0 +1,9 @@ +package province + +// 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/province/tycovar.go b/internal/use-case/main-use-case/province/tycovar.go index e65ab008..0c4349aa 100644 --- a/internal/use-case/main-use-case/province/tycovar.go +++ b/internal/use-case/main-use-case/province/tycovar.go @@ -14,11 +14,23 @@ import ( e "simrs-vx/internal/domain/main-entities/province" ) -type createMw func(input *e.CreateDto, data *e.Province, tx *gorm.DB) error -type readListMw func(input *e.ReadListDto, data *e.Province, tx *gorm.DB) error -type readDetailMw func(input *e.ReadDetailDto, data *e.Province, tx *gorm.DB) error -type updateMw func(input *e.ReadDetailDto, data *e.Province, tx *gorm.DB) error -type deleteMw func(input *e.ReadDetailDto, data *e.Province, tx *gorm.DB) error +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.Province, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.Province, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.Province, tx *gorm.DB) error +} + +type UpdateMw = readDetailMw +type DeleteMw = readDetailMw var createPreMw []createMw // preprocess middleware var createPostMw []createMw // postprocess middleware diff --git a/internal/use-case/main-use-case/regency/case.go b/internal/use-case/main-use-case/regency/case.go index deabdc4c..a0836549 100644 --- a/internal/use-case/main-use-case/regency/case.go +++ b/internal/use-case/main-use-case/regency/case.go @@ -1,7 +1,6 @@ package regency import ( - "fmt" e "simrs-vx/internal/domain/main-entities/regency" "strconv" @@ -19,8 +18,6 @@ const source = "regency" func Create(input e.CreateDto) (*d.Data, error) { data := e.Regency{} - setData(&input, &data) - event := pl.Event{ Feature: "Create", Source: source, @@ -30,51 +27,23 @@ func Create(input e.CreateDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "create") err := dg.I.Transaction(func(tx *gorm.DB) error { - for i := range createPreMw { - mwName := fmt.Sprintf("createPreMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := createPreMw[i](&input, &data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunCreateMiddleware(createPreMw, &input, &data); err != nil { + return err } - pl.SetLogInfo(&event, data, "started", "DBCreate") - _, err := CreateData(&data, tx) - if err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-create-fail", - Detail: "Database insert failed", - Raw: err, - } - return pl.SetLogError(event, data) + if resData, err := CreateData(input, &event, tx); err != nil { + return err + } else { + data = *resData } - pl.SetLogInfo(&event, nil, "complete") - - for i := range createPostMw { - mwName := fmt.Sprintf("createPostMw[%d]", i) - - pl.SetLogInfo(&event, input, "started", mwName) - if err := createPostMw[i](&input, &data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunCreateMiddleware(createPostMw, &input, &data); err != nil { + return err } pl.SetLogInfo(&event, nil, "complete") @@ -111,54 +80,21 @@ func ReadList(input e.ReadListDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "readList") err = dg.I.Transaction(func(tx *gorm.DB) error { - for i := range readListPreMw { - mwName := fmt.Sprintf("readListPreMw[%d]", i) - - pl.SetLogInfo(&event, input, "started", mwName) - - if err := readListPreMw[i](&input, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, input) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadListMiddleware(readListPreMw, &input, data); err != nil { + return err } - pl.SetLogInfo(&event, input, "started", "DBReadList") - dataList, metaList, err = ReadListData(input, tx) - if err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-read-list-fail", - Detail: "Database read list failed", - Raw: err, - } - return pl.SetLogError(event, input) + if dataList, metaList, err = ReadListData(input, &event, tx); err != nil { + return err } - pl.SetLogInfo(&event, nil, "complete") - - for i := range readListPostMw { - mwName := fmt.Sprintf("readListPostMw[%d]", i) - - pl.SetLogInfo(&event, input, "started", mwName) - - if err := readListPostMw[i](&input, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, input) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadListMiddleware(readListPostMw, &input, data); err != nil { + return err } return nil @@ -194,46 +130,21 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "readDetail") err = dg.I.Transaction(func(tx *gorm.DB) error { - for i := range readDetailPreMw { - mwName := fmt.Sprintf("readDetailPreMw[%d]", i) - - pl.SetLogInfo(&event, input, "started", mwName) - - if err := readDetailPreMw[i](&input, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, input) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadDetailMiddleware(readDetailPreMw, &input, data); err != nil { + return err } - pl.SetLogInfo(&event, input, "started", "DBReadDetail") - data, err = ReadDetailData(input, tx) - if processedErr := pu.HandleReadError(err, &event, source, input.Id, data); processedErr != nil { - return processedErr + if data, err = ReadDetailData(input, &event, tx); err != nil { + return err } - for i := range readDetailPostMw { - mwName := fmt.Sprintf("readDetailPostMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := readDetailPostMw[i](&input, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadDetailMiddleware(readDetailPostMw, &input, data); err != nil { + return err } return nil @@ -249,7 +160,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { "structure": "single-data", "status": "fetched", }, - Data: pu.SafeToResponse(data), + Data: data.ToResponse(), }, nil } @@ -268,61 +179,27 @@ func Update(input e.UpdateDto) (*d.Data, error) { err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") - data, err = ReadDetailData(rdDto, tx) - if processedErr := pu.HandleReadError(err, &event, source, input.Id, data); processedErr != nil { - return processedErr + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + return err } - pl.SetLogInfo(&event, input, "started", "setUpdate") - setData(&input, data) - - for i := range updatePreMw { - mwName := fmt.Sprintf("updatePreMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := updatePreMw[i](&rdDto, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPreMw, &rdDto, data); err != nil { + return err } - pl.SetLogInfo(&event, data, "started", "DBUpdate") - if err := UpdateData(*data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-update-fail", - Detail: "Database update failed", - Raw: err, - } - return pl.SetLogError(event, data) + if err := UpdateData(input, data, &event, tx); err != nil { + return err } pl.SetLogInfo(&event, nil, "complete") - for i := range updatePostMw { - mwName := fmt.Sprintf("updatePostMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := updatePostMw[i](&rdDto, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - 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 @@ -358,58 +235,25 @@ func Delete(input e.DeleteDto) (*d.Data, error) { err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") - data, err = ReadDetailData(rdDto, tx) - if processedErr := pu.HandleReadError(err, &event, source, input.Id, data); processedErr != nil { - return processedErr + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + return err } - for i := range deletePreMw { - mwName := fmt.Sprintf("deletePreMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := deletePreMw[i](&rdDto, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunDeleteMiddleware(readDetailPreMw, &rdDto, data); err != nil { + return err } - pl.SetLogInfo(&event, data, "started", "DBDelete") - if err := DeleteData(data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-delete-fail", - Detail: "Database delete failed", - Raw: err, - } - return pl.SetLogError(event, data) + if err := DeleteData(data, &event, tx); err != nil { + return err } - pl.SetLogInfo(&event, nil, "complete") - - for i := range deletePostMw { - mwName := fmt.Sprintf("deletePostMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := deletePostMw[i](&rdDto, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunDeleteMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err } return nil diff --git a/internal/use-case/main-use-case/regency/lib.go b/internal/use-case/main-use-case/regency/lib.go index 67bb1a17..61577d9c 100644 --- a/internal/use-case/main-use-case/regency/lib.go +++ b/internal/use-case/main-use-case/regency/lib.go @@ -2,13 +2,20 @@ package regency import ( e "simrs-vx/internal/domain/main-entities/regency" + 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.Regency, dbx ...*gorm.DB) (*e.Regency, error) { +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.Regency, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.Regency{} + setData(&input, &data) + var tx *gorm.DB if len(dbx) > 0 { tx = dbx[0] @@ -16,14 +23,22 @@ func CreateData(input *e.Regency, dbx ...*gorm.DB) (*e.Regency, error) { tx = dg.I } - if err := tx.Create(&input).Error; err != nil { - return nil, err + if err := tx.Create(&data).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-create-fail", + Detail: "Database insert failed", + Raw: err, + } + return nil, pl.SetLogError(event, input) } - return input, nil + pl.SetLogInfo(event, nil, "complete") + return &data, nil } -func ReadListData(input e.ReadListDto, dbx ...*gorm.DB) ([]e.Regency, *e.MetaDto, error) { +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.Regency, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") data := []e.Regency{} pagination := gh.Pagination{} count := int64(0) @@ -38,8 +53,6 @@ func ReadListData(input e.ReadListDto, dbx ...*gorm.DB) ([]e.Regency, *e.MetaDto tx = tx. Model(&e.Regency{}). - // Joins("Patient"). // if needed - // Preload("Patient"). // if needed Scopes(gh.Filter(input)). Count(&count). Scopes(gh.Paginate(input, &pagination)) @@ -48,16 +61,25 @@ func ReadListData(input e.ReadListDto, dbx ...*gorm.DB) ([]e.Regency, *e.MetaDto if err == gorm.ErrRecordNotFound { return nil, &meta, nil } - return nil, nil, err + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-create-fail", + Detail: "Database insert failed", + Raw: err, + } + return nil, nil, pl.SetLogError(event, input) } 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, dbx ...*gorm.DB) (*e.Regency, error) { +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.Regency, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") data := e.Regency{} var tx *gorm.DB @@ -68,13 +90,19 @@ func ReadDetailData(input e.ReadDetailDto, dbx ...*gorm.DB) (*e.Regency, error) } if err := tx.First(&data, input.Id).Error; err != nil { - return nil, err + 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.Regency, dbx ...*gorm.DB) error { +func UpdateData(input e.UpdateDto, data *e.Regency, 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] @@ -82,10 +110,22 @@ func UpdateData(input e.Regency, dbx ...*gorm.DB) error { tx = dg.I } - return tx.Save(&input).Error + 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(input *e.Regency, dbx ...*gorm.DB) error { +func DeleteData(data *e.Regency, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBDelete") var tx *gorm.DB if len(dbx) > 0 { tx = dbx[0] @@ -93,5 +133,16 @@ func DeleteData(input *e.Regency, dbx ...*gorm.DB) error { tx = dg.I } - return tx.Delete(input).Error + 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/regency/middleware-runner.go b/internal/use-case/main-use-case/regency/middleware-runner.go new file mode 100644 index 00000000..777525a3 --- /dev/null +++ b/internal/use-case/main-use-case/regency/middleware-runner.go @@ -0,0 +1,105 @@ +package regency + +// pm "simrs-vx/internal/use-case/plugin/modifier" + +import ( + e "simrs-vx/internal/domain/main-entities/regency" + 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.Regency) 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.Regency) 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.Regency) 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.Regency) 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.Regency) 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/regency/middleware.go b/internal/use-case/main-use-case/regency/middleware.go new file mode 100644 index 00000000..6b042fbd --- /dev/null +++ b/internal/use-case/main-use-case/regency/middleware.go @@ -0,0 +1,9 @@ +package regency + +// 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/regency/tycovar.go b/internal/use-case/main-use-case/regency/tycovar.go index 711d0831..fb80215c 100644 --- a/internal/use-case/main-use-case/regency/tycovar.go +++ b/internal/use-case/main-use-case/regency/tycovar.go @@ -14,11 +14,23 @@ import ( e "simrs-vx/internal/domain/main-entities/regency" ) -type createMw func(input *e.CreateDto, data *e.Regency, tx *gorm.DB) error -type readListMw func(input *e.ReadListDto, data *e.Regency, tx *gorm.DB) error -type readDetailMw func(input *e.ReadDetailDto, data *e.Regency, tx *gorm.DB) error -type updateMw func(input *e.ReadDetailDto, data *e.Regency, tx *gorm.DB) error -type deleteMw func(input *e.ReadDetailDto, data *e.Regency, tx *gorm.DB) error +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.Regency, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.Regency, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.Regency, tx *gorm.DB) error +} + +type UpdateMw = readDetailMw +type DeleteMw = readDetailMw var createPreMw []createMw // preprocess middleware var createPostMw []createMw // postprocess middleware diff --git a/internal/use-case/main-use-case/unit/case.go b/internal/use-case/main-use-case/unit/case.go index 78f86cc5..0ab8cdcb 100644 --- a/internal/use-case/main-use-case/unit/case.go +++ b/internal/use-case/main-use-case/unit/case.go @@ -1,7 +1,6 @@ package unit import ( - "fmt" e "simrs-vx/internal/domain/main-entities/unit" "strconv" @@ -19,8 +18,6 @@ const source = "unit" func Create(input e.CreateDto) (*d.Data, error) { data := e.Unit{} - setData(&input, &data) - event := pl.Event{ Feature: "Create", Source: source, @@ -30,51 +27,23 @@ func Create(input e.CreateDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "create") err := dg.I.Transaction(func(tx *gorm.DB) error { - for i := range createPreMw { - mwName := fmt.Sprintf("createPreMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := createPreMw[i](&input, &data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunCreateMiddleware(createPreMw, &input, &data); err != nil { + return err } - pl.SetLogInfo(&event, data, "started", "DBCreate") - _, err := CreateData(&data, tx) - if err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-create-fail", - Detail: "Database insert failed", - Raw: err, - } - return pl.SetLogError(event, data) + if resData, err := CreateData(input, &event, tx); err != nil { + return err + } else { + data = *resData } - pl.SetLogInfo(&event, nil, "complete") - - for i := range createPostMw { - mwName := fmt.Sprintf("createPostMw[%d]", i) - - pl.SetLogInfo(&event, input, "started", mwName) - if err := createPostMw[i](&input, &data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunCreateMiddleware(createPostMw, &input, &data); err != nil { + return err } pl.SetLogInfo(&event, nil, "complete") @@ -111,54 +80,21 @@ func ReadList(input e.ReadListDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "readList") err = dg.I.Transaction(func(tx *gorm.DB) error { - for i := range readListPreMw { - mwName := fmt.Sprintf("readListPreMw[%d]", i) - - pl.SetLogInfo(&event, input, "started", mwName) - - if err := readListPreMw[i](&input, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, input) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadListMiddleware(readListPreMw, &input, data); err != nil { + return err } - pl.SetLogInfo(&event, input, "started", "DBReadList") - dataList, metaList, err = ReadListData(input, tx) - if err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-read-list-fail", - Detail: "Database read list failed", - Raw: err, - } - return pl.SetLogError(event, input) + if dataList, metaList, err = ReadListData(input, &event, tx); err != nil { + return err } - pl.SetLogInfo(&event, nil, "complete") - - for i := range readListPostMw { - mwName := fmt.Sprintf("readListPostMw[%d]", i) - - pl.SetLogInfo(&event, input, "started", mwName) - - if err := readListPostMw[i](&input, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, input) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadListMiddleware(readListPostMw, &input, data); err != nil { + return err } return nil @@ -194,46 +130,21 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "readDetail") err = dg.I.Transaction(func(tx *gorm.DB) error { - for i := range readDetailPreMw { - mwName := fmt.Sprintf("readDetailPreMw[%d]", i) - - pl.SetLogInfo(&event, input, "started", mwName) - - if err := readDetailPreMw[i](&input, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, input) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadDetailMiddleware(readDetailPreMw, &input, data); err != nil { + return err } - pl.SetLogInfo(&event, input, "started", "DBReadDetail") - data, err = ReadDetailData(input, tx) - if processedErr := pu.HandleReadError(err, &event, source, input.Id, data); processedErr != nil { - return processedErr + if data, err = ReadDetailData(input, &event, tx); err != nil { + return err } - for i := range readDetailPostMw { - mwName := fmt.Sprintf("readDetailPostMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := readDetailPostMw[i](&input, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadDetailMiddleware(readDetailPostMw, &input, data); err != nil { + return err } return nil @@ -249,7 +160,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { "structure": "single-data", "status": "fetched", }, - Data: pu.SafeToResponse(data), + Data: data.ToResponse(), }, nil } @@ -268,61 +179,27 @@ func Update(input e.UpdateDto) (*d.Data, error) { err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") - data, err = ReadDetailData(rdDto, tx) - if processedErr := pu.HandleReadError(err, &event, source, input.Id, data); processedErr != nil { - return processedErr + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + return err } - pl.SetLogInfo(&event, input, "started", "setUpdate") - setData(&input, data) - - for i := range updatePreMw { - mwName := fmt.Sprintf("updatePreMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := updatePreMw[i](&rdDto, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPreMw, &rdDto, data); err != nil { + return err } - pl.SetLogInfo(&event, data, "started", "DBUpdate") - if err := UpdateData(*data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-update-fail", - Detail: "Database update failed", - Raw: err, - } - return pl.SetLogError(event, data) + if err := UpdateData(input, data, &event, tx); err != nil { + return err } pl.SetLogInfo(&event, nil, "complete") - for i := range updatePostMw { - mwName := fmt.Sprintf("updatePostMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := updatePostMw[i](&rdDto, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - 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 @@ -358,58 +235,25 @@ func Delete(input e.DeleteDto) (*d.Data, error) { err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") - data, err = ReadDetailData(rdDto, tx) - if processedErr := pu.HandleReadError(err, &event, source, input.Id, data); processedErr != nil { - return processedErr + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + return err } - for i := range deletePreMw { - mwName := fmt.Sprintf("deletePreMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := deletePreMw[i](&rdDto, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunDeleteMiddleware(readDetailPreMw, &rdDto, data); err != nil { + return err } - pl.SetLogInfo(&event, data, "started", "DBDelete") - if err := DeleteData(data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-delete-fail", - Detail: "Database delete failed", - Raw: err, - } - return pl.SetLogError(event, data) + if err := DeleteData(data, &event, tx); err != nil { + return err } - pl.SetLogInfo(&event, nil, "complete") - - for i := range deletePostMw { - mwName := fmt.Sprintf("deletePostMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := deletePostMw[i](&rdDto, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunDeleteMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err } return nil diff --git a/internal/use-case/main-use-case/unit/lib.go b/internal/use-case/main-use-case/unit/lib.go index ee4ddf1e..5a1776e6 100644 --- a/internal/use-case/main-use-case/unit/lib.go +++ b/internal/use-case/main-use-case/unit/lib.go @@ -2,13 +2,20 @@ package unit import ( e "simrs-vx/internal/domain/main-entities/unit" + 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.Unit, dbx ...*gorm.DB) (*e.Unit, error) { +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.Unit, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.Unit{} + setData(&input, &data) + var tx *gorm.DB if len(dbx) > 0 { tx = dbx[0] @@ -16,14 +23,22 @@ func CreateData(input *e.Unit, dbx ...*gorm.DB) (*e.Unit, error) { tx = dg.I } - if err := tx.Create(&input).Error; err != nil { - return nil, err + if err := tx.Create(&data).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-create-fail", + Detail: "Database insert failed", + Raw: err, + } + return nil, pl.SetLogError(event, input) } - return input, nil + pl.SetLogInfo(event, nil, "complete") + return &data, nil } -func ReadListData(input e.ReadListDto, dbx ...*gorm.DB) ([]e.Unit, *e.MetaDto, error) { +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.Unit, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") data := []e.Unit{} pagination := gh.Pagination{} count := int64(0) @@ -38,9 +53,7 @@ func ReadListData(input e.ReadListDto, dbx ...*gorm.DB) ([]e.Unit, *e.MetaDto, e tx = tx. Model(&e.Unit{}). - // Joins("Patient"). // if needed - // Preload("Patient"). // if needed - Preload("Installation"). // if needed + Preload("Installation"). Scopes(gh.Filter(input)). Count(&count). Scopes(gh.Paginate(input, &pagination)). @@ -50,16 +63,25 @@ func ReadListData(input e.ReadListDto, dbx ...*gorm.DB) ([]e.Unit, *e.MetaDto, e if err == gorm.ErrRecordNotFound { return nil, &meta, nil } - return nil, nil, err + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-create-fail", + Detail: "Database insert failed", + Raw: err, + } + return nil, nil, pl.SetLogError(event, input) } 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, dbx ...*gorm.DB) (*e.Unit, error) { +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.Unit, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") data := e.Unit{} var tx *gorm.DB @@ -70,13 +92,19 @@ func ReadDetailData(input e.ReadDetailDto, dbx ...*gorm.DB) (*e.Unit, error) { } if err := tx.First(&data, input.Id).Error; err != nil { - return nil, err + 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.Unit, dbx ...*gorm.DB) error { +func UpdateData(input e.UpdateDto, data *e.Unit, 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] @@ -84,10 +112,22 @@ func UpdateData(input e.Unit, dbx ...*gorm.DB) error { tx = dg.I } - return tx.Save(&input).Error + 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(input *e.Unit, dbx ...*gorm.DB) error { +func DeleteData(data *e.Unit, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBDelete") var tx *gorm.DB if len(dbx) > 0 { tx = dbx[0] @@ -95,5 +135,16 @@ func DeleteData(input *e.Unit, dbx ...*gorm.DB) error { tx = dg.I } - return tx.Delete(input).Error + 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/unit/middleware-runner.go b/internal/use-case/main-use-case/unit/middleware-runner.go new file mode 100644 index 00000000..fdce9d02 --- /dev/null +++ b/internal/use-case/main-use-case/unit/middleware-runner.go @@ -0,0 +1,103 @@ +package unit + +import ( + e "simrs-vx/internal/domain/main-entities/unit" + 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.Unit) 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.Unit) 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.Unit) 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.Unit) 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.Unit) 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/unit/middleware.go b/internal/use-case/main-use-case/unit/middleware.go new file mode 100644 index 00000000..bac48f4d --- /dev/null +++ b/internal/use-case/main-use-case/unit/middleware.go @@ -0,0 +1,9 @@ +package unit + +// 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/unit/tycovar.go b/internal/use-case/main-use-case/unit/tycovar.go index 410328d3..e1a7c69f 100644 --- a/internal/use-case/main-use-case/unit/tycovar.go +++ b/internal/use-case/main-use-case/unit/tycovar.go @@ -14,11 +14,23 @@ import ( e "simrs-vx/internal/domain/main-entities/unit" ) -type createMw func(input *e.CreateDto, data *e.Unit, tx *gorm.DB) error -type readListMw func(input *e.ReadListDto, data *e.Unit, tx *gorm.DB) error -type readDetailMw func(input *e.ReadDetailDto, data *e.Unit, tx *gorm.DB) error -type updateMw func(input *e.ReadDetailDto, data *e.Unit, tx *gorm.DB) error -type deleteMw func(input *e.ReadDetailDto, data *e.Unit, tx *gorm.DB) error +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.Unit, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.Unit, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.Unit, tx *gorm.DB) error +} + +type UpdateMw = readDetailMw +type DeleteMw = readDetailMw var createPreMw []createMw // preprocess middleware var createPostMw []createMw // postprocess middleware diff --git a/internal/use-case/main-use-case/user/case.go b/internal/use-case/main-use-case/user/case.go index c125afd0..85902fc6 100644 --- a/internal/use-case/main-use-case/user/case.go +++ b/internal/use-case/main-use-case/user/case.go @@ -18,8 +18,6 @@ const source = "user" func Create(input e.CreateDto) (*d.Data, error) { data := e.User{} - setCreate(input, &data) - event := pl.Event{ Feature: "Create", Source: source, @@ -29,31 +27,22 @@ func Create(input e.CreateDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "create") err := dg.I.Transaction(func(tx *gorm.DB) error { - executor := newMiddlewareExecutor(&event, tx) - executor.setMwtype(pu.MWTPre) - - // Execute pre-middleware - if err := executor.ExecuteCreateMiddleware(createPreMw, &input, &data); err != nil { + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunCreateMiddleware(createPreMw, &input, &data); err != nil { return err } - pl.SetLogInfo(&event, data, "started", "DBCreate") - _, err := CreateData(&data, tx) - if err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-create-fail", - Detail: "Database insert failed", - Raw: err, - } - return pl.SetLogError(event, data) + if resData, err := CreateData(input, &event, tx); err != nil { + return err + } else { + data = *resData } - pl.SetLogInfo(&event, nil, "complete") - - executor.setMwtype(pu.MWTPost) - // Execute post-middleware - if err := executor.ExecuteCreateMiddleware(createPostMw, &input, &data); err != nil { + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunCreateMiddleware(createPostMw, &input, &data); err != nil { return err } @@ -91,31 +80,20 @@ func ReadList(input e.ReadListDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "readList") err = dg.I.Transaction(func(tx *gorm.DB) error { - executor := newMiddlewareExecutor(&event, tx) - executor.setMwtype(pu.MWTPre) - - // Execute pre-middleware - if err := executor.ExecuteReadListMiddleware(readListPreMw, &input, data); err != nil { + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadListMiddleware(readListPreMw, &input, data); err != nil { return err } - pl.SetLogInfo(&event, input, "started", "DBReadList") - dataList, metaList, err = ReadListData(input, tx) - if err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-read-list-fail", - Detail: "Database read list failed", - Raw: err, - } - return pl.SetLogError(event, input) + if dataList, metaList, err = ReadListData(input, &event, tx); err != nil { + return err } - pl.SetLogInfo(&event, nil, "complete") - - executor.setMwtype(pu.MWTPost) - // Execute post-middleware - if err := executor.ExecuteReadListMiddleware(readListPostMw, &input, data); err != nil { + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadListMiddleware(readListPostMw, &input, data); err != nil { return err } @@ -152,23 +130,20 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "readDetail") err = dg.I.Transaction(func(tx *gorm.DB) error { - executor := newMiddlewareExecutor(&event, tx) - executor.setMwtype(pu.MWTPre) - - // Execute pre-middleware - if err := executor.ExecuteReadDetailMiddleware(readDetailPreMw, &input, data); err != nil { + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadDetailMiddleware(readDetailPreMw, &input, data); err != nil { return err } - pl.SetLogInfo(&event, input, "started", "DBReadDetail") - data, err = ReadDetailData(input, tx) - if processedErr := pu.HandleReadError(err, &event, source, input.Id, data); processedErr != nil { - return processedErr + if data, err = ReadDetailData(input, &event, tx); err != nil { + return err } - executor.setMwtype(pu.MWTPost) - // Execute post-middleware - if err := executor.ExecuteReadDetailMiddleware(readDetailPostMw, &input, data); err != nil { + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadDetailMiddleware(readDetailPostMw, &input, data); err != nil { return err } @@ -185,7 +160,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { "structure": "single-data", "status": "fetched", }, - Data: pu.SafeToResponse(data), + Data: data.ToResponse(), }, nil } @@ -204,49 +179,26 @@ func Update(input e.UpdateDto) (*d.Data, error) { err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") - data, err = ReadDetailData(rdDto, tx) - if processedErr := pu.HandleReadError(err, &event, source, input.Id, data); processedErr != nil { - return processedErr - } - - pl.SetLogInfo(&event, input, "started", "setUpdate") - err = setUpdate(input, data) - if err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "set-update-fail", - Detail: "Set update data failed", - Raw: err, - } - return pl.SetLogError(event, input) - } - - pl.SetLogInfo(&event, nil, "complete") - - executor := newMiddlewareExecutor(&event, tx) - executor.setMwtype(pu.MWTPre) - - // Execute pre-middleware - if err := executor.ExecuteUpdateMiddleware(readDetailPreMw, &rdDto, data); err != nil { + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { return err } - pl.SetLogInfo(&event, data, "started", "DBUpdate") - if err := UpdateData(*data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-update-fail", - Detail: "Database update failed", - Raw: err, - } - return pl.SetLogError(event, data) + 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") - executor.setMwtype(pu.MWTPost) - // Execute post-middleware - if err := executor.ExecuteUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { return err } @@ -283,35 +235,24 @@ func Delete(input e.DeleteDto) (*d.Data, error) { err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") - data, err = ReadDetailData(rdDto, tx) - if processedErr := pu.HandleReadError(err, &event, source, input.Id, data); processedErr != nil { - return processedErr - } - - executor := newMiddlewareExecutor(&event, tx) - executor.setMwtype(pu.MWTPre) - - // Execute pre-middleware - if err := executor.ExecuteDeleteMiddleware(readDetailPreMw, &rdDto, data); err != nil { + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { return err } - pl.SetLogInfo(&event, data, "started", "DBDelete") - if err := DeleteData(data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-delete-fail", - Detail: "Database delete failed", - Raw: err, - } - return pl.SetLogError(event, data) + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunDeleteMiddleware(readDetailPreMw, &rdDto, data); err != nil { + return err } - pl.SetLogInfo(&event, nil, "complete") + if err := DeleteData(data, &event, tx); err != nil { + return err + } - executor.setMwtype(pu.MWTPost) - // Execute post-middleware - if err := executor.ExecuteDeleteMiddleware(readDetailPostMw, &rdDto, data); err != nil { + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunDeleteMiddleware(readDetailPostMw, &rdDto, data); err != nil { return err } diff --git a/internal/use-case/main-use-case/user/helper.go b/internal/use-case/main-use-case/user/helper.go index 7fa1ec34..37815b51 100644 --- a/internal/use-case/main-use-case/user/helper.go +++ b/internal/use-case/main-use-case/user/helper.go @@ -5,13 +5,9 @@ Any functions that are used internally by the use-case package user import ( - "fmt" e "simrs-vx/internal/domain/main-entities/user" - pl "simrs-vx/pkg/logger" p "simrs-vx/pkg/password" - - "gorm.io/gorm" ) func setCreate(src e.CreateDto, dst *e.User) error { @@ -27,109 +23,8 @@ func setCreate(src e.CreateDto, dst *e.User) error { return nil } -func setUpdate(src e.UpdateDto, dst *e.User) error { +func setUpdate(src e.UpdateDto, dst *e.User) { dst.Name = src.Name dst.Status_Code = src.Status_Code - return nil -} - -// executeCreateMiddleware executes create middleware (pre or post) -func executeCreateMiddleware(middlewares []createMw, input *e.CreateDto, data *e.User, tx *gorm.DB, event *pl.Event, mwType string) error { - for i := range middlewares { - mwName := fmt.Sprintf("%s[%d]", mwType, i) - - pl.SetLogInfo(event, data, "started", mwName) - - if err := middlewares[i](input, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: getMiddlewareErrorCode(mwType), - Detail: fmt.Sprintf("%s middleware %s failed", getMiddlewareTypeLabel(mwType), mwName), - Raw: err, - } - return pl.SetLogError(*event, data) - } - - pl.SetLogInfo(event, nil, "complete") - } - return nil -} - -// executeReadListMiddleware executes read list middleware (pre or post) -func executeReadListMiddleware(middlewares []readListMw, input *e.ReadListDto, data *e.User, tx *gorm.DB, event *pl.Event, mwType string) error { - for i := range middlewares { - mwName := fmt.Sprintf("%s[%d]", mwType, i) - - pl.SetLogInfo(event, input, "started", mwName) - - if err := middlewares[i](input, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: getMiddlewareErrorCode(mwType), - Detail: fmt.Sprintf("%s middleware %s failed", getMiddlewareTypeLabel(mwType), mwName), - Raw: err, - } - return pl.SetLogError(*event, input) - } - - pl.SetLogInfo(event, nil, "complete") - } - return nil -} - -// executeReadDetailMiddleware executes read detail middleware (pre or post) -func executeReadDetailMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.User, tx *gorm.DB, event *pl.Event, mwType string) error { - for i := range middlewares { - mwName := fmt.Sprintf("%s[%d]", mwType, i) - - // Use data for logging if available, otherwise use input - logData := interface{}(input) - if data != nil { - logData = data - } - - pl.SetLogInfo(event, logData, "started", mwName) - - if err := middlewares[i](input, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: getMiddlewareErrorCode(mwType), - Detail: fmt.Sprintf("%s middleware %s failed", getMiddlewareTypeLabel(mwType), mwName), - Raw: err, - } - return pl.SetLogError(*event, logData) - } - - pl.SetLogInfo(event, nil, "complete") - } - return nil -} - -// Helper functions to determine error codes and labels based on middleware type -func getMiddlewareErrorCode(mwType string) string { - if containsString(mwType, "Pre") { - return "MW_PRE_FAILED" - } - return "MW_POST_FAILED" -} - -func getMiddlewareTypeLabel(mwType string) string { - if containsString(mwType, "Pre") { - return "Pre" - } - return "Post" -} - -func containsString(str, substr string) bool { - return len(str) >= len(substr) && str[len(str)-len(substr):] != substr && - (len(str) == len(substr) || str[len(str)-len(substr)-1:len(str)-len(substr)] != substr) && - func() bool { - for i := 0; i <= len(str)-len(substr); i++ { - if str[i:i+len(substr)] == substr { - return true - } - } - return false - }() } diff --git a/internal/use-case/main-use-case/user/lib.go b/internal/use-case/main-use-case/user/lib.go index c767bdf1..40ad6e17 100644 --- a/internal/use-case/main-use-case/user/lib.go +++ b/internal/use-case/main-use-case/user/lib.go @@ -2,13 +2,20 @@ package user import ( e "simrs-vx/internal/domain/main-entities/user" + 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.User, dbx ...*gorm.DB) (*e.User, error) { +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.User, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.User{} + setCreate(input, &data) + var tx *gorm.DB if len(dbx) > 0 { tx = dbx[0] @@ -16,14 +23,22 @@ func CreateData(input *e.User, dbx ...*gorm.DB) (*e.User, error) { tx = dg.I } - if err := tx.Create(&input).Error; err != nil { - return nil, err + if err := tx.Create(&data).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-create-fail", + Detail: "Database insert failed", + Raw: err, + } + return nil, pl.SetLogError(event, input) } - return input, nil + pl.SetLogInfo(event, nil, "complete") + return &data, nil } -func ReadListData(input e.ReadListDto, dbx ...*gorm.DB) ([]e.User, *e.MetaDto, error) { +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.User, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") data := []e.User{} pagination := gh.Pagination{} count := int64(0) @@ -38,8 +53,6 @@ func ReadListData(input e.ReadListDto, dbx ...*gorm.DB) ([]e.User, *e.MetaDto, e tx = tx. Model(&e.User{}). - // Joins("Patient"). // if needed - // Preload("Patient"). // if needed Scopes(gh.Filter(input)). Count(&count). Scopes(gh.Paginate(input, &pagination)). @@ -49,16 +62,25 @@ func ReadListData(input e.ReadListDto, dbx ...*gorm.DB) ([]e.User, *e.MetaDto, e if err == gorm.ErrRecordNotFound { return nil, &meta, nil } - return nil, nil, err + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-create-fail", + Detail: "Database insert failed", + Raw: err, + } + return nil, nil, pl.SetLogError(event, input) } 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, dbx ...*gorm.DB) (*e.User, error) { +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.User, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") data := e.User{} var tx *gorm.DB @@ -69,13 +91,19 @@ func ReadDetailData(input e.ReadDetailDto, dbx ...*gorm.DB) (*e.User, error) { } if err := tx.First(&data, input.Id).Error; err != nil { - return nil, err + 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.User, dbx ...*gorm.DB) error { +func UpdateData(input e.UpdateDto, data *e.User, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBUpdate") + setUpdate(input, data) + var tx *gorm.DB if len(dbx) > 0 { tx = dbx[0] @@ -83,10 +111,22 @@ func UpdateData(input e.User, dbx ...*gorm.DB) error { tx = dg.I } - return tx.Save(&input).Error + 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(input *e.User, dbx ...*gorm.DB) error { +func DeleteData(data *e.User, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBDelete") var tx *gorm.DB if len(dbx) > 0 { tx = dbx[0] @@ -94,5 +134,16 @@ func DeleteData(input *e.User, dbx ...*gorm.DB) error { tx = dg.I } - return tx.Delete(input).Error + 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/user/middleware-runner.go b/internal/use-case/main-use-case/user/middleware-runner.go new file mode 100644 index 00000000..89b61c74 --- /dev/null +++ b/internal/use-case/main-use-case/user/middleware-runner.go @@ -0,0 +1,103 @@ +package user + +import ( + e "simrs-vx/internal/domain/main-entities/user" + 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.User) 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.User) 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.User) 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.User) 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.User) 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/user/middleware.go b/internal/use-case/main-use-case/user/middleware.go index 208468b6..6cf33b97 100644 --- a/internal/use-case/main-use-case/user/middleware.go +++ b/internal/use-case/main-use-case/user/middleware.go @@ -1,159 +1,9 @@ package user -// pm "simrs-vx/internal/use-case/plugin/modifier" - -import ( - "fmt" - e "simrs-vx/internal/domain/main-entities/user" - pl "simrs-vx/pkg/logger" - pu "simrs-vx/pkg/use-case-helper" - - "gorm.io/gorm" -) - +// example of middleware // func init() { -// createPreMw = append(createPreMw, pm.ModifInput) -// createPreMw = append(createPreMw, pm.CheckData) +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) // } - -type middlewareExecutor struct { - Event *pl.Event - Tx *gorm.DB - MwType pu.MWType -} - -// NewMiddlewareExecutor creates a new middleware executor -func newMiddlewareExecutor(event *pl.Event, tx *gorm.DB) *middlewareExecutor { - return &middlewareExecutor{ - Event: event, - Tx: tx, - } -} - -// ExecuteCreateMiddleware executes create middleware -func (me *middlewareExecutor) ExecuteCreateMiddleware(middlewares []createMw, input *e.CreateDto, data *e.User) error { - for i, middleware := range middlewares { - mwName := fmt.Sprintf("%s[%d]", me.MwType, i) - - pl.SetLogInfo(me.Event, data, "started", mwName) - - if err := middleware(input, data, me.Tx); err != nil { - me.Event.Status = "failed" - me.Event.ErrInfo = pl.ErrorInfo{ - Code: pu.GetMiddlewareErrorCode(me.MwType), - Detail: fmt.Sprintf("%s middleware %s failed", me.MwType, mwName), - Raw: err, - } - return pl.SetLogError(*me.Event, data) - } - - pl.SetLogInfo(me.Event, nil, "complete") - } - return nil -} - -func (me *middlewareExecutor) ExecuteReadListMiddleware(middlewares []readListMw, input *e.ReadListDto, data *e.User) error { - for i, middleware := range middlewares { - mwName := fmt.Sprintf("%s[%d]", me.MwType, i) - - pl.SetLogInfo(me.Event, input, "started", mwName) - - if err := middleware(input, data, me.Tx); err != nil { - me.Event.Status = "failed" - me.Event.ErrInfo = pl.ErrorInfo{ - Code: pu.GetMiddlewareErrorCode(me.MwType), - Detail: fmt.Sprintf("%s middleware %s failed", me.MwType, mwName), - Raw: err, - } - return pl.SetLogError(*me.Event, input) - } - - pl.SetLogInfo(me.Event, nil, "complete") - } - return nil -} - -func (me *middlewareExecutor) ExecuteReadDetailMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.User) error { - for i, middleware := range middlewares { - mwName := fmt.Sprintf("%s[%d]", me.MwType, i) - - // Use data for logging if available, otherwise use input - logData := interface{}(input) - if data != nil { - logData = data - } - - pl.SetLogInfo(me.Event, logData, "started", mwName) - - if err := middleware(input, data, me.Tx); err != nil { - me.Event.Status = "failed" - me.Event.ErrInfo = pl.ErrorInfo{ - Code: pu.GetMiddlewareErrorCode(me.MwType), - Detail: fmt.Sprintf("%s middleware %s failed", me.MwType, mwName), - Raw: err, - } - return pl.SetLogError(*me.Event, logData) - } - - pl.SetLogInfo(me.Event, nil, "complete") - } - return nil -} - -func (me *middlewareExecutor) ExecuteUpdateMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.User) error { - for i, middleware := range middlewares { - mwName := fmt.Sprintf("%s[%d]", me.MwType, i) - - // Use data for logging if available, otherwise use input - logData := interface{}(input) - if data != nil { - logData = data - } - - pl.SetLogInfo(me.Event, logData, "started", mwName) - - if err := middleware(input, data, me.Tx); err != nil { - me.Event.Status = "failed" - me.Event.ErrInfo = pl.ErrorInfo{ - Code: pu.GetMiddlewareErrorCode(me.MwType), - Detail: fmt.Sprintf("%s middleware %s failed", me.MwType, mwName), - Raw: err, - } - return pl.SetLogError(*me.Event, logData) - } - - pl.SetLogInfo(me.Event, nil, "complete") - } - return nil -} - -func (me *middlewareExecutor) ExecuteDeleteMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.User) error { - for i, middleware := range middlewares { - mwName := fmt.Sprintf("%s[%d]", me.MwType, i) - - // Use data for logging if available, otherwise use input - logData := interface{}(input) - if data != nil { - logData = data - } - - pl.SetLogInfo(me.Event, logData, "started", mwName) - - if err := middleware(input, data, me.Tx); err != nil { - me.Event.Status = "failed" - me.Event.ErrInfo = pl.ErrorInfo{ - Code: pu.GetMiddlewareErrorCode(me.MwType), - Detail: fmt.Sprintf("%s middleware %s failed", me.MwType, mwName), - Raw: err, - } - return pl.SetLogError(*me.Event, logData) - } - - pl.SetLogInfo(me.Event, nil, "complete") - } - return nil -} - -func (me *middlewareExecutor) setMwtype(mwType pu.MWType) { - me.MwType = mwType -} diff --git a/internal/use-case/main-use-case/user/tycovar.go b/internal/use-case/main-use-case/user/tycovar.go index e8d564df..1fc948e4 100644 --- a/internal/use-case/main-use-case/user/tycovar.go +++ b/internal/use-case/main-use-case/user/tycovar.go @@ -14,11 +14,23 @@ import ( e "simrs-vx/internal/domain/main-entities/user" ) -type createMw func(input *e.CreateDto, data *e.User, tx *gorm.DB) error -type readListMw func(input *e.ReadListDto, data *e.User, tx *gorm.DB) error -type readDetailMw func(input *e.ReadDetailDto, data *e.User, tx *gorm.DB) error -type updateMw func(input *e.ReadDetailDto, data *e.User, tx *gorm.DB) error -type deleteMw func(input *e.ReadDetailDto, data *e.User, tx *gorm.DB) error +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.User, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.User, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.User, tx *gorm.DB) error +} + +type UpdateMw = readDetailMw +type DeleteMw = readDetailMw var createPreMw []createMw // preprocess middleware var createPostMw []createMw // postprocess middleware diff --git a/internal/use-case/main-use-case/village/case.go b/internal/use-case/main-use-case/village/case.go index dbcc501a..dbdeb33d 100644 --- a/internal/use-case/main-use-case/village/case.go +++ b/internal/use-case/main-use-case/village/case.go @@ -1,7 +1,6 @@ package village import ( - "fmt" e "simrs-vx/internal/domain/main-entities/village" "strconv" @@ -19,8 +18,6 @@ const source = "village" func Create(input e.CreateDto) (*d.Data, error) { data := e.Village{} - setData(&input, &data) - event := pl.Event{ Feature: "Create", Source: source, @@ -30,51 +27,23 @@ func Create(input e.CreateDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "create") err := dg.I.Transaction(func(tx *gorm.DB) error { - for i := range createPreMw { - mwName := fmt.Sprintf("createPreMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := createPreMw[i](&input, &data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunCreateMiddleware(createPreMw, &input, &data); err != nil { + return err } - pl.SetLogInfo(&event, data, "started", "DBCreate") - _, err := CreateData(&data, tx) - if err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-create-fail", - Detail: "Database insert failed", - Raw: err, - } - return pl.SetLogError(event, data) + if resData, err := CreateData(input, &event, tx); err != nil { + return err + } else { + data = *resData } - pl.SetLogInfo(&event, nil, "complete") - - for i := range createPostMw { - mwName := fmt.Sprintf("createPostMw[%d]", i) - - pl.SetLogInfo(&event, input, "started", mwName) - if err := createPostMw[i](&input, &data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunCreateMiddleware(createPostMw, &input, &data); err != nil { + return err } pl.SetLogInfo(&event, nil, "complete") @@ -111,54 +80,21 @@ func ReadList(input e.ReadListDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "readList") err = dg.I.Transaction(func(tx *gorm.DB) error { - for i := range readListPreMw { - mwName := fmt.Sprintf("readListPreMw[%d]", i) - - pl.SetLogInfo(&event, input, "started", mwName) - - if err := readListPreMw[i](&input, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, input) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadListMiddleware(readListPreMw, &input, data); err != nil { + return err } - pl.SetLogInfo(&event, input, "started", "DBReadList") - dataList, metaList, err = ReadListData(input, tx) - if err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-read-list-fail", - Detail: "Database read list failed", - Raw: err, - } - return pl.SetLogError(event, input) + if dataList, metaList, err = ReadListData(input, &event, tx); err != nil { + return err } - pl.SetLogInfo(&event, nil, "complete") - - for i := range readListPostMw { - mwName := fmt.Sprintf("readListPostMw[%d]", i) - - pl.SetLogInfo(&event, input, "started", mwName) - - if err := readListPostMw[i](&input, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, input) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadListMiddleware(readListPostMw, &input, data); err != nil { + return err } return nil @@ -194,46 +130,21 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { pl.SetLogInfo(&event, input, "started", "readDetail") err = dg.I.Transaction(func(tx *gorm.DB) error { - for i := range readDetailPreMw { - mwName := fmt.Sprintf("readDetailPreMw[%d]", i) - - pl.SetLogInfo(&event, input, "started", mwName) - - if err := readDetailPreMw[i](&input, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, input) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadDetailMiddleware(readDetailPreMw, &input, data); err != nil { + return err } - pl.SetLogInfo(&event, input, "started", "DBReadDetail") - data, err = ReadDetailData(input, tx) - if processedErr := pu.HandleReadError(err, &event, source, input.Id, data); processedErr != nil { - return processedErr + if data, err = ReadDetailData(input, &event, tx); err != nil { + return err } - for i := range readDetailPostMw { - mwName := fmt.Sprintf("readDetailPostMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := readDetailPostMw[i](&input, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadDetailMiddleware(readDetailPostMw, &input, data); err != nil { + return err } return nil @@ -249,7 +160,7 @@ func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { "structure": "single-data", "status": "fetched", }, - Data: pu.SafeToResponse(data), + Data: data.ToResponse(), }, nil } @@ -268,61 +179,27 @@ func Update(input e.UpdateDto) (*d.Data, error) { err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") - data, err = ReadDetailData(rdDto, tx) - if processedErr := pu.HandleReadError(err, &event, source, input.Id, data); processedErr != nil { - return processedErr + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + return err } - pl.SetLogInfo(&event, input, "started", "setUpdate") - setData(&input, data) - - for i := range updatePreMw { - mwName := fmt.Sprintf("updatePreMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := updatePreMw[i](&rdDto, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPreMw, &rdDto, data); err != nil { + return err } - pl.SetLogInfo(&event, data, "started", "DBUpdate") - if err := UpdateData(*data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-update-fail", - Detail: "Database update failed", - Raw: err, - } - return pl.SetLogError(event, data) + if err := UpdateData(input, data, &event, tx); err != nil { + return err } pl.SetLogInfo(&event, nil, "complete") - for i := range updatePostMw { - mwName := fmt.Sprintf("updatePostMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := updatePostMw[i](&rdDto, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - 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 @@ -358,66 +235,25 @@ func Delete(input e.DeleteDto) (*d.Data, error) { err = dg.I.Transaction(func(tx *gorm.DB) error { pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") - data, err = ReadDetailData(rdDto, tx) - if err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-read-detail-fail", - Detail: "Database read detail failed", - Raw: err, - } - return pl.SetLogError(event, rdDto) + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + return err } - pl.SetLogInfo(&event, nil, "complete") - - for i := range deletePreMw { - mwName := fmt.Sprintf("deletePreMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := deletePreMw[i](&rdDto, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_PRE_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Pre-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunDeleteMiddleware(readDetailPreMw, &rdDto, data); err != nil { + return err } - pl.SetLogInfo(&event, data, "started", "DBDelete") - if err := DeleteData(data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "data-delete-fail", - Detail: "Database delete failed", - Raw: err, - } - return pl.SetLogError(event, data) + if err := DeleteData(data, &event, tx); err != nil { + return err } - pl.SetLogInfo(&event, nil, "complete") - - for i := range deletePostMw { - mwName := fmt.Sprintf("deletePostMw[%d]", i) - - pl.SetLogInfo(&event, data, "started", mwName) - - if err := deletePostMw[i](&rdDto, data, tx); err != nil { - event.Status = "failed" - event.ErrInfo = pl.ErrorInfo{ - Code: "MW_POST_FAILED", // TODO: add to lang json - Detail: fmt.Sprintf("Post-middleware %s failed", mwName), - Raw: err, - } - return pl.SetLogError(event, data) - } - - pl.SetLogInfo(&event, nil, "complete") + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunDeleteMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err } return nil diff --git a/internal/use-case/main-use-case/village/lib.go b/internal/use-case/main-use-case/village/lib.go index aec8e05a..154f1fb9 100644 --- a/internal/use-case/main-use-case/village/lib.go +++ b/internal/use-case/main-use-case/village/lib.go @@ -2,13 +2,20 @@ package village import ( e "simrs-vx/internal/domain/main-entities/village" + 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.Village, dbx ...*gorm.DB) (*e.Village, error) { +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.Village, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.Village{} + setData(&input, &data) + var tx *gorm.DB if len(dbx) > 0 { tx = dbx[0] @@ -16,14 +23,22 @@ func CreateData(input *e.Village, dbx ...*gorm.DB) (*e.Village, error) { tx = dg.I } - if err := tx.Create(&input).Error; err != nil { - return nil, err + if err := tx.Create(&data).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-create-fail", + Detail: "Database insert failed", + Raw: err, + } + return nil, pl.SetLogError(event, input) } - return input, nil + pl.SetLogInfo(event, nil, "complete") + return &data, nil } -func ReadListData(input e.ReadListDto, dbx ...*gorm.DB) ([]e.Village, *e.MetaDto, error) { +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.Village, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") data := []e.Village{} pagination := gh.Pagination{} count := int64(0) @@ -38,8 +53,6 @@ func ReadListData(input e.ReadListDto, dbx ...*gorm.DB) ([]e.Village, *e.MetaDto tx = tx. Model(&e.Village{}). - // Joins("Patient"). // if needed - // Preload("Patient"). // if needed Scopes(gh.Filter(input)). Count(&count). Scopes(gh.Paginate(input, &pagination)) @@ -48,16 +61,25 @@ func ReadListData(input e.ReadListDto, dbx ...*gorm.DB) ([]e.Village, *e.MetaDto if err == gorm.ErrRecordNotFound { return nil, &meta, nil } - return nil, nil, err + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-create-fail", + Detail: "Database insert failed", + Raw: err, + } + return nil, nil, pl.SetLogError(event, input) } 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, dbx ...*gorm.DB) (*e.Village, error) { +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.Village, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") data := e.Village{} var tx *gorm.DB @@ -68,13 +90,19 @@ func ReadDetailData(input e.ReadDetailDto, dbx ...*gorm.DB) (*e.Village, error) } if err := tx.First(&data, input.Id).Error; err != nil { - return nil, err + 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.Village, dbx ...*gorm.DB) error { +func UpdateData(input e.UpdateDto, data *e.Village, 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] @@ -82,10 +110,22 @@ func UpdateData(input e.Village, dbx ...*gorm.DB) error { tx = dg.I } - return tx.Save(&input).Error + 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(input *e.Village, dbx ...*gorm.DB) error { +func DeleteData(data *e.Village, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBDelete") var tx *gorm.DB if len(dbx) > 0 { tx = dbx[0] @@ -93,5 +133,16 @@ func DeleteData(input *e.Village, dbx ...*gorm.DB) error { tx = dg.I } - return tx.Delete(input).Error + 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/village/middleware-runner.go b/internal/use-case/main-use-case/village/middleware-runner.go new file mode 100644 index 00000000..db1d2c0c --- /dev/null +++ b/internal/use-case/main-use-case/village/middleware-runner.go @@ -0,0 +1,103 @@ +package village + +import ( + e "simrs-vx/internal/domain/main-entities/village" + 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.Village) 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.Village) 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.Village) 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.Village) 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.Village) 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/village/middleware.go b/internal/use-case/main-use-case/village/middleware.go new file mode 100644 index 00000000..3a113862 --- /dev/null +++ b/internal/use-case/main-use-case/village/middleware.go @@ -0,0 +1,9 @@ +package village + +// 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/village/tycovar.go b/internal/use-case/main-use-case/village/tycovar.go index e1aa31c5..0ca1b412 100644 --- a/internal/use-case/main-use-case/village/tycovar.go +++ b/internal/use-case/main-use-case/village/tycovar.go @@ -14,11 +14,23 @@ import ( e "simrs-vx/internal/domain/main-entities/village" ) -type createMw func(input *e.CreateDto, data *e.Village, tx *gorm.DB) error -type readListMw func(input *e.ReadListDto, data *e.Village, tx *gorm.DB) error -type readDetailMw func(input *e.ReadDetailDto, data *e.Village, tx *gorm.DB) error -type updateMw func(input *e.ReadDetailDto, data *e.Village, tx *gorm.DB) error -type deleteMw func(input *e.ReadDetailDto, data *e.Village, tx *gorm.DB) error +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.Village, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.Village, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.Village, tx *gorm.DB) error +} + +type UpdateMw = readDetailMw +type DeleteMw = readDetailMw var createPreMw []createMw // preprocess middleware var createPostMw []createMw // postprocess middleware diff --git a/pkg/logger/logger.go b/pkg/logger/logger.go index 73f884bd..8666e56b 100644 --- a/pkg/logger/logger.go +++ b/pkg/logger/logger.go @@ -49,7 +49,7 @@ func SetLogInfo(e *Event, data any, args ...string) { Send() } -func SetLogError(e Event, data any) error { +func SetLogError(e *Event, data any) error { dataString, _ := json.Marshal(data) msg := l.I.Msg(e.ErrInfo.Code) diff --git a/pkg/use-case-helper/use-case-helper.go b/pkg/use-case-helper/use-case-helper.go index 999bc732..b88db3b4 100644 --- a/pkg/use-case-helper/use-case-helper.go +++ b/pkg/use-case-helper/use-case-helper.go @@ -20,6 +20,10 @@ func SafeToResponse[T any](data *T) any { return converter.ToResponse() } + if converter, ok := any(*data).(interface{ ToResponse() any }); ok { + return converter.ToResponse() + } + return nil } @@ -45,7 +49,7 @@ func HandleReadError(err error, event *pl.Event, itemType string, id interface{} } } - return pl.SetLogError(*event, nil) + return pl.SetLogError(event, nil) } func GetMiddlewareErrorCode(mwType MWType) string { @@ -54,3 +58,21 @@ func GetMiddlewareErrorCode(mwType MWType) string { } return "MW_POST_FAILED" } + +// GetLogData returns whichever of data or input is non-nil (prefers data) +func GetLogData(input interface{}, data interface{}) interface{} { + if data != nil { + return data + } + return input +} + +func HandleMiddlewareError(event *pl.Event, mwType, mwName string, logData interface{}, err error) error { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: GetMiddlewareErrorCode(MWType(mwType)), + Detail: fmt.Sprintf("%s middleware %s failed", mwType, mwName), + Raw: err, + } + return pl.SetLogError(event, logData) +}