From 547a54cbe4a93107c96af30f1c6599cdca5d163c Mon Sep 17 00:00:00 2001 From: poetrasapoetra Date: Wed, 3 Dec 2025 10:37:50 +0700 Subject: [PATCH] Fix CUD Patient --- .../domain/simgos-entities/m-pasien/dto.go | 26 ++- .../old/patient/handler.go | 82 ++------- .../simgos-sync-use-case/old/patient/case.go | 166 ++++++++++++++++++ .../old/patient/helper.go | 69 ++++++++ .../simgos-sync-use-case/old/patient/lib.go | 19 ++ .../old/patient/tycovar.go | 14 ++ 6 files changed, 290 insertions(+), 86 deletions(-) create mode 100644 internal/use-case/simgos-sync-use-case/old/patient/case.go create mode 100644 internal/use-case/simgos-sync-use-case/old/patient/helper.go create mode 100644 internal/use-case/simgos-sync-use-case/old/patient/lib.go create mode 100644 internal/use-case/simgos-sync-use-case/old/patient/tycovar.go diff --git a/internal/domain/simgos-entities/m-pasien/dto.go b/internal/domain/simgos-entities/m-pasien/dto.go index 68a2d068..8d2c3368 100644 --- a/internal/domain/simgos-entities/m-pasien/dto.go +++ b/internal/domain/simgos-entities/m-pasien/dto.go @@ -2,12 +2,12 @@ package m_pasien import ( "fmt" + ecore "simrs-vx/internal/domain/base-entities/core" e "simrs-vx/internal/domain/main-entities/patient" pr "simrs-vx/internal/domain/main-entities/person" pa "simrs-vx/internal/domain/main-entities/person-address" pab "simrs-vx/internal/domain/main-entities/person-address/base" pc "simrs-vx/internal/domain/main-entities/person-contact" - cm "simrs-vx/internal/domain/references/common" rf "simrs-vx/internal/domain/references/person" "time" @@ -89,8 +89,9 @@ type MPasienDto struct { func (mp MPasienDto) ToPatient() e.Patient { patient := e.Patient{ - // TODO get patient person_id from database - Person_Id: &mp.Id, + Main: ecore.Main{ + Id: mp.Id, + }, NewBornStatus: mp.ParentNomr != nil, RegisteredAt: parseTimeDateOnly(mp.Tgldaftar), RegisteredBy_User_Name: mp.Nip, @@ -116,9 +117,9 @@ func (mp MPasienDto) ToPatient() e.Patient { BirthDate: parseTimeDateOnly(mp.Tgllahir), BirthRegency_Code: &bc, Gender_Code: &gc, - ResidentIdentityNumber: nilEmptyString(mp.Noktp), - PassportNumber: nilEmptyString(*mp.Paspor), - DrivingLicenseNumber: nilEmptyString(*mp.Sim), + ResidentIdentityNumber: nilEmptyString(&mp.Noktp), + PassportNumber: nilEmptyString(mp.Paspor), + DrivingLicenseNumber: nilEmptyString(mp.Sim), Religion_Code: &rc, Education_Code: &ec, Ocupation_Name: &mp.Pekerjaan, @@ -166,18 +167,11 @@ func (mp MPasienDto) ToPatient() e.Patient { return patient } -func getActiveStatus(s uint) cm.ActiveStatusCode { - if s == 1 { - return cm.SCActive - } - return cm.SCInactive -} - -func nilEmptyString(s string) *string { - if s == "" { +func nilEmptyString(s *string) *string { + if s == nil { return nil } - return &s + return s } func getGender(g string) rf.GenderCode { diff --git a/internal/interface/simgos-sync-handler/old/patient/handler.go b/internal/interface/simgos-sync-handler/old/patient/handler.go index b794de07..4c697fd4 100644 --- a/internal/interface/simgos-sync-handler/old/patient/handler.go +++ b/internal/interface/simgos-sync-handler/old/patient/handler.go @@ -1,14 +1,10 @@ package patient import ( - "bytes" - "encoding/json" - "fmt" - "io" "net/http" p "simrs-vx/internal/domain/simgos-entities/m-pasien" - cfg "simrs-vx/internal/infra/sync-cfg" + uo "simrs-vx/internal/use-case/simgos-sync-use-case/old/patient" rw "github.com/karincake/risoles" ) @@ -22,85 +18,31 @@ func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { if !rw.ValidateStructByIOR(w, r.Body, &dto) { return } - // translate m_pasien ke Patient + + // mapping m_patient to patient patient := dto.ToPatient() - jsonPatient, err := json.Marshal(patient) - if err != nil { - fmt.Println(err) - } - // fmt.Println(string(jsonPatient)) - // kirim request ke api sim-baru - reqBody := bytes.NewBuffer(jsonPatient) - err = send(http.MethodPost, "patient", reqBody) - if err != nil { - fmt.Println("request error:", err) - } + res, err := uo.Create(patient) + rw.DataResponse(w, res, err) } + func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + dto := p.MPasienDto{} if !rw.ValidateStructByIOR(w, r.Body, &dto) { return } patient := dto.ToPatient() - // TODO DELETE BELOW, - var ( - personId uint = 68 - patientId uint = 34 - ) - patient.Person_Id = &personId - patient.Id = patientId - patient.Person.Id = personId - // TODO DELETE ABOVE - jsonPatient, err := json.MarshalIndent(patient, "", " ") - if err != nil { - fmt.Println(err) - } - fmt.Println(string(jsonPatient)) - url := fmt.Sprintf("%s%v", "patient/", patient.Id) - fmt.Println(url) - reqBody := bytes.NewBuffer(jsonPatient) - err = send(http.MethodPatch, url, reqBody) - if err != nil { - fmt.Println("request error:", err) - } + res, err := uo.Update(patient) + rw.DataResponse(w, res, err) } + func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { dto := p.MPasienDto{} if !rw.ValidateStructByIOR(w, r.Body, &dto) { return } patient := dto.ToPatient() - jsonPatient, err := json.Marshal(patient) - if err != nil { - fmt.Println(err) - } - reqBody := bytes.NewBuffer(jsonPatient) - err = send(http.MethodDelete, fmt.Sprintf("%s%v", "patient/", *patient.Person_Id), reqBody) - if err != nil { - fmt.Println("request error:", err) - } -} -func (obj myBase) CreateLog(w http.ResponseWriter, r *http.Request) { - -} - -func send(method string, endpoint string, body *bytes.Buffer) error { - var url string = cfg.O.NewHost + endpoint - req, err := http.NewRequest(method, url, body) - if err != nil { - return err - } - req.Header.Set("Content-Type", "application/json") - req.Header.Set("X-Sync-Source", cfg.O.OldSource) - req.Header.Set("X-Sync-SecretKey", cfg.O.NewSecretKey) - req.Header.Set("X-Sync-UserName", "dave") - resp, err := http.DefaultClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - respBody, _ := io.ReadAll(resp.Body) - fmt.Println(resp.StatusCode, string(respBody), method, url) - return nil + res, err := uo.Delete(patient) + rw.DataResponse(w, res, err) } diff --git a/internal/use-case/simgos-sync-use-case/old/patient/case.go b/internal/use-case/simgos-sync-use-case/old/patient/case.go new file mode 100644 index 00000000..ae52e37a --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/old/patient/case.go @@ -0,0 +1,166 @@ +package patient + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" + + cfg "simrs-vx/internal/infra/sync-cfg" + pl "simrs-vx/pkg/logger" + + e "simrs-vx/internal/domain/main-entities/patient" + un "simrs-vx/internal/use-case/simgos-sync-use-case/new/patient" + + d "github.com/karincake/dodol" +) + +const source = "old-to-new-patient" + +var path = "patient" + +func Create(input e.Patient) (*d.Data, error) { + evt := pl.Event{ + Feature: "Create", + Source: source, + } + + pl.SetLogInfo(&evt, input, "started", "create") + + // create request body + jsonPatient, err := json.Marshal(input) + if err != nil { + return nil, pl.SetLogError(&evt, input) + } + reqBody := bytes.NewBuffer(jsonPatient) + // send data to main-api + resp, err := send(http.MethodPost, path, reqBody) + if err != nil { + return nil, pl.SetLogError(&evt, input) + } + // getting response + var data MainApiResp + err = json.Unmarshal(resp, &data) + if err != nil { + return nil, pl.SetLogError(&evt, string(resp)) + } + // create PatientLink + un.CreateLinkData(data.Data.Id, input.Id, &evt) + pl.SetLogInfo(&evt, nil, "complete") + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: input.ToResponse(), + }, nil +} + +func Update(input e.Patient) (*d.Data, error) { + evt := pl.Event{ + Feature: "Update", + Source: source, + } + pl.SetLogInfo(&evt, input, "started", "update") + + // get patient link from database + patientLink, err := ReadDetailLinkData(input.Id) + if err != nil { + return nil, pl.SetLogError(&evt, input) + } + + // get data patient from main-api + resp, err := send(http.MethodGet, fmt.Sprintf("%s%v", "patient/", patientLink.Simx_Id), nil) + if err != nil { + return nil, pl.SetLogError(&evt, input) + } + // unpack data from resp + var respData MainApiResp + err = json.Unmarshal(resp, &respData) + if err != nil { + return nil, pl.SetLogError(&evt, input) + } + + // copy data from simgos m_patient to simx Patient + preserve := map[string]bool{ + "Main.Id": true, + "Person.Id": true, + } + simxPatient := respData.Data + SetPatient(&simxPatient, &input, preserve) + + jsonPatient, err := json.Marshal(simxPatient) + if err != nil { + return nil, pl.SetLogError(&evt, input) + } + + // send data to main api + url := fmt.Sprintf("%s%v", "patient/", simxPatient.Id) + reqBody := bytes.NewBuffer(jsonPatient) + _, err = send(http.MethodPatch, url, reqBody) + if err != nil { + return nil, pl.SetLogError(&evt, input) + } + + pl.SetLogInfo(&evt, nil, "complete") + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: input.ToResponse(), + }, nil +} + +func Delete(input e.Patient) (*d.Data, error) { + evt := pl.Event{ + Feature: "Delete", + Source: source, + } + pl.SetLogInfo(&evt, input, "started", "delete") + + // get patient link from database + patientLink, err := ReadDetailLinkData(input.Id) + if err != nil { + return nil, err + } + _, err = send(http.MethodDelete, fmt.Sprintf("%s%v", "patient/", patientLink.Simx_Id), nil) + if err != nil { + return nil, err + } + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + Data: input.ToResponse(), + }, nil +} + +func send(method string, endpoint string, body *bytes.Buffer) ([]byte, error) { + var url string = cfg.O.NewHost + endpoint + var reader io.Reader = nil + if body != nil { + reader = body + } + req, err := http.NewRequest(method, url, reader) + if err != nil { + return nil, err + } + req.Header.Set("Content-Type", "application/json") + req.Header.Set("X-Sync-Source", cfg.O.OldSource) + req.Header.Set("X-Sync-SecretKey", cfg.O.NewSecretKey) + // TODO get use username from patient, migreate database first + req.Header.Set("X-Sync-UserName", "dave") + resp, err := http.DefaultClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + respBody, _ := io.ReadAll(resp.Body) + return respBody, nil +} diff --git a/internal/use-case/simgos-sync-use-case/old/patient/helper.go b/internal/use-case/simgos-sync-use-case/old/patient/helper.go new file mode 100644 index 00000000..2d89bff9 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/old/patient/helper.go @@ -0,0 +1,69 @@ +package patient + +import ( + "reflect" + "strings" +) + +func SetPatient(dst, src interface{}, preserve map[string]bool) { + dv := reflect.ValueOf(dst).Elem() + sv := reflect.ValueOf(src).Elem() + + for i := 0; i < dv.NumField(); i++ { + f := dv.Type().Field(i) + fieldName := f.Name + + // skip preserved fields + if preserve[fieldName] { + continue + } + + df := dv.Field(i) + sf := sv.Field(i) + if !df.CanSet() { + // skip unexported skip + continue + } + + switch df.Kind() { + + case reflect.Struct: + nestedPreserve := map[string]bool{} + + for key := range preserve { + if strings.HasPrefix(key, fieldName+".") { + nestedPreserve[strings.TrimPrefix(key, fieldName+".")] = true + } + } + + SetPatient(df.Addr().Interface(), sf.Addr().Interface(), nestedPreserve) + case reflect.Pointer: + // Check if pointer points to a struct + if df.Type().Elem().Kind() == reflect.Struct { + if sf.IsNil() { + break + } + + // If dest pointer is nil, allocate it + if df.IsNil() { + df.Set(reflect.New(df.Type().Elem())) + } + + // Recurse into struct via Elem() + nestedPreserve := map[string]bool{} + for key := range preserve { + if strings.HasPrefix(key, fieldName+".") { + nestedPreserve[strings.TrimPrefix(key, fieldName+".")] = true + } + } + + SetPatient(df.Elem().Addr().Interface(), sf.Elem().Addr().Interface(), nestedPreserve) + } + default: + // Overwrite only when src has non-zero value + if !sf.IsZero() { + df.Set(sf) + } + } + } +} diff --git a/internal/use-case/simgos-sync-use-case/old/patient/lib.go b/internal/use-case/simgos-sync-use-case/old/patient/lib.go new file mode 100644 index 00000000..d6b5f470 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/old/patient/lib.go @@ -0,0 +1,19 @@ +package patient + +import ( + esync "simrs-vx/internal/domain/sync-entities/patient" + + dg "github.com/karincake/apem/db-gorm-pg" +) + +func ReadDetailLinkData(simgosId uint) (*esync.PatientLink, error) { + // log event + var data esync.PatientLink + var tx = dg.I + + if err := tx.Where("\"Simgos_Id\" = ?", simgosId).First(&data).Error; err != nil { + return nil, err + } + // log end event + return &data, nil +} diff --git a/internal/use-case/simgos-sync-use-case/old/patient/tycovar.go b/internal/use-case/simgos-sync-use-case/old/patient/tycovar.go new file mode 100644 index 00000000..15d99d0f --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/old/patient/tycovar.go @@ -0,0 +1,14 @@ +package patient + +import e "simrs-vx/internal/domain/main-entities/patient" + +type MainApiResp struct { + Meta MetaData `json:"meta"` + Data e.Patient `json:"data"` +} + +type MetaData struct { + Source string `json:"source"` + Status string `json:"status"` + Structure string `json:"structure"` +}