From 856bcd8f3d1e60a259d36be7938c3f3d32c288c9 Mon Sep 17 00:00:00 2001 From: poetrasapoetra Date: Fri, 28 Nov 2025 12:53:44 +0700 Subject: [PATCH 1/6] Sync old-to-new patient handler --- .../domain/simgos-entities/patient/dto.go | 273 ++++++++++++++++++ .../old/patient/handler.go | 88 ++++++ .../simgos-sync-handler.go | 5 + 3 files changed, 366 insertions(+) create mode 100644 internal/domain/simgos-entities/patient/dto.go create mode 100644 internal/interface/simgos-sync-handler/old/patient/handler.go diff --git a/internal/domain/simgos-entities/patient/dto.go b/internal/domain/simgos-entities/patient/dto.go new file mode 100644 index 00000000..77fe7449 --- /dev/null +++ b/internal/domain/simgos-entities/patient/dto.go @@ -0,0 +1,273 @@ +package patient + +import ( + "fmt" + 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" + pc "simrs-vx/internal/domain/main-entities/person-contact" + cm "simrs-vx/internal/domain/references/common" + rf "simrs-vx/internal/domain/references/person" + + "time" +) + +type MPasienDto struct { + Id uint `json:"id" gorm:"primaryKey;autoIncrement;column:id"` + Nomr string `json:"nomr" gorm:"uniqueIndex;column:nomr"` + Title string `json:"title" gorm:"column:title"` + Nama string `json:"nama" gorm:"column:nama"` + Tempat string `json:"tempat" gorm:"column:tempat"` + Tgllahir string `json:"tgllahir" gorm:"column:tgllahir"` + Jeniskelamin string `json:"jeniskelamin" gorm:"column:jeniskelamin"` + Alamat string `json:"alamat" gorm:"column:alamat"` + Kelurahan uint64 `json:"kelurahan" gorm:"column:kelurahan"` + Kdkecamatan uint `json:"kdkecamatan" gorm:"column:kdkecamatan"` + Kota uint `json:"kota" gorm:"column:kota"` + Kdprovinsi uint `json:"kdprovinsi" gorm:"column:kdprovinsi"` + Notelp string `json:"notelp" gorm:"column:notelp"` + Noktp string `json:"noktp" gorm:"column:noktp"` + SuamiOrtu *string `json:"suami_ortu" gorm:"column:suami_ortu"` + Pekerjaan string `json:"pekerjaan" gorm:"column:pekerjaan"` + Status uint `json:"status" gorm:"column:status"` + Agama uint `json:"agama" gorm:"column:agama"` + Pendidikan uint `json:"pendidikan" gorm:"column:pendidikan"` + Kdcarabayar *uint `json:"kdcarabayar" gorm:"column:kdcarabayar"` + Nip *string `json:"nip" gorm:"column:nip"` + Tgldaftar string `json:"tgldaftar" gorm:"column:tgldaftar"` + AlamatKtp string `json:"alamat_ktp" gorm:"column:alamat_ktp"` + ParentNomr *string `json:"parent_nomr" gorm:"column:parent_nomr"` + Kepercayaan string `json:"kepercayaan" gorm:"column:kepercayaan"` + PenanggungjawabNama string `json:"penanggungjawab_nama" gorm:"column:penanggungjawab_nama"` + PenanggungjawabHubungan string `json:"penanggungjawab_hubungan" gorm:"column:penanggungjawab_hubungan"` + PenanggungjawabAlamat string `json:"penanggungjawab_alamat" gorm:"column:penanggungjawab_alamat"` + PenanggungjawabPhone string `json:"penanggungjawab_phone" gorm:"column:penanggungjawab_phone"` + NoKartu string `json:"no_kartu" gorm:"column:no_kartu"` + JnsPasien string `json:"jns_pasien" gorm:"column:jns_pasien"` + Nk *string `json:"nk" gorm:"column:nk"` + Kdprovider *string `json:"kdprovider" gorm:"column:kdprovider"` + Nmprovider *string `json:"nmprovider" gorm:"column:nmprovider"` + Kelas *uint `json:"kelas" gorm:"column:kelas"` + Sim *string `json:"sim" gorm:"column:sim"` + Paspor *string `json:"paspor" gorm:"column:paspor"` + Disabilitas *string `json:"disabilitas" gorm:"column:disabilitas"` + Bahasa string `json:"bahasa" gorm:"column:bahasa"` + HambatanKomunikasi string `json:"hambatan_komunikasi" gorm:"column:hambatan_komunikasi"` + Kebangsaan string `json:"kebangsaan" gorm:"column:kebangsaan"` + Notelprumah1 string `json:"notelprumah1" gorm:"column:notelprumah1"` + Notelprumah2 *string `json:"notelprumah2" gorm:"column:notelprumah2"` + Notelpkantor string `json:"notelpkantor" gorm:"column:notelpkantor"` + NoHp *string `json:"no_hp" gorm:"column:no_hp"` + AsalMasuk *string `json:"asal_masuk" gorm:"column:asal_masuk"` + Diagnosa *string `json:"diagnosa" gorm:"column:diagnosa"` + DiagnosaUtama *string `json:"diagnosa_utama" gorm:"column:diagnosa_utama"` + Suku string `json:"suku" gorm:"column:suku"` + AgamaLain string `json:"agama_lain" gorm:"column:agama_lain"` + StDisabilitas uint `json:"stDisabilitas" gorm:"column:st_disabilitas"` + TxtKelurahan string `json:"txt_kelurahan" gorm:"column:txt_kelurahan"` + TxtKecamatan string `json:"txt_kecamatan" gorm:"column:txt_kecamatan"` + TxtKota string `json:"txt_kota" gorm:"column:txt_kota"` + TxtProvinsi string `json:"txt_provinsi" gorm:"column:txt_provinsi"` + TxtStatus string `json:"txt_status" gorm:"column:txt_status"` + TxtAgama string `json:"txt_agama" gorm:"column:txt_agama"` + TxtPendidikan string `json:"txt_pendidikan" gorm:"column:txt_pendidikan"` + NamaAyah string `json:"nama_ayah" gorm:"column:nama_ayah"` + NamaIbu string `json:"nama_ibu" gorm:"column:nama_ibu"` + PendidikanAyah string `json:"pendidikan_ayah" gorm:"column:pendidikan_ayah"` + PendidikanIbu string `json:"pendidikan_ibu" gorm:"column:pendidikan_ibu"` + StIdentitasOrtu int `json:"st_identitas_ortu" gorm:"column:st_identitas_ortu"` + NomrBaru *string `json:"nomr_baru" gorm:"column:nomr_baru"` + KtpFile *string `json:"ktp_file" gorm:"column:ktp_file"` + KkFile *string `json:"kk_file" gorm:"column:kk_file"` + CreatedAt *time.Time `json:"created_at" gorm:"column:created_at"` + UpdatedAt *time.Time `json:"updated_at" gorm:"column:updated_at"` + NoKk *string `json:"no_kk" gorm:"column:no_kk"` + NoktpBaru string `json:"noktp_baru" gorm:"column:noktp_baru"` +} + +func (mp MPasienDto) ToPatient() e.Patient { + + patient := e.Patient{ + Person_Id: &mp.Id, + NewBornStatus: mp.ParentNomr != nil, + RegisteredAt: parseTimeDateOnly(mp.Tgldaftar), + RegisteredBy_User_Name: mp.Nip, + Number: &mp.Nomr, + Parent_Number: mp.ParentNomr, + // Status_Code: getActiveStatus(mp.Status), + // mp.Status is marital status + // Parent + } + + // person + gc := getGender(mp.Jeniskelamin) + rc := getReligion(mp.Agama) + ec := getEducation(mp.Pendidikan) + mc := getMaritalStatus(mp.Status) + bc := getBirthRegencyCode(mp.Tempat) + et := getEthnicCode(mp.Suku) + lc := getLanguageCode(mp.Bahasa) + + person := pr.Person{ + Name: mp.Nama, + FrontTitle: &mp.Title, + BirthDate: parseTimeDateOnly(mp.Tgllahir), + BirthRegency_Code: &bc, + Gender_Code: &gc, + ResidentIdentityNumber: nilEmptyString(*mp.Nip), + PassportNumber: nilEmptyString(*mp.Paspor), + DrivingLicenseNumber: nilEmptyString(*mp.Sim), + Religion_Code: &rc, + Education_Code: &ec, + Ocupation_Name: &mp.Pekerjaan, + MaritalStatus_Code: &mc, + Nationality: &mp.Kebangsaan, + Ethnic_Code: &et, + Language_Code: &lc, + CommunicationIssueStatus: mp.HambatanKomunikasi == "Y", + Disability: mp.Disabilitas, + ResidentIdentityFileUrl: mp.KtpFile, + FamilyIdentityFileUrl: mp.KkFile, + // EndTitle + // Confidence + // Ocupation_Code + } + var addresses []pa.PersonAddress + if mp.Alamat != "" { + vc := fmt.Sprintf("%d", mp.Kelurahan) + addresses = append(addresses, pa.PersonAddress{ + Address: mp.Alamat, + LocationType_Code: rf.ALTCDom, + Village_Code: &vc, + }) + } + if mp.AlamatKtp != "" { + addresses = append(addresses, pa.PersonAddress{ + Address: mp.AlamatKtp, + LocationType_Code: rf.ALTCIdn, + }) + } + + var contacts []pc.PersonContact + + if mp.NoHp != nil { + + } + + person.Addresses = &addresses + person.Contacts = &contacts + patient.Person = &person + return patient +} + +func getActiveStatus(s uint) cm.ActiveStatusCode { + if s == 1 { + return cm.SCActive + } + return cm.SCInactive +} + +func nilEmptyString(s string) *string { + if s == "" { + return nil + } + return &s +} + +func getGender(g string) rf.GenderCode { + if g == "L" { + return rf.GCMale + } else if g == "P" { + return rf.GCFemale + } + return rf.GCUnknown + +} + +func getReligion(r uint) rf.ReligionCode { + switch r { + case 1: + return rf.RCIslam + case 2: + return rf.RCProtestan + case 3: + return rf.RCKatolik + case 4: + return rf.RCHindu + case 5: + return rf.RCBudha + case 6: + return rf.RCKonghucu + default: + // 9 "Lainnya" + // 0 "Tidak diketahui" + return "" + } +} + +func getEducation(e uint) rf.EducationCode { + switch e { + case 0: + return rf.ECTS + case 1: + return rf.ECSD + case 2: + return rf.ECSLTP + case 3: + return rf.ECSLTA + case 4: + return rf.ECD3 + case 5: + return rf.ECS1 + case 6: + return rf.ECOther + case 7: + return rf.ECUnkown + default: + return rf.ECUnkown + } +} + +func getMaritalStatus(m uint) rf.MaritalStatusCode { + switch m { + case 1: + return rf.MaritalStatusSingle // S + case 2: + return rf.MaritalStatusMarried // M + case 3: + return rf.MaritalStatusWidowed // W + case 4: + return rf.MaritalStatusDivorced // D + default: + return "" // unknown + } +} + +func getBirthRegencyCode(r string) string { + if r != "" { + // TODO get from database + } + return "3574" +} + +func getEthnicCode(s string) string { + if s != "" { + // TODO check database + } + return "jawa" +} + +func getLanguageCode(s string) string { + if s != "" { + // TODO check database + } + return "jawa" +} + +func parseTimeDateOnly(d string) *time.Time { + do, err := time.Parse("2006-01-02", d) + if err == nil { + return &do + } + return nil +} diff --git a/internal/interface/simgos-sync-handler/old/patient/handler.go b/internal/interface/simgos-sync-handler/old/patient/handler.go new file mode 100644 index 00000000..970111e0 --- /dev/null +++ b/internal/interface/simgos-sync-handler/old/patient/handler.go @@ -0,0 +1,88 @@ +package patient + +import ( + "bytes" + "encoding/json" + "fmt" + "net/http" + + rw "github.com/karincake/risoles" + + p "simrs-vx/internal/domain/simgos-entities/patient" +) + +type myBase struct{} + +var O myBase + +const baseUrl string = "http://localhost:8000/v1/" + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := p.MPasienDto{} + if !rw.ValidateStructByIOR(w, r.Body, &dto) { + return + } + // translate m_pasien ke 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, baseUrl+"patient", reqBody) + if err != nil { + fmt.Println("request error:", 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() + jsonPatient, err := json.Marshal(patient) + if err != nil { + fmt.Println(err) + } + reqBody := bytes.NewBuffer(jsonPatient) + err = send(http.MethodPatch, fmt.Sprintf("%s%s%v", baseUrl, "patient/", patient.Id), reqBody) + if err != nil { + fmt.Println("request error:", 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%s%v", baseUrl, "patient/", patient.Id), reqBody) + if err != nil { + fmt.Println("request error:", err) + } +} +func (obj myBase) CreateLog(w http.ResponseWriter, r *http.Request) { + +} + +func send(method string, url string, body *bytes.Buffer) error { + req, err := http.NewRequest(method, url, body) + 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() + return nil +} diff --git a/internal/interface/simgos-sync-handler/simgos-sync-handler.go b/internal/interface/simgos-sync-handler/simgos-sync-handler.go index 2a67b7e9..a23e110c 100644 --- a/internal/interface/simgos-sync-handler/simgos-sync-handler.go +++ b/internal/interface/simgos-sync-handler/simgos-sync-handler.go @@ -8,6 +8,7 @@ import ( /******************** infra ********************/ gs "simrs-vx/internal/infra/gorm-setting" simgosdb "simrs-vx/internal/infra/simgos-db" + /******************** pkg ********************/ cmw "simrs-vx/pkg/cors-manager-mw" lh "simrs-vx/pkg/lang-helper" @@ -20,6 +21,7 @@ import ( "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" + oldPatient "simrs-vx/internal/interface/simgos-sync-handler/old/patient" patient "simrs-vx/internal/interface/simgos-sync-handler/patient" specialist "simrs-vx/internal/interface/simgos-sync-handler/specialist" subspecialist "simrs-vx/internal/interface/simgos-sync-handler/subspecialist" @@ -48,5 +50,8 @@ func SetRoutes() http.Handler { hc.SyncCrud(r, prefix+"/v1/patient", patient.O) r.HandleFunc(fmt.Sprintf("GET %s/v1/patient-nomr-generator", prefix), patient.O.GenerateNomr) + /*********** Source old-to-new ****************/ + oldPrefix := "/old-to-new" + hc.SyncCrud(r, oldPrefix+"/v1/patient", oldPatient.O) return cmw.SetCors(handlerlogger.SetLog(r)) } From 0decd8330a178933a3a5e5bb79563b553baa87ee Mon Sep 17 00:00:00 2001 From: poetrasapoetra Date: Fri, 28 Nov 2025 17:26:58 +0700 Subject: [PATCH 2/6] Change Address --- internal/domain/simgos-entities/m-pasien/dto.go | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/internal/domain/simgos-entities/m-pasien/dto.go b/internal/domain/simgos-entities/m-pasien/dto.go index 77fe7449..b117655d 100644 --- a/internal/domain/simgos-entities/m-pasien/dto.go +++ b/internal/domain/simgos-entities/m-pasien/dto.go @@ -1,10 +1,11 @@ -package patient +package m_pasien import ( "fmt" 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" @@ -136,15 +137,19 @@ func (mp MPasienDto) ToPatient() e.Patient { if mp.Alamat != "" { vc := fmt.Sprintf("%d", mp.Kelurahan) addresses = append(addresses, pa.PersonAddress{ - Address: mp.Alamat, - LocationType_Code: rf.ALTCDom, - Village_Code: &vc, + PersonAddress: pab.PersonAddress{ + Address: mp.Alamat, + LocationType_Code: rf.ALTCDom, + Village_Code: &vc, + }, }) } if mp.AlamatKtp != "" { addresses = append(addresses, pa.PersonAddress{ - Address: mp.AlamatKtp, - LocationType_Code: rf.ALTCIdn, + PersonAddress: pab.PersonAddress{ + Address: mp.AlamatKtp, + LocationType_Code: rf.ALTCIdn, + }, }) } From af6ff9294801d0386b398a0a6c91e7df26b20bdc Mon Sep 17 00:00:00 2001 From: poetrasapoetra Date: Fri, 28 Nov 2025 17:29:12 +0700 Subject: [PATCH 3/6] Add header to handler --- .../simgos-sync-handler/old/patient/handler.go | 14 ++++++++++---- .../simgos-sync-handler/simgos-sync-handler.go | 10 ++++++++-- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/internal/interface/simgos-sync-handler/old/patient/handler.go b/internal/interface/simgos-sync-handler/old/patient/handler.go index 970111e0..44d202a9 100644 --- a/internal/interface/simgos-sync-handler/old/patient/handler.go +++ b/internal/interface/simgos-sync-handler/old/patient/handler.go @@ -6,9 +6,10 @@ import ( "fmt" "net/http" - rw "github.com/karincake/risoles" + p "simrs-vx/internal/domain/simgos-entities/m-pasien" + cfg "simrs-vx/internal/infra/sync-cfg" - p "simrs-vx/internal/domain/simgos-entities/patient" + rw "github.com/karincake/risoles" ) type myBase struct{} @@ -47,8 +48,11 @@ func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { if err != nil { fmt.Println(err) } + // fmt.Println(string(jsonPatient)) + url := fmt.Sprintf("%s%s%v", baseUrl, "patient/", *patient.Person_Id) + fmt.Println(url) reqBody := bytes.NewBuffer(jsonPatient) - err = send(http.MethodPatch, fmt.Sprintf("%s%s%v", baseUrl, "patient/", patient.Id), reqBody) + err = send(http.MethodPatch, url, reqBody) if err != nil { fmt.Println("request error:", err) } @@ -64,7 +68,7 @@ func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { fmt.Println(err) } reqBody := bytes.NewBuffer(jsonPatient) - err = send(http.MethodDelete, fmt.Sprintf("%s%s%v", baseUrl, "patient/", patient.Id), reqBody) + err = send(http.MethodDelete, fmt.Sprintf("%s%s%v", baseUrl, "patient/", *patient.Person_Id), reqBody) if err != nil { fmt.Println("request error:", err) } @@ -79,6 +83,8 @@ func send(method string, url string, body *bytes.Buffer) error { 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) resp, err := http.DefaultClient.Do(req) if err != nil { return err diff --git a/internal/interface/simgos-sync-handler/simgos-sync-handler.go b/internal/interface/simgos-sync-handler/simgos-sync-handler.go index 17b5bd1e..7d7887f0 100644 --- a/internal/interface/simgos-sync-handler/simgos-sync-handler.go +++ b/internal/interface/simgos-sync-handler/simgos-sync-handler.go @@ -6,7 +6,7 @@ import ( /******************** infra ********************/ gs "simrs-vx/internal/infra/gorm-setting" simgosdb "simrs-vx/internal/infra/simgos-db" - sync "simrs-vx/internal/infra/sync-consumer-cfg" + sync "simrs-vx/internal/infra/sync-cfg" /******************** pkg ********************/ cmw "simrs-vx/pkg/cors-manager-mw" @@ -29,6 +29,8 @@ import ( "simrs-vx/internal/interface/simgos-sync-handler/new/subspecialist" "simrs-vx/internal/interface/simgos-sync-handler/new/unit" + oldpatient "simrs-vx/internal/interface/simgos-sync-handler/old/patient" + oauth "simrs-vx/internal/interface/simgos-sync-handler/old/authentication" // just a reminder, an openauth ) @@ -71,6 +73,10 @@ func SetRoutes() http.Handler { /******************** SvcToNew ******************/ prefixold := "/old-to-new" - hk.GroupRoutes(prefixold+"/v1/patient", r, oauth.OldGuardMW, hk.MapHandlerFunc{}) // FINISH THIS + hk.GroupRoutes(prefixold+"/v1/patient", r, oauth.OldGuardMW, hk.MapHandlerFunc{ + "POST /": oldpatient.O.Create, + "PATCH /{id}": oldpatient.O.Update, + "DELETE /{id}": oldpatient.O.Delete, + }) // FINISH THIS return cmw.SetCors(handlerlogger.SetLog(r)) } From 6a49f09180bb7a0f11182f6ebf784a975539b024 Mon Sep 17 00:00:00 2001 From: poetrasapoetra Date: Fri, 28 Nov 2025 19:43:53 +0700 Subject: [PATCH 4/6] Fix update patient --- .../domain/simgos-entities/m-pasien/dto.go | 3 +- .../old/patient/handler.go | 28 +++++++++++++------ 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/internal/domain/simgos-entities/m-pasien/dto.go b/internal/domain/simgos-entities/m-pasien/dto.go index b117655d..68a2d068 100644 --- a/internal/domain/simgos-entities/m-pasien/dto.go +++ b/internal/domain/simgos-entities/m-pasien/dto.go @@ -89,6 +89,7 @@ type MPasienDto struct { func (mp MPasienDto) ToPatient() e.Patient { patient := e.Patient{ + // TODO get patient person_id from database Person_Id: &mp.Id, NewBornStatus: mp.ParentNomr != nil, RegisteredAt: parseTimeDateOnly(mp.Tgldaftar), @@ -115,7 +116,7 @@ func (mp MPasienDto) ToPatient() e.Patient { BirthDate: parseTimeDateOnly(mp.Tgllahir), BirthRegency_Code: &bc, Gender_Code: &gc, - ResidentIdentityNumber: nilEmptyString(*mp.Nip), + ResidentIdentityNumber: nilEmptyString(mp.Noktp), PassportNumber: nilEmptyString(*mp.Paspor), DrivingLicenseNumber: nilEmptyString(*mp.Sim), Religion_Code: &rc, diff --git a/internal/interface/simgos-sync-handler/old/patient/handler.go b/internal/interface/simgos-sync-handler/old/patient/handler.go index 44d202a9..b794de07 100644 --- a/internal/interface/simgos-sync-handler/old/patient/handler.go +++ b/internal/interface/simgos-sync-handler/old/patient/handler.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/json" "fmt" + "io" "net/http" p "simrs-vx/internal/domain/simgos-entities/m-pasien" @@ -16,8 +17,6 @@ type myBase struct{} var O myBase -const baseUrl string = "http://localhost:8000/v1/" - func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { dto := p.MPasienDto{} if !rw.ValidateStructByIOR(w, r.Body, &dto) { @@ -32,7 +31,7 @@ func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { // fmt.Println(string(jsonPatient)) // kirim request ke api sim-baru reqBody := bytes.NewBuffer(jsonPatient) - err = send(http.MethodPost, baseUrl+"patient", reqBody) + err = send(http.MethodPost, "patient", reqBody) if err != nil { fmt.Println("request error:", err) } @@ -44,12 +43,21 @@ func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { return } patient := dto.ToPatient() - jsonPatient, err := json.Marshal(patient) + // 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%s%v", baseUrl, "patient/", *patient.Person_Id) + 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) @@ -68,7 +76,7 @@ func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { fmt.Println(err) } reqBody := bytes.NewBuffer(jsonPatient) - err = send(http.MethodDelete, fmt.Sprintf("%s%s%v", baseUrl, "patient/", *patient.Person_Id), reqBody) + err = send(http.MethodDelete, fmt.Sprintf("%s%v", "patient/", *patient.Person_Id), reqBody) if err != nil { fmt.Println("request error:", err) } @@ -77,7 +85,8 @@ func (obj myBase) CreateLog(w http.ResponseWriter, r *http.Request) { } -func send(method string, url string, body *bytes.Buffer) error { +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 @@ -85,10 +94,13 @@ func send(method string, url string, body *bytes.Buffer) error { 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 } From 547a54cbe4a93107c96af30f1c6599cdca5d163c Mon Sep 17 00:00:00 2001 From: poetrasapoetra Date: Wed, 3 Dec 2025 10:37:50 +0700 Subject: [PATCH 5/6] 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"` +} From 11ed6e3ad5d3053b1d249207b78239067807efc4 Mon Sep 17 00:00:00 2001 From: poetrasapoetra Date: Wed, 3 Dec 2025 10:48:19 +0700 Subject: [PATCH 6/6] Using username from m_pasien.nip --- .../simgos-sync-use-case/old/patient/case.go | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) 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 index ae52e37a..09afa2bd 100644 --- a/internal/use-case/simgos-sync-use-case/old/patient/case.go +++ b/internal/use-case/simgos-sync-use-case/old/patient/case.go @@ -35,7 +35,7 @@ func Create(input e.Patient) (*d.Data, error) { } reqBody := bytes.NewBuffer(jsonPatient) // send data to main-api - resp, err := send(http.MethodPost, path, reqBody) + resp, err := send(http.MethodPost, path, reqBody, *input.RegisteredBy_User_Name) if err != nil { return nil, pl.SetLogError(&evt, input) } @@ -72,7 +72,7 @@ func Update(input e.Patient) (*d.Data, error) { } // get data patient from main-api - resp, err := send(http.MethodGet, fmt.Sprintf("%s%v", "patient/", patientLink.Simx_Id), nil) + resp, err := send(http.MethodGet, fmt.Sprintf("%s%v", "patient/", patientLink.Simx_Id), nil, *input.RegisteredBy_User_Name) if err != nil { return nil, pl.SetLogError(&evt, input) } @@ -99,7 +99,7 @@ func Update(input e.Patient) (*d.Data, error) { // send data to main api url := fmt.Sprintf("%s%v", "patient/", simxPatient.Id) reqBody := bytes.NewBuffer(jsonPatient) - _, err = send(http.MethodPatch, url, reqBody) + _, err = send(http.MethodPatch, url, reqBody, *input.RegisteredBy_User_Name) if err != nil { return nil, pl.SetLogError(&evt, input) } @@ -127,7 +127,7 @@ func Delete(input e.Patient) (*d.Data, error) { if err != nil { return nil, err } - _, err = send(http.MethodDelete, fmt.Sprintf("%s%v", "patient/", patientLink.Simx_Id), nil) + _, err = send(http.MethodDelete, fmt.Sprintf("%s%v", "patient/", patientLink.Simx_Id), nil, *input.RegisteredBy_User_Name) if err != nil { return nil, err } @@ -141,7 +141,7 @@ func Delete(input e.Patient) (*d.Data, error) { }, nil } -func send(method string, endpoint string, body *bytes.Buffer) ([]byte, error) { +func send(method string, endpoint string, body *bytes.Buffer, username string) ([]byte, error) { var url string = cfg.O.NewHost + endpoint var reader io.Reader = nil if body != nil { @@ -154,8 +154,7 @@ func send(method string, endpoint string, body *bytes.Buffer) ([]byte, error) { 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") + req.Header.Set("X-Sync-UserName", username) resp, err := http.DefaultClient.Do(req) if err != nil { return nil, err