From 2e70cd727c9eb5730bef2ac30c468c39ba5f7ccb Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Thu, 11 Dec 2025 15:29:01 +0700 Subject: [PATCH 1/8] feat (encounter): create-with-patient wip --- .../domain/main-entities/encounter/dto.go | 5 + .../main-handler/encounter/handler.go | 26 ++++ .../interface/main-handler/main-handler.go | 1 + .../use-case/main-use-case/encounter/case.go | 143 ++++++++++++++++++ .../encounter/middleware-runner.go | 19 +++ .../main-use-case/encounter/tycovar.go | 7 + .../use-case/main-use-case/patient/case.go | 27 ++-- 7 files changed, 218 insertions(+), 10 deletions(-) diff --git a/internal/domain/main-entities/encounter/dto.go b/internal/domain/main-entities/encounter/dto.go index 324501e4..9265978b 100644 --- a/internal/domain/main-entities/encounter/dto.go +++ b/internal/domain/main-entities/encounter/dto.go @@ -297,3 +297,8 @@ func ToResponseList(data []Encounter) []ResponseDto { } return resp } + +type CreateWithPatientDto struct { + Encounter CreateDto `json:"encounter"` + Patient ep.CreateDto `json:"patient"` +} diff --git a/internal/interface/main-handler/encounter/handler.go b/internal/interface/main-handler/encounter/handler.go index 7ac31393..c6a02ba9 100644 --- a/internal/interface/main-handler/encounter/handler.go +++ b/internal/interface/main-handler/encounter/handler.go @@ -312,3 +312,29 @@ func (obj myBase) CancelSwitchUnit(w http.ResponseWriter, r *http.Request) { res, err := u.CancelSwitchUnit(dto) rw.DataResponse(w, res, err) } + +func (obj myBase) CreateWithPatient(w http.ResponseWriter, r *http.Request) { + authInfo, err := pa.GetAuthInfo(r) + if err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil) + } + + dto := e.CreateWithPatientDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + + // validate SubClass + if err := verifyClassCode(dto.Encounter); err != nil { + rw.DataResponse(w, nil, d.FieldError{ + Code: dataValidationFail, + Message: err.Error(), + }) + return + } + + dto.Encounter.AuthInfo = *authInfo + dto.Patient.AuthInfo = *authInfo + res, err := u.CreateWithPatient(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index f6f6bfce..c47ae37d 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -197,6 +197,7 @@ func SetRoutes() http.Handler { "PATCH /{id}/req-switch-unit": encounter.O.RequestSwitchUnit, "PATCH /{id}/approve-switch-unit": encounter.O.ApproveSwitchUnit, "PATCH /{id}/cancel-switch-unit": encounter.O.CancelSwitchUnit, + "POST /create-with-patient": encounter.O.CreateWithPatient, }) hk.GroupRoutes("/v1/mcu-order", r, auth.GuardMW, hk.MapHandlerFunc{ "GET /": mcuorder.O.GetList, diff --git a/internal/use-case/main-use-case/encounter/case.go b/internal/use-case/main-use-case/encounter/case.go index 62a7c992..3b966ef9 100644 --- a/internal/use-case/main-use-case/encounter/case.go +++ b/internal/use-case/main-use-case/encounter/case.go @@ -22,12 +22,14 @@ import ( edc "simrs-vx/internal/domain/main-entities/death-cause" e "simrs-vx/internal/domain/main-entities/encounter" eir "simrs-vx/internal/domain/main-entities/internal-reference" + ep "simrs-vx/internal/domain/main-entities/patient" es "simrs-vx/internal/domain/main-entities/soapi" esync "simrs-vx/internal/domain/sync-entities/log" uv "simrs-vx/internal/use-case/bpjs-use-case/vclaim-reference" udc "simrs-vx/internal/use-case/main-use-case/death-cause" uir "simrs-vx/internal/use-case/main-use-case/internal-reference" + up "simrs-vx/internal/use-case/main-use-case/patient" us "simrs-vx/internal/use-case/main-use-case/soapi" ) @@ -1075,3 +1077,144 @@ func validateAuth(a auth.AuthInfo, roleAllowed []string, action string, event *p return nil } + +func CreateWithPatient(input e.CreateWithPatientDto) (*d.Data, error) { + var ( + data e.Encounter + recentSoapiDataforCopy []es.CreateDto + err error + ) + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + roleAllowed := []string{string(erg.EPCReg)} + err = validateAuth(input.Encounter.AuthInfo, roleAllowed, "create-encounter", &event) + if err != nil { + return nil, err + } + + // validate rehab by bpjs + if input.Encounter.RefTypeCode == ere.RTCBpjs && + input.Encounter.Class_Code == ere.ECAmbulatory && + ere.AmbulatoryClassCode(*input.Encounter.SubClass_Code) == ere.ACCRehab { + // get latest rehab data + recentRehabData, err := getLatestRehabData(input.Encounter, &event) + if err != nil { + return nil, err + } + + // If recentRehabData is nil, then visitMode_Code = "adm" + if recentRehabData != nil { + // If recentRehabData is not nil, determine the visitMode_Code: + // If the mode is "series", verify whether the visit count still remains + // and whether the series has not expired. + // If visitMode is "series", then get encounterAdm + input.Encounter.VisitMode_Code, input.Encounter.RecentEncounterAdm, err = determineVisitMode(recentRehabData, input.Encounter, &event) + if err != nil { + return nil, err + } + } else { + input.Encounter.VisitMode_Code = ere.VMCAdm + } + + // When visitMode_Code is "series", load the associated SOAPI record to copy its values. + if input.Encounter.VisitMode_Code == ere.VMCSeries { + // get data soapi + recentSoapiDataforCopy, err = getSoapiEncounterAdm(*input.Encounter.RecentEncounterAdm, &event) + if err != nil { + return nil, err + } + } + } + + // check if patient is new in the hospital + input.Encounter.NewStatus, err = identifyPatientStatus(input.Encounter) + if err != nil { + return nil, err + } + input.Encounter.Adm_Employee_Id = input.Encounter.AuthInfo.Employee_Id + + mwRunner := newMiddlewareRunner(&event, input.Encounter.Sync) + + err = dg.I.Transaction(func(tx *gorm.DB) error { + // create patient + var patientId uint + patientData, err := up.Create(input.Patient, tx) + if err != nil { + return err + } + + if patientData != nil { + patientId = patientData.Data.(*ep.Patient).Id + } + + // create encounter + input.Encounter.Patient_Id = &patientId + if resData, err := CreateData(input.Encounter, &event, tx); err != nil { + return err + } else { + data = *resData + input.Encounter.Id = data.Id + } + + // insert ambulatory/emergency/inpatient + err = insertdataClassCode(input.Encounter, recentSoapiDataforCopy, &event, tx) + if err != nil { + return err + } + + // insert vclaimReference + if vr := input.Encounter.VclaimReference; vr != nil { + t, _ := time.Parse("2006-01-02", vr.TglRujukan) + _, err = uv.CreateData(ev.CreateDto{ + Encounter_Id: &data.Id, + Date: &t, + SrcCode: input.Encounter.Ref_Number, + SrcName: input.Encounter.RefSource_Name, + Number: &vr.NoSep}, &event, tx) + if err != nil { + return err + } + } + + dataEncounter, err := ReadDetailData(e.ReadDetailDto{ + Id: data.Id, + Includes: "Adm_Employee.User,Adm_Employee.Person," + + "Patient.Person.Relatives," + + "Patient.Person.VclaimMember,VclaimReference," + + "Patient.Person.Contacts,Patient.Person.Addresses"}, + &event, tx) + if err != nil { + return err + } + + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunCreateWithPatientMiddleware(createWithPatientPreMw, dataEncounter); err != nil { + return err + } + + return nil + }) + + if err = runLogMiddleware(err, input, mwRunner); err != nil { + return nil, err + } + + pl.SetLogInfo(&event, nil, "complete") + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: data.ToResponse(), + }, nil +} diff --git a/internal/use-case/main-use-case/encounter/middleware-runner.go b/internal/use-case/main-use-case/encounter/middleware-runner.go index da62fdb6..3ee19355 100644 --- a/internal/use-case/main-use-case/encounter/middleware-runner.go +++ b/internal/use-case/main-use-case/encounter/middleware-runner.go @@ -259,3 +259,22 @@ func (me *middlewareRunner) RunCancelSwitchUnitMiddleware(middleware cancelSwitc func (me *middlewareRunner) setMwType(mwType pu.MWType) { me.MwType = mwType } + +func (me *middlewareRunner) RunCreateWithPatientMiddleware(middlewares []createWithPatientMw, input *e.Encounter) error { + if !me.SyncOn { + return nil + } + + for _, middleware := range middlewares { + logData := pu.GetLogData(input, nil) + + pl.SetLogInfo(me.Event, logData, "started", middleware.Name) + + if err := middleware.Func(input); err != nil { + return pu.HandleMiddlewareError(me.Event, string(me.MwType), middleware.Name, logData, err) + } + + pl.SetLogInfo(me.Event, nil, "complete") + } + return nil +} diff --git a/internal/use-case/main-use-case/encounter/tycovar.go b/internal/use-case/main-use-case/encounter/tycovar.go index 2b268378..376baed8 100644 --- a/internal/use-case/main-use-case/encounter/tycovar.go +++ b/internal/use-case/main-use-case/encounter/tycovar.go @@ -74,6 +74,11 @@ type cancelSwitchUnitMw struct { Func func(input *e.ApproveCancelUnitDto) error } +type createWithPatientMw struct { + Name string + Func func(input *e.Encounter) error +} + type UpdateMw = updateMw type DeleteMw = deleteMw @@ -94,3 +99,5 @@ var updatestatusEncounter []updateStatusMw var requestSwitchEncounter requestSwitchUnitMw var approveSwitchEncounter approveSwitchUnitMw var cancelSwitchEncounter cancelSwitchUnitMw +var createWithPatientPreMw []createWithPatientMw +var createWithPatientPostMw []createWithPatientMw diff --git a/internal/use-case/main-use-case/patient/case.go b/internal/use-case/main-use-case/patient/case.go index 5180137b..ec518fe4 100644 --- a/internal/use-case/main-use-case/patient/case.go +++ b/internal/use-case/main-use-case/patient/case.go @@ -27,7 +27,7 @@ import ( const source = "patient" -func Create(input e.CreateDto) (*d.Data, error) { +func Create(input e.CreateDto, dbx ...*gorm.DB) (*d.Data, error) { data := e.Patient{} event := pl.Event{ @@ -35,6 +35,13 @@ func Create(input e.CreateDto) (*d.Data, error) { Source: source, } + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + // Start log pl.SetLogInfo(&event, input, "started", "create") mwRunner := newMiddlewareRunner(&event, input.Sync) @@ -51,7 +58,7 @@ func Create(input e.CreateDto) (*d.Data, error) { input.RegisteredBy_User_Name = &input.AuthInfo.User_Name - err := dg.I.Transaction(func(tx *gorm.DB) error { + err := tx.Transaction(func(tx1 *gorm.DB) error { mwRunner.setMwType(pu.MWTPre) // Run pre-middleware if err := mwRunner.RunCreateMiddleware(createPreMw, &input, &data); err != nil { @@ -65,14 +72,14 @@ func Create(input e.CreateDto) (*d.Data, error) { } input.Number = nomr - if person_id, err := upe.CreateOrUpdatePerson(input.Person, &event, tx); err != nil { + if person_id, err := upe.CreateOrUpdatePerson(input.Person, &event, tx1); err != nil { return err } else { input.Person_Id = person_id } if input.Person.VclaimMember_CardNumber != nil && input.Person.ResidentIdentityNumber != nil { - if err := uvm.CreateOrUpdateData(evm.CreateDto{CardNumber: input.Person.VclaimMember_CardNumber, Person_Id: input.Person_Id}, &event, tx); err != nil { + if err := uvm.CreateOrUpdateData(evm.CreateDto{CardNumber: input.Person.VclaimMember_CardNumber, Person_Id: input.Person_Id}, &event, tx1); err != nil { return err } } @@ -80,38 +87,38 @@ func Create(input e.CreateDto) (*d.Data, error) { for idx := range input.PersonAddresses { input.PersonAddresses[idx].Person_Id = *input.Person_Id } - if err := upa.CreateOrUpdateBatch(input.PersonAddresses, &event, tx); err != nil { + if err := upa.CreateOrUpdateBatch(input.PersonAddresses, &event, tx1); err != nil { return err } for idx := range input.PersonContacts { input.PersonContacts[idx].Person_Id = *input.Person_Id } - if err := upc.CreateOrUpdateBatch(input.PersonContacts, &event, tx); err != nil { + if err := upc.CreateOrUpdateBatch(input.PersonContacts, &event, tx1); err != nil { return err } for idx := range input.PersonRelatives { input.PersonRelatives[idx].Person_Id = *input.Person_Id } - if err := upr.CreateOrUpdateBatch(input.PersonRelatives, &event, tx); err != nil { + if err := upr.CreateOrUpdateBatch(input.PersonRelatives, &event, tx1); err != nil { return err } for idx := range input.PersonInsurances { input.PersonInsurances[idx].Person_Id = *input.Person_Id } - if err := upi.CreateOrUpdateBatch(input.PersonInsurances, &event, tx); err != nil { + if err := upi.CreateOrUpdateBatch(input.PersonInsurances, &event, tx1); err != nil { return err } - if resData, err := CreateData(input, &event, tx); err != nil { + if resData, err := CreateData(input, &event, tx1); err != nil { return err } else { data = *resData } - dataPatient, err := ReadDetailData(e.ReadDetailDto{Id: uint16(data.Id)}, &event, tx) + dataPatient, err := ReadDetailData(e.ReadDetailDto{Id: uint16(data.Id)}, &event, tx1) if err != nil { return err } From 4214bd00bd41a0453b78d12f5443c1857aca9423 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Thu, 11 Dec 2025 15:40:07 +0700 Subject: [PATCH 2/8] feat/dockerize: added assets --- Dockerfile-main-api | 1 + Dockerfile-simgos-sync-api | 1 + 2 files changed, 2 insertions(+) diff --git a/Dockerfile-main-api b/Dockerfile-main-api index 0c75acfa..ea038869 100644 --- a/Dockerfile-main-api +++ b/Dockerfile-main-api @@ -7,6 +7,7 @@ RUN CGO_ENABLED=0 GOOS=linux go build -o ./cmd/main-api/main-api ./cmd/main-api/ FROM alpine:latest WORKDIR /app +COPY --from=builder /src/assets . COPY --from=builder /src/cmd/main-api/main-api . COPY --from=builder /src/cmd/main-api/config.yml . EXPOSE 8000 diff --git a/Dockerfile-simgos-sync-api b/Dockerfile-simgos-sync-api index 35660a2f..efb675db 100644 --- a/Dockerfile-simgos-sync-api +++ b/Dockerfile-simgos-sync-api @@ -7,6 +7,7 @@ RUN CGO_ENABLED=0 GOOS=linux go build -o ./cmd/simgos-sync-api/simgos-sync-api . FROM alpine:latest WORKDIR /app +COPY --from=builder /src/assets . COPY --from=builder /src/cmd/simgos-sync-api/simgos-sync-api . COPY --from=builder /src/cmd/simgos-sync-api/config.yml . EXPOSE 8000 From 4a62316548a22a9ea16f0b64c834532530f1a1b9 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Thu, 11 Dec 2025 15:51:55 +0700 Subject: [PATCH 3/8] feat (encounter): create-with-patient done, tested with positif case only --- internal/use-case/main-use-case/encounter/case.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/use-case/main-use-case/encounter/case.go b/internal/use-case/main-use-case/encounter/case.go index 3b966ef9..b4001156 100644 --- a/internal/use-case/main-use-case/encounter/case.go +++ b/internal/use-case/main-use-case/encounter/case.go @@ -1151,7 +1151,7 @@ func CreateWithPatient(input e.CreateWithPatientDto) (*d.Data, error) { } if patientData != nil { - patientId = patientData.Data.(*ep.Patient).Id + patientId = patientData.Data.(ep.ResponseDto).Id } // create encounter From c7f2876e6e0e43fefbe54d477cb123c47b068805 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Thu, 11 Dec 2025 16:43:14 +0700 Subject: [PATCH 4/8] dev: chore, moved Dockerfile* to example --- .gitignore | 2 ++ Dockerfile-main-api => Dockerfile-main-api-example | 2 +- Dockerfile-simgos-sync-api => Dockerfile-sync-api-example | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) rename Dockerfile-main-api => Dockerfile-main-api-example (96%) rename Dockerfile-simgos-sync-api => Dockerfile-sync-api-example (97%) diff --git a/.gitignore b/.gitignore index 7800ac94..4c10eb38 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,8 @@ go.work.sum # env file .env config.yml +Dockerfile-main-api +Dockerfile-sync-api **/atlas.hcl !**/atlas.hcl.example diff --git a/Dockerfile-main-api b/Dockerfile-main-api-example similarity index 96% rename from Dockerfile-main-api rename to Dockerfile-main-api-example index ea038869..cb8839b9 100644 --- a/Dockerfile-main-api +++ b/Dockerfile-main-api-example @@ -10,5 +10,5 @@ WORKDIR /app COPY --from=builder /src/assets . COPY --from=builder /src/cmd/main-api/main-api . COPY --from=builder /src/cmd/main-api/config.yml . -EXPOSE 8000 +EXPOSE 8010 CMD ["./main-api"] diff --git a/Dockerfile-simgos-sync-api b/Dockerfile-sync-api-example similarity index 97% rename from Dockerfile-simgos-sync-api rename to Dockerfile-sync-api-example index efb675db..5b32d522 100644 --- a/Dockerfile-simgos-sync-api +++ b/Dockerfile-sync-api-example @@ -10,5 +10,5 @@ WORKDIR /app COPY --from=builder /src/assets . COPY --from=builder /src/cmd/simgos-sync-api/simgos-sync-api . COPY --from=builder /src/cmd/simgos-sync-api/config.yml . -EXPOSE 8000 +EXPOSE 8011 CMD ["./simgos-sync-api"] From a892e5ee437cadcff26168ea1debcf77fd1c6f28 Mon Sep 17 00:00:00 2001 From: vanilia Date: Thu, 11 Dec 2025 18:35:43 +0700 Subject: [PATCH 5/8] ongoing seed subspecialist --- .../domain/main-entities/installation/dto.go | 4 + .../domain/main-entities/specialist/dto.go | 4 + .../domain/main-entities/subspecialist/dto.go | 4 + .../satu-entities/daftar-specialist/entity.go | 12 ++ .../domain/simgos-entities/m-ruang/entity.go | 24 ++++ internal/infra/satu-db/satu-db.go | 9 ++ internal/infra/satu-db/tycovar.go | 5 + .../main-handler/installation/handler.go | 9 ++ .../interface/main-handler/main-handler.go | 27 ++++- .../main-handler/specialist/handler.go | 9 ++ .../main-handler/subspecialist/handler.go | 9 ++ .../simgos-sync-handler.go | 2 + .../main-use-case/installation/case.go | 34 ++++++ .../main-use-case/installation/helper.go | 12 ++ .../main-use-case/installation/lib.go | 24 ++++ .../use-case/main-use-case/specialist/case.go | 34 ++++++ .../main-use-case/specialist/helper.go | 11 ++ .../use-case/main-use-case/specialist/lib.go | 24 ++++ .../main-use-case/subspecialist/case.go | 34 ++++++ .../main-use-case/subspecialist/helper.go | 14 +++ .../main-use-case/subspecialist/lib.go | 24 ++++ .../new/installation/helper.go | 12 ++ .../new/installation/lib.go | 23 ++++ .../new/specialist/helper.go | 12 ++ .../new/specialist/lib.go | 23 ++++ .../new/subspecialist/helper.go | 6 +- .../new/subspecialist/lib.go | 33 +++++- .../simgos-sync-use-case/seeder/helper.go | 1 + .../seeder/installation/seeder.go | 92 ++++++++++++++++ .../seeder/seeder/seeder.go | 103 +++++++++++------- .../seeder/specialist/seeder.go | 90 +++++++++++++++ .../seeder/subspecialist/seeder.go | 100 +++++++++++++++++ pkg/dualtrx-helper/dualtrx-helper.go | 2 + 33 files changed, 773 insertions(+), 53 deletions(-) create mode 100644 internal/domain/satu-entities/daftar-specialist/entity.go create mode 100644 internal/domain/simgos-entities/m-ruang/entity.go create mode 100644 internal/infra/satu-db/satu-db.go create mode 100644 internal/infra/satu-db/tycovar.go create mode 100644 internal/use-case/simgos-sync-use-case/seeder/installation/seeder.go create mode 100644 internal/use-case/simgos-sync-use-case/seeder/specialist/seeder.go create mode 100644 internal/use-case/simgos-sync-use-case/seeder/subspecialist/seeder.go diff --git a/internal/domain/main-entities/installation/dto.go b/internal/domain/main-entities/installation/dto.go index bd6fcc0e..56fdb382 100644 --- a/internal/domain/main-entities/installation/dto.go +++ b/internal/domain/main-entities/installation/dto.go @@ -14,6 +14,10 @@ type CreateDto struct { EncounterClass_Code ere.EncounterClassCode `json:"encounterClass_code" validate:"maxLength=20"` } +type CreateBulkDto struct { + Value []CreateDto `json:"value"` +} + type ReadListDto struct { FilterDto Includes string `json:"includes"` diff --git a/internal/domain/main-entities/specialist/dto.go b/internal/domain/main-entities/specialist/dto.go index 2d656556..90eb38b4 100644 --- a/internal/domain/main-entities/specialist/dto.go +++ b/internal/domain/main-entities/specialist/dto.go @@ -44,6 +44,10 @@ type DeleteDto struct { Code *string `json:"code"` } +type CreateBulkDto struct { + Value []CreateDto `json:"value"` +} + type MetaDto struct { PageNumber int `json:"page_number"` PageSize int `json:"page_size"` diff --git a/internal/domain/main-entities/subspecialist/dto.go b/internal/domain/main-entities/subspecialist/dto.go index 303da04f..378fdd2c 100644 --- a/internal/domain/main-entities/subspecialist/dto.go +++ b/internal/domain/main-entities/subspecialist/dto.go @@ -43,6 +43,10 @@ type DeleteDto struct { Code *string `json:"code"` } +type CreateBulkDto struct { + Value []CreateDto `json:"value"` +} + type MetaDto struct { PageNumber int `json:"page_number"` PageSize int `json:"page_size"` diff --git a/internal/domain/satu-entities/daftar-specialist/entity.go b/internal/domain/satu-entities/daftar-specialist/entity.go new file mode 100644 index 00000000..de69a7bf --- /dev/null +++ b/internal/domain/satu-entities/daftar-specialist/entity.go @@ -0,0 +1,12 @@ +package daftar_specialist + +type DaftarSpesialis struct { + ID uint `json:"id" gorm:"column:id;primaryKey;autoIncrement"` + Kode string `json:"kode" gorm:"column:Kode"` + Spesialis string `json:"spesialis" gorm:"column:Spesialis"` + IdGroupLocationSimgos *string `json:"id_group_location_simgos" gorm:"column:Id_group_location_simgos"` +} + +func (DaftarSpesialis) TableName() string { + return "daftar_spesialis" +} diff --git a/internal/domain/simgos-entities/m-ruang/entity.go b/internal/domain/simgos-entities/m-ruang/entity.go new file mode 100644 index 00000000..1c2b5b31 --- /dev/null +++ b/internal/domain/simgos-entities/m-ruang/entity.go @@ -0,0 +1,24 @@ +package m_ruang + +type MRuang struct { + No uint `json:"no" gorm:"column:no;primaryKey;autoIncrement"` + Nama string `json:"nama" gorm:"column:nama"` + Kelas string `json:"kelas" gorm:"column:kelas"` + IdxRuang string `json:"idx_ruang" gorm:"column:idx_ruang"` + Kelompok string `json:"kelompok" gorm:"column:kelompok"` + Ruang *string `json:"ruang" gorm:"column:ruang"` + KdUnit int `json:"kdunit" gorm:"column:kdunit"` + JumlahTT int `json:"jumlah_tt" gorm:"column:jumlah_tt"` + KetRuang *string `json:"ket_ruang" gorm:"column:ket_ruang"` + Fasilitas *string `json:"fasilitas" gorm:"column:fasilitas"` + Keterangan *string `json:"keterangan" gorm:"column:keterangan"` + SubSistem string `json:"subsistem" gorm:"column:subsistem"` + StAktif int16 `json:"st_aktif" gorm:"column:st_aktif"` + KodeRuang *string `json:"kode_ruang" gorm:"column:kode_ruang"` + IsPartial *string `json:"is_partial" gorm:"column:is_partial"` +} + +// Nama tabel (opsional jika nama struct ≠ nama tabel) +func (MRuang) TableName() string { + return "m_ruang" +} diff --git a/internal/infra/satu-db/satu-db.go b/internal/infra/satu-db/satu-db.go new file mode 100644 index 00000000..4894b4e3 --- /dev/null +++ b/internal/infra/satu-db/satu-db.go @@ -0,0 +1,9 @@ +package simgos_db + +import ( + dg "github.com/karincake/apem/db-gorm-pg" +) + +func SetInstance() { + I = dg.IS["satu"] +} diff --git a/internal/infra/satu-db/tycovar.go b/internal/infra/satu-db/tycovar.go new file mode 100644 index 00000000..b9c9f2b3 --- /dev/null +++ b/internal/infra/satu-db/tycovar.go @@ -0,0 +1,5 @@ +package simgos_db + +import "gorm.io/gorm" + +var I *gorm.DB diff --git a/internal/interface/main-handler/installation/handler.go b/internal/interface/main-handler/installation/handler.go index 0b3f52ef..f9644129 100644 --- a/internal/interface/main-handler/installation/handler.go +++ b/internal/interface/main-handler/installation/handler.go @@ -71,3 +71,12 @@ func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { res, err := u.Delete(dto) rw.DataResponse(w, res, err) } + +func (obj myBase) CreateBulk(w http.ResponseWriter, r *http.Request) { + dto := e.CreateBulkDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.CreateBulk(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index f6f6bfce..130cdc2d 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -367,12 +367,33 @@ func SetRoutes() http.Handler { /******************** sources ********************/ hc.RegCrudByCode(r, "/v1/division", division.O) hc.RegCrudByCode(r, "/v1/division-position", divisionposition.O) - hc.RegCrudByCode(r, "/v1/installation", installation.O) + hk.GroupRoutes("/v1/installation", r, hk.MapHandlerFunc{ + "GET /": installation.O.GetList, + "GET /{id}": installation.O.GetDetail, + "POST /": installation.O.Create, + "PATCH /{id}": installation.O.Update, + "DELETE /{id}": installation.O.Delete, + "POST /bulk": installation.O.CreateBulk, + }) hc.RegCrudByCode(r, "/v1/unit", unit.O) hc.RegCrudByCode(r, "/v1/installation-position", installationposition.O) hc.RegCrudByCode(r, "/v1/unit-position", unitposition.O) - hc.RegCrudByCode(r, "/v1/specialist", specialist.O) - hc.RegCrudByCode(r, "/v1/subspecialist", subspecialist.O) + hk.GroupRoutes("/v1/specialist", r, hk.MapHandlerFunc{ + "GET /": specialist.O.GetList, + "GET /{id}": specialist.O.GetDetail, + "POST /": specialist.O.Create, + "PATCH /{id}": specialist.O.Update, + "DELETE /{id}": specialist.O.Delete, + "POST /bulk": specialist.O.CreateBulk, + }) + hk.GroupRoutes("/v1/subspecialist", r, hk.MapHandlerFunc{ + "GET /": subspecialist.O.GetList, + "GET /{id}": subspecialist.O.GetDetail, + "POST /": subspecialist.O.Create, + "PATCH /{id}": subspecialist.O.Update, + "DELETE /{id}": subspecialist.O.Delete, + "POST /bulk": subspecialist.O.CreateBulk, + }) hc.RegCrudByCode(r, "/v1/specialist-position", specialistposition.O) hc.RegCrudByCode(r, "/v1/subspecialist-position", subspecialistposition.O) hc.RegCrudByCode(r, "/v1/infra", infra.O) diff --git a/internal/interface/main-handler/specialist/handler.go b/internal/interface/main-handler/specialist/handler.go index 246da8f4..184fbd79 100644 --- a/internal/interface/main-handler/specialist/handler.go +++ b/internal/interface/main-handler/specialist/handler.go @@ -71,3 +71,12 @@ func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { res, err := u.Delete(dto) rw.DataResponse(w, res, err) } + +func (obj myBase) CreateBulk(w http.ResponseWriter, r *http.Request) { + dto := e.CreateBulkDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.CreateBulk(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/main-handler/subspecialist/handler.go b/internal/interface/main-handler/subspecialist/handler.go index 0e5a41d0..f021b592 100644 --- a/internal/interface/main-handler/subspecialist/handler.go +++ b/internal/interface/main-handler/subspecialist/handler.go @@ -71,3 +71,12 @@ func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { res, err := u.Delete(dto) rw.DataResponse(w, res, err) } + +func (obj myBase) CreateBulk(w http.ResponseWriter, r *http.Request) { + dto := e.CreateBulkDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.CreateBulk(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/simgos-sync-handler/simgos-sync-handler.go b/internal/interface/simgos-sync-handler/simgos-sync-handler.go index c8a08b7f..d3b9ee72 100644 --- a/internal/interface/simgos-sync-handler/simgos-sync-handler.go +++ b/internal/interface/simgos-sync-handler/simgos-sync-handler.go @@ -5,6 +5,7 @@ import ( /******************** infra ********************/ gs "simrs-vx/internal/infra/gorm-setting" + satudb "simrs-vx/internal/infra/satu-db" simgosdb "simrs-vx/internal/infra/simgos-db" sync "simrs-vx/internal/infra/sync-cfg" @@ -44,6 +45,7 @@ func SetRoutes() http.Handler { a.RegisterExtCall(lh.Populate) a.RegisterExtCall(sync.SetConfig) a.RegisterExtCall(simgosdb.SetInstance) + a.RegisterExtCall(satudb.SetInstance) r := http.NewServeMux() diff --git a/internal/use-case/main-use-case/installation/case.go b/internal/use-case/main-use-case/installation/case.go index b80b6ca5..fb18b655 100644 --- a/internal/use-case/main-use-case/installation/case.go +++ b/internal/use-case/main-use-case/installation/case.go @@ -241,6 +241,40 @@ func Delete(input e.DeleteDto) (*d.Data, error) { } +func CreateBulk(input e.CreateBulkDto) (*d.Data, error) { + var data []e.Installation + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + err := dg.I.Transaction(func(tx *gorm.DB) error { + if resData, err := CreateBulkData(input.Value, &event, tx); err != nil { + return err + } else { + data = *resData + } + return nil + }) + + if err != nil { + return nil, err + } + pl.SetLogInfo(&event, nil, "complete") + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: e.ToResponseList(data), + }, nil +} + func runLogMiddleware(err error, input any, mwRunner *middlewareRunner) error { var errMsg string inputLog := esync.SimxLogDto{ diff --git a/internal/use-case/main-use-case/installation/helper.go b/internal/use-case/main-use-case/installation/helper.go index d3d96b5c..a8055c6c 100644 --- a/internal/use-case/main-use-case/installation/helper.go +++ b/internal/use-case/main-use-case/installation/helper.go @@ -21,3 +21,15 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Installation) { data.Name = inputSrc.Name data.EncounterClass_Code = inputSrc.EncounterClass_Code } + +func setBulkData(input []e.CreateDto) (data []e.Installation) { + for _, i := range input { + data = append(data, e.Installation{ + Code: *i.Code, + Name: i.Name, + EncounterClass_Code: i.EncounterClass_Code, + }) + } + + return data +} diff --git a/internal/use-case/main-use-case/installation/lib.go b/internal/use-case/main-use-case/installation/lib.go index d75b2ecd..218c738d 100644 --- a/internal/use-case/main-use-case/installation/lib.go +++ b/internal/use-case/main-use-case/installation/lib.go @@ -1,6 +1,7 @@ package installation import ( + "fmt" e "simrs-vx/internal/domain/main-entities/installation" plh "simrs-vx/pkg/lib-helper" @@ -147,3 +148,26 @@ func DeleteData(data *e.Installation, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, nil, "complete") return nil } + +func CreateBulkData(input []e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*[]e.Installation, error) { + pl.SetLogInfo(event, nil, "started", "DBBulkCreate") + + data := setBulkData(input) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + result := tx.Create(&data) + if err := result.Error; err != nil { + return nil, plh.HandleCreateError(input, event, err) + } + + fmt.Println("Inserted:", result.RowsAffected) + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} diff --git a/internal/use-case/main-use-case/specialist/case.go b/internal/use-case/main-use-case/specialist/case.go index f9f5442b..547677cd 100644 --- a/internal/use-case/main-use-case/specialist/case.go +++ b/internal/use-case/main-use-case/specialist/case.go @@ -295,3 +295,37 @@ func runLogMiddleware(err error, input any, mwRunner *middlewareRunner) error { return nil } + +func CreateBulk(input e.CreateBulkDto) (*d.Data, error) { + var data []e.Specialist + + event := pl.Event{ + Feature: "CreateBulk", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + err := dg.I.Transaction(func(tx *gorm.DB) error { + if resData, err := CreateBulkData(input.Value, &event, tx); err != nil { + return err + } else { + data = *resData + } + return nil + }) + + if err != nil { + return nil, err + } + pl.SetLogInfo(&event, nil, "complete") + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: e.ToResponseList(data), + }, nil +} diff --git a/internal/use-case/main-use-case/specialist/helper.go b/internal/use-case/main-use-case/specialist/helper.go index 5c59b1cf..0071b816 100644 --- a/internal/use-case/main-use-case/specialist/helper.go +++ b/internal/use-case/main-use-case/specialist/helper.go @@ -21,3 +21,14 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Specialist) { data.Name = inputSrc.Name data.Unit_Code = inputSrc.Unit_Code } + +func setBulkData(input []e.CreateDto) (data []e.Specialist) { + for _, i := range input { + data = append(data, e.Specialist{ + Code: i.Code, + Name: i.Name, + }) + } + + return data +} diff --git a/internal/use-case/main-use-case/specialist/lib.go b/internal/use-case/main-use-case/specialist/lib.go index 069f5fbb..c7f27b91 100644 --- a/internal/use-case/main-use-case/specialist/lib.go +++ b/internal/use-case/main-use-case/specialist/lib.go @@ -1,6 +1,7 @@ package specialist import ( + "fmt" e "simrs-vx/internal/domain/main-entities/specialist" plh "simrs-vx/pkg/lib-helper" @@ -147,3 +148,26 @@ func DeleteData(data *e.Specialist, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, nil, "complete") return nil } + +func CreateBulkData(input []e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*[]e.Specialist, error) { + pl.SetLogInfo(event, nil, "started", "DBBulkCreate") + + data := setBulkData(input) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + result := tx.Create(&data) + if err := result.Error; err != nil { + return nil, plh.HandleCreateError(input, event, err) + } + + fmt.Println("Inserted:", result.RowsAffected) + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} diff --git a/internal/use-case/main-use-case/subspecialist/case.go b/internal/use-case/main-use-case/subspecialist/case.go index ca99750d..7d60b73b 100644 --- a/internal/use-case/main-use-case/subspecialist/case.go +++ b/internal/use-case/main-use-case/subspecialist/case.go @@ -293,3 +293,37 @@ func runLogMiddleware(err error, input any, mwRunner *middlewareRunner) error { return nil } + +func CreateBulk(input e.CreateBulkDto) (*d.Data, error) { + var data []e.Subspecialist + + event := pl.Event{ + Feature: "CreateBulk", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + err := dg.I.Transaction(func(tx *gorm.DB) error { + if resData, err := CreateBulkData(input.Value, &event, tx); err != nil { + return err + } else { + data = *resData + } + return nil + }) + + if err != nil { + return nil, err + } + pl.SetLogInfo(&event, nil, "complete") + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: e.ToResponseList(data), + }, nil +} diff --git a/internal/use-case/main-use-case/subspecialist/helper.go b/internal/use-case/main-use-case/subspecialist/helper.go index 08d64941..4cb1b8da 100644 --- a/internal/use-case/main-use-case/subspecialist/helper.go +++ b/internal/use-case/main-use-case/subspecialist/helper.go @@ -6,6 +6,7 @@ package subspecialist import ( e "simrs-vx/internal/domain/main-entities/subspecialist" + "simrs-vx/internal/domain/main-entities/subspecialist/base" ) func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Subspecialist) { @@ -21,3 +22,16 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Subspecialist) { data.Name = inputSrc.Name data.Specialist_Code = inputSrc.Specialist_Code } + +func setBulkData(input []e.CreateDto) (data []e.Subspecialist) { + for _, i := range input { + data = append(data, e.Subspecialist{ + Basic: base.Basic{ + Code: i.Code, + Name: i.Name, + }, + }) + } + + return data +} diff --git a/internal/use-case/main-use-case/subspecialist/lib.go b/internal/use-case/main-use-case/subspecialist/lib.go index c5a742df..af35fa56 100644 --- a/internal/use-case/main-use-case/subspecialist/lib.go +++ b/internal/use-case/main-use-case/subspecialist/lib.go @@ -1,6 +1,7 @@ package subspecialist import ( + "fmt" e "simrs-vx/internal/domain/main-entities/subspecialist" plh "simrs-vx/pkg/lib-helper" @@ -147,3 +148,26 @@ func DeleteData(data *e.Subspecialist, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, nil, "complete") return nil } + +func CreateBulkData(input []e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*[]e.Subspecialist, error) { + pl.SetLogInfo(event, nil, "started", "DBBulkCreate") + + data := setBulkData(input) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + result := tx.Create(&data) + if err := result.Error; err != nil { + return nil, plh.HandleCreateError(input, event, err) + } + + fmt.Println("Inserted:", result.RowsAffected) + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} diff --git a/internal/use-case/simgos-sync-use-case/new/installation/helper.go b/internal/use-case/simgos-sync-use-case/new/installation/helper.go index 1bb722dd..ab0efb25 100644 --- a/internal/use-case/simgos-sync-use-case/new/installation/helper.go +++ b/internal/use-case/simgos-sync-use-case/new/installation/helper.go @@ -11,6 +11,7 @@ import ( esimgos "simrs-vx/internal/domain/simgos-entities/m-instalasi" esync "simrs-vx/internal/domain/sync-entities/installation" esyncLog "simrs-vx/internal/domain/sync-entities/log" + "strconv" ) func setDataSimgos[T *e.CreateDto | *e.UpdateDto](input T) (data esimgos.MInstalasi) { @@ -56,3 +57,14 @@ func setDataSimxLink(simxId, simgosId uint) (data esync.InstallationLink) { data.Simgos_Id = simgosId return } + +func setBulkDataSimxLink(input []e.Installation) (data []esync.InstallationLink) { + for _, i := range input { + kode, _ := strconv.Atoi(i.Code) + data = append(data, esync.InstallationLink{ + Simx_Id: uint(i.Id), + Simgos_Id: uint(kode), + }) + } + return +} diff --git a/internal/use-case/simgos-sync-use-case/new/installation/lib.go b/internal/use-case/simgos-sync-use-case/new/installation/lib.go index a8d074fa..bd906679 100644 --- a/internal/use-case/simgos-sync-use-case/new/installation/lib.go +++ b/internal/use-case/simgos-sync-use-case/new/installation/lib.go @@ -1,6 +1,7 @@ package installation import ( + "fmt" plh "simrs-vx/pkg/lib-helper" pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" @@ -212,3 +213,25 @@ func CreateLogData(input esynclog.SimxLogDto, event *pl.Event, dbx ...*gorm.DB) pl.SetLogInfo(event, nil, "complete") return nil } + +func CreateBulkLinkData(input []e.Installation, event *pl.Event, dbx ...*gorm.DB) (*[]esync.InstallationLink, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + data := setBulkDataSimxLink(input) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + result := tx.Create(&data) + if err := result.Error; err != nil { + return nil, plh.HandleCreateError(input, event, err) + } + + fmt.Println("Inserted Link:", result.RowsAffected) + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} diff --git a/internal/use-case/simgos-sync-use-case/new/specialist/helper.go b/internal/use-case/simgos-sync-use-case/new/specialist/helper.go index adce079f..21ed4996 100644 --- a/internal/use-case/simgos-sync-use-case/new/specialist/helper.go +++ b/internal/use-case/simgos-sync-use-case/new/specialist/helper.go @@ -7,6 +7,7 @@ package specialist import ( "encoding/json" erc "simrs-vx/internal/domain/references/common" + "strconv" e "simrs-vx/internal/domain/main-entities/specialist" esimgos "simrs-vx/internal/domain/simgos-entities/m-polihfis" @@ -58,3 +59,14 @@ func setDataSimxLink(simxId, simgosId uint) (data esync.SpecialistLink) { data.Simgos_Id = simgosId return } + +func setBulkDataSimxLink(input []e.Specialist) (data []esync.SpecialistLink) { + for _, i := range input { + kode, _ := strconv.Atoi(i.Code) + data = append(data, esync.SpecialistLink{ + Simx_Id: uint(i.Id), + Simgos_Id: uint(kode), + }) + } + return +} diff --git a/internal/use-case/simgos-sync-use-case/new/specialist/lib.go b/internal/use-case/simgos-sync-use-case/new/specialist/lib.go index 0aee2ceb..787c0039 100644 --- a/internal/use-case/simgos-sync-use-case/new/specialist/lib.go +++ b/internal/use-case/simgos-sync-use-case/new/specialist/lib.go @@ -1,6 +1,7 @@ package specialist import ( + "fmt" plh "simrs-vx/pkg/lib-helper" pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" @@ -189,3 +190,25 @@ func CreateLogData(input esynclog.SimxLogDto, event *pl.Event, dbx ...*gorm.DB) pl.SetLogInfo(event, nil, "complete") return nil } + +func CreateBulkLinkData(input []e.Specialist, event *pl.Event, dbx ...*gorm.DB) (*[]esync.SpecialistLink, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + data := setBulkDataSimxLink(input) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + result := tx.Create(&data) + if err := result.Error; err != nil { + return nil, plh.HandleCreateError(input, event, err) + } + + fmt.Println("Inserted Link:", result.RowsAffected) + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} diff --git a/internal/use-case/simgos-sync-use-case/new/subspecialist/helper.go b/internal/use-case/simgos-sync-use-case/new/subspecialist/helper.go index 898f161c..2e1460d6 100644 --- a/internal/use-case/simgos-sync-use-case/new/subspecialist/helper.go +++ b/internal/use-case/simgos-sync-use-case/new/subspecialist/helper.go @@ -9,7 +9,7 @@ import ( erc "simrs-vx/internal/domain/references/common" //esimgos "simrs-vx/internal/domain/simgos-entities/specialist" esyncLog "simrs-vx/internal/domain/sync-entities/log" - esync "simrs-vx/internal/domain/sync-entities/specialist" + esync "simrs-vx/internal/domain/sync-entities/subspecialist" ) //func setDataSimgos[T *e.CreateDto | *e.UpdateDto](input T) (data esimgos.MPolihfis) { @@ -30,7 +30,7 @@ import ( // return //} -func setDataSimxLog(input *esyncLog.SimxLogDto) (data esync.SpecialistSimxLog) { +func setDataSimxLog(input *esyncLog.SimxLogDto) (data esync.SubspecialistSimxLog) { // encode to JSON jsonData, _ := json.MarshalIndent(input.Payload, "", " ") jsonString := string(jsonData) @@ -52,7 +52,7 @@ func setDataSimxLog(input *esyncLog.SimxLogDto) (data esync.SpecialistSimxLog) { return } -func setDataSimxLink(simxId, simgosId uint) (data esync.SpecialistLink) { +func setDataSimxLink(simxId, simgosId uint) (data esync.SubspecialistLink) { data.Simx_Id = simxId data.Simgos_Id = simgosId return diff --git a/internal/use-case/simgos-sync-use-case/new/subspecialist/lib.go b/internal/use-case/simgos-sync-use-case/new/subspecialist/lib.go index 781e899d..d9d7381d 100644 --- a/internal/use-case/simgos-sync-use-case/new/subspecialist/lib.go +++ b/internal/use-case/simgos-sync-use-case/new/subspecialist/lib.go @@ -1,6 +1,7 @@ package subspecialist import ( + "fmt" plh "simrs-vx/pkg/lib-helper" pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" @@ -9,9 +10,8 @@ import ( dg "github.com/karincake/apem/db-gorm-pg" "gorm.io/gorm" - //esimgos "simrs-vx/internal/domain/simgos-entities/specialist" esynclog "simrs-vx/internal/domain/sync-entities/log" - esync "simrs-vx/internal/domain/sync-entities/specialist" + esync "simrs-vx/internal/domain/sync-entities/subspecialist" ) var now = time.Now() @@ -106,7 +106,7 @@ var now = time.Now() // return nil //} -func CreateLinkData(simxId, simgosId uint, event *pl.Event, dbx ...*gorm.DB) (*esync.SpecialistLink, error) { +func CreateLinkData(simxId, simgosId uint, event *pl.Event, dbx ...*gorm.DB) (*esync.SubspecialistLink, error) { pl.SetLogInfo(event, nil, "started", "DBCreate") data := setDataSimxLink(simxId, simgosId) @@ -125,9 +125,9 @@ func CreateLinkData(simxId, simgosId uint, event *pl.Event, dbx ...*gorm.DB) (*e return &data, nil } -func ReadDetailLinkData(simxId uint16, event *pl.Event) (*esync.SpecialistLink, error) { +func ReadDetailLinkData(simxId uint16, event *pl.Event) (*esync.SubspecialistLink, error) { pl.SetLogInfo(event, simxId, "started", "DBReadDetail") - data := esync.SpecialistLink{} + data := esync.SubspecialistLink{} var tx = dg.I @@ -143,7 +143,7 @@ func ReadDetailLinkData(simxId uint16, event *pl.Event) (*esync.SpecialistLink, return &data, nil } -func DeleteLinkData(data *esync.SpecialistLink, event *pl.Event, dbx ...*gorm.DB) error { +func DeleteLinkData(data *esync.SubspecialistLink, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, data, "started", "DBDelete") var tx *gorm.DB @@ -185,3 +185,24 @@ func CreateLogData(input esynclog.SimxLogDto, event *pl.Event, dbx ...*gorm.DB) pl.SetLogInfo(event, nil, "complete") return nil } + +func CreateBulkLinkData(data []esync.SubspecialistLink, event *pl.Event, dbx ...*gorm.DB) (*[]esync.SubspecialistLink, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + result := tx.Create(&data) + if err := result.Error; err != nil { + return nil, plh.HandleCreateError(data, event, err) + } + + fmt.Println("Inserted Link:", result.RowsAffected) + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} diff --git a/internal/use-case/simgos-sync-use-case/seeder/helper.go b/internal/use-case/simgos-sync-use-case/seeder/helper.go index 74006fe2..8fc5538e 100644 --- a/internal/use-case/simgos-sync-use-case/seeder/helper.go +++ b/internal/use-case/simgos-sync-use-case/seeder/helper.go @@ -15,6 +15,7 @@ import ( type Dto struct { LoginNip []string `json:"loginNip"` Instalasi_Code string `json:"instalasi_code"` + SeedTableName string `json:"seedTableName"` } func Send(method string, endpoint string, body *bytes.Buffer, username string) ([]byte, error) { diff --git a/internal/use-case/simgos-sync-use-case/seeder/installation/seeder.go b/internal/use-case/simgos-sync-use-case/seeder/installation/seeder.go new file mode 100644 index 00000000..04c7f028 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/seeder/installation/seeder.go @@ -0,0 +1,92 @@ +package installation + +import ( + "bytes" + "encoding/json" + "log" + "net/http" + ere "simrs-vx/internal/domain/references/encounter" + db "simrs-vx/pkg/dualtrx-helper" + pl "simrs-vx/pkg/logger" + "strconv" + + ei "simrs-vx/internal/domain/main-entities/installation" + eu "simrs-vx/internal/domain/simgos-entities/m-unit" + + ui "simrs-vx/internal/use-case/simgos-sync-use-case/new/installation" + "simrs-vx/internal/use-case/simgos-sync-use-case/seeder" +) + +func SeedInstallation(event *pl.Event, tx *db.Dualtx) error { + unit := []eu.MUnit{} + + // Get M_Unit + err := tx.Simgos.Model(&eu.MUnit{}). + Find(&unit).Error + if err != nil { + log.Println("Error Querying MUnit:", err) + return err + } + + // Mapping To Installation + var installationData []ei.CreateDto + for _, v := range unit { + + codeString := strconv.Itoa(int(v.KodeUnit)) + installationData = append(installationData, ei.CreateDto{ + Name: v.NamaUnit, + EncounterClass_Code: ere.ECAmbulatory, + Code: &codeString, + }) + } + + dataInstallation, err := CreateBulkInstallation(ei.CreateBulkDto{Value: installationData}) + if err != nil { + return err + } + + _, err = ui.CreateBulkLinkData(dataInstallation, event, tx.Sync) + if err != nil { + return err + } + + return nil + +} + +func CreateBulkInstallation(ins ei.CreateBulkDto) ([]ei.Installation, error) { + var path = "installation/bulk" + + // create request body + jsonData, err := json.Marshal(ins) + if err != nil { + return nil, err + } + + reqBody := bytes.NewBuffer(jsonData) + // send data to main-api + resp, err := seeder.Send(http.MethodPost, path, reqBody, "von") + if err != nil { + return nil, err + } + + type MetaData struct { + Source string `json:"source"` + Status string `json:"status"` + Structure string `json:"structure"` + } + + type MainApiResp struct { + Meta MetaData `json:"meta"` + Data []ei.Installation `json:"data"` + } + + // getting response + var data MainApiResp + err = json.Unmarshal(resp, &data) + if err != nil { + return nil, err + } + + return data.Data, nil +} diff --git a/internal/use-case/simgos-sync-use-case/seeder/seeder/seeder.go b/internal/use-case/simgos-sync-use-case/seeder/seeder/seeder.go index 49f59b99..d52caec6 100644 --- a/internal/use-case/simgos-sync-use-case/seeder/seeder/seeder.go +++ b/internal/use-case/simgos-sync-use-case/seeder/seeder/seeder.go @@ -2,9 +2,6 @@ package seeder import ( "log" - "simrs-vx/internal/use-case/simgos-sync-use-case/seeder/doctor" - "simrs-vx/internal/use-case/simgos-sync-use-case/seeder/nurse" - "simrs-vx/internal/use-case/simgos-sync-use-case/seeder/regular" db "simrs-vx/pkg/dualtrx-helper" pl "simrs-vx/pkg/logger" @@ -14,6 +11,13 @@ import ( el "simrs-vx/internal/domain/simgos-entities/m-login" "simrs-vx/internal/use-case/simgos-sync-use-case/seeder" + + "simrs-vx/internal/use-case/simgos-sync-use-case/seeder/doctor" + "simrs-vx/internal/use-case/simgos-sync-use-case/seeder/installation" + "simrs-vx/internal/use-case/simgos-sync-use-case/seeder/nurse" + "simrs-vx/internal/use-case/simgos-sync-use-case/seeder/regular" + "simrs-vx/internal/use-case/simgos-sync-use-case/seeder/specialist" + "simrs-vx/internal/use-case/simgos-sync-use-case/seeder/subspecialist" ) const source = "seeder" @@ -33,52 +37,69 @@ func SeedToSimx(input seeder.Dto) (*d.Data, error) { kddokter, kdperawat []uint ) - // Get M_login - err := tx.Simgos.Model(&el.MLogin{}). - Select(`DISTINCT ON (nip) m_login.*`). - Where(`"nip" IN (?)`, input.LoginNip). - Find(&mlogin).Error - if err != nil { - log.Println("Error Querying Mlogin:", err) - return nil, err - } + switch input.SeedTableName { + case "installation": + if err := installation.SeedInstallation(&event, tx); err != nil { + return nil, err + } + case "specialist": + if err := specialist.SeedSpecialist(&event, tx); err != nil { + return nil, err + } + case "subspecialist": + if err := subspecialist.SeedSubspecialist(&event, tx); err != nil { + return nil, err + } - // SET data - if len(mlogin) > 0 { - for _, l := range mlogin { - if l.KdDokter != 0 { - kddokter = append(kddokter, l.KdDokter) - continue + default: + + // Get M_login + err := tx.Simgos.Model(&el.MLogin{}). + Select(`DISTINCT ON (nip) m_login.*`). + Where(`"nip" IN (?)`, input.LoginNip). + Find(&mlogin).Error + if err != nil { + log.Println("Error Querying Mlogin:", err) + return nil, err + } + + // SET data + if len(mlogin) > 0 { + for _, l := range mlogin { + if l.KdDokter != 0 { + kddokter = append(kddokter, l.KdDokter) + continue + } + + if l.KdPerawat != 0 { + kdperawat = append(kdperawat, l.KdPerawat) + continue + } + + regLogin = append(regLogin, l) } + } - if l.KdPerawat != 0 { - kdperawat = append(kdperawat, l.KdPerawat) - continue + // Seed based on role + if len(kddokter) > 0 { + err = doctor.SeedDoctor(kddokter, &event, tx) + if err != nil { + return nil, err } - - regLogin = append(regLogin, l) } - } - // Seed based on role - if len(kddokter) > 0 { - err = doctor.SeedDoctor(kddokter, &event, tx) - if err != nil { - return nil, err + if len(kdperawat) > 0 { + err = nurse.SeedNurse(kdperawat, &event, tx) + if err != nil { + return nil, err + } } - } - if len(kdperawat) > 0 { - err = nurse.SeedNurse(kdperawat, &event, tx) - if err != nil { - return nil, err - } - } - - if len(regLogin) > 0 { - err = regular.SeedRegular(regLogin, input.Instalasi_Code) - if err != nil { - return nil, err + if len(regLogin) > 0 { + err = regular.SeedRegular(regLogin, input.Instalasi_Code) + if err != nil { + return nil, err + } } } diff --git a/internal/use-case/simgos-sync-use-case/seeder/specialist/seeder.go b/internal/use-case/simgos-sync-use-case/seeder/specialist/seeder.go new file mode 100644 index 00000000..a4cde9b3 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/seeder/specialist/seeder.go @@ -0,0 +1,90 @@ +package specialist + +import ( + "bytes" + "encoding/json" + "log" + "net/http" + db "simrs-vx/pkg/dualtrx-helper" + pl "simrs-vx/pkg/logger" + "strconv" + + es "simrs-vx/internal/domain/main-entities/specialist" + er "simrs-vx/internal/domain/simgos-entities/m-ruang" + + us "simrs-vx/internal/use-case/simgos-sync-use-case/new/specialist" + "simrs-vx/internal/use-case/simgos-sync-use-case/seeder" +) + +func SeedSpecialist(event *pl.Event, tx *db.Dualtx) error { + ruang := []er.MRuang{} + + // Get M_Ruang + err := tx.Simgos.Model(&er.MRuang{}). + Find(&ruang).Error + if err != nil { + log.Println("Error Querying MRuang:", err) + return err + } + + // Mapping To Installation + var speData []es.CreateDto + for _, v := range ruang { + + codeString := strconv.Itoa(int(v.No)) + speData = append(speData, es.CreateDto{ + Code: codeString, + Name: v.Nama, + }) + } + + dataSpe, err := CreateBulkSpecialist(es.CreateBulkDto{Value: speData}) + if err != nil { + return err + } + + _, err = us.CreateBulkLinkData(dataSpe, event, tx.Sync) + if err != nil { + return err + } + + return nil + +} + +func CreateBulkSpecialist(ins es.CreateBulkDto) ([]es.Specialist, error) { + var path = "specialist/bulk" + + // create request body + jsonData, err := json.Marshal(ins) + if err != nil { + return nil, err + } + + reqBody := bytes.NewBuffer(jsonData) + // send data to main-api + resp, err := seeder.Send(http.MethodPost, path, reqBody, "von") + if err != nil { + return nil, err + } + + type MetaData struct { + Source string `json:"source"` + Status string `json:"status"` + Structure string `json:"structure"` + } + + type MainApiResp struct { + Meta MetaData `json:"meta"` + Data []es.Specialist `json:"data"` + } + + // getting response + var data MainApiResp + err = json.Unmarshal(resp, &data) + if err != nil { + return nil, err + } + + return data.Data, nil +} diff --git a/internal/use-case/simgos-sync-use-case/seeder/subspecialist/seeder.go b/internal/use-case/simgos-sync-use-case/seeder/subspecialist/seeder.go new file mode 100644 index 00000000..cc95d371 --- /dev/null +++ b/internal/use-case/simgos-sync-use-case/seeder/subspecialist/seeder.go @@ -0,0 +1,100 @@ +package subspecialist + +import ( + "bytes" + "encoding/json" + "log" + "net/http" + db "simrs-vx/pkg/dualtrx-helper" + pl "simrs-vx/pkg/logger" + + es "simrs-vx/internal/domain/main-entities/subspecialist" + eds "simrs-vx/internal/domain/satu-entities/daftar-specialist" + esb "simrs-vx/internal/domain/sync-entities/subspecialist" + + us "simrs-vx/internal/use-case/simgos-sync-use-case/new/subspecialist" + "simrs-vx/internal/use-case/simgos-sync-use-case/seeder" +) + +func SeedSubspecialist(event *pl.Event, tx *db.Dualtx) error { + dspe := []eds.DaftarSpesialis{} + subspeMap := make(map[string]uint) + + // Get Daftar Specialist + err := tx.Satu.Model(&eds.DaftarSpesialis{}). + Find(&dspe).Error + if err != nil { + log.Println("Error Querying DaftarSpecialist:", err) + return err + } + + // Mapping To Subspecialist + var speData []es.CreateDto + for _, v := range dspe { + speData = append(speData, es.CreateDto{ + Code: v.Kode, + Name: v.Spesialis, + }) + + subspeMap[v.Kode] = v.ID + } + + dataSpe, err := CreateBulkSubSpecialist(es.CreateBulkDto{Value: speData}) + if err != nil { + return err + } + + // mapping link for subspecialist + var subspecliast []esb.SubspecialistLink + for _, v := range dataSpe { + subspecliast = append(subspecliast, esb.SubspecialistLink{ + Simx_Id: uint(v.Id), + Simgos_Id: subspeMap[v.Code], + }) + } + + _, err = us.CreateBulkLinkData(subspecliast, event, tx.Sync) + if err != nil { + return err + } + + return nil + +} + +func CreateBulkSubSpecialist(ins es.CreateBulkDto) ([]es.Subspecialist, error) { + var path = "subspecialist/bulk" + + // create request body + jsonData, err := json.Marshal(ins) + if err != nil { + return nil, err + } + + reqBody := bytes.NewBuffer(jsonData) + // send data to main-api + resp, err := seeder.Send(http.MethodPost, path, reqBody, "von") + if err != nil { + return nil, err + } + + type MetaData struct { + Source string `json:"source"` + Status string `json:"status"` + Structure string `json:"structure"` + } + + type MainApiResp struct { + Meta MetaData `json:"meta"` + Data []es.Subspecialist `json:"data"` + } + + // getting response + var data MainApiResp + err = json.Unmarshal(resp, &data) + if err != nil { + return nil, err + } + + return data.Data, nil +} diff --git a/pkg/dualtrx-helper/dualtrx-helper.go b/pkg/dualtrx-helper/dualtrx-helper.go index 144337c5..94b60a5a 100644 --- a/pkg/dualtrx-helper/dualtrx-helper.go +++ b/pkg/dualtrx-helper/dualtrx-helper.go @@ -8,6 +8,7 @@ import ( type Dualtx struct { Sync *gorm.DB Simgos *gorm.DB + Satu *gorm.DB } func NewDualtx() *Dualtx { @@ -24,6 +25,7 @@ func NewTx() *Dualtx { return &Dualtx{ Sync: dg.I, Simgos: dg.IS["simrs"], + Satu: dg.IS["satu"], } } From bc1209a2706f22d4ea92988c65a606ee092c1c1a Mon Sep 17 00:00:00 2001 From: vanilia Date: Thu, 11 Dec 2025 20:22:37 +0700 Subject: [PATCH 6/8] seeder ongoing --- .../use-case/main-use-case/encounter/case.go | 2 +- .../seeder/specialist/seeder.go | 19 +++++++++++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/internal/use-case/main-use-case/encounter/case.go b/internal/use-case/main-use-case/encounter/case.go index dd131944..1c3d63aa 100644 --- a/internal/use-case/main-use-case/encounter/case.go +++ b/internal/use-case/main-use-case/encounter/case.go @@ -889,7 +889,7 @@ func ApproveSwitchSpecialist(input e.ApproveCancelSpecialistDto) (*d.Data, error } // Set doctor_code; nil indicates no change. - if input.Dst_Doctor_Code == nil { + if input.Dst_Doctor_Code == nil || *input.Dst_Doctor_Code == "" { input.Dst_Doctor_Code = irData.Doctor_Code } diff --git a/internal/use-case/simgos-sync-use-case/seeder/specialist/seeder.go b/internal/use-case/simgos-sync-use-case/seeder/specialist/seeder.go index a4cde9b3..038c2356 100644 --- a/internal/use-case/simgos-sync-use-case/seeder/specialist/seeder.go +++ b/internal/use-case/simgos-sync-use-case/seeder/specialist/seeder.go @@ -27,14 +27,25 @@ func SeedSpecialist(event *pl.Event, tx *db.Dualtx) error { return err } - // Mapping To Installation + // Mapping To Specialist var speData []es.CreateDto for _, v := range ruang { + if v.StAktif == 0 { + continue + } + + speCode := strconv.Itoa(int(v.No)) + + var insCode string + if v.KdUnit != 0 { + code := strconv.Itoa(v.KdUnit) + insCode = code + } - codeString := strconv.Itoa(int(v.No)) speData = append(speData, es.CreateDto{ - Code: codeString, - Name: v.Nama, + Code: speCode, + Name: v.Nama, + Installation_Code: insCode, }) } From 2011b318cacd1f0c6753b51f1b862007686b4872 Mon Sep 17 00:00:00 2001 From: vanilia Date: Thu, 11 Dec 2025 20:26:12 +0700 Subject: [PATCH 7/8] set instalation_code to ptr --- cmd/main-migration/migrations/atlas.sum | 4 ++-- internal/domain/main-entities/specialist/entity.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 3ff7d286..77699682 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:IfSOZ5RxGCWboRtqCJrYxCJa1HYSrlROJLXcElq1P3I= +h1:bNByj2VsHOaJEMfbX3xRNdLNTeYIVgInihZwRFfBUpc= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -162,4 +162,4 @@ h1:IfSOZ5RxGCWboRtqCJrYxCJa1HYSrlROJLXcElq1P3I= 20251209084929.sql h1:u4LPMvkGAH4RfGC2IlBTIm7T7paMHoBSvTQ0w5Br7d0= 20251210145148.sql h1:rejGrnTpaygxPv06v0vxMytF4rk1OJBXaw3ttSmidgc= 20251211101547.sql h1:+jT5yRCEsSRExzoawrqymS/I7lVfwUQQSgSzbxCxgRk= -20251211113942.sql h1:F8go8XaJf4GFa4RuoMlo4U/NtbDtbDkVYHZOJz7GYhM= +20251211113942.sql h1:hRwiVZnXGzgUbqOk5TZ6ZHzGs1GebIFeIKkJNb+6+f0= diff --git a/internal/domain/main-entities/specialist/entity.go b/internal/domain/main-entities/specialist/entity.go index 0326f614..c53e29ec 100644 --- a/internal/domain/main-entities/specialist/entity.go +++ b/internal/domain/main-entities/specialist/entity.go @@ -11,7 +11,7 @@ type Specialist struct { ecore.SmallMain // adjust this according to the needs Code string `json:"code" gorm:"unique;size:20"` Name string `json:"name" gorm:"size:50"` - Installation_Code string `json:"installation_code" gorm:"size:20"` + Installation_Code *string `json:"installation_code" gorm:"size:20"` Installation *ei.Installation `json:"installation,omitempty" gorm:"foreignKey:Installation_Code;references:Code"` SpecialistPositions []eub.Basic `json:"specialistPositions,omitempty" gorm:"foreignKey:Specialist_Code;references:Code"` Subspecialists []essb.Basic `json:"subspecialists,omitempty" gorm:"foreignKey:Specialist_Code;references:Code"` From 158e57f6f2794f32e0f38cb49d03a6064f899d1d Mon Sep 17 00:00:00 2001 From: vanilia Date: Fri, 12 Dec 2025 07:47:28 +0700 Subject: [PATCH 8/8] seed complete --- internal/domain/main-entities/specialist/dto.go | 8 ++++---- internal/use-case/main-use-case/specialist/helper.go | 5 +++-- .../simgos-sync-use-case/seeder/specialist/seeder.go | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/internal/domain/main-entities/specialist/dto.go b/internal/domain/main-entities/specialist/dto.go index 04f848cd..1b75e7cb 100644 --- a/internal/domain/main-entities/specialist/dto.go +++ b/internal/domain/main-entities/specialist/dto.go @@ -7,10 +7,10 @@ import ( ) type CreateDto struct { - Id *uint `json:"id"` - Installation_Code string `json:"installation_code"` - Code string `json:"code" validate:"maxLength=10"` - Name string `json:"name" validate:"maxLength=50"` + Id *uint `json:"id"` + Installation_Code *string `json:"installation_code"` + Code string `json:"code" validate:"maxLength=10"` + Name string `json:"name" validate:"maxLength=50"` } type ReadListDto struct { diff --git a/internal/use-case/main-use-case/specialist/helper.go b/internal/use-case/main-use-case/specialist/helper.go index 49f5745f..f5130d4e 100644 --- a/internal/use-case/main-use-case/specialist/helper.go +++ b/internal/use-case/main-use-case/specialist/helper.go @@ -25,8 +25,9 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Specialist) { func setBulkData(input []e.CreateDto) (data []e.Specialist) { for _, i := range input { data = append(data, e.Specialist{ - Code: i.Code, - Name: i.Name, + Code: i.Code, + Name: i.Name, + Installation_Code: i.Installation_Code, }) } diff --git a/internal/use-case/simgos-sync-use-case/seeder/specialist/seeder.go b/internal/use-case/simgos-sync-use-case/seeder/specialist/seeder.go index 038c2356..e108aaee 100644 --- a/internal/use-case/simgos-sync-use-case/seeder/specialist/seeder.go +++ b/internal/use-case/simgos-sync-use-case/seeder/specialist/seeder.go @@ -36,10 +36,10 @@ func SeedSpecialist(event *pl.Event, tx *db.Dualtx) error { speCode := strconv.Itoa(int(v.No)) - var insCode string + var insCode *string if v.KdUnit != 0 { code := strconv.Itoa(v.KdUnit) - insCode = code + insCode = &code } speData = append(speData, es.CreateDto{