From 27ba102ca763bfe44e93961c56866867a1ca74d7 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Fri, 3 Oct 2025 11:05:49 +0700 Subject: [PATCH 1/6] migration from server --- cmd/main-migration/migrations/atlas.sum | 50 ++++++++++++------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 571f69da..cc9c7026 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,25 +1,25 @@ -h1:EkXfc/qeBa+6Fog89GGHEbrpjWfLwy/t6MQdrP9tImE= -20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= -20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= -20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= -20250908062323.sql h1:oXl6Z143tOpIl4EfP4B8JNU8LrMvVmHEtCgAfiB4gs8= -20250908073811.sql h1:m2aNXfnGxnLq1+rVWrh4f60q7fhyhV3gEwNu/OIqQlE= -20250908073839.sql h1:cPk54xjLdMs26uY8ZHjNWLuyfAMzV7Zb0/9oJQrsw04= -20250910055902.sql h1:5xwjAV6QbtZT9empTJKfhyAjdknbHzb15B0Ku5dzqtQ= -20250915123412.sql h1:D83xaU2YlDEd21HLup/YQpQ2easMToYCyy/oK6AFgQs= -20250916043819.sql h1:ekoTJsBqQZ8G8n0qJ03d13+eoNoc7sAUEQGA5D/CCxk= -20250917040616.sql h1:zoCnmcXuM7AVv85SmN7RmFglCgJnoDmpRWExH0LAc9Q= -20250917040751.sql h1:J1xyRrh32y1+lezwAyNwPcUQ6ABBSgbvzNLva4SVdQU= -20250917045138.sql h1:jKe1Z0uOLG4SGBYM+S/3P+/zMPztmgoderD5swnMuCg= -20250917093645.sql h1:cNI3Pbz1R3LxvIXLuexafJFCXUXrmuFCgXXJ2sG+FW0= -20250918073552.sql h1:RJ1SvMzP6aeWnoPVD3eVAmIQOkcp6Php8z3QRri6v4g= -20250918073742.sql h1:+cEsnJTJFybe2fR69ZoOiX2R6c6iITl4m6WTZ1hjyzY= -20250918074745.sql h1:2hNVQCXF/dVYXAh+T/7oBFgERGWxzVb2FXJjwkFWGCI= -20250923025134.sql h1:Ykz/qpHiGDXPsCsWTjydQFVSibZP2D+h2fIeb2h2JGA= -20250924051317.sql h1:yQuW6SwJxIOM5fcxeAaie5lSm1oLysU/C2hH2xNCVoQ= -20250929034321.sql h1:101FJ8VH12mrZWlt/X1gvKUGOhoiF8tFbjiapAjnHzg= -20250929034428.sql h1:i+pROD9p+g5dOmmZma6WF/0Hw5g3Ha28NN85iTo1K34= -20250930025550.sql h1:+F+CsCUXD/ql0tHGEow70GhPBX1ZybVn+bh/T4YMh7Y= -20250930140351.sql h1:9AAEG1AnOAH+o0+oHL5G7I8vqlWOhwRlCGyyCpT/y1Q= -20251002085604.sql h1:3xZ68eYp4urXRnvotNH1XvG2mYOSDV/j3zHEZ/txg5E= -20251003032030.sql h1:hdN6UINPM9Pz9ME6uP3pr6PNCqqz4y7h2qY1UlVjw60= +h1:x6PUnQLcwgdcTvuTAMcDT6t9fPz/u1d1YFIFXyuGIKU= +20250904105930.sql h1:Vv4vCurl7m7/ZB6TjRpkubHpQ4RYwSUn0QHdzfoGpzY= +20250904141448.sql h1:FYCHH9Os4KkrZMDu/jR8FMP+wLMRW+Mb0PkLU/9BRDg= +20250908062237.sql h1:oanBpKZd+akPu2I/xYhUSbd0G5tAFbXzKLER/Zs8ENI= +20250908062323.sql h1:miNG9COddXkD1jGTgaROMAZ618eT6oiLGiJhXWnQwhE= +20250908073811.sql h1:gOi5cnGG1htlpfizybYmUIT0vYjZTBfXiI0nPSYK2u8= +20250908073839.sql h1:cWNDA4YikjoOteAJuNLFILjQUJPFB6o8Wxreiek4QyI= +20250910055902.sql h1:nxxOGnU0BbH/v3IPgeIOXOwH8d3tKomw7h6FTeMnnBs= +20250915123412.sql h1:mz7SiWfrdf0qE1VTSAAnA/147d6gyp6ry5vZ2bR9SH0= +20250916043819.sql h1:RHXVtmMkB6wfv06HfPyHMBmUfIpFt1xveafNz0kwKnE= +20250917040616.sql h1:MYVDht+akBlzQGKNu2hTTTLPEcH1bxT/Q8MK6WEtuhs= +20250917040751.sql h1:J79YyS2JzWgh5oKXMTgh67uo3gLxKaAsxRiZmSIfjBs= +20250917045138.sql h1:/SM1N4O8X3yxpoJgMEARmS1uOkuLKsTOy4PLsRCOKaQ= +20250917093645.sql h1:PNBTGZ7s10e5b5+Tie8YfVQBN0zKtJ5T34oK1iOUEb4= +20250918073552.sql h1:jG7+g3i8ODYaJdcdZz12v3nbsZ5mB9wG6kWnGyTQIRI= +20250918073742.sql h1:j+rgw7puxE7s+phqPVZHmPk0af3rcaA56Itp86y1suY= +20250918074745.sql h1:rPmP4DXs6OnY4Vp+xO/z9jFpJt/RrJ52SJJjIIxeDvc= +20250923025134.sql h1:2r6pcwnBSU5Y9Czk1OHBoh4yZXiMtEca9X8843fTEX0= +20250924051317.sql h1:iUAk2gsGoEGIPQ0lEEUp8maMSId8emNbP+kP712ABIA= +20250929034321.sql h1:UlpALNVmdi95zOIT0yc6ZyTj9bBjQEIpZhvgrc52M+k= +20250929034428.sql h1:feF+H4nDyHh5bdx48Oiz0A1qecZfi6v3qTTdjzJ45Dg= +20250930025550.sql h1:6XT1kXI3Z3ZIxxmvT7poufZWWCW0QiejZPaFV5wBnjI= +20250930140351.sql h1:HxnmAbh9gCy8jwl/9ycGktiByaUripsjFFvohofY2CY= +20251002085604.sql h1:SjLPi+ZN6qDccK3DaEQCgNsZpPwr5kynWXwbwEsziCI= +20251003032030.sql h1:oHfxNSuqTxU8Zaf9H+h8TuUb1Da03wcyc6hZjDrUQ2s= From ad358e4f79a65696a363cdf7d585001b49b30aea Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Sun, 5 Oct 2025 13:01:43 +0700 Subject: [PATCH 2/6] feat (chemo): add entities --- internal/domain/main-entities/chemo/dto.go | 86 +++++++++++++++++++ internal/domain/main-entities/chemo/entity.go | 24 ++++++ 2 files changed, 110 insertions(+) create mode 100644 internal/domain/main-entities/chemo/dto.go create mode 100644 internal/domain/main-entities/chemo/entity.go diff --git a/internal/domain/main-entities/chemo/dto.go b/internal/domain/main-entities/chemo/dto.go new file mode 100644 index 00000000..cf01b8ad --- /dev/null +++ b/internal/domain/main-entities/chemo/dto.go @@ -0,0 +1,86 @@ +package chemo + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ee "simrs-vx/internal/domain/main-entities/encounter" + eun "simrs-vx/internal/domain/main-entities/unit" + eus "simrs-vx/internal/domain/main-entities/user" + "time" + + erc "simrs-vx/internal/domain/references/common" +) + +type CreateDto struct { + Encounter_Id *uint `json:"encounter_id"` + Status_Code erc.DataStatusCode `json:"status_code"` + VerifiedBy_User_Id *uint `json:"verifiedBy_user_id"` + SrcUnit_Id *uint `json:"src_unit_id"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Preloads []string `json:"-"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Encounter_Id *uint `json:"encounter_id"` + Status_Code *erc.DataVerifiedCode `json:"status_code"` + VerifiedBy_User_Id *uint `json:"verifiedBy_user_id"` + SrcUnit_Id *uint `json:"src_unit_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"` + Encounter *ee.Encounter `json:"encounter,omitempty"` + Status_Code erc.DataVerifiedCode `json:"status_code"` + VerifiedAt *time.Time `json:"verifiedAt"` + VerifiedBy_User_Id *uint `json:"verifiedBy_user_id"` + VerifiedBy *eus.User `json:"verifiedBy,omitempty"` + SrcUnit_Id *uint `json:"src_unit_id"` + SrcUnit *eun.Unit `json:"src_unit,omitempty"` +} + +func (d Chemo) ToResponse() ResponseDto { + resp := ResponseDto{ + Encounter_Id: d.Encounter_Id, + Encounter: d.Encounter, + Status_Code: d.Status_Code, + VerifiedAt: d.VerifiedAt, + VerifiedBy_User_Id: d.VerifiedBy_User_Id, + VerifiedBy: d.VerifiedBy, + SrcUnit_Id: d.SrcUnit_Id, + SrcUnit: d.SrcUnit, + } + resp.Main = d.Main + return resp +} + +func ToResponseList(data []Chemo) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/chemo/entity.go b/internal/domain/main-entities/chemo/entity.go new file mode 100644 index 00000000..2ba83990 --- /dev/null +++ b/internal/domain/main-entities/chemo/entity.go @@ -0,0 +1,24 @@ +package chemo + +import ( + "time" + + ecore "simrs-vx/internal/domain/base-entities/core" + ee "simrs-vx/internal/domain/main-entities/encounter" + eun "simrs-vx/internal/domain/main-entities/unit" + eus "simrs-vx/internal/domain/main-entities/user" + + erc "simrs-vx/internal/domain/references/common" +) + +type Chemo struct { + ecore.Main // adjust this according to the needs + Encounter_Id *uint `json:"encounter_id"` + Encounter *ee.Encounter `json:"encounter,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` + Status_Code erc.DataVerifiedCode `json:"status_code"` + VerifiedAt *time.Time `json:"verifiedAt"` + VerifiedBy_User_Id *uint `json:"verifiedBy_user_id"` + VerifiedBy *eus.User `json:"verifiedBy,omitempty" gorm:"foreignKey:VerifiedBy_User_Id;references:Id"` + SrcUnit_Id *uint `json:"src_unit_id"` + SrcUnit *eun.Unit `json:"src_unit,omitempty" gorm:"foreignKey:SrcUnit_Id;references:Id"` +} From 3a68aac53eed9c592e7aa8ba2f8ba2128350f60f Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Sun, 5 Oct 2025 13:02:19 +0700 Subject: [PATCH 3/6] feat (consultation): update column and adjust --- .../domain/main-entities/consultation/dto.go | 34 ++++++++++--------- .../main-entities/consultation/entity.go | 16 +++++---- internal/interface/migration/main-entities.go | 2 ++ .../main-use-case/consultation/case.go | 4 +-- .../main-use-case/consultation/helper.go | 5 +-- 5 files changed, 34 insertions(+), 27 deletions(-) diff --git a/internal/domain/main-entities/consultation/dto.go b/internal/domain/main-entities/consultation/dto.go index a13231da..7b53f90f 100644 --- a/internal/domain/main-entities/consultation/dto.go +++ b/internal/domain/main-entities/consultation/dto.go @@ -12,9 +12,10 @@ import ( ) type CreateDto struct { - Encounter_Id *uint `json:"encounter_id"` - Case *string `json:"case" validate:"maxLength=2048"` - Unit_Id *uint `json:"unit_id"` + Encounter_Id *uint `json:"encounter_id"` + Date *time.Time `json:"date"` + Problem *string `json:"problem" validate:"maxLength=10240"` + DstUnit_Id *uint `json:"dstUnit_id"` } type ReadListDto struct { @@ -26,8 +27,8 @@ type ReadListDto struct { type FilterDto struct { Encounter_Id *uint `json:"encounter_id"` - Unit_Id *uint `json:"unit_id"` - Doctor_Id *uint `json:"doctor_id"` + DstUnit_Id *uint `json:"dstUnit_id"` + DstDoctor_Id *uint `json:"dstDoctor_id"` } type ReadDetailDto struct { @@ -60,12 +61,13 @@ type ResponseDto struct { ecore.Main Encounter_Id *uint `json:"encounter_id"` Encounter *ee.Encounter `json:"encounter,omitempty"` - Case *string `json:"case"` + Date *time.Time `json:"date"` + Problem *string `json:"problem"` Solution *string `json:"solution"` - Unit_Id *uint `json:"unit_id"` - Unit *eu.Unit `json:"unit,omitempty"` - Doctor_Id *uint `json:"doctor_id"` - Doctor *ed.Doctor `json:"doctor,omitempty"` + DstUnit_Id *uint `json:"dstUnit_id"` + DstUnit *eu.Unit `json:"dstUnit,omitempty"` + DstDoctor_Id *uint `json:"dstDoctor_id"` + DstDoctor *ed.Doctor `json:"dstDoctor,omitempty"` RepliedAt *time.Time `json:"repliedAt"` } @@ -73,13 +75,13 @@ func (d Consultation) ToResponse() ResponseDto { resp := ResponseDto{ Encounter_Id: d.Encounter_Id, Encounter: d.Encounter, - Case: d.Case, + Date: d.Date, + Problem: d.Problem, Solution: d.Solution, - Unit_Id: d.Unit_Id, - Unit: d.Unit, - Doctor_Id: d.Doctor_Id, - Doctor: d.Doctor, - RepliedAt: d.RepliedAt, + DstUnit_Id: d.DstUnit_Id, + DstUnit: d.DstUnit, + DstDoctor_Id: d.DstDoctor_Id, + DstDoctor: d.DstDoctor, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/consultation/entity.go b/internal/domain/main-entities/consultation/entity.go index 68ad37f2..2fda8bd0 100644 --- a/internal/domain/main-entities/consultation/entity.go +++ b/internal/domain/main-entities/consultation/entity.go @@ -13,11 +13,13 @@ type Consultation struct { ecore.Main // adjust this according to the needs Encounter_Id *uint `json:"encounter_id"` Encounter *ee.Encounter `json:"encounter" gorm:"foreignKey:Encounter_Id;references:Id"` - Case *string `json:"case" gorm:"size:2048"` - Solution *string `json:"solution" gorm:"size:2048"` - Unit_Id *uint `json:"unit_id"` - Unit *eu.Unit `json:"unit" gorm:"foreignKey:Unit_Id;references:Id"` - Doctor_Id *uint `json:"doctor_id"` - Doctor *ed.Doctor `json:"doctor" gorm:"foreignKey:Doctor_Id;references:Id"` - RepliedAt *time.Time `json:"repliedAt"` + Date *time.Time `json:"date"` + + Problem *string `json:"case" gorm:"size:10240"` + Solution *string `json:"solution" gorm:"size:10240"` + DstUnit_Id *uint `json:"dstUnit_id"` + DstUnit *eu.Unit `json:"dstUnit" gorm:"foreignKey:DstUnit_Id;references:Id"` + DstDoctor_Id *uint `json:"dstDoctor_id"` + DstDoctor *ed.Doctor `json:"dstDoctor" gorm:"foreignKey:DstDoctor_Id;references:Id"` + RepliedAt *time.Time `json:"repliedAt"` } diff --git a/internal/interface/migration/main-entities.go b/internal/interface/migration/main-entities.go index 6e582af2..4d0f79c1 100644 --- a/internal/interface/migration/main-entities.go +++ b/internal/interface/migration/main-entities.go @@ -4,6 +4,7 @@ import ( adime "simrs-vx/internal/domain/main-entities/adime" ambulatory "simrs-vx/internal/domain/main-entities/ambulatory" appointment "simrs-vx/internal/domain/main-entities/appointment" + chemo "simrs-vx/internal/domain/main-entities/chemo" consultation "simrs-vx/internal/domain/main-entities/consultation" counter "simrs-vx/internal/domain/main-entities/counter" device "simrs-vx/internal/domain/main-entities/device" @@ -145,5 +146,6 @@ func getMainEntities() []any { &mcusubsrc.McuSubSrc{}, &mcuordersubitem.McuOrderSubItem{}, &consultation.Consultation{}, + &chemo.Chemo{}, } } diff --git a/internal/use-case/main-use-case/consultation/case.go b/internal/use-case/main-use-case/consultation/case.go index 683ece20..1b20d463 100644 --- a/internal/use-case/main-use-case/consultation/case.go +++ b/internal/use-case/main-use-case/consultation/case.go @@ -322,7 +322,7 @@ func Reply(input e.ReplyDto) (*d.Data, error) { return err } - if data.Doctor_Id != nil && data.Doctor_Id != doctor_id { + if data.DstDoctor_Id != nil && data.DstDoctor_Id != doctor_id { event.Status = "failed" event.ErrInfo = pl.ErrorInfo{ Code: "data-handled-mismatch", @@ -332,7 +332,7 @@ func Reply(input e.ReplyDto) (*d.Data, error) { return pl.SetLogError(&event, input) } - data.Doctor_Id = doctor_id + data.DstDoctor_Id = doctor_id data.Solution = input.Solution data.RepliedAt = pu.GetTimeNow() err = tx.Save(&data).Error diff --git a/internal/use-case/main-use-case/consultation/helper.go b/internal/use-case/main-use-case/consultation/helper.go index 7df4a9f9..519c3c91 100644 --- a/internal/use-case/main-use-case/consultation/helper.go +++ b/internal/use-case/main-use-case/consultation/helper.go @@ -18,6 +18,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Consultation) { } data.Encounter_Id = inputSrc.Encounter_Id - data.Case = inputSrc.Case - data.Unit_Id = inputSrc.Unit_Id + data.Date = inputSrc.Date + data.Problem = inputSrc.Problem + data.DstUnit_Id = inputSrc.DstUnit_Id } From b603a05980fc2ea63d8d14ae18d8afefbdfc4012 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Sun, 5 Oct 2025 13:03:51 +0700 Subject: [PATCH 4/6] feat (person): add column nationality and adjust --- internal/domain/main-entities/person/dto.go | 4 ++++ internal/domain/main-entities/person/entity.go | 1 + internal/use-case/main-use-case/person/helper.go | 1 + 3 files changed, 6 insertions(+) diff --git a/internal/domain/main-entities/person/dto.go b/internal/domain/main-entities/person/dto.go index b946436b..3cfe18f2 100644 --- a/internal/domain/main-entities/person/dto.go +++ b/internal/domain/main-entities/person/dto.go @@ -26,6 +26,7 @@ type CreateDto struct { Education_Code *erp.EducationCode `json:"education_code" validate:"maxLength=10"` Ocupation_Code *erp.OcupationCode `json:"occupation_code" validate:"maxLength=15"` Ocupation_Name *string `json:"occupation_name" validate:"maxLength=50"` + Nationality *string `json:"nationality" validate:"maxLength=50"` Ethnic_Code *string `json:"ethnic_code" validate:"maxLength=20"` Language_Code *string `json:"language_code" validate:"maxLength=10"` } @@ -51,6 +52,7 @@ type FilterDto struct { Education_Code *erp.EducationCode `json:"education_code"` Ocupation_Code *erp.OcupationCode `json:"occupation_code"` Ocupation_Name *string `json:"occupation_name"` + Nationality *string `json:"nationality"` Ethnic_Code *string `json:"ethnic_code"` Language_Code *string `json:"language_code"` } @@ -93,6 +95,7 @@ type ResponseDto struct { Education_Code *erp.EducationCode `json:"education_code"` Ocupation_Code *erp.OcupationCode `json:"occupation_code"` Ocupation_Name *string `json:"occupation_name"` + Nationality *string `json:"nationality"` Ethnic_Code *string `json:"ethnic_code"` Ethnic *ee.Ethnic `json:"ethnic,omitempty"` Addresses *[]epa.PersonAddress `json:"addresses,omitempty"` @@ -120,6 +123,7 @@ func (d *Person) ToResponse() ResponseDto { Education_Code: d.Education_Code, Ocupation_Code: d.Ocupation_Code, Ocupation_Name: d.Ocupation_Name, + Nationality: d.Nationality, Ethnic_Code: d.Ethnic_Code, Ethnic: d.Ethnic, Addresses: d.Addresses, diff --git a/internal/domain/main-entities/person/entity.go b/internal/domain/main-entities/person/entity.go index 37e2086c..0f12fcd3 100644 --- a/internal/domain/main-entities/person/entity.go +++ b/internal/domain/main-entities/person/entity.go @@ -27,6 +27,7 @@ type Person struct { Education_Code *erp.EducationCode `json:"education_code" gorm:"size:10"` Ocupation_Code *erp.OcupationCode `json:"occupation_code" gorm:"size:15"` Ocupation_Name *string `json:"occupation_name" gorm:"size:50"` + Nationality *string `json:"nationality": gorm:"size:50"` Ethnic_Code *string `json:"ethnic_code" gorm:"size:20"` Ethnic *ee.Ethnic `json:"ethnic,omitempty" gorm:"foreignKey:Ethnic_Code;references:Code"` Addresses *[]epa.PersonAddress `json:"addresses" gorm:"foreignKey:Person_Id"` diff --git a/internal/use-case/main-use-case/person/helper.go b/internal/use-case/main-use-case/person/helper.go index a2588c0e..f412a268 100644 --- a/internal/use-case/main-use-case/person/helper.go +++ b/internal/use-case/main-use-case/person/helper.go @@ -30,6 +30,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Person) { data.Education_Code = inputSrc.Education_Code data.Ocupation_Code = inputSrc.Ocupation_Code data.Ocupation_Name = inputSrc.Ocupation_Name + data.Nationality = inputSrc.Nationality data.Ethnic_Code = inputSrc.Ethnic_Code data.Language_Code = inputSrc.Language_Code } From 6c91c6df59d3dd7764a5c2bbb1154d84ceb7943d Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Sun, 5 Oct 2025 13:05:36 +0700 Subject: [PATCH 5/6] run migration --- .../migrations/20251005060450.sql | 24 +++++++++++++++++++ cmd/main-migration/migrations/atlas.sum | 5 ++-- 2 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 cmd/main-migration/migrations/20251005060450.sql diff --git a/cmd/main-migration/migrations/20251005060450.sql b/cmd/main-migration/migrations/20251005060450.sql new file mode 100644 index 00000000..7ec05f92 --- /dev/null +++ b/cmd/main-migration/migrations/20251005060450.sql @@ -0,0 +1,24 @@ +-- Modify "Person" table +ALTER TABLE "public"."Person" ADD COLUMN "Nationality" text NULL; +-- Create "Chemo" table +CREATE TABLE "public"."Chemo" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NULL, + "Status_Code" text NULL, + "VerifiedAt" timestamptz NULL, + "VerifiedBy_User_Id" bigint NULL, + "SrcUnit_Id" bigint NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_Chemo_Encounter" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Chemo_SrcUnit" FOREIGN KEY ("SrcUnit_Id") REFERENCES "public"."Unit" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, + CONSTRAINT "fk_Chemo_VerifiedBy" FOREIGN KEY ("VerifiedBy_User_Id") REFERENCES "public"."User" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); +-- Rename a column from "Unit_Id" to "DstUnit_Id" +ALTER TABLE "public"."Consultation" RENAME COLUMN "Unit_Id" TO "DstUnit_Id"; +-- Rename a column from "Doctor_Id" to "DstDoctor_Id" +ALTER TABLE "public"."Consultation" RENAME COLUMN "Doctor_Id" TO "DstDoctor_Id"; +-- Modify "Consultation" table +ALTER TABLE "public"."Consultation" DROP CONSTRAINT "fk_Consultation_Doctor", DROP CONSTRAINT "fk_Consultation_Unit", DROP COLUMN "Case", ALTER COLUMN "Solution" TYPE character varying(10240), ADD COLUMN "Date" timestamptz NULL, ADD COLUMN "Problem" character varying(10240) NULL, ADD CONSTRAINT "fk_Consultation_DstDoctor" FOREIGN KEY ("DstDoctor_Id") REFERENCES "public"."Doctor" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION, ADD CONSTRAINT "fk_Consultation_DstUnit" FOREIGN KEY ("DstUnit_Id") REFERENCES "public"."Unit" ("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 571f69da..649eb37f 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:EkXfc/qeBa+6Fog89GGHEbrpjWfLwy/t6MQdrP9tImE= +h1:kjCOkexwu0wdD+/FPTIz43E0F/a1LI1VtyxR9B+CWyo= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -22,4 +22,5 @@ h1:EkXfc/qeBa+6Fog89GGHEbrpjWfLwy/t6MQdrP9tImE= 20250930025550.sql h1:+F+CsCUXD/ql0tHGEow70GhPBX1ZybVn+bh/T4YMh7Y= 20250930140351.sql h1:9AAEG1AnOAH+o0+oHL5G7I8vqlWOhwRlCGyyCpT/y1Q= 20251002085604.sql h1:3xZ68eYp4urXRnvotNH1XvG2mYOSDV/j3zHEZ/txg5E= -20251003032030.sql h1:hdN6UINPM9Pz9ME6uP3pr6PNCqqz4y7h2qY1UlVjw60= +20251003032030.sql h1:HB+mQ2lXMNomHDpaRhB/9IwYI9/YiDO5eOJ+nAQH/jw= +20251005060450.sql h1:zM3l4oB0U1kNpAvz47IBBIKdRW0QOGylzWHiBNLfUzs= From 854143ef42d1458619e68c8b49760e737ae8f92a Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Sun, 5 Oct 2025 14:38:33 +0700 Subject: [PATCH 6/6] feat (chemo): add handler, use case, and handle in encounter --- internal/domain/main-entities/chemo/dto.go | 19 +- .../interface/main-handler/chemo/handler.go | 114 ++++++ .../interface/main-handler/main-handler.go | 11 + internal/use-case/main-use-case/chemo/case.go | 346 ++++++++++++++++++ .../use-case/main-use-case/chemo/helper.go | 23 ++ internal/use-case/main-use-case/chemo/lib.go | 151 ++++++++ .../main-use-case/chemo/middleware-runner.go | 103 ++++++ .../main-use-case/chemo/middleware.go | 9 + .../use-case/main-use-case/chemo/tycovar.go | 44 +++ .../use-case/main-use-case/encounter/case.go | 16 + 10 files changed, 831 insertions(+), 5 deletions(-) create mode 100644 internal/interface/main-handler/chemo/handler.go create mode 100644 internal/use-case/main-use-case/chemo/case.go create mode 100644 internal/use-case/main-use-case/chemo/helper.go create mode 100644 internal/use-case/main-use-case/chemo/lib.go create mode 100644 internal/use-case/main-use-case/chemo/middleware-runner.go create mode 100644 internal/use-case/main-use-case/chemo/middleware.go create mode 100644 internal/use-case/main-use-case/chemo/tycovar.go diff --git a/internal/domain/main-entities/chemo/dto.go b/internal/domain/main-entities/chemo/dto.go index cf01b8ad..9b50b37c 100644 --- a/internal/domain/main-entities/chemo/dto.go +++ b/internal/domain/main-entities/chemo/dto.go @@ -1,20 +1,22 @@ package chemo import ( + "time" + ecore "simrs-vx/internal/domain/base-entities/core" ee "simrs-vx/internal/domain/main-entities/encounter" eun "simrs-vx/internal/domain/main-entities/unit" eus "simrs-vx/internal/domain/main-entities/user" - "time" erc "simrs-vx/internal/domain/references/common" + + pa "simrs-vx/pkg/auth-helper" ) type CreateDto struct { - Encounter_Id *uint `json:"encounter_id"` - Status_Code erc.DataStatusCode `json:"status_code"` - VerifiedBy_User_Id *uint `json:"verifiedBy_user_id"` - SrcUnit_Id *uint `json:"src_unit_id"` + Encounter_Id *uint `json:"encounter_id"` + Status_Code erc.DataVerifiedCode `json:"status_code"` + SrcUnit_Id *uint `json:"src_unit_id"` } type ReadListDto struct { @@ -44,6 +46,13 @@ type DeleteDto struct { Id uint16 `json:"id"` } +type VerifyDto struct { + Id uint16 `json:"id"` + Status_Code erc.DataVerifiedCode `json:"status_code"` + + pa.AuthInfo +} + type MetaDto struct { PageNumber int `json:"page_number"` PageSize int `json:"page_size"` diff --git a/internal/interface/main-handler/chemo/handler.go b/internal/interface/main-handler/chemo/handler.go new file mode 100644 index 00000000..ee8c0435 --- /dev/null +++ b/internal/interface/main-handler/chemo/handler.go @@ -0,0 +1,114 @@ +package chemo + +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/chemo" + + erc "simrs-vx/internal/domain/references/common" + + u "simrs-vx/internal/use-case/main-use-case/chemo" + + pa "simrs-vx/pkg/auth-helper" + + d "github.com/karincake/dodol" +) + +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) +} + +func (obj myBase) Verify(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.VerifyDto{} + dto.Id = uint16(id) + authInfo, err := pa.GetAuthInfo(r) + if err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil) + } + dto.AuthInfo = *authInfo + dto.Status_Code = erc.DVCVerified + res, err := u.Verify(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Reject(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.VerifyDto{} + dto.Id = uint16(id) + authInfo, err := pa.GetAuthInfo(r) + if err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil) + } + dto.AuthInfo = *authInfo + dto.Status_Code = erc.DVCRejected + res, err := u.Verify(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 87325400..f718697d 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -6,6 +6,7 @@ import ( /******************** main / transaction ********************/ adime "simrs-vx/internal/interface/main-handler/adime" auth "simrs-vx/internal/interface/main-handler/authentication" + chemo "simrs-vx/internal/interface/main-handler/chemo" consultation "simrs-vx/internal/interface/main-handler/consultation" counter "simrs-vx/internal/interface/main-handler/counter" deviceorder "simrs-vx/internal/interface/main-handler/device-order" @@ -220,6 +221,16 @@ func SetRoutes() http.Handler { "PATCH /{id}/reply": consultation.O.Reply, }) + hk.GroupRoutes("/v1/chemo", r, auth.GuardMW, hk.MapHandlerFunc{ + "GET /": chemo.O.GetList, + "GET /{id}": chemo.O.GetDetail, + "POST /": chemo.O.Create, + "PATCH /{id}": chemo.O.Update, + "DELETE /{id}": chemo.O.Delete, + "PATCH /{id}/verify": chemo.O.Verify, + "PATCH /{id}/reject": chemo.O.Reject, + }) + /******************** actor ********************/ hc.RegCrud(r, "/v1/person", person.O) hc.RegCrud(r, "/v1/person-address", personaddress.O) diff --git a/internal/use-case/main-use-case/chemo/case.go b/internal/use-case/main-use-case/chemo/case.go new file mode 100644 index 00000000..7167588b --- /dev/null +++ b/internal/use-case/main-use-case/chemo/case.go @@ -0,0 +1,346 @@ +package chemo + +import ( + "errors" + "strconv" + + e "simrs-vx/internal/domain/main-entities/chemo" + + erc "simrs-vx/internal/domain/references/common" + + 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 = "division" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.Chemo{} + + 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.Chemo + var dataList []e.Chemo + 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 len(input.Includes) > 0 { + input.Preloads = pu.GetPreloads(input.Includes) + } + 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.Chemo + 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.Chemo + 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.Chemo + 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 + +} + +func Verify(input e.VerifyDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.Chemo + var err error + + event := pl.Event{ + Feature: "Verify", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "verify") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + return err + } + + if data.Status_Code != erc.DVCNew { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-state-mismatch", + Detail: "data is not new", + Raw: errors.New("data is not new"), + } + return pl.SetLogError(&event, input) + } + + data.VerifiedAt = pu.GetTimeNow() + data.Status_Code = input.Status_Code + data.VerifiedBy_User_Id = &input.AuthInfo.User_Id + + err = tx.Save(&data).Error + if 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 + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "verify", + }, + Data: data.ToResponse(), + }, nil +} diff --git a/internal/use-case/main-use-case/chemo/helper.go b/internal/use-case/main-use-case/chemo/helper.go new file mode 100644 index 00000000..bb60a39b --- /dev/null +++ b/internal/use-case/main-use-case/chemo/helper.go @@ -0,0 +1,23 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package chemo + +import ( + e "simrs-vx/internal/domain/main-entities/chemo" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Chemo) { + 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.Status_Code = inputSrc.Status_Code + data.SrcUnit_Id = inputSrc.SrcUnit_Id +} diff --git a/internal/use-case/main-use-case/chemo/lib.go b/internal/use-case/main-use-case/chemo/lib.go new file mode 100644 index 00000000..0fa1d51e --- /dev/null +++ b/internal/use-case/main-use-case/chemo/lib.go @@ -0,0 +1,151 @@ +package chemo + +import ( + e "simrs-vx/internal/domain/main-entities/chemo" + + 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.Chemo, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.Chemo{} + 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.Chemo, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.Chemo{} + pagination := gh.Pagination{} + count := int64(0) + meta := e.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if len(input.Preloads) > 0 { + for _, preload := range input.Preloads { + tx = tx.Preload(preload) + } + } + + tx = tx. + Model(&e.Chemo{}). + Scopes(gh.Filter(input.FilterDto)). + 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.Chemo, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.Chemo{} + + 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.Chemo, 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.Chemo, 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/chemo/middleware-runner.go b/internal/use-case/main-use-case/chemo/middleware-runner.go new file mode 100644 index 00000000..a29ded7a --- /dev/null +++ b/internal/use-case/main-use-case/chemo/middleware-runner.go @@ -0,0 +1,103 @@ +package chemo + +import ( + e "simrs-vx/internal/domain/main-entities/chemo" + 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.Chemo) 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.Chemo) 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.Chemo) 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.Chemo) 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.Chemo) 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/chemo/middleware.go b/internal/use-case/main-use-case/chemo/middleware.go new file mode 100644 index 00000000..df8c0bc3 --- /dev/null +++ b/internal/use-case/main-use-case/chemo/middleware.go @@ -0,0 +1,9 @@ +package chemo + +// 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/chemo/tycovar.go b/internal/use-case/main-use-case/chemo/tycovar.go new file mode 100644 index 00000000..857871c9 --- /dev/null +++ b/internal/use-case/main-use-case/chemo/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 chemo + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/chemo" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.Chemo, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.Chemo, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.Chemo, 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/encounter/case.go b/internal/use-case/main-use-case/encounter/case.go index 50761e11..cdd3beb2 100644 --- a/internal/use-case/main-use-case/encounter/case.go +++ b/internal/use-case/main-use-case/encounter/case.go @@ -5,14 +5,17 @@ import ( "strconv" ea "simrs-vx/internal/domain/main-entities/ambulatory" + ec "simrs-vx/internal/domain/main-entities/chemo" ee "simrs-vx/internal/domain/main-entities/emergency" 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" ui "simrs-vx/internal/use-case/main-use-case/inpatient" + erc "simrs-vx/internal/domain/references/common" ere "simrs-vx/internal/domain/references/encounter" dg "github.com/karincake/apem/db-gorm-pg" @@ -65,6 +68,19 @@ func Create(input e.CreateDto) (*d.Data, error) { if err != nil { return err } + + if subCode == ere.ACCCac || subCode == ere.ACCCad { + chemoCreate := ec.CreateDto{ + Encounter_Id: &data.Id, + Status_Code: erc.DVCNew, + SrcUnit_Id: input.Unit_Id, + } + + _, err = uc.CreateData(chemoCreate, &event, tx) + if err != nil { + return err + } + } case ere.ECEmergency: subCode, err := ue.CheckClassCode(input.SubClass_Code) if err != nil {