Merge pull request #206 from dikstub-rssa/feat/sync-seeder

Feat/sync seeder
This commit is contained in:
Munawwirul Jamal
2025-12-11 07:25:09 +07:00
committed by GitHub
32 changed files with 1169 additions and 12 deletions

View File

@@ -0,0 +1,2 @@
-- Modify "ChemoPlan" table
ALTER TABLE "public"."ChemoPlan" ADD COLUMN "Reasons" text NULL;

View File

@@ -0,0 +1,2 @@
-- Modify "User" table
ALTER TABLE "public"."User" ALTER COLUMN "Name" TYPE character varying(50);

View File

@@ -1,4 +1,4 @@
h1:B/ZKq0d90aqLf0EvQfND4cd8ZRHcmxfzKF2N1lpSeIs=
h1:nDEuOqs0hKLyxdzKDcaNhEkrmnmbm6o/jgoGigw47bo=
20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k=
20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0=
20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI=
@@ -156,6 +156,8 @@ h1:B/ZKq0d90aqLf0EvQfND4cd8ZRHcmxfzKF2N1lpSeIs=
20251209022744.sql h1:y5/PAiZH/fYCpDJpkQdNRJwWICHH2iNIwM1V+S1P6KA=
20251209025908.sql h1:p3kZA8kyEj+mQZSrdY3k2K1NojQzFJh/MlZJ0Oy6t/k=
20251209030538.sql h1:zltV6/Fu2zJW0/lVBl7MdnWuJcqNTUIRcqYYZ8Fi1wo=
20251209064304.sql h1:Mj6Zh+2b/4AkM1HjnJGjAs788kVN0UaL34jeaKQIjT0=
20251209070128.sql h1:ip4wNCIF/UFQlNo6KpFG87/XA08aG3/Rf5zpxz3xioY=
20251209084929.sql h1:Z5higP1Ecq5UPWhrWZ5UCrxddMNqiJi8PbCNvGBE48A=
20251209051742.sql h1:BBNSmWfkamWrcKdxWjPiBS9yJ8yyQQUQIj3kip53nuE=
20251209064304.sql h1:Xs73yQbuJvuQ0OnW1FAZpeytmUl/bGTlJFrwGOsTF4w=
20251209070128.sql h1:fPGE6xOV6uCiVOqnvwn2L/GsBbgp2wxgmZOhF3bSGGM=
20251209084929.sql h1:u4LPMvkGAH4RfGC2IlBTIm7T7paMHoBSvTQ0w5Br7d0=
20251210145148.sql h1:EWbK5f1QKyhaVsKZfJFunmQuw22Msl0Ox3KQ/uag2bw=

View File

@@ -1,10 +1,10 @@
package main
import (
a "github.com/karincake/apem"
h "simrs-vx/internal/interface/simgos-sync-handler"
a "github.com/karincake/apem"
d "github.com/karincake/apem/db-gorm-pg"
l "github.com/karincake/apem/logger-zerolog"

View File

@@ -0,0 +1,72 @@
-- Create "DoctorLink" table
CREATE TABLE "public"."DoctorLink" (
"Id" bigserial NOT NULL,
"CreatedAt" timestamptz NULL,
"UpdatedAt" timestamptz NULL,
"DeletedAt" timestamptz NULL,
"Simx_Id" bigint NULL,
"Simgos_Id" bigint NULL,
PRIMARY KEY ("Id"),
CONSTRAINT "uni_DoctorLink_Simgos_Id" UNIQUE ("Simgos_Id"),
CONSTRAINT "uni_DoctorLink_Simx_Id" UNIQUE ("Simx_Id")
);
-- Create "DoctorSimgosLog" table
CREATE TABLE "public"."DoctorSimgosLog" (
"Id" bigserial NOT NULL,
"CreatedAt" timestamptz NULL,
"UpdatedAt" timestamptz NULL,
"DeletedAt" timestamptz NULL,
"Value" text NULL,
"Date" timestamptz NULL,
"Status" text NULL,
"ErrMessage" text NULL,
PRIMARY KEY ("Id")
);
-- Create "DoctorSimxLog" table
CREATE TABLE "public"."DoctorSimxLog" (
"Id" bigserial NOT NULL,
"CreatedAt" timestamptz NULL,
"UpdatedAt" timestamptz NULL,
"DeletedAt" timestamptz NULL,
"Value" text NULL,
"Date" timestamptz NULL,
"Status" text NULL,
"ErrMessage" text NULL,
PRIMARY KEY ("Id")
);
-- Create "NurseLink" table
CREATE TABLE "public"."NurseLink" (
"Id" bigserial NOT NULL,
"CreatedAt" timestamptz NULL,
"UpdatedAt" timestamptz NULL,
"DeletedAt" timestamptz NULL,
"Simx_Id" bigint NULL,
"Simgos_Id" bigint NULL,
PRIMARY KEY ("Id"),
CONSTRAINT "uni_NurseLink_Simgos_Id" UNIQUE ("Simgos_Id"),
CONSTRAINT "uni_NurseLink_Simx_Id" UNIQUE ("Simx_Id")
);
-- Create "NurseSimgosLog" table
CREATE TABLE "public"."NurseSimgosLog" (
"Id" bigserial NOT NULL,
"CreatedAt" timestamptz NULL,
"UpdatedAt" timestamptz NULL,
"DeletedAt" timestamptz NULL,
"Value" text NULL,
"Date" timestamptz NULL,
"Status" text NULL,
"ErrMessage" text NULL,
PRIMARY KEY ("Id")
);
-- Create "NurseSimxLog" table
CREATE TABLE "public"."NurseSimxLog" (
"Id" bigserial NOT NULL,
"CreatedAt" timestamptz NULL,
"UpdatedAt" timestamptz NULL,
"DeletedAt" timestamptz NULL,
"Value" text NULL,
"Date" timestamptz NULL,
"Status" text NULL,
"ErrMessage" text NULL,
PRIMARY KEY ("Id")
);

View File

@@ -1,8 +1,9 @@
h1:6YZBXq/r79I5tuYyY1+CBzhZsSeukHSs8MyHCC5QuV4=
h1:D3uD6s7yxMG7Roi9DCeYuLeRazZmQnd3rHMmUWf6YMM=
20251113035508.sql h1:rjDlu6yDdy5xv6nrCOr7NialrLSLT23pzduYNq29Hf0=
20251114071129.sql h1:Z0GQ5bJo3C+tplaWzxT8n3J9HLkEaVsRVp5nn7bmYow=
20251117041601.sql h1:l/RPG5mObqCSBjO4mzG+wTq2ieSycvlfOSz4czpUdWY=
20251118082246.sql h1:xLUwA+EvKWIg3X/TJvu7rqbtBzONiINfag5NJpMV29E=
20251118082915.sql h1:hP6FmUVFuADIN2cDg2Z1l7Wx7PQRb+IYQDvKD7J8VAM=
20251126115527.sql h1:Bvg+Y7k+h5s+/UaezUyJb7J7uzEJS7U5Z/RoCixcUtI=
20251201093443.sql h1:m18tksKG3OzbkxXkhfKUUqbkxnJ0VBPi3Cw34Tbywyc=
20251201093443.sql h1:dyiD1WzU9D6RjGhF0AtGfGLEsG6yocuk3HbcZWt9ZRQ=
20251209083238.sql h1:83pG5dPfMh8v0QognjeacK6s3fGxQ0nkijxtKL5y3Dc=

View File

@@ -61,6 +61,7 @@ type ResponseDto struct {
RealizationDate *time.Time `json:"realizationDate"`
Notes *string `json:"notes"`
Status ere.StatusProtocolChemo `json:"status"`
Reasons *string `json:"reasons"`
}
func (d ChemoPlan) ToResponse() ResponseDto {

View File

@@ -21,4 +21,5 @@ type ChemoPlan struct {
Status ere.StatusProtocolChemo `json:"status"`
Encounter_Id *uint `json:"encounter_id"`
Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"`
Reasons *string `json:"reasons"` // json
}

View File

@@ -10,7 +10,7 @@ import (
type User struct {
ecore.Main // adjust this according to the needs
Name string `json:"name" gorm:"unique;not null;size:25"`
Name string `json:"name" gorm:"unique;not null;size:50"`
Password string `json:"password" gorm:"not null;size:255"`
Status_Code erc.UserStatusCode `json:"status_code" gorm:"not null;size:10"`
ContractPosition_Code erg.ContractPositionCode `json:"contractPosition_code" gorm:"not null;size:20"`

View File

@@ -0,0 +1,24 @@
package m_dokter
import "time"
type MDokter struct {
Kddokter uint `gorm:"column:kddokter;primaryKey;autoIncrement" json:"kddokter"`
Kdpoly uint `gorm:"column:kdpoly" json:"kdpoly"`
Namadokter string `gorm:"column:namadokter" json:"namadokter"`
Kdprofesi *uint `gorm:"column:kdprofesi" json:"kdprofesi"`
Namaprofesi *string `gorm:"column:namaprofesi" json:"namaprofesi"`
Aktif uint16 `gorm:"column:aktif" json:"aktif"`
KdSMF *string `gorm:"column:kdsmf" json:"kdsmf"`
KodeDPJP *string `gorm:"column:kode_dpjp" json:"kode_dpjp"`
NIP *string `gorm:"column:nip" json:"nip"`
Kategori *string `gorm:"column:kategori" json:"kategori"`
TglAkhirSIP *time.Time `gorm:"column:tgl_akhir_sip" json:"tgl_akhir_sip"`
NoHP *string `gorm:"column:no_hp" json:"no_hp"`
Email *string `gorm:"column:email" json:"email"`
TglAkhirSPK *time.Time `gorm:"column:tgl_akhir_spk" json:"tgl_akhir_spk"`
}
func (MDokter) TableName() string {
return "m_dokter"
}

View File

@@ -0,0 +1,22 @@
package m_login
type MLogin struct {
NIP string `gorm:"column:nip;primaryKey"`
Password string `gorm:"column:pwd"`
SesReg string `gorm:"column:ses_reg"`
KdPerawat uint `gorm:"column:kdperawat"`
KdDokter uint `gorm:"column:kddokter"`
NamaPegawai string `gorm:"column:nama_pegawai"`
Roles int `gorm:"column:roles"`
KdUnit uint `gorm:"column:kdunit"`
Departemen string `gorm:"column:departemen"`
StDokterRajalEksekutif *uint16 `gorm:"column:st_dokter_rajal_eksekutif"`
StDokterRajalReguler *uint16 `gorm:"column:st_dokter_rajal_reguler"`
StDokterRajalEmergency *uint16 `gorm:"column:st_dokter_rajal_emergency"`
NIPB *string `gorm:"column:nipb"`
Aktif uint16 `gorm:"column:aktif"`
}
func (MLogin) TableName() string {
return "m_login"
}

View File

@@ -0,0 +1,38 @@
package m_pegawai
import "time"
type MPegawai struct {
NoPeg uint `gorm:"column:no_peg;primaryKey"`
NamaPeg string `gorm:"column:nama_peg"`
NIPB string `gorm:"column:nipb"`
Gol string `gorm:"column:gol"`
SatuanKerja string `gorm:"column:satuan_kerja"`
Ruang string `gorm:"column:ruang"`
Pendidikan string `gorm:"column:pendidikan"`
Tenaga string `gorm:"column:tenaga"`
Tenaga1 string `gorm:"column:tenaga1"`
Tenaga2 string `gorm:"column:tenaga2"`
TMTMasuk *time.Time `gorm:"column:tmt_masuk"`
TempatLahir string `gorm:"column:tmp_lahir"`
TanggalLahir *time.Time `gorm:"column:tgl_lahir"`
Alamat string `gorm:"column:alamat"`
Telepon string `gorm:"column:telepon"`
HP string `gorm:"column:hp"`
Karpeg string `gorm:"column:karpeg"`
Kelamin string `gorm:"column:kelamin"`
Agama string `gorm:"column:agama"`
StatusTubel uint16 `gorm:"column:status_tubel"` // smallint → bool
NIK string `gorm:"column:nik"`
Seksi string `gorm:"column:seksi"`
TMTAwalSIP *time.Time `gorm:"column:tmt_awal_sip"`
TMTAkhirSIPStr *time.Time `gorm:"column:tmt_akhir_sip_str"`
NoSIP string `gorm:"column:no_sip"`
NoSTR string `gorm:"column:no_str"`
LoginID string `gorm:"column:login_id"`
CodeKasir string `gorm:"column:code_kasir"`
}
func (MPegawai) TableName() string {
return "m_pegawai"
}

View File

@@ -0,0 +1,52 @@
package m_perawat
import (
"time"
)
type MPerawat struct {
Idperawat *uint `json:"idperawat" gorm:"column:idperawat;primaryKey"`
NIP string `json:"nip" gorm:"column:nip"`
UnitKerja *uint `json:"unit_kerja" gorm:"column:unit_kerja"`
Ruang *string `json:"ruang" gorm:"column:ruang"`
Nama string `json:"nama" gorm:"column:nama"`
Tempat *string `json:"tempat" gorm:"column:tempat"`
TglLahir *time.Time `json:"tgllahir" gorm:"column:tgllahir"`
JenisKelamin *string `json:"jeniskelamin" gorm:"column:jeniskelamin"`
Alamat *string `json:"alamat" gorm:"column:alamat"`
Kelurahan *string `json:"kelurahan" gorm:"column:kelurahan"`
Kdkecamatan *uint `json:"kdkecamatan" gorm:"column:kdkecamatan"`
Kota *string `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"`
Status *uint `json:"status" gorm:"column:status"`
Agama *uint `json:"agama" gorm:"column:agama"`
Pendidikan *uint `json:"pendidikan" gorm:"column:pendidikan"`
AlamatKTP *string `json:"alamat_ktp" gorm:"column:alamat_ktp"`
JabFung *string `json:"jabfung" gorm:"column:jabfung"`
JabStruk *string `json:"jabstruk" gorm:"column:jabstruk"`
LamKer *string `json:"lamker" gorm:"column:lamker"`
TemKer *string `json:"temker" gorm:"column:temker"`
TemKer2 *string `json:"temker2" gorm:"column:temker2"`
PelManKep *string `json:"pelmankep" gorm:"column:pelmankep"`
PelTekKepGaw *string `json:"peltekkepgaw" gorm:"column:peltekkepgaw"`
PelTekKepMedah *string `json:"peltekkepmedah" gorm:"column:peltekkepmedah"`
PelTekKepNak *string `json:"peltekkepnak" gorm:"column:peltekkepnak"`
PelTekKepMat *string `json:"peltekkepmat" gorm:"column:peltekkepmat"`
PelTekKepJiwa *string `json:"peltekkepjiwa" gorm:"column:peltekkepjiwa"`
TemKerTuj *string `json:"temkertuj" gorm:"column:temkertuj"`
TemKerTuj2 *string `json:"temkertuj2" gorm:"column:temkertuj2"`
TglMutasi *time.Time `json:"tglmutasi" gorm:"column:tglmutasi"`
Alasan *string `json:"alasan" gorm:"column:alasan"`
TglKeluar *time.Time `json:"tglkeluar" gorm:"column:tglkeluar"`
ProgPendidikan *uint `json:"progpendidikan" gorm:"column:progpendidikan"`
ProgPeng *string `json:"progpeng" gorm:"column:progpeng"`
JabLain *string `json:"jablain" gorm:"column:jablain"`
PPA uint `json:"ppa" gorm:"column:ppa"`
Aktif uint `json:"aktif" gorm:"column:aktif"`
}
func (MPerawat) TableName() string {
return "m_perawat"
}

View File

@@ -0,0 +1,29 @@
package doctor
import (
ecore "simrs-vx/internal/domain/base-entities/core"
erc "simrs-vx/internal/domain/references/common"
"time"
)
type DoctorLink struct {
ecore.Main
Simx_Id uint `json:"simx_id" gorm:"unique"`
Simgos_Id uint `json:"simgos_id" gorm:"unique"`
}
type DoctorSimxLog struct {
ecore.Main
Value *string `json:"value"`
Date *time.Time `json:"date"`
Status erc.ProcessStatusCode `json:"status"`
ErrMessage *string `json:"errMessage"`
}
type DoctorSimgosLog struct {
ecore.Main
Value *string `json:"value"`
Date *time.Time `json:"date"`
Status erc.ProcessStatusCode `json:"status"`
ErrMessage *string `json:"errMessage"`
}

View File

@@ -0,0 +1,29 @@
package nurse
import (
ecore "simrs-vx/internal/domain/base-entities/core"
erc "simrs-vx/internal/domain/references/common"
"time"
)
type NurseLink struct {
ecore.Main
Simx_Id uint `json:"simx_id" gorm:"unique"`
Simgos_Id uint `json:"simgos_id" gorm:"unique"`
}
type NurseSimxLog struct {
ecore.Main
Value *string `json:"value"`
Date *time.Time `json:"date"`
Status erc.ProcessStatusCode `json:"status"`
ErrMessage *string `json:"errMessage"`
}
type NurseSimgosLog struct {
ecore.Main
Value *string `json:"value"`
Date *time.Time `json:"date"`
Status erc.ProcessStatusCode `json:"status"`
ErrMessage *string `json:"errMessage"`
}

View File

@@ -39,5 +39,4 @@ func getEntities(input string) []any {
func Migrate(input string) {
loader(input)
}

View File

@@ -3,9 +3,11 @@ package migration
import (
/************** Source ***************/
division "simrs-vx/internal/domain/sync-entities/division"
doctor "simrs-vx/internal/domain/sync-entities/doctor"
encounter "simrs-vx/internal/domain/sync-entities/encounter"
installation "simrs-vx/internal/domain/sync-entities/installation"
internalreference "simrs-vx/internal/domain/sync-entities/internal-reference"
nurse "simrs-vx/internal/domain/sync-entities/nurse"
patient "simrs-vx/internal/domain/sync-entities/patient"
soapi "simrs-vx/internal/domain/sync-entities/soapi"
specialist "simrs-vx/internal/domain/sync-entities/specialist"
@@ -42,5 +44,11 @@ func getSyncEntities() []any {
&soapi.SoapiLink{},
&soapi.SoapiSimxLog{},
&soapi.SoapiSimgosLog{},
&doctor.DoctorLink{},
&doctor.DoctorSimxLog{},
&doctor.DoctorSimgosLog{},
&nurse.NurseLink{},
&nurse.NurseSimxLog{},
&nurse.NurseSimgosLog{},
}
}

View File

@@ -0,0 +1,23 @@
package seeder
import (
"net/http"
seeder "simrs-vx/internal/use-case/simgos-sync-use-case/seeder"
main "simrs-vx/internal/use-case/simgos-sync-use-case/seeder/seeder"
rw "github.com/karincake/risoles"
)
type myBase struct{}
var O myBase
func (obj myBase) Seeder(w http.ResponseWriter, r *http.Request) {
dto := seeder.Dto{}
if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res {
return
}
res, err := main.SeedToSimx(dto)
rw.DataResponse(w, res, err)
}

View File

@@ -30,6 +30,8 @@ import (
"simrs-vx/internal/interface/simgos-sync-handler/new/subspecialist"
"simrs-vx/internal/interface/simgos-sync-handler/new/unit"
sd "simrs-vx/internal/interface/simgos-sync-handler/seeder"
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
@@ -76,6 +78,12 @@ func SetRoutes() http.Handler {
})
hc.SyncCrud(r, prefixnew+"/v1/soapi", soapi.O)
/******************** Seeder ******************/
prefixseeder := "/seeder"
hk.GroupRoutes(prefixseeder+"/v1", r, hk.MapHandlerFunc{
"POST /": sd.O.Seeder,
})
/******************** SvcToNew ******************/
prefixold := "/old-to-new"
hk.GroupRoutes(prefixold+"/v1/patient", r, oauth.OldGuardMW, hk.MapHandlerFunc{

View File

@@ -141,7 +141,7 @@ func DeleteData(data *e.Patient, event *pl.Event, dbx ...*gorm.DB) error {
tx = dg.I
}
if err := tx.Delete(&data).Error; err != nil {
if err := tx.Unscoped().Delete(&data).Error; err != nil {
event.Status = "failed"
event.ErrInfo = pl.ErrorInfo{
Code: "data-delete-fail",

View File

@@ -169,9 +169,14 @@ func Create(input e.CreateDto) (*d.Data, error) {
return err
}
case ero.EPCReg, ero.EPCScr:
var instalationCode string
if input.Installation_Code != nil {
instalationCode = *input.Installation_Code
}
createSub := er.CreateDto{
Employee_Id: employeeData.Id,
Installation_Code: *input.Installation_Code,
Installation_Code: instalationCode,
}
if _, err := ur.CreateData(createSub, &event, tx); err != nil {
return err

View File

@@ -0,0 +1,48 @@
package doctor
import (
pl "simrs-vx/pkg/logger"
d "github.com/karincake/dodol"
"gorm.io/gorm"
db "simrs-vx/pkg/dualtrx-helper"
elog "simrs-vx/internal/domain/sync-entities/log"
)
const source = "doctor"
func CreateSimxLog(input elog.SimxLogDto) (*d.Data, error) {
event := pl.Event{
Feature: "Create",
Source: source,
}
// Start log
pl.SetLogInfo(&event, input, "started", "create")
tx := db.NewTx()
err := tx.Sync.Transaction(func(tx *gorm.DB) error {
// Insert to Log
if err := CreateLogData(input, &event, tx); err != nil {
return err
}
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",
},
}, nil
}

View File

@@ -0,0 +1,41 @@
/*
DESCRIPTION:
Any functions that are used internally by the use-case
*/
package doctor
import (
"encoding/json"
erc "simrs-vx/internal/domain/references/common"
esync "simrs-vx/internal/domain/sync-entities/doctor"
esyncLog "simrs-vx/internal/domain/sync-entities/log"
)
func setDataSimxLog(input *esyncLog.SimxLogDto) (data esync.DoctorSimxLog) {
// encode to JSON
jsonData, _ := json.MarshalIndent(input.Payload, "", " ")
jsonString := string(jsonData)
var status erc.ProcessStatusCode
if input.IsSuccess {
status = erc.PSCSuccess
} else {
status = erc.PSCFailed
if input.ErrMessage != nil {
data.ErrMessage = input.ErrMessage
}
}
data.Value = &jsonString
data.Date = &now
data.Status = status
return
}
func setDataSimxLink(simxId, simgosId uint) (data esync.DoctorLink) {
data.Simx_Id = simxId
data.Simgos_Id = simgosId
return
}

View File

@@ -0,0 +1,53 @@
package doctor
import (
plh "simrs-vx/pkg/lib-helper"
pl "simrs-vx/pkg/logger"
"time"
dg "github.com/karincake/apem/db-gorm-pg"
"gorm.io/gorm"
esync "simrs-vx/internal/domain/sync-entities/doctor"
esynclog "simrs-vx/internal/domain/sync-entities/log"
)
var now = time.Now()
func CreateLinkData(simxId, simgosId uint, event *pl.Event, dbx ...*gorm.DB) (*esync.DoctorLink, error) {
pl.SetLogInfo(event, nil, "started", "DBCreate")
data := setDataSimxLink(simxId, simgosId)
var tx *gorm.DB
if len(dbx) > 0 {
tx = dbx[0]
} else {
tx = dg.I
}
if err := tx.Create(&data).Error; err != nil {
return nil, plh.HandleCreateError(data, event, err)
}
pl.SetLogInfo(event, nil, "complete")
return &data, nil
}
func CreateLogData(input esynclog.SimxLogDto, event *pl.Event, dbx ...*gorm.DB) error {
pl.SetLogInfo(event, nil, "started", "DBCreate")
data := setDataSimxLog(&input)
var tx *gorm.DB
if len(dbx) > 0 {
tx = dbx[0]
} else {
tx = dg.I
}
if err := tx.Create(&data).Error; err != nil {
return plh.HandleCreateError(input, event, err)
}
pl.SetLogInfo(event, nil, "complete")
return nil
}

View File

@@ -0,0 +1,48 @@
package nurse
import (
pl "simrs-vx/pkg/logger"
d "github.com/karincake/dodol"
"gorm.io/gorm"
db "simrs-vx/pkg/dualtrx-helper"
elog "simrs-vx/internal/domain/sync-entities/log"
)
const source = "nurse"
func CreateSimxLog(input elog.SimxLogDto) (*d.Data, error) {
event := pl.Event{
Feature: "Create",
Source: source,
}
// Start log
pl.SetLogInfo(&event, input, "started", "create")
tx := db.NewTx()
err := tx.Sync.Transaction(func(tx *gorm.DB) error {
// Insert to Log
if err := CreateLogData(input, &event, tx); err != nil {
return err
}
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",
},
}, nil
}

View File

@@ -0,0 +1,41 @@
/*
DESCRIPTION:
Any functions that are used internally by the use-case
*/
package nurse
import (
"encoding/json"
erc "simrs-vx/internal/domain/references/common"
esyncLog "simrs-vx/internal/domain/sync-entities/log"
esync "simrs-vx/internal/domain/sync-entities/nurse"
)
func setDataSimxLog(input *esyncLog.SimxLogDto) (data esync.NurseSimxLog) {
// encode to JSON
jsonData, _ := json.MarshalIndent(input.Payload, "", " ")
jsonString := string(jsonData)
var status erc.ProcessStatusCode
if input.IsSuccess {
status = erc.PSCSuccess
} else {
status = erc.PSCFailed
if input.ErrMessage != nil {
data.ErrMessage = input.ErrMessage
}
}
data.Value = &jsonString
data.Date = &now
data.Status = status
return
}
func setDataSimxLink(simxId, simgosId uint) (data esync.NurseLink) {
data.Simx_Id = simxId
data.Simgos_Id = simgosId
return
}

View File

@@ -0,0 +1,53 @@
package nurse
import (
plh "simrs-vx/pkg/lib-helper"
pl "simrs-vx/pkg/logger"
"time"
dg "github.com/karincake/apem/db-gorm-pg"
"gorm.io/gorm"
esynclog "simrs-vx/internal/domain/sync-entities/log"
esync "simrs-vx/internal/domain/sync-entities/nurse"
)
var now = time.Now()
func CreateLinkData(simxId, simgosId uint, event *pl.Event, dbx ...*gorm.DB) (*esync.NurseLink, error) {
pl.SetLogInfo(event, nil, "started", "DBCreate")
data := setDataSimxLink(simxId, simgosId)
var tx *gorm.DB
if len(dbx) > 0 {
tx = dbx[0]
} else {
tx = dg.I
}
if err := tx.Create(&data).Error; err != nil {
return nil, plh.HandleCreateError(data, event, err)
}
pl.SetLogInfo(event, nil, "complete")
return &data, nil
}
func CreateLogData(input esynclog.SimxLogDto, event *pl.Event, dbx ...*gorm.DB) error {
pl.SetLogInfo(event, nil, "started", "DBCreate")
data := setDataSimxLog(&input)
var tx *gorm.DB
if len(dbx) > 0 {
tx = dbx[0]
} else {
tx = dg.I
}
if err := tx.Create(&data).Error; err != nil {
return plh.HandleCreateError(input, event, err)
}
pl.SetLogInfo(event, nil, "complete")
return nil
}

View File

@@ -0,0 +1,147 @@
package doctor
import (
"encoding/json"
"fmt"
"log"
"net/http"
pl "simrs-vx/pkg/logger"
"strconv"
db "simrs-vx/pkg/dualtrx-helper"
erg "simrs-vx/internal/domain/references/organization"
eed "simrs-vx/internal/domain/main-entities/doctor"
epr "simrs-vx/internal/domain/main-entities/person"
es "simrs-vx/internal/domain/main-entities/user"
ud "simrs-vx/internal/use-case/simgos-sync-use-case/new/doctor"
"simrs-vx/internal/use-case/simgos-sync-use-case/seeder"
)
type user struct {
Kddokter uint `gorm:"column:kddokter"`
Kdpoly uint `gorm:"column:kdpoly"`
NIP string `gorm:"column:nip"`
NamaPegawai string `gorm:"column:nama_pegawai"`
}
func SeedDoctor(kddoc []uint, event *pl.Event, tx *db.Dualtx) error {
log.Println("=== START SeedDoctor ===")
var users []user
log.Println("Querying SIMGOS doctors...")
err := tx.Simgos.
Table("m_dokter").
Select(`
DISTINCT ON (l.nip)
m_dokter.kddokter as kddokter,
m_dokter.kdpoly as kdpoly,
l.nip as nip,
l.nama_pegawai as nama_pegawai
`).
Joins(`LEFT JOIN m_login l ON l.kddokter = m_dokter.kddokter`).
Where(`m_dokter.kddokter IN (?)`, kddoc).
Order(`l.nip`).
Scan(&users).Error
if err != nil {
return err
}
log.Printf("Found %d doctors to seed\n", len(users))
// mapping
for i, d := range users {
log.Printf("[%d/%d] Processing doctor KdDokter=%d ...", i+1, len(users), d.Kddokter)
kddokter := strconv.Itoa(int(d.Kddokter))
//kdpoly := strconv.Itoa(int(d.MDokter.Kdpoly))
nik := seeder.GenerateDummyNIK("F")
doctorsimx := es.CreateDto{
Name: d.NIP,
Password: "1234",
ContractPosition_Code: erg.CSCEmp,
Code: &kddokter,
Person: &epr.UpdateDto{
CreateDto: epr.CreateDto{
Name: d.NamaPegawai,
ResidentIdentityNumber: &nik,
},
},
Employee: &es.EmployeUpdateDto{
Position_Code: erg.EPCDoc,
},
}
log.Printf("[%d] Creating User for NIP=%s ...", i+1, d.NIP)
// create user
userData, err := seeder.CreateUser(doctorsimx)
if err != nil {
log.Println("Error createUser:", err)
return err
}
log.Printf("[%d] User created: ID=%d", i+1, userData.Id)
log.Printf("[%d] Fetching doctor with code=%s ...", i+1, kddokter)
// get doctor
dataDoctor, err := getDoctors(kddokter)
if err != nil {
log.Println("Error getDoctors:", err)
return err
}
doc := *dataDoctor
ddoc := doc[0]
log.Printf("[%d] Linking doctor %d to %s ...", i+1, ddoc.Id, kddokter)
if _, err = ud.CreateLinkData(ddoc.Id, d.Kddokter, event); err != nil {
return err
}
log.Printf("[%d] Link created successfully.", i+1)
}
log.Println("=== FINISH SeedDoctor ===")
return nil
}
func getDoctors(code string) (*[]eed.Doctor, error) {
path := fmt.Sprintf("doctor?code=%s", code)
resp, err := seeder.Send(http.MethodGet, path, nil, "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 []eed.Doctor `json:"data"`
}
// getting response
var data MainApiResp
err = json.Unmarshal(resp, &data)
if err != nil {
return nil, err
}
return &data.Data, nil
}

View File

@@ -0,0 +1,110 @@
package seeder
import (
"bytes"
"encoding/json"
"fmt"
"io"
"math/rand"
"net/http"
es "simrs-vx/internal/domain/main-entities/user"
cfg "simrs-vx/internal/infra/sync-cfg"
"time"
)
type Dto struct {
LoginNip []string `json:"loginNip"`
Instalasi_Code string `json:"instalasi_code"`
}
func Send(method string, endpoint string, body *bytes.Buffer, username string) ([]byte, error) {
var url string = cfg.O.NewHost + "v1/" + 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)
req.Header.Set("X-Sync-UserName", username)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("http status code %d", resp.StatusCode)
}
respBody, _ := io.ReadAll(resp.Body)
return respBody, nil
}
func CreateUser(user es.CreateDto) (*es.User, error) {
var path = "user"
// create request body
jsonUser, err := json.Marshal(user)
if err != nil {
return nil, err
}
reqBody := bytes.NewBuffer(jsonUser)
// send data to main-api
resp, err := 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.User `json:"data"`
}
// getting response
var data MainApiResp
err = json.Unmarshal(resp, &data)
if err != nil {
return nil, err
}
return &data.Data, nil
}
func GenerateDummyNIK(gender string) string {
rand.Seed(time.Now().UnixNano())
// 1⃣ Kode wilayah (6 digit)
// Bisa di-random, atau gunakan kode tetap seperti Jakarta: 317301
region := rand.Intn(999999) // 000000 - 999999
regionCode := fmt.Sprintf("%06d", region)
// 2⃣ Tanggal lahir (DDMMYY)
year := rand.Intn(30) + 70 // antara tahun 1970-1999 (bisa diganti range lain)
month := rand.Intn(12) + 1
day := rand.Intn(28) + 1 // selalu valid
if gender == "F" {
day += 40 // aturan NIK perempuan: tanggal lahir + 40
}
birth := fmt.Sprintf("%02d%02d%02d", day, month, year)
// 3⃣ Nomor urut (4 digit)
sequence := fmt.Sprintf("%04d", rand.Intn(9999))
// 4⃣ Susun NIK akhir
nik := regionCode + birth + sequence
return nik
}

View File

@@ -0,0 +1,147 @@
package nurse
import (
"encoding/json"
"fmt"
"log"
"net/http"
"simrs-vx/internal/use-case/simgos-sync-use-case/seeder"
db "simrs-vx/pkg/dualtrx-helper"
pl "simrs-vx/pkg/logger"
"strconv"
erg "simrs-vx/internal/domain/references/organization"
enr "simrs-vx/internal/domain/main-entities/nurse"
epr "simrs-vx/internal/domain/main-entities/person"
es "simrs-vx/internal/domain/main-entities/user"
el "simrs-vx/internal/domain/simgos-entities/m-login"
en "simrs-vx/internal/domain/simgos-entities/m-perawat"
un "simrs-vx/internal/use-case/simgos-sync-use-case/new/nurse"
)
type user struct {
el.MLogin
en.MPerawat
}
func SeedNurse(kdnur []uint, event *pl.Event, tx *db.Dualtx) error {
log.Println("=== START SeedNurse ===")
var users []user
log.Println("Querying SIMGOS nurses...")
err := tx.Simgos.
Table("m_perawat").
Select(`
DISTINCT ON (l.nip)
m_perawat.idperawat,
m_perawat.nama,
l.nip,
l.nama_pegawai
`).
Joins("LEFT JOIN m_login l ON l.kdperawat = m_perawat.idperawat").
Where(`m_perawat.idperawat IN (?)`, kdnur).
Order(`l.nip`).
Scan(&users).Error
if err != nil {
log.Println("Error Querying SIMGOS:", err)
return err
}
log.Printf("Found %d nurses to seed\n", len(users))
// mapping
for i, d := range users {
log.Printf("[%d/%d] Processing nurse KdPerawat=%d ...", i+1, len(users), d.Idperawat)
kdprawat := strconv.Itoa(int(*d.Idperawat))
nik := seeder.GenerateDummyNIK("F")
nursesimx := es.CreateDto{
Name: d.MLogin.NIP,
Password: "1234",
ContractPosition_Code: erg.CSCEmp,
Code: &kdprawat,
Person: &epr.UpdateDto{
CreateDto: epr.CreateDto{
Name: d.NamaPegawai,
ResidentIdentityNumber: &nik,
},
},
Employee: &es.EmployeUpdateDto{
Position_Code: erg.EPCNur,
},
}
log.Printf("[%d] Creating User for NIP=%v ...", i+1, d.MLogin.NIP)
// create user
userData, err := seeder.CreateUser(nursesimx)
if err != nil {
log.Println("Error createUser:", err)
return err
}
log.Printf("[%d] User created: ID=%d", i+1, userData.Id)
log.Printf("[%d] Fetching nurse with code=%s ...", i+1, kdprawat)
// get nurse
dataNurse, err := getNurse(kdprawat)
if err != nil {
log.Println("Error get nurses:", err)
return err
}
data := *dataNurse
ddata := data[0]
log.Printf("[%d] Linking nurse %d to %s ...", i+1, ddata.Id, kdprawat)
if _, err := un.CreateLinkData(ddata.Id, *d.Idperawat, event); err != nil {
return err
}
log.Printf("[%d] Link created successfully.", i+1)
}
log.Println("=== FINISH Seednurse ===")
return nil
}
func getNurse(code string) (*[]enr.Nurse, error) {
path := fmt.Sprintf("nurse?code=%s", code)
resp, err := seeder.Send(http.MethodGet, path, nil, "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 []enr.Nurse `json:"data"`
}
// getting response
var data MainApiResp
err = json.Unmarshal(resp, &data)
if err != nil {
return nil, err
}
return &data.Data, nil
}

View File

@@ -0,0 +1,57 @@
package regular
import (
"log"
erg "simrs-vx/internal/domain/references/organization"
epr "simrs-vx/internal/domain/main-entities/person"
es "simrs-vx/internal/domain/main-entities/user"
el "simrs-vx/internal/domain/simgos-entities/m-login"
"simrs-vx/internal/use-case/simgos-sync-use-case/seeder"
)
func SeedRegular(regLogin []el.MLogin, instalasiCode string) error {
log.Println("=== START SeedRegular ===")
// mapping
for i, d := range regLogin {
log.Printf("[%d/%d] Processing Regular NIP=%s ...", i+1, len(regLogin), d.NIP)
nik := seeder.GenerateDummyNIK("F")
regularsimx := es.CreateDto{
Name: d.NIP,
Password: "1234",
ContractPosition_Code: erg.CSCEmp,
Installation_Code: &instalasiCode,
Person: &epr.UpdateDto{
CreateDto: epr.CreateDto{
Name: d.NamaPegawai,
ResidentIdentityNumber: &nik,
},
},
Employee: &es.EmployeUpdateDto{
Position_Code: erg.EPCReg,
},
}
log.Printf("[%d] Creating User for NIP=%s ...", i+1, d.NIP)
// create user
userData, err := seeder.CreateUser(regularsimx)
if err != nil {
log.Println("Error createUser:", err)
return err
}
log.Printf("[%d] User created: ID=%d", i+1, userData.Id)
}
log.Println("=== FINISH SeedRegular ===")
return nil
}

View File

@@ -0,0 +1,94 @@
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"
d "github.com/karincake/dodol"
el "simrs-vx/internal/domain/simgos-entities/m-login"
"simrs-vx/internal/use-case/simgos-sync-use-case/seeder"
)
const source = "seeder"
func SeedToSimx(input seeder.Dto) (*d.Data, error) {
event := pl.Event{
Feature: "Seeder",
Source: source,
}
// Start log
pl.SetLogInfo(&event, input, "started", "create")
var (
tx = db.NewTx()
mlogin, regLogin []el.MLogin
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
}
// 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)
}
}
// 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(regLogin) > 0 {
err = regular.SeedRegular(regLogin, input.Instalasi_Code)
if err != nil {
return nil, err
}
}
pl.SetLogInfo(&event, nil, "complete")
return &d.Data{
Meta: d.II{
"source": source,
"structure": "single-data",
"status": "created",
},
}, nil
}