diff --git a/cmd/main-migration/migrations/20251019093915.sql b/cmd/main-migration/migrations/20251019093915.sql index 31ac3655..add924ea 100644 --- a/cmd/main-migration/migrations/20251019093915.sql +++ b/cmd/main-migration/migrations/20251019093915.sql @@ -1,15 +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 -); +-- -- 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/20251021041042.sql b/cmd/main-migration/migrations/20251021041042.sql new file mode 100644 index 00000000..43701307 --- /dev/null +++ b/cmd/main-migration/migrations/20251021041042.sql @@ -0,0 +1,60 @@ +-- Create "DeathCause" table +CREATE TABLE "public"."DeathCause" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NOT NULL, + "Value" text NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_DeathCause_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "EduAssessment" table +CREATE TABLE "public"."EduAssessment" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NOT NULL, + "GeneralEdus" text NULL, + "SpecialEdus" text NULL, + "Assessments" text NULL, + "Plan" text NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_EduAssessment_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "GeneralConsent" table +CREATE TABLE "public"."GeneralConsent" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NOT NULL, + "Value" text NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_GeneralConsent_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Create "TherapyProtocol" table +CREATE TABLE "public"."TherapyProtocol" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NOT NULL, + "Doctor_Id" bigint NULL, + "Anamnesis" character varying(2048) NULL, + "MedicalDiagnoses" text NULL, + "FunctionDiagnoses" text NULL, + "Procedures" text NULL, + "SupportingExams" character varying(2048) NULL, + "Instruction" character varying(2048) NULL, + "Evaluation" character varying(2048) NULL, + "WorkCauseStatus" character varying(2048) NULL, + "Frequency" bigint NULL, + "IntervalUnit_Code" character varying(10) NULL, + "Duration" bigint NULL, + "DurationUnit_Code" character varying(10) NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_TherapyProtocol_Doctor" FOREIGN KEY ("Doctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_TherapyProtocol_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/20251021075552.sql b/cmd/main-migration/migrations/20251021075552.sql new file mode 100644 index 00000000..ead1e95b --- /dev/null +++ b/cmd/main-migration/migrations/20251021075552.sql @@ -0,0 +1,8 @@ +-- Rename a column from "DischargeMethod_Code" to "Discharge_Method_Code" +ALTER TABLE "public"."Encounter" RENAME COLUMN "DischargeMethod_Code" TO "Discharge_Method_Code"; +-- Modify "Encounter" table +ALTER TABLE "public"."Encounter" ADD COLUMN "Discharge_Date" timestamptz NULL; +-- Modify "DeathCause" table +ALTER TABLE "public"."DeathCause" DROP CONSTRAINT "fk_DeathCause_Encounter", ADD CONSTRAINT "fk_Encounter_DeathCause" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION; +-- Modify "InternalReference" table +ALTER TABLE "public"."InternalReference" DROP CONSTRAINT "fk_InternalReference_Encounter", ADD CONSTRAINT "fk_Encounter_InternalReferences" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("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 42b47eae..d28421e6 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:ymfgaEhen/ZEJoOaBP0BLfKbsTZRjKjQqNbO58caXLU= +h1:nkA4yHX6MSnA6zb6xACKXMBMwaAu4BRoT1Cs4DW3z80= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -49,5 +49,9 @@ h1:ymfgaEhen/ZEJoOaBP0BLfKbsTZRjKjQqNbO58caXLU= 20251016062912.sql h1:ACNn0fe+EMqUt3hoY+Dr3uqAV/QICBa1+mIW7fUc9Fk= 20251017060617.sql h1:4T3t9ifWrEQTPMSM0XJ98pF7Qdt+UfgtMui17bhrnWI= 20251017082207.sql h1:8vLG1l/saRRMHXkyA4nelJyjaSddhZd6r7R+Uo4JS/c= -20251019093915.sql h1:vWqTEc9bZpnAj53DLNKaTYbEoiSqdQJ9Mx4Qv9zmXU8= -20251020062553.sql h1:llHc4558mdcMjVYMdrCb6ZClnjUd56DnJuwYGbae/Ms= +20251018032635.sql h1:2xey5gnO3y2XSOrU8MLlIfoylPKbRGDRtHDD07B3MbQ= +20251018040322.sql h1:k/pdNiSoT8zFPqNQ/avOD0vYkNh3BTD64IlHrfVXr7I= +20251019093915.sql h1:hFcQE0y+p5dZiVwePGsRGto9m/q6kJNiUZbVDd5Rnjk= +20251020062553.sql h1:Iw7hulcm5iRQlfW+ygA4iTPxLqkxx6h9vXMXEwUAHKs= +20251021041042.sql h1:wMgSivBV2A0NDcsLmKGIp0kMcVh2IODSG9b4dgzCaOM= +20251021075552.sql h1:8gfSMAglflNO6L0sSzxFNEubYN8/O4thT7OQT+WH+3M= diff --git a/internal/domain/main-entities/death-cause/dto.go b/internal/domain/main-entities/death-cause/dto.go new file mode 100644 index 00000000..8781ace8 --- /dev/null +++ b/internal/domain/main-entities/death-cause/dto.go @@ -0,0 +1,62 @@ +package death_cause + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" +) + +type CreateDto struct { + Encounter_Id *uint `json:"-"` + Value *string `json:"value"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Encounter_Id *uint `json:"encounter-id"` +} + +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 + Encounter_Id *uint `json:"encounter_id"` + Value *string `json:"value"` +} + +func (d DeathCause) ToResponse() ResponseDto { + resp := ResponseDto{ + Encounter_Id: d.Encounter_Id, + Value: d.Value, + } + resp.Main = d.Main + return resp +} + +func ToResponseList(data []DeathCause) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/death-cause/entity.go b/internal/domain/main-entities/death-cause/entity.go new file mode 100644 index 00000000..6e1741a1 --- /dev/null +++ b/internal/domain/main-entities/death-cause/entity.go @@ -0,0 +1,11 @@ +package death_cause + +import ( + "simrs-vx/internal/domain/base-entities/core" +) + +type DeathCause struct { + core.Main + Encounter_Id *uint `json:"encounter_id" gorm:"not null"` + Value *string `json:"value"` +} diff --git a/internal/domain/main-entities/edu-assessment/entity.go b/internal/domain/main-entities/edu-assessment/entity.go new file mode 100644 index 00000000..8f037c5a --- /dev/null +++ b/internal/domain/main-entities/edu-assessment/entity.go @@ -0,0 +1,17 @@ +package edu_assessment + +import ( + "simrs-vx/internal/domain/base-entities/core" + ee "simrs-vx/internal/domain/main-entities/encounter" +) + +type EduAssessment struct { + core.Main + Encounter_Id *uint `json:"encounter_id" gorm:"not null"` + Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` + + GeneralEdus *string `json:"generalEdus"` + SpecialEdus *string `json:"specialEdus"` + Assessments *string `json:"assessments"` + Plan *string `json:"plan"` +} diff --git a/internal/domain/main-entities/employee/dto.go b/internal/domain/main-entities/employee/dto.go index 9e0e93d2..133260c7 100644 --- a/internal/domain/main-entities/employee/dto.go +++ b/internal/domain/main-entities/employee/dto.go @@ -5,16 +5,18 @@ import ( ed "simrs-vx/internal/domain/main-entities/division" ep "simrs-vx/internal/domain/main-entities/person" eu "simrs-vx/internal/domain/main-entities/user" + erg "simrs-vx/internal/domain/references/organization" erc "simrs-vx/internal/domain/references/common" ) type CreateDto struct { - User_Id *uint `json:"user_id"` - Person_Id *uint `json:"person_id"` - Division_Code *string `json:"division_code"` - Number *string `json:"number" validate:"maxLength=20"` - Status_Code erc.ActiveStatusCode `json:"status_code" validate:"maxLength=10"` + User_Id *uint `json:"user_id"` + Person_Id *uint `json:"person_id"` + Division_Code *string `json:"division_code"` + Number *string `json:"number" validate:"maxLength=20"` + Status_Code erc.ActiveStatusCode `json:"status_code" validate:"maxLength=10"` + Position_Code *erg.EmployeePositionCode `json:"position_code"` } type ReadListDto struct { @@ -56,14 +58,15 @@ type MetaDto struct { type ResponseDto struct { ecore.Main - User_Id *uint `json:"user_id"` - User *eu.User `json:"user,omitempty"` - Person_Id *uint `json:"person_id"` - Person *ep.Person `json:"person,omitempty"` - Division_Code *string `json:"division_code"` - Division *ed.Division `json:"division,omitempty"` - Number *string `json:"number"` - Status_Code erc.ActiveStatusCode `json:"status_code"` + User_Id *uint `json:"user_id"` + User *eu.User `json:"user,omitempty"` + Person_Id *uint `json:"person_id"` + Person *ep.Person `json:"person,omitempty"` + Division_Code *string `json:"division_code"` + Division *ed.Division `json:"division,omitempty"` + Position_Code *erg.EmployeePositionCode `json:"position_code"` + Number *string `json:"number"` + Status_Code erc.ActiveStatusCode `json:"status_code"` } func (d Employee) ToResponse() ResponseDto { @@ -76,6 +79,7 @@ func (d Employee) ToResponse() ResponseDto { Division: d.Division, Number: d.Number, Status_Code: d.Status_Code, + Position_Code: d.Position_Code, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/employee/entity.go b/internal/domain/main-entities/employee/entity.go index 2e8cd953..1177abe9 100644 --- a/internal/domain/main-entities/employee/entity.go +++ b/internal/domain/main-entities/employee/entity.go @@ -10,14 +10,14 @@ import ( ) 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"` - 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"` + 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.EmployeePositionCode `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 67810d27..4a30281d 100644 --- a/internal/domain/main-entities/encounter/dto.go +++ b/internal/domain/main-entities/encounter/dto.go @@ -8,6 +8,7 @@ import ( ea "simrs-vx/internal/domain/main-entities/appointment" ed "simrs-vx/internal/domain/main-entities/doctor" ee "simrs-vx/internal/domain/main-entities/employee" + eir "simrs-vx/internal/domain/main-entities/internal-reference" ep "simrs-vx/internal/domain/main-entities/patient" es "simrs-vx/internal/domain/main-entities/specialist" ess "simrs-vx/internal/domain/main-entities/subspecialist" @@ -95,11 +96,13 @@ type MetaDto struct { } type DischargeDto struct { Id uint `json:"id"` - DischargeMethod_Code *ere.DischargeMethodCode `json:"dischargeMethod_code" validate:"maxLength=16"` + Discharge_Method_Code *ere.DischargeMethodCode `json:"discharge_method_code" validate:"maxLength=16"` EarlyEducation *string `json:"earlyEducation"` MedicalDischargeEducation *string `json:"medicalDischargeEducation"` AdmDischargeEducation *string `json:"admDischargeEducation"` DischargeReason *string `json:"dischargeReason"` + DeathCause *string `json:"deathCause"` + InternalReferences *[]eir.CreateDto `json:"internalReferences,omitempty"` } type ResponseDto struct { @@ -126,7 +129,7 @@ type ResponseDto struct { 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"` + Discharge_Method_Code *ere.DischargeMethodCode `json:"discharge_method_code"` RefSource_Name *string `json:"refSource_name"` Appointment_Id *uint `json:"appointment_id"` Appointment *ea.Appointment `json:"appointment,omitempty"` @@ -162,7 +165,7 @@ func (d Encounter) ToResponse() ResponseDto { Adm_Employee: d.Adm_Employee, Responsible_Doctor_Id: d.Responsible_Doctor_Id, Responsible_Doctor: d.Responsible_Doctor, - DischargeMethod_Code: d.DischargeMethod_Code, + Discharge_Method_Code: d.Discharge_Method_Code, RefSource_Name: d.RefSource_Name, Appointment_Id: d.Appointment_Id, Appointment: d.Appointment, diff --git a/internal/domain/main-entities/encounter/entity.go b/internal/domain/main-entities/encounter/entity.go index 528f28ae..fccbab41 100644 --- a/internal/domain/main-entities/encounter/entity.go +++ b/internal/domain/main-entities/encounter/entity.go @@ -4,9 +4,11 @@ import ( 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" + edc "simrs-vx/internal/domain/main-entities/death-cause" ed "simrs-vx/internal/domain/main-entities/doctor" ee "simrs-vx/internal/domain/main-entities/employee" ei "simrs-vx/internal/domain/main-entities/insurance-company" + eir "simrs-vx/internal/domain/main-entities/internal-reference" ep "simrs-vx/internal/domain/main-entities/patient" es "simrs-vx/internal/domain/main-entities/specialist" ess "simrs-vx/internal/domain/main-entities/subspecialist" @@ -42,7 +44,7 @@ type Encounter struct { 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"` + Discharge_Method_Code *ere.DischargeMethodCode `json:"discharge_method_code" gorm:"size:16"` RefSource_Name *string `json:"refSource_name" gorm:"size:100"` Appointment_Id *uint `json:"appointment_id"` Appointment *ea.Appointment `json:"appointment,omitempty" gorm:"foreignKey:Appointment_Id;references:Id"` @@ -52,6 +54,9 @@ type Encounter struct { DischargeReason *string `json:"dischargeReason"` Status_Code erc.DataStatusCode `json:"status_code" gorm:"size:10"` VclaimSep *evs.VclaimSep `json:"vclaimSep,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` + Discharge_Date *time.Time `json:"discharge_date"` + InternalReferences *[]eir.InternalReference `json:"internalReferences,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` + DeathCause *edc.DeathCause `json:"deathCause,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` } func (d Encounter) IsDone() bool { diff --git a/internal/domain/main-entities/general-consent/entity.go b/internal/domain/main-entities/general-consent/entity.go new file mode 100644 index 00000000..96758406 --- /dev/null +++ b/internal/domain/main-entities/general-consent/entity.go @@ -0,0 +1,13 @@ +package general_consent + +import ( + "simrs-vx/internal/domain/base-entities/core" + ee "simrs-vx/internal/domain/main-entities/encounter" +) + +type GeneralConsent struct { + core.Main + Encounter_Id *uint `json:"encounter_id" gorm:"not null"` + Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` + Value *string `json:"value"` +} diff --git a/internal/domain/main-entities/internal-reference/dto.go b/internal/domain/main-entities/internal-reference/dto.go index 6c71e6f1..360c3193 100644 --- a/internal/domain/main-entities/internal-reference/dto.go +++ b/internal/domain/main-entities/internal-reference/dto.go @@ -3,12 +3,11 @@ package internal_reference import ( ecore "simrs-vx/internal/domain/base-entities/core" ed "simrs-vx/internal/domain/main-entities/doctor" - ee "simrs-vx/internal/domain/main-entities/encounter" eu "simrs-vx/internal/domain/main-entities/unit" ) type CreateDto struct { - Encounter_Id *uint `json:"encounter_id"` + Encounter_Id *uint `json:"-"` Unit_Id *uint16 `json:"unit_id"` Doctor_Id *uint `json:"doctor_Id"` } @@ -47,18 +46,16 @@ type MetaDto struct { type ResponseDto struct { ecore.Main - Encounter_Id *uint `json:"encounter_id"` - Encounter *ee.Encounter `json:"encounter,omitempty"` - Unit_Id *uint16 `json:"unit_id"` - Unit *eu.Unit `json:"unit,omitempty"` - Doctor_Id *uint `json:"doctor_id"` - Doctor *ed.Doctor `json:"doctor,omitempty"` + Encounter_Id *uint `json:"encounter_id"` + Unit_Id *uint16 `json:"unit_id"` + Unit *eu.Unit `json:"unit,omitempty"` + Doctor_Id *uint `json:"doctor_id"` + Doctor *ed.Doctor `json:"doctor,omitempty"` } func (d InternalReference) ToResponse() ResponseDto { resp := ResponseDto{ Encounter_Id: d.Encounter_Id, - Encounter: d.Encounter, Unit_Id: d.Unit_Id, Unit: d.Unit, Doctor_Id: d.Doctor_Id, diff --git a/internal/domain/main-entities/internal-reference/entity.go b/internal/domain/main-entities/internal-reference/entity.go index 56dcdc19..85334449 100644 --- a/internal/domain/main-entities/internal-reference/entity.go +++ b/internal/domain/main-entities/internal-reference/entity.go @@ -3,16 +3,14 @@ package internal_reference import ( ecore "simrs-vx/internal/domain/base-entities/core" ed "simrs-vx/internal/domain/main-entities/doctor" - ee "simrs-vx/internal/domain/main-entities/encounter" eu "simrs-vx/internal/domain/main-entities/unit" ) type InternalReference struct { ecore.Main - Encounter_Id *uint `json:"encounter_id"` - Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` - Unit_Id *uint16 `json:"unit_id"` - Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Id;references:Id"` - Doctor_Id *uint `json:"doctor_id"` - Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Id;references:Id"` + Encounter_Id *uint `json:"encounter_id"` + Unit_Id *uint16 `json:"unit_id"` + Unit *eu.Unit `json:"unit,omitempty" gorm:"foreignKey:Unit_Id;references:Id"` + Doctor_Id *uint `json:"doctor_id"` + Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Id;references:Id"` } diff --git a/internal/domain/main-entities/therapy-protocol/entity.go b/internal/domain/main-entities/therapy-protocol/entity.go new file mode 100644 index 00000000..99b5b59d --- /dev/null +++ b/internal/domain/main-entities/therapy-protocol/entity.go @@ -0,0 +1,31 @@ +package therapy_protocol + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ed "simrs-vx/internal/domain/main-entities/doctor" + ee "simrs-vx/internal/domain/main-entities/encounter" + + common "simrs-vx/internal/domain/references/common" +) + +type TherapyProtocol struct { + ecore.Main + Encounter_Id *uint `json:"encounter_id" gorm:"not null"` + Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` + + Doctor_Id *uint `json:"doctor_id"` + Doctor *ed.Doctor `json:"doctor,omitempty" gorm:"foreignKey:Doctor_Id;references:Id"` + + Anamnesis *string `json:"anamnesis" gorm:"size:2048"` + MedicalDiagnoses *string `json:"medicalDiagnoses"` + FunctionDiagnoses *string `json:"functionDiagnoses"` + Procedures *string `json:"procedures"` + SupportingExams *string `json:"supportingExams" gorm:"size:2048"` + Instruction *string `json:"instruction" gorm:"size:2048"` + Evaluation *string `json:"evaluation" gorm:"size:2048"` + WorkCauseStatus *string `json:"workCauseStatus" gorm:"size:2048"` + Frequency *uint `json:"frequency"` + IntervalUnit_Code *common.TimeUnitCode `json:"intervalUnit_Code" gorm:"size:10"` + Duration *uint `json:"duration"` + DurationUnit_Code *common.TimeUnitCode `json:"durationUnit_Code" gorm:"size:10"` +} diff --git a/internal/domain/main-entities/user/dto.go b/internal/domain/main-entities/user/dto.go index 55a53686..b06a4bb0 100644 --- a/internal/domain/main-entities/user/dto.go +++ b/internal/domain/main-entities/user/dto.go @@ -84,13 +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"` - Position_Code erg.EmployeePosisitionCode `json:"status_code" validate:"maxLength=10"` - 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.EmployeePositionCode `json:"position_code" validate:"maxLength=20"` + Status_Code erc.ActiveStatusCode `json:"status_code" validate:"maxLength=10"` } func ToResponseList(data []User) []ResponseDto { diff --git a/internal/domain/references/clinical/clinical.go b/internal/domain/references/clinical/clinical.go index 47872aa5..c0eb3594 100644 --- a/internal/domain/references/clinical/clinical.go +++ b/internal/domain/references/clinical/clinical.go @@ -12,6 +12,15 @@ type ( SoapiTypeCode string MedicalAction string VehicleTypeCode string + GeneralEduCode string + SpecialEduCode string + EduAssessmentCode string + AbilityCode string + WillCode string + MedObstacleCode string + LearnMethodCode string + LangClassCode string + TranslatorSrcCode string ) const ( @@ -54,9 +63,15 @@ const ( OCHeight ObjectCode = "height" // Tinggi Badan OCHeadToToe ObjectCode = "head-to-toe" // Kepala Sampai Kaki - ACEarlyDiag AssessmentCode = "early-diag" // Diagnosis Awal - ACLateDiag AssessmentCode = "late-diag" // Diagnosis Akhir - ACSecDiag AssessmentCode = "sec-diag" // Diagnosis Sekunder + ACEarlyDiag AssessmentCode = "early-diag" // Diagnosis Awal + ACLateDiag AssessmentCode = "late-diag" // Diagnosis Akhir + ACSecDiag AssessmentCode = "sec-diag" // Diagnosis Sekunder + ACEarlyMedDiag AssessmentCode = "early-med-diag" // Diagnosis Medis Awal + ACLateMedDiag AssessmentCode = "late-med-diag" // Diagnosis Medis Akhir + ACSecMedDiag AssessmentCode = "sec-med-diag" // Diagnosis Medis Sekunder + ACEarlyFuncDiag AssessmentCode = "early-func-diag" // Diagnosis Fungsi Awal + ACLateFuncDiag AssessmentCode = "late-func-diag" // Diagnosis Fungsi Akhir + ACSecFuncDiag AssessmentCode = "sec-func-diag" // Diagnosis Fungsi Sekunder PCPlan PlanCode = "plan" // Rencana @@ -113,6 +128,58 @@ const ( VTCAmbulance VehicleTypeCode = "ambulance" // Ambulans VTCTransport VehicleTypeCode = "transport" // Transport VTCHearse VehicleTypeCode = "hearse" // Jenazah + + GECRightObg GeneralEduCode = "right-obg" // Hak dan kewajiban pasien dan keluarga + GECGeneralConsent GeneralEduCode = "general-consent" // General Consent + GECService GeneralEduCode = "service" // Pelayanan yang disediakan (jam pelayanan, akses pelayanan dan proses pelayanan) + GECAltCareSrc GeneralEduCode = "alt-care-src" // Sumber alternatif asuhan di tempat lain/faskes lain + GECHomePlan GeneralEduCode = "home-plan" // Rencana tindakan di rumah + GECHomeCare GeneralEduCode = "home-care" // Kebutuhan perawatan di rumah + GECOrientation GeneralEduCode = "orientation" // Orientasi ruangan + GECFallRiskPrevention GeneralEduCode = "fall-risk-prevention" // Pencegahan risiko jatuh + GECAltCare GeneralEduCode = "alt-care" // Alternatif pelayanan + GECActDelay GeneralEduCode = "act-delay" // Penundaan Tindakan + GECOthers GeneralEduCode = "others" // Lain - lain + + SECDiseaseDiagDev SpecialEduCode = "disease-diag-dev" // Diagnosa penyakit dan perkembangannya + SECSafeMedUsage SpecialEduCode = "safe-med-usage" // Penggunaan obat yang aman, + SECSideEffect SpecialEduCode = "side-effect" // Efek samping dan reaksi obat + SECDiet SpecialEduCode = "diet" // Diet/Nutrisi + SECPainMgmt SpecialEduCode = "pain-mgmt" // Managemen nyeri + SECMedicalEqUsage SpecialEduCode = "medical-eq-usage" // Penggunaan Peralatan Medis + SECRehabTechnique SpecialEduCode = "rehab-technique" // Teknik Rehabilitasi + SECPreventionAct SpecialEduCode = "prevention-act" // Tindakan pencegahan (cuci tangan, pemasangan gelang) + + EACLearnAbility EduAssessmentCode = "learn-ability" // Kemampuan Belajar + EACLearnWill EduAssessmentCode = "learn-will" // Kemauan Belajar + EACObstacle EduAssessmentCode = "obstacle" // Hambatan + EACLearnMethod EduAssessmentCode = "learn-method" // Metode Pembelajaran + EACLang EduAssessmentCode = "lang" // Bahasa + EACLangObstacle EduAssessmentCode = "lang-obstacle" // Hambatan Bahasa + EACBelief EduAssessmentCode = "belief" // Keyakinan + + ACAble AbilityCode = "able" // Mampu + ACNotAble AbilityCode = "not-able" // Tidak Mampu + + WCReady WillCode = "ready" // Siap + WCInterested WillCode = "interested" // Tertarik + WCNotInterested WillCode = "not-interested" // Tidak Tertarik + + MOCHearing MedObstacleCode = "hearing" // Pendengaran + MOCSight MedObstacleCode = "sight" // Penglihatan + MOCPhysical MedObstacleCode = "physical" // Fisik + MOCEmotional MedObstacleCode = "emotional" // Emosional + MOCCognitif MedObstacleCode = "cognitif" // Kognitif + + LMCDemo LearnMethodCode = "demo" // Demonstrasi + LMCDiscussLeaflet LearnMethodCode = "discuss-leaflet" // Diskusi Leaflet + + LCCInd LangClassCode = "ind" // Indonesia + LCCRegion LangClassCode = "region" // Daerah + LCCForeign LangClassCode = "foreign" // Asing + + TSCTeam TranslatorSrcCode = "team" // Tim Penerjemah + TSCFamily TranslatorSrcCode = "family" // Keluarga ) type Soapi struct { diff --git a/internal/domain/references/organization/organization.go b/internal/domain/references/organization/organization.go index 93eabe63..0309cbee 100644 --- a/internal/domain/references/organization/organization.go +++ b/internal/domain/references/organization/organization.go @@ -1,30 +1,30 @@ package organization type ( - ContractPositionCode string - EmployeePosisitionCode string - InternPosisitionCode string - ItemGroupCode string - InfraGroupCode string - UnitTypeCode string - DoctorFeeTypeCode string + ContractPositionCode string + EmployeePositionCode string + InternPosisitionCode string + ItemGroupCode string + InfraGroupCode string + UnitTypeCode string + DoctorFeeTypeCode string ) const ( 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 + EPCReg EmployeePositionCode = "registration" // Admisi/Pendaftaran + EPCNur EmployeePositionCode = "nurse" // Perawat + EPCDoc EmployeePositionCode = "doctor" // Dokter + EPCNut EmployeePositionCode = "nutritionist" // Ahli gizi + EPCMwi EmployeePositionCode = "mid-wife" // Bidan + EPCLab EmployeePositionCode = "laborant" // Laboran + EPCPha EmployeePositionCode = "pharmacy" // Farmasi + EPCPay EmployeePositionCode = "payment" // Pembayaran + EPCHur EmployeePositionCode = "human-resource" // Sumber Daya Manusia + EPCGea EmployeePositionCode = "general-affair" // Bagian Umum + EPCMan EmployeePositionCode = "management" // Manajemen IPCSpecialist = "specialist-intern" IPCNurse = "nurse-intern" diff --git a/internal/interface/main-handler/encounter/handler.go b/internal/interface/main-handler/encounter/handler.go index 96063298..6cf91832 100644 --- a/internal/interface/main-handler/encounter/handler.go +++ b/internal/interface/main-handler/encounter/handler.go @@ -1,6 +1,7 @@ package encounter import ( + "fmt" "net/http" rw "github.com/karincake/risoles" @@ -12,6 +13,7 @@ import ( u "simrs-vx/internal/use-case/main-use-case/encounter" erc "simrs-vx/internal/domain/references/common" + ere "simrs-vx/internal/domain/references/encounter" pa "simrs-vx/pkg/auth-helper" @@ -83,14 +85,58 @@ func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { } func (obj myBase) CheckOut(w http.ResponseWriter, r *http.Request) { + const dataValidationVail = "data-validation-fail" + dto := e.DischargeDto{} id := rw.ValidateInt(w, "id", r.PathValue("id")) if id <= 0 { return } + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { return } + + // validate request body + { + switch *dto.Discharge_Method_Code { + case ere.DMCDeath: + if dto.DeathCause == nil { + rw.DataResponse(w, nil, d.FieldError{ + Code: dataValidationVail, + Message: "deathCause required if discharge_method_code is death", + }) + return + } + case ere.DMCConsulPoly, ere.DMCConsulExecutive: + if dto.InternalReferences == nil { + rw.DataResponse(w, nil, d.FieldError{ + Code: dataValidationVail, + Message: fmt.Sprintf("internalReferences required if discharge_method_code is %s", *dto.Discharge_Method_Code), + }) + return + } + + for _, v := range *dto.InternalReferences { + if v.Unit_Id == nil { + rw.DataResponse(w, nil, d.FieldError{ + Code: dataValidationVail, + Message: "internalReferences.unit_id required", + }) + return + } + + if v.Doctor_Id == nil { + rw.DataResponse(w, nil, d.FieldError{ + Code: dataValidationVail, + Message: "internalReferences.doctor_id required", + }) + return + } + } + } + } + dto.Id = uint(id) res, err := u.CheckOut(dto) rw.DataResponse(w, res, err) diff --git a/internal/interface/migration/main-entities.go b/internal/interface/migration/main-entities.go index 131b2972..597c3f77 100644 --- a/internal/interface/migration/main-entities.go +++ b/internal/interface/migration/main-entities.go @@ -8,6 +8,7 @@ import ( chemo "simrs-vx/internal/domain/main-entities/chemo" consultation "simrs-vx/internal/domain/main-entities/consultation" counter "simrs-vx/internal/domain/main-entities/counter" + deathcause "simrs-vx/internal/domain/main-entities/death-cause" device "simrs-vx/internal/domain/main-entities/device" deviceorder "simrs-vx/internal/domain/main-entities/device-order" deviceorderitem "simrs-vx/internal/domain/main-entities/device-order-item" @@ -17,10 +18,12 @@ import ( divisionposition "simrs-vx/internal/domain/main-entities/division-position" doctor "simrs-vx/internal/domain/main-entities/doctor" doctorfee "simrs-vx/internal/domain/main-entities/doctor-fee" + eduassesment "simrs-vx/internal/domain/main-entities/edu-assessment" emergency "simrs-vx/internal/domain/main-entities/emergency" employee "simrs-vx/internal/domain/main-entities/employee" encounter "simrs-vx/internal/domain/main-entities/encounter" ethnic "simrs-vx/internal/domain/main-entities/ethnic" + generalconsent "simrs-vx/internal/domain/main-entities/general-consent" infra "simrs-vx/internal/domain/main-entities/infra" inpatient "simrs-vx/internal/domain/main-entities/inpatient" installation "simrs-vx/internal/domain/main-entities/installation" @@ -74,6 +77,7 @@ import ( specialist "simrs-vx/internal/domain/main-entities/specialist" specialistintern "simrs-vx/internal/domain/main-entities/specialist-intern" subspecialist "simrs-vx/internal/domain/main-entities/subspecialist" + therapyprotocol "simrs-vx/internal/domain/main-entities/therapy-protocol" unit "simrs-vx/internal/domain/main-entities/unit" uom "simrs-vx/internal/domain/main-entities/uom" user "simrs-vx/internal/domain/main-entities/user" @@ -171,5 +175,9 @@ func getMainEntities() []any { &vehicle.Vehicle{}, &vehiclehist.VehicleHist{}, &ambulancetransportreq.AmbulanceTransportReq{}, + &therapyprotocol.TherapyProtocol{}, + &eduassesment.EduAssessment{}, + &generalconsent.GeneralConsent{}, + &deathcause.DeathCause{}, } } diff --git a/internal/use-case/main-use-case/ambulance-transport-req/case.go b/internal/use-case/main-use-case/ambulance-transport-req/case.go index 712d6241..6810fe83 100644 --- a/internal/use-case/main-use-case/ambulance-transport-req/case.go +++ b/internal/use-case/main-use-case/ambulance-transport-req/case.go @@ -1,4 +1,4 @@ -package ambulancetransport +package ambulance_transport_req import ( "errors" diff --git a/internal/use-case/main-use-case/ambulance-transport-req/helper.go b/internal/use-case/main-use-case/ambulance-transport-req/helper.go index 3c739eb0..9ad4122d 100644 --- a/internal/use-case/main-use-case/ambulance-transport-req/helper.go +++ b/internal/use-case/main-use-case/ambulance-transport-req/helper.go @@ -2,7 +2,7 @@ DESCRIPTION: Any functions that are used internally by the use-case */ -package ambulancetransport +package ambulance_transport_req import ( "errors" diff --git a/internal/use-case/main-use-case/ambulance-transport-req/lib.go b/internal/use-case/main-use-case/ambulance-transport-req/lib.go index e8555a6f..eca1c5b9 100644 --- a/internal/use-case/main-use-case/ambulance-transport-req/lib.go +++ b/internal/use-case/main-use-case/ambulance-transport-req/lib.go @@ -1,4 +1,4 @@ -package ambulancetransport +package ambulance_transport_req import ( "errors" diff --git a/internal/use-case/main-use-case/ambulance-transport-req/middleware-runner.go b/internal/use-case/main-use-case/ambulance-transport-req/middleware-runner.go index b98c497d..18937f5c 100644 --- a/internal/use-case/main-use-case/ambulance-transport-req/middleware-runner.go +++ b/internal/use-case/main-use-case/ambulance-transport-req/middleware-runner.go @@ -1,4 +1,4 @@ -package ambulancetransport +package ambulance_transport_req import ( atr "simrs-vx/internal/domain/main-entities/ambulance-transport-req" diff --git a/internal/use-case/main-use-case/ambulance-transport-req/middleware.go b/internal/use-case/main-use-case/ambulance-transport-req/middleware.go index 847aa3dd..cc1f7c3e 100644 --- a/internal/use-case/main-use-case/ambulance-transport-req/middleware.go +++ b/internal/use-case/main-use-case/ambulance-transport-req/middleware.go @@ -1,4 +1,4 @@ -package ambulancetransport +package ambulance_transport_req // example of middleware // func init() { diff --git a/internal/use-case/main-use-case/ambulance-transport-req/tycovar.go b/internal/use-case/main-use-case/ambulance-transport-req/tycovar.go index 5d3ac027..54f8f604 100644 --- a/internal/use-case/main-use-case/ambulance-transport-req/tycovar.go +++ b/internal/use-case/main-use-case/ambulance-transport-req/tycovar.go @@ -6,7 +6,7 @@ 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 ambulancetransport +package ambulance_transport_req import ( "gorm.io/gorm" diff --git a/internal/use-case/main-use-case/death-cause/case.go b/internal/use-case/main-use-case/death-cause/case.go new file mode 100644 index 00000000..484c0f66 --- /dev/null +++ b/internal/use-case/main-use-case/death-cause/case.go @@ -0,0 +1,228 @@ +package deathcause + +import ( + + // main entities + edc "simrs-vx/internal/domain/main-entities/death-cause" + "strconv" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + "gorm.io/gorm" +) + +const source = "death-cause" + +func Create(input edc.CreateDto) (*d.Data, error) { + data := edc.DeathCause{} + + 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 edc.ReadListDto) (*d.Data, error) { + var data *edc.DeathCause + var dataList []edc.DeathCause + var metaList *edc.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: edc.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input edc.ReadDetailDto) (*d.Data, error) { + var data *edc.DeathCause + 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 edc.UpdateDto) (*d.Data, error) { + rdDto := edc.ReadDetailDto{Id: input.Id} + var data *edc.DeathCause + 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 + } + + // Get Updated Data + if data, err = ReadDetailData(rdDto, &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 + +} diff --git a/internal/use-case/main-use-case/death-cause/helper.go b/internal/use-case/main-use-case/death-cause/helper.go new file mode 100644 index 00000000..c655a966 --- /dev/null +++ b/internal/use-case/main-use-case/death-cause/helper.go @@ -0,0 +1,22 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package deathcause + +import ( + e "simrs-vx/internal/domain/main-entities/death-cause" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.DeathCause) { + 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.Value = inputSrc.Value +} diff --git a/internal/use-case/main-use-case/death-cause/lib.go b/internal/use-case/main-use-case/death-cause/lib.go new file mode 100644 index 00000000..9f1d548b --- /dev/null +++ b/internal/use-case/main-use-case/death-cause/lib.go @@ -0,0 +1,140 @@ +package deathcause + +import ( + "errors" + e "simrs-vx/internal/domain/main-entities/death-cause" + 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.DeathCause, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.DeathCause{} + 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.DeathCause, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.DeathCause{} + 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.DeathCause{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Order("\"CreatedAt\" DESC") + + if err := tx.Find(&data).Error; err != nil { + if errors.Is(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.DeathCause, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.DeathCause{} + + 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.DeathCause, 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.DeathCause, 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/main-use-case/death-cause/middleware-runner.go b/internal/use-case/main-use-case/death-cause/middleware-runner.go new file mode 100644 index 00000000..3b0b1aa0 --- /dev/null +++ b/internal/use-case/main-use-case/death-cause/middleware-runner.go @@ -0,0 +1,103 @@ +package deathcause + +import ( + e "simrs-vx/internal/domain/main-entities/death-cause" + 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.DeathCause) 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.DeathCause) 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.DeathCause) 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.DeathCause) 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.DeathCause) 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/death-cause/middleware.go b/internal/use-case/main-use-case/death-cause/middleware.go new file mode 100644 index 00000000..845ec256 --- /dev/null +++ b/internal/use-case/main-use-case/death-cause/middleware.go @@ -0,0 +1,9 @@ +package deathcause + +// 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/death-cause/tycovar.go b/internal/use-case/main-use-case/death-cause/tycovar.go new file mode 100644 index 00000000..9cfe21a6 --- /dev/null +++ b/internal/use-case/main-use-case/death-cause/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 deathcause + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/death-cause" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.DeathCause, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.DeathCause, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.DeathCause, 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/employee/helper.go b/internal/use-case/main-use-case/employee/helper.go index 252d35eb..b0202c08 100644 --- a/internal/use-case/main-use-case/employee/helper.go +++ b/internal/use-case/main-use-case/employee/helper.go @@ -22,6 +22,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Employee) { data.Division_Code = inputSrc.Division_Code data.Number = inputSrc.Number data.Status_Code = inputSrc.Status_Code + data.Position_Code = inputSrc.Position_Code } // func createUser(input *e.CreateDto, event *pl.Event, tx *gorm.DB) error { diff --git a/internal/use-case/main-use-case/encounter/case.go b/internal/use-case/main-use-case/encounter/case.go index fad183f6..5f31e371 100644 --- a/internal/use-case/main-use-case/encounter/case.go +++ b/internal/use-case/main-use-case/encounter/case.go @@ -2,10 +2,13 @@ package encounter import ( "errors" + "fmt" + uir "simrs-vx/internal/use-case/main-use-case/internal-reference" "strconv" ea "simrs-vx/internal/domain/main-entities/ambulatory" ec "simrs-vx/internal/domain/main-entities/chemo" + edc "simrs-vx/internal/domain/main-entities/death-cause" ee "simrs-vx/internal/domain/main-entities/emergency" eem "simrs-vx/internal/domain/main-entities/employee" e "simrs-vx/internal/domain/main-entities/encounter" @@ -13,6 +16,7 @@ import ( ua "simrs-vx/internal/use-case/main-use-case/ambulatory" uc "simrs-vx/internal/use-case/main-use-case/chemo" + udc "simrs-vx/internal/use-case/main-use-case/death-cause" 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" @@ -20,12 +24,12 @@ import ( erc "simrs-vx/internal/domain/references/common" ere "simrs-vx/internal/domain/references/encounter" - 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" + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + "gorm.io/gorm" ) @@ -393,6 +397,7 @@ func CheckOut(input e.DischargeDto) (*d.Data, error) { } return pl.SetLogError(&event, input) } + if err := checkSoapiByDocExists(data.Id, &event, tx); err != nil { return err } @@ -411,6 +416,66 @@ func CheckOut(input e.DischargeDto) (*d.Data, error) { } } + switch *input.Discharge_Method_Code { + case ere.DMCDeath: + // insert data death-cause + if _, err := udc.CreateData(edc.CreateDto{ + Encounter_Id: &input.Id, + Value: input.DeathCause, + }, &event, tx); err != nil { + return err + } + + case ere.DMCConsulPoly, ere.DMCConsulExecutive: + unitIDs := make(map[uint16]struct{}) + doctorIDs := make(map[uint]struct{}) + + for _, ref := range *input.InternalReferences { + if ref.Unit_Id != nil { + unitIDs[*ref.Unit_Id] = struct{}{} + } + if ref.Doctor_Id != nil { + doctorIDs[*ref.Doctor_Id] = struct{}{} + } + } + + // validate unitIds + if len(unitIDs) > 0 { + var ids []uint16 + for id := range unitIDs { + ids = append(ids, id) + } + + units, err := getUnits(ids, &event, tx) + if err != nil { + return fmt.Errorf("failed to fetch units: %w", err) + } + if len(units) != len(ids) { + return fmt.Errorf("unit_id not found") + } + } + + // validate doctorIds + if len(doctorIDs) > 0 { + var ids []uint + for id := range doctorIDs { + ids = append(ids, id) + } + + doctors, err := getDoctors(ids, &event, tx) + if err != nil { + return fmt.Errorf("failed to fetch doctors: %w", err) + } + if len(doctors) != len(ids) { + return fmt.Errorf("doctor_id not found") + } + } + + if err := uir.CreateBulkData(*input.InternalReferences, input.Id, &event, tx); err != nil { + return err + } + } + pl.SetLogInfo(&event, nil, "complete") return nil diff --git a/internal/use-case/main-use-case/encounter/helper.go b/internal/use-case/main-use-case/encounter/helper.go index 7cb72938..36244f83 100644 --- a/internal/use-case/main-use-case/encounter/helper.go +++ b/internal/use-case/main-use-case/encounter/helper.go @@ -8,6 +8,7 @@ import ( "errors" "fmt" "strings" + "time" "gorm.io/gorm" @@ -15,6 +16,7 @@ import ( pu "simrs-vx/pkg/use-case-helper" edo "simrs-vx/internal/domain/main-entities/device-order" + ed "simrs-vx/internal/domain/main-entities/doctor" emo "simrs-vx/internal/domain/main-entities/material-order" emco "simrs-vx/internal/domain/main-entities/mcu-order" em "simrs-vx/internal/domain/main-entities/medication" @@ -23,6 +25,7 @@ import ( emmi "simrs-vx/internal/domain/main-entities/medicine-mix-item" ep "simrs-vx/internal/domain/main-entities/prescription" epi "simrs-vx/internal/domain/main-entities/prescription-item" + eu "simrs-vx/internal/domain/main-entities/unit" // udo "simrs-vx/internal/use-case/main-use-case/device-order" es "simrs-vx/internal/domain/main-entities/soapi" @@ -77,12 +80,15 @@ func setDataUpdate(src e.UpdateDto, dst *e.Encounter) { } func setDataDischarge(src e.DischargeDto, dst *e.Encounter) { - dst.DischargeMethod_Code = src.DischargeMethod_Code + dst.Discharge_Method_Code = src.Discharge_Method_Code dst.EarlyEducation = src.EarlyEducation dst.MedicalDischargeEducation = src.MedicalDischargeEducation dst.AdmDischargeEducation = src.AdmDischargeEducation dst.DischargeReason = src.DischargeReason dst.Status_Code = erc.DSCDone + + now := time.Now() + dst.Discharge_Date = &now } func checkSoapiByDocExists(encounter_id uint, event *pl.Event, tx *gorm.DB) error { @@ -317,3 +323,35 @@ func getMcuOrders(encounter_id uint, event *pl.Event, tx *gorm.DB) error { func setDataUpdateStatus(src e.UpdateStatusDto, dst *e.Encounter) { dst.Status_Code = src.StatusCode } + +func getUnits(unitIds []uint16, event *pl.Event, tx *gorm.DB) ([]eu.Unit, error) { + pl.SetLogInfo(event, nil, "started", "getUnits") + var units []eu.Unit + err := tx.Where("\"Id\" IN ?", unitIds).Find(&units).Error + if err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-get-fail", + Detail: "get units", + Raw: err, + } + return nil, pl.SetLogError(event, nil) + } + return units, nil +} + +func getDoctors(doctorIds []uint, event *pl.Event, tx *gorm.DB) ([]ed.Doctor, error) { + pl.SetLogInfo(event, nil, "started", "getDoctors") + var doctors []ed.Doctor + err := tx.Where("\"Id\" IN ?", doctorIds).Find(&doctors).Error + if err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-get-fail", + Detail: "get doctors", + Raw: err, + } + return nil, pl.SetLogError(event, nil) + } + return doctors, nil +} diff --git a/internal/use-case/main-use-case/internal-reference/case.go b/internal/use-case/main-use-case/internal-reference/case.go index 1681bf26..bfd9550f 100644 --- a/internal/use-case/main-use-case/internal-reference/case.go +++ b/internal/use-case/main-use-case/internal-reference/case.go @@ -1,19 +1,9 @@ package internal_reference import ( - - // main entities - ed "simrs-vx/internal/domain/main-entities/doctor" - ee "simrs-vx/internal/domain/main-entities/encounter" eir "simrs-vx/internal/domain/main-entities/internal-reference" - eu "simrs-vx/internal/domain/main-entities/unit" "strconv" - // main use case - ud "simrs-vx/internal/use-case/main-use-case/doctor" - ue "simrs-vx/internal/use-case/main-use-case/encounter" - uu "simrs-vx/internal/use-case/main-use-case/unit" - pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" @@ -43,11 +33,6 @@ func Create(input eir.CreateDto) (*d.Data, error) { return err } - // Validate Request - if err := validateRequest(input); err != nil { - return err - } - if resData, err := CreateData(input, &event, tx); err != nil { return err } else { @@ -179,29 +164,6 @@ func ReadDetail(input eir.ReadDetailDto) (*d.Data, error) { }, nil } -func validateRequest(input eir.CreateDto) (err error) { - - // Validate Encounter Id - _, err = ue.ReadDetail(ee.ReadDetailDto{Id: uint16(*input.Encounter_Id)}) - if err != nil { - return err - } - - // Validate Unit Id - _, err = uu.ReadDetail(eu.ReadDetailDto{Id: *input.Unit_Id}) - if err != nil { - return err - } - - // Validate Doctor Id - _, err = ud.ReadDetail(ed.ReadDetailDto{Id: uint16(*input.Doctor_Id)}) - if err != nil { - return err - } - - return -} - func Update(input eir.UpdateDto) (*d.Data, error) { rdDto := eir.ReadDetailDto{Id: input.Id} var data *eir.InternalReference @@ -228,21 +190,10 @@ func Update(input eir.UpdateDto) (*d.Data, error) { return err } - // Validate Request - if err := validateRequest(input.CreateDto); err != nil { - return err - } - if err := UpdateData(input, data, &event, tx); err != nil { return err } - // Get Updated Data - rdDto.Includes = "encounter,unit,doctor" - if data, err = ReadDetailData(rdDto, &event, tx); err != nil { - return err - } - pl.SetLogInfo(&event, nil, "complete") mwRunner.setMwType(pu.MWTPost) diff --git a/internal/use-case/main-use-case/internal-reference/helper.go b/internal/use-case/main-use-case/internal-reference/helper.go index aaef382a..dbd92f73 100644 --- a/internal/use-case/main-use-case/internal-reference/helper.go +++ b/internal/use-case/main-use-case/internal-reference/helper.go @@ -21,3 +21,17 @@ func setData[T *ir.CreateDto | *ir.UpdateDto](input T, data *ir.InternalReferenc data.Unit_Id = inputSrc.Unit_Id data.Doctor_Id = inputSrc.Doctor_Id } + +func setBulkData(input []ir.CreateDto, encounterId uint) []ir.InternalReference { + var data []ir.InternalReference + + for _, v := range input { + data = append(data, ir.InternalReference{ + Encounter_Id: &encounterId, + Unit_Id: v.Unit_Id, + Doctor_Id: v.Doctor_Id, + }) + } + + return data +} diff --git a/internal/use-case/main-use-case/internal-reference/lib.go b/internal/use-case/main-use-case/internal-reference/lib.go index a50d594c..bf852dc6 100644 --- a/internal/use-case/main-use-case/internal-reference/lib.go +++ b/internal/use-case/main-use-case/internal-reference/lib.go @@ -142,3 +142,23 @@ func DeleteData(data *eir.InternalReference, event *pl.Event, dbx ...*gorm.DB) e pl.SetLogInfo(event, nil, "complete") return nil } + +func CreateBulkData(input []eir.CreateDto, encounterId uint, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := setBulkData(input, encounterId) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if err := tx.Create(&data).Error; err != nil { + return plh.HandleCreateError(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return nil +} diff --git a/internal/use-case/main-use-case/user/helper.go b/internal/use-case/main-use-case/user/helper.go index 1663bb24..cb640dcb 100644 --- a/internal/use-case/main-use-case/user/helper.go +++ b/internal/use-case/main-use-case/user/helper.go @@ -49,6 +49,7 @@ func setDataEmployeeUpdate(src e.EmployeUpdateDto) ee.UpdateDto { Division_Code: src.Division_Code, Number: src.Number, Status_Code: src.Status_Code, + Position_Code: &src.Position_Code, }, } }