Fix CUD Patient

This commit is contained in:
poetrasapoetra
2025-12-03 10:37:50 +07:00
parent 3b7d6eac29
commit 547a54cbe4
6 changed files with 290 additions and 86 deletions
+10 -16
View File
@@ -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 {
@@ -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)
}
@@ -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
}
@@ -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)
}
}
}
}
@@ -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
}
@@ -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"`
}