From 34b79e6472a12dc31d8b8cce61849bdfea6043ab Mon Sep 17 00:00:00 2001 From: vanilia Date: Mon, 17 Nov 2025 12:06:09 +0700 Subject: [PATCH] on going division --- .../simgos-sync-handler/division/handler.go | 66 ++++++ .../simgos-sync-handler.go | 20 +- .../simgos-sync-plugin/division/plugin.go | 153 +++++++++++++ .../simgos-sync-use-case/division/case.go | 214 ++++++++++++++++++ .../simgos-sync-use-case/division/helper.go | 58 +++++ .../simgos-sync-use-case/division/lib.go | 188 +++++++++++++++ .../division/middleware-runner.go | 104 +++++++++ .../division/middleware.go | 9 + .../simgos-sync-use-case/division/tycovar.go | 44 ++++ .../simgos-sync-use-case/installation/case.go | 5 +- .../installation/helper.go | 4 +- .../simgos-sync-use-case/installation/lib.go | 2 +- .../handler-crud-helper.go | 33 +++ pkg/handler-crud-helper/types.go | 7 + 14 files changed, 886 insertions(+), 21 deletions(-) create mode 100644 internal/interface/simgos-sync-handler/division/handler.go create mode 100644 internal/use-case/simgos-sync-plugin/division/plugin.go create mode 100644 internal/use-case/simgos-sync-use-case/division/case.go create mode 100644 internal/use-case/simgos-sync-use-case/division/helper.go create mode 100644 internal/use-case/simgos-sync-use-case/division/lib.go create mode 100644 internal/use-case/simgos-sync-use-case/division/middleware-runner.go create mode 100644 internal/use-case/simgos-sync-use-case/division/middleware.go create mode 100644 internal/use-case/simgos-sync-use-case/division/tycovar.go diff --git a/internal/interface/simgos-sync-handler/division/handler.go b/internal/interface/simgos-sync-handler/division/handler.go new file mode 100644 index 00000000..0f87ca8a --- /dev/null +++ b/internal/interface/simgos-sync-handler/division/handler.go @@ -0,0 +1,66 @@ +package division + +import ( + "net/http" + + rw "github.com/karincake/risoles" + // ua "github.com/karincake/tumpeng/auth/svc" + + e "simrs-vx/internal/domain/main-entities/division" + esync "simrs-vx/internal/domain/sync-entities/log" + u "simrs-vx/internal/use-case/simgos-sync-use-case/division" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.CreateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) CreateLog(w http.ResponseWriter, r *http.Request) { + dto := esync.SimxLogDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.CreateSimxLog(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + + val := uint16(id) + dto.Id = &val + + res, err := u.Update(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.DeleteDto{} + val := uint16(id) + dto.Id = &val + + res, err := u.Delete(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/simgos-sync-handler/simgos-sync-handler.go b/internal/interface/simgos-sync-handler/simgos-sync-handler.go index 3b1908a9..590d7b9d 100644 --- a/internal/interface/simgos-sync-handler/simgos-sync-handler.go +++ b/internal/interface/simgos-sync-handler/simgos-sync-handler.go @@ -2,6 +2,7 @@ package simgossynchandler import ( "net/http" + hc "simrs-vx/pkg/handler-crud-helper" /******************** infra ********************/ gs "simrs-vx/internal/infra/gorm-setting" @@ -14,10 +15,9 @@ import ( /******************** external ********************/ a "github.com/karincake/apem" - hk "github.com/karincake/hongkue" - /******************** internal ********************/ "simrs-vx/internal/interface/main-handler/home" + division "simrs-vx/internal/interface/simgos-sync-handler/division" installation "simrs-vx/internal/interface/simgos-sync-handler/installation" unit "simrs-vx/internal/interface/simgos-sync-handler/unit" ) @@ -36,19 +36,9 @@ func SetRoutes() http.Handler { /******************** Source ******************/ prefix := "/new-to-old" - hk.GroupRoutes(prefix+"/v1/installation", r, hk.MapHandlerFunc{ - "POST /": installation.O.Create, - "POST /log": installation.O.CreateLog, - "PATCH /{id}": installation.O.Update, - "DELETE /{id}": installation.O.Delete, - }) - - hk.GroupRoutes(prefix+"/v1/unit", r, hk.MapHandlerFunc{ - "POST /": unit.O.Create, - "POST /log": unit.O.CreateLog, - "PATCH /{id}": unit.O.Update, - "DELETE /{id}": unit.O.Delete, - }) + hc.SyncCrud(r, prefix+"/v1/installation", installation.O) + hc.SyncCrud(r, prefix+"/v1/unit", unit.O) + hc.SyncCrud(r, prefix+"/v1/division", division.O) return cmw.SetCors(handlerlogger.SetLog(r)) } diff --git a/internal/use-case/simgos-sync-plugin/division/plugin.go b/internal/use-case/simgos-sync-plugin/division/plugin.go new file mode 100644 index 00000000..06e54e31 --- /dev/null +++ b/internal/use-case/simgos-sync-plugin/division/plugin.go @@ -0,0 +1,153 @@ +package division + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" + + sync "simrs-vx/internal/infra/sync-cfg" + + e "simrs-vx/internal/domain/main-entities/unit" + elog "simrs-vx/internal/domain/sync-entities/log" +) + +func Create(input *e.CreateDto) error { + endpoint := getPrefixEndpoint() + + jsonData, err := json.Marshal(input) + if err != nil { + return fmt.Errorf("failed to encode JSON: %w", err) + } + + req, err := http.NewRequest("POST", endpoint, bytes.NewReader(jsonData)) + if err != nil { + return err + } + + req.Header.Set("Content-Type", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf(resp.Status) + } + + _, err = io.ReadAll(resp.Body) + if err != nil { + return err + } + + return nil +} + +func CreateLog(input *elog.SimxLogDto) error { + prefixEndpoint := getPrefixEndpoint() + endpoint := prefixEndpoint + "/log" + + jsonData, err := json.Marshal(input) + if err != nil { + return fmt.Errorf("failed to encode JSON: %w", err) + } + + req, err := http.NewRequest("POST", endpoint, bytes.NewReader(jsonData)) + if err != nil { + return err + } + + req.Header.Set("Content-Type", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf(resp.Status) + } + + _, err = io.ReadAll(resp.Body) + if err != nil { + return err + } + + return nil +} + +func Update(input *e.UpdateDto) error { + prefixEndpoint := getPrefixEndpoint() + endpoint := fmt.Sprintf("%s/%v", prefixEndpoint, *input.Id) + + jsonData, err := json.Marshal(input) + if err != nil { + return fmt.Errorf("failed to encode JSON: %w", err) + } + + req, err := http.NewRequest("PATCH", endpoint, bytes.NewReader(jsonData)) + if err != nil { + return err + } + + req.Header.Set("Content-Type", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf(resp.Status) + } + + _, err = io.ReadAll(resp.Body) + if err != nil { + return err + } + + return nil +} + +func Delete(input *e.DeleteDto) error { + prefixEndpoint := getPrefixEndpoint() + endpoint := fmt.Sprintf("%s/%v", prefixEndpoint, *input.Id) + + jsonData, err := json.Marshal(input) + if err != nil { + return fmt.Errorf("failed to encode JSON: %w", err) + } + + req, err := http.NewRequest("DELETE", endpoint, bytes.NewReader(jsonData)) + if err != nil { + return err + } + + req.Header.Set("Content-Type", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf(resp.Status) + } + + _, err = io.ReadAll(resp.Body) + if err != nil { + return err + } + + return nil +} + +func getPrefixEndpoint() string { + return fmt.Sprintf("%s%s/v1/division", sync.O.Host, sync.O.Prefix) +} diff --git a/internal/use-case/simgos-sync-use-case/division/case.go b/internal/use-case/simgos-sync-use-case/division/case.go new file mode 100644 index 00000000..074bf2a7 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/division/case.go @@ -0,0 +1,214 @@ +package division + +import ( + pl "simrs-vx/pkg/logger" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/division" + esync "simrs-vx/internal/domain/sync-entities/log" + //esimgos "simrs-vx/internal/domain/simgos-entities/installation" +) + +const source = "division" + +func Create(input e.CreateDto) (*d.Data, error) { + //var ( + // txSync = dg.I.Begin() + // txSimgos = dg.IS["simrs"].Begin() + //) + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + // STEP 1: Insert to simgos + //sgData, err := CreateSimgosData(input, &event, txSimgos) + //if err != nil { + // return nil, err + //} + // + //// STEP 2: Insert to Link + //syncLink, err := CreateLinkData(*input.Id, sgData.Kode, &event, txSync) + //if err != nil { + // txSimgos.Rollback() + // return nil, err + //} + // + //// STEP 3: Commit two trx + //if err = txSync.Commit().Error; err != nil { + // txSync.Rollback() + // txSimgos.Rollback() + // return nil, err + //} + // + //if err = txSimgos.Commit().Error; err != nil { + // // STEP 4: Rollback Partial + // go func() { + // _ = DeleteLinkData(syncLink, &event) + // }() + // return nil, err + //} + + pl.SetLogInfo(&event, nil, "complete") + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + }, nil +} + +func CreateSimxLog(input esync.SimxLogDto) (*d.Data, error) { + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + err := dg.I.Transaction(func(tx *gorm.DB) error { + // InsertSimxLog + if err := CreateLogData(input, &event, tx); err != nil { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + pl.SetLogInfo(&event, nil, "complete") + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + }, nil +} + +func Update(input e.UpdateDto) (*d.Data, error) { + //var ( + // txSimgos = dg.IS["simrs"].Begin() + // err error + //) + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + //// STEP 1: Get Installation Link + //syncLink, err := ReadDetailLinkData(*input.Id, &event) + //if err != nil { + // return nil, err + //} + // + //// Step 2: Update Simgos + //err = UpdateSimgosData(input, syncLink, &event, txSimgos) + //if err != nil { + // return nil, err + //} + // + //// STEP 4: Commit two trx + //if err = txSimgos.Commit().Error; err != nil { + // txSimgos.Rollback() + // return nil, err + //} + + pl.SetLogInfo(&event, nil, "complete") + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + }, nil +} + +func Delete(input e.DeleteDto) (*d.Data, error) { + //var ( + // txSync = dg.I.Begin() + // txSimgos = dg.IS["simrs"].Begin() + // sgData *esimgos.MPloy + // err error + //) + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + //// STEP 1: Get Installation Link + //syncLink, err := ReadDetailLinkData(*input.Id, &event) + //if err != nil { + // return nil, err + //} + // + //// STEP 2: Get Simgos + //sgData, err = ReadDetailSimgosData(uint16(syncLink.Simgos_Id), &event) + //if err != nil { + // return nil, err + //} + // + //// STEP 3: Delete M_Poly Simgos + //err = HardDeleteSimgosData(sgData, &event, txSimgos) + //if err != nil { + // return nil, err + //} + // + //// STEP 4: Delete Installation Link + //err = DeleteLinkData(syncLink, &event, txSync) + //if err != nil { + // txSimgos.Rollback() + // return nil, err + //} + // + //// STEP 4: Commit two trx + //if err = txSync.Commit().Error; err != nil { + // txSync.Rollback() + // txSimgos.Rollback() + // return nil, err + //} + // + //if err = txSimgos.Commit().Error; err != nil { + // // STEP 5: Rollback Partial + // go func() { + // _, _ = CreateLinkData(uint(*input.Id), sgData.Kode, &event) + // }() + // return nil, err + //} + + pl.SetLogInfo(&event, nil, "complete") + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + }, nil + +} diff --git a/internal/use-case/simgos-sync-use-case/division/helper.go b/internal/use-case/simgos-sync-use-case/division/helper.go new file mode 100644 index 00000000..210d6e7c --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/division/helper.go @@ -0,0 +1,58 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package division + +import ( + "encoding/json" + erc "simrs-vx/internal/domain/references/common" + + //e "simrs-vx/internal/domain/main-entities/division" + // esimgos "simrs-vx/internal/domain/simgos-entities/divison" TBC + esync "simrs-vx/internal/domain/sync-entities/division" + esyncLog "simrs-vx/internal/domain/sync-entities/log" +) + +//func setDataSimgos[T *e.CreateDto | *e.UpdateDto](input T) (data esimgos.MPloy) { +// var inputSrc *e.CreateDto +// if inputT, ok := any(input).(*e.CreateDto); ok { +// inputSrc = inputT +// } else { +// inputTemp := any(input).(*e.UpdateDto) +// inputSrc = &inputTemp.CreateDto +// } +// +// data.Nama = inputSrc.Name +// data.Jenispoly = 0 +// +// return +//} + +func setDataSimxLog(input *esyncLog.SimxLogDto) (data esync.DivisionSimxLog) { + // encode to JSON + jsonData, _ := json.MarshalIndent(input.Payload, "", " ") + jsonString := string(jsonData) + + var status erc.ProcessStatusCode + if input.IsSuccess { + status = erc.PSCSuccess + } else { + status = erc.PSCFailed + if input.ErrMessage != nil { + data.ErrMessage = input.ErrMessage + } + } + + data.Value = &jsonString + data.Date = &now + data.Status = status + + return +} + +func setDataSimxLink(simxId, simgosId uint) (data esync.DivisionLink) { + data.Simx_Id = simxId + data.Simgos_Id = simgosId + return +} diff --git a/internal/use-case/simgos-sync-use-case/division/lib.go b/internal/use-case/simgos-sync-use-case/division/lib.go new file mode 100644 index 00000000..ce13068d --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/division/lib.go @@ -0,0 +1,188 @@ +package division + +import ( + plh "simrs-vx/pkg/lib-helper" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + "time" + + dg "github.com/karincake/apem/db-gorm-pg" + "gorm.io/gorm" + + //e "simrs-vx/internal/domain/main-entities/division" + esync "simrs-vx/internal/domain/sync-entities/division" + //esimgos "simrs-vx/internal/domain/simgos-entities/unit" + esynclog "simrs-vx/internal/domain/sync-entities/log" +) + +var now = time.Now() + +//func CreateSimgosData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*esimgos.MPloy, error) { +// pl.SetLogInfo(event, nil, "started", "DBCreate") +// +// data := setDataSimgos(&input) +// +// var tx *gorm.DB +// if len(dbx) > 0 { +// tx = dbx[0] +// } else { +// tx = dg.IS["simrs"] +// } +// +// if err := tx.Create(&data).Error; err != nil { +// return nil, plh.HandleCreateError(input, event, err) +// } +// +// pl.SetLogInfo(event, nil, "complete") +// return &data, nil +//} + +//func ReadDetailSimgosData(simgosId uint16, event *pl.Event) (*esimgos.MPloy, error) { +// pl.SetLogInfo(event, simgosId, "started", "DBReadDetail") +// data := esimgos.MPloy{} +// +// var tx = dg.IS["simrs"] +// +// if err := tx. +// Where("\"kode\" = ?", simgosId). +// First(&data).Error; err != nil { +// if processedErr := pu.HandleReadError(err, event, source, simgosId, data); processedErr != nil { +// return nil, processedErr +// } +// } +// +// pl.SetLogInfo(event, nil, "complete") +// return &data, nil +//} + +//func UpdateSimgosData(input e.UpdateDto, dataSimgos *esync.DivisionLink, event *pl.Event, dbx ...*gorm.DB) error { +// pl.SetLogInfo(event, input, "started", "DBUpdate") +// +// data := setDataSimgos(&input) +// data.Kode = dataSimgos.Simgos_Id +// +// var tx *gorm.DB +// if len(dbx) > 0 { +// tx = dbx[0] +// } else { +// tx = dg.IS["simrs"] +// } +// +// if err := tx.Save(&data).Error; err != nil { +// event.Status = "failed" +// event.ErrInfo = pl.ErrorInfo{ +// Code: "data-update-fail", +// Detail: "Database update failed", +// Raw: err, +// } +// return pl.SetLogError(event, input) +// } +// +// pl.SetLogInfo(event, nil, "complete") +// return nil +//} + +//func HardDeleteSimgosData(data *esimgos.MPloy, event *pl.Event, dbx ...*gorm.DB) error { +// pl.SetLogInfo(event, data, "started", "DBDelete") +// +// var tx *gorm.DB +// if len(dbx) > 0 { +// tx = dbx[0] +// } else { +// tx = dg.IS["simrs"] +// } +// +// if err := tx. +// Delete(&data).Error; err != nil { +// event.Status = "failed" +// event.ErrInfo = pl.ErrorInfo{ +// Code: "data-delete-fail", +// Detail: "Database delete failed", +// Raw: err, +// } +// return pl.SetLogError(event, data) +// } +// +// pl.SetLogInfo(event, nil, "complete") +// return nil +//} + +func CreateLinkData(simxId, simgosId uint, event *pl.Event, dbx ...*gorm.DB) (*esync.DivisionLink, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + data := setDataSimxLink(simxId, simgosId) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if err := tx.Create(&data).Error; err != nil { + return nil, plh.HandleCreateError(data, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadDetailLinkData(simxId uint16, event *pl.Event) (*esync.DivisionLink, error) { + pl.SetLogInfo(event, simxId, "started", "DBReadDetail") + data := esync.DivisionLink{} + + var tx = dg.I + + if err := tx. + Where("\"Simx_Id\" = ?", simxId). + First(&data).Error; err != nil { + if processedErr := pu.HandleReadError(err, event, source, simxId, data); processedErr != nil { + return nil, processedErr + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func DeleteLinkData(data *esync.DivisionLink, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBDelete") + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if err := tx.Delete(&data).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-delete-fail", + Detail: "Database delete failed", + Raw: err, + } + return pl.SetLogError(event, data) + } + + pl.SetLogInfo(event, nil, "complete") + return nil +} + +func CreateLogData(input esynclog.SimxLogDto, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, nil, "started", "DBCreate") + data := setDataSimxLog(&input) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if err := tx.Create(&data).Error; err != nil { + return plh.HandleCreateError(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return nil +} diff --git a/internal/use-case/simgos-sync-use-case/division/middleware-runner.go b/internal/use-case/simgos-sync-use-case/division/middleware-runner.go new file mode 100644 index 00000000..dad68114 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/division/middleware-runner.go @@ -0,0 +1,104 @@ +package division + +import ( + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/division" +) + +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/simgos-sync-use-case/division/middleware.go b/internal/use-case/simgos-sync-use-case/division/middleware.go new file mode 100644 index 00000000..f066ffb8 --- /dev/null +++ b/internal/use-case/simgos-sync-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/simgos-sync-use-case/division/tycovar.go b/internal/use-case/simgos-sync-use-case/division/tycovar.go new file mode 100644 index 00000000..c7733117 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/division/tycovar.go @@ -0,0 +1,44 @@ +/* +DESCRIPTION: +A sample, part of the package that contains type, constants, and/or variables. + +In this sample it also provides type and variable regarding the needs of the +middleware to separate from main use-case which has the basic CRUD +functionality. The purpose of this is to make the code more maintainable. +*/ +package division + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/division" +) + +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 +var readListPreMw []readListMw // .. +var readListPostMw []readListMw // .. +var readDetailPreMw []readDetailMw +var readDetailPostMw []readDetailMw +var updatePreMw []readDetailMw +var updatePostMw []readDetailMw +var deletePreMw []readDetailMw +var deletePostMw []readDetailMw diff --git a/internal/use-case/simgos-sync-use-case/installation/case.go b/internal/use-case/simgos-sync-use-case/installation/case.go index 755c65d3..c920fca1 100644 --- a/internal/use-case/simgos-sync-use-case/installation/case.go +++ b/internal/use-case/simgos-sync-use-case/installation/case.go @@ -1,9 +1,6 @@ package installation import ( - esimgos "simrs-vx/internal/domain/simgos-entities/installation" - esync "simrs-vx/internal/domain/sync-entities/log" - dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" @@ -12,6 +9,8 @@ import ( "gorm.io/gorm" e "simrs-vx/internal/domain/main-entities/installation" + esimgos "simrs-vx/internal/domain/simgos-entities/installation" + esync "simrs-vx/internal/domain/sync-entities/log" ) const source = "installation" diff --git a/internal/use-case/simgos-sync-use-case/installation/helper.go b/internal/use-case/simgos-sync-use-case/installation/helper.go index 51316d79..aa33ef4b 100644 --- a/internal/use-case/simgos-sync-use-case/installation/helper.go +++ b/internal/use-case/simgos-sync-use-case/installation/helper.go @@ -10,7 +10,7 @@ import ( erc "simrs-vx/internal/domain/references/common" esimgos "simrs-vx/internal/domain/simgos-entities/installation" esync "simrs-vx/internal/domain/sync-entities/installation" - "simrs-vx/internal/domain/sync-entities/log" + esyncLog "simrs-vx/internal/domain/sync-entities/log" ) func setDataSimgos[T *e.CreateDto | *e.UpdateDto](input T) (data esimgos.MInstalasi) { @@ -29,7 +29,7 @@ func setDataSimgos[T *e.CreateDto | *e.UpdateDto](input T) (data esimgos.MInstal return } -func setDataSimxLog(input *log.SimxLogDto) (data esync.InstallationSimxLog) { +func setDataSimxLog(input *esyncLog.SimxLogDto) (data esync.InstallationSimxLog) { // encode to JSON jsonData, _ := json.MarshalIndent(input.Payload, "", " ") jsonString := string(jsonData) diff --git a/internal/use-case/simgos-sync-use-case/installation/lib.go b/internal/use-case/simgos-sync-use-case/installation/lib.go index 77140553..9b057ece 100644 --- a/internal/use-case/simgos-sync-use-case/installation/lib.go +++ b/internal/use-case/simgos-sync-use-case/installation/lib.go @@ -1,7 +1,6 @@ package installation import ( - esynclog "simrs-vx/internal/domain/sync-entities/log" plh "simrs-vx/pkg/lib-helper" pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" @@ -13,6 +12,7 @@ import ( e "simrs-vx/internal/domain/main-entities/installation" esimgos "simrs-vx/internal/domain/simgos-entities/installation" esync "simrs-vx/internal/domain/sync-entities/installation" + esynclog "simrs-vx/internal/domain/sync-entities/log" ) var now = time.Now() diff --git a/pkg/handler-crud-helper/handler-crud-helper.go b/pkg/handler-crud-helper/handler-crud-helper.go index df475094..3003e812 100644 --- a/pkg/handler-crud-helper/handler-crud-helper.go +++ b/pkg/handler-crud-helper/handler-crud-helper.go @@ -74,3 +74,36 @@ func RegCrudByCode(r *http.ServeMux, path string, mwAndRouter ...any) { "DELETE /{code}": c.Delete, }) } + +func SyncCrud(r *http.ServeMux, path string, mwAndRouter ...any) { + sLength := len(mwAndRouter) + + mwCandidates := mwAndRouter[:sLength-1] + mwList := []hk.HandlerMw{} + for i := range mwCandidates { + // have to do it manually, since casting directly results unexpected result + myType := reflect.TypeOf(mwCandidates[i]) + if myType.String() != "func(http.Handler) http.Handler" { + panic("non middleware included as middleware") + } + mwList = append(mwList, mwCandidates[i].(func(http.Handler) http.Handler)) + + // if g, okHandler := mwCandidates[i].(func(http.Handler) http.Handler); !okHandler { + // panic("non middleware included") + // } else { + // mwList = append(mwList, g) + // } + } + + c, ok := mwAndRouter[sLength-1].(SyncCrudBase) + if !ok { + panic("non CrudBase used in the last paramter") + } + + hk.GroupRoutes(path, r, mwList, hk.MapHandlerFunc{ + "POST /": c.Create, + "POST /log": c.CreateLog, + "PATCH /{id}": c.Update, + "DELETE /{id}": c.Delete, + }) +} diff --git a/pkg/handler-crud-helper/types.go b/pkg/handler-crud-helper/types.go index e85f22fc..891af38e 100644 --- a/pkg/handler-crud-helper/types.go +++ b/pkg/handler-crud-helper/types.go @@ -9,3 +9,10 @@ type CrudBase interface { Update(w http.ResponseWriter, r *http.Request) Delete(w http.ResponseWriter, r *http.Request) } + +type SyncCrudBase interface { + Create(w http.ResponseWriter, r *http.Request) + CreateLog(w http.ResponseWriter, r *http.Request) + Update(w http.ResponseWriter, r *http.Request) + Delete(w http.ResponseWriter, r *http.Request) +}