Merge pull request #171 from dikstub-rssa/feat/sync-from-simx-160

Feat/sync from simx 160
This commit is contained in:
vaniliacahya
2025-11-27 11:46:23 +07:00
committed by GitHub
48 changed files with 1418 additions and 419 deletions
@@ -0,0 +1,2 @@
-- Modify "Encounter" table
ALTER TABLE "public"."Encounter" ADD COLUMN "Responsible_Nurse_Code" character varying(20) NULL, ADD CONSTRAINT "fk_Encounter_Responsible_Nurse" FOREIGN KEY ("Responsible_Nurse_Code") REFERENCES "public"."Nurse" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION;
@@ -0,0 +1,2 @@
-- Modify "InternalReference" table
ALTER TABLE "public"."InternalReference" ADD COLUMN "SrcDoctor_Code" character varying(20) NULL, ADD COLUMN "SrcNurse_Code" character varying(20) NULL, ADD COLUMN "Nurse_Code" character varying(20) NULL, ADD CONSTRAINT "fk_InternalReference_Nurse" FOREIGN KEY ("Nurse_Code") REFERENCES "public"."Nurse" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, ADD CONSTRAINT "fk_InternalReference_SrcDoctor" FOREIGN KEY ("SrcDoctor_Code") REFERENCES "public"."Doctor" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION, ADD CONSTRAINT "fk_InternalReference_SrcNurse" FOREIGN KEY ("SrcNurse_Code") REFERENCES "public"."Nurse" ("Code") ON UPDATE NO ACTION ON DELETE NO ACTION;
+4 -2
View File
@@ -1,4 +1,4 @@
h1:87NyL1nIRuVvOiLbfdC1+PF+v2R/joAnBYyh2CrlGdU=
h1:U9vdficFramvwnH40psSuRxzUuq6EPJwLcr9MvVTq7s=
20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k=
20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0=
20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI=
@@ -128,4 +128,6 @@ h1:87NyL1nIRuVvOiLbfdC1+PF+v2R/joAnBYyh2CrlGdU=
20251120005512.sql h1:Ek6qpacAI/qVuTYxKno+uJyzn7s5z9pf3t7VA8gTzm4=
20251120074415.sql h1:NNUeJVA03EeBHJhHqPXEZoDv/PnC6yK1/cRhmukyaJo=
20251121033803.sql h1:/vfvFX/3pzSCIHnSbMUT9EMBDykOpVkvyfeTEle9Vas=
20251124071457.sql h1:HBaNJQIzUe6wK8CgBxamuKor7ZiAASzgkkXzL6kWsjY=
20251124071457.sql h1:qg2dhCL9YwD13xnfJ175lW/p6MGfzFKaBqd908FByRc=
20251125125303.sql h1:4JSFv1Pmhbe9tqpLXgO63OwYnGsalStgUXKVWPyc1YE=
20251126064057.sql h1:+lByIo0zAsHVSFzQGVMuymFQajyl7fRNqgs9d/76y+E=
@@ -0,0 +1,36 @@
-- Create "InternalReferenceLink" table
CREATE TABLE "public"."InternalReferenceLink" (
"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_InternalReferenceLink_Simgos_Id" UNIQUE ("Simgos_Id"),
CONSTRAINT "uni_InternalReferenceLink_Simx_Id" UNIQUE ("Simx_Id")
);
-- Create "InternalReferenceSimgosLog" table
CREATE TABLE "public"."InternalReferenceSimgosLog" (
"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 "InternalReferenceSimxLog" table
CREATE TABLE "public"."InternalReferenceSimxLog" (
"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")
);
@@ -1,6 +1,7 @@
h1:keVmwgYtvwxSqkq+7nB0BA25JFYRAVBpBBu5eA4Q9Hw=
h1:UdPzQZ17yyNN9HVuyrFFHj5KjLj4m6/e7s9frkdpQVU=
20251113035508.sql h1:rjDlu6yDdy5xv6nrCOr7NialrLSLT23pzduYNq29Hf0=
20251114071129.sql h1:Z0GQ5bJo3C+tplaWzxT8n3J9HLkEaVsRVp5nn7bmYow=
20251117041601.sql h1:l/RPG5mObqCSBjO4mzG+wTq2ieSycvlfOSz4czpUdWY=
20251118082246.sql h1:VFnYls2DBC8tJm2aw0iBcbWGLsKezYdOHJJV9iS7MjI=
20251118082915.sql h1:tAm67fXrH+8IJCjKbJroIqc1uQyqCnuGJnQtLmw7D20=
20251118082246.sql h1:xLUwA+EvKWIg3X/TJvu7rqbtBzONiINfag5NJpMV29E=
20251118082915.sql h1:hP6FmUVFuADIN2cDg2Z1l7Wx7PQRb+IYQDvKD7J8VAM=
20251126115527.sql h1:+2bp2nWTTqaPpKKfy5ZYSr6b1nEUXFG3tIw4r3OEnAQ=
+34 -23
View File
@@ -1,14 +1,6 @@
package encounter
import (
eam "simrs-vx/internal/domain/main-entities/ambulatory"
edc "simrs-vx/internal/domain/main-entities/death-cause"
eem "simrs-vx/internal/domain/main-entities/emergency"
eed "simrs-vx/internal/domain/main-entities/encounter-document"
eip "simrs-vx/internal/domain/main-entities/inpatient"
eir "simrs-vx/internal/domain/main-entities/internal-reference"
er "simrs-vx/internal/domain/main-entities/rehab/base"
// std
"time"
@@ -24,10 +16,18 @@ import (
// internal - domain - main-entities
evs "simrs-vx/internal/domain/bpjs-entities/vclaim-sep"
eam "simrs-vx/internal/domain/main-entities/ambulatory"
ea "simrs-vx/internal/domain/main-entities/appointment"
edc "simrs-vx/internal/domain/main-entities/death-cause"
ed "simrs-vx/internal/domain/main-entities/doctor"
eem "simrs-vx/internal/domain/main-entities/emergency"
ee "simrs-vx/internal/domain/main-entities/employee"
eed "simrs-vx/internal/domain/main-entities/encounter-document"
eip "simrs-vx/internal/domain/main-entities/inpatient"
eir "simrs-vx/internal/domain/main-entities/internal-reference"
en "simrs-vx/internal/domain/main-entities/nurse"
ep "simrs-vx/internal/domain/main-entities/patient"
er "simrs-vx/internal/domain/main-entities/rehab/base"
es "simrs-vx/internal/domain/main-entities/specialist"
ess "simrs-vx/internal/domain/main-entities/subspecialist"
eu "simrs-vx/internal/domain/main-entities/unit"
@@ -65,15 +65,15 @@ type CreateDto struct {
}
type TRujukan struct {
NoSep string `json:"noSep"`
NoSep string `json:"noSep"` // Surat Eligibilitas Peserta
TglRujukan string `json:"tglRujukan"`
PpkDirujuk string `json:"ppkDirujuk"`
JnsPelayanan string `json:"jnsPelayanan"`
PpkDirujuk string `json:"ppkDirujuk"` // PPK (Provider Pelayanan Kesehatan) -> kode RS tujuan
JnsPelayanan string `json:"jnsPelayanan"` // Jenis pelayanan yang dimintakan; 1 = RawatInap; 2 = RawatJalan
Catatan string `json:"catatan"`
DiagRujukan string `json:"diagRujukan"`
TipeRujukan string `json:"tipeRujukan"`
PoliRujukan string `json:"poliRujukan"`
User string `json:"user"`
DiagRujukan string `json:"diagRujukan"` // Kode Diagnosa
TipeRujukan string `json:"tipeRujukan"` // 0 = Rujukan Penuh; 1 = Rujukan Partial (hanya untuk tindakan tertentu); 2 = Balik (dikembalikan ke faskes asal)
PoliRujukan string `json:"poliRujukan"` // Kode Poli Tujuan
User string `json:"user"` // user yang membuat rujukan
}
type ReadListDto struct {
@@ -105,24 +105,24 @@ type FilterDto struct {
}
type ReadDetailDto struct {
Id uint16 `json:"id"`
Id uint `json:"id"`
Includes string `json:"includes"`
}
type UpdateDto struct {
Id uint16 `json:"id"`
Id uint `json:"id"`
CreateDto
}
type UpdateStatusDto struct {
Id uint16 `json:"id"`
Id uint `json:"id"`
StatusCode erc.DataStatusCode `json:"status_code"`
pa.AuthInfo
}
type DeleteDto struct {
Id uint16 `json:"id"`
Id uint `json:"id"`
pa.AuthInfo
}
@@ -147,7 +147,7 @@ type DischargeDto struct {
type CheckinDto struct {
Id uint `json:"id"`
Responsible_Doctor_Code *string `json:"responsible_doctor_code"`
Adm_Employee_Id *uint `json:"adm_employee_id"`
Responsible_Nurse_Code *string `json:"responsible_nurse_code"`
StartedAt *time.Time `json:"startedAt"`
FinishedAt *time.Time `json:"finishedAt"`
@@ -158,11 +158,18 @@ type SwitchUnitDto struct {
Id uint `json:"id"`
PolySwitchCode *ere.PolySwitchCode `json:"polySwitchCode"`
InternalReferences *[]eir.CreateDto `json:"internalReferences" validate:"required"`
Src_Doctor_Code *string `json:"-"`
Src_Nurse_Code *string `json:"-"`
pa.AuthInfo
}
type ApproveUnitDto struct {
Id uint `json:"id"`
InternalReferences_Id uint16 `json:"internalReferences_id" validate:"required"`
type ApproveCancelUnitDto struct {
Id uint `json:"id"`
InternalReferences_Id uint `json:"internalReferences_id" validate:"required"`
Dst_Doctor_Code *string `json:"dst_doctor_code"`
pa.AuthInfo
}
type ResponseDto struct {
@@ -211,6 +218,8 @@ type ResponseDto struct {
Rehab *er.Basic `json:"rehab,omitempty"`
RehabChildren *[]er.Basic `json:"rehabChildren,omitempty"`
EncounterDocuments *[]eed.EncounterDocument `json:"encounterDocuments,omitempty"`
Responsible_Nurse_Code *string `json:"responsible_nurse_code"`
Responsible_Nurse *en.Nurse `json:"responsible_nurse,omitempty"`
}
func (d Encounter) ToResponse() ResponseDto {
@@ -258,6 +267,8 @@ func (d Encounter) ToResponse() ResponseDto {
Rehab: d.Rehab,
RehabChildren: d.RehabChildren,
EncounterDocuments: d.EncounterDocuments,
Responsible_Nurse_Code: d.Responsible_Nurse_Code,
Responsible_Nurse: d.Responsible_Nurse,
}
resp.Main = d.Main
return resp
@@ -20,6 +20,7 @@ import (
eip "simrs-vx/internal/domain/main-entities/inpatient"
ei "simrs-vx/internal/domain/main-entities/insurance-company"
eir "simrs-vx/internal/domain/main-entities/internal-reference"
en "simrs-vx/internal/domain/main-entities/nurse"
ep "simrs-vx/internal/domain/main-entities/patient"
er "simrs-vx/internal/domain/main-entities/rehab/base"
es "simrs-vx/internal/domain/main-entities/specialist"
@@ -77,6 +78,8 @@ type Encounter struct {
EncounterDocuments *[]eed.EncounterDocument `json:"encounterDocuments,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"`
GeneralConsents *[]egc.GeneralConsent `json:"generalConsents,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"`
VclaimReference *evr.VclaimReference `json:"vclaimReference,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"`
Responsible_Nurse_Code *string `json:"responsible_nurse_code"`
Responsible_Nurse *en.Nurse `json:"responsible_nurse,omitempty" gorm:"foreignKey:Responsible_Nurse_Code;references:Code"`
}
func (d Encounter) IsDone() bool {
@@ -9,10 +9,13 @@ import (
)
type CreateDto struct {
Encounter_Id *uint `json:"-"`
Unit_Code *string `json:"unit_code"`
Doctor_Code *string `json:"doctor_code"`
Status_Code erc.DataApprovalCode `json:"status_code"`
Encounter_Id *uint `json:"-"`
Unit_Code *string `json:"unit_code"`
Doctor_Code *string `json:"doctor_code"`
Nurse_Code *string `json:"nurse_code"`
Status_Code erc.DataApprovalCode `json:"status_code"`
SrcDoctor_Code *string `json:"srcDoctor_code"`
SrcNurse_Code *string `json:"srcNurse_code"`
}
type ReadListDto struct {
@@ -29,17 +32,17 @@ type FilterDto struct {
}
type ReadDetailDto struct {
Id uint16 `json:"id"`
Id uint `json:"id"`
Includes string `json:"includes"`
}
type UpdateDto struct {
Id uint16 `json:"id"`
Id uint `json:"id"`
CreateDto
}
type DeleteDto struct {
Id uint16 `json:"id"`
Id uint `json:"id"`
}
type MetaDto struct {
@@ -5,15 +5,22 @@ import (
ecore "simrs-vx/internal/domain/base-entities/core"
ed "simrs-vx/internal/domain/main-entities/doctor"
en "simrs-vx/internal/domain/main-entities/nurse"
eu "simrs-vx/internal/domain/main-entities/unit"
)
type InternalReference struct {
ecore.Main
Encounter_Id *uint `json:"encounter_id"`
Unit_Code *string `json:"unit_code"`
Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Code;references:Code"`
Doctor_Code *string `json:"doctor_code"`
Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Code;references:Code"`
Status_Code *erc.DataApprovalCode `json:"status_code"`
Encounter_Id *uint `json:"encounter_id"`
Unit_Code *string `json:"unit_code"`
Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Code;references:Code"`
Doctor_Code *string `json:"doctor_code"`
Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Code;references:Code"`
Status_Code *erc.DataApprovalCode `json:"status_code"`
SrcDoctor_Code *string `json:"srcDoctor_code"`
SrcDoctor *ed.Doctor `json:"srcDoctor,omitempty" gorm:"foreignKey:SrcDoctor_Code;references:Code"`
SrcNurse_Code *string `json:"srcNurse_code"`
SrcNurse *en.Nurse `json:"srcNurse,omitempty" gorm:"foreignKey:SrcNurse_Code;references:Code"`
Nurse_Code *string `json:"nurse_code"`
Nurse *en.Nurse `json:"nurse,omitempty" gorm:"foreignKey:Nurse_Code;references:Code"`
}
@@ -106,6 +106,7 @@ const (
DACNew DataApprovalCode = "new"
DACApproved DataApprovalCode = "approved"
DACRejected DataApprovalCode = "rejected"
DACCanceled DataApprovalCode = "canceled"
PSCSuccess ProcessStatusCode = "success"
PSCFailed ProcessStatusCode = "failed"
@@ -95,10 +95,10 @@ const (
RTCPrivate RefTypeCode = "private" // Swasta
RTCBpjs RefTypeCode = "bpjs" // BPJS
APMCJkn AllPaymentMethodCode = "jkn" // JKN
APMCJkmm AllPaymentMethodCode = "jkmm" // JKMM
APMCSpm AllPaymentMethodCode = "spm" // SPM
APMCPks AllPaymentMethodCode = "pks" // PKS
APMCJkn AllPaymentMethodCode = "jkn" // JKN -> Jaminan Kesehatan Nasional -> BPJS Kesehatan
APMCJkmm AllPaymentMethodCode = "jkmm" // JKMM -> Jaminan Kesehatan Masyarakat Miskin -> Dibiayai oleh APBD daerah
APMCSpm AllPaymentMethodCode = "spm" // SPM -> Surat Pernyataan Miskin
APMCPks AllPaymentMethodCode = "pks" // PKS -> Perjanjian Kerjasama -> Pembayaran melalui instansi atau perusahaan yang memiliki kontrak dengan rumah sakit
APMCUmum AllPaymentMethodCode = "umum"
SRTCInternal SEPRefTypeCode = "internal" // Rujukan Internal
@@ -1,4 +1,4 @@
package division
package m_polihfis
type MPolihfis struct {
Id uint `json:"id" gorm:"primaryKey;autoIncrement;column:id"`
@@ -1,7 +1,7 @@
package m_poly
type MPoly struct {
Kode uint `json:"kode" gorm:"primaryKey;autoIncrement;column:kode"`
Kode uint `json:"kode" gorm:"primaryKey;column:kode"`
Nama string `json:"nama" gorm:"column:nama"`
Jenispoly uint `json:"jenispoly" gorm:"column:jenispoly"`
}
@@ -82,7 +82,6 @@ type TPendaftaran struct {
DokterNameHfis *string `json:"dokter_name_hfis" gorm:"column:dokter_name_hfis"`
DokterIdHfis *string `json:"dokter_id_hfis" gorm:"column:dokter_id_hfis"`
StatusBridging *string `json:"status_bridging" gorm:"column:status_bridging"`
NoSpri *string `json:"no_spri" gorm:"column:no_spri"`
}
func (TPendaftaran) TableName() string {
@@ -0,0 +1,29 @@
package internal_reference
import (
ecore "simrs-vx/internal/domain/base-entities/core"
erc "simrs-vx/internal/domain/references/common"
"time"
)
type InternalReferenceLink struct {
ecore.Main
Simx_Id uint `json:"simx_id" gorm:"unique"`
Simgos_Id uint `json:"simgos_id" gorm:"unique"`
}
type InternalReferenceSimxLog struct {
ecore.Main
Value *string `json:"value"`
Date *time.Time `json:"date"`
Status erc.ProcessStatusCode `json:"status"`
ErrMessage *string `json:"errMessage"`
}
type InternalReferenceSimgosLog struct {
ecore.Main
Value *string `json:"value"`
Date *time.Time `json:"date"`
Status erc.ProcessStatusCode `json:"status"`
ErrMessage *string `json:"errMessage"`
}
@@ -64,7 +64,7 @@ func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) {
}
dto := e.ReadDetailDto{}
sf.UrlQueryParam(&dto, *r.URL)
dto.Id = uint16(id)
dto.Id = uint(id)
res, err := u.ReadDetail(dto)
rw.DataResponse(w, res, err)
}
@@ -84,7 +84,7 @@ func (obj myBase) Update(w http.ResponseWriter, r *http.Request) {
if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res {
return
}
dto.Id = uint16(id)
dto.Id = uint(id)
dto.AuthInfo = *authInfo
res, err := u.Update(dto)
@@ -103,7 +103,7 @@ func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) {
}
dto := e.DeleteDto{}
dto.Id = uint16(id)
dto.Id = uint(id)
dto.AuthInfo = *authInfo
res, err := u.Delete(dto)
@@ -174,9 +174,15 @@ func (obj myBase) Process(w http.ResponseWriter, r *http.Request) {
return
}
authInfo, err := pa.GetAuthInfo(r)
if err != nil {
rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil)
}
dto := e.UpdateStatusDto{
Id: uint16(id),
Id: uint(id),
StatusCode: erc.DSCProcess,
AuthInfo: *authInfo,
}
res, err := u.UpdateStatusCode(dto)
@@ -195,11 +201,11 @@ func (obj myBase) Cancel(w http.ResponseWriter, r *http.Request) {
}
dto := e.UpdateStatusDto{
Id: uint16(id),
Id: uint(id),
StatusCode: erc.DSCCancel,
AuthInfo: *authInfo,
}
dto.AuthInfo = *authInfo
res, err := u.UpdateStatusCode(dto)
rw.DataResponse(w, res, err)
}
@@ -211,7 +217,7 @@ func (obj myBase) Reject(w http.ResponseWriter, r *http.Request) {
}
dto := e.UpdateStatusDto{
Id: uint16(id),
Id: uint(id),
StatusCode: erc.DSCRejected,
}
@@ -226,7 +232,7 @@ func (obj myBase) Skip(w http.ResponseWriter, r *http.Request) {
}
dto := e.UpdateStatusDto{
Id: uint16(id),
Id: uint(id),
StatusCode: erc.DSCSkipped,
}
@@ -250,13 +256,19 @@ func (obj myBase) RequestSwitchUnit(w http.ResponseWriter, r *http.Request) {
return
}
authInfo, err := pa.GetAuthInfo(r)
if err != nil {
rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil)
}
dto.AuthInfo = *authInfo
dto.Id = uint(id)
res, err := u.RequestSwitchUnit(dto)
rw.DataResponse(w, res, err)
}
func (obj myBase) ApproveSwitchUnit(w http.ResponseWriter, r *http.Request) {
dto := e.ApproveUnitDto{}
dto := e.ApproveCancelUnitDto{}
id := rw.ValidateInt(w, "id", r.PathValue("id"))
if id <= 0 {
return
@@ -266,7 +278,37 @@ func (obj myBase) ApproveSwitchUnit(w http.ResponseWriter, r *http.Request) {
return
}
authInfo, err := pa.GetAuthInfo(r)
if err != nil {
rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil)
}
dto.AuthInfo = *authInfo
dto.Id = uint(id)
res, err := u.ApproveSwitchUnit(dto)
rw.DataResponse(w, res, err)
}
func (obj myBase) CancelSwitchUnit(w http.ResponseWriter, r *http.Request) {
dto := e.ApproveCancelUnitDto{}
id := rw.ValidateInt(w, "id", r.PathValue("id"))
if id <= 0 {
return
}
if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res {
return
}
authInfo, err := pa.GetAuthInfo(r)
if err != nil {
rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil)
}
dto.AuthInfo = *authInfo
dto.Id = uint(id)
res, err := u.CancelSwitchUnit(dto)
rw.DataResponse(w, res, err)
}
@@ -59,6 +59,22 @@ func validateRequestCheckIn(w http.ResponseWriter, i e.CheckinDto) (valid bool)
}
func validateRequestSwitchUnit(w http.ResponseWriter, i e.SwitchUnitDto) (valid bool) {
// validate poly-switch-code
if i.PolySwitchCode == nil {
rw.DataResponse(w, nil, d.FieldError{
Code: dataValidationFail,
Message: fmt.Sprintf("polySwitchCode required"),
})
return
}
if *i.PolySwitchCode != ere.PSCConsulPoly && *i.PolySwitchCode != ere.PSCConsulExecutive {
rw.DataResponse(w, nil, d.FieldError{
Code: dataValidationFail,
Message: "invalid PolySwitchCode",
})
}
if i.InternalReferences == nil {
rw.DataResponse(w, nil, d.FieldError{
Code: dataValidationFail,
@@ -39,7 +39,7 @@ func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) {
dto := eir.ReadDetailDto{}
sf.UrlQueryParam(&dto, *r.URL)
dto.Id = uint16(id)
dto.Id = uint(id)
res, err := uir.ReadDetail(dto)
rw.DataResponse(w, res, err)
}
@@ -54,7 +54,7 @@ func (obj myBase) Update(w http.ResponseWriter, r *http.Request) {
if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res {
return
}
dto.Id = uint16(id)
dto.Id = uint(id)
res, err := uir.Update(dto)
rw.DataResponse(w, res, err)
}
@@ -66,7 +66,7 @@ func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) {
}
dto := eir.DeleteDto{}
dto.Id = uint16(id)
dto.Id = uint(id)
res, err := uir.Delete(dto)
rw.DataResponse(w, res, err)
}
@@ -175,6 +175,7 @@ func SetRoutes() http.Handler {
"PATCH /{id}/skip": encounter.O.Skip,
"PATCH /{id}/req-switch-unit": encounter.O.RequestSwitchUnit,
"PATCH /{id}/approve-switch-unit": encounter.O.ApproveSwitchUnit,
"PATCH /{id}/cancel-switch-unit": encounter.O.CancelSwitchUnit,
})
hk.GroupRoutes("/v1/mcu-order", r, auth.GuardMW, hk.MapHandlerFunc{
"GET /": mcuorder.O.GetList,
@@ -5,6 +5,7 @@ import (
division "simrs-vx/internal/domain/sync-entities/division"
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"
patient "simrs-vx/internal/domain/sync-entities/patient"
specialist "simrs-vx/internal/domain/sync-entities/specialist"
subspecialist "simrs-vx/internal/domain/sync-entities/subspecialist"
@@ -34,5 +35,8 @@ func getSyncEntities() []any {
&encounter.EncounterLink{},
&encounter.EncounterSimxLog{},
&encounter.EncounterSimgosLog{},
&internalreference.InternalReferenceLink{},
&internalreference.InternalReferenceSimxLog{},
&internalreference.InternalReferenceSimgosLog{},
}
}
@@ -51,7 +51,7 @@ func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) {
}
dto := e.DeleteDto{}
dto.Id = uint16(id)
dto.Id = uint(id)
res, err := u.Delete(dto)
rw.DataResponse(w, res, err)
@@ -77,12 +77,42 @@ func (obj myBase) Checkout(w http.ResponseWriter, r *http.Request) {
rw.DataResponse(w, res, err)
}
func (obj myBase) Cancel(w http.ResponseWriter, r *http.Request) {
func (obj myBase) UpdateStatus(w http.ResponseWriter, r *http.Request) {
dto := e.Encounter{}
if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res {
return
}
res, err := u.Cancel(dto)
res, err := u.UpdateStatus(dto)
rw.DataResponse(w, res, err)
}
func (obj myBase) RequestSwitchUnit(w http.ResponseWriter, r *http.Request) {
dto := e.Encounter{}
if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res {
return
}
res, err := u.RequestSwitchUnit(dto)
rw.DataResponse(w, res, err)
}
func (obj myBase) ApproveSwitchUnit(w http.ResponseWriter, r *http.Request) {
dto := e.ApproveCancelUnitDto{}
if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res {
return
}
res, err := u.ApproveSwitchUnit(dto)
rw.DataResponse(w, res, err)
}
func (obj myBase) CancelSwitchUnit(w http.ResponseWriter, r *http.Request) {
dto := e.ApproveCancelUnitDto{}
if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res {
return
}
res, err := u.CancelSwitchUnit(dto)
rw.DataResponse(w, res, err)
}
@@ -56,13 +56,16 @@ func SetRoutes() http.Handler {
"POST /nomr": patient.O.GenerateNomr,
})
hk.GroupRoutes(prefixnew+"/v1/encounter", r, hk.MapHandlerFunc{
"POST /": encounter.O.Create,
"POST /log": encounter.O.CreateLog,
"PATCH /{id}": encounter.O.Update,
"DELETE /{id}": encounter.O.Delete,
"PATCH /{id}/checkin": encounter.O.Checkin,
"PATCH /{id}/checkout": encounter.O.Checkout,
"PATCH /{id}/cancel": encounter.O.Cancel,
"POST /": encounter.O.Create,
"POST /log": encounter.O.CreateLog,
"PATCH /{id}": encounter.O.Update,
"DELETE /{id}": encounter.O.Delete,
"PATCH /{id}/checkin": encounter.O.Checkin,
"PATCH /{id}/checkout": encounter.O.Checkout,
"PATCH /{id}/update-status": encounter.O.UpdateStatus,
"PATCH /{id}/req-switch-unit": encounter.O.RequestSwitchUnit,
"PATCH /{id}/approve-switch-unit": encounter.O.ApproveSwitchUnit,
"PATCH /{id}/cancel-switch-unit": encounter.O.CancelSwitchUnit,
})
/******************** SvcToNew ******************/
@@ -87,6 +87,9 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e
if input.Id != nil {
tx = tx.Where("\"Id\" = ?", input.Id)
}
if input.Code != nil {
tx = tx.Where("\"Code\" = ?", input.Code)
}
if err := tx.First(&data).Error; err != nil {
if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil {
return nil, processedErr
@@ -37,7 +37,7 @@ func Create(input e.CreateDto) (*d.Data, error) {
}
// validate encounter_id
_, err := ue.ReadDetail(ee.ReadDetailDto{Id: uint16(*input.Encounter_Id)})
_, err := ue.ReadDetail(ee.ReadDetailDto{Id: *input.Encounter_Id})
if err != nil {
return err
}
+219 -154
View File
@@ -19,19 +19,15 @@ import (
erg "simrs-vx/internal/domain/references/organization"
ev "simrs-vx/internal/domain/bpjs-entities/vclaim-reference"
eaeh "simrs-vx/internal/domain/main-entities/adm-employee-hist"
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"
erdh "simrs-vx/internal/domain/main-entities/responsible-doctor-hist"
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"
uaeh "simrs-vx/internal/use-case/main-use-case/adm-employee-hist"
udc "simrs-vx/internal/use-case/main-use-case/death-cause"
uir "simrs-vx/internal/use-case/main-use-case/internal-reference"
urdh "simrs-vx/internal/use-case/main-use-case/responsible-doctor-hist"
us "simrs-vx/internal/use-case/main-use-case/soapi"
)
@@ -118,7 +114,6 @@ func Create(input e.CreateDto) (*d.Data, error) {
// insert vclaimReference
if vr := input.VclaimReference; vr != nil {
t, _ := time.Parse("2006-01-02", vr.TglRujukan)
_, err = uv.CreateData(ev.CreateDto{
Encounter_Id: &data.Id,
Date: &t,
@@ -127,17 +122,11 @@ func Create(input e.CreateDto) (*d.Data, error) {
Number: &vr.NoSep}, &event, tx)
}
// insert adm_employee_hist (employee with role reg for create)
if _, err = uaeh.CreateData(eaeh.CreateDto{
Encounter_Id: &data.Id,
Employee_Id: data.Adm_Employee_Id,
StartedAt: &now}, &event, tx); err != nil {
return err
}
dataEncounter, err := ReadDetailData(e.ReadDetailDto{
Id: uint16(data.Id),
Includes: "Adm_Employee.User,Patient.Person.Relatives,Patient.Person.VclaimMember,VclaimReference"},
Id: data.Id,
Includes: "Adm_Employee.User,Patient.Person.Relatives," +
"Patient.Person.VclaimMember,VclaimReference," +
"Patient.Person.Contacts,Patient.Person.Addresses"},
&event, tx)
if err != nil {
return err
@@ -311,7 +300,7 @@ func Update(input e.UpdateDto) (*d.Data, error) {
}
dataEncounter, err := ReadDetailData(e.ReadDetailDto{
Id: uint16(data.Id),
Id: data.Id,
Includes: "Adm_Employee.User,Patient.Person.Relatives,Patient.Person.VclaimMember"},
&event, tx)
if err != nil {
@@ -429,7 +418,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) {
}
func CheckOut(input e.DischargeDto) (*d.Data, error) {
rdDto := e.ReadDetailDto{Id: uint16(input.Id), Includes: "Ambulatory,Rehab"}
rdDto := e.ReadDetailDto{Id: input.Id, Includes: "Ambulatory,Rehab,InternalReferences"}
var data *e.Encounter
var err error
@@ -441,7 +430,7 @@ func CheckOut(input e.DischargeDto) (*d.Data, error) {
// Start log
pl.SetLogInfo(&event, input, "started", "checkOut")
roleAllowed := []string{string(erg.EPCNur), string(erg.EPCDoc)}
roleAllowed := []string{string(erg.EPCNur)}
err = validateAuth(input.AuthInfo, roleAllowed, "checkOut-encounter", &event)
if err != nil {
return nil, err
@@ -466,7 +455,7 @@ func CheckOut(input e.DischargeDto) (*d.Data, error) {
}
if data.Ambulatory != nil && (data.Ambulatory.Class_Code == ere.ACCReg || data.Ambulatory.Class_Code == ere.ACCRehab) {
// validate if soapi exist
// Validate SOAPI completeness: abort checkout if any required SOAPI is missing.
if err = getSoapiByTypeCode(data, &event, "check-out"); err != nil {
return err
}
@@ -478,12 +467,13 @@ func CheckOut(input e.DischargeDto) (*d.Data, error) {
}
}
} else {
// chemo TBC
// TODO: chemo TBC (to be confirm)
if err := checkSoapiByDocExists(data.Id, &event, tx); err != nil {
return err
}
}
// update encounter
if err := updateDischargeData(input, data, &event, tx); err != nil {
return err
}
@@ -498,16 +488,6 @@ func CheckOut(input e.DischargeDto) (*d.Data, error) {
}
}
// update finishedAt in latest responsible_doctor_hist
if err = updateLatestResponsibleDoctorHist(e.CheckinDto{Id: input.Id, FinishedAt: &now}, &event, tx); err != nil {
return err
}
// update finishedAt in latest adm_employee_hist
if err = updateLatestAdmEmployeeHist(e.CheckinDto{Id: input.Id, FinishedAt: &now}, &event, tx); err != nil {
return err
}
// insert data death-cause
if *input.Discharge_Method_Code == ere.DMCDeath {
if _, err = udc.CreateData(edc.CreateDto{Encounter_Id: &input.Id, Value: input.DeathCause}, &event, tx); err != nil {
@@ -515,10 +495,23 @@ func CheckOut(input e.DischargeDto) (*d.Data, error) {
}
}
dataEncounter, err := ReadDetailData(e.ReadDetailDto{
Id: uint16(data.Id),
Includes: "DeathCause"},
&event, tx)
// perform additional validation when discharge_method_code is "consul-poly" or "consul-executive"
if *data.Discharge_Method_Code == ere.DMCConsulPoly || *data.Discharge_Method_Code == ere.DMCConsulExecutive {
for _, v := range *data.InternalReferences {
if *v.Status_Code == erc.DACNew {
event.Status = "failed"
event.ErrInfo = pl.ErrorInfo{
Code: "data-state-mismatch",
Detail: "checkout is not allowed because the internal-reference status is 'new'",
Raw: errors.New("internal-referral status not done yet"),
}
return pl.SetLogError(&event, input)
}
}
}
// read the newest data encounter for sync
dataEncounter, err := ReadDetailData(e.ReadDetailDto{Id: data.Id, Includes: "DeathCause"}, &event, tx)
if err != nil {
return err
}
@@ -560,6 +553,14 @@ func UpdateStatusCode(input e.UpdateStatusDto) (*d.Data, error) {
// Start log
pl.SetLogInfo(&event, input, "started", "update")
// TODO: Only "supervisi pendaftaran" could cancel encounter
roleAllowed := []string{string(erg.EPCReg), string(erg.EPCNur), string(erg.EPCDoc)}
err = validateAuth(input.AuthInfo, roleAllowed, "update-status-encounter", &event)
if err != nil {
return nil, err
}
mwRunner := newMiddlewareRunner(&event)
err = dg.I.Transaction(func(tx *gorm.DB) error {
@@ -581,34 +582,6 @@ func UpdateStatusCode(input e.UpdateStatusDto) (*d.Data, error) {
if input.StatusCode == erc.DSCCancel {
// TODO: Prevent cancellation if the billing has been verified
// TODO: Only "supervisi pendaftaran" could cancel encounter
roleAllowedToCancel := []string{
string(erg.EPCReg),
string(erg.EPCNur),
string(erg.EPCDoc),
}
// check if user has employee position
if !input.AuthInfo.HasEmployeePosition() {
event.Status = "failed"
event.ErrInfo = pl.ErrorInfo{
Code: "auth-forbidden",
Detail: "user has no employee position",
Raw: errors.New("authentication failed"),
}
return pl.SetLogError(&event, input)
}
if input.AuthInfo.Employee_Position_Code != nil && !pu.Contains(roleAllowedToCancel, *input.AuthInfo.Employee_Position_Code) {
event.Status = "failed"
event.ErrInfo = pl.ErrorInfo{
Code: "auth-forbidden",
Detail: "user position is not allowed, only user with registration, nurse, or doctor position is allowed to cancel encounter",
Raw: errors.New("authentication failed"),
}
return pl.SetLogError(&event, input)
}
// Prevent cancellation if soapi exist
dataSoapi, _, err := us.ReadListData(es.ReadListDto{
FilterDto: es.FilterDto{Encounter_Id: &data.Id}}, &event, tx)
@@ -627,11 +600,13 @@ func UpdateStatusCode(input e.UpdateStatusDto) (*d.Data, error) {
}
}
if err := UpdateStatusData(input, data, &event, tx); err != nil {
if err := UpdateStatusData(input, &event, tx); err != nil {
return err
}
if input.StatusCode == erc.DSCCancel {
if input.StatusCode == erc.DSCProcess || input.StatusCode == erc.DSCCancel {
data.Status_Code = input.StatusCode
mwRunner.setMwType(pu.MWTPre)
// Run pre-middleware
if err := mwRunner.RunUpdateStatusMiddleware(updatestatusEncounter, data); err != nil {
@@ -642,10 +617,12 @@ func UpdateStatusCode(input e.UpdateStatusDto) (*d.Data, error) {
return nil
})
if err != nil {
if err = runLogMiddleware(err, input, mwRunner); err != nil {
return nil, err
}
pl.SetLogInfo(&event, nil, "complete")
return &d.Data{
Meta: d.IS{
"source": source,
@@ -658,7 +635,7 @@ func UpdateStatusCode(input e.UpdateStatusDto) (*d.Data, error) {
}
func CheckIn(input e.CheckinDto) (*d.Data, error) {
rdDto := e.ReadDetailDto{Id: uint16(input.Id), Includes: "Rehab,Ambulatory"}
rdDto := e.ReadDetailDto{Id: input.Id, Includes: "Rehab,Ambulatory"}
var data *e.Encounter
var err error
@@ -675,10 +652,10 @@ func CheckIn(input e.CheckinDto) (*d.Data, error) {
if err != nil {
return nil, err
}
input.Adm_Employee_Id = input.AuthInfo.Employee_Id
input.Responsible_Nurse_Code = input.AuthInfo.Nurse_Code
// validate foreign key
if err := validateForeignKey(input); err != nil {
if err := validateForeignKey(input, &event); err != nil {
return nil, err
}
@@ -705,7 +682,7 @@ func CheckIn(input e.CheckinDto) (*d.Data, error) {
return pl.SetLogError(&event, input)
}
// validate if soapi exist
// prevent repeated check-in. If SOAPI already exists, block the check-in process.
if data.Ambulatory != nil && (data.Ambulatory.Class_Code == ere.ACCReg || data.Ambulatory.Class_Code == ere.ACCRehab) {
err = getSoapiByTypeCode(data, &event, "check-in")
if err != nil {
@@ -713,39 +690,13 @@ func CheckIn(input e.CheckinDto) (*d.Data, error) {
}
}
// Upsert responsible_doctor_hist if responsible_doctor_code has changed
if data.Responsible_Doctor_Code == nil || *input.Responsible_Doctor_Code != *data.Responsible_Doctor_Code {
// upsert responsibleDoctorHist
if err = upsertResponsibleDoctorHist(erdh.CreateDto{
Encounter_Id: &data.Id,
Doctor_Code: input.Responsible_Doctor_Code,
StartedAt: input.StartedAt,
}, &event, tx); err != nil {
return err
}
}
// Upsert adm_employee_hist if adm_employee_id has changed
if *input.Adm_Employee_Id != *data.Adm_Employee_Id {
// upsert admEmployeeHist
if err = upsertAdmEmployeeHist(eaeh.CreateDto{
Encounter_Id: &data.Id,
Employee_Id: input.Adm_Employee_Id,
StartedAt: input.StartedAt,
}, &event, tx); err != nil {
return err
}
}
// update encounter data
if err := updateCheckInData(input, data, &event, tx); err != nil {
return err
}
dataEncounter, err := ReadDetailData(e.ReadDetailDto{
Id: uint16(data.Id),
Includes: "Adm_Employee.User"},
&event, tx)
// read the newest data encounter for sync
dataEncounter, err := ReadDetailData(e.ReadDetailDto{Id: data.Id, Includes: "Responsible_Nurse.Employee.User"}, &event, tx)
if err != nil {
return err
}
@@ -776,7 +727,7 @@ func CheckIn(input e.CheckinDto) (*d.Data, error) {
}
func RequestSwitchUnit(input e.SwitchUnitDto) (*d.Data, error) {
rdDto := e.ReadDetailDto{Id: uint16(input.Id), Includes: "Responsible_Doctor"}
rdDto := e.ReadDetailDto{Id: input.Id, Includes: "Responsible_Nurse.Employee.User,Responsible_Doctor.Employee"}
var data *e.Encounter
var err error
@@ -809,23 +760,33 @@ func RequestSwitchUnit(input e.SwitchUnitDto) (*d.Data, error) {
return nil, err
}
roleAllowed := []string{string(erg.EPCNur)}
err = validateAuth(input.AuthInfo, roleAllowed, "request-switch-poly", &event)
if err != nil {
return nil, err
}
input.Src_Nurse_Code = input.AuthInfo.Nurse_Code
mwRunner := newMiddlewareRunner(&event)
err = dg.I.Transaction(func(tx *gorm.DB) error {
pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail")
if data, err = ReadDetailData(rdDto, &event, tx); err != nil {
return err
}
input.Src_Doctor_Code = data.Responsible_Doctor_Code
//if data.IsDone() {
// event.Status = "failed"
// event.ErrInfo = pl.ErrorInfo{
// Code: "data-state-mismatch",
// Detail: "encounter is done",
// Raw: errors.New("encounter is done"),
// }
// return pl.SetLogError(&event, input)
//}
if data.IsDone() {
event.Status = "failed"
event.ErrInfo = pl.ErrorInfo{
Code: "data-state-mismatch",
Detail: "encounter is done",
Raw: errors.New("encounter is done"),
}
return pl.SetLogError(&event, input)
}
// verify Soapi exist for current responsible doctor
// Poly-Switch-Requests can only be processed if the previous responsible doctor has completed their SOAPI.
dataSoapi, err := getSoapiByResponsibleDoctor(*data, &event)
if err != nil {
return err
@@ -839,21 +800,36 @@ func RequestSwitchUnit(input e.SwitchUnitDto) (*d.Data, error) {
return pl.SetLogError(&event, input)
}
// bulk internal references
if err := uir.CreateBulkData(*input.InternalReferences, input.Id, &event, tx); err != nil {
// update encounter discharge_method_code
if err = UpdateDischargeMethod(input, &event, tx); err != nil {
return err
}
// TODO: update status encounter, finishedAt
// bulk internal references
if err := uir.CreateBulkData(&input, &event, tx); err != nil {
return err
}
pl.SetLogInfo(&event, nil, "complete")
// read the newest data encounter for sync
dataEncounter, err := ReadDetailData(e.ReadDetailDto{Id: data.Id, Includes: "InternalReferences,Responsible_Nurse.Employee.User"}, &event, tx)
if err != nil {
return err
}
mwRunner.setMwType(pu.MWTPre)
// Run pre-middleware
if err := mwRunner.RunRequestSwitchUnitMiddleware(requestSwitchEncounter, dataEncounter); err != nil {
return err
}
return nil
})
if err != nil {
if err = runLogMiddleware(err, input, mwRunner); err != nil {
return nil, err
}
pl.SetLogInfo(&event, nil, "complete")
return &d.Data{
Meta: d.IS{
"source": source,
@@ -864,10 +840,12 @@ func RequestSwitchUnit(input e.SwitchUnitDto) (*d.Data, error) {
}, nil
}
func ApproveSwitchUnit(input e.ApproveUnitDto) (*d.Data, error) {
rdDto := e.ReadDetailDto{Id: uint16(input.Id), Includes: "Responsible_Doctor"}
var data *e.Encounter
var err error
func ApproveSwitchUnit(input e.ApproveCancelUnitDto) (*d.Data, error) {
rdDto := e.ReadDetailDto{Id: input.Id, Includes: "Responsible_Doctor.Employee"}
var (
data *e.Encounter
err error
)
event := pl.Event{
Feature: "ApproveSwitchUnit",
@@ -877,13 +855,31 @@ func ApproveSwitchUnit(input e.ApproveUnitDto) (*d.Data, error) {
// Start log
pl.SetLogInfo(&event, input, "started", "approveSwitchUnit")
roleAllowed := []string{string(erg.EPCNur)}
err = validateAuth(input.AuthInfo, roleAllowed, "request-switch-poly", &event)
if err != nil {
return nil, err
}
mwRunner := newMiddlewareRunner(&event)
err = dg.I.Transaction(func(tx *gorm.DB) error {
pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail")
if data, err = ReadDetailData(rdDto, &event, tx); err != nil {
return err
}
// get internal reference
if data.IsDone() {
event.Status = "failed"
event.ErrInfo = pl.ErrorInfo{
Code: "data-state-mismatch",
Detail: "encounter is done",
Raw: errors.New("encounter is done"),
}
return pl.SetLogError(&event, input)
}
// get internalReference based on internalReferences_Id
irData, err := uir.ReadDetailData(eir.ReadDetailDto{
Id: input.InternalReferences_Id, Includes: "Doctor"}, &event, tx)
if err != nil {
@@ -900,17 +896,7 @@ func ApproveSwitchUnit(input e.ApproveUnitDto) (*d.Data, error) {
return pl.SetLogError(&event, input)
}
//if data.IsDone() {
// event.Status = "failed"
// event.ErrInfo = pl.ErrorInfo{
// Code: "data-state-mismatch",
// Detail: "encounter is done",
// Raw: errors.New("encounter is done"),
// }
// return pl.SetLogError(&event, input)
//}
// verify Soapi exist for current responsible doctor
// Approve-Switch-Requests can only be processed if the previous responsible doctor has completed their SOAPI.
dataSoapi, err := getSoapiByResponsibleDoctor(*data, &event)
if err != nil {
return err
@@ -924,51 +910,130 @@ func ApproveSwitchUnit(input e.ApproveUnitDto) (*d.Data, error) {
return pl.SetLogError(&event, input)
}
// Set doctor_code; nil indicates no change.
if input.Dst_Doctor_Code == nil {
input.Dst_Doctor_Code = irData.Doctor_Code
}
// update internal reference
if err = uir.UpdateData(eir.UpdateDto{
Id: input.InternalReferences_Id,
CreateDto: eir.CreateDto{
Encounter_Id: &input.Id,
Doctor_Code: irData.Doctor_Code,
Unit_Code: irData.Unit_Code,
Status_Code: erc.DACApproved,
}}, irData, &event, tx); err != nil {
Status_Code: erc.DACApproved,
Doctor_Code: input.Dst_Doctor_Code,
Nurse_Code: input.Nurse_Code}}, irData, &event, tx); err != nil {
return err
}
// update encounter
if err = updateEncounterApproveSwitchUnit(*irData, &event, tx); err != nil {
if err = updateEncounterApproveSwitchUnit(input, &event, tx); err != nil {
return err
}
// update latest responsible doctor hist
if err = updateLatestResponsibleDoctorHist(e.CheckinDto{Id: input.Id, FinishedAt: &now}, &event, tx); err != nil {
mwRunner.setMwType(pu.MWTPre)
// Run pre-middleware
if err := mwRunner.RunApproveSwitchUnitMiddleware(approveSwitchEncounter, &input); err != nil {
return err
}
// create responsible doctor based on internal reference data
if _, err = urdh.CreateData(erdh.CreateDto{
Encounter_Id: &input.Id,
Doctor_Code: irData.Doctor_Code,
StartedAt: &now,
}, &event, tx); err != nil {
return err
}
// update data response
data.Responsible_Doctor_Code = irData.Doctor_Code
data.Unit_Code = irData.Unit_Code
data.Specialist_Code = irData.Doctor.Specialist_Code
data.Subspecialist_Code = irData.Doctor.Subspecialist_Code
pl.SetLogInfo(&event, nil, "complete")
return nil
})
if err = runLogMiddleware(err, input, mwRunner); err != nil {
return nil, err
}
pl.SetLogInfo(&event, nil, "complete")
return &d.Data{
Meta: d.IS{
"source": source,
"structure": "single-data",
"status": "updated",
},
Data: data.ToResponse(),
}, nil
}
func CancelSwitchUnit(input e.ApproveCancelUnitDto) (*d.Data, error) {
rdDto := e.ReadDetailDto{Id: input.Id}
var (
data *e.Encounter
err error
)
event := pl.Event{
Feature: "CancelSwitchUnit",
Source: source,
}
// Start log
pl.SetLogInfo(&event, input, "started", "cancelSwitchUnit")
roleAllowed := []string{string(erg.EPCNur)}
err = validateAuth(input.AuthInfo, roleAllowed, "request-switch-poly", &event)
if err != nil {
return nil, err
}
mwRunner := newMiddlewareRunner(&event)
err = dg.I.Transaction(func(tx *gorm.DB) error {
pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail")
if data, err = ReadDetailData(rdDto, &event, tx); err != nil {
return err
}
if data.IsDone() {
event.Status = "failed"
event.ErrInfo = pl.ErrorInfo{
Code: "data-state-mismatch",
Detail: "encounter is done",
Raw: errors.New("encounter is done"),
}
return pl.SetLogError(&event, input)
}
// get internalReference based on internalReferences_Id
irData, err := uir.ReadDetailData(eir.ReadDetailDto{
Id: input.InternalReferences_Id}, &event, tx)
if err != nil {
return err
}
if *irData.Status_Code != erc.DACNew {
event.Status = "failed"
event.ErrInfo = pl.ErrorInfo{
Code: "data-state-mismatch",
Detail: "internal references is approve",
Raw: errors.New("internal references is approve"),
}
return pl.SetLogError(&event, input)
}
// update internal reference
if err = uir.UpdateData(eir.UpdateDto{
Id: input.InternalReferences_Id,
CreateDto: eir.CreateDto{
Status_Code: erc.DACCanceled,
Nurse_Code: input.Nurse_Code}}, irData, &event, tx); err != nil {
return err
}
mwRunner.setMwType(pu.MWTPre)
// Run pre-middleware
if err := mwRunner.RunCancelSwitchUnitMiddleware(cancelSwitchEncounter, &input); 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.IS{
"source": source,
@@ -7,6 +7,7 @@ package encounter
import (
"errors"
"fmt"
un "simrs-vx/internal/use-case/main-use-case/nurse"
"strings"
"time"
@@ -29,7 +30,6 @@ import (
edo "simrs-vx/internal/domain/main-entities/device-order"
ed "simrs-vx/internal/domain/main-entities/doctor"
ee "simrs-vx/internal/domain/main-entities/emergency"
eem "simrs-vx/internal/domain/main-entities/employee"
e "simrs-vx/internal/domain/main-entities/encounter"
ei "simrs-vx/internal/domain/main-entities/inpatient"
emo "simrs-vx/internal/domain/main-entities/material-order"
@@ -38,6 +38,7 @@ import (
emei "simrs-vx/internal/domain/main-entities/medication-item"
emi "simrs-vx/internal/domain/main-entities/medicine-mix"
emmi "simrs-vx/internal/domain/main-entities/medicine-mix-item"
en "simrs-vx/internal/domain/main-entities/nurse"
ep "simrs-vx/internal/domain/main-entities/prescription"
epi "simrs-vx/internal/domain/main-entities/prescription-item"
er "simrs-vx/internal/domain/main-entities/rehab"
@@ -51,12 +52,12 @@ import (
uc "simrs-vx/internal/use-case/main-use-case/chemo"
ud "simrs-vx/internal/use-case/main-use-case/doctor"
ue "simrs-vx/internal/use-case/main-use-case/emergency"
uem "simrs-vx/internal/use-case/main-use-case/employee"
ui "simrs-vx/internal/use-case/main-use-case/inpatient"
um "simrs-vx/internal/use-case/main-use-case/medication"
umei "simrs-vx/internal/use-case/main-use-case/medication-item"
umi "simrs-vx/internal/use-case/main-use-case/medicine-mix"
ummi "simrs-vx/internal/use-case/main-use-case/medicine-mix-item"
_ "simrs-vx/internal/use-case/main-use-case/nurse"
up "simrs-vx/internal/use-case/main-use-case/prescription"
upi "simrs-vx/internal/use-case/main-use-case/prescription-item"
ur "simrs-vx/internal/use-case/main-use-case/rehab"
@@ -68,6 +69,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Encounter) {
var inputSrc *e.CreateDto
if inputT, ok := any(input).(*e.CreateDto); ok {
inputSrc = inputT
data.Status_Code = erc.DSCNew
} else {
inputTemp := any(input).(*e.UpdateDto)
inputSrc = &inputTemp.CreateDto
@@ -90,7 +92,6 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Encounter) {
data.Responsible_Doctor_Code = inputSrc.Responsible_Doctor_Code
data.RefSource_Name = inputSrc.RefSource_Name
data.Appointment_Id = inputSrc.Appointment_Id
data.Status_Code = erc.DSCProcess
data.RefType_Code = &inputSrc.RefTypeCode
data.NewStatus = inputSrc.NewStatus
}
@@ -117,17 +118,24 @@ func setDataDischarge(src e.DischargeDto, dst *e.Encounter) {
dst.FinishedAt = &now
}
func setDataUpdateStatus(src e.UpdateStatusDto, dst *e.Encounter) {
dst.Status_Code = src.StatusCode
}
func setDataCheckIn(src e.CheckinDto, dst *e.Encounter) {
if src.Adm_Employee_Id != nil {
dst.Adm_Employee_Id = src.Adm_Employee_Id
}
dst.Responsible_Nurse_Code = src.Responsible_Nurse_Code
dst.Responsible_Doctor_Code = src.Responsible_Doctor_Code
dst.StartedAt = src.StartedAt
dst.Status_Code = erc.DSCProcess
}
func setDischargeMethodCode(code ere.PolySwitchCode) *ere.DischargeMethodCode {
var dcm ere.DischargeMethodCode
switch code {
case ere.PSCConsulPoly:
dcm = ere.DMCConsulPoly
case ere.PSCConsulExecutive:
dcm = ere.DMCConsulExecutive
}
return &dcm
}
func checkSoapiByDocExists(encounter_id uint, event *pl.Event, tx *gorm.DB) error {
@@ -556,6 +564,7 @@ func getSoapiByResponsibleDoctor(enc e.Encounter, event *pl.Event) (data []es.So
Code: "no responsible-doctor found",
Detail: "Encounter does not have responsible-doctor",
}
return nil, pl.SetLogError(event, enc)
}
err = dg.I.
@@ -904,17 +913,17 @@ func updateRehabStatus(input er.UpdateDto, event *pl.Event, dbx ...*gorm.DB) err
return nil
}
func validateForeignKey(input e.CheckinDto) error {
func validateForeignKey(input e.CheckinDto, event *pl.Event) error {
// validate employee_Id
if input.Adm_Employee_Id != nil {
if _, err := uem.ReadDetail(eem.ReadDetailDto{Id: uint16(*input.Adm_Employee_Id)}); err != nil {
if input.Responsible_Nurse_Code != nil {
if _, err := un.ReadDetailData(en.ReadDetailDto{Code: input.Responsible_Nurse_Code}, event); err != nil {
return err
}
}
// validate doctor_Code
if input.Responsible_Doctor_Code != nil {
if _, err := ud.ReadDetail(ed.ReadDetailDto{Code: input.Responsible_Doctor_Code}); err != nil {
if _, err := ud.ReadDetailData(ed.ReadDetailDto{Code: input.Responsible_Doctor_Code}, event); err != nil {
return err
}
}
@@ -3,7 +3,6 @@ package encounter
import (
// std
"errors"
eir "simrs-vx/internal/domain/main-entities/internal-reference"
// external
dg "github.com/karincake/apem/db-gorm-pg"
gh "github.com/karincake/getuk"
@@ -205,9 +204,8 @@ func IsDone(encounter_id uint, event *pl.Event, dbx ...*gorm.DB) bool {
return data.IsDone()
}
func UpdateStatusData(input e.UpdateStatusDto, data *e.Encounter, event *pl.Event, dbx ...*gorm.DB) error {
pl.SetLogInfo(event, data, "started", "DBUpdate")
setDataUpdateStatus(input, data)
func UpdateStatusData(input e.UpdateStatusDto, event *pl.Event, dbx ...*gorm.DB) error {
pl.SetLogInfo(event, input, "started", "DBUpdateStatus")
var tx *gorm.DB
if len(dbx) > 0 {
@@ -216,22 +214,49 @@ func UpdateStatusData(input e.UpdateStatusDto, data *e.Encounter, event *pl.Even
tx = dg.I
}
if err := tx.Save(&data).Error; err != nil {
if err := tx.Model(&e.Encounter{}).
Where("\"Id\" = ?", input.Id).
Update("Status_Code", input.StatusCode).Error; err != nil {
event.Status = "failed"
event.ErrInfo = pl.ErrorInfo{
Code: "data-update-fail",
Detail: "Database update failed",
Code: "update-fail",
Detail: "Failed to update status code",
Raw: err,
}
return pl.SetLogError(event, input)
}
return nil
}
func UpdateDischargeMethod(input e.SwitchUnitDto, event *pl.Event, dbx ...*gorm.DB) error {
pl.SetLogInfo(event, input, "started", "DBUpdateDischargeMethod")
dischargeCode := setDischargeMethodCode(*input.PolySwitchCode)
var tx *gorm.DB
if len(dbx) > 0 {
tx = dbx[0]
} else {
tx = dg.I
}
if err := tx.Model(&e.Encounter{}).
Where("\"Id\" = ?", input.Id).
Update("Discharge_Method_Code", dischargeCode).Error; err != nil {
event.Status = "failed"
event.ErrInfo = pl.ErrorInfo{
Code: "update-fail",
Detail: "Failed to update discharge method code",
Raw: err,
}
return pl.SetLogError(event, input)
}
pl.SetLogInfo(event, nil, "complete")
return nil
}
func updateCheckInData(input e.CheckinDto, data *e.Encounter, event *pl.Event, dbx ...*gorm.DB) error {
pl.SetLogInfo(event, data, "started", "DBUpdate")
pl.SetLogInfo(event, data, "started", "DBUpdateCheckin")
setDataCheckIn(input, data)
var tx *gorm.DB
@@ -318,7 +343,7 @@ func verifyAllocatedVisitCount(i e.CreateDto, event *pl.Event) (e.Encounter, boo
return recentEncounterAdm, valid, nil
}
func updateEncounterApproveSwitchUnit(input eir.InternalReference, event *pl.Event, dbx ...*gorm.DB) (err error) {
func updateEncounterApproveSwitchUnit(input e.ApproveCancelUnitDto, event *pl.Event, dbx ...*gorm.DB) (err error) {
pl.SetLogInfo(event, nil, "started", "DBCreate")
var tx *gorm.DB
@@ -329,10 +354,10 @@ func updateEncounterApproveSwitchUnit(input eir.InternalReference, event *pl.Eve
}
if err := tx.Model(&e.Encounter{}).
Where("\"Id\" = ?", input.Encounter_Id).
Where("\"Id\" = ?", input.Id).
Updates(map[string]interface{}{
"Responsible_Doctor_Code": input.Doctor_Code,
"Unit_Code": input.Unit_Code,
"Responsible_Doctor_Code": input.Dst_Doctor_Code,
"Responsible_Nurse_Code": input.Nurse_Code,
}).Error; err != nil {
event.Status = "failed"
event.ErrInfo = pl.ErrorInfo{
@@ -27,7 +27,6 @@ func newMiddlewareRunner(event *pl.Event) *middlewareRunner {
}
}
// ExecuteCreateMiddleware executes create middleware
func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e.Encounter) error {
if !me.SyncOn {
return nil
@@ -47,7 +46,6 @@ func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e
return nil
}
// ExecuteCreateMiddleware executes create middleware
func (me *middlewareRunner) RunCreateLogMiddleware(middlewares []createLogMw, input *esync.SimxLogDto) error {
if !me.SyncOn {
return nil
@@ -199,6 +197,60 @@ func (me *middlewareRunner) RunUpdateStatusMiddleware(middlewares []updateStatus
return nil
}
func (me *middlewareRunner) RunRequestSwitchUnitMiddleware(middleware requestSwitchUnitMw, input *e.Encounter) error {
if !me.SyncOn {
return nil
}
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
}
func (me *middlewareRunner) RunApproveSwitchUnitMiddleware(middleware approveSwitchUnitMw, input *e.ApproveCancelUnitDto) error {
if !me.SyncOn {
return nil
}
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
}
func (me *middlewareRunner) RunCancelSwitchUnitMiddleware(middleware cancelSwitchUnitMw, input *e.ApproveCancelUnitDto) error {
if !me.SyncOn {
return nil
}
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
}
func (me *middlewareRunner) setMwType(mwType pu.MWType) {
me.MwType = mwType
}
@@ -21,5 +21,9 @@ func init() {
checkoutEncounter = checkoutMw{Name: "sync-checkout-encounter", Func: plugin.Checkout}
updatestatusEncounter = append(updatestatusEncounter,
updateStatusMw{Name: "sync-update-status-encounter", Func: plugin.Cancel})
updateStatusMw{Name: "sync-update-status-encounter", Func: plugin.UpdateStatus})
requestSwitchEncounter = requestSwitchUnitMw{Name: "sync-request-switch-unit-encounter", Func: plugin.RequestSwitchUnit}
approveSwitchEncounter = approveSwitchUnitMw{Name: "sync-approve-switch-unit-encounter", Func: plugin.ApproveSwitchUnit}
cancelSwitchEncounter = cancelSwitchUnitMw{Name: "sync-cancel-switch-unit-encounter", Func: plugin.CancelSwitchUnit}
}
@@ -59,6 +59,21 @@ type updateStatusMw struct {
Func func(input *e.Encounter) error
}
type requestSwitchUnitMw struct {
Name string
Func func(input *e.Encounter) error
}
type approveSwitchUnitMw struct {
Name string
Func func(input *e.ApproveCancelUnitDto) error
}
type cancelSwitchUnitMw struct {
Name string
Func func(input *e.ApproveCancelUnitDto) error
}
type UpdateMw = updateMw
type DeleteMw = deleteMw
@@ -76,3 +91,6 @@ var deletePostMw []readDetailMw
var checkinEncounterMw checkinMw
var checkoutEncounter checkoutMw
var updatestatusEncounter []updateStatusMw
var requestSwitchEncounter requestSwitchUnitMw
var approveSwitchEncounter approveSwitchUnitMw
var cancelSwitchEncounter cancelSwitchUnitMw
@@ -5,35 +5,41 @@ Any functions that are used internally by the use-case
package internal_reference
import (
e "simrs-vx/internal/domain/main-entities/encounter"
ir "simrs-vx/internal/domain/main-entities/internal-reference"
erc "simrs-vx/internal/domain/references/common"
)
func setData[T *ir.CreateDto | *ir.UpdateDto](input T, data *ir.InternalReference) {
var inputSrc *ir.CreateDto
if inputT, ok := any(input).(*ir.CreateDto); ok {
inputSrc = inputT
} else {
inputTemp := any(input).(*ir.UpdateDto)
inputSrc = &inputTemp.CreateDto
}
func setDataCreate(input *ir.CreateDto, data *ir.InternalReference) {
data.Encounter_Id = input.Encounter_Id
data.Unit_Code = input.Unit_Code
data.Encounter_Id = inputSrc.Encounter_Id
data.Unit_Code = inputSrc.Unit_Code
data.Doctor_Code = inputSrc.Doctor_Code
data.Status_Code = &inputSrc.Status_Code
data.Doctor_Code = input.Doctor_Code
data.SrcDoctor_Code = input.SrcDoctor_Code
data.Nurse_Code = input.Nurse_Code
data.SrcNurse_Code = input.SrcNurse_Code
data.Status_Code = &input.Status_Code
}
func setBulkData(input []ir.CreateDto, encounterId uint) []ir.InternalReference {
func setDataUpdate(input *ir.UpdateDto, data *ir.InternalReference) {
data.Doctor_Code = input.Doctor_Code
data.Nurse_Code = input.Nurse_Code
data.Status_Code = &input.Status_Code
}
func setBulkData(input *e.SwitchUnitDto) []ir.InternalReference {
var data []ir.InternalReference
for _, v := range input {
for _, v := range *input.InternalReferences {
statusCode := erc.DACNew
data = append(data, ir.InternalReference{
Encounter_Id: &encounterId,
Unit_Code: v.Unit_Code,
Doctor_Code: v.Doctor_Code,
Status_Code: &statusCode,
Encounter_Id: &input.Id,
Unit_Code: v.Unit_Code,
Doctor_Code: v.Doctor_Code,
Status_Code: &statusCode,
SrcDoctor_Code: input.Src_Doctor_Code,
SrcNurse_Code: input.Src_Nurse_Code,
})
}
@@ -2,6 +2,7 @@ package internal_reference
import (
"errors"
e "simrs-vx/internal/domain/main-entities/encounter"
eir "simrs-vx/internal/domain/main-entities/internal-reference"
plh "simrs-vx/pkg/lib-helper"
pl "simrs-vx/pkg/logger"
@@ -16,7 +17,7 @@ func CreateData(input eir.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*eir.Int
pl.SetLogInfo(event, nil, "started", "DBCreate")
data := eir.InternalReference{}
setData(&input, &data)
setDataCreate(&input, &data)
var tx *gorm.DB
if len(dbx) > 0 {
@@ -97,7 +98,7 @@ func ReadDetailData(input eir.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (
func UpdateData(input eir.UpdateDto, data *eir.InternalReference, event *pl.Event, dbx ...*gorm.DB) error {
pl.SetLogInfo(event, data, "started", "DBUpdate")
setData(&input, data)
setDataUpdate(&input, data)
var tx *gorm.DB
if len(dbx) > 0 {
@@ -143,10 +144,10 @@ func DeleteData(data *eir.InternalReference, event *pl.Event, dbx ...*gorm.DB) e
return nil
}
func CreateBulkData(input []eir.CreateDto, encounterId uint, event *pl.Event, dbx ...*gorm.DB) error {
func CreateBulkData(input *e.SwitchUnitDto, event *pl.Event, dbx ...*gorm.DB) error {
pl.SetLogInfo(event, nil, "started", "DBCreate")
data := setBulkData(input, encounterId)
data := setBulkData(input)
var tx *gorm.DB
if len(dbx) > 0 {
@@ -359,7 +359,7 @@ func Verify(input e.VerifyDto) (*d.Data, error) {
func validateForeignKey(input e.CreateDto) error {
// validate encounter
if input.Encounter_Id != nil {
if _, err := ue.ReadDetail(ee.ReadDetailDto{Id: uint16(*input.Encounter_Id)}); err != nil {
if _, err := ue.ReadDetail(ee.ReadDetailDto{Id: *input.Encounter_Id}); err != nil {
return err
}
}
+15 -1
View File
@@ -1,6 +1,7 @@
package unit
import (
"errors"
e "simrs-vx/internal/domain/main-entities/unit"
erc "simrs-vx/internal/domain/references/common"
esync "simrs-vx/internal/domain/sync-entities/log"
@@ -27,9 +28,22 @@ func Create(input e.CreateDto) (*d.Data, error) {
// Start log
pl.SetLogInfo(&event, input, "started", "create")
// validate unit_code
_, err := strconv.Atoi(input.Code)
if err != nil {
event.Status = "failed"
event.ErrInfo = pl.ErrorInfo{
Code: "invalid_code_format",
Detail: "unit_code must be a valid integer",
Raw: errors.New("invalid unit_code format"),
}
return nil, pl.SetLogError(&event, input)
}
mwRunner := newMiddlewareRunner(&event)
err := dg.I.Transaction(func(tx *gorm.DB) error {
err = dg.I.Transaction(func(tx *gorm.DB) error {
if resData, err := CreateData(input, &event, tx); err != nil {
return err
} else {
@@ -43,9 +43,27 @@ func Checkout(input *e.Encounter) error {
return helper.DoJsonRequest(input, "PATCH", endpoint)
}
func Cancel(input *e.Encounter) error {
func UpdateStatus(input *e.Encounter) error {
prefixEndpoint := getPrefixEndpoint()
endpoint := fmt.Sprintf("%s/%v/cancel", prefixEndpoint, input.Id)
endpoint := fmt.Sprintf("%s/%v/update-status", prefixEndpoint, input.Id)
return helper.DoJsonRequest(input, "PATCH", endpoint)
}
func RequestSwitchUnit(input *e.Encounter) error {
prefixEndpoint := getPrefixEndpoint()
endpoint := fmt.Sprintf("%s/%v/req-switch-unit", prefixEndpoint, input.Id)
return helper.DoJsonRequest(input, "PATCH", endpoint)
}
func ApproveSwitchUnit(input *e.ApproveCancelUnitDto) error {
prefixEndpoint := getPrefixEndpoint()
endpoint := fmt.Sprintf("%s/%v/approve-switch-unit", prefixEndpoint, input.Id)
return helper.DoJsonRequest(input, "PATCH", endpoint)
}
func CancelSwitchUnit(input *e.ApproveCancelUnitDto) error {
prefixEndpoint := getPrefixEndpoint()
endpoint := fmt.Sprintf("%s/%v/cancel-switch-unit", prefixEndpoint, input.Id)
return helper.DoJsonRequest(input, "PATCH", endpoint)
}
@@ -10,10 +10,11 @@ import (
e "simrs-vx/internal/domain/main-entities/encounter"
etp "simrs-vx/internal/domain/simgos-entities/t-pendaftaran"
esync "simrs-vx/internal/domain/sync-entities/encounter"
synce "simrs-vx/internal/domain/sync-entities/encounter"
syncir "simrs-vx/internal/domain/sync-entities/internal-reference"
elog "simrs-vx/internal/domain/sync-entities/log"
up "simrs-vx/internal/use-case/simgos-sync-use-case/new/patient"
utph "simrs-vx/internal/use-case/simgos-sync-use-case/new/internal-reference"
)
const source = "encounter"
@@ -21,7 +22,7 @@ const source = "encounter"
func Create(input e.Encounter) (*d.Data, error) {
var (
sgData *etp.TPendaftaran
syncLink *esync.EncounterLink
syncLink *synce.EncounterLink
err error
)
@@ -46,14 +47,8 @@ func Create(input e.Encounter) (*d.Data, error) {
return err
}
// STEP: 3 Get MPasien
dataPatient, err := up.ReadDetailSimgosByNomrData(sgData.Nomr, &event, tx.Simgos)
if err != nil {
return err
}
// STEP 4: Update MPasien
err = updatePatient(*dataPatient, &event, tx.Simgos)
// STEP 3: Update MPasien
err = updatePatientCaraBayar(*sgData, &event, tx.Simgos)
if err != nil {
return err
}
@@ -123,13 +118,13 @@ func Update(input e.Encounter) (*d.Data, error) {
pl.SetLogInfo(&event, input, "started", "update")
// STEP 1: Get Link
syncLink, err := ReadDetailLinkData(uint16(input.Id), &event)
syncLink, err := ReadDetailLinkData(input.Id, &event)
if err != nil {
return nil, err
}
// STEP 2: Get Simgos
simgos, err := ReadTPendaftaranDetailData(uint16(syncLink.Simgos_Id), &event)
simgos, err := ReadTPendaftaranDetailData(syncLink.Simgos_Id, &event)
if err != nil {
return nil, err
}
@@ -137,7 +132,7 @@ func Update(input e.Encounter) (*d.Data, error) {
tx := db.NewTx()
err = tx.Simgos.Transaction(func(tx *gorm.DB) error {
// Step 2: Update Simgos
if err = UpdateTPendaftaranData(input, *simgos, "update", &event, tx); err != nil {
if err = UpdateTPendaftaranData(input, simgos, "update", &event, tx); err != nil {
return err
}
@@ -173,7 +168,7 @@ func Delete(input e.DeleteDto) (*d.Data, error) {
}
// STEP 2: Get Simgos
sgData, err := ReadTPendaftaranDetailData(uint16(syncLink.Simgos_Id), &event)
sgData, err := ReadTPendaftaranDetailData(syncLink.Simgos_Id, &event)
if err != nil {
return nil, err
}
@@ -226,13 +221,13 @@ func CheckIn(input e.Encounter) (*d.Data, error) {
pl.SetLogInfo(&event, input, "started", "check-in")
// STEP 1: Get Link
syncLink, err := ReadDetailLinkData(uint16(input.Id), &event)
syncLink, err := ReadDetailLinkData(input.Id, &event)
if err != nil {
return nil, err
}
// STEP 2: Get Simgos
simgos, err := ReadTPendaftaranDetailData(uint16(syncLink.Simgos_Id), &event)
simgos, err := ReadTPendaftaranDetailData(syncLink.Simgos_Id, &event)
if err != nil {
return nil, err
}
@@ -240,7 +235,7 @@ func CheckIn(input e.Encounter) (*d.Data, error) {
tx := db.NewTx()
err = tx.Simgos.Transaction(func(tx *gorm.DB) error {
// Step 2: Update Simgos
if err = UpdateTPendaftaranData(input, *simgos, "check-in", &event, tx); err != nil {
if err = UpdateTPendaftaranData(input, simgos, "check-in", &event, tx); err != nil {
return err
}
@@ -268,13 +263,13 @@ func CheckOut(input e.Encounter) (*d.Data, error) {
pl.SetLogInfo(&event, input, "started", "check-out")
// STEP 1: Get Link
syncLink, err := ReadDetailLinkData(uint16(input.Id), &event)
syncLink, err := ReadDetailLinkData(input.Id, &event)
if err != nil {
return nil, err
}
// STEP 2: Get Simgos
simgos, err := ReadTPendaftaranDetailData(uint16(syncLink.Simgos_Id), &event)
simgos, err := ReadTPendaftaranDetailData(syncLink.Simgos_Id, &event)
if err != nil {
return nil, err
}
@@ -282,10 +277,12 @@ func CheckOut(input e.Encounter) (*d.Data, error) {
tx := db.NewTx()
err = tx.Simgos.Transaction(func(tx *gorm.DB) error {
// Step 2: Update Simgos
if err = UpdateTPendaftaranData(input, *simgos, "check-out", &event, tx); err != nil {
if err = UpdateTPendaftaranData(input, simgos, "check-out", &event, tx); err != nil {
return err
}
// TODO: Update TPemeriksaanHistory end_konsul if internal reference exist
return nil
})
@@ -300,7 +297,7 @@ func CheckOut(input e.Encounter) (*d.Data, error) {
}, nil
}
func Cancel(input e.Encounter) (*d.Data, error) {
func UpdateStatus(input e.Encounter) (*d.Data, error) {
event := pl.Event{
Feature: "Cancel",
Source: source,
@@ -310,13 +307,13 @@ func Cancel(input e.Encounter) (*d.Data, error) {
pl.SetLogInfo(&event, input, "started", "cancel")
// STEP 1: Get Link
syncLink, err := ReadDetailLinkData(uint16(input.Id), &event)
syncLink, err := ReadDetailLinkData(input.Id, &event)
if err != nil {
return nil, err
}
// STEP 2: Get Simgos
simgos, err := ReadTPendaftaranDetailData(uint16(syncLink.Simgos_Id), &event)
simgos, err := ReadTPendaftaranDetailData(syncLink.Simgos_Id, &event)
if err != nil {
return nil, err
}
@@ -324,7 +321,7 @@ func Cancel(input e.Encounter) (*d.Data, error) {
tx := db.NewTx()
err = tx.Simgos.Transaction(func(tx *gorm.DB) error {
// Step 2: Update Simgos
if err = UpdateTPendaftaranData(input, *simgos, "update-status", &event, tx); err != nil {
if err = UpdateTPendaftaranData(input, simgos, "update-status", &event, tx); err != nil {
return err
}
@@ -343,6 +340,10 @@ func Cancel(input e.Encounter) (*d.Data, error) {
}
func RequestSwitchUnit(input e.Encounter) (*d.Data, error) {
var (
syncLinkInternal *[]syncir.InternalReferenceLink
)
event := pl.Event{
Feature: "RequestSwitchUnit",
Source: source,
@@ -352,26 +353,80 @@ func RequestSwitchUnit(input e.Encounter) (*d.Data, error) {
pl.SetLogInfo(&event, input, "started", "request-switch-unit")
// STEP 1: Get Link
syncLink, err := ReadDetailLinkData(uint16(input.Id), &event)
syncLink, err := ReadDetailLinkData(input.Id, &event)
if err != nil {
return nil, err
}
// STEP 2: Get Simgos
tpendaftaran, err := ReadTPendaftaranDetailData(uint16(syncLink.Simgos_Id), &event)
tpendaftaran, err := ReadTPendaftaranDetailData(syncLink.Simgos_Id, &event)
if err != nil {
return nil, err
}
err = db.WithDualTx(func(tx *db.Dualtx) error {
// Step 3: Update TPendaftaran
if err = UpdateTPendaftaranData(input, tpendaftaran, "update-status", &event, tx.Simgos); err != nil {
return err
}
// Step 4: Bulk Insert TPemeriksaanHist
tPemeriksanHistory, err := utph.CreateSimgosData(input, tpendaftaran, &event, tx.Simgos)
if err != nil {
return err
}
// Step 5: Bulk Insert To Link
if syncLinkInternal, err = utph.CreateBulkLinkData(*input.InternalReferences, *tPemeriksanHistory, &event, tx.Sync); err != nil {
return err
}
return nil
})
if err != nil {
if syncLinkInternal != nil {
go func() { _ = utph.DeleteLinkData(syncLinkInternal, &event) }()
}
return nil, err
}
pl.SetLogInfo(&event, nil, "complete")
return &d.Data{
Meta: d.IS{
"source": source,
"structure": "single-data",
"status": "updated",
},
}, nil
}
func ApproveSwitchUnit(input e.ApproveCancelUnitDto) (*d.Data, error) {
event := pl.Event{
Feature: "ApproveSwitchUnit",
Source: source,
}
// Start log
pl.SetLogInfo(&event, input, "started", "approve-switch-unit")
// STEP 1: Get InternalReference Link
syncLink, err := utph.ReadDetailLinkData(input.InternalReferences_Id, &event)
if err != nil {
return nil, err
}
// STEP 2: Get TPemeriksaanHist
tPemeriksaanHist, err := utph.ReadDetailSimgosData(syncLink.Simgos_Id, &event)
if err != nil {
return nil, err
}
tx := db.NewTx()
err = tx.Simgos.Transaction(func(tx *gorm.DB) error {
// Step 2: Update TPendaftaran
if err = UpdateTPendaftaranData(input, *tpendaftaran, "update-status", &event, tx); err != nil {
return err
}
// Step 3: Insert TPemeriksaanHist
if _, err := CreateBulkTPemeriksaanHistData(input, *tpendaftaran, &event, tx); err != nil {
// Step 3: Update TPemeriksaanHist
if err := utph.UpdateSimgosData(input, tPemeriksaanHist, "approve", &event, tx); err != nil {
return err
}
@@ -389,36 +444,31 @@ func RequestSwitchUnit(input e.Encounter) (*d.Data, error) {
}, nil
}
func ApproveSwitchUnit(input e.Encounter) (*d.Data, error) {
func CancelSwitchUnit(input e.ApproveCancelUnitDto) (*d.Data, error) {
event := pl.Event{
Feature: "RequestSwitchUnit",
Feature: "CancelSwitchUnit",
Source: source,
}
// Start log
pl.SetLogInfo(&event, input, "started", "request-switch-unit")
pl.SetLogInfo(&event, input, "started", "cancel-switch-unit")
// STEP 1: Get Link
syncLink, err := ReadDetailLinkData(uint16(input.Id), &event)
// STEP 1: Get InternalReference Link
syncLink, err := utph.ReadDetailLinkData(input.InternalReferences_Id, &event)
if err != nil {
return nil, err
}
// STEP 2: Get Simgos
tpendaftaran, err := ReadTPendaftaranDetailData(uint16(syncLink.Simgos_Id), &event)
// STEP 2: Get TPemeriksaanHist
tPemeriksaanHist, err := utph.ReadDetailSimgosData(syncLink.Simgos_Id, &event)
if err != nil {
return nil, err
}
tx := db.NewTx()
err = tx.Simgos.Transaction(func(tx *gorm.DB) error {
// Step 2: Update TPendaftaran
if err = UpdateTPendaftaranData(input, *tpendaftaran, "update-status", &event, tx); err != nil {
return err
}
// Step 3: Insert TPemeriksaanHist
if _, err := CreateBulkTPemeriksaanHistData(input, *tpendaftaran, &event, tx); err != nil {
// Step 3: Update TPemeriksaanHist
if err := utph.UpdateSimgosData(input, tPemeriksaanHist, "cancel", &event, tx); err != nil {
return err
}
@@ -6,7 +6,6 @@ package encounter
import (
"encoding/json"
epr "simrs-vx/internal/domain/main-entities/person-relative"
erc "simrs-vx/internal/domain/references/common"
ere "simrs-vx/internal/domain/references/encounter"
erp "simrs-vx/internal/domain/references/person"
@@ -14,6 +13,9 @@ import (
"strconv"
e "simrs-vx/internal/domain/main-entities/encounter"
epa "simrs-vx/internal/domain/main-entities/person-address"
epc "simrs-vx/internal/domain/main-entities/person-contact"
epr "simrs-vx/internal/domain/main-entities/person-relative"
ep "simrs-vx/internal/domain/simgos-entities/m-pasien"
etph "simrs-vx/internal/domain/simgos-entities/t-pemeriksaan-hist"
etp "simrs-vx/internal/domain/simgos-entities/t-pendaftaran"
@@ -47,20 +49,29 @@ func setDataCreateTPendaftaran(input *e.Encounter) (data etp.TPendaftaran, err e
}
data.NoKunjung = uint(noKunjung)
setDataTPendaftaran(input, data)
if p := input.Patient.Person; p != nil {
mapRelative(p.Relatives, &data)
if data.PenanggungjawabNama == "" {
data.PenanggungjawabHubungan = "DIRI SENDIRI"
data.PenanggungjawabNama = p.Name
mapContact(p.Contacts, &data)
mapAddress(p.Addresses, &data)
}
if bpjs := p.VclaimMember; bpjs != nil {
data.Nokartu = *bpjs.CardNumber
}
}
setDataTPendaftaran(input, &data)
return
}
func setDataTPendaftaran(input *e.Encounter, data etp.TPendaftaran) {
func setDataTPendaftaran(input *e.Encounter, data *etp.TPendaftaran) {
data.Tglreg = input.RegisteredAt
// set kddokter
if d := input.Appointment_Doctor_Code; d != nil {
kddokter, _ := strconv.Atoi(*input.Appointment_Doctor_Code)
data.Kddokter = uint(kddokter)
}
// set kdpoly
if p := input.Unit_Code; p != nil {
kdpoly, _ := strconv.Atoi(*input.Unit_Code)
@@ -82,22 +93,18 @@ func setDataTPendaftaran(input *e.Encounter, data etp.TPendaftaran) {
}
}
if ref := input.VclaimReference; ref != nil {
data.Ketrujuk = *ref.SrcCode
data.Norujukan = *ref.Number
data.Tglrujukan = ref.Date
// set data if payment_method bpjs
if input.RefSource_Name != nil {
data.Ketrujuk = *input.RefSource_Name
data.Strujukan = 1
} else {
data.Ketrujuk = "TR"
data.Strujukan = 0
}
if p := input.Patient.Person; p != nil {
mapRelative(p.Relatives, data)
if bpjs := p.VclaimMember; bpjs != nil {
data.Nokartu = *bpjs.CardNumber
}
if ref := input.VclaimReference; ref != nil {
data.Norujukan = *ref.Number
data.Tglrujukan = ref.Date
}
data.Jamreg = input.RegisteredAt
@@ -107,16 +114,35 @@ func setDataTPendaftaran(input *e.Encounter, data etp.TPendaftaran) {
return
}
func setDataCheckIn(input e.Encounter, data etp.TPendaftaran) {
func setDataUpdateStatus(input e.Encounter, data *etp.TPendaftaran) {
switch input.Status_Code {
case erc.DSCProcess:
data.Masukpoly = &now
}
if input.Status_Code == erc.DSCCancel {
data.Status = 11
return
}
if input.Discharge_Method_Code != nil {
setStatus(input.Discharge_Method_Code, data)
}
}
func setDataCheckIn(input e.Encounter, data *etp.TPendaftaran) {
// set kddokter
kddokter, _ := strconv.Atoi(*input.Responsible_Doctor_Code)
data.Kddokter = uint(kddokter)
// set petugas_klinik
if data.PetugasKlinik != "" {
if a := input.Adm_Employee; a != nil {
if u := a.User; u != nil {
data.PetugasKlinik = u.Name
// only update once
if data.PetugasKlinik == "" {
if n := input.Responsible_Nurse; n != nil {
if emp := n.Employee; emp != nil {
if u := emp.User; u != nil {
data.PetugasKlinik = u.Name
}
}
}
}
@@ -125,21 +151,60 @@ func setDataCheckIn(input e.Encounter, data etp.TPendaftaran) {
return
}
func setDataRequestSwitchUnit(input e.Encounter, data etp.TPendaftaran) (hist []etph.TPemeriksaanHist) {
func setDataCheckOut(input e.Encounter, data *etp.TPendaftaran) {
data.Keluarpoly = input.FinishedAt
// set status
setStatus(input.Discharge_Method_Code, data)
if data.Status == 8 || data.Status == 3 {
if dc := input.DeathCause; dc != nil {
var dcSrc []DeathCauseSrc
_ = json.Unmarshal([]byte(*dc.Value), &dcSrc)
for i, v := range dcSrc {
switch i {
case 0:
data.SebabMati1 = &v.Name
data.IcdMati1 = &v.Code
case 1:
data.SebabMati2 = &v.Name
data.IcdMati2 = &v.Code
case 2:
data.SebabMati3 = &v.Name
data.IcdMati3 = &v.Code
default:
break
}
}
}
death := uint(1)
data.StMeninggal = &death
data.DtMeninggal = data.Keluarpoly
}
setPelayanan := uint(1)
data.StPelayanan = &setPelayanan
return
}
func setDataRequestSwitchUnit(input e.Encounter, data *etp.TPendaftaran) (hist []etph.TPemeriksaanHist) {
if enc := input.InternalReferences; enc != nil {
for i, ref := range *enc {
hist = append(hist, etph.TPemeriksaanHist{
Idxdaftar: &data.Idxdaftar,
Kdpoly: stringtouint(*ref.Unit_Code),
DokterPengonsul: stringtouint(*input.Responsible_Doctor_Code),
DokterPengonsul: stringtouint(*ref.SrcDoctor_Code),
DokterPenerima: stringtouint(*ref.Doctor_Code),
StartKonsul: &now,
})
// set user konsul
if emp := input.Adm_Employee; emp != nil {
if u := emp.User; u != nil {
hist[i].UserKonsul = &u.Name
if n := input.Responsible_Nurse; n != nil {
if emp := n.Employee; emp != nil {
if u := emp.User; u != nil {
hist[i].UserKonsul = &u.Name
}
}
}
@@ -151,31 +216,7 @@ func setDataRequestSwitchUnit(input e.Encounter, data etp.TPendaftaran) (hist []
return
}
func setDataCheckOut(input e.Encounter, data etp.TPendaftaran) {
data.Keluarpoly = input.Discharge_Date
// set status
setStatus(input.Discharge_Method_Code, data)
if data.Status == 8 || data.Status == 3 {
if dc := input.DeathCause; dc != nil {
data.SebabMati1 = dc.Value
}
}
setPelayanan := uint(1)
data.StPelayanan = &setPelayanan
return
}
func setDataUpdateStatus(input e.Encounter, data etp.TPendaftaran) {
if input.Status_Code == erc.DSCCancel {
data.Status = 11
}
}
func setKdrujuk(input *ere.RefTypeCode, data etp.TPendaftaran) {
func setKdrujuk(input *ere.RefTypeCode, data *etp.TPendaftaran) {
switch *input {
case ere.RTCGov:
data.Kdrujuk = 1
@@ -188,7 +229,7 @@ func setKdrujuk(input *ere.RefTypeCode, data etp.TPendaftaran) {
}
}
func setKdcarabayar(input ere.AllPaymentMethodCode, data etp.TPendaftaran) {
func setKdcarabayar(input ere.AllPaymentMethodCode, data *etp.TPendaftaran) {
switch input {
case ere.APMCPks:
data.Kdcarabayar = 12
@@ -203,7 +244,7 @@ func setKdcarabayar(input ere.AllPaymentMethodCode, data etp.TPendaftaran) {
}
}
func setStatus(code *ere.DischargeMethodCode, data etp.TPendaftaran) {
func setStatus(code *ere.DischargeMethodCode, data *etp.TPendaftaran) {
switch *code {
case ere.DMCHome:
data.Status = 1
@@ -221,24 +262,12 @@ func setStatus(code *ere.DischargeMethodCode, data etp.TPendaftaran) {
data.Status = 7
case ere.DMCConsulPoly:
data.Status = 5
data.PoliNameHfis = nil
data.SpesialisIdHfis = nil
data.DokterNameHfis = nil
data.DokterIdHfis = nil
case ere.DMCExtRef:
data.Status = 6
case ere.DMCConsulChDay:
data.Status = 12
data.PoliNameHfis = nil
data.SpesialisIdHfis = nil
data.DokterNameHfis = nil
data.DokterIdHfis = nil
case ere.DMCEmergency:
data.Status = 10
data.PoliNameHfis = nil
data.SpesialisIdHfis = nil
data.DokterNameHfis = nil
data.DokterIdHfis = nil
case ere.DMCEmergencyCovid:
data.Status = 13
case ere.DMCConsulExecutive:
@@ -250,7 +279,7 @@ func setStatus(code *ere.DischargeMethodCode, data etp.TPendaftaran) {
}
}
func mapRelative(relative *[]epr.PersonRelative, data etp.TPendaftaran) {
func mapRelative(relative *[]epr.PersonRelative, data *etp.TPendaftaran) {
if relative == nil || len(*relative) == 0 {
return
}
@@ -322,10 +351,11 @@ func generateNoKunjung() (int, error) {
// Lock rows for this prefix → prevents race condition
if err := dg.IS["simrs"].
Table("t_pendaftaran").
Select("COALESCE(MAX(no_kunjung),0)").
Select("no_kunjung").
Where("tglreg = CURRENT_DATE").
Order("no_kunjung DESC").
Clauses(clause.Locking{Strength: "UPDATE"}).
Limit(1).
Scan(&lastNumber).Error; err != nil {
return 0, err
}
@@ -339,7 +369,7 @@ func stringtouint(v string) *uint {
return &point
}
func updatePatient(patient ep.MPasien, event *pl.Event, dbx ...*gorm.DB) error {
func updatePatientCaraBayar(input etp.TPendaftaran, event *pl.Event, dbx ...*gorm.DB) error {
pl.SetLogInfo(event, nil, "started", "DBUpdate")
var tx *gorm.DB
@@ -350,9 +380,9 @@ func updatePatient(patient ep.MPasien, event *pl.Event, dbx ...*gorm.DB) error {
}
if err := tx.Model(&ep.MPasien{}).
Where("\"nomr\" = ?", patient.Nomr).
Where("\"nomr\" = ?", input.Nomr).
Updates(map[string]interface{}{
"kdcarabayar": patient.Kdcarabayar,
"kdcarabayar": input.Kdcarabayar,
}).Error; err != nil {
event.Status = "failed"
event.ErrInfo = pl.ErrorInfo{
@@ -360,9 +390,30 @@ func updatePatient(patient ep.MPasien, event *pl.Event, dbx ...*gorm.DB) error {
Detail: "Failed to update patient",
Raw: err,
}
return pl.SetLogError(event, patient)
return pl.SetLogError(event, input)
}
pl.SetLogInfo(event, patient, "complete")
pl.SetLogInfo(event, input, "complete")
return nil
}
func mapContact(contact *[]epc.PersonContact, data *etp.TPendaftaran) {
if contact == nil || len(*contact) == 0 {
return
}
for _, c := range *contact {
if c.Type_Code == erp.CTPhone || c.Type_Code == erp.CTMPhone {
data.PenanggungjawabPhone = c.Value
break
}
}
}
func mapAddress(addresses *[]epa.PersonAddress, data *etp.TPendaftaran) {
if addresses == nil || len(*addresses) == 0 {
return
}
a := (*addresses)[0]
data.PenanggungjawabAlamat = a.Address
}
@@ -41,7 +41,7 @@ func CreateTPendaftaranData(input e.Encounter, event *pl.Event, dbx ...*gorm.DB)
return &data, nil
}
func ReadTPendaftaranDetailData(simgosId uint16, event *pl.Event) (*etp.TPendaftaran, error) {
func ReadTPendaftaranDetailData(simgosId uint, event *pl.Event) (*etp.TPendaftaran, error) {
pl.SetLogInfo(event, simgosId, "started", "DBReadDetail")
data := etp.TPendaftaran{}
@@ -59,7 +59,7 @@ func ReadTPendaftaranDetailData(simgosId uint16, event *pl.Event) (*etp.TPendaft
return &data, nil
}
func UpdateTPendaftaranData(input e.Encounter, data etp.TPendaftaran, method string, event *pl.Event, dbx ...*gorm.DB) error {
func UpdateTPendaftaranData(input e.Encounter, data *etp.TPendaftaran, method string, event *pl.Event, dbx ...*gorm.DB) error {
pl.SetLogInfo(event, input, "started", "DBUpdate")
switch method {
@@ -138,7 +138,26 @@ func CreateLinkData(simxId, simgosId uint, event *pl.Event, dbx ...*gorm.DB) (*e
return &data, nil
}
func ReadDetailLinkData(simxId uint16, event *pl.Event) (*esync.EncounterLink, error) {
func CreateBulkLinkData(simxId, simgosId uint, event *pl.Event, dbx ...*gorm.DB) (*esync.EncounterLink, 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 ReadDetailLinkData(simxId uint, event *pl.Event) (*esync.EncounterLink, error) {
pl.SetLogInfo(event, simxId, "started", "DBReadDetail")
data := esync.EncounterLink{}
@@ -199,7 +218,7 @@ func CreateLogData(input esynclog.SimxLogDto, event *pl.Event, dbx ...*gorm.DB)
return nil
}
func CreateBulkTPemeriksaanHistData(input e.Encounter, data etp.TPendaftaran, event *pl.Event, dbx ...*gorm.DB) (hist []etph.TPemeriksaanHist, err error) {
func CreateBulkTPemeriksaanHistData(input e.Encounter, data *etp.TPendaftaran, event *pl.Event, dbx ...*gorm.DB) (hist []etph.TPemeriksaanHist, err error) {
pl.SetLogInfo(event, nil, "started", "DBCreate")
hist = setDataRequestSwitchUnit(input, data)
@@ -218,3 +237,27 @@ func CreateBulkTPemeriksaanHistData(input e.Encounter, data etp.TPendaftaran, ev
pl.SetLogInfo(event, nil, "complete")
return hist, nil
}
func UpdateTPemeriksaanHistData(input e.ApproveCancelUnitDto, data *etph.TPemeriksaanHist, event *pl.Event, dbx ...*gorm.DB) error {
pl.SetLogInfo(event, input, "started", "DBUpdateTPemeriksaanHist")
var tx *gorm.DB
if len(dbx) > 0 {
tx = dbx[0]
} else {
tx = dg.IS["simrs"]
}
if err := tx.Save(&data).Error; err != nil {
event.Status = "failed"
event.ErrInfo = pl.ErrorInfo{
Code: "data-update-fail",
Detail: "Database update failed",
Raw: err,
}
return pl.SetLogError(event, input)
}
pl.SetLogInfo(event, nil, "complete")
return nil
}
@@ -42,3 +42,10 @@ var updatePreMw []readDetailMw
var updatePostMw []readDetailMw
var deletePreMw []readDetailMw
var deletePostMw []readDetailMw
type DeathCauseSrc struct {
Id uint `json:"id"`
Code string `json:"code"`
Name string `json:"name"`
IndName string `json:"indName"`
}
@@ -0,0 +1,103 @@
/*
DESCRIPTION:
Any functions that are used internally by the use-case
*/
package internal_reference
import (
"encoding/json"
eir "simrs-vx/internal/domain/main-entities/internal-reference"
erc "simrs-vx/internal/domain/references/common"
"strconv"
e "simrs-vx/internal/domain/main-entities/encounter"
etph "simrs-vx/internal/domain/simgos-entities/t-pemeriksaan-hist"
etp "simrs-vx/internal/domain/simgos-entities/t-pendaftaran"
esync "simrs-vx/internal/domain/sync-entities/internal-reference"
esyncLog "simrs-vx/internal/domain/sync-entities/log"
)
func setCreateDataSimgos(input e.Encounter, data *etp.TPendaftaran) (hist []etph.TPemeriksaanHist) {
if enc := input.InternalReferences; enc != nil {
for i, ref := range *enc {
hist = append(hist, etph.TPemeriksaanHist{
Idxdaftar: &data.Idxdaftar,
Kdpoly: stringtouint(*ref.Unit_Code),
DokterPengonsul: stringtouint(*ref.SrcDoctor_Code),
DokterPenerima: stringtouint(*ref.Doctor_Code),
})
// set user konsul
if n := input.Responsible_Nurse; n != nil {
if emp := n.Employee; emp != nil {
if u := emp.User; u != nil {
hist[i].UserKonsul = &u.Name
}
}
}
// setaktif
aktif := uint16(1)
hist[i].StAktif = &aktif
}
}
return
}
func setUpdateApproveDataSimgos(input e.ApproveCancelUnitDto, data *etph.TPemeriksaanHist) {
data.DokterPenerima = stringtouint(*input.Dst_Doctor_Code)
data.StartKonsul = &now
data.UserPenerima = &input.User_Name
data.MasukPoly = data.StartKonsul
return
}
func setUpdateCancelDataSimgos(input e.ApproveCancelUnitDto, data *etph.TPemeriksaanHist) {
data.UserBatal = &input.User_Name
data.TglBatal = &now
aktif := uint16(0)
data.StAktif = &aktif
return
}
func setDataSimxLog(input *esyncLog.SimxLogDto) (data esync.InternalReferenceSimxLog) {
// 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(ir []eir.InternalReference, tph []etph.TPemeriksaanHist) (data []esync.InternalReferenceLink) {
for i := range len(ir) {
data = append(data, esync.InternalReferenceLink{
Simx_Id: ir[i].Id,
Simgos_Id: tph[i].IdPemeriksaanHist,
})
}
return
}
func stringtouint(v string) *uint {
u, _ := strconv.Atoi(v)
point := uint(u)
return &point
}
@@ -0,0 +1,173 @@
package internal_reference
import (
plh "simrs-vx/pkg/lib-helper"
pl "simrs-vx/pkg/logger"
pu "simrs-vx/pkg/use-case-helper"
"time"
dg "github.com/karincake/apem/db-gorm-pg"
"gorm.io/gorm"
e "simrs-vx/internal/domain/main-entities/encounter"
eir "simrs-vx/internal/domain/main-entities/internal-reference"
etph "simrs-vx/internal/domain/simgos-entities/t-pemeriksaan-hist"
etp "simrs-vx/internal/domain/simgos-entities/t-pendaftaran"
esync "simrs-vx/internal/domain/sync-entities/internal-reference"
esynclog "simrs-vx/internal/domain/sync-entities/log"
)
const source = "internal-reference"
var now = time.Now()
func CreateSimgosData(input e.Encounter, dataDaftar *etp.TPendaftaran, event *pl.Event, dbx ...*gorm.DB) (*[]etph.TPemeriksaanHist, error) {
pl.SetLogInfo(event, nil, "started", "DBCreate")
data := setCreateDataSimgos(input, dataDaftar)
var tx *gorm.DB
if len(dbx) > 0 {
tx = dbx[0]
} else {
tx = dg.IS["simrs"]
}
if err := tx.Create(&data).Error; err != nil {
return nil, plh.HandleCreateError(input, event, err)
}
pl.SetLogInfo(event, nil, "complete")
return &data, nil
}
func ReadDetailSimgosData(simgosId uint, event *pl.Event) (*etph.TPemeriksaanHist, error) {
pl.SetLogInfo(event, simgosId, "started", "DBReadDetail")
data := etph.TPemeriksaanHist{}
var tx = dg.IS["simrs"]
if err := tx.
Where("\"id_pemeriksaanhist\" = ?", simgosId).
First(&data).Error; err != nil {
if processedErr := pu.HandleReadError(err, event, source, simgosId, data); processedErr != nil {
return nil, processedErr
}
}
pl.SetLogInfo(event, nil, "complete")
return &data, nil
}
func UpdateSimgosData(input e.ApproveCancelUnitDto, data *etph.TPemeriksaanHist, method string, event *pl.Event, dbx ...*gorm.DB) error {
pl.SetLogInfo(event, input, "started", "DBUpdate")
switch method {
case "approve":
setUpdateApproveDataSimgos(input, data)
case "cancel":
setUpdateCancelDataSimgos(input, data)
}
var tx *gorm.DB
if len(dbx) > 0 {
tx = dbx[0]
} else {
tx = dg.IS["simrs"]
}
if err := tx.Save(&data).Error; err != nil {
event.Status = "failed"
event.ErrInfo = pl.ErrorInfo{
Code: "data-update-fail",
Detail: "Database update failed",
Raw: err,
}
return pl.SetLogError(event, input)
}
pl.SetLogInfo(event, nil, "complete")
return nil
}
func CreateBulkLinkData(ir []eir.InternalReference, tph []etph.TPemeriksaanHist, event *pl.Event, dbx ...*gorm.DB) (*[]esync.InternalReferenceLink, error) {
pl.SetLogInfo(event, nil, "started", "DBCreate")
data := setDataSimxLink(ir, tph)
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 ReadDetailLinkData(simxId uint, event *pl.Event) (*esync.InternalReferenceLink, error) {
pl.SetLogInfo(event, simxId, "started", "DBReadDetail")
data := esync.InternalReferenceLink{}
var tx = dg.I
if err := tx.
Where("\"Simx_Id\" = ?", simxId).
First(&data).Error; err != nil {
if processedErr := pu.HandleReadError(err, event, source, simxId, data); processedErr != nil {
return nil, processedErr
}
}
pl.SetLogInfo(event, nil, "complete")
return &data, nil
}
func DeleteLinkData(data *[]esync.InternalReferenceLink, event *pl.Event, dbx ...*gorm.DB) error {
pl.SetLogInfo(event, data, "started", "DBDelete")
var tx *gorm.DB
if len(dbx) > 0 {
tx = dbx[0]
} else {
tx = dg.I
}
if err := tx.Delete(*data).Error; err != nil {
event.Status = "failed"
event.ErrInfo = pl.ErrorInfo{
Code: "data-delete-fail",
Detail: "Database delete failed",
Raw: err,
}
return pl.SetLogError(event, data)
}
pl.SetLogInfo(event, nil, "complete")
return 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
}
@@ -0,0 +1,103 @@
package internal_reference
import (
e "simrs-vx/internal/domain/main-entities/internal-reference"
pl "simrs-vx/pkg/logger"
pu "simrs-vx/pkg/use-case-helper"
"gorm.io/gorm"
)
type middlewareRunner struct {
Event *pl.Event
Tx *gorm.DB
MwType pu.MWType
}
// NewMiddlewareExecutor creates a new middleware executor
func newMiddlewareRunner(event *pl.Event, tx *gorm.DB) *middlewareRunner {
return &middlewareRunner{
Event: event,
Tx: tx,
}
}
// ExecuteCreateMiddleware executes create middleware
func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e.CreateDto, data *e.InternalReference) error {
for _, middleware := range middlewares {
logData := pu.GetLogData(input, data)
pl.SetLogInfo(me.Event, logData, "started", middleware.Name)
if err := middleware.Func(input, data, me.Tx); err != nil {
return pu.HandleMiddlewareError(me.Event, string(me.MwType), middleware.Name, logData, err)
}
pl.SetLogInfo(me.Event, nil, "complete")
}
return nil
}
func (me *middlewareRunner) RunReadListMiddleware(middlewares []readListMw, input *e.ReadListDto, data *e.InternalReference) error {
for _, middleware := range middlewares {
logData := pu.GetLogData(input, data)
pl.SetLogInfo(me.Event, logData, "started", middleware.Name)
if err := middleware.Func(input, data, me.Tx); err != nil {
return pu.HandleMiddlewareError(me.Event, string(me.MwType), middleware.Name, logData, err)
}
pl.SetLogInfo(me.Event, nil, "complete")
}
return nil
}
func (me *middlewareRunner) RunReadDetailMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.InternalReference) error {
for _, middleware := range middlewares {
logData := pu.GetLogData(input, data)
pl.SetLogInfo(me.Event, logData, "started", middleware.Name)
if err := middleware.Func(input, data, me.Tx); err != nil {
return pu.HandleMiddlewareError(me.Event, string(me.MwType), middleware.Name, logData, err)
}
pl.SetLogInfo(me.Event, nil, "complete")
}
return nil
}
func (me *middlewareRunner) RunUpdateMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.InternalReference) error {
for _, middleware := range middlewares {
logData := pu.GetLogData(input, data)
pl.SetLogInfo(me.Event, logData, "started", middleware.Name)
if err := middleware.Func(input, data, me.Tx); err != nil {
return pu.HandleMiddlewareError(me.Event, string(me.MwType), middleware.Name, logData, err)
}
pl.SetLogInfo(me.Event, nil, "complete")
}
return nil
}
func (me *middlewareRunner) RunDeleteMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.InternalReference) error {
for _, middleware := range middlewares {
logData := pu.GetLogData(input, data)
pl.SetLogInfo(me.Event, logData, "started", middleware.Name)
if err := middleware.Func(input, data, me.Tx); err != nil {
return pu.HandleMiddlewareError(me.Event, string(me.MwType), middleware.Name, logData, err)
}
pl.SetLogInfo(me.Event, nil, "complete")
}
return nil
}
func (me *middlewareRunner) setMwType(mwType pu.MWType) {
me.MwType = mwType
}
@@ -0,0 +1,9 @@
package internal_reference
// example of middleware
// func init() {
// createPreMw = append(createPreMw,
// CreateMw{Name: "modif-input", Func: pm.ModifInput},
// CreateMw{Name: "check-data", Func: pm.CheckData},
// )
// }
@@ -0,0 +1,44 @@
/*
DESCRIPTION:
A sample, part of the package that contains type, constants, and/or variables.
In this sample it also provides type and variable regarding the needs of the
middleware to separate from main use-case which has the basic CRUD
functionality. The purpose of this is to make the code more maintainable.
*/
package internal_reference
import (
"gorm.io/gorm"
e "simrs-vx/internal/domain/main-entities/internal-reference"
)
type createMw struct {
Name string
Func func(input *e.CreateDto, data *e.InternalReference, tx *gorm.DB) error
}
type readListMw struct {
Name string
Func func(input *e.ReadListDto, data *e.InternalReference, tx *gorm.DB) error
}
type readDetailMw struct {
Name string
Func func(input *e.ReadDetailDto, data *e.InternalReference, tx *gorm.DB) error
}
type UpdateMw = readDetailMw
type DeleteMw = readDetailMw
var createPreMw []createMw // preprocess middleware
var createPostMw []createMw // postprocess middleware
var readListPreMw []readListMw // ..
var readListPostMw []readListMw // ..
var readDetailPreMw []readDetailMw
var readDetailPostMw []readDetailMw
var updatePreMw []readDetailMw
var updatePostMw []readDetailMw
var deletePreMw []readDetailMw
var deletePostMw []readDetailMw
@@ -37,12 +37,15 @@ func setDataSimgos(input *e.Patient) (data esimgos.MPasien) {
mapContact(input.Person.Contacts, &data)
}
data.PenanggungjawabHubungan = "DIRI SENDIRI"
data.PenanggungjawabNama = input.Person.Name
data.PenanggungjawabPhone = data.Notelp
data.PenanggungjawabAlamat = data.Alamat
if input.Person != nil || input.Person.Relatives != nil {
mapRelative(input.Person.Relatives, &data)
if input.Person != nil {
data.PenanggungjawabHubungan = "DIRI SENDIRI"
data.PenanggungjawabNama = input.Person.Name
data.PenanggungjawabPhone = data.Notelp
data.PenanggungjawabAlamat = data.Alamat
if input.Person.Relatives != nil {
mapRelative(input.Person.Relatives, &data)
}
}
data.Nip = input.RegisteredBy_User_Name
@@ -14,7 +14,7 @@ import (
esync "simrs-vx/internal/domain/sync-entities/specialist"
)
func setDataSimgos[T *e.CreateDto | *e.UpdateDto](input T) (data esimgos.MPolihfis) {
func setDataSimgos[T *e.CreateDto | *e.UpdateDto](input T, data *esimgos.MPolihfis) {
var inputSrc *e.CreateDto
if inputT, ok := any(input).(*e.CreateDto); ok {
inputSrc = inputT
@@ -20,7 +20,8 @@ var now = time.Now()
func CreateSimgosData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*esimgos.MPolihfis, error) {
pl.SetLogInfo(event, nil, "started", "DBCreate")
data := setDataSimgos(&input)
data := esimgos.MPolihfis{}
setDataSimgos(&input, &data)
var tx *gorm.DB
if len(dbx) > 0 {
@@ -29,7 +30,7 @@ func CreateSimgosData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*esi
tx = dg.IS["simrs"]
}
if err := tx.Create(&data).Error; err != nil {
if err := tx.Debug().Create(&data).Error; err != nil {
return nil, plh.HandleCreateError(input, event, err)
}
@@ -58,7 +59,9 @@ func ReadDetailSimgosData(simgosId uint16, event *pl.Event) (*esimgos.MPolihfis,
func UpdateSimgosData(input e.UpdateDto, dataSimgos *esync.SpecialistLink, event *pl.Event, dbx ...*gorm.DB) error {
pl.SetLogInfo(event, input, "started", "DBUpdate")
data := setDataSimgos(&input)
data := esimgos.MPolihfis{}
setDataSimgos(&input, &data)
data.Id = dataSimgos.Simgos_Id
var tx *gorm.DB
@@ -7,6 +7,7 @@ package unit
import (
"encoding/json"
erc "simrs-vx/internal/domain/references/common"
"strconv"
e "simrs-vx/internal/domain/main-entities/unit"
@@ -27,6 +28,8 @@ func setDataSimgos[T *e.CreateDto | *e.UpdateDto](input T) (data esimgos.MPoly)
data.Nama = inputSrc.Name
data.Jenispoly = 0
kodePoly, _ := strconv.Atoi(inputSrc.Code)
data.Kode = uint(kodePoly)
return
}