diff --git a/.vscode/launch.json b/.vscode/launch.json index 7098c42c..fddb0d29 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -7,6 +7,13 @@ "mode": "auto", "program": "${workspaceFolder}/cmd/main-api" }, + { + "name": "Launch Package bpjs API", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "${workspaceFolder}/cmd/bpjs-api" + }, { "name": "Launch Package migratioon", "type": "go", diff --git a/cmd/bpjs-api/config.yml-example b/cmd/bpjs-api/config.yml-example index f131a725..60b1644c 100644 --- a/cmd/bpjs-api/config.yml-example +++ b/cmd/bpjs-api/config.yml-example @@ -63,4 +63,7 @@ bpjsCfg: corsCfg: allowedOrigins: - http://example.com - allowedMethod: \ No newline at end of file + allowedMethod: + +bpjsCfg: + baseUrl: \ No newline at end of file diff --git a/cmd/bpjs-api/main.go b/cmd/bpjs-api/main.go index 74be3afd..e1cb2468 100644 --- a/cmd/bpjs-api/main.go +++ b/cmd/bpjs-api/main.go @@ -6,7 +6,7 @@ import ( l "github.com/karincake/apem/logger-zerolog" m "github.com/karincake/apem/ms-redis" - h "simrs-vx/internal/interface/main-handler" + h "simrs-vx/internal/interface/bpjs-handler" ) func main() { diff --git a/cmd/main-migration/migrations/20251017060617.sql b/cmd/main-migration/migrations/20251017060617.sql new file mode 100644 index 00000000..8e3acbd2 --- /dev/null +++ b/cmd/main-migration/migrations/20251017060617.sql @@ -0,0 +1,2 @@ +-- Modify "MedicalActionSrc" table +ALTER TABLE "public"."MedicalActionSrc" ADD COLUMN "Type_Code" character varying(20) NULL; diff --git a/cmd/main-migration/migrations/20251017082207.sql b/cmd/main-migration/migrations/20251017082207.sql new file mode 100644 index 00000000..732c8d71 --- /dev/null +++ b/cmd/main-migration/migrations/20251017082207.sql @@ -0,0 +1,2 @@ +-- Modify "Item" table +ALTER TABLE "public"."Item" ALTER COLUMN "ItemGroup_Code" TYPE character varying(15); diff --git a/cmd/main-migration/migrations/20251018032635.sql b/cmd/main-migration/migrations/20251018032635.sql new file mode 100644 index 00000000..d8c5a2c9 --- /dev/null +++ b/cmd/main-migration/migrations/20251018032635.sql @@ -0,0 +1,4 @@ +-- Modify "Employee" table +ALTER TABLE "public"."Employee" ADD COLUMN "Position_Code" character varying(20) NULL; +-- Rename a column from "Position_Code" to "ContractPosition_Code" +ALTER TABLE "public"."User" RENAME COLUMN "Position_Code" TO "ContractPosition_Code"; diff --git a/cmd/main-migration/migrations/20251018040322.sql b/cmd/main-migration/migrations/20251018040322.sql new file mode 100644 index 00000000..d35e9199 --- /dev/null +++ b/cmd/main-migration/migrations/20251018040322.sql @@ -0,0 +1,13 @@ +-- Create "Intern" table +CREATE TABLE "public"."Intern" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Person_Id" bigint NULL, + "Position_Code" character varying(20) NULL, + "User_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_Intern_Person" FOREIGN KEY ("Person_Id") REFERENCES "public"."Person" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Intern_User" FOREIGN KEY ("User_Id") REFERENCES "public"."User" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/20251019093915.sql b/cmd/main-migration/migrations/20251019093915.sql new file mode 100644 index 00000000..31ac3655 --- /dev/null +++ b/cmd/main-migration/migrations/20251019093915.sql @@ -0,0 +1,15 @@ +-- Rename a column from "Position_Code" to "ContractPosition_Code" +ALTER TABLE "public"."User" RENAME COLUMN "Position_Code" TO "ContractPosition_Code"; +-- Create "Intern" table +CREATE TABLE "public"."Intern" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Person_Id" bigint NULL, + "Position_Code" character varying(20) NULL, + "User_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_Intern_Person" FOREIGN KEY ("Person_Id") REFERENCES "public"."Person" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Intern_User" FOREIGN KEY ("User_Id") REFERENCES "public"."User" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index bb5cb4b0..582b2527 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:5BOKtrJDl7mHDO/coJzV0ot0hVU9OVg5eP5Wg+zsIGo= +h1:eCBVp2yPQk7VrLdSk2mDps+FXavKA5OcJ1/QRBh+ovI= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -46,4 +46,7 @@ h1:5BOKtrJDl7mHDO/coJzV0ot0hVU9OVg5eP5Wg+zsIGo= 20251015045455.sql h1:MeLWmMhAOAz8b15Dd7IAQnt6JxjSml02XCXK22C0Lpg= 20251016010845.sql h1:4BncQdDOasRZJkzVJrSJJA7091A9VPNVx/faUCUPhBM= 20251016011023.sql h1:9JB9eFZKURK5RoCVDKR6glSvdJ8NTXrN7K/4q51zkz4= -20251016062912.sql h1:v21euwdu/4JCN3E2LFO4Iav4d7FEiAVH0dyEltmIeMw= +20251016062912.sql h1:ACNn0fe+EMqUt3hoY+Dr3uqAV/QICBa1+mIW7fUc9Fk= +20251017060617.sql h1:4T3t9ifWrEQTPMSM0XJ98pF7Qdt+UfgtMui17bhrnWI= +20251017082207.sql h1:8vLG1l/saRRMHXkyA4nelJyjaSddhZd6r7R+Uo4JS/c= +20251019093915.sql h1:wsJMh1r45ONaY7zIq2c3rTcuGXN4mI0irZK7a96HZW8= diff --git a/internal/domain/bpjs-entities/member/dto.go b/internal/domain/bpjs-entities/member/dto.go new file mode 100644 index 00000000..f9c95655 --- /dev/null +++ b/internal/domain/bpjs-entities/member/dto.go @@ -0,0 +1,15 @@ +package member + +type ReadListDto struct { + ReferenceType ReferenceType `json:"-"` + PathValue1 string `json:"-"` + PathValue2 string `json:"-"` + PathValue3 string `json:"-"` +} + +type ReferenceType string + +const ( + RTNik ReferenceType = "nik" + RTBpjs ReferenceType = "bpjs" +) diff --git a/internal/domain/bpjs-entities/member/entity.go b/internal/domain/bpjs-entities/member/entity.go new file mode 100644 index 00000000..b6c4f0d7 --- /dev/null +++ b/internal/domain/bpjs-entities/member/entity.go @@ -0,0 +1,78 @@ +package member + +type Response struct { + MetaData *MetaData `json:"metaData"` + Response *BPJSDataRes `json:"response"` +} + +type MetaData struct { + Code string `json:"code"` + Message string `json:"message"` +} + +type BPJSDataRes struct { + Peserta *Peserta `json:"peserta"` +} + +type Peserta struct { + Cob *COB `json:"cob"` + HakKelas *HakKelas `json:"hakKelas"` + Informasi *Informasi `json:"informasi"` + JenisPeserta *JenisPeserta `json:"jenisPeserta"` + Mr *MR `json:"mr"` + Nama *string `json:"nama"` + Nik *string `json:"nik"` + NoKartu *string `json:"noKartu"` + Pisa *string `json:"pisa"` + ProvUmum *ProvUmum `json:"provUmum"` + Sex *string `json:"sex"` + StatusPeserta *StatusPeserta `json:"statusPeserta"` + TglCetakKartu *string `json:"tglCetakKartu"` + TglLahir *string `json:"tglLahir"` + TglTAT *string `json:"tglTAT"` + TglTMT *string `json:"tglTMT"` + Umur *Umur `json:"umur"` +} + +type COB struct { + NmAsuransi *string `json:"nmAsuransi"` + NoAsuransi *string `json:"noAsuransi"` + TglTAT *string `json:"tglTAT"` + TglTMT *string `json:"tglTMT"` +} + +type HakKelas struct { + Keterangan *string `json:"keterangan"` + Kode *string `json:"kode"` +} + +type Informasi struct { + Dinsos *string `json:"dinsos"` + NoSKTM *string `json:"noSKTM"` + ProlanisPRB *string `json:"prolanisPRB"` +} + +type JenisPeserta struct { + Keterangan *string `json:"keterangan"` + Kode *string `json:"kode"` +} + +type MR struct { + NoMR *string `json:"noMR"` + NoTelepon *string `json:"noTelepon"` +} + +type ProvUmum struct { + KdProvider *string `json:"kdProvider"` + NmProvider *string `json:"nmProvider"` +} + +type StatusPeserta struct { + Keterangan *string `json:"keterangan"` + Kode *string `json:"kode"` +} + +type Umur struct { + UmurSaatPelayanan *string `json:"umurSaatPelayanan"` + UmurSekarang *string `json:"umurSekarang"` +} diff --git a/internal/domain/bpjs-entities/monitoring/dto.go b/internal/domain/bpjs-entities/monitoring/dto.go new file mode 100644 index 00000000..c5c1e0d1 --- /dev/null +++ b/internal/domain/bpjs-entities/monitoring/dto.go @@ -0,0 +1,15 @@ +package monitoring + +type ReadListDto struct { + ReferenceType ReferenceType `json:"-"` + PathValue1 string `json:"-"` + PathValue2 string `json:"-"` + PathValue3 string `json:"-"` +} + +type ReferenceType string + +const ( + RTVisit ReferenceType = "visit" + RTHist ReferenceType = "hist" +) diff --git a/internal/domain/bpjs-entities/monitoring/entity.go b/internal/domain/bpjs-entities/monitoring/entity.go new file mode 100644 index 00000000..eb604942 --- /dev/null +++ b/internal/domain/bpjs-entities/monitoring/entity.go @@ -0,0 +1,43 @@ +package monitoring + +type Response struct { + MetaData MetaData `json:"metaData"` + Response *BPJSDataRes `json:"response"` +} + +type MetaData struct { + Code string `json:"code"` + Message string `json:"message"` +} + +type BPJSDataRes struct { + Sep []Sep `json:"sep"` + Histori []Histori `json:"histori"` +} + +type Sep struct { + Diagnosa string `json:"diagnosa"` + JnsPelayanan string `json:"jnsPelayanan"` + KelasRawat string `json:"kelasRawat"` + Nama string `json:"nama"` + NoKartu string `json:"noKartu"` + NoSep string `json:"noSep"` + NoRujukan string `json:"noRujukan"` + Poli *string `json:"poli"` + TglPlgSep string `json:"tglPlgSep"` + TglSep string `json:"tglSep"` +} + +type Histori struct { + Diagnosa string `json:"diagnosa"` + JnsPelayanan string `json:"jnsPelayanan"` + KelasRawat *string `json:"kelasRawat"` + NamaPeserta string `json:"namaPeserta"` + NoKartu string `json:"noKartu"` + NoSep string `json:"noSep"` + NoRujukan string `json:"noRujukan"` + Poli string `json:"poli"` + PpkPelayanan string `json:"ppkPelayanan"` + TglPlgSep string `json:"tglPlgSep"` + TglSep string `json:"tglSep"` +} diff --git a/internal/domain/bpjs-entities/reference/dto.go b/internal/domain/bpjs-entities/reference/dto.go new file mode 100644 index 00000000..9be2ab5b --- /dev/null +++ b/internal/domain/bpjs-entities/reference/dto.go @@ -0,0 +1,22 @@ +package reference + +type ReadListDto struct { + ReferenceType ReferenceType `json:"-"` + PathValue1 string `json:"-"` + PathValue2 string `json:"-"` + PathValue3 string `json:"-"` +} + +type ReferenceType string + +const ( + RTProvince ReferenceType = "province" + RTDistrict ReferenceType = "district" + RTCities ReferenceType = "cities" + RTDiagnose ReferenceType = "diagnose" + RTDiagnosePrb ReferenceType = "diagnose-prb" + RTMedicinePrb ReferenceType = "medicine-prb" + RTUnit ReferenceType = "unit" + RTHealthcare ReferenceType = "healthcare" + RTDoctor ReferenceType = "doctor" +) diff --git a/internal/domain/bpjs-entities/reference/entity.go b/internal/domain/bpjs-entities/reference/entity.go new file mode 100644 index 00000000..bfcbb66e --- /dev/null +++ b/internal/domain/bpjs-entities/reference/entity.go @@ -0,0 +1,23 @@ +package reference + +type Response struct { + MetaData MetaData `json:"metaData"` + Response *CodeNameList `json:"response"` // pointer to handle possible null +} + +type MetaData struct { + Code string `json:"code"` + Message string `json:"message"` +} + +type CodeNameList struct { + List []CodeName `json:"list,omitempty"` + Diagnosa []CodeName `json:"diagnosa,omitempty"` + Poli []CodeName `json:"poli,omitempty"` + Faskes []CodeName `json:"faskes,omitempty"` +} + +type CodeName struct { + Kode string `json:"kode"` + Nama string `json:"nama"` +} diff --git a/internal/domain/bpjs-entities/vclaim-sep-hist/dto.go b/internal/domain/bpjs-entities/vclaim-sep-hist/dto.go index 778154cb..d58eaf6e 100644 --- a/internal/domain/bpjs-entities/vclaim-sep-hist/dto.go +++ b/internal/domain/bpjs-entities/vclaim-sep-hist/dto.go @@ -1 +1,68 @@ package vclaimsephist + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" +) + +type CreateDto struct { + RequestPayload string `json:"requestPayload"` + ResponseBody string `json:"responseBody"` + Message string `json:"message"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Sort string `json:"sort"` + Pagination ecore.Pagination +} + +type FilterDto struct { + RequestPayload *string `json:"requestPayload"` + ResponseBody *string `json:"responseBody"` + Message *string `json:"message"` +} + +type ReadDetailDto struct { + Id uint `json:"id"` +} + +type UpdateDto struct { + Id uint `json:"id"` + CreateDto +} + +type DeleteDto struct { + Id uint `json:"id"` +} + +type MetaDto struct { + PageNumber int `json:"page_number"` + PageSize int `json:"page_size"` + Count int `json:"count"` +} + +type ResponseDto struct { + ecore.Main + RequestPayload *string `json:"requestPayload"` + ResponseBody *string `json:"responseBody"` + Message *string `json:"message"` +} + +func (d VclaimSepHist) ToResponse() ResponseDto { + resp := ResponseDto{ + RequestPayload: d.RequestPayload, + ResponseBody: d.ResponseBody, + Message: d.Message, + } + resp.Main = d.Main + return resp +} + +func ToResponseList(data []VclaimSepHist) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/bpjs-entities/vclaim-sep-print/dto.go b/internal/domain/bpjs-entities/vclaim-sep-print/dto.go index b975dd96..17650e40 100644 --- a/internal/domain/bpjs-entities/vclaim-sep-print/dto.go +++ b/internal/domain/bpjs-entities/vclaim-sep-print/dto.go @@ -1 +1,62 @@ package vclaimsepprint + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" +) + +type CreateDto struct { + VclaimSep_Number *string `json:"vclaimSep_number"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Sort string `json:"sort"` + Pagination ecore.Pagination +} + +type FilterDto struct { + VclaimSep_Number *string `json:"vclaimSep_number"` +} + +type ReadDetailDto struct { + Id uint `json:"id"` +} + +type UpdateDto struct { + Id uint `json:"id"` + CreateDto +} + +type DeleteDto struct { + Id uint `json:"id"` +} + +type MetaDto struct { + PageNumber int `json:"page_number"` + PageSize int `json:"page_size"` + Count int `json:"count"` +} + +type ResponseDto struct { + ecore.Main + VclaimSep_Number *string `json:"vclaimSep_number"` + Counter *uint `json:"counter"` +} + +func (d VclaimSepPrint) ToResponse() ResponseDto { + resp := ResponseDto{ + VclaimSep_Number: d.VclaimSep_Number, + Counter: d.Counter, + } + resp.Main = d.Main + return resp +} + +func ToResponseList(data []VclaimSepPrint) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/bpjs-entities/vclaim-sep/dto.go b/internal/domain/bpjs-entities/vclaim-sep/dto.go index ce4c6f55..8a174688 100644 --- a/internal/domain/bpjs-entities/vclaim-sep/dto.go +++ b/internal/domain/bpjs-entities/vclaim-sep/dto.go @@ -1 +1,73 @@ package vclaimsep + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + evsh "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-hist" +) + +type CreateDto struct { + Encounter_Id *uint `json:"encounter_id"` + Number *string `json:"number" validate:"maxLength=19"` + RequestPayload []byte `json:"requestPayload" validate:"maxLength=1024"` + + VclaimSepHist evsh.CreateDto +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Sort string `json:"sort"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Number *string `json:"number"` +} + +type ReadDetailDto struct { + Id uint `json:"id"` + Number *string `json:"number"` +} + +type UpdateDto struct { + Id uint `json:"id"` + CreateDto +} + +type DeleteDto struct { + Id uint `json:"id"` + Number *string `json:"number"` +} + +type MetaDto struct { + PageNumber int `json:"page_number"` + PageSize int `json:"page_size"` + Count int `json:"count"` +} + +type ResponseDto struct { + ecore.Main + Encounter_Id *uint `json:"encounter_id"` + Number *string `json:"number"` +} + +func (d VclaimSep) ToResponse() ResponseDto { + resp := ResponseDto{ + Encounter_Id: d.Encounter_Id, + Number: d.Number, + } + resp.Main = d.Main + return resp +} + +func ToResponseList(data []VclaimSep) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} + +func (c CreateDto) IsMessageSuccess() bool { + return c.VclaimSepHist.Message == "Sukses" +} diff --git a/internal/domain/main-entities/employee/entity.go b/internal/domain/main-entities/employee/entity.go index 8113fc96..2e8cd953 100644 --- a/internal/domain/main-entities/employee/entity.go +++ b/internal/domain/main-entities/employee/entity.go @@ -6,16 +6,18 @@ import ( ep "simrs-vx/internal/domain/main-entities/person" eu "simrs-vx/internal/domain/main-entities/user" erc "simrs-vx/internal/domain/references/common" + erg "simrs-vx/internal/domain/references/organization" ) type Employee struct { - ecore.Main // adjust this according to the needs - User_Id *uint `json:"user_id"` - User *eu.User `json:"user,omitempty" gorm:"foreignKey:User_Id;references:Id"` - Person_Id *uint `json:"person_id"` - Person *ep.Person `json:"person,omitempty" gorm:"foreignKey:Person_Id;references:Id"` - Division_Code *string `json:"division_code"` - Division *ed.Division `json:"division,omitempty" gorm:"foreignKey:Division_Code;references:Code"` - Number *string `json:"number" gorm:"size:20"` - Status_Code erc.ActiveStatusCode `json:"status_code" gorm:"not null;size:10"` + ecore.Main // adjust this according to the needs + User_Id *uint `json:"user_id"` + User *eu.User `json:"user,omitempty" gorm:"foreignKey:User_Id;references:Id"` + Person_Id *uint `json:"person_id"` + Person *ep.Person `json:"person,omitempty" gorm:"foreignKey:Person_Id;references:Id"` + Position_Code *erg.EmployeePosisitionCode `json:"position_code" gorm:"size:20"` + Division_Code *string `json:"division_code"` + Division *ed.Division `json:"division,omitempty" gorm:"foreignKey:Division_Code;references:Code"` + Number *string `json:"number" gorm:"size:20"` + Status_Code erc.ActiveStatusCode `json:"status_code" gorm:"not null;size:10"` } diff --git a/internal/domain/main-entities/encounter/dto.go b/internal/domain/main-entities/encounter/dto.go index bd630857..67810d27 100644 --- a/internal/domain/main-entities/encounter/dto.go +++ b/internal/domain/main-entities/encounter/dto.go @@ -4,8 +4,10 @@ import ( "time" ecore "simrs-vx/internal/domain/base-entities/core" + evs "simrs-vx/internal/domain/bpjs-entities/vclaim-sep" ea "simrs-vx/internal/domain/main-entities/appointment" ed "simrs-vx/internal/domain/main-entities/doctor" + ee "simrs-vx/internal/domain/main-entities/employee" ep "simrs-vx/internal/domain/main-entities/patient" es "simrs-vx/internal/domain/main-entities/specialist" ess "simrs-vx/internal/domain/main-entities/subspecialist" @@ -13,6 +15,8 @@ import ( erc "simrs-vx/internal/domain/references/common" ere "simrs-vx/internal/domain/references/encounter" + + pa "simrs-vx/pkg/auth-helper" ) type CreateDto struct { @@ -25,10 +29,18 @@ type CreateDto struct { Specialist_Id *uint16 `json:"specialist_id"` Subspecialist_Id *uint16 `json:"subspecialist_id"` VisitDate time.Time `json:"visitDate"` + PaymentMethod_Code erc.PaymentMethodCode `json:"paymentMethod_code" gorm:"size:10"` + InsuranceCompany_Id *uint `json:"insuranceCompany_id"` + Member_Number *string `json:"member_number" validate:"maxLength=20"` + Ref_Number *string `json:"ref_number" validate:"maxLength=20"` + Trx_Number *string `json:"trx_number" validate:"maxLength=20"` Appointment_Doctor_Id *uint `json:"appointment_doctor_id"` + Adm_Employee_Id *uint `json:"-"` Responsible_Doctor_Id *uint `json:"responsible_doctor_id"` RefSource_Name *string `json:"refSource_name" validate:"maxLength=100"` Appointment_Id *uint `json:"appointment_id"` + + pa.AuthInfo } type ReadListDto struct { @@ -41,7 +53,7 @@ type FilterDto struct { Patient_Id *uint `json:"patient-id"` Patient *ep.Patient `json:"patient,omitempty"` RegisteredAt *time.Time `json:"registeredAt"` - Class_Code ere.EncounterClassCode `json:"class_code" validate:"maxLength=10"` + Class_Code ere.EncounterClassCode `json:"class-code" validate:"maxLength=10"` Unit_Id *uint `json:"unit-id"` Specialist_Id *uint16 `json:"specialist-id"` Subspecialist_Id *uint16 `json:"subspecialist-id"` @@ -58,7 +70,8 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id uint16 `json:"id"` + Includes string `json:"includes"` } type UpdateDto struct { @@ -102,10 +115,17 @@ type ResponseDto struct { Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty"` Unit *eu.Unit `json:"unit,omitempty"` VisitDate time.Time `json:"visitDate"` - Appointment_Doctor_Id *uint `json:"assignment_doctor_id"` - Appointment_Doctor *ed.Doctor `json:"assignment_doctor,omitempty"` + PaymentMethod_Code erc.PaymentMethodCode `json:"paymentMethod_code"` + InsuranceCompany_Id *uint `json:"insuranceCompany_id"` + Member_Number *string `json:"member_number"` + Ref_Number *string `json:"ref_number"` + Trx_Number *string `json:"trx_number"` + Appointment_Doctor_Id *uint `json:"appointment_doctor_id"` + Appointment_Doctor *ed.Doctor `json:"appointment_doctor,omitempty"` Responsible_Doctor_Id *uint `json:"responsible_doctor_id"` Responsible_Doctor *ed.Doctor `json:"responsible_doctor,omitempty"` + Adm_Employee_Id *uint `json:"adm_employee_id"` + Adm_Employee *ee.Employee `json:"adm_employee,omitempty"` DischargeMethod_Code *ere.DischargeMethodCode `json:"dischargeMethod_code"` RefSource_Name *string `json:"refSource_name"` Appointment_Id *uint `json:"appointment_id"` @@ -115,6 +135,7 @@ type ResponseDto struct { AdmDischargeEducation *string `json:"admDischargeEducation"` DischargeReason *string `json:"dischargeReason"` Status_Code erc.DataStatusCode `json:"status_code"` + VclaimSep *evs.VclaimSep `json:"vclaimSep,omitempty"` } func (d Encounter) ToResponse() ResponseDto { @@ -130,8 +151,15 @@ func (d Encounter) ToResponse() ResponseDto { Subspecialist_Id: d.Subspecialist_Id, Subspecialist: d.Subspecialist, VisitDate: d.VisitDate, + PaymentMethod_Code: d.PaymentMethod_Code, + InsuranceCompany_Id: d.InsuranceCompany_Id, + Member_Number: d.Member_Number, + Ref_Number: d.Ref_Number, + Trx_Number: d.Trx_Number, Appointment_Doctor_Id: d.Appointment_Doctor_Id, Appointment_Doctor: d.Appointment_Doctor, + Adm_Employee_Id: d.Adm_Employee_Id, + Adm_Employee: d.Adm_Employee, Responsible_Doctor_Id: d.Responsible_Doctor_Id, Responsible_Doctor: d.Responsible_Doctor, DischargeMethod_Code: d.DischargeMethod_Code, @@ -143,6 +171,7 @@ func (d Encounter) ToResponse() ResponseDto { AdmDischargeEducation: d.AdmDischargeEducation, DischargeReason: d.DischargeReason, Status_Code: d.Status_Code, + VclaimSep: d.VclaimSep, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/encounter/entity.go b/internal/domain/main-entities/encounter/entity.go index 3e888356..528f28ae 100644 --- a/internal/domain/main-entities/encounter/entity.go +++ b/internal/domain/main-entities/encounter/entity.go @@ -38,8 +38,8 @@ type Encounter struct { Trx_Number *string `json:"trxNumber" gorm:"unique;size:20"` Appointment_Doctor_Id *uint `json:"appointment_doctor_id"` Appointment_Doctor *ed.Doctor `json:"appointment_doctor,omitempty" gorm:"foreignKey:Appointment_Doctor_Id;references:Id"` - Adm_Employee_Id *uint `json:"admEmployee_id"` - Adm_Employee *ee.Employee `json:"admEmployee,omitempty" gorm:"foreignKey:Adm_Employee_Id;references:Id"` + Adm_Employee_Id *uint `json:"adm_employee_id"` + Adm_Employee *ee.Employee `json:"adm_employee,omitempty" gorm:"foreignKey:Adm_Employee_Id;references:Id"` Responsible_Doctor_Id *uint `json:"responsible_doctor_id"` Responsible_Doctor *ed.Doctor `json:"responsible_doctor,omitempty" gorm:"foreignKey:Responsible_Doctor_Id;references:Id"` DischargeMethod_Code *ere.DischargeMethodCode `json:"dischargeMethod_code" gorm:"size:16"` diff --git a/internal/domain/main-entities/intern/dto.go b/internal/domain/main-entities/intern/dto.go new file mode 100644 index 00000000..b8c60aee --- /dev/null +++ b/internal/domain/main-entities/intern/dto.go @@ -0,0 +1,81 @@ +package intern + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ep "simrs-vx/internal/domain/main-entities/person" + es "simrs-vx/internal/domain/main-entities/specialist" + ess "simrs-vx/internal/domain/main-entities/subspecialist" + eu "simrs-vx/internal/domain/main-entities/user" +) + +type CreateDto struct { + Person_Id *uint `json:"person_id"` + Specialist_Id *uint16 `json:"specialist_id"` + Subspecialist_Id *uint16 `json:"subspecialist_id"` + User_Id *uint `json:"user_id"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Preloads []string `json:"-"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Person_Id *uint `json:"person_id"` + Specialist_Id *uint16 `json:"specialist_id"` + Subspecialist_Id *uint16 `json:"subspecialist_id"` + User_Id *uint `json:"user_id"` +} + +type ReadDetailDto struct { + Id uint16 `json:"id"` + User_Id *uint `json:"user_id"` +} + +type UpdateDto struct { + Id uint `json:"id"` + CreateDto +} + +type DeleteDto struct { + Id uint `json:"id"` +} + +type MetaDto struct { + PageNumber int `json:"page_number"` + PageSize int `json:"page_size"` + Count int `json:"count"` +} + +type ResponseDto struct { + ecore.Main + Person_Id *uint `json:"person_id"` + Person *ep.Person `json:"person,omitempty"` + Specialist_Id *uint16 `json:"specialist_id"` + Specialist *es.Specialist `json:"specialist,omitempty"` + Subspecialist_Id *uint16 `json:"subspecialist_id"` + Subspecialist *ess.Subspecialist `json:"subspecialist,omitempty"` + User_Id *uint `json:"user_id"` + User *eu.User `json:"user,omitempty"` +} + +func (d Intern) ToResponse() ResponseDto { + resp := ResponseDto{ + Person_Id: d.Person_Id, + Person: d.Person, + User_Id: d.User_Id, + User: d.User, + } + resp.Main = d.Main + return resp +} + +func ToResponseList(data []Intern) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/intern/entity.go b/internal/domain/main-entities/intern/entity.go new file mode 100644 index 00000000..5ac2df49 --- /dev/null +++ b/internal/domain/main-entities/intern/entity.go @@ -0,0 +1,17 @@ +package intern + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ep "simrs-vx/internal/domain/main-entities/person" + eu "simrs-vx/internal/domain/main-entities/user" + erg "simrs-vx/internal/domain/references/organization" +) + +type Intern struct { + ecore.Main // adjust this according to the needs + Person_Id *uint `json:"person_id"` + Person *ep.Person `json:"person,omitempty" gorm:"foreignKey:Person_Id"` + Position_Code *erg.InternPosisitionCode `json:"position_code" gorm:"size:20"` + User_Id *uint `json:"user_id"` + User *eu.User `json:"user,omitempty" gorm:"foreignKey:User_Id"` +} diff --git a/internal/domain/main-entities/item/entity.go b/internal/domain/main-entities/item/entity.go index 9ac471ad..e0ff4e21 100644 --- a/internal/domain/main-entities/item/entity.go +++ b/internal/domain/main-entities/item/entity.go @@ -11,7 +11,7 @@ type Item struct { ecore.Main // adjust this according to the needs Code string `json:"code" gorm:"unique;size:50"` Name string `json:"name" gorm:"size:100"` - ItemGroup_Code ero.ItemGroupCode `json:"itemGroup_code" gorm:"size:10"` + ItemGroup_Code ero.ItemGroupCode `json:"itemGroup_code" gorm:"size:15"` Uom_Code *string `json:"uom_code" gorm:"size:10"` Uom *eu.Uom `json:"uom,omitempty" gorm:"foreignKey:Uom_Code;references:Code"` Infra_Id *uint16 `json:"infra_id"` diff --git a/internal/domain/main-entities/medical-action-src/dto.go b/internal/domain/main-entities/medical-action-src/dto.go index c67a2429..32e248d8 100644 --- a/internal/domain/main-entities/medical-action-src/dto.go +++ b/internal/domain/main-entities/medical-action-src/dto.go @@ -6,9 +6,10 @@ import ( ) type CreateDto struct { - Code string `json:"code" validate:"maxLength=20"` - Name string `json:"name" validate:"maxLength=50"` - Item_Id *uint `json:"item_id"` + Code string `json:"code" validate:"maxLength=20"` + Name string `json:"name" validate:"maxLength=50"` + Type_Code string `json:"type_code" validate:"maxLength=20"` + Item_Id *uint `json:"item_id"` } type ReadListDto struct { @@ -19,10 +20,11 @@ type ReadListDto struct { } type FilterDto struct { - Code string `json:"code"` - Name string `json:"name"` - Item_Id *uint `json:"item-id"` - Search string `json:"search" gormhelper:"searchColumns=Code,Name"` + Code string `json:"code"` + Name string `json:"name"` + Type_Code string `json:"type_code"` + Item_Id *uint `json:"item-id"` + Search string `json:"search" gormhelper:"searchColumns=Code,Name"` } type ReadDetailDto struct { @@ -47,18 +49,20 @@ type MetaDto struct { type ResponseDto struct { ecore.Main - Code string `json:"code"` - Name string `json:"name"` - Item_Id *uint `json:"item_id"` - Item *ei.Item `json:"item,omitempty"` + Code string `json:"code"` + Name string `json:"name"` + Type_Code string `json:"type_code"` + Item_Id *uint `json:"item_id"` + Item *ei.Item `json:"item,omitempty"` } func (d MedicalActionSrc) ToResponse() ResponseDto { resp := ResponseDto{ - Code: d.Code, - Name: d.Name, - Item_Id: d.Item_Id, - Item: d.Item, + Code: d.Code, + Name: d.Name, + Type_Code: d.Type_Code, + Item_Id: d.Item_Id, + Item: d.Item, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/medical-action-src/entity.go b/internal/domain/main-entities/medical-action-src/entity.go index fbbbdb28..60f15816 100644 --- a/internal/domain/main-entities/medical-action-src/entity.go +++ b/internal/domain/main-entities/medical-action-src/entity.go @@ -9,6 +9,7 @@ type MedicalActionSrc struct { ecore.Main // adjust this according to the needs Code string `json:"code" gorm:"unique;size:20"` Name string `json:"name" gorm:"size:50"` + Type_Code string `json:"type_code" gorm:"size:20"` Item_Id *uint `json:"item_id"` Item *ei.Item `json:"item,omitempty" gorm:"foreignKey:Item_Id;references:Id"` } diff --git a/internal/domain/main-entities/patient/dto.go b/internal/domain/main-entities/patient/dto.go index d1d32324..00134b6e 100644 --- a/internal/domain/main-entities/patient/dto.go +++ b/internal/domain/main-entities/patient/dto.go @@ -8,6 +8,7 @@ import ( ep "simrs-vx/internal/domain/main-entities/person" epa "simrs-vx/internal/domain/main-entities/person-address" epc "simrs-vx/internal/domain/main-entities/person-contact" + epi "simrs-vx/internal/domain/main-entities/person-insurance" epr "simrs-vx/internal/domain/main-entities/person-relative" erc "simrs-vx/internal/domain/references/common" @@ -15,14 +16,15 @@ import ( ) type CreateDto struct { - Person_Id *uint `json:"-"` - Person *ep.UpdateDto `json:"person"` - NewBornStatus bool `json:"newBornStatus"` - PersonAddresses []epa.UpdateDto `json:"personAddresses"` - PersonContacts []epc.UpdateDto `json:"personContacts"` - PersonRelatives []epr.UpdateDto `json:"personRelatives"` - RegisteredAt *time.Time `json:"registeredAt"` - Status_Code erc.ActiveStatusCode `json:"status_code" validate:"maxLength=10"` + Person_Id *uint `json:"-"` + Person *ep.UpdateDto `json:"person"` + NewBornStatus bool `json:"newBornStatus"` + PersonAddresses []epa.UpdateDto `json:"personAddresses"` + PersonContacts []epc.UpdateDto `json:"personContacts"` + PersonRelatives []epr.UpdateDto `json:"personRelatives"` + PersonInsurances []epi.UpdateDto `json:"personInsurances"` + RegisteredAt *time.Time `json:"registeredAt"` + Status_Code erc.ActiveStatusCode `json:"status_code" validate:"maxLength=10"` } type ReadListDto struct { @@ -55,7 +57,8 @@ type DeleteDto struct { } type SearchDto struct { - Search string `json:"search"` + Search string `json:"search"` + Mode SearchMode `json:"mode"` } type UploadDto struct { diff --git a/internal/domain/main-entities/patient/tycovar.go b/internal/domain/main-entities/patient/tycovar.go new file mode 100644 index 00000000..aa419b57 --- /dev/null +++ b/internal/domain/main-entities/patient/tycovar.go @@ -0,0 +1,8 @@ +package patient + +type SearchMode string + +const ( + SMNik SearchMode = "resident-identity" + SMIdent SearchMode = "identifier" +) diff --git a/internal/domain/main-entities/person-insurance/dto.go b/internal/domain/main-entities/person-insurance/dto.go index 5a2ee2a1..e811023d 100644 --- a/internal/domain/main-entities/person-insurance/dto.go +++ b/internal/domain/main-entities/person-insurance/dto.go @@ -1 +1,75 @@ package personinsurance + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ei "simrs-vx/internal/domain/main-entities/insurance-company" +) + +type CreateDto struct { + Person_Id uint `json:"person_id"` + InsuranceCompany_Id *uint `json:"insurance_id"` + Ref_Number *string `json:"ref_number" gorm:"unique;size:20"` + DefaultStatus *bool `json:"default_status" gorm:"uniqueIndex:idx_person_insurance"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Sort string `json:"sort"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Person_Id *uint `json:"person-id"` + InsuranceCompany_Id *uint `json:"insurance-company-id"` + Ref_Number *string `json:"ref-number"` + DefaultStatus *bool `json:"default-status"` +} + +type ReadDetailDto struct { + Id uint16 `json:"id"` +} + +type UpdateDto struct { + Id uint16 `json:"id"` + CreateDto +} + +type DeleteDto struct { + Id uint16 `json:"id"` +} + +type MetaDto struct { + PageNumber int `json:"page_number"` + PageSize int `json:"page_size"` + Count int `json:"count"` +} + +type ResponseDto struct { + ecore.Main + Person_Id *uint `json:"person_id"` + InsuranceCompany_Id *uint `json:"insuranceCompany_id"` + InsuranceCompany *ei.InsuranceCompany `json:"insuranceCompany,omitempty"` + Ref_Number *string `json:"ref_number"` + DefaultStatus *bool `json:"defaultStatus"` +} + +func (d PersonInsurance) ToResponse() ResponseDto { + resp := ResponseDto{ + Person_Id: d.Person_Id, + InsuranceCompany_Id: d.InsuranceCompany_Id, + InsuranceCompany: d.InsuranceCompany, + Ref_Number: d.Ref_Number, + DefaultStatus: d.DefaultStatus, + } + resp.Main = d.Main + return resp +} + +func ToResponseList(data []PersonInsurance) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/user/dto.go b/internal/domain/main-entities/user/dto.go index 9f948fe7..55a53686 100644 --- a/internal/domain/main-entities/user/dto.go +++ b/internal/domain/main-entities/user/dto.go @@ -1,33 +1,33 @@ package user import ( + ecore "simrs-vx/internal/domain/base-entities/core" "time" - ecore "simrs-vx/internal/domain/base-entities/core" ep "simrs-vx/internal/domain/main-entities/person" epa "simrs-vx/internal/domain/main-entities/person-address" epc "simrs-vx/internal/domain/main-entities/person-contact" erc "simrs-vx/internal/domain/references/common" - ero "simrs-vx/internal/domain/references/organization" + erg "simrs-vx/internal/domain/references/organization" ) type CreateDto struct { - Name string `json:"name" validate:"maxLength=25"` - Password string `json:"password" validate:"maxLength=255"` - Status_Code erc.UserStatusCode `json:"status_code" validate:"maxLength=10"` - Position_Code ero.UserPosisitionCode `json:"position_code" validate:"maxLength=20"` - Person_Id *uint `json:"-"` - Person *ep.UpdateDto `json:"person"` - PersonAddresses []epa.UpdateDto `json:"personAddresses"` - PersonContacts []epc.UpdateDto `json:"personContacts"` - Employee *EmployeUpdateDto `json:"employee"` - IHS_Number *string `json:"ihs_number" validate:"maxLength=20"` - SIP_Number *string `json:"sip_number" validate:"maxLength=20"` - Unit_Id *uint16 `json:"unit_id"` - Infra_Id *uint16 `json:"infra_id"` - Specialist_Id *uint16 `json:"specialist_id"` - Subspecialist_Id *uint16 `json:"subspecialist_id"` + Name string `json:"name" validate:"maxLength=25"` + Password string `json:"password" validate:"maxLength=255"` + Status_Code erc.UserStatusCode `json:"status_code" validate:"maxLength=10"` + Person_Id *uint `json:"-"` + Person *ep.UpdateDto `json:"person"` + PersonAddresses []epa.UpdateDto `json:"personAddresses"` + PersonContacts []epc.UpdateDto `json:"personContacts"` + Employee *EmployeUpdateDto `json:"employee"` + IHS_Number *string `json:"ihs_number" validate:"maxLength=20"` + SIP_Number *string `json:"sip_number" validate:"maxLength=20"` + Unit_Id *uint16 `json:"unit_id"` + Infra_Id *uint16 `json:"infra_id"` + Specialist_Id *uint16 `json:"specialist_id"` + Subspecialist_Id *uint16 `json:"subspecialist_id"` + ContractPosition_Code erg.ContractPositionCode `json:"contractPosition_code" gorm:"not null;size:20"` } type ReadListDto struct { @@ -84,12 +84,13 @@ func (d *User) ToResponse() ResponseDto { } type EmployeUpdateDto struct { - Id uint `json:"id"` - User_Id *uint `json:"-"` - Person_Id *uint `json:"-"` - Division_Code *string `json:"division_code"` - Number *string `json:"number" validate:"maxLength=20"` - Status_Code erc.ActiveStatusCode `json:"status_code" validate:"maxLength=10"` + Id uint `json:"id"` + User_Id *uint `json:"-"` + Person_Id *uint `json:"-"` + Division_Code *string `json:"division_code"` + Number *string `json:"number" validate:"maxLength=20"` + Position_Code erg.EmployeePosisitionCode `json:"status_code" validate:"maxLength=10"` + Status_Code erc.ActiveStatusCode `json:"status_code" validate:"maxLength=10"` } func ToResponseList(data []User) []ResponseDto { diff --git a/internal/domain/main-entities/user/entity.go b/internal/domain/main-entities/user/entity.go index 4f7d8792..f51dbf14 100644 --- a/internal/domain/main-entities/user/entity.go +++ b/internal/domain/main-entities/user/entity.go @@ -5,17 +5,17 @@ import ( ecore "simrs-vx/internal/domain/base-entities/core" erc "simrs-vx/internal/domain/references/common" - ero "simrs-vx/internal/domain/references/organization" + erg "simrs-vx/internal/domain/references/organization" ) type User struct { - ecore.Main // adjust this according to the needs - Name string `json:"name" gorm:"unique;not null;size:25"` - Password string `json:"password" gorm:"not null;size:255"` - Status_Code erc.UserStatusCode `json:"status_code" gorm:"not null;size:10"` - FailedLoginCount uint8 `json:"failedLoginCount" gorm:"type:smallint"` - Position_Code ero.UserPosisitionCode `json:"position_code" gorm:"not null;size:20"` - LoginAttemptCount int `json:"-"` - LastSuccessLogin *time.Time `json:"lastSuccessLogin,omitempty"` - LastAllowdLogin *time.Time `json:"lastAllowdLogin,omitempty"` + ecore.Main // adjust this according to the needs + Name string `json:"name" gorm:"unique;not null;size:25"` + Password string `json:"password" gorm:"not null;size:255"` + Status_Code erc.UserStatusCode `json:"status_code" gorm:"not null;size:10"` + ContractPosition_Code erg.ContractPositionCode `json:"contractPosition_code" gorm:"not null;size:20"` + FailedLoginCount uint8 `json:"failedLoginCount" gorm:"type:smallint"` + LoginAttemptCount int `json:"-"` + LastSuccessLogin *time.Time `json:"lastSuccessLogin,omitempty"` + LastAllowdLogin *time.Time `json:"lastAllowdLogin,omitempty"` } diff --git a/internal/domain/references/organization/organization.go b/internal/domain/references/organization/organization.go index bf11fbd6..93eabe63 100644 --- a/internal/domain/references/organization/organization.go +++ b/internal/domain/references/organization/organization.go @@ -1,26 +1,33 @@ package organization type ( - UserPosisitionCode string - ItemGroupCode string - InfraGroupCode string - UnitTypeCode string - DoctorFeeTypeCode string + ContractPositionCode string + EmployeePosisitionCode string + InternPosisitionCode string + ItemGroupCode string + InfraGroupCode string + UnitTypeCode string + DoctorFeeTypeCode string ) const ( - UPCReg UserPosisitionCode = "registration" // Admisi/Pendaftaran - UPCNur UserPosisitionCode = "nurse" // Perawat - UPCDoc UserPosisitionCode = "doctor" // Dokter - UPCNut UserPosisitionCode = "nutritionist" // Ahli gizi - UPCMwi UserPosisitionCode = "mid-wife" // Bidan - UPCLab UserPosisitionCode = "laborant" // Laboran - UPCPha UserPosisitionCode = "pharmacy" // Farmasi - UPCPay UserPosisitionCode = "payment" // Pembayaran - UPCHur UserPosisitionCode = "human-resource" // Sumber Daya Manusia - UPCGea UserPosisitionCode = "general-affair" // Bagian Umum - UPCInt UserPosisitionCode = "specialist-intern" // PPDS - UPCMan UserPosisitionCode = "management" // Manajemen + CSCEmp ContractPositionCode = "employee" // Pegawai + CSCInt ContractPositionCode = "intern" // PPDS + + EPCReg EmployeePosisitionCode = "registration" // Admisi/Pendaftaran + EPCNur EmployeePosisitionCode = "nurse" // Perawat + EPCDoc EmployeePosisitionCode = "doctor" // Dokter + EPCNut EmployeePosisitionCode = "nutritionist" // Ahli gizi + EPCMwi EmployeePosisitionCode = "mid-wife" // Bidan + EPCLab EmployeePosisitionCode = "laborant" // Laboran + EPCPha EmployeePosisitionCode = "pharmacy" // Farmasi + EPCPay EmployeePosisitionCode = "payment" // Pembayaran + EPCHur EmployeePosisitionCode = "human-resource" // Sumber Daya Manusia + EPCGea EmployeePosisitionCode = "general-affair" // Bagian Umum + EPCMan EmployeePosisitionCode = "management" // Manajemen + + IPCSpecialist = "specialist-intern" + IPCNurse = "nurse-intern" ITGCInfra ItemGroupCode = "infra" ITGCMedicine ItemGroupCode = "medicine" @@ -30,6 +37,7 @@ const ( ITGCMCUSub ItemGroupCode = "mcuSub" ITGCEmpFee ItemGroupCode = "employee-fee" ITGCDocFee ItemGroupCode = "doctor-fee" + ITGCMedAct ItemGroupCode = "medical-action" IFGCBuilding InfraGroupCode = "building" // Bangunan IFGCFloor InfraGroupCode = "floor" // Lantai diff --git a/internal/infra/bpjs/bpjs.go b/internal/infra/bpjs/bpjs.go new file mode 100644 index 00000000..36935c74 --- /dev/null +++ b/internal/infra/bpjs/bpjs.go @@ -0,0 +1,14 @@ +package bpjs + +import ( + a "github.com/karincake/apem" + lo "github.com/karincake/apem/loggero" +) + +func SetConfig() { + a.ParseSingleCfg(&O) + if O.BaseUrl == "" { + panic("config bpjs base url empty") + } + lo.I.Println("Bpjs config loaded, status: DONE!!") +} diff --git a/internal/infra/bpjs/tycovar.go b/internal/infra/bpjs/tycovar.go new file mode 100644 index 00000000..54e45a63 --- /dev/null +++ b/internal/infra/bpjs/tycovar.go @@ -0,0 +1,7 @@ +package bpjs + +var O BpjsCfg = BpjsCfg{} + +type BpjsCfg struct { + BaseUrl string `yaml:"baseUrl"` +} diff --git a/internal/interface/bpjs-handler/bpjs-handler.go b/internal/interface/bpjs-handler/bpjs-handler.go index a3d86116..175bb667 100644 --- a/internal/interface/bpjs-handler/bpjs-handler.go +++ b/internal/interface/bpjs-handler/bpjs-handler.go @@ -4,22 +4,27 @@ import ( "net/http" /******************** main / transaction ********************/ + member "simrs-vx/internal/interface/bpjs-handler/member" + monitoring "simrs-vx/internal/interface/bpjs-handler/monitoring" + reference "simrs-vx/internal/interface/bpjs-handler/reference" + vclaimsep "simrs-vx/internal/interface/bpjs-handler/vclaim-sep" + vclaimsephist "simrs-vx/internal/interface/bpjs-handler/vclaim-sep-hist" + vclaimsepprint "simrs-vx/internal/interface/bpjs-handler/vclaim-sep-print" /******************** actor ********************/ /******************** external ********************/ a "github.com/karincake/apem" + hk "github.com/karincake/hongkue" /******************** infra ********************/ + ibpjs "simrs-vx/internal/infra/bpjs" gs "simrs-vx/internal/infra/gorm-setting" - minio "simrs-vx/internal/infra/minio" - ssdb "simrs-vx/internal/infra/ss-db" /******************** pkg ********************/ cmw "simrs-vx/pkg/cors-manager-mw" lh "simrs-vx/pkg/lang-helper" handlerlogger "simrs-vx/pkg/middleware/handler-logger" - mh "simrs-vx/pkg/minio-helper" zlc "simrs-vx/pkg/zerolog-ctx" /******************** sources ********************/ @@ -33,10 +38,8 @@ func SetRoutes() http.Handler { ///// a.RegisterExtCall(gs.Adjust) a.RegisterExtCall(zlc.Adjust) - a.RegisterExtCall(ssdb.SetInstance) a.RegisterExtCall(lh.Populate) - a.RegisterExtCall(minio.Connect) - a.RegisterExtCall(mh.I.SetClient) + a.RegisterExtCall(ibpjs.SetConfig) a.RegisterExtCall(validation.RegisterValidation) r := http.NewServeMux() @@ -44,6 +47,42 @@ func SetRoutes() http.Handler { /******************** Main ********************/ r.HandleFunc("/", home.Home) + hk.GroupRoutes("/v1/vclaim-sep", r, hk.MapHandlerFunc{ + "POST /": vclaimsep.O.Create, + "PATCH /{id}": vclaimsep.O.Update, + "DELETE /{id}": vclaimsep.O.Delete, + }) + + hk.GroupRoutes("/v1/vclaim-sep-hist", r, hk.MapHandlerFunc{ + "GET /": vclaimsephist.O.GetList, + }) + + hk.GroupRoutes("/v1/vclaim-sep-print", r, hk.MapHandlerFunc{ + "POST /": vclaimsepprint.O.Create, + }) + + hk.GroupRoutes("/v1/reference", r, hk.MapHandlerFunc{ + "GET /province": reference.GetListProvince, + "GET /regency/{provinceCode}": reference.GetListCities, + "GET /district/{regencyCode}": reference.GetListDistrict, + "GET /diagnose/{keyword}": reference.GetListDiagnose, + "GET /diagnose-prb": reference.GetListDiagnosePrb, + "GET /medicine-prb/{keyword}": reference.GetListMedicinePrb, + "GET /unit/{unitCode}": reference.GetListUnit, + "GET /healthcare/{healthcare}/{healthcareType}": reference.GetListHealthcare, + "GET /responsible-doctor/{serviceType}/{serviceDate}/{specialistCode}": reference.GetListDoctor, + }) + + hk.GroupRoutes("/v1/member", r, hk.MapHandlerFunc{ + "GET /bpjs/{cardNumber}/{sepDate}": member.GetListByBpjsNumber, + "GET /nik/{nik}/{sepDate}": member.GetListByNik, + }) + + hk.GroupRoutes("/v1/monitoring", r, hk.MapHandlerFunc{ + "GET /visit/{date}/{serviceType}": monitoring.GetListVisit, + "GET /hist/{cardNumber}/{startDate}/{endDate}": monitoring.GetListHist, + }) + /******************** actor ********************/ /******************** sources ********************/ diff --git a/internal/interface/bpjs-handler/member/handler.go b/internal/interface/bpjs-handler/member/handler.go new file mode 100644 index 00000000..80881ee3 --- /dev/null +++ b/internal/interface/bpjs-handler/member/handler.go @@ -0,0 +1,45 @@ +package member + +import ( + "net/http" + + e "simrs-vx/internal/domain/bpjs-entities/member" + u "simrs-vx/internal/use-case/bpjs-use-case/member" + + d "github.com/karincake/dodol" + rw "github.com/karincake/risoles" +) + +func GetListByBpjsNumber(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + pValue1 := rw.ValidateString(w, "cardNumber", r.PathValue("cardNumber")) + if pValue1 == "" { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "cardNumber is required"}, nil) + } + pValue2 := rw.ValidateString(w, "sepDate", r.PathValue("sepDate")) + if pValue2 == "" { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "sepDate is required"}, nil) + } + dto.ReferenceType = e.RTBpjs + dto.PathValue1 = pValue1 + dto.PathValue2 = pValue2 + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func GetListByNik(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + pValue1 := rw.ValidateString(w, "nik", r.PathValue("nik")) + if pValue1 == "" { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "nik is required"}, nil) + } + pValue2 := rw.ValidateString(w, "sepDate", r.PathValue("sepDate")) + if pValue2 == "" { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "sepDate is required"}, nil) + } + dto.ReferenceType = e.RTNik + dto.PathValue1 = pValue1 + dto.PathValue2 = pValue2 + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/bpjs-handler/monitoring/handler.go b/internal/interface/bpjs-handler/monitoring/handler.go new file mode 100644 index 00000000..cf82a5b9 --- /dev/null +++ b/internal/interface/bpjs-handler/monitoring/handler.go @@ -0,0 +1,50 @@ +package monitoring + +import ( + "net/http" + + e "simrs-vx/internal/domain/bpjs-entities/monitoring" + u "simrs-vx/internal/use-case/bpjs-use-case/monitoring" + + d "github.com/karincake/dodol" + rw "github.com/karincake/risoles" +) + +func GetListVisit(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + pValue1 := rw.ValidateString(w, "date", r.PathValue("date")) + if pValue1 == "" { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "date is required"}, nil) + } + pValue2 := rw.ValidateString(w, "serviceType", r.PathValue("serviceType")) + if pValue2 == "" { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "serviceType is required"}, nil) + } + dto.ReferenceType = e.RTVisit + dto.PathValue1 = pValue1 + dto.PathValue2 = pValue2 + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func GetListHist(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + pValue1 := rw.ValidateString(w, "cardNumber", r.PathValue("cardNumber")) + if pValue1 == "" { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "cardNumber is required"}, nil) + } + pValue2 := rw.ValidateString(w, "startDate", r.PathValue("startDate")) + if pValue2 == "" { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "startDate is required"}, nil) + } + pValue3 := rw.ValidateString(w, "endDate", r.PathValue("endDate")) + if pValue3 == "" { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "endDate is required"}, nil) + } + dto.ReferenceType = e.RTHist + dto.PathValue1 = pValue1 + dto.PathValue2 = pValue2 + dto.PathValue3 = pValue3 + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/bpjs-handler/reference/handler.go b/internal/interface/bpjs-handler/reference/handler.go new file mode 100644 index 00000000..fb972af1 --- /dev/null +++ b/internal/interface/bpjs-handler/reference/handler.go @@ -0,0 +1,124 @@ +package reference + +import ( + "net/http" + + e "simrs-vx/internal/domain/bpjs-entities/reference" + u "simrs-vx/internal/use-case/bpjs-use-case/reference" + + d "github.com/karincake/dodol" + rw "github.com/karincake/risoles" +) + +func GetListProvince(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + dto.ReferenceType = e.RTProvince + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func GetListCities(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + pValue := rw.ValidateString(w, "provinceCode", r.PathValue("provinceCode")) + if pValue == "" { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "provinceCode is required"}, nil) + } + dto.ReferenceType = e.RTCities + dto.PathValue1 = pValue + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func GetListDistrict(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + pValue := rw.ValidateString(w, "regencyCode", r.PathValue("regencyCode")) + if pValue == "" { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "regencyCode is required"}, nil) + } + dto.ReferenceType = e.RTDistrict + dto.PathValue1 = pValue + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func GetListDiagnose(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + pValue := rw.ValidateString(w, "keyword", r.PathValue("keyword")) + if pValue == "" { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "keyword is required"}, nil) + } + dto.ReferenceType = e.RTDiagnose + dto.PathValue1 = pValue + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func GetListDiagnosePrb(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + dto.ReferenceType = e.RTDiagnosePrb + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func GetListMedicinePrb(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + pValue := rw.ValidateString(w, "keyword", r.PathValue("keyword")) + if pValue == "" { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "keyword is required"}, nil) + } + dto.ReferenceType = e.RTMedicinePrb + dto.PathValue1 = pValue + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func GetListUnit(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + pValue := rw.ValidateString(w, "unitCode", r.PathValue("unitCode")) + if pValue == "" { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "unitCode is required"}, nil) + } + dto.ReferenceType = e.RTUnit + dto.PathValue1 = pValue + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func GetListHealthcare(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + pValue1 := rw.ValidateString(w, "healthcare", r.PathValue("healthcare")) + if pValue1 == "" { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "healthcare is required"}, nil) + } + pValue2 := rw.ValidateString(w, "healthcareType", r.PathValue("healthcareType")) + if pValue2 == "" { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "healthcareType is required"}, nil) + } + dto.ReferenceType = e.RTHealthcare + dto.PathValue1 = pValue1 + dto.PathValue2 = pValue2 + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func GetListDoctor(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + pValue1 := rw.ValidateString(w, "serviceType", r.PathValue("serviceType")) + if pValue1 == "" { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "serviceType is required"}, nil) + } + pValue2 := rw.ValidateString(w, "serviceDate", r.PathValue("serviceDate")) + if pValue2 == "" { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "serviceDate is required"}, nil) + } + pValue3 := rw.ValidateString(w, "specialistCode", r.PathValue("specialistCode")) + if pValue3 == "" { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "specialistCode is required"}, nil) + } + dto.PathValue1 = pValue1 + dto.PathValue2 = pValue2 + dto.PathValue3 = pValue3 + dto.ReferenceType = e.RTDoctor + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/bpjs-handler/vclaim-sep-hist/handler.go b/internal/interface/bpjs-handler/vclaim-sep-hist/handler.go new file mode 100644 index 00000000..73c2c4e2 --- /dev/null +++ b/internal/interface/bpjs-handler/vclaim-sep-hist/handler.go @@ -0,0 +1,22 @@ +package vclaimsephist + +import ( + "net/http" + + e "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-hist" + u "simrs-vx/internal/use-case/bpjs-use-case/vclaim-sep-hist" + + rw "github.com/karincake/risoles" + sf "github.com/karincake/semprit" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + sf.UrlQueryParam(&dto, *r.URL) + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/bpjs-handler/vclaim-sep-print/handler.go b/internal/interface/bpjs-handler/vclaim-sep-print/handler.go new file mode 100644 index 00000000..838bc65b --- /dev/null +++ b/internal/interface/bpjs-handler/vclaim-sep-print/handler.go @@ -0,0 +1,23 @@ +package vclaimsepprint + +import ( + "net/http" + + e "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-print" + u "simrs-vx/internal/use-case/bpjs-use-case/vclaim-sep-print" + + rw "github.com/karincake/risoles" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.CreateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/bpjs-handler/vclaim-sep/handler.go b/internal/interface/bpjs-handler/vclaim-sep/handler.go new file mode 100644 index 00000000..d40c76e9 --- /dev/null +++ b/internal/interface/bpjs-handler/vclaim-sep/handler.go @@ -0,0 +1,73 @@ +package vclaimsep + +import ( + "io" + "net/http" + + rw "github.com/karincake/risoles" + + e "simrs-vx/internal/domain/bpjs-entities/vclaim-sep" + u "simrs-vx/internal/use-case/bpjs-use-case/vclaim-sep" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.CreateDto{} + body, err := io.ReadAll(r.Body) + if err != nil { + http.Error(w, "failed to read body", http.StatusBadRequest) + return + } + defer r.Body.Close() + + dto.RequestPayload = body + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} + +// func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { +// dto := e.ReadListDto{} +// sf.UrlQueryParam(&dto, *r.URL) +// res, err := u.ReadList(dto) +// rw.DataResponse(w, res, err) +// } + +// func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { +// id := rw.ValidateInt(w, "id", r.PathValue("id")) +// if id <= 0 { +// return +// } +// dto := e.ReadDetailDto{} +// dto.Id = uint(id) +// res, err := u.ReadDetail(dto) +// rw.DataResponse(w, res, err) +// } + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + number := rw.ValidateString(w, "number", r.PathValue("number")) + if number != "" { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Number = &number + res, err := u.Update(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { + number := rw.ValidateString(w, "number", r.PathValue("number")) + if number != "" { + return + } + dto := e.DeleteDto{} + dto.Number = &number + res, err := u.Delete(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/main-handler/encounter/handler.go b/internal/interface/main-handler/encounter/handler.go index 3c0d2da4..96063298 100644 --- a/internal/interface/main-handler/encounter/handler.go +++ b/internal/interface/main-handler/encounter/handler.go @@ -12,6 +12,10 @@ import ( u "simrs-vx/internal/use-case/main-use-case/encounter" erc "simrs-vx/internal/domain/references/common" + + pa "simrs-vx/pkg/auth-helper" + + d "github.com/karincake/dodol" ) type myBase struct{} @@ -19,10 +23,15 @@ type myBase struct{} var O myBase func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + authInfo, err := pa.GetAuthInfo(r) + if err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil) + } dto := e.CreateDto{} if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { return } + dto.AuthInfo = *authInfo res, err := u.Create(dto) rw.DataResponse(w, res, err) } @@ -40,6 +49,7 @@ func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { return } dto := e.ReadDetailDto{} + sf.UrlQueryParam(&dto, *r.URL) dto.Id = uint16(id) res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index 4e0acd0b..2b7ff784 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -39,6 +39,7 @@ import ( person "simrs-vx/internal/interface/main-handler/person" personaddress "simrs-vx/internal/interface/main-handler/person-address" personcontact "simrs-vx/internal/interface/main-handler/person-contact" + personinsurance "simrs-vx/internal/interface/main-handler/person-insurance" pharmacist "simrs-vx/internal/interface/main-handler/pharmacist" user "simrs-vx/internal/interface/main-handler/user" @@ -116,7 +117,6 @@ func SetRoutes() http.Handler { r.HandleFunc("/", home.Home) r.HandleFunc("POST /v1/authentication/login", auth.Login) - // r.HandleFunc("POST /v1/authentication/logout", auth.Logout) hk.Route("POST /v1/authentication/logout", r, auth.GuardMW, auth.Logout) hc.RegCrud(r, "/v1/practice-schedule", practiceschedule.O) hc.RegCrud(r, "/v1/counter", counter.O) @@ -162,7 +162,7 @@ func SetRoutes() http.Handler { "DELETE /{id}": mcuordersubitem.O.Delete, "PATCH /{id}/complete": mcuordersubitem.O.Complete, }) - hk.GroupRoutes("/v1/encounter", r, hk.MapHandlerFunc{ + hk.GroupRoutes("/v1/encounter", r, auth.GuardMW, hk.MapHandlerFunc{ "GET /": encounter.O.GetList, "GET /{id}": encounter.O.GetDetail, "POST /": encounter.O.Create, @@ -244,6 +244,7 @@ func SetRoutes() http.Handler { hc.RegCrud(r, "/v1/person", person.O) hc.RegCrud(r, "/v1/person-address", personaddress.O) hc.RegCrud(r, "/v1/person-contact", personcontact.O) + hc.RegCrud(r, "/v1/person-insurance", personinsurance.O) hc.RegCrud(r, "/v1/employee", employee.O) hc.RegCrud(r, "/v1/doctor", doctor.O) hc.RegCrud(r, "/v1/nurse", nurse.O) @@ -259,13 +260,14 @@ func SetRoutes() http.Handler { "PATCH /{id}/active": user.O.Active, }) hk.GroupRoutes("/v1/patient", r, hk.MapHandlerFunc{ - "GET /": patient.O.GetList, - "GET /{id}": patient.O.GetDetail, - "POST /": patient.O.Create, - "PATCH /{id}": patient.O.Update, - "DELETE /{id}": patient.O.Delete, - "GET /by-identifier": patient.O.Search, - "POST /{id}/upload": patient.O.Upload, + "GET /": patient.O.GetList, + "GET /{id}": patient.O.GetDetail, + "POST /": patient.O.Create, + "PATCH /{id}": patient.O.Update, + "DELETE /{id}": patient.O.Delete, + "GET /search/{keyword}": patient.O.Search, + "GET /by-resident-identity": patient.O.SearchByResidentIdentity, + "POST /{id}/upload": patient.O.Upload, }) /******************** sources ********************/ diff --git a/internal/interface/main-handler/patient/handler.go b/internal/interface/main-handler/patient/handler.go index 1bcdacee..2c5fcb5b 100644 --- a/internal/interface/main-handler/patient/handler.go +++ b/internal/interface/main-handler/patient/handler.go @@ -12,6 +12,8 @@ import ( u "simrs-vx/internal/use-case/main-use-case/patient" ere "simrs-vx/internal/domain/references/encounter" + + d "github.com/karincake/dodol" ) type myBase struct{} @@ -73,8 +75,21 @@ func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { } func (obj myBase) Search(w http.ResponseWriter, r *http.Request) { + dto := e.SearchDto{} + keyword := rw.ValidateString(w, "keyword", r.PathValue("keyword")) + if keyword == "" { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "keyword is required"}, nil) + } + dto.Mode = e.SMIdent + dto.Search = keyword + res, err := u.Search(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) SearchByResidentIdentity(w http.ResponseWriter, r *http.Request) { dto := e.SearchDto{} sf.UrlQueryParam(&dto, *r.URL) + dto.Mode = e.SMNik res, err := u.Search(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-handler/person-insurance/handler.go b/internal/interface/main-handler/person-insurance/handler.go new file mode 100644 index 00000000..d5e42f7b --- /dev/null +++ b/internal/interface/main-handler/person-insurance/handler.go @@ -0,0 +1,71 @@ +package personinsurance + +import ( + "net/http" + + rw "github.com/karincake/risoles" + sf "github.com/karincake/semprit" + + // ua "github.com/karincake/tumpeng/auth/svc" + + e "simrs-vx/internal/domain/main-entities/person-insurance" + u "simrs-vx/internal/use-case/main-use-case/person-insurance" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.CreateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + sf.UrlQueryParam(&dto, *r.URL) + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + dto := e.ReadDetailDto{} + dto.Id = uint16(id) + res, err := u.ReadDetail(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Id = uint16(id) + res, err := u.Update(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.DeleteDto{} + dto.Id = uint16(id) + res, err := u.Delete(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/migration/main-entities.go b/internal/interface/migration/main-entities.go index ae155e9c..131b2972 100644 --- a/internal/interface/migration/main-entities.go +++ b/internal/interface/migration/main-entities.go @@ -25,6 +25,7 @@ import ( inpatient "simrs-vx/internal/domain/main-entities/inpatient" installation "simrs-vx/internal/domain/main-entities/installation" insurancecompany "simrs-vx/internal/domain/main-entities/insurance-company" + intern "simrs-vx/internal/domain/main-entities/intern" internalreference "simrs-vx/internal/domain/main-entities/internal-reference" item "simrs-vx/internal/domain/main-entities/item" itemprice "simrs-vx/internal/domain/main-entities/item-price" @@ -105,6 +106,7 @@ func getMainEntities() []any { &diagnosesrc.DiagnoseSrc{}, &proceduresrc.ProcedureSrc{}, &employee.Employee{}, + &intern.Intern{}, &doctor.Doctor{}, &nurse.Nurse{}, &nutritionist.Nutritionist{}, diff --git a/internal/use-case/bpjs-plugin/member/helper.go b/internal/use-case/bpjs-plugin/member/helper.go new file mode 100644 index 00000000..f5e2bc0e --- /dev/null +++ b/internal/use-case/bpjs-plugin/member/helper.go @@ -0,0 +1,18 @@ +package member + +import ( + "fmt" + e "simrs-vx/internal/domain/bpjs-entities/member" + ibpjs "simrs-vx/internal/infra/bpjs" +) + +func endpointMapper(input *e.ReadListDto) string { + switch input.ReferenceType { + case e.RTBpjs: + return fmt.Sprintf("%speserta/nokartu?noKartu=%s&tglpelayanan=%s", ibpjs.O.BaseUrl, input.PathValue1, input.PathValue2) + case e.RTNik: + return fmt.Sprintf("%speserta/nik?nik=%s&tglpelayanan=%s", ibpjs.O.BaseUrl, input.PathValue1, input.PathValue2) + default: + return "" + } +} diff --git a/internal/use-case/bpjs-plugin/member/plugin.go b/internal/use-case/bpjs-plugin/member/plugin.go new file mode 100644 index 00000000..7610a5ac --- /dev/null +++ b/internal/use-case/bpjs-plugin/member/plugin.go @@ -0,0 +1,37 @@ +package member + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + e "simrs-vx/internal/domain/bpjs-entities/member" + + "gorm.io/gorm" +) + +func ReadList(input *e.ReadListDto, data *e.Response, tx *gorm.DB) error { + endpoint := endpointMapper(input) + req, err := http.NewRequest("GET", endpoint, nil) + if err != nil { + return err + } + req.Header.Set("Content-Type", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return err + } + + if err := json.Unmarshal(body, &data); err != nil { + return fmt.Errorf("failed to parse response JSON: %w", err) + } + + return nil +} diff --git a/internal/use-case/bpjs-plugin/monitoring/helper.go b/internal/use-case/bpjs-plugin/monitoring/helper.go new file mode 100644 index 00000000..8f6d2c88 --- /dev/null +++ b/internal/use-case/bpjs-plugin/monitoring/helper.go @@ -0,0 +1,18 @@ +package monitoring + +import ( + "fmt" + e "simrs-vx/internal/domain/bpjs-entities/monitoring" + ibpjs "simrs-vx/internal/infra/bpjs" +) + +func endpointMapper(input *e.ReadListDto) string { + switch input.ReferenceType { + case e.RTHist: + return fmt.Sprintf("%smonitoring/history/%s?tglawal=%s&tglakhir=%s", ibpjs.O.BaseUrl, input.PathValue1, input.PathValue2, input.PathValue3) + case e.RTVisit: + return fmt.Sprintf("%smonitoring/kunjungan?tglpelayanan=%s&jnspelayanan=%s", ibpjs.O.BaseUrl, input.PathValue1, input.PathValue2) + default: + return "" + } +} diff --git a/internal/use-case/bpjs-plugin/monitoring/plugin.go b/internal/use-case/bpjs-plugin/monitoring/plugin.go new file mode 100644 index 00000000..2450e4e9 --- /dev/null +++ b/internal/use-case/bpjs-plugin/monitoring/plugin.go @@ -0,0 +1,37 @@ +package monitoring + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + e "simrs-vx/internal/domain/bpjs-entities/monitoring" + + "gorm.io/gorm" +) + +func ReadList(input *e.ReadListDto, data *e.Response, tx *gorm.DB) error { + endpoint := endpointMapper(input) + req, err := http.NewRequest("GET", endpoint, nil) + if err != nil { + return err + } + req.Header.Set("Content-Type", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return err + } + + if err := json.Unmarshal(body, &data); err != nil { + return fmt.Errorf("failed to parse response JSON: %w", err) + } + + return nil +} diff --git a/internal/use-case/bpjs-plugin/reference/helper.go b/internal/use-case/bpjs-plugin/reference/helper.go new file mode 100644 index 00000000..3e87089b --- /dev/null +++ b/internal/use-case/bpjs-plugin/reference/helper.go @@ -0,0 +1,32 @@ +package reference + +import ( + "fmt" + e "simrs-vx/internal/domain/bpjs-entities/reference" + ibpjs "simrs-vx/internal/infra/bpjs" +) + +func endpointMapper(input *e.ReadListDto) string { + switch input.ReferenceType { + case e.RTProvince: + return ibpjs.O.BaseUrl + "provinces" + case e.RTCities: + return ibpjs.O.BaseUrl + "cities/" + input.PathValue1 + case e.RTDistrict: + return ibpjs.O.BaseUrl + "districts/" + input.PathValue1 + case e.RTDiagnose: + return ibpjs.O.BaseUrl + "diagnosa/" + input.PathValue1 + case e.RTDiagnosePrb: + return ibpjs.O.BaseUrl + "diagnosaprb" + case e.RTMedicinePrb: + return ibpjs.O.BaseUrl + "obatprb/" + input.PathValue1 + case e.RTUnit: + return ibpjs.O.BaseUrl + "referensi/poli/" + input.PathValue1 + case e.RTHealthcare: + return fmt.Sprintf("%sreferensi/faskes?faskes=%s&jenis-faskes=%s", ibpjs.O.BaseUrl, input.PathValue1, input.PathValue2) + case e.RTDoctor: + return fmt.Sprintf("%sreferensi/dokter-dpjp?jenis-pelayanan=%s&tgl-pelayanan=%s&kode-spesialis=%s", ibpjs.O.BaseUrl, input.PathValue1, input.PathValue2, input.PathValue3) + default: + return "" + } +} diff --git a/internal/use-case/bpjs-plugin/reference/plugin.go b/internal/use-case/bpjs-plugin/reference/plugin.go new file mode 100644 index 00000000..f4d4098e --- /dev/null +++ b/internal/use-case/bpjs-plugin/reference/plugin.go @@ -0,0 +1,37 @@ +package reference + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + e "simrs-vx/internal/domain/bpjs-entities/reference" + + "gorm.io/gorm" +) + +func ReadList(input *e.ReadListDto, data *e.Response, tx *gorm.DB) error { + endpoint := endpointMapper(input) + req, err := http.NewRequest("GET", endpoint, nil) + if err != nil { + return err + } + req.Header.Set("Content-Type", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return err + } + + if err := json.Unmarshal(body, &data); err != nil { + return fmt.Errorf("failed to parse response JSON: %w", err) + } + + return nil +} diff --git a/internal/use-case/bpjs-plugin/vclaim-sep/plugin.go b/internal/use-case/bpjs-plugin/vclaim-sep/plugin.go new file mode 100644 index 00000000..fd18763f --- /dev/null +++ b/internal/use-case/bpjs-plugin/vclaim-sep/plugin.go @@ -0,0 +1,58 @@ +package vclaimsep + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" + e "simrs-vx/internal/domain/bpjs-entities/vclaim-sep" + + ibpjs "simrs-vx/internal/infra/bpjs" + + "gorm.io/gorm" +) + +func CreateSep(input *e.CreateDto, data *e.VclaimSep, tx *gorm.DB) error { + req, err := http.NewRequest("POST", ibpjs.O.BaseUrl+"/sep", bytes.NewReader(input.RequestPayload)) + if err != nil { + return err + } + req.Header.Set("Content-Type", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return err + } + + var vresp vclaimResponse + if err := json.Unmarshal(body, &vresp); err != nil { + return fmt.Errorf("failed to parse response JSON: %w", err) + } + + msg := vresp.MetaData.Message + + if err := json.Unmarshal(body, data); err != nil { + return fmt.Errorf("failed to unmarshal into VclaimSep: %w", err) + } + + // Save request/response details in DTO for further use + input.VclaimSepHist.RequestPayload = string(input.RequestPayload) + input.VclaimSepHist.ResponseBody = string(body) + input.VclaimSepHist.Message = msg + input.Number = func() *string { + number := "" + if vresp.Response != nil && vresp.Response.Sep != nil { + number = vresp.Response.Sep.NoSep + } + return &number + }() + + return nil +} diff --git a/internal/use-case/bpjs-plugin/vclaim-sep/tycovar.go b/internal/use-case/bpjs-plugin/vclaim-sep/tycovar.go new file mode 100644 index 00000000..f057726e --- /dev/null +++ b/internal/use-case/bpjs-plugin/vclaim-sep/tycovar.go @@ -0,0 +1,12 @@ +package vclaimsep + +type vclaimResponse struct { + MetaData struct { + Message string `json:"message"` + } `json:"metaData"` + Response *struct { + Sep *struct { + NoSep string `json:"noSep"` + } `json:"sep"` + } `json:"response"` +} diff --git a/internal/use-case/bpjs-use-case/member/case.go b/internal/use-case/bpjs-use-case/member/case.go new file mode 100644 index 00000000..7c50ea76 --- /dev/null +++ b/internal/use-case/bpjs-use-case/member/case.go @@ -0,0 +1,50 @@ +package member + +import ( + e "simrs-vx/internal/domain/bpjs-entities/member" + + dg "github.com/karincake/apem/db-gorm-pg" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +const source = "member" + +func ReadList(input e.ReadListDto) (*e.Response, error) { + var data e.Response + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "readList") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadListMiddleware(readListPreMw, &input, &data); err != nil { + return err + } + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadListMiddleware(readListPostMw, &input, &data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &data, nil +} diff --git a/internal/use-case/bpjs-use-case/member/middleware-runner.go b/internal/use-case/bpjs-use-case/member/middleware-runner.go new file mode 100644 index 00000000..71061a1b --- /dev/null +++ b/internal/use-case/bpjs-use-case/member/middleware-runner.go @@ -0,0 +1,42 @@ +package member + +import ( + e "simrs-vx/internal/domain/bpjs-entities/member" + 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, + } +} + +func (me *middlewareRunner) RunReadListMiddleware(middlewares []readListMw, input *e.ReadListDto, data *e.Response) 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 +} diff --git a/internal/use-case/bpjs-use-case/member/middleware.go b/internal/use-case/bpjs-use-case/member/middleware.go new file mode 100644 index 00000000..e2fd5584 --- /dev/null +++ b/internal/use-case/bpjs-use-case/member/middleware.go @@ -0,0 +1,12 @@ +package member + +import ( + pm "simrs-vx/internal/use-case/bpjs-plugin/member" +) + +func init() { + readListPreMw = append(readListPreMw, + readListMw{Name: "readList-member", Func: pm.ReadList}, + ) + +} diff --git a/internal/use-case/bpjs-use-case/member/tycovar.go b/internal/use-case/bpjs-use-case/member/tycovar.go new file mode 100644 index 00000000..7d04363f --- /dev/null +++ b/internal/use-case/bpjs-use-case/member/tycovar.go @@ -0,0 +1,18 @@ +/* +member is peserta +*/ +package member + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/bpjs-entities/member" +) + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.Response, tx *gorm.DB) error +} + +var readListPreMw []readListMw // .. +var readListPostMw []readListMw // .. diff --git a/internal/use-case/bpjs-use-case/monitoring/case.go b/internal/use-case/bpjs-use-case/monitoring/case.go new file mode 100644 index 00000000..43109cca --- /dev/null +++ b/internal/use-case/bpjs-use-case/monitoring/case.go @@ -0,0 +1,50 @@ +package monitoring + +import ( + e "simrs-vx/internal/domain/bpjs-entities/monitoring" + + dg "github.com/karincake/apem/db-gorm-pg" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +const source = "monitoring" + +func ReadList(input e.ReadListDto) (*e.Response, error) { + var data e.Response + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "readList") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadListMiddleware(readListPreMw, &input, &data); err != nil { + return err + } + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadListMiddleware(readListPostMw, &input, &data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &data, nil +} diff --git a/internal/use-case/bpjs-use-case/monitoring/middleware-runner.go b/internal/use-case/bpjs-use-case/monitoring/middleware-runner.go new file mode 100644 index 00000000..49bc5efe --- /dev/null +++ b/internal/use-case/bpjs-use-case/monitoring/middleware-runner.go @@ -0,0 +1,42 @@ +package monitoring + +import ( + e "simrs-vx/internal/domain/bpjs-entities/monitoring" + 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, + } +} + +func (me *middlewareRunner) RunReadListMiddleware(middlewares []readListMw, input *e.ReadListDto, data *e.Response) 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 +} diff --git a/internal/use-case/bpjs-use-case/monitoring/middleware.go b/internal/use-case/bpjs-use-case/monitoring/middleware.go new file mode 100644 index 00000000..d5e77655 --- /dev/null +++ b/internal/use-case/bpjs-use-case/monitoring/middleware.go @@ -0,0 +1,12 @@ +package monitoring + +import ( + pm "simrs-vx/internal/use-case/bpjs-plugin/monitoring" +) + +func init() { + readListPreMw = append(readListPreMw, + readListMw{Name: "readList-monitoring", Func: pm.ReadList}, + ) + +} diff --git a/internal/use-case/bpjs-use-case/monitoring/tycovar.go b/internal/use-case/bpjs-use-case/monitoring/tycovar.go new file mode 100644 index 00000000..463109c7 --- /dev/null +++ b/internal/use-case/bpjs-use-case/monitoring/tycovar.go @@ -0,0 +1,18 @@ +/* +member is peserta +*/ +package monitoring + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/bpjs-entities/monitoring" +) + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.Response, tx *gorm.DB) error +} + +var readListPreMw []readListMw // .. +var readListPostMw []readListMw // .. diff --git a/internal/use-case/bpjs-use-case/reference/case.go b/internal/use-case/bpjs-use-case/reference/case.go new file mode 100644 index 00000000..bc9bb5d6 --- /dev/null +++ b/internal/use-case/bpjs-use-case/reference/case.go @@ -0,0 +1,50 @@ +package reference + +import ( + e "simrs-vx/internal/domain/bpjs-entities/reference" + + dg "github.com/karincake/apem/db-gorm-pg" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +const source = "reference" + +func ReadList(input e.ReadListDto) (*e.Response, error) { + var data e.Response + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "readList") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadListMiddleware(readListPreMw, &input, &data); err != nil { + return err + } + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadListMiddleware(readListPostMw, &input, &data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &data, nil +} diff --git a/internal/use-case/bpjs-use-case/reference/middleware-runner.go b/internal/use-case/bpjs-use-case/reference/middleware-runner.go new file mode 100644 index 00000000..0d13c083 --- /dev/null +++ b/internal/use-case/bpjs-use-case/reference/middleware-runner.go @@ -0,0 +1,42 @@ +package reference + +import ( + e "simrs-vx/internal/domain/bpjs-entities/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, + } +} + +func (me *middlewareRunner) RunReadListMiddleware(middlewares []readListMw, input *e.ReadListDto, data *e.Response) 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 +} diff --git a/internal/use-case/bpjs-use-case/reference/middleware.go b/internal/use-case/bpjs-use-case/reference/middleware.go new file mode 100644 index 00000000..f7680ffd --- /dev/null +++ b/internal/use-case/bpjs-use-case/reference/middleware.go @@ -0,0 +1,12 @@ +package reference + +import ( + pr "simrs-vx/internal/use-case/bpjs-plugin/reference" +) + +func init() { + readListPreMw = append(readListPreMw, + readListMw{Name: "readList-reference", Func: pr.ReadList}, + ) + +} diff --git a/internal/use-case/bpjs-use-case/reference/tycovar.go b/internal/use-case/bpjs-use-case/reference/tycovar.go new file mode 100644 index 00000000..51df4160 --- /dev/null +++ b/internal/use-case/bpjs-use-case/reference/tycovar.go @@ -0,0 +1,23 @@ +/* +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 reference + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/bpjs-entities/reference" +) + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.Response, tx *gorm.DB) error +} + +var readListPreMw []readListMw // .. +var readListPostMw []readListMw // .. diff --git a/internal/use-case/bpjs-use-case/vclaim-sep-hist/case.go b/internal/use-case/bpjs-use-case/vclaim-sep-hist/case.go new file mode 100644 index 00000000..0d2e77d0 --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-sep-hist/case.go @@ -0,0 +1,277 @@ +package vclaimsephist + +import ( + "strconv" + + e "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-hist" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +const source = "vclaim-sep-hist" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.VclaimSepHist{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + err := dg.I.Transaction(func(tx *gorm.DB) error { + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunCreateMiddleware(createPreMw, &input, &data); err != nil { + return err + } + + if resData, err := CreateData(input, &event, tx); err != nil { + return err + } else { + data = *resData + } + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunCreateMiddleware(createPostMw, &input, &data); err != nil { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: data.ToResponse(), + }, nil +} + +func ReadList(input e.ReadListDto) (*d.Data, error) { + var data *e.VclaimSepHist + var dataList []e.VclaimSepHist + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "readList") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadListMiddleware(readListPreMw, &input, data); err != nil { + return err + } + + if dataList, metaList, err = ReadListData(input, &event, tx); err != nil { + return err + } + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadListMiddleware(readListPostMw, &input, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.VclaimSepHist + var err error + + event := pl.Event{ + Feature: "ReadDetail", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "readDetail") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadDetailMiddleware(readDetailPreMw, &input, data); err != nil { + return err + } + + if data, err = ReadDetailData(input, &event, tx); err != nil { + return err + } + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadDetailMiddleware(readDetailPostMw, &input, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "fetched", + }, + Data: data.ToResponse(), + }, nil +} + +func Update(input e.UpdateDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.VclaimSepHist + var err error + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + 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 + } + + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPreMw, &rdDto, data); err != nil { + return err + } + + if err := UpdateData(input, data, &event, tx); err != nil { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: data.ToResponse(), + }, nil + +} + +func Delete(input e.DeleteDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.VclaimSepHist + var err error + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + 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 + } + + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunDeleteMiddleware(readDetailPreMw, &rdDto, data); err != nil { + return err + } + + if err := DeleteData(data, &event, tx); err != nil { + return err + } + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunDeleteMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + Data: data.ToResponse(), + }, nil + +} diff --git a/internal/use-case/bpjs-use-case/vclaim-sep-hist/helper.go b/internal/use-case/bpjs-use-case/vclaim-sep-hist/helper.go new file mode 100644 index 00000000..038983bb --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-sep-hist/helper.go @@ -0,0 +1,23 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package vclaimsephist + +import ( + e "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-hist" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.VclaimSepHist) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.RequestPayload = &inputSrc.RequestPayload + data.ResponseBody = &inputSrc.ResponseBody + data.Message = &inputSrc.Message +} diff --git a/internal/use-case/bpjs-use-case/vclaim-sep-hist/lib.go b/internal/use-case/bpjs-use-case/vclaim-sep-hist/lib.go new file mode 100644 index 00000000..13104e36 --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-sep-hist/lib.go @@ -0,0 +1,140 @@ +package vclaimsephist + +import ( + e "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-hist" + + plh "simrs-vx/pkg/lib-helper" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + gh "github.com/karincake/getuk" + "gorm.io/gorm" +) + +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.VclaimSepHist, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.VclaimSepHist{} + setData(&input, &data) + + 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(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.VclaimSepHist, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.VclaimSepHist{} + pagination := gh.Pagination{} + count := int64(0) + meta := e.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&e.VclaimSepHist{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Scopes(gh.Sort(input.Sort)) + + if err := tx.Find(&data).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, &meta, nil + } + return nil, nil, plh.HandleListError(input, event, err) + } + + meta.Count = int(count) + meta.PageNumber = pagination.PageNumber + meta.PageSize = pagination.PageSize + + pl.SetLogInfo(event, nil, "complete") + return data, &meta, nil +} + +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.VclaimSepHist, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.VclaimSepHist{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if err := tx.First(&data, input.Id).Error; err != nil { + if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { + return nil, processedErr + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateData(input e.UpdateDto, data *e.VclaimSepHist, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBUpdate") + setData(&input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 DeleteData(data *e.VclaimSepHist, 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 +} diff --git a/internal/use-case/bpjs-use-case/vclaim-sep-hist/middleware-runner.go b/internal/use-case/bpjs-use-case/vclaim-sep-hist/middleware-runner.go new file mode 100644 index 00000000..315a358e --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-sep-hist/middleware-runner.go @@ -0,0 +1,103 @@ +package vclaimsephist + +import ( + e "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-hist" + 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.VclaimSepHist) 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.VclaimSepHist) 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.VclaimSepHist) 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.VclaimSepHist) 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.VclaimSepHist) 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 +} diff --git a/internal/use-case/bpjs-use-case/vclaim-sep-hist/middleware.go b/internal/use-case/bpjs-use-case/vclaim-sep-hist/middleware.go new file mode 100644 index 00000000..16cf95b9 --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-sep-hist/middleware.go @@ -0,0 +1,9 @@ +package vclaimsephist + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } diff --git a/internal/use-case/bpjs-use-case/vclaim-sep-hist/tycovar.go b/internal/use-case/bpjs-use-case/vclaim-sep-hist/tycovar.go new file mode 100644 index 00000000..f525303a --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-sep-hist/tycovar.go @@ -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 vclaimsephist + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-hist" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.VclaimSepHist, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.VclaimSepHist, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.VclaimSepHist, 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 diff --git a/internal/use-case/bpjs-use-case/vclaim-sep-print/case.go b/internal/use-case/bpjs-use-case/vclaim-sep-print/case.go new file mode 100644 index 00000000..e1f26e10 --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-sep-print/case.go @@ -0,0 +1,277 @@ +package vclaimsepprint + +import ( + "strconv" + + e "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-print" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +const source = "vclaim-sep-print" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.VclaimSepPrint{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + err := dg.I.Transaction(func(tx *gorm.DB) error { + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunCreateMiddleware(createPreMw, &input, &data); err != nil { + return err + } + + if resData, err := CreateData(input, &event, tx); err != nil { + return err + } else { + data = *resData + } + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunCreateMiddleware(createPostMw, &input, &data); err != nil { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: data.ToResponse(), + }, nil +} + +func ReadList(input e.ReadListDto) (*d.Data, error) { + var data *e.VclaimSepPrint + var dataList []e.VclaimSepPrint + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "readList") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadListMiddleware(readListPreMw, &input, data); err != nil { + return err + } + + if dataList, metaList, err = ReadListData(input, &event, tx); err != nil { + return err + } + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadListMiddleware(readListPostMw, &input, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.VclaimSepPrint + var err error + + event := pl.Event{ + Feature: "ReadDetail", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "readDetail") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadDetailMiddleware(readDetailPreMw, &input, data); err != nil { + return err + } + + if data, err = ReadDetailData(input, &event, tx); err != nil { + return err + } + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadDetailMiddleware(readDetailPostMw, &input, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "fetched", + }, + Data: data.ToResponse(), + }, nil +} + +func Update(input e.UpdateDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.VclaimSepPrint + var err error + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + 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 + } + + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPreMw, &rdDto, data); err != nil { + return err + } + + if err := UpdateData(input, data, &event, tx); err != nil { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: data.ToResponse(), + }, nil + +} + +func Delete(input e.DeleteDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.VclaimSepPrint + var err error + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + 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 + } + + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunDeleteMiddleware(readDetailPreMw, &rdDto, data); err != nil { + return err + } + + if err := DeleteData(data, &event, tx); err != nil { + return err + } + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunDeleteMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + Data: data.ToResponse(), + }, nil + +} diff --git a/internal/use-case/bpjs-use-case/vclaim-sep-print/helper.go b/internal/use-case/bpjs-use-case/vclaim-sep-print/helper.go new file mode 100644 index 00000000..5a89f7a9 --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-sep-print/helper.go @@ -0,0 +1,21 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package vclaimsepprint + +import ( + e "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-print" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.VclaimSepPrint) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.VclaimSep_Number = inputSrc.VclaimSep_Number +} diff --git a/internal/use-case/bpjs-use-case/vclaim-sep-print/lib.go b/internal/use-case/bpjs-use-case/vclaim-sep-print/lib.go new file mode 100644 index 00000000..12bdad69 --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-sep-print/lib.go @@ -0,0 +1,148 @@ +package vclaimsepprint + +import ( + e "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-print" + + plh "simrs-vx/pkg/lib-helper" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + gh "github.com/karincake/getuk" + "gorm.io/gorm" +) + +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.VclaimSepPrint, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.VclaimSepPrint{} + var maxCounter uint + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + err := tx.Model(&data). + Where("VclaimSep_Number = ?", input.VclaimSep_Number). + Select("COALESCE(MAX(Counter), 0)"). + Scan(&maxCounter).Error + if err != nil { + return nil, err + } + + if err := tx.Create(&data).Error; err != nil { + return nil, plh.HandleCreateError(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.VclaimSepPrint, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.VclaimSepPrint{} + pagination := gh.Pagination{} + count := int64(0) + meta := e.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&e.VclaimSepPrint{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Scopes(gh.Sort(input.Sort)) + + if err := tx.Find(&data).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, &meta, nil + } + return nil, nil, plh.HandleListError(input, event, err) + } + + meta.Count = int(count) + meta.PageNumber = pagination.PageNumber + meta.PageSize = pagination.PageSize + + pl.SetLogInfo(event, nil, "complete") + return data, &meta, nil +} + +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.VclaimSepPrint, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.VclaimSepPrint{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if err := tx.First(&data, input.Id).Error; err != nil { + if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { + return nil, processedErr + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateData(input e.UpdateDto, data *e.VclaimSepPrint, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBUpdate") + setData(&input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 DeleteData(data *e.VclaimSepPrint, 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 +} diff --git a/internal/use-case/bpjs-use-case/vclaim-sep-print/middleware-runner.go b/internal/use-case/bpjs-use-case/vclaim-sep-print/middleware-runner.go new file mode 100644 index 00000000..47db3773 --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-sep-print/middleware-runner.go @@ -0,0 +1,103 @@ +package vclaimsepprint + +import ( + e "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-print" + 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.VclaimSepPrint) 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.VclaimSepPrint) 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.VclaimSepPrint) 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.VclaimSepPrint) 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.VclaimSepPrint) 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 +} diff --git a/internal/use-case/bpjs-use-case/vclaim-sep-print/middleware.go b/internal/use-case/bpjs-use-case/vclaim-sep-print/middleware.go new file mode 100644 index 00000000..ae857af4 --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-sep-print/middleware.go @@ -0,0 +1,9 @@ +package vclaimsepprint + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } diff --git a/internal/use-case/bpjs-use-case/vclaim-sep-print/tycovar.go b/internal/use-case/bpjs-use-case/vclaim-sep-print/tycovar.go new file mode 100644 index 00000000..9566a7e0 --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-sep-print/tycovar.go @@ -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 vclaimsepprint + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-print" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.VclaimSepPrint, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.VclaimSepPrint, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.VclaimSepPrint, 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 diff --git a/internal/use-case/bpjs-use-case/vclaim-sep/case.go b/internal/use-case/bpjs-use-case/vclaim-sep/case.go new file mode 100644 index 00000000..ac72d648 --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-sep/case.go @@ -0,0 +1,288 @@ +package vclaimsep + +import ( + "strconv" + + e "simrs-vx/internal/domain/bpjs-entities/vclaim-sep" + // evsh "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-hist" + + uvsh "simrs-vx/internal/use-case/bpjs-use-case/vclaim-sep-hist" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +const source = "vclaim-sep" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.VclaimSep{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + err := dg.I.Transaction(func(tx *gorm.DB) error { + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunCreateMiddleware(createPreMw, &input, &data); err != nil { + return err + } + + if _, err := uvsh.CreateData(input.VclaimSepHist, &event, tx); err != nil { + return err + } + + if !input.IsMessageSuccess() { + return nil + } + + if resData, err := CreateData(input, &event, tx); err != nil { + return err + } else { + data = *resData + } + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunCreateMiddleware(createPostMw, &input, &data); err != nil { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: data.ToResponse(), + }, nil +} + +func ReadList(input e.ReadListDto) (*d.Data, error) { + var data *e.VclaimSep + var dataList []e.VclaimSep + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "readList") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadListMiddleware(readListPreMw, &input, data); err != nil { + return err + } + + if dataList, metaList, err = ReadListData(input, &event, tx); err != nil { + return err + } + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadListMiddleware(readListPostMw, &input, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.VclaimSep + var err error + + event := pl.Event{ + Feature: "ReadDetail", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "readDetail") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadDetailMiddleware(readDetailPreMw, &input, data); err != nil { + return err + } + + if data, err = ReadDetailData(input, &event, tx); err != nil { + return err + } + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadDetailMiddleware(readDetailPostMw, &input, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "fetched", + }, + Data: data.ToResponse(), + }, nil +} + +func Update(input e.UpdateDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Number: input.Number} + var data *e.VclaimSep + var err error + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + 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 + } + + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPreMw, &rdDto, data); err != nil { + return err + } + + if err := UpdateData(input, data, &event, tx); err != nil { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: data.ToResponse(), + }, nil + +} + +func Delete(input e.DeleteDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Number: input.Number} + var data *e.VclaimSep + var err error + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + 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 + } + + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunDeleteMiddleware(readDetailPreMw, &rdDto, data); err != nil { + return err + } + + if err := DeleteData(data, &event, tx); err != nil { + return err + } + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunDeleteMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + Data: data.ToResponse(), + }, nil + +} diff --git a/internal/use-case/bpjs-use-case/vclaim-sep/helper.go b/internal/use-case/bpjs-use-case/vclaim-sep/helper.go new file mode 100644 index 00000000..7760d854 --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-sep/helper.go @@ -0,0 +1,22 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package vclaimsep + +import ( + e "simrs-vx/internal/domain/bpjs-entities/vclaim-sep" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.VclaimSep) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.Encounter_Id = inputSrc.Encounter_Id + data.Number = inputSrc.Number +} diff --git a/internal/use-case/bpjs-use-case/vclaim-sep/lib.go b/internal/use-case/bpjs-use-case/vclaim-sep/lib.go new file mode 100644 index 00000000..817c357c --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-sep/lib.go @@ -0,0 +1,147 @@ +package vclaimsep + +import ( + e "simrs-vx/internal/domain/bpjs-entities/vclaim-sep" + + plh "simrs-vx/pkg/lib-helper" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + gh "github.com/karincake/getuk" + "gorm.io/gorm" +) + +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.VclaimSep, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.VclaimSep{} + setData(&input, &data) + + 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(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.VclaimSep, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.VclaimSep{} + pagination := gh.Pagination{} + count := int64(0) + meta := e.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&e.VclaimSep{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Scopes(gh.Sort(input.Sort)) + + if err := tx.Find(&data).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, &meta, nil + } + return nil, nil, plh.HandleListError(input, event, err) + } + + meta.Count = int(count) + meta.PageNumber = pagination.PageNumber + meta.PageSize = pagination.PageSize + + pl.SetLogInfo(event, nil, "complete") + return data, &meta, nil +} + +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.VclaimSep, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.VclaimSep{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if input.Number != nil { + tx = tx.Where("\"Number\" = ?", *input.Number) + } + if input.Id != 0 { + tx = tx.Where("\"Id\" = ?", input.Id) + } + + if err := tx.First(&data).Error; err != nil { + if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { + return nil, processedErr + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateData(input e.UpdateDto, data *e.VclaimSep, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBUpdate") + setData(&input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 DeleteData(data *e.VclaimSep, 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 +} diff --git a/internal/use-case/bpjs-use-case/vclaim-sep/middleware-runner.go b/internal/use-case/bpjs-use-case/vclaim-sep/middleware-runner.go new file mode 100644 index 00000000..dee35276 --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-sep/middleware-runner.go @@ -0,0 +1,103 @@ +package vclaimsep + +import ( + e "simrs-vx/internal/domain/bpjs-entities/vclaim-sep" + 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.VclaimSep) 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.VclaimSep) 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.VclaimSep) 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.VclaimSep) 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.VclaimSep) 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 +} diff --git a/internal/use-case/bpjs-use-case/vclaim-sep/middleware.go b/internal/use-case/bpjs-use-case/vclaim-sep/middleware.go new file mode 100644 index 00000000..1ad0a853 --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-sep/middleware.go @@ -0,0 +1,13 @@ +package vclaimsep + +import ( + pvs "simrs-vx/internal/use-case/bpjs-plugin/vclaim-sep" +) + +// example of middleware +func init() { + createPreMw = append(createPreMw, + createMw{Name: "create-sep", Func: pvs.CreateSep}, + ) + +} diff --git a/internal/use-case/bpjs-use-case/vclaim-sep/tycovar.go b/internal/use-case/bpjs-use-case/vclaim-sep/tycovar.go new file mode 100644 index 00000000..932bc355 --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-sep/tycovar.go @@ -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 vclaimsep + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/bpjs-entities/vclaim-sep" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.VclaimSep, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.VclaimSep, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.VclaimSep, 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 diff --git a/internal/use-case/main-use-case/authentication/case.go b/internal/use-case/main-use-case/authentication/case.go index b6e9f2f4..ffefa7ef 100644 --- a/internal/use-case/main-use-case/authentication/case.go +++ b/internal/use-case/main-use-case/authentication/case.go @@ -10,13 +10,19 @@ import ( "github.com/golang-jwt/jwt" "github.com/google/uuid" + "simrs-vx/internal/domain/main-entities/intern" eu "simrs-vx/internal/domain/main-entities/user" - erc "simrs-vx/internal/domain/references/common" pa "simrs-vx/pkg/auth-helper" el "simrs-vx/pkg/logger" p "simrs-vx/pkg/password" + ed "simrs-vx/internal/domain/main-entities/doctor" + ee "simrs-vx/internal/domain/main-entities/employee" + en "simrs-vx/internal/domain/main-entities/nurse" + erc "simrs-vx/internal/domain/references/common" + erg "simrs-vx/internal/domain/references/organization" + a "github.com/karincake/apem" dg "github.com/karincake/apem/db-gorm-pg" ms "github.com/karincake/apem/ms-redis" @@ -72,11 +78,6 @@ func GenToken(input eu.LoginDto) (*d.Data, error) { return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-login-unverified", Message: el.GenMessage("auth-login-unverified")}} } - userDivisionPositions, err := getDivisionPosition(user.Id) - if err != nil { - return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-getData-failed", Message: el.GenMessage("auth-getData-failed")}} - } - // Access token prep id, err := uuid.NewRandom() if err != nil { @@ -90,19 +91,94 @@ func GenToken(input eu.LoginDto) (*d.Data, error) { atExpires := time.Now().Add(duration).Unix() atSecretKey := authCfg.AtSecretKey - // Creating Access Token + // Create Claim atClaims := jwt.MapClaims{} atClaims["user_id"] = user.Id atClaims["user_name"] = user.Name - atClaims["user_position_code"] = user.Position_Code - atClaims["exp"] = atExpires + atClaims["user_contractPosition_code"] = user.ContractPosition_Code atClaims["uuid"] = aUuid - atClaims["user_division_positions"] = userDivisionPositions + atClaims["exp"] = atExpires + + // Create output + outputData := d.II{ + "user_id": strconv.Itoa(int(user.Id)), + "user_name": user.Name, + "user_contractPosition_code": user.ContractPosition_Code, + } + + // extra + role := []string{} + switch user.ContractPosition_Code { + case erg.CSCEmp: + // employee + employee := ee.Employee{} + dg.I.Where("\"User_Id\" = ?", user.Id).First(&employee) + if employee.Id == 0 { + return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noEmployee", Message: el.GenMessage("auth-noEmployee")}} + } + atClaims["employee_id"] = employee.Id + outputData["employee_id"] = employee.Id + role = append(role, "emp-"+string(*employee.Position_Code)) + + if employee.Division_Code != nil { + atClaims["employee_division_code"] = employee.Division_Code + outputData["employee_division_code"] = employee.Division_Code + } + + // employee position + if employee.Id > 0 && employee.Position_Code != nil { + switch *employee.Position_Code { + case erg.EPCDoc: + doctor := ed.Doctor{} + dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&doctor) + if doctor.Id == 0 { + return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noDoctor", Message: el.GenMessage("auth-noDoctor")}} + } + atClaims["doctor_id"] = doctor.Id + outputData["doctor_id"] = doctor.Id + + // specialist + if doctor.Specialist_Id != nil { + atClaims["specialist_id"] = doctor.Specialist_Id + outputData["specialist_id"] = doctor.Specialist_Id + } + if doctor.Subspecialist_Id != nil { + atClaims["subspecialist_id"] = doctor.Subspecialist_Id + outputData["subspecialist_id"] = doctor.Subspecialist_Id + } + case erg.EPCNur: + nurse := en.Nurse{} + dg.I.Where("\"Employee_Id\" = ?", employee.Id).First(&nurse) + if nurse.Id == 0 { + return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-noNurse", Message: el.GenMessage("auth-noNurse")}} + } + atClaims["nurse_id"] = nurse.Id + outputData["nurse_id"] = nurse.Id + } + // division position + divsionPositions, err := getDivisionPosition(employee.Id) + if err != nil { + return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-getData-failed", Message: el.GenMessage("auth-getData-failed")}} + } + role = append(role, divsionPositions...) + // atClaims["division_positions"] = divsionPositions + // outputData["division_positions"] = divsionPositions + } + case erg.CSCInt: + intern := intern.Intern{} + dg.I.Where("\"User_Id\" = ?", user.Id).First(&intern) + role = append(role, "int-"+string(*intern.Position_Code)) + } + atClaims["roles"] = role + outputData["roles"] = role + + // Generate jwt at := jwt.NewWithClaims(jwt.SigningMethodHS256, atClaims) ats, err := at.SignedString([]byte(atSecretKey)) if err != nil { return nil, d.FieldErrors{"user": d.FieldError{Code: "token-sign-err", Message: el.GenMessage("token-sign-err")}} } + outputData["accessToken"] = ats // Save to redis now := time.Now() @@ -125,13 +201,7 @@ func GenToken(input eu.LoginDto) (*d.Data, error) { "structure": "single-data", "status": "verified", }, - Data: d.II{ - "user_id": strconv.Itoa(int(user.Id)), - "user_name": user.Name, - "user_position_code": user.Position_Code, - "accessToken": ats, - "user_division_positions": userDivisionPositions, - }, + Data: outputData, }, nil } @@ -186,41 +256,41 @@ func ExtractToken(r *http.Request, tokenType TokenType) (data *pa.AuthInfo, err return nil, d.FieldError{Code: "token-unidentified", Message: el.GenMessage("token-unidentified")} } user_name := fmt.Sprintf("%v", claims["user_name"]) + // user_email := "" + // if v, exist := claims["user_email"]; exist && v != nil { + // user_email = v.(string) + // } + // ref_id := 0 + // if v, exist := claims["user_ref_id"]; exist && v != nil { + // tmp := v.(float64) + // ref_id = int(tmp) + // } + // position_code := "" + // if v, exist := claims["user_position_code"]; exist && v != nil { + // position_code = v.(string) + // } + // data = &AuthInfo{ + // Uuid: accessUuid, + // User_Id: int(user_id), + // User_Name: user_name, + // User_Email: user_email, + // User_Ref_Id: ref_id, + // User_Position_Code: position_code, + contractPosition_code := "" + if v, exist := claims["contractPosition_code"]; exist && v != nil { + contractPosition_code = v.(string) + } + employee_position_code := "" + if v, exist := claims["employee_position_code"]; exist && v != nil { + employee_position_code = v.(string) + } - var userDivisionPositions []pa.DivisionPosition - raw := claims["user_division_positions"] - if raw == nil { - fmt.Println("No user_division_positions found in claims") - } else { - list, ok := raw.([]interface{}) - if !ok { - fmt.Printf("user_division_positions is not []interface{}, but %T\n", raw) - } else { - fmt.Printf("Found %d division positions\n", len(list)) - for i, item := range list { - if m, ok := item.(map[string]interface{}); ok { - fmt.Printf("Item %d: %v\n", i, m) - dp := pa.DivisionPosition{ - Division_Code: fmt.Sprintf("%v", m["division_code"]), - DivisionPosition_Code: fmt.Sprintf("%v", m["divisionPosition_code"]), - } - userDivisionPositions = append(userDivisionPositions, dp) - } else { - fmt.Printf("Item %d not map[string]interface{} but %T\n", i, item) - } - } - } - } - position_code := "" - if v, exist := claims["user_position_code"]; exist && v != nil { - position_code = v.(string) - } data = &pa.AuthInfo{ - Uuid: accessUuid, - User_Id: uint(user_id), - User_Name: user_name, - User_Position_Code: position_code, - User_DivisionPositions: userDivisionPositions, + Uuid: accessUuid, + User_Id: uint(user_id), + User_Name: user_name, + User_ContractPosition_code: contractPosition_code, + Employee_Position_Code: &employee_position_code, } return } diff --git a/internal/use-case/main-use-case/authentication/helper.go b/internal/use-case/main-use-case/authentication/helper.go index 50b0c8fd..c4e67200 100644 --- a/internal/use-case/main-use-case/authentication/helper.go +++ b/internal/use-case/main-use-case/authentication/helper.go @@ -1,11 +1,7 @@ package authentication import ( - "errors" edp "simrs-vx/internal/domain/main-entities/division-position" - ee "simrs-vx/internal/domain/main-entities/employee" - - pa "simrs-vx/pkg/auth-helper" dg "github.com/karincake/apem/db-gorm-pg" "gorm.io/gorm" @@ -27,21 +23,21 @@ func getDocName(id uint) string { return "authentication" } -func getDivisionPosition(user_id uint) ([]pa.DivisionPosition, error) { - var result []pa.DivisionPosition +func getDivisionPosition(employee_id uint) ([]string, error) { + var result []string - var employee ee.Employee - if err := dg.I.Where("\"User_Id\" = ?", user_id).First(&employee).Error; err != nil { - if err == gorm.ErrRecordNotFound { - return result, nil - } - return result, errors.New("no employee found") - } + // var employee ee.Employee + // if err := dg.I.Where("\"Employee_Id\" = ?", employee_id).First(&employee).Error; err != nil { + // if err == gorm.ErrRecordNotFound { + // return result, nil + // } + // return result, errors.New("no employee found") + // } var divisionPositions []edp.DivisionPosition err := dg.I. Preload("Division"). - Where("\"Employee_Id\" = ?", employee.Id). + Where("\"Employee_Id\" = ?", employee_id). Find(&divisionPositions).Error if err != nil { if err == gorm.ErrRecordNotFound { @@ -51,15 +47,9 @@ func getDivisionPosition(user_id uint) ([]pa.DivisionPosition, error) { } for _, dp := range divisionPositions { - result = append(result, pa.DivisionPosition{ - Division_Code: func() string { - if dp.Division != nil { - return dp.Division.Code - } - return "" - }(), - DivisionPosition_Code: dp.Code, - }) + if dp.Division != nil { + result = append(result, "div-"+dp.Division.Code+"-"+dp.Code) + } } return result, nil diff --git a/internal/use-case/main-use-case/encounter/case.go b/internal/use-case/main-use-case/encounter/case.go index 453ea6cb..fad183f6 100644 --- a/internal/use-case/main-use-case/encounter/case.go +++ b/internal/use-case/main-use-case/encounter/case.go @@ -7,12 +7,14 @@ import ( ea "simrs-vx/internal/domain/main-entities/ambulatory" ec "simrs-vx/internal/domain/main-entities/chemo" 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" ua "simrs-vx/internal/use-case/main-use-case/ambulatory" uc "simrs-vx/internal/use-case/main-use-case/chemo" 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" erc "simrs-vx/internal/domain/references/common" @@ -48,6 +50,12 @@ func Create(input e.CreateDto) (*d.Data, error) { return err } + if emp, err := uem.ReadDetailData(eem.ReadDetailDto{User_Id: &input.AuthInfo.User_Id}, &event, tx); err != nil { + return err + } else { + input.Adm_Employee_Id = &emp.Id + } + if resData, err := CreateData(input, &event, tx); err != nil { return err } else { diff --git a/internal/use-case/main-use-case/encounter/helper.go b/internal/use-case/main-use-case/encounter/helper.go index 448f7be7..7cb72938 100644 --- a/internal/use-case/main-use-case/encounter/helper.go +++ b/internal/use-case/main-use-case/encounter/helper.go @@ -9,8 +9,10 @@ import ( "fmt" "strings" - e "simrs-vx/internal/domain/main-entities/encounter" - es "simrs-vx/internal/domain/main-entities/soapi" + "gorm.io/gorm" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" edo "simrs-vx/internal/domain/main-entities/device-order" emo "simrs-vx/internal/domain/main-entities/material-order" @@ -23,6 +25,7 @@ import ( epi "simrs-vx/internal/domain/main-entities/prescription-item" // udo "simrs-vx/internal/use-case/main-use-case/device-order" + es "simrs-vx/internal/domain/main-entities/soapi" 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" @@ -30,13 +33,9 @@ import ( up "simrs-vx/internal/use-case/main-use-case/prescription" upi "simrs-vx/internal/use-case/main-use-case/prescription-item" - pl "simrs-vx/pkg/logger" - pu "simrs-vx/pkg/use-case-helper" - + e "simrs-vx/internal/domain/main-entities/encounter" erc "simrs-vx/internal/domain/references/common" - ero "simrs-vx/internal/domain/references/organization" - - "gorm.io/gorm" + erg "simrs-vx/internal/domain/references/organization" ) func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Encounter) { @@ -55,7 +54,13 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Encounter) { data.Specialist_Id = inputSrc.Specialist_Id data.Subspecialist_Id = inputSrc.Subspecialist_Id data.VisitDate = inputSrc.VisitDate + data.PaymentMethod_Code = inputSrc.PaymentMethod_Code + data.InsuranceCompany_Id = inputSrc.InsuranceCompany_Id + data.Member_Number = inputSrc.Member_Number + data.Ref_Number = inputSrc.Ref_Number + data.Trx_Number = inputSrc.Trx_Number data.Appointment_Doctor_Id = inputSrc.Appointment_Doctor_Id + data.Adm_Employee_Id = inputSrc.Adm_Employee_Id data.Responsible_Doctor_Id = inputSrc.Responsible_Doctor_Id data.RefSource_Name = inputSrc.RefSource_Name data.Appointment_Id = inputSrc.Appointment_Id @@ -108,7 +113,7 @@ func checkSoapiByDocExists(encounter_id uint, event *pl.Event, tx *gorm.DB) erro } for _, s := range soapies { - if s.Employee != nil && s.Employee.User != nil && s.Employee.User.Position_Code == ero.UPCDoc { + if s.Employee != nil && *s.Employee.Position_Code == erg.EPCDoc { return nil } } diff --git a/internal/use-case/main-use-case/encounter/lib.go b/internal/use-case/main-use-case/encounter/lib.go index 2f4d69fa..ccc4b811 100644 --- a/internal/use-case/main-use-case/encounter/lib.go +++ b/internal/use-case/main-use-case/encounter/lib.go @@ -81,7 +81,7 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e tx = dg.I } - if err := tx.First(&data, input.Id).Error; err != nil { + if err := tx.Scopes(gh.Preload(input.Includes)).First(&data, input.Id).Error; err != nil { if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { return nil, processedErr } diff --git a/internal/use-case/main-use-case/medical-action-src/case.go b/internal/use-case/main-use-case/medical-action-src/case.go index d3fb840b..cd42766c 100644 --- a/internal/use-case/main-use-case/medical-action-src/case.go +++ b/internal/use-case/main-use-case/medical-action-src/case.go @@ -34,6 +34,9 @@ func Create(input e.CreateDto) (*d.Data, error) { return err } + if err := createItem(&input, &event, tx); err != nil { + return err + } if resData, err := CreateData(input, &event, tx); err != nil { return err } else { diff --git a/internal/use-case/main-use-case/medical-action-src/helper.go b/internal/use-case/main-use-case/medical-action-src/helper.go index 22c0d26d..c955274d 100644 --- a/internal/use-case/main-use-case/medical-action-src/helper.go +++ b/internal/use-case/main-use-case/medical-action-src/helper.go @@ -5,7 +5,17 @@ Any functions that are used internally by the use-case package medicalactionsrc import ( + ei "simrs-vx/internal/domain/main-entities/item" e "simrs-vx/internal/domain/main-entities/medical-action-src" + + ero "simrs-vx/internal/domain/references/organization" + + ui "simrs-vx/internal/use-case/main-use-case/item" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" ) func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.MedicalActionSrc) { @@ -19,5 +29,21 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.MedicalActionSrc) { data.Code = inputSrc.Code data.Name = inputSrc.Name + data.Type_Code = inputSrc.Type_Code data.Item_Id = inputSrc.Item_Id } + +func createItem(input *e.CreateDto, event *pl.Event, tx *gorm.DB) error { + itemCreate := ei.CreateDto{ + Code: pu.AddPrefix("medAct-", input.Code), + Name: input.Name, + ItemGroup_Code: ero.ITGCMedAct, + } + item, err := ui.CreateData(itemCreate, event, tx) + if err != nil { + return err + } + + input.Item_Id = &item.Id + return nil +} diff --git a/internal/use-case/main-use-case/patient/case.go b/internal/use-case/main-use-case/patient/case.go index 9736ee09..fd17d7fb 100644 --- a/internal/use-case/main-use-case/patient/case.go +++ b/internal/use-case/main-use-case/patient/case.go @@ -9,6 +9,7 @@ import ( upe "simrs-vx/internal/use-case/main-use-case/person" upa "simrs-vx/internal/use-case/main-use-case/person-address" upc "simrs-vx/internal/use-case/main-use-case/person-contact" + upi "simrs-vx/internal/use-case/main-use-case/person-insurance" upr "simrs-vx/internal/use-case/main-use-case/person-relative" ere "simrs-vx/internal/domain/references/encounter" @@ -47,6 +48,7 @@ func Create(input e.CreateDto) (*d.Data, error) { } else { input.Person_Id = person_id } + for idx := range input.PersonAddresses { input.PersonAddresses[idx].Person_Id = *input.Person_Id } @@ -68,6 +70,13 @@ func Create(input e.CreateDto) (*d.Data, error) { return err } + for idx := range input.PersonInsurances { + input.PersonInsurances[idx].Person_Id = *input.Person_Id + } + if err := upi.CreateOrUpdateBatch(input.PersonInsurances, &event, tx); err != nil { + return err + } + if resData, err := CreateData(input, &event, tx); err != nil { return err } else { @@ -252,6 +261,13 @@ func Update(input e.UpdateDto) (*d.Data, error) { return err } + for idx := range input.PersonInsurances { + input.PersonInsurances[idx].Person_Id = *input.Person_Id + } + if err := upi.CreateOrUpdateBatch(input.PersonInsurances, &event, tx); err != nil { + return err + } + if err := UpdateData(input, data, &event, tx); err != nil { return err } diff --git a/internal/use-case/main-use-case/patient/lib.go b/internal/use-case/main-use-case/patient/lib.go index e126ec0d..f35e3853 100644 --- a/internal/use-case/main-use-case/patient/lib.go +++ b/internal/use-case/main-use-case/patient/lib.go @@ -91,7 +91,8 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e Preload("Person.Contacts"). Preload("Person.Relatives.Village.District.Regency.Province"). Preload("Person.Addresses.Village.District.Regency.Province"). - Preload("Person.Addresses.PostalRegion.Village.District.Regency.Province") + Preload("Person.Addresses.PostalRegion.Village.District.Regency.Province"). + Preload("Person.Insurances.InsuranceCompany") if err := tx.First(&data, input.Id).Error; err != nil { if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { @@ -157,6 +158,7 @@ func SearchData(input e.SearchDto, event *pl.Event, dbx ...*gorm.DB) (*e.Patient pl.SetLogInfo(event, input, "started", "DBSearch") var patient e.Patient + var err error var tx *gorm.DB if len(dbx) > 0 { @@ -167,15 +169,25 @@ func SearchData(input e.SearchDto, event *pl.Event, dbx ...*gorm.DB) (*e.Patient // Preload associations for complete data tx = tx.Preload(clause.Associations) - tx = tx.Preload("Person.Addresses") - tx = tx.Preload("Person.Contacts") - tx = tx.Preload("Person.Relatives") + tx = tx.Preload("Person.Addresses"). + Preload("Person.Contacts"). + Preload("Person.Relatives"). + Preload("Person.Insurances") - // Search by patient number OR person's resident identity number (exact match) - err := tx.Joins("JOIN \"Person\" ON \"Patient\".\"Person_Id\" = \"Person\".\"Id\""). - Where("\"Patient\".\"Number\" = ? OR \"Person\".\"ResidentIdentityNumber\" = ?", - input.Search, input.Search). - First(&patient).Error + switch input.Mode { + case e.SMIdent: + // Search by patient number OR person's resident identity number (exact match) OR person's name (partial match) + err = tx.Joins("JOIN \"Person\" ON \"Patient\".\"Person_Id\" = \"Person\".\"Id\""). + Where("\"Patient\".\"Number\" = ? OR \"Person\".\"ResidentIdentityNumber\" = ? OR \"Person\".\"Name\" ILIKE ?", + input.Search, input.Search, "%"+input.Search+"%"). + First(&patient).Error + case e.SMNik: + // Search by patient person's resident identity number (exact match) + err = tx.Joins("JOIN \"Person\" ON \"Patient\".\"Person_Id\" = \"Person\".\"Id\""). + Where("\"Person\".\"ResidentIdentityNumber\" = ?", + input.Search). + First(&patient).Error + } if err != nil { if processedErr := pu.HandleSearchError(err, event, source, input.Search, patient); processedErr != nil { diff --git a/internal/use-case/main-use-case/person-insurance/case.go b/internal/use-case/main-use-case/person-insurance/case.go new file mode 100644 index 00000000..e9595137 --- /dev/null +++ b/internal/use-case/main-use-case/person-insurance/case.go @@ -0,0 +1,276 @@ +package personinsurance + +import ( + e "simrs-vx/internal/domain/main-entities/person-insurance" + "strconv" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +const source = "person-insurance" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.PersonInsurance{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + err := dg.I.Transaction(func(tx *gorm.DB) error { + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunCreateMiddleware(createPreMw, &input, &data); err != nil { + return err + } + + if resData, err := CreateData(input, &event, tx); err != nil { + return err + } else { + data = *resData + } + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunCreateMiddleware(createPostMw, &input, &data); err != nil { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: data.ToResponse(), + }, nil +} + +func ReadList(input e.ReadListDto) (*d.Data, error) { + var data *e.PersonInsurance + var dataList []e.PersonInsurance + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "readList") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadListMiddleware(readListPreMw, &input, data); err != nil { + return err + } + + if dataList, metaList, err = ReadListData(input, &event, tx); err != nil { + return err + } + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadListMiddleware(readListPostMw, &input, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.PersonInsurance + var err error + + event := pl.Event{ + Feature: "ReadDetail", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "readDetail") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadDetailMiddleware(readDetailPreMw, &input, data); err != nil { + return err + } + + if data, err = ReadDetailData(input, &event, tx); err != nil { + return err + } + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadDetailMiddleware(readDetailPostMw, &input, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "fetched", + }, + Data: data.ToResponse(), + }, nil +} + +func Update(input e.UpdateDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.PersonInsurance + var err error + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + 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 + } + + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPreMw, &rdDto, data); err != nil { + return err + } + + if err := UpdateData(input, data, &event, tx); err != nil { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: data.ToResponse(), + }, nil + +} + +func Delete(input e.DeleteDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.PersonInsurance + var err error + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + 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 + } + + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunDeleteMiddleware(readDetailPreMw, &rdDto, data); err != nil { + return err + } + + if err := DeleteData(data, &event, tx); err != nil { + return err + } + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunDeleteMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + Data: data.ToResponse(), + }, nil + +} diff --git a/internal/use-case/main-use-case/person-insurance/helper.go b/internal/use-case/main-use-case/person-insurance/helper.go new file mode 100644 index 00000000..e9352119 --- /dev/null +++ b/internal/use-case/main-use-case/person-insurance/helper.go @@ -0,0 +1,24 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package personinsurance + +import ( + e "simrs-vx/internal/domain/main-entities/person-insurance" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.PersonInsurance) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.Person_Id = &inputSrc.Person_Id + data.InsuranceCompany_Id = inputSrc.InsuranceCompany_Id + data.Ref_Number = inputSrc.Ref_Number + data.DefaultStatus = inputSrc.DefaultStatus +} diff --git a/internal/use-case/main-use-case/person-insurance/lib.go b/internal/use-case/main-use-case/person-insurance/lib.go new file mode 100644 index 00000000..86c6dc83 --- /dev/null +++ b/internal/use-case/main-use-case/person-insurance/lib.go @@ -0,0 +1,193 @@ +package personinsurance + +import ( + e "simrs-vx/internal/domain/main-entities/person-insurance" + + plh "simrs-vx/pkg/lib-helper" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + gh "github.com/karincake/getuk" + "gorm.io/gorm" +) + +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.PersonInsurance, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.PersonInsurance{} + setData(&input, &data) + + 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(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.PersonInsurance, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.PersonInsurance{} + pagination := gh.Pagination{} + count := int64(0) + meta := e.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&e.PersonInsurance{}). + Scopes(gh.Filter(input)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Order("\"CreatedAt\" DESC") + + if err := tx.Find(&data).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, &meta, nil + } + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-get-fail", + Detail: "Database get failed", + Raw: err, + } + return nil, nil, pl.SetLogError(event, input) + + } + meta.Count = int(count) + meta.PageNumber = pagination.PageNumber + meta.PageSize = pagination.PageSize + + pl.SetLogInfo(event, nil, "complete") + return data, &meta, nil +} + +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.PersonInsurance, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.PersonInsurance{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if err := tx.First(&data, input.Id).Error; err != nil { + if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { + return nil, processedErr + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateData(input e.UpdateDto, data *e.PersonInsurance, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBUpdate") + setData(&input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 DeleteData(data *e.PersonInsurance, 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 CreateOrUpdateBatch(input []e.UpdateDto, event *pl.Event, tx ...*gorm.DB) error { + var data = make([]e.PersonInsurance, len(input)) + var dbx *gorm.DB + if len(tx) > 0 { + dbx = tx[0] + } else { + dbx = dg.I + } + + for idx := range input { + if input[idx].Id > 0 { + if err := dbx.Where("\"Id\" = ? AND \"Person_Id\" = ?", input[idx].Id, input[idx].Person_Id).First(&data[idx]).Error; err == nil { + setData(&input[idx], &data[idx]) + if err := dbx.Save(&data[idx]).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) + } + } else if err != gorm.ErrRecordNotFound { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-get-fail", + Detail: "Database get failed", + Raw: err, + } + return pl.SetLogError(event, input) + } + continue + } + setData(&input[idx], &data[idx]) + if err := dbx.Create(&data[idx]).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-create-fail", + Detail: "Database insert failed", + Raw: err, + } + return pl.SetLogError(event, input) + } + } + + return nil +} diff --git a/internal/use-case/main-use-case/person-insurance/middleware-runner.go b/internal/use-case/main-use-case/person-insurance/middleware-runner.go new file mode 100644 index 00000000..ce9ff869 --- /dev/null +++ b/internal/use-case/main-use-case/person-insurance/middleware-runner.go @@ -0,0 +1,103 @@ +package personinsurance + +import ( + e "simrs-vx/internal/domain/main-entities/person-insurance" + 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.PersonInsurance) 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.PersonInsurance) 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.PersonInsurance) 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.PersonInsurance) 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.PersonInsurance) 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 +} diff --git a/internal/use-case/main-use-case/person-insurance/middleware.go b/internal/use-case/main-use-case/person-insurance/middleware.go new file mode 100644 index 00000000..a190f067 --- /dev/null +++ b/internal/use-case/main-use-case/person-insurance/middleware.go @@ -0,0 +1,9 @@ +package personinsurance + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } diff --git a/internal/use-case/main-use-case/person-insurance/tycovar.go b/internal/use-case/main-use-case/person-insurance/tycovar.go new file mode 100644 index 00000000..2cc94930 --- /dev/null +++ b/internal/use-case/main-use-case/person-insurance/tycovar.go @@ -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 personinsurance + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/person-insurance" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.PersonInsurance, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.PersonInsurance, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.PersonInsurance, 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 diff --git a/internal/use-case/main-use-case/user/case.go b/internal/use-case/main-use-case/user/case.go index ba5859ee..7d2053de 100644 --- a/internal/use-case/main-use-case/user/case.go +++ b/internal/use-case/main-use-case/user/case.go @@ -9,7 +9,6 @@ import ( ed "simrs-vx/internal/domain/main-entities/doctor" ee "simrs-vx/internal/domain/main-entities/employee" el "simrs-vx/internal/domain/main-entities/laborant" - em "simrs-vx/internal/domain/main-entities/midwife" en "simrs-vx/internal/domain/main-entities/nurse" et "simrs-vx/internal/domain/main-entities/nutritionist" ep "simrs-vx/internal/domain/main-entities/pharmacist" @@ -19,7 +18,6 @@ import ( ud "simrs-vx/internal/use-case/main-use-case/doctor" ue "simrs-vx/internal/use-case/main-use-case/employee" ul "simrs-vx/internal/use-case/main-use-case/laborant" - um "simrs-vx/internal/use-case/main-use-case/midwife" un "simrs-vx/internal/use-case/main-use-case/nurse" ut "simrs-vx/internal/use-case/main-use-case/nutritionist" upe "simrs-vx/internal/use-case/main-use-case/person" @@ -85,7 +83,7 @@ func Create(input e.CreateDto) (*d.Data, error) { data = *resData } - if input.Position_Code == ero.UPCInt { + if input.ContractPosition_Code == ero.CSCInt { createInt := esi.CreateDto{ Person_Id: input.Person_Id, Specialist_Id: input.Specialist_Id, @@ -105,8 +103,8 @@ func Create(input e.CreateDto) (*d.Data, error) { return err } - switch input.Position_Code { - case ero.UPCDoc: + switch input.Employee.Position_Code { + case ero.EPCDoc: createDoc := ed.CreateDto{ Employee_Id: &employeeData.Id, IHS_Number: input.IHS_Number, @@ -118,7 +116,7 @@ func Create(input e.CreateDto) (*d.Data, error) { if _, err := ud.CreateData(createDoc, &event, tx); err != nil { return err } - case ero.UPCNur: + case ero.EPCNur: createNurse := en.CreateDto{ Employee_Id: &employeeData.Id, IHS_Number: input.IHS_Number, @@ -128,7 +126,7 @@ func Create(input e.CreateDto) (*d.Data, error) { if _, err := un.CreateData(createNurse, &event, tx); err != nil { return err } - case ero.UPCNut: + case ero.EPCNut: createNutritionist := et.CreateDto{ Employee_Id: &employeeData.Id, IHS_Number: input.IHS_Number, @@ -136,7 +134,7 @@ func Create(input e.CreateDto) (*d.Data, error) { if _, err := ut.CreateData(createNutritionist, &event, tx); err != nil { return err } - case ero.UPCPha: + case ero.EPCPha: createPharmacist := ep.CreateDto{ Employee_Id: &employeeData.Id, IHS_Number: input.IHS_Number, @@ -144,7 +142,7 @@ func Create(input e.CreateDto) (*d.Data, error) { if _, err := up.CreateData(createPharmacist, &event, tx); err != nil { return err } - case ero.UPCLab: + case ero.EPCLab: createLaborant := el.CreateDto{ Employee_Id: &employeeData.Id, IHS_Number: input.IHS_Number, @@ -152,16 +150,6 @@ func Create(input e.CreateDto) (*d.Data, error) { if _, err := ul.CreateData(createLaborant, &event, tx); err != nil { return err } - case ero.UPCMwi: - createMidwife := em.CreateDto{ - Employee_Id: &employeeData.Id, - IHS_Number: input.IHS_Number, - } - if _, err := um.CreateData(em.CreateDto(createMidwife), &event, tx); err != nil { - return err - } - case ero.UPCReg, ero.UPCHur, ero.UPCGea, ero.UPCMan: - // do nothing default: return errors.New("invalid employee position") } @@ -317,7 +305,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { return err } - person_id, err := getPersonIdByUserId(data.Id, input.Position_Code, &event, tx) + person_id, err := getPersonIdByUserId(data.Id, input.ContractPosition_Code, &event, tx) if err != nil { return err } else { @@ -348,7 +336,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { return err } - if input.Position_Code == ero.UPCInt { + if input.ContractPosition_Code == ero.CSCInt { readInt := esi.ReadDetailDto{User_Id: &data.Id} readIntData, err := usi.ReadDetailData(readInt, &event, tx) if err != nil { @@ -384,8 +372,8 @@ func Update(input e.UpdateDto) (*d.Data, error) { return err } - switch input.Position_Code { - case ero.UPCDoc: + switch input.Employee.Position_Code { + case ero.EPCDoc: readDoc := ed.ReadDetailDto{Employee_Id: &employeeData.Id} readDocData, err := ud.ReadDetailData(readDoc, &event, tx) if err != nil { @@ -407,7 +395,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { if _, err := ud.CreateData(createDoc, &event, tx); err != nil { return err } - case ero.UPCNur: + case ero.EPCNur: readNur := en.ReadDetailDto{Employee_Id: &employeeData.Id} readNurData, err := un.ReadDetailData(readNur, &event, tx) if err != nil { @@ -427,7 +415,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { if _, err := un.CreateData(createNur, &event, tx); err != nil { return err } - case ero.UPCNut: + case ero.EPCNut: readNut := et.ReadDetailDto{Employee_Id: &employeeData.Id} readNutData, err := ut.ReadDetailData(readNut, &event, tx) if err != nil { @@ -447,7 +435,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { if _, err := ut.CreateData(createNut, &event, tx); err != nil { return err } - case ero.UPCPha: + case ero.EPCPha: readPha := ep.ReadDetailDto{Employee_Id: &employeeData.Id} readPhaData, err := up.ReadDetailData(readPha, &event, tx) if err != nil { @@ -467,7 +455,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { if _, err := up.CreateData(createPha, &event, tx); err != nil { return err } - case ero.UPCLab: + case ero.EPCLab: readLab := el.ReadDetailDto{Employee_Id: &employeeData.Id} readLabData, err := ul.ReadDetailData(readLab, &event, tx) if err != nil { @@ -487,28 +475,6 @@ func Update(input e.UpdateDto) (*d.Data, error) { if _, err := ul.CreateData(createLab, &event, tx); err != nil { return err } - case ero.UPCMwi: - readMidwife := em.ReadDetailDto{Employee_Id: &employeeData.Id} - readMidwifeData, err := um.ReadDetailData(readMidwife, &event, tx) - if err != nil { - return err - } - createMidwife := em.CreateDto{ - Employee_Id: &employeeData.Id, - IHS_Number: input.IHS_Number, - } - if readMidwifeData != nil { - if err := um.UpdateData(em.UpdateDto{CreateDto: createMidwife}, readMidwifeData, &event, tx); err != nil { - return err - } - return nil - } - - if _, err := um.CreateData(createMidwife, &event, tx); err != nil { - return err - } - case ero.UPCReg, ero.UPCHur, ero.UPCGea, ero.UPCMan: - // do nothing default: return errors.New("invalid employee position") } diff --git a/internal/use-case/main-use-case/user/helper.go b/internal/use-case/main-use-case/user/helper.go index 111d333f..1663bb24 100644 --- a/internal/use-case/main-use-case/user/helper.go +++ b/internal/use-case/main-use-case/user/helper.go @@ -6,19 +6,19 @@ package user import ( "errors" - ee "simrs-vx/internal/domain/main-entities/employee" - esi "simrs-vx/internal/domain/main-entities/specialist-intern" - e "simrs-vx/internal/domain/main-entities/user" - ue "simrs-vx/internal/use-case/main-use-case/employee" - usi "simrs-vx/internal/use-case/main-use-case/specialist-intern" - - ero "simrs-vx/internal/domain/references/organization" + "gorm.io/gorm" pl "simrs-vx/pkg/logger" p "simrs-vx/pkg/password" - "gorm.io/gorm" + ue "simrs-vx/internal/use-case/main-use-case/employee" + usi "simrs-vx/internal/use-case/main-use-case/specialist-intern" + + ee "simrs-vx/internal/domain/main-entities/employee" + esi "simrs-vx/internal/domain/main-entities/specialist-intern" + e "simrs-vx/internal/domain/main-entities/user" + erg "simrs-vx/internal/domain/references/organization" ) func setCreate(src e.CreateDto, dst *e.User) error { @@ -30,15 +30,14 @@ func setCreate(src e.CreateDto, dst *e.User) error { dst.Name = src.Name dst.Password = pass dst.Status_Code = src.Status_Code - dst.Position_Code = src.Position_Code + dst.ContractPosition_Code = src.ContractPosition_Code return nil } func setUpdate(src e.UpdateDto, dst *e.User) { dst.Status_Code = src.Status_Code - dst.Position_Code = src.Position_Code - + dst.ContractPosition_Code = src.ContractPosition_Code } func setDataEmployeeUpdate(src e.EmployeUpdateDto) ee.UpdateDto { @@ -54,9 +53,10 @@ func setDataEmployeeUpdate(src e.EmployeUpdateDto) ee.UpdateDto { } } -func getPersonIdByUserId(userId uint, positionCode ero.UserPosisitionCode, event *pl.Event, tx *gorm.DB) (*uint, error) { +func getPersonIdByUserId(userId uint, positionCode erg.ContractPositionCode, event *pl.Event, tx *gorm.DB) (*uint, error) { pl.SetLogInfo(event, nil, "started", "DBGetPersonIdByUserId") - if positionCode == ero.UPCInt { + if positionCode == erg.CSCEmp { + } else if positionCode == erg.CSCInt { specInt, err := usi.ReadDetailData(esi.ReadDetailDto{User_Id: &userId}, event, tx) if err != nil { return nil, err diff --git a/pkg/auth-helper/tycovar.go b/pkg/auth-helper/tycovar.go index 288c9d21..06618350 100644 --- a/pkg/auth-helper/tycovar.go +++ b/pkg/auth-helper/tycovar.go @@ -7,11 +7,15 @@ import ( type AuthKey struct{} type AuthInfo struct { - Uuid string - User_Id uint - User_Name string - User_DivisionPositions []DivisionPosition - User_Position_Code string + Uuid string + User_Id uint + User_Name string + User_ContractPosition_code string + Employee_Position_Code *string + Intern_Position_Code *string + User_DivisionPositions []DivisionPosition + // User_DivisionPositions []DivisionPosition + // User_Position_Code string } type DivisionPosition struct { @@ -20,33 +24,64 @@ type DivisionPosition struct { } func (a AuthInfo) IsDoctor() bool { - return a.User_Position_Code == string(ero.UPCDoc) + if a.Employee_Position_Code == nil { + return false + } + return *a.Employee_Position_Code == string(ero.EPCDoc) } func (a AuthInfo) IsNurse() bool { - return a.User_Position_Code == string(ero.UPCNur) + if a.Employee_Position_Code == nil { + return false + } + return *a.Employee_Position_Code == string(ero.EPCNur) } func (a AuthInfo) IsNutritionist() bool { - return a.User_Position_Code == string(ero.UPCNut) + if a.Employee_Position_Code == nil { + return false + } + return *a.Employee_Position_Code == string(ero.EPCNut) } func (a AuthInfo) IsLaborant() bool { - return a.User_Position_Code == string(ero.UPCLab) + if a.Employee_Position_Code == nil { + return false + } + return *a.Employee_Position_Code == string(ero.EPCLab) } func (a AuthInfo) IsPharmacist() bool { - return a.User_Position_Code == string(ero.UPCPha) + if a.Employee_Position_Code == nil { + return false + } + return *a.Employee_Position_Code == string(ero.EPCPha) } func (a AuthInfo) IsPayment() bool { - return a.User_Position_Code == string(ero.UPCPay) + if a.Employee_Position_Code == nil { + return false + } + return *a.Employee_Position_Code == string(ero.EPCPay) } func (a AuthInfo) IsManagement() bool { - return a.User_Position_Code == string(ero.UPCMan) + if a.Employee_Position_Code == nil { + return false + } + return *a.Employee_Position_Code == string(ero.EPCMan) } func (a AuthInfo) IsSpecialistIntern() bool { - return a.User_Position_Code == string(ero.UPCInt) + if a.Intern_Position_Code == nil { + return false + } + return *a.Intern_Position_Code == string(ero.IPCSpecialist) +} + +func (a AuthInfo) IsNurseIntern() bool { + if a.Intern_Position_Code == nil { + return false + } + return *a.Intern_Position_Code == string(ero.IPCNurse) }