From 2fb47d0d4856d2503324470214e959734323e1f4 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Thu, 16 Oct 2025 11:26:09 +0700 Subject: [PATCH] monitoring done --- internal/domain/bpjs-entities/member/dto.go | 1 + .../domain/bpjs-entities/monitoring/dto.go | 15 ++++++ .../domain/bpjs-entities/monitoring/entity.go | 43 ++++++++++++++++ .../interface/bpjs-handler/bpjs-handler.go | 6 +++ .../bpjs-handler/monitoring/handler.go | 50 +++++++++++++++++++ .../use-case/bpjs-plugin/monitoring/helper.go | 18 +++++++ .../use-case/bpjs-plugin/monitoring/plugin.go | 37 ++++++++++++++ .../use-case/bpjs-use-case/monitoring/case.go | 50 +++++++++++++++++++ .../monitoring/middleware-runner.go | 42 ++++++++++++++++ .../bpjs-use-case/monitoring/middleware.go | 12 +++++ .../bpjs-use-case/monitoring/tycovar.go | 18 +++++++ 11 files changed, 292 insertions(+) create mode 100644 internal/domain/bpjs-entities/monitoring/dto.go create mode 100644 internal/domain/bpjs-entities/monitoring/entity.go create mode 100644 internal/interface/bpjs-handler/monitoring/handler.go create mode 100644 internal/use-case/bpjs-plugin/monitoring/helper.go create mode 100644 internal/use-case/bpjs-plugin/monitoring/plugin.go create mode 100644 internal/use-case/bpjs-use-case/monitoring/case.go create mode 100644 internal/use-case/bpjs-use-case/monitoring/middleware-runner.go create mode 100644 internal/use-case/bpjs-use-case/monitoring/middleware.go create mode 100644 internal/use-case/bpjs-use-case/monitoring/tycovar.go diff --git a/internal/domain/bpjs-entities/member/dto.go b/internal/domain/bpjs-entities/member/dto.go index e61a9f74..f9c95655 100644 --- a/internal/domain/bpjs-entities/member/dto.go +++ b/internal/domain/bpjs-entities/member/dto.go @@ -4,6 +4,7 @@ type ReadListDto struct { ReferenceType ReferenceType `json:"-"` PathValue1 string `json:"-"` PathValue2 string `json:"-"` + PathValue3 string `json:"-"` } type ReferenceType string diff --git a/internal/domain/bpjs-entities/monitoring/dto.go b/internal/domain/bpjs-entities/monitoring/dto.go new file mode 100644 index 00000000..c5c1e0d1 --- /dev/null +++ b/internal/domain/bpjs-entities/monitoring/dto.go @@ -0,0 +1,15 @@ +package monitoring + +type ReadListDto struct { + ReferenceType ReferenceType `json:"-"` + PathValue1 string `json:"-"` + PathValue2 string `json:"-"` + PathValue3 string `json:"-"` +} + +type ReferenceType string + +const ( + RTVisit ReferenceType = "visit" + RTHist ReferenceType = "hist" +) diff --git a/internal/domain/bpjs-entities/monitoring/entity.go b/internal/domain/bpjs-entities/monitoring/entity.go new file mode 100644 index 00000000..eb604942 --- /dev/null +++ b/internal/domain/bpjs-entities/monitoring/entity.go @@ -0,0 +1,43 @@ +package monitoring + +type Response struct { + MetaData MetaData `json:"metaData"` + Response *BPJSDataRes `json:"response"` +} + +type MetaData struct { + Code string `json:"code"` + Message string `json:"message"` +} + +type BPJSDataRes struct { + Sep []Sep `json:"sep"` + Histori []Histori `json:"histori"` +} + +type Sep struct { + Diagnosa string `json:"diagnosa"` + JnsPelayanan string `json:"jnsPelayanan"` + KelasRawat string `json:"kelasRawat"` + Nama string `json:"nama"` + NoKartu string `json:"noKartu"` + NoSep string `json:"noSep"` + NoRujukan string `json:"noRujukan"` + Poli *string `json:"poli"` + TglPlgSep string `json:"tglPlgSep"` + TglSep string `json:"tglSep"` +} + +type Histori struct { + Diagnosa string `json:"diagnosa"` + JnsPelayanan string `json:"jnsPelayanan"` + KelasRawat *string `json:"kelasRawat"` + NamaPeserta string `json:"namaPeserta"` + NoKartu string `json:"noKartu"` + NoSep string `json:"noSep"` + NoRujukan string `json:"noRujukan"` + Poli string `json:"poli"` + PpkPelayanan string `json:"ppkPelayanan"` + TglPlgSep string `json:"tglPlgSep"` + TglSep string `json:"tglSep"` +} diff --git a/internal/interface/bpjs-handler/bpjs-handler.go b/internal/interface/bpjs-handler/bpjs-handler.go index b1a2c80a..175bb667 100644 --- a/internal/interface/bpjs-handler/bpjs-handler.go +++ b/internal/interface/bpjs-handler/bpjs-handler.go @@ -5,6 +5,7 @@ import ( /******************** main / transaction ********************/ member "simrs-vx/internal/interface/bpjs-handler/member" + monitoring "simrs-vx/internal/interface/bpjs-handler/monitoring" reference "simrs-vx/internal/interface/bpjs-handler/reference" vclaimsep "simrs-vx/internal/interface/bpjs-handler/vclaim-sep" vclaimsephist "simrs-vx/internal/interface/bpjs-handler/vclaim-sep-hist" @@ -77,6 +78,11 @@ func SetRoutes() http.Handler { "GET /nik/{nik}/{sepDate}": member.GetListByNik, }) + hk.GroupRoutes("/v1/monitoring", r, hk.MapHandlerFunc{ + "GET /visit/{date}/{serviceType}": monitoring.GetListVisit, + "GET /hist/{cardNumber}/{startDate}/{endDate}": monitoring.GetListHist, + }) + /******************** actor ********************/ /******************** sources ********************/ diff --git a/internal/interface/bpjs-handler/monitoring/handler.go b/internal/interface/bpjs-handler/monitoring/handler.go new file mode 100644 index 00000000..cf82a5b9 --- /dev/null +++ b/internal/interface/bpjs-handler/monitoring/handler.go @@ -0,0 +1,50 @@ +package monitoring + +import ( + "net/http" + + e "simrs-vx/internal/domain/bpjs-entities/monitoring" + u "simrs-vx/internal/use-case/bpjs-use-case/monitoring" + + d "github.com/karincake/dodol" + rw "github.com/karincake/risoles" +) + +func GetListVisit(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + pValue1 := rw.ValidateString(w, "date", r.PathValue("date")) + if pValue1 == "" { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "date is required"}, nil) + } + pValue2 := rw.ValidateString(w, "serviceType", r.PathValue("serviceType")) + if pValue2 == "" { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "serviceType is required"}, nil) + } + dto.ReferenceType = e.RTVisit + dto.PathValue1 = pValue1 + dto.PathValue2 = pValue2 + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func GetListHist(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + pValue1 := rw.ValidateString(w, "cardNumber", r.PathValue("cardNumber")) + if pValue1 == "" { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "cardNumber is required"}, nil) + } + pValue2 := rw.ValidateString(w, "startDate", r.PathValue("startDate")) + if pValue2 == "" { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "startDate is required"}, nil) + } + pValue3 := rw.ValidateString(w, "endDate", r.PathValue("endDate")) + if pValue3 == "" { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "endDate is required"}, nil) + } + dto.ReferenceType = e.RTHist + dto.PathValue1 = pValue1 + dto.PathValue2 = pValue2 + dto.PathValue3 = pValue3 + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/use-case/bpjs-plugin/monitoring/helper.go b/internal/use-case/bpjs-plugin/monitoring/helper.go new file mode 100644 index 00000000..8f6d2c88 --- /dev/null +++ b/internal/use-case/bpjs-plugin/monitoring/helper.go @@ -0,0 +1,18 @@ +package monitoring + +import ( + "fmt" + e "simrs-vx/internal/domain/bpjs-entities/monitoring" + ibpjs "simrs-vx/internal/infra/bpjs" +) + +func endpointMapper(input *e.ReadListDto) string { + switch input.ReferenceType { + case e.RTHist: + return fmt.Sprintf("%smonitoring/history/%s?tglawal=%s&tglakhir=%s", ibpjs.O.BaseUrl, input.PathValue1, input.PathValue2, input.PathValue3) + case e.RTVisit: + return fmt.Sprintf("%smonitoring/kunjungan?tglpelayanan=%s&jnspelayanan=%s", ibpjs.O.BaseUrl, input.PathValue1, input.PathValue2) + default: + return "" + } +} diff --git a/internal/use-case/bpjs-plugin/monitoring/plugin.go b/internal/use-case/bpjs-plugin/monitoring/plugin.go new file mode 100644 index 00000000..2450e4e9 --- /dev/null +++ b/internal/use-case/bpjs-plugin/monitoring/plugin.go @@ -0,0 +1,37 @@ +package monitoring + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + e "simrs-vx/internal/domain/bpjs-entities/monitoring" + + "gorm.io/gorm" +) + +func ReadList(input *e.ReadListDto, data *e.Response, tx *gorm.DB) error { + endpoint := endpointMapper(input) + req, err := http.NewRequest("GET", endpoint, nil) + 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() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return err + } + + if err := json.Unmarshal(body, &data); err != nil { + return fmt.Errorf("failed to parse response JSON: %w", err) + } + + return nil +} diff --git a/internal/use-case/bpjs-use-case/monitoring/case.go b/internal/use-case/bpjs-use-case/monitoring/case.go new file mode 100644 index 00000000..43109cca --- /dev/null +++ b/internal/use-case/bpjs-use-case/monitoring/case.go @@ -0,0 +1,50 @@ +package monitoring + +import ( + e "simrs-vx/internal/domain/bpjs-entities/monitoring" + + dg "github.com/karincake/apem/db-gorm-pg" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +const source = "monitoring" + +func ReadList(input e.ReadListDto) (*e.Response, error) { + var data e.Response + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "readList") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadListMiddleware(readListPreMw, &input, &data); err != nil { + return err + } + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadListMiddleware(readListPostMw, &input, &data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &data, nil +} diff --git a/internal/use-case/bpjs-use-case/monitoring/middleware-runner.go b/internal/use-case/bpjs-use-case/monitoring/middleware-runner.go new file mode 100644 index 00000000..49bc5efe --- /dev/null +++ b/internal/use-case/bpjs-use-case/monitoring/middleware-runner.go @@ -0,0 +1,42 @@ +package monitoring + +import ( + e "simrs-vx/internal/domain/bpjs-entities/monitoring" + 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, + } +} + +func (me *middlewareRunner) RunReadListMiddleware(middlewares []readListMw, input *e.ReadListDto, data *e.Response) 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/bpjs-use-case/monitoring/middleware.go b/internal/use-case/bpjs-use-case/monitoring/middleware.go new file mode 100644 index 00000000..d5e77655 --- /dev/null +++ b/internal/use-case/bpjs-use-case/monitoring/middleware.go @@ -0,0 +1,12 @@ +package monitoring + +import ( + pm "simrs-vx/internal/use-case/bpjs-plugin/monitoring" +) + +func init() { + readListPreMw = append(readListPreMw, + readListMw{Name: "readList-monitoring", Func: pm.ReadList}, + ) + +} diff --git a/internal/use-case/bpjs-use-case/monitoring/tycovar.go b/internal/use-case/bpjs-use-case/monitoring/tycovar.go new file mode 100644 index 00000000..463109c7 --- /dev/null +++ b/internal/use-case/bpjs-use-case/monitoring/tycovar.go @@ -0,0 +1,18 @@ +/* +member is peserta +*/ +package monitoring + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/bpjs-entities/monitoring" +) + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.Response, tx *gorm.DB) error +} + +var readListPreMw []readListMw // .. +var readListPostMw []readListMw // ..