From c009a34f5e7d15a46afb6f1c89a6eb0d4f3565c3 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Thu, 16 Oct 2025 09:50:40 +0700 Subject: [PATCH] member, nik ok, bpjs tested but failed from 3rd party --- internal/domain/bpjs-entities/member/dto.go | 14 ++++ .../domain/bpjs-entities/member/entity.go | 78 +++++++++++++++++++ .../interface/bpjs-handler/bpjs-handler.go | 6 ++ .../interface/bpjs-handler/member/handler.go | 45 +++++++++++ .../bpjs-handler/reference/handler.go | 1 + .../use-case/bpjs-plugin/member/helper.go | 18 +++++ .../use-case/bpjs-plugin/member/plugin.go | 37 +++++++++ .../use-case/bpjs-use-case/member/case.go | 50 ++++++++++++ .../bpjs-use-case/member/middleware-runner.go | 42 ++++++++++ .../bpjs-use-case/member/middleware.go | 12 +++ .../use-case/bpjs-use-case/member/tycovar.go | 18 +++++ .../use-case/bpjs-use-case/reference/case.go | 6 -- .../bpjs-use-case/reference/helper.go | 22 ------ .../use-case/bpjs-use-case/reference/lib.go | 1 - 14 files changed, 321 insertions(+), 29 deletions(-) create mode 100644 internal/domain/bpjs-entities/member/dto.go create mode 100644 internal/domain/bpjs-entities/member/entity.go create mode 100644 internal/interface/bpjs-handler/member/handler.go create mode 100644 internal/use-case/bpjs-plugin/member/helper.go create mode 100644 internal/use-case/bpjs-plugin/member/plugin.go create mode 100644 internal/use-case/bpjs-use-case/member/case.go create mode 100644 internal/use-case/bpjs-use-case/member/middleware-runner.go create mode 100644 internal/use-case/bpjs-use-case/member/middleware.go create mode 100644 internal/use-case/bpjs-use-case/member/tycovar.go delete mode 100644 internal/use-case/bpjs-use-case/reference/helper.go delete mode 100644 internal/use-case/bpjs-use-case/reference/lib.go diff --git a/internal/domain/bpjs-entities/member/dto.go b/internal/domain/bpjs-entities/member/dto.go new file mode 100644 index 00000000..e61a9f74 --- /dev/null +++ b/internal/domain/bpjs-entities/member/dto.go @@ -0,0 +1,14 @@ +package member + +type ReadListDto struct { + ReferenceType ReferenceType `json:"-"` + PathValue1 string `json:"-"` + PathValue2 string `json:"-"` +} + +type ReferenceType string + +const ( + RTNik ReferenceType = "nik" + RTBpjs ReferenceType = "bpjs" +) diff --git a/internal/domain/bpjs-entities/member/entity.go b/internal/domain/bpjs-entities/member/entity.go new file mode 100644 index 00000000..b6c4f0d7 --- /dev/null +++ b/internal/domain/bpjs-entities/member/entity.go @@ -0,0 +1,78 @@ +package member + +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 { + Peserta *Peserta `json:"peserta"` +} + +type Peserta struct { + Cob *COB `json:"cob"` + HakKelas *HakKelas `json:"hakKelas"` + Informasi *Informasi `json:"informasi"` + JenisPeserta *JenisPeserta `json:"jenisPeserta"` + Mr *MR `json:"mr"` + Nama *string `json:"nama"` + Nik *string `json:"nik"` + NoKartu *string `json:"noKartu"` + Pisa *string `json:"pisa"` + ProvUmum *ProvUmum `json:"provUmum"` + Sex *string `json:"sex"` + StatusPeserta *StatusPeserta `json:"statusPeserta"` + TglCetakKartu *string `json:"tglCetakKartu"` + TglLahir *string `json:"tglLahir"` + TglTAT *string `json:"tglTAT"` + TglTMT *string `json:"tglTMT"` + Umur *Umur `json:"umur"` +} + +type COB struct { + NmAsuransi *string `json:"nmAsuransi"` + NoAsuransi *string `json:"noAsuransi"` + TglTAT *string `json:"tglTAT"` + TglTMT *string `json:"tglTMT"` +} + +type HakKelas struct { + Keterangan *string `json:"keterangan"` + Kode *string `json:"kode"` +} + +type Informasi struct { + Dinsos *string `json:"dinsos"` + NoSKTM *string `json:"noSKTM"` + ProlanisPRB *string `json:"prolanisPRB"` +} + +type JenisPeserta struct { + Keterangan *string `json:"keterangan"` + Kode *string `json:"kode"` +} + +type MR struct { + NoMR *string `json:"noMR"` + NoTelepon *string `json:"noTelepon"` +} + +type ProvUmum struct { + KdProvider *string `json:"kdProvider"` + NmProvider *string `json:"nmProvider"` +} + +type StatusPeserta struct { + Keterangan *string `json:"keterangan"` + Kode *string `json:"kode"` +} + +type Umur struct { + UmurSaatPelayanan *string `json:"umurSaatPelayanan"` + UmurSekarang *string `json:"umurSekarang"` +} diff --git a/internal/interface/bpjs-handler/bpjs-handler.go b/internal/interface/bpjs-handler/bpjs-handler.go index 5d5673df..b1a2c80a 100644 --- a/internal/interface/bpjs-handler/bpjs-handler.go +++ b/internal/interface/bpjs-handler/bpjs-handler.go @@ -4,6 +4,7 @@ import ( "net/http" /******************** main / transaction ********************/ + member "simrs-vx/internal/interface/bpjs-handler/member" 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" @@ -71,6 +72,11 @@ func SetRoutes() http.Handler { "GET /responsible-doctor/{serviceType}/{serviceDate}/{specialistCode}": reference.GetListDoctor, }) + hk.GroupRoutes("/v1/member", r, hk.MapHandlerFunc{ + "GET /bpjs/{cardNumber}/{sepDate}": member.GetListByBpjsNumber, + "GET /nik/{nik}/{sepDate}": member.GetListByNik, + }) + /******************** actor ********************/ /******************** sources ********************/ diff --git a/internal/interface/bpjs-handler/member/handler.go b/internal/interface/bpjs-handler/member/handler.go new file mode 100644 index 00000000..80881ee3 --- /dev/null +++ b/internal/interface/bpjs-handler/member/handler.go @@ -0,0 +1,45 @@ +package member + +import ( + "net/http" + + e "simrs-vx/internal/domain/bpjs-entities/member" + u "simrs-vx/internal/use-case/bpjs-use-case/member" + + d "github.com/karincake/dodol" + rw "github.com/karincake/risoles" +) + +func GetListByBpjsNumber(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, "sepDate", r.PathValue("sepDate")) + if pValue2 == "" { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "sepDate is required"}, nil) + } + dto.ReferenceType = e.RTBpjs + dto.PathValue1 = pValue1 + dto.PathValue2 = pValue2 + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func GetListByNik(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + pValue1 := rw.ValidateString(w, "nik", r.PathValue("nik")) + if pValue1 == "" { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "nik is required"}, nil) + } + pValue2 := rw.ValidateString(w, "sepDate", r.PathValue("sepDate")) + if pValue2 == "" { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "sepDate is required"}, nil) + } + dto.ReferenceType = e.RTNik + dto.PathValue1 = pValue1 + dto.PathValue2 = pValue2 + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/bpjs-handler/reference/handler.go b/internal/interface/bpjs-handler/reference/handler.go index d452ebc4..fb972af1 100644 --- a/internal/interface/bpjs-handler/reference/handler.go +++ b/internal/interface/bpjs-handler/reference/handler.go @@ -2,6 +2,7 @@ package reference import ( "net/http" + e "simrs-vx/internal/domain/bpjs-entities/reference" u "simrs-vx/internal/use-case/bpjs-use-case/reference" diff --git a/internal/use-case/bpjs-plugin/member/helper.go b/internal/use-case/bpjs-plugin/member/helper.go new file mode 100644 index 00000000..f5e2bc0e --- /dev/null +++ b/internal/use-case/bpjs-plugin/member/helper.go @@ -0,0 +1,18 @@ +package member + +import ( + "fmt" + e "simrs-vx/internal/domain/bpjs-entities/member" + ibpjs "simrs-vx/internal/infra/bpjs" +) + +func endpointMapper(input *e.ReadListDto) string { + switch input.ReferenceType { + case e.RTBpjs: + return fmt.Sprintf("%speserta/nokartu?noKartu=%s&tglpelayanan=%s", ibpjs.O.BaseUrl, input.PathValue1, input.PathValue2) + case e.RTNik: + return fmt.Sprintf("%speserta/nik?nik=%s&tglpelayanan=%s", ibpjs.O.BaseUrl, input.PathValue1, input.PathValue2) + default: + return "" + } +} diff --git a/internal/use-case/bpjs-plugin/member/plugin.go b/internal/use-case/bpjs-plugin/member/plugin.go new file mode 100644 index 00000000..7610a5ac --- /dev/null +++ b/internal/use-case/bpjs-plugin/member/plugin.go @@ -0,0 +1,37 @@ +package member + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + e "simrs-vx/internal/domain/bpjs-entities/member" + + "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/member/case.go b/internal/use-case/bpjs-use-case/member/case.go new file mode 100644 index 00000000..7c50ea76 --- /dev/null +++ b/internal/use-case/bpjs-use-case/member/case.go @@ -0,0 +1,50 @@ +package member + +import ( + e "simrs-vx/internal/domain/bpjs-entities/member" + + 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 = "member" + +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/member/middleware-runner.go b/internal/use-case/bpjs-use-case/member/middleware-runner.go new file mode 100644 index 00000000..71061a1b --- /dev/null +++ b/internal/use-case/bpjs-use-case/member/middleware-runner.go @@ -0,0 +1,42 @@ +package member + +import ( + e "simrs-vx/internal/domain/bpjs-entities/member" + 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/member/middleware.go b/internal/use-case/bpjs-use-case/member/middleware.go new file mode 100644 index 00000000..e2fd5584 --- /dev/null +++ b/internal/use-case/bpjs-use-case/member/middleware.go @@ -0,0 +1,12 @@ +package member + +import ( + pm "simrs-vx/internal/use-case/bpjs-plugin/member" +) + +func init() { + readListPreMw = append(readListPreMw, + readListMw{Name: "readList-member", Func: pm.ReadList}, + ) + +} diff --git a/internal/use-case/bpjs-use-case/member/tycovar.go b/internal/use-case/bpjs-use-case/member/tycovar.go new file mode 100644 index 00000000..7d04363f --- /dev/null +++ b/internal/use-case/bpjs-use-case/member/tycovar.go @@ -0,0 +1,18 @@ +/* +member is peserta +*/ +package member + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/bpjs-entities/member" +) + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.Response, tx *gorm.DB) error +} + +var readListPreMw []readListMw // .. +var readListPostMw []readListMw // .. diff --git a/internal/use-case/bpjs-use-case/reference/case.go b/internal/use-case/bpjs-use-case/reference/case.go index d753a955..bc9bb5d6 100644 --- a/internal/use-case/bpjs-use-case/reference/case.go +++ b/internal/use-case/bpjs-use-case/reference/case.go @@ -2,7 +2,6 @@ package reference import ( e "simrs-vx/internal/domain/bpjs-entities/reference" - // evsh "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-hist" dg "github.com/karincake/apem/db-gorm-pg" @@ -16,7 +15,6 @@ const source = "reference" func ReadList(input e.ReadListDto) (*e.Response, error) { var data e.Response - // var dataList []e.Response var err error event := pl.Event{ @@ -35,10 +33,6 @@ func ReadList(input e.ReadListDto) (*e.Response, error) { return err } - // if dataList, metaList, err = ReadListData(input, &event, tx); err != nil { - // return err - // } - mwRunner.setMwType(pu.MWTPost) // Run post-middleware if err := mwRunner.RunReadListMiddleware(readListPostMw, &input, &data); err != nil { diff --git a/internal/use-case/bpjs-use-case/reference/helper.go b/internal/use-case/bpjs-use-case/reference/helper.go deleted file mode 100644 index 5f664320..00000000 --- a/internal/use-case/bpjs-use-case/reference/helper.go +++ /dev/null @@ -1,22 +0,0 @@ -/* -DESCRIPTION: -Any functions that are used internally by the use-case -*/ -package reference - -// import ( -// e "simrs-vx/internal/domain/bpjs-entities/vclaim-sep" -// ) - -// func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.VclaimSep) { -// var inputSrc *e.CreateDto -// if inputT, ok := any(input).(*e.CreateDto); ok { -// inputSrc = inputT -// } else { -// inputTemp := any(input).(*e.UpdateDto) -// inputSrc = &inputTemp.CreateDto -// } - -// data.Encounter_Id = inputSrc.Encounter_Id -// data.Number = inputSrc.Number -// } diff --git a/internal/use-case/bpjs-use-case/reference/lib.go b/internal/use-case/bpjs-use-case/reference/lib.go deleted file mode 100644 index bccaf5df..00000000 --- a/internal/use-case/bpjs-use-case/reference/lib.go +++ /dev/null @@ -1 +0,0 @@ -package reference