From 39efdf4d57d5bb006a7b0c44a28bd29d9f387a90 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Fri, 3 Oct 2025 10:53:06 +0700 Subject: [PATCH] material, device-order required doctor_id, infra search and parent,childrens --- .../domain/main-entities/device-order/dto.go | 11 +++++ .../main-entities/device-order/entity.go | 4 ++ internal/domain/main-entities/division/dto.go | 5 +- internal/domain/main-entities/infra/dto.go | 5 ++ .../main-entities/material-order/dto.go | 11 +++++ .../main-entities/material-order/entity.go | 4 ++ .../main-handler/device-order/handler.go | 17 ++++++- .../interface/main-handler/main-handler.go | 4 +- .../main-handler/material-order/handler.go | 14 ++++++ .../main-use-case/device-order/case.go | 47 +++++++++++++++++++ .../main-use-case/device-order/helper.go | 1 + .../use-case/main-use-case/division/lib.go | 2 + internal/use-case/main-use-case/infra/lib.go | 2 + .../main-use-case/material-order/case.go | 44 +++++++++++++++++ .../main-use-case/material-order/helper.go | 1 + 15 files changed, 166 insertions(+), 6 deletions(-) diff --git a/internal/domain/main-entities/device-order/dto.go b/internal/domain/main-entities/device-order/dto.go index f26d1155..6d61757e 100644 --- a/internal/domain/main-entities/device-order/dto.go +++ b/internal/domain/main-entities/device-order/dto.go @@ -2,13 +2,20 @@ package deviceorder 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" + 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"` + Doctor_Id *uint `json:"doctor_id"` + + pa.AuthInfo } type ReadListDto struct { @@ -48,6 +55,8 @@ type ResponseDto struct { ecore.Main Encounter_Id *uint `json:"encounter_id"` Encounter *ee.Encounter `json:"encounter,omitempty"` + Doctor_Id *uint `json:"doctor_id"` + Doctor *ed.Doctor `json:"doctor,omitempty"` Status_Code erc.DataStatusCode `json:"status_code"` } @@ -55,6 +64,8 @@ func (d DeviceOrder) ToResponse() ResponseDto { resp := ResponseDto{ Encounter_Id: d.Encounter_Id, Encounter: d.Encounter, + Doctor_Id: d.Doctor_Id, + Doctor: d.Doctor, Status_Code: d.Status_Code, } resp.Main = d.Main diff --git a/internal/domain/main-entities/device-order/entity.go b/internal/domain/main-entities/device-order/entity.go index 53470219..7f693518 100644 --- a/internal/domain/main-entities/device-order/entity.go +++ b/internal/domain/main-entities/device-order/entity.go @@ -20,3 +20,7 @@ type DeviceOrder struct { func (d DeviceOrder) IsCompleted() bool { return d.Status_Code == erc.DSCDone } + +func (d DeviceOrder) IsSameDoctor(doctor_id *uint) bool { + return d.Doctor_Id == doctor_id +} diff --git a/internal/domain/main-entities/division/dto.go b/internal/domain/main-entities/division/dto.go index 49f2b647..ea45ee1d 100644 --- a/internal/domain/main-entities/division/dto.go +++ b/internal/domain/main-entities/division/dto.go @@ -14,6 +14,7 @@ type ReadListDto struct { FilterDto Includes string `json:"includes"` Preloads []string `json:"-"` + Search string `json:"search"` } type FilterDto struct { @@ -51,8 +52,8 @@ type ResponseDto struct { Code string `json:"code"` Name string `json:"name"` Parent_Id *uint16 `json:"parent_id"` - Parent *Division `json:"parent"` - Childrens []Division `json:"childrens"` + Parent *Division `json:"parent,omitempty"` + Childrens []Division `json:"childrens,omitempty"` } func (d Division) ToResponse() ResponseDto { diff --git a/internal/domain/main-entities/infra/dto.go b/internal/domain/main-entities/infra/dto.go index 69531f5f..b51937ce 100644 --- a/internal/domain/main-entities/infra/dto.go +++ b/internal/domain/main-entities/infra/dto.go @@ -23,6 +23,7 @@ type ReadListDto struct { FilterDto Includes string `json:"includes"` Preloads []string `json:"-"` + Search string `json:"search"` } type FilterDto struct { @@ -64,6 +65,8 @@ type ResponseDto struct { Name string `json:"name"` InfraGroup_Code ero.InfraGroupCode `json:"infraGroup_code"` Parent_Id *uint16 `json:"parent_id"` + Parent *Infra `json:"parent,omitempty"` + Childrens []Infra `json:"childrens,omitempty"` Item_Id *uint `json:"item_id"` Item *ei.Item `json:"item,omitempty"` } @@ -74,6 +77,8 @@ func (d Infra) ToResponse() ResponseDto { Name: d.Name, InfraGroup_Code: d.InfraGroup_Code, Parent_Id: d.Parent_Id, + Parent: d.Parent, + Childrens: d.Childrens, Item_Id: d.Item_Id, Item: d.Item, } diff --git a/internal/domain/main-entities/material-order/dto.go b/internal/domain/main-entities/material-order/dto.go index 849f887f..1c58c379 100644 --- a/internal/domain/main-entities/material-order/dto.go +++ b/internal/domain/main-entities/material-order/dto.go @@ -2,13 +2,20 @@ package materialorder 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" + 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"` + Doctor_Id *uint `json:"doctor_id"` + + pa.AuthInfo } type ReadListDto struct { @@ -48,6 +55,8 @@ type ResponseDto struct { ecore.Main Encounter_Id *uint `json:"encounter_id"` Encounter *ee.Encounter `json:"encounter,omitempty"` + Doctor_Id *uint `json:"doctor_id"` + Doctor *ed.Doctor `json:"doctor,omitempty"` Status_Code erc.DataStatusCode `json:"status_code"` } @@ -55,6 +64,8 @@ func (d MaterialOrder) ToResponse() ResponseDto { resp := ResponseDto{ Encounter_Id: d.Encounter_Id, Encounter: d.Encounter, + Doctor_Id: d.Doctor_Id, + Doctor: d.Doctor, Status_Code: d.Status_Code, } resp.Main = d.Main diff --git a/internal/domain/main-entities/material-order/entity.go b/internal/domain/main-entities/material-order/entity.go index 0a2d8d51..27b5c011 100644 --- a/internal/domain/main-entities/material-order/entity.go +++ b/internal/domain/main-entities/material-order/entity.go @@ -20,3 +20,7 @@ type MaterialOrder struct { func (d MaterialOrder) IsCompleted() bool { return d.Status_Code == erc.DSCDone } + +func (d MaterialOrder) IsSameDoctor(doctor_id *uint) bool { + return d.Doctor_Id == doctor_id +} diff --git a/internal/interface/main-handler/device-order/handler.go b/internal/interface/main-handler/device-order/handler.go index ca11ff90..42135e58 100644 --- a/internal/interface/main-handler/device-order/handler.go +++ b/internal/interface/main-handler/device-order/handler.go @@ -6,10 +6,12 @@ import ( rw "github.com/karincake/risoles" sf "github.com/karincake/semprit" - // ua "github.com/karincake/tumpeng/auth/svc" - e "simrs-vx/internal/domain/main-entities/device-order" u "simrs-vx/internal/use-case/main-use-case/device-order" + + pa "simrs-vx/pkg/auth-helper" + + d "github.com/karincake/dodol" ) type myBase struct{} @@ -21,6 +23,12 @@ func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { return } + + authInfo, err := pa.GetAuthInfo(r) + if err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil) + } + dto.AuthInfo = *authInfo res, err := u.Create(dto) rw.DataResponse(w, res, err) } @@ -54,6 +62,11 @@ func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { return } 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 res, err := u.Update(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 43b2f950..5adb40cd 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -193,7 +193,7 @@ func SetRoutes() http.Handler { "PATCH /{id}/consume": medicationitemdist.O.Consume, }) - hk.GroupRoutes("/v1/device-order", r, hk.MapHandlerFunc{ + hk.GroupRoutes("/v1/device-order", r, auth.GuardMW, hk.MapHandlerFunc{ "GET /": deviceorder.O.GetList, "GET /{id}": deviceorder.O.GetDetail, "POST /": deviceorder.O.Create, @@ -202,7 +202,7 @@ func SetRoutes() http.Handler { "PATCH /{id}/complete": deviceorder.O.Complete, }) - hk.GroupRoutes("/v1/material-order", r, hk.MapHandlerFunc{ + hk.GroupRoutes("/v1/material-order", r, auth.GuardMW, hk.MapHandlerFunc{ "GET /": materialorder.O.GetList, "GET /{id}": materialorder.O.GetDetail, "POST /": materialorder.O.Create, diff --git a/internal/interface/main-handler/material-order/handler.go b/internal/interface/main-handler/material-order/handler.go index eb717973..ae8777cb 100644 --- a/internal/interface/main-handler/material-order/handler.go +++ b/internal/interface/main-handler/material-order/handler.go @@ -10,6 +10,10 @@ import ( e "simrs-vx/internal/domain/main-entities/material-order" u "simrs-vx/internal/use-case/main-use-case/material-order" + + pa "simrs-vx/pkg/auth-helper" + + d "github.com/karincake/dodol" ) type myBase struct{} @@ -21,6 +25,11 @@ func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { return } + authInfo, err := pa.GetAuthInfo(r) + if err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil) + } + dto.AuthInfo = *authInfo res, err := u.Create(dto) rw.DataResponse(w, res, err) } @@ -53,6 +62,11 @@ func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { return } + authInfo, err := pa.GetAuthInfo(r) + if err != nil { + rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": err.Error()}, nil) + } + dto.AuthInfo = *authInfo dto.Id = uint16(id) res, err := u.Update(dto) rw.DataResponse(w, res, err) diff --git a/internal/use-case/main-use-case/device-order/case.go b/internal/use-case/main-use-case/device-order/case.go index 66dc1949..422c4f1a 100644 --- a/internal/use-case/main-use-case/device-order/case.go +++ b/internal/use-case/main-use-case/device-order/case.go @@ -6,6 +6,7 @@ import ( e "simrs-vx/internal/domain/main-entities/device-order" + ud "simrs-vx/internal/use-case/main-use-case/doctor" ue "simrs-vx/internal/use-case/main-use-case/encounter" erc "simrs-vx/internal/domain/references/common" @@ -45,6 +46,26 @@ func Create(input e.CreateDto) (*d.Data, error) { return errors.New("encounter is already done") } + if data.IsCompleted() { + return errors.New("data already completed") + } + + if !input.AuthInfo.IsDoctor() { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "auth-forbidden", + Detail: "user position is not allowed", + Raw: errors.New("authentication failed"), + } + return pl.SetLogError(&event, input) + } + + doctor_id, err := ud.GetIdByUserId(&input.AuthInfo.User_Id, &event, tx) + if err != nil { + return err + } + input.Doctor_Id = doctor_id + if resData, err := CreateData(input, &event, tx); err != nil { return err } else { @@ -207,6 +228,32 @@ func Update(input e.UpdateDto) (*d.Data, error) { return err } + if !input.AuthInfo.IsDoctor() { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "auth-forbidden", + Detail: "user position is not allowed", + Raw: errors.New("authentication failed"), + } + return pl.SetLogError(&event, input) + } + + doctor_id, err := ud.GetIdByUserId(&input.AuthInfo.User_Id, &event, tx) + if err != nil { + return err + } + if !data.IsSameDoctor(doctor_id) { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "auth-forbidden", + Detail: "doctor is not the same as the data", + Raw: errors.New("authentication failed"), + } + return pl.SetLogError(&event, input) + } + + input.Doctor_Id = doctor_id + if err := UpdateData(input, data, &event, tx); err != nil { return err } diff --git a/internal/use-case/main-use-case/device-order/helper.go b/internal/use-case/main-use-case/device-order/helper.go index 84a49fa2..f64e8886 100644 --- a/internal/use-case/main-use-case/device-order/helper.go +++ b/internal/use-case/main-use-case/device-order/helper.go @@ -19,4 +19,5 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.DeviceOrder) { data.Encounter_Id = inputSrc.Encounter_Id data.Status_Code = inputSrc.Status_Code + data.Doctor_Id = inputSrc.Doctor_Id } diff --git a/internal/use-case/main-use-case/division/lib.go b/internal/use-case/main-use-case/division/lib.go index 9e0909c8..25ccd22f 100644 --- a/internal/use-case/main-use-case/division/lib.go +++ b/internal/use-case/main-use-case/division/lib.go @@ -53,6 +53,8 @@ func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.Di } } + plh.SearchCodeOrName(input.Search, tx) + tx = tx. Model(&e.Division{}). Scopes(gh.Filter(input.FilterDto)). diff --git a/internal/use-case/main-use-case/infra/lib.go b/internal/use-case/main-use-case/infra/lib.go index c733ca39..656aec39 100644 --- a/internal/use-case/main-use-case/infra/lib.go +++ b/internal/use-case/main-use-case/infra/lib.go @@ -53,6 +53,8 @@ func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.In } } + plh.SearchCodeOrName(input.Search, tx) + tx = tx. Model(&e.Infra{}). Scopes(gh.Filter(input.FilterDto)). diff --git a/internal/use-case/main-use-case/material-order/case.go b/internal/use-case/main-use-case/material-order/case.go index bed63695..af93924c 100644 --- a/internal/use-case/main-use-case/material-order/case.go +++ b/internal/use-case/main-use-case/material-order/case.go @@ -6,6 +6,7 @@ import ( e "simrs-vx/internal/domain/main-entities/material-order" + ud "simrs-vx/internal/use-case/main-use-case/doctor" ue "simrs-vx/internal/use-case/main-use-case/encounter" erc "simrs-vx/internal/domain/references/common" @@ -45,6 +46,22 @@ func Create(input e.CreateDto) (*d.Data, error) { return errors.New("encounter is already done") } + if !input.AuthInfo.IsDoctor() { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "auth-forbidden", + Detail: "user position is not allowed", + Raw: errors.New("authentication failed"), + } + return pl.SetLogError(&event, input) + } + + doctor_id, err := ud.GetIdByUserId(&input.AuthInfo.User_Id, &event, tx) + if err != nil { + return err + } + input.Doctor_Id = doctor_id + if resData, err := CreateData(input, &event, tx); err != nil { return err } else { @@ -208,6 +225,33 @@ func Update(input e.UpdateDto) (*d.Data, error) { return err } + if !input.AuthInfo.IsDoctor() { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "auth-forbidden", + Detail: "user position is not allowed", + Raw: errors.New("authentication failed"), + } + return pl.SetLogError(&event, input) + } + + doctor_id, err := ud.GetIdByUserId(&input.AuthInfo.User_Id, &event, tx) + if err != nil { + return err + } + + if !data.IsSameDoctor(doctor_id) { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "auth-forbidden", + Detail: "doctor is not the same as the data", + Raw: errors.New("authentication failed"), + } + return pl.SetLogError(&event, input) + } + + input.Doctor_Id = doctor_id + if err := UpdateData(input, data, &event, tx); err != nil { return err } diff --git a/internal/use-case/main-use-case/material-order/helper.go b/internal/use-case/main-use-case/material-order/helper.go index f5f67b1a..c3a0fdde 100644 --- a/internal/use-case/main-use-case/material-order/helper.go +++ b/internal/use-case/main-use-case/material-order/helper.go @@ -19,4 +19,5 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.MaterialOrder) { data.Encounter_Id = inputSrc.Encounter_Id data.Status_Code = inputSrc.Status_Code + data.Doctor_Id = inputSrc.Doctor_Id }