diff --git a/internal/domain/main-entities/installation-position/dto.go b/internal/domain/main-entities/installation-position/dto.go new file mode 100644 index 00000000..aada7443 --- /dev/null +++ b/internal/domain/main-entities/installation-position/dto.go @@ -0,0 +1,84 @@ +package installation_position + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ee "simrs-vx/internal/domain/main-entities/employee" + ei "simrs-vx/internal/domain/main-entities/installation" +) + +type CreateDto struct { + Installation_Id *uint16 `json:"installation_id" validate:"required"` + Code string `json:"code" validate:"maxLength=10;required"` + Name string `json:"name" validate:"maxLength=30;required"` + HeadStatus bool `json:"headStatus"` + Employee_Id *uint `json:"employee_id"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Sort string `json:"sort"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Installation_Id *uint16 `json:"installation-id"` + Code string `json:"code"` + Name string `json:"name"` + HeadStatus *bool `json:"head-status"` + Employee_Id *uint `json:"employee-id"` + Search string `json:"search" gormhelper:"searchColumns=Code,Name"` +} + +type ReadDetailDto struct { + Id uint16 `json:"id"` + Code *string `json:"code"` +} + +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.SmallMain + Installation_Id *uint16 `json:"installation_id"` + Installation *ei.Installation `json:"installation,omitempty"` + Code string `json:"code"` + Name string `json:"name"` + HeadStatus bool `json:"headStatus"` + Employee_Id *uint `json:"employee_id"` + Employee *ee.Employee `json:"employee,omitempty"` +} + +func (d InstallationPosition) ToResponse() ResponseDto { + resp := ResponseDto{ + Installation_Id: d.Installation_Id, + Installation: d.Installation, + Code: d.Code, + Name: d.Name, + HeadStatus: d.HeadStatus, + Employee_Id: d.Employee_Id, + Employee: d.Employee, + } + resp.SmallMain = d.SmallMain + return resp +} + +func ToResponseList(data []InstallationPosition) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/specialist-position/dto.go b/internal/domain/main-entities/specialist-position/dto.go new file mode 100644 index 00000000..0641fb12 --- /dev/null +++ b/internal/domain/main-entities/specialist-position/dto.go @@ -0,0 +1,84 @@ +package specialist_position + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ee "simrs-vx/internal/domain/main-entities/employee" + es "simrs-vx/internal/domain/main-entities/specialist" +) + +type CreateDto struct { + Specialist_Id *uint16 `json:"specialist_id" validate:"required"` + Code string `json:"code" validate:"maxLength=10;required"` + Name string `json:"name" validate:"maxLength=30;required"` + HeadStatus bool `json:"headStatus"` + Employee_Id *uint `json:"employee_id"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Sort string `json:"sort"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Specialist_Id *uint16 `json:"specialist-id"` + Code string `json:"code"` + Name string `json:"name"` + HeadStatus *bool `json:"head-status"` + Employee_Id *uint `json:"employee-id"` + Search string `json:"search" gormhelper:"searchColumns=Code,Name"` +} + +type ReadDetailDto struct { + Id uint16 `json:"id"` + Code *string `json:"code"` +} + +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.SmallMain + Specialist_Id *uint16 `json:"specialist_id"` + Specialist *es.Specialist `json:"specialist,omitempty"` + Code string `json:"code"` + Name string `json:"name"` + HeadStatus bool `json:"headStatus"` + Employee_Id *uint `json:"employee_id"` + Employee *ee.Employee `json:"employee,omitempty"` +} + +func (d SpecialistPosition) ToResponse() ResponseDto { + resp := ResponseDto{ + Specialist_Id: d.Specialist_Id, + Specialist: d.Specialist, + Code: d.Code, + Name: d.Name, + HeadStatus: d.HeadStatus, + Employee_Id: d.Employee_Id, + Employee: d.Employee, + } + resp.SmallMain = d.SmallMain + return resp +} + +func ToResponseList(data []SpecialistPosition) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/subspecialist-position/dto.go b/internal/domain/main-entities/subspecialist-position/dto.go new file mode 100644 index 00000000..3c65841e --- /dev/null +++ b/internal/domain/main-entities/subspecialist-position/dto.go @@ -0,0 +1,84 @@ +package subspecialist_position + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ee "simrs-vx/internal/domain/main-entities/employee" + es "simrs-vx/internal/domain/main-entities/subspecialist" +) + +type CreateDto struct { + Subspecialist_Id *uint16 `json:"subspecialist_id" validate:"required"` + Code string `json:"code" validate:"maxLength=10;required"` + Name string `json:"name" validate:"maxLength=30;required"` + HeadStatus bool `json:"headStatus"` + Employee_Id *uint `json:"employee_id"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Sort string `json:"sort"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Subspecialist_Id *uint16 `json:"subspecialist-id"` + Code string `json:"code"` + Name string `json:"name"` + HeadStatus *bool `json:"head-status"` + Employee_Id *uint `json:"employee-id"` + Search string `json:"search" gormhelper:"searchColumns=Code,Name"` +} + +type ReadDetailDto struct { + Id uint16 `json:"id"` + Code *string `json:"code"` +} + +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.SmallMain + Subspecialist_Id *uint16 `json:"subspecialist_id"` + Subspecialist *es.Subspecialist `json:"subspecialist,omitempty"` + Code string `json:"code"` + Name string `json:"name"` + HeadStatus bool `json:"headStatus"` + Employee_Id *uint `json:"employee_id"` + Employee *ee.Employee `json:"employee,omitempty"` +} + +func (d SubspecialistPosition) ToResponse() ResponseDto { + resp := ResponseDto{ + Subspecialist_Id: d.Subspecialist_Id, + Subspecialist: d.Subspecialist, + Code: d.Code, + Name: d.Name, + HeadStatus: d.HeadStatus, + Employee_Id: d.Employee_Id, + Employee: d.Employee, + } + resp.SmallMain = d.SmallMain + return resp +} + +func ToResponseList(data []SubspecialistPosition) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/unit-position/dto.go b/internal/domain/main-entities/unit-position/dto.go new file mode 100644 index 00000000..cc52c493 --- /dev/null +++ b/internal/domain/main-entities/unit-position/dto.go @@ -0,0 +1,84 @@ +package unit_position + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ee "simrs-vx/internal/domain/main-entities/employee" + eu "simrs-vx/internal/domain/main-entities/unit" +) + +type CreateDto struct { + Unit_Id *uint16 `json:"unit_id" validate:"required"` + Code string `json:"code" validate:"maxLength=10;required"` + Name string `json:"name" validate:"maxLength=30;required"` + HeadStatus bool `json:"headStatus"` + Employee_Id *uint `json:"employee_id"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Sort string `json:"sort"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Unit_Id *uint16 `json:"unit-id"` + Code string `json:"code"` + Name string `json:"name"` + HeadStatus *bool `json:"head-status"` + Employee_Id *uint `json:"employee-id"` + Search string `json:"search" gormhelper:"searchColumns=Code,Name"` +} + +type ReadDetailDto struct { + Id uint16 `json:"id"` + Code *string `json:"code"` +} + +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.SmallMain + Unit_Id *uint16 `json:"unit_id"` + Unit *eu.Unit `json:"unit,omitempty"` + Code string `json:"code"` + Name string `json:"name"` + HeadStatus bool `json:"headStatus"` + Employee_Id *uint `json:"employee_id"` + Employee *ee.Employee `json:"employee,omitempty"` +} + +func (d UnitPosition) ToResponse() ResponseDto { + resp := ResponseDto{ + Unit_Id: d.Unit_Id, + Unit: d.Unit, + Code: d.Code, + Name: d.Name, + HeadStatus: d.HeadStatus, + Employee_Id: d.Employee_Id, + Employee: d.Employee, + } + resp.SmallMain = d.SmallMain + return resp +} + +func ToResponseList(data []UnitPosition) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/interface/main-handler/installation-position/handler.go b/internal/interface/main-handler/installation-position/handler.go new file mode 100644 index 00000000..59f35340 --- /dev/null +++ b/internal/interface/main-handler/installation-position/handler.go @@ -0,0 +1,71 @@ +package installation_position + +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/installation-position" + u "simrs-vx/internal/use-case/main-use-case/installation-position" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.CreateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + sf.UrlQueryParam(&dto, *r.URL) + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + dto := e.ReadDetailDto{} + dto.Id = uint16(id) + res, err := u.ReadDetail(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Id = uint16(id) + res, err := u.Update(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.DeleteDto{} + dto.Id = uint16(id) + res, err := u.Delete(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index 94c16fc1..690a830a 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -70,6 +70,7 @@ import ( ethnic "simrs-vx/internal/interface/main-handler/ethnic" infra "simrs-vx/internal/interface/main-handler/infra" installation "simrs-vx/internal/interface/main-handler/installation" + installationposition "simrs-vx/internal/interface/main-handler/installation-position" insurancecompany "simrs-vx/internal/interface/main-handler/insurance-company" item "simrs-vx/internal/interface/main-handler/item" itemprice "simrs-vx/internal/interface/main-handler/item-price" @@ -86,8 +87,11 @@ import ( pharmacycompany "simrs-vx/internal/interface/main-handler/pharmacy-company" proceduresrc "simrs-vx/internal/interface/main-handler/procedure-src" specialist "simrs-vx/internal/interface/main-handler/specialist" + specialistposition "simrs-vx/internal/interface/main-handler/specialist-position" subspecialist "simrs-vx/internal/interface/main-handler/subspecialist" + subspecialistposition "simrs-vx/internal/interface/main-handler/subspecialist-position" unit "simrs-vx/internal/interface/main-handler/unit" + unitposition "simrs-vx/internal/interface/main-handler/unit-position" uom "simrs-vx/internal/interface/main-handler/uom" vehicle "simrs-vx/internal/interface/main-handler/vehicle" vehiclehist "simrs-vx/internal/interface/main-handler/vehicle-hist" @@ -305,6 +309,10 @@ func SetRoutes() http.Handler { hc.RegCrud(r, "/v1/vehicle", vehicle.O) hc.RegCrud(r, "/v1/vehicle-hist", vehiclehist.O) hc.RegCrud(r, "/v1/edu-assessment", eduassesment.O) + hc.RegCrud(r, "/v1/installation-position", installationposition.O) + hc.RegCrud(r, "/v1/unit-position", unitposition.O) + hc.RegCrud(r, "/v1/specialist-position", specialistposition.O) + hc.RegCrud(r, "/v1/subspecialist-position", subspecialistposition.O) hc.RegCrud(r, "/v1/village", village.O) hc.RegCrud(r, "/v1/district", district.O) diff --git a/internal/interface/main-handler/specialist-position/handler.go b/internal/interface/main-handler/specialist-position/handler.go new file mode 100644 index 00000000..d16c2c7e --- /dev/null +++ b/internal/interface/main-handler/specialist-position/handler.go @@ -0,0 +1,71 @@ +package divisionposition + +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/specialist-position" + u "simrs-vx/internal/use-case/main-use-case/specialist-position" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.CreateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + sf.UrlQueryParam(&dto, *r.URL) + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + dto := e.ReadDetailDto{} + dto.Id = uint16(id) + res, err := u.ReadDetail(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Id = uint16(id) + res, err := u.Update(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.DeleteDto{} + dto.Id = uint16(id) + res, err := u.Delete(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/main-handler/subspecialist-position/handler.go b/internal/interface/main-handler/subspecialist-position/handler.go new file mode 100644 index 00000000..d8e27b14 --- /dev/null +++ b/internal/interface/main-handler/subspecialist-position/handler.go @@ -0,0 +1,71 @@ +package divisionposition + +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/subspecialist-position" + u "simrs-vx/internal/use-case/main-use-case/subspecialist-position" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.CreateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + sf.UrlQueryParam(&dto, *r.URL) + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + dto := e.ReadDetailDto{} + dto.Id = uint16(id) + res, err := u.ReadDetail(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Id = uint16(id) + res, err := u.Update(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.DeleteDto{} + dto.Id = uint16(id) + res, err := u.Delete(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/main-handler/unit-position/handler.go b/internal/interface/main-handler/unit-position/handler.go new file mode 100644 index 00000000..82b89465 --- /dev/null +++ b/internal/interface/main-handler/unit-position/handler.go @@ -0,0 +1,71 @@ +package unit_position + +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/unit-position" + u "simrs-vx/internal/use-case/main-use-case/unit-position" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.CreateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + sf.UrlQueryParam(&dto, *r.URL) + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + dto := e.ReadDetailDto{} + dto.Id = uint16(id) + res, err := u.ReadDetail(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Id = uint16(id) + res, err := u.Update(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.DeleteDto{} + dto.Id = uint16(id) + res, err := u.Delete(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/use-case/main-use-case/authentication/case.go b/internal/use-case/main-use-case/authentication/case.go index ffefa7ef..da454333 100644 --- a/internal/use-case/main-use-case/authentication/case.go +++ b/internal/use-case/main-use-case/authentication/case.go @@ -155,12 +155,44 @@ func GenToken(input eu.LoginDto) (*d.Data, error) { atClaims["nurse_id"] = nurse.Id outputData["nurse_id"] = nurse.Id } + + errorGetPosition := d.FieldErrors{"authentication": d.FieldError{Code: "auth-getData-failed", Message: el.GenMessage("auth-getData-failed")}} + // division position divsionPositions, err := getDivisionPosition(employee.Id) if err != nil { - return nil, d.FieldErrors{"authentication": d.FieldError{Code: "auth-getData-failed", Message: el.GenMessage("auth-getData-failed")}} + return nil, errorGetPosition } + + // installation position + installationPositions, err := getInstallationPosition(employee.Id) + if err != nil { + return nil, errorGetPosition + } + + // unit position + unitPositions, err := getUnitPosition(employee.Id) + if err != nil { + return nil, errorGetPosition + } + + // specialist position + specialistPositions, err := getSpecialistPosition(employee.Id) + if err != nil { + return nil, errorGetPosition + } + + // subspecialist position + subspecialistPositions, err := getSubspecialistPosition(employee.Id) + if err != nil { + return nil, errorGetPosition + } + role = append(role, divsionPositions...) + role = append(role, installationPositions...) + role = append(role, unitPositions...) + role = append(role, specialistPositions...) + role = append(role, subspecialistPositions...) // atClaims["division_positions"] = divsionPositions // outputData["division_positions"] = divsionPositions } diff --git a/internal/use-case/main-use-case/authentication/helper.go b/internal/use-case/main-use-case/authentication/helper.go index c4e67200..87473386 100644 --- a/internal/use-case/main-use-case/authentication/helper.go +++ b/internal/use-case/main-use-case/authentication/helper.go @@ -2,9 +2,18 @@ package authentication import ( edp "simrs-vx/internal/domain/main-entities/division-position" + eip "simrs-vx/internal/domain/main-entities/installation-position" + esp "simrs-vx/internal/domain/main-entities/specialist-position" + essp "simrs-vx/internal/domain/main-entities/subspecialist-position" + eup "simrs-vx/internal/domain/main-entities/unit-position" + + udp "simrs-vx/internal/use-case/main-use-case/division-position" + uip "simrs-vx/internal/use-case/main-use-case/installation-position" + usp "simrs-vx/internal/use-case/main-use-case/specialist-position" + ussp "simrs-vx/internal/use-case/main-use-case/subspecialist-position" + uup "simrs-vx/internal/use-case/main-use-case/unit-position" dg "github.com/karincake/apem/db-gorm-pg" - "gorm.io/gorm" ) // just return the error code @@ -34,21 +43,129 @@ func getDivisionPosition(employee_id uint) ([]string, error) { // return result, errors.New("no employee found") // } - var divisionPositions []edp.DivisionPosition - err := dg.I. - Preload("Division"). - Where("\"Employee_Id\" = ?", employee_id). - Find(&divisionPositions).Error + //var divisionPositions []edp.DivisionPosition + //err := dg.I. + // Preload("Division"). + // Where("\"Employee_Id\" = ?", employee_id). + // Find(&divisionPositions).Error + //if err != nil { + // if err == gorm.ErrRecordNotFound { + // return result, nil + // } + // return result, err + //} + + // get data division_position based on employee_id + dataDivisionPosition, err := udp.ReadList(edp.ReadListDto{ + FilterDto: edp.FilterDto{Employee_Id: &employee_id}, + Includes: "division"}) if err != nil { - if err == gorm.ErrRecordNotFound { - return result, nil - } - return result, err + return nil, err } - for _, dp := range divisionPositions { - if dp.Division != nil { - result = append(result, "div-"+dp.Division.Code+"-"+dp.Code) + if list, ok := dataDivisionPosition.Data.([]edp.ResponseDto); ok { + if len(list) > 0 { + for _, dp := range list { + if dp.Division != nil { + result = append(result, "div-"+dp.Division.Code+"-"+dp.Code) + } + } + } + } + + return result, nil +} + +func getInstallationPosition(employeeId uint) ([]string, error) { + var result []string + + // get data unit_position based on employee_id + dataInstallationPosition, err := uip.ReadList(eip.ReadListDto{ + FilterDto: eip.FilterDto{Employee_Id: &employeeId}, + Includes: "installation"}) + if err != nil { + return nil, err + } + + if list, ok := dataInstallationPosition.Data.([]eip.ResponseDto); ok { + if len(list) > 0 { + for _, dp := range list { + if dp.Installation != nil { + result = append(result, "inst-"+dp.Installation.Code+"-"+dp.Code) + } + } + } + } + + return result, nil +} + +func getUnitPosition(employeeId uint) ([]string, error) { + var result []string + + // get data unit_position based on employee_id + dataUnitPosition, err := uup.ReadList(eup.ReadListDto{ + FilterDto: eup.FilterDto{Employee_Id: &employeeId}, + Includes: "unit"}) + if err != nil { + return nil, err + } + + if list, ok := dataUnitPosition.Data.([]eup.ResponseDto); ok { + if len(list) > 0 { + for _, dp := range list { + if dp.Unit != nil { + result = append(result, "unit-"+dp.Unit.Code+"-"+dp.Code) + } + } + } + } + + return result, nil +} + +func getSpecialistPosition(employeeId uint) ([]string, error) { + var result []string + + // get data unit_position based on employee_id + dataSpecialistPosition, err := usp.ReadList(esp.ReadListDto{ + FilterDto: esp.FilterDto{Employee_Id: &employeeId}, + Includes: "specialist"}) + if err != nil { + return nil, err + } + + if list, ok := dataSpecialistPosition.Data.([]esp.ResponseDto); ok { + if len(list) > 0 { + for _, dp := range list { + if dp.Specialist != nil { + result = append(result, "spec-"+dp.Specialist.Code+"-"+dp.Code) + } + } + } + } + + return result, nil +} + +func getSubspecialistPosition(employeeId uint) ([]string, error) { + var result []string + + // get data unit_position based on employee_id + dataSubspecialistPosition, err := ussp.ReadList(essp.ReadListDto{ + FilterDto: essp.FilterDto{Employee_Id: &employeeId}, + Includes: "subspecialist"}) + if err != nil { + return nil, err + } + + if list, ok := dataSubspecialistPosition.Data.([]essp.ResponseDto); ok { + if len(list) > 0 { + for _, dp := range list { + if dp.Subspecialist != nil { + result = append(result, "subspec-"+dp.Subspecialist.Code+"-"+dp.Code) + } + } } } diff --git a/internal/use-case/main-use-case/installation-position/case.go b/internal/use-case/main-use-case/installation-position/case.go new file mode 100644 index 00000000..f9458c0b --- /dev/null +++ b/internal/use-case/main-use-case/installation-position/case.go @@ -0,0 +1,302 @@ +package installation_position + +import ( + ee "simrs-vx/internal/domain/main-entities/employee" + ei "simrs-vx/internal/domain/main-entities/installation" + e "simrs-vx/internal/domain/main-entities/installation-position" + "strconv" + + ue "simrs-vx/internal/use-case/main-use-case/employee" + ui "simrs-vx/internal/use-case/main-use-case/installation" + + 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 = "installation-position" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.InstallationPosition{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + err := dg.I.Transaction(func(tx *gorm.DB) error { + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunCreateMiddleware(createPreMw, &input, &data); err != nil { + return err + } + + if err := validateForeignKey(input); 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.InstallationPosition + var dataList []e.InstallationPosition + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "readList") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadListMiddleware(readListPreMw, &input, data); err != nil { + return err + } + + if dataList, metaList, err = ReadListData(input, &event, tx); err != nil { + return err + } + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadListMiddleware(readListPostMw, &input, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.InstallationPosition + 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.InstallationPosition + 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 := validateForeignKey(input.CreateDto); 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.InstallationPosition + 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 validateForeignKey(input e.CreateDto) error { + // validate installation_id + if _, err := ui.ReadDetail(ei.ReadDetailDto{Id: *input.Installation_Id}); err != nil { + return err + } + + // validate employee_Id + if _, err := ue.ReadDetail(ee.ReadDetailDto{Id: uint16(*input.Employee_Id)}); err != nil { + return err + } + return nil +} diff --git a/internal/use-case/main-use-case/installation-position/helper.go b/internal/use-case/main-use-case/installation-position/helper.go new file mode 100644 index 00000000..640993c8 --- /dev/null +++ b/internal/use-case/main-use-case/installation-position/helper.go @@ -0,0 +1,25 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package installation_position + +import ( + e "simrs-vx/internal/domain/main-entities/installation-position" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.InstallationPosition) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.Installation_Id = inputSrc.Installation_Id + data.Code = inputSrc.Code + data.Name = inputSrc.Name + data.HeadStatus = inputSrc.HeadStatus + data.Employee_Id = inputSrc.Employee_Id +} diff --git a/internal/use-case/main-use-case/installation-position/lib.go b/internal/use-case/main-use-case/installation-position/lib.go new file mode 100644 index 00000000..bb33356f --- /dev/null +++ b/internal/use-case/main-use-case/installation-position/lib.go @@ -0,0 +1,156 @@ +package installation_position + +import ( + "errors" + e "simrs-vx/internal/domain/main-entities/installation-position" + + 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.InstallationPosition, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.InstallationPosition{} + 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.InstallationPosition, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.InstallationPosition{} + 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.InstallationPosition{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Scopes(gh.Sort(input.Sort)) + + if err := tx.Find(&data).Error; err != nil { + if 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.InstallationPosition, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.InstallationPosition{} + + var tx, getData *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + switch { + case input.Id != 0: + getData = tx.First(&data, input.Id) + case input.Code != nil && *input.Code != "": + getData = tx.Where("code = ?", *input.Code).First(&data) + default: + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-read-detail-fail", + Detail: "either Id or Code must be provided", + } + + return nil, pl.SetLogError(event, nil) + } + + if err := getData.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.InstallationPosition, 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.InstallationPosition, 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/installation-position/middleware-runner.go b/internal/use-case/main-use-case/installation-position/middleware-runner.go new file mode 100644 index 00000000..f59aedd9 --- /dev/null +++ b/internal/use-case/main-use-case/installation-position/middleware-runner.go @@ -0,0 +1,103 @@ +package installation_position + +import ( + e "simrs-vx/internal/domain/main-entities/installation-position" + 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.InstallationPosition) 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.InstallationPosition) 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.InstallationPosition) 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.InstallationPosition) 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.InstallationPosition) 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/installation-position/middleware.go b/internal/use-case/main-use-case/installation-position/middleware.go new file mode 100644 index 00000000..ed9aac6e --- /dev/null +++ b/internal/use-case/main-use-case/installation-position/middleware.go @@ -0,0 +1,9 @@ +package installation_position + +// 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/installation-position/tycovar.go b/internal/use-case/main-use-case/installation-position/tycovar.go new file mode 100644 index 00000000..38807df3 --- /dev/null +++ b/internal/use-case/main-use-case/installation-position/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 installation_position + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/installation-position" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.InstallationPosition, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.InstallationPosition, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.InstallationPosition, 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/specialist-position/case.go b/internal/use-case/main-use-case/specialist-position/case.go new file mode 100644 index 00000000..c3c469e6 --- /dev/null +++ b/internal/use-case/main-use-case/specialist-position/case.go @@ -0,0 +1,302 @@ +package specialist_position + +import ( + ee "simrs-vx/internal/domain/main-entities/employee" + es "simrs-vx/internal/domain/main-entities/specialist" + e "simrs-vx/internal/domain/main-entities/specialist-position" + "strconv" + + ue "simrs-vx/internal/use-case/main-use-case/employee" + us "simrs-vx/internal/use-case/main-use-case/specialist" + + 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 = "specialist-position" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.SpecialistPosition{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + err := dg.I.Transaction(func(tx *gorm.DB) error { + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunCreateMiddleware(createPreMw, &input, &data); err != nil { + return err + } + + if err := validateForeignKey(input); 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.SpecialistPosition + var dataList []e.SpecialistPosition + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "readList") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadListMiddleware(readListPreMw, &input, data); err != nil { + return err + } + + if dataList, metaList, err = ReadListData(input, &event, tx); err != nil { + return err + } + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadListMiddleware(readListPostMw, &input, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.SpecialistPosition + 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.SpecialistPosition + 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 := validateForeignKey(input.CreateDto); 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.SpecialistPosition + 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 validateForeignKey(input e.CreateDto) error { + // validate installation_id + if _, err := us.ReadDetail(es.ReadDetailDto{Id: *input.Specialist_Id}); err != nil { + return err + } + + // validate employee_Id + if _, err := ue.ReadDetail(ee.ReadDetailDto{Id: uint16(*input.Employee_Id)}); err != nil { + return err + } + return nil +} diff --git a/internal/use-case/main-use-case/specialist-position/helper.go b/internal/use-case/main-use-case/specialist-position/helper.go new file mode 100644 index 00000000..6c3d6434 --- /dev/null +++ b/internal/use-case/main-use-case/specialist-position/helper.go @@ -0,0 +1,25 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package specialist_position + +import ( + e "simrs-vx/internal/domain/main-entities/specialist-position" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.SpecialistPosition) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.Specialist_Id = inputSrc.Specialist_Id + data.Code = inputSrc.Code + data.Name = inputSrc.Name + data.HeadStatus = inputSrc.HeadStatus + data.Employee_Id = inputSrc.Employee_Id +} diff --git a/internal/use-case/main-use-case/specialist-position/lib.go b/internal/use-case/main-use-case/specialist-position/lib.go new file mode 100644 index 00000000..3ae54f50 --- /dev/null +++ b/internal/use-case/main-use-case/specialist-position/lib.go @@ -0,0 +1,156 @@ +package specialist_position + +import ( + "errors" + e "simrs-vx/internal/domain/main-entities/specialist-position" + + 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.SpecialistPosition, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.SpecialistPosition{} + 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.SpecialistPosition, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.SpecialistPosition{} + 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.SpecialistPosition{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Scopes(gh.Sort(input.Sort)) + + if err := tx.Find(&data).Error; err != nil { + if 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.SpecialistPosition, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.SpecialistPosition{} + + var tx, getData *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + switch { + case input.Id != 0: + getData = tx.First(&data, input.Id) + case input.Code != nil && *input.Code != "": + getData = tx.Where("code = ?", *input.Code).First(&data) + default: + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-read-detail-fail", + Detail: "either Id or Code must be provided", + } + + return nil, pl.SetLogError(event, nil) + } + + if err := getData.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.SpecialistPosition, 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.SpecialistPosition, 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/specialist-position/middleware-runner.go b/internal/use-case/main-use-case/specialist-position/middleware-runner.go new file mode 100644 index 00000000..cade8cf9 --- /dev/null +++ b/internal/use-case/main-use-case/specialist-position/middleware-runner.go @@ -0,0 +1,103 @@ +package specialist_position + +import ( + e "simrs-vx/internal/domain/main-entities/specialist-position" + 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.SpecialistPosition) 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.SpecialistPosition) 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.SpecialistPosition) 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.SpecialistPosition) 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.SpecialistPosition) 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/specialist-position/middleware.go b/internal/use-case/main-use-case/specialist-position/middleware.go new file mode 100644 index 00000000..9e3bc169 --- /dev/null +++ b/internal/use-case/main-use-case/specialist-position/middleware.go @@ -0,0 +1,9 @@ +package specialist_position + +// 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/specialist-position/tycovar.go b/internal/use-case/main-use-case/specialist-position/tycovar.go new file mode 100644 index 00000000..4cf93b3b --- /dev/null +++ b/internal/use-case/main-use-case/specialist-position/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 specialist_position + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/specialist-position" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.SpecialistPosition, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.SpecialistPosition, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.SpecialistPosition, 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/subspecialist-position/case.go b/internal/use-case/main-use-case/subspecialist-position/case.go new file mode 100644 index 00000000..d954427a --- /dev/null +++ b/internal/use-case/main-use-case/subspecialist-position/case.go @@ -0,0 +1,302 @@ +package subspecialist_position + +import ( + ee "simrs-vx/internal/domain/main-entities/employee" + es "simrs-vx/internal/domain/main-entities/subspecialist" + e "simrs-vx/internal/domain/main-entities/subspecialist-position" + "strconv" + + ue "simrs-vx/internal/use-case/main-use-case/employee" + us "simrs-vx/internal/use-case/main-use-case/subspecialist" + + 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 = "subspecialist-position" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.SubspecialistPosition{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + err := dg.I.Transaction(func(tx *gorm.DB) error { + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunCreateMiddleware(createPreMw, &input, &data); err != nil { + return err + } + + if err := validateForeignKey(input); 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.SubspecialistPosition + var dataList []e.SubspecialistPosition + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "readList") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadListMiddleware(readListPreMw, &input, data); err != nil { + return err + } + + if dataList, metaList, err = ReadListData(input, &event, tx); err != nil { + return err + } + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadListMiddleware(readListPostMw, &input, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.SubspecialistPosition + 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.SubspecialistPosition + 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 := validateForeignKey(input.CreateDto); 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.SubspecialistPosition + 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 validateForeignKey(input e.CreateDto) error { + // validate installation_id + if _, err := us.ReadDetail(es.ReadDetailDto{Id: *input.Subspecialist_Id}); err != nil { + return err + } + + // validate employee_Id + if _, err := ue.ReadDetail(ee.ReadDetailDto{Id: uint16(*input.Employee_Id)}); err != nil { + return err + } + return nil +} diff --git a/internal/use-case/main-use-case/subspecialist-position/helper.go b/internal/use-case/main-use-case/subspecialist-position/helper.go new file mode 100644 index 00000000..1f4c9b2b --- /dev/null +++ b/internal/use-case/main-use-case/subspecialist-position/helper.go @@ -0,0 +1,25 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package subspecialist_position + +import ( + e "simrs-vx/internal/domain/main-entities/subspecialist-position" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.SubspecialistPosition) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.Subspecialist_Id = inputSrc.Subspecialist_Id + data.Code = inputSrc.Code + data.Name = inputSrc.Name + data.HeadStatus = inputSrc.HeadStatus + data.Employee_Id = inputSrc.Employee_Id +} diff --git a/internal/use-case/main-use-case/subspecialist-position/lib.go b/internal/use-case/main-use-case/subspecialist-position/lib.go new file mode 100644 index 00000000..136e982e --- /dev/null +++ b/internal/use-case/main-use-case/subspecialist-position/lib.go @@ -0,0 +1,156 @@ +package subspecialist_position + +import ( + "errors" + e "simrs-vx/internal/domain/main-entities/subspecialist-position" + + 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.SubspecialistPosition, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.SubspecialistPosition{} + 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.SubspecialistPosition, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.SubspecialistPosition{} + 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.SubspecialistPosition{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Scopes(gh.Sort(input.Sort)) + + if err := tx.Find(&data).Error; err != nil { + if 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.SubspecialistPosition, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.SubspecialistPosition{} + + var tx, getData *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + switch { + case input.Id != 0: + getData = tx.First(&data, input.Id) + case input.Code != nil && *input.Code != "": + getData = tx.Where("code = ?", *input.Code).First(&data) + default: + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-read-detail-fail", + Detail: "either Id or Code must be provided", + } + + return nil, pl.SetLogError(event, nil) + } + + if err := getData.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.SubspecialistPosition, 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.SubspecialistPosition, 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/subspecialist-position/middleware-runner.go b/internal/use-case/main-use-case/subspecialist-position/middleware-runner.go new file mode 100644 index 00000000..66c3d013 --- /dev/null +++ b/internal/use-case/main-use-case/subspecialist-position/middleware-runner.go @@ -0,0 +1,103 @@ +package subspecialist_position + +import ( + e "simrs-vx/internal/domain/main-entities/subspecialist-position" + 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.SubspecialistPosition) 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.SubspecialistPosition) 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.SubspecialistPosition) 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.SubspecialistPosition) 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.SubspecialistPosition) 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/subspecialist-position/middleware.go b/internal/use-case/main-use-case/subspecialist-position/middleware.go new file mode 100644 index 00000000..e7cafc86 --- /dev/null +++ b/internal/use-case/main-use-case/subspecialist-position/middleware.go @@ -0,0 +1,9 @@ +package subspecialist_position + +// 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/subspecialist-position/tycovar.go b/internal/use-case/main-use-case/subspecialist-position/tycovar.go new file mode 100644 index 00000000..e2cd8acd --- /dev/null +++ b/internal/use-case/main-use-case/subspecialist-position/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 subspecialist_position + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/subspecialist-position" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.SubspecialistPosition, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.SubspecialistPosition, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.SubspecialistPosition, 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/unit-position/case.go b/internal/use-case/main-use-case/unit-position/case.go new file mode 100644 index 00000000..f3bd2840 --- /dev/null +++ b/internal/use-case/main-use-case/unit-position/case.go @@ -0,0 +1,302 @@ +package unit_position + +import ( + ee "simrs-vx/internal/domain/main-entities/employee" + eu "simrs-vx/internal/domain/main-entities/unit" + e "simrs-vx/internal/domain/main-entities/unit-position" + "strconv" + + ue "simrs-vx/internal/use-case/main-use-case/employee" + uu "simrs-vx/internal/use-case/main-use-case/unit" + + 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 = "unit-position" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.UnitPosition{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + err := dg.I.Transaction(func(tx *gorm.DB) error { + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunCreateMiddleware(createPreMw, &input, &data); err != nil { + return err + } + + if err := validateForeignKey(input); 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.UnitPosition + var dataList []e.UnitPosition + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "readList") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadListMiddleware(readListPreMw, &input, data); err != nil { + return err + } + + if dataList, metaList, err = ReadListData(input, &event, tx); err != nil { + return err + } + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadListMiddleware(readListPostMw, &input, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.UnitPosition + 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.UnitPosition + 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 := validateForeignKey(input.CreateDto); 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.UnitPosition + 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 validateForeignKey(input e.CreateDto) error { + // validate installation_id + if _, err := uu.ReadDetail(eu.ReadDetailDto{Id: *input.Unit_Id}); err != nil { + return err + } + + // validate employee_Id + if _, err := ue.ReadDetail(ee.ReadDetailDto{Id: uint16(*input.Employee_Id)}); err != nil { + return err + } + return nil +} diff --git a/internal/use-case/main-use-case/unit-position/helper.go b/internal/use-case/main-use-case/unit-position/helper.go new file mode 100644 index 00000000..c1db758d --- /dev/null +++ b/internal/use-case/main-use-case/unit-position/helper.go @@ -0,0 +1,25 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package unit_position + +import ( + e "simrs-vx/internal/domain/main-entities/unit-position" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.UnitPosition) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.Unit_Id = inputSrc.Unit_Id + data.Code = inputSrc.Code + data.Name = inputSrc.Name + data.HeadStatus = inputSrc.HeadStatus + data.Employee_Id = inputSrc.Employee_Id +} diff --git a/internal/use-case/main-use-case/unit-position/lib.go b/internal/use-case/main-use-case/unit-position/lib.go new file mode 100644 index 00000000..c58edd4e --- /dev/null +++ b/internal/use-case/main-use-case/unit-position/lib.go @@ -0,0 +1,156 @@ +package unit_position + +import ( + "errors" + e "simrs-vx/internal/domain/main-entities/unit-position" + + 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.UnitPosition, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.UnitPosition{} + 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.UnitPosition, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.UnitPosition{} + 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.UnitPosition{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Scopes(gh.Sort(input.Sort)) + + if err := tx.Find(&data).Error; err != nil { + if 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.UnitPosition, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.UnitPosition{} + + var tx, getData *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + switch { + case input.Id != 0: + getData = tx.First(&data, input.Id) + case input.Code != nil && *input.Code != "": + getData = tx.Where("code = ?", *input.Code).First(&data) + default: + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-read-detail-fail", + Detail: "either Id or Code must be provided", + } + + return nil, pl.SetLogError(event, nil) + } + + if err := getData.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.UnitPosition, 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.UnitPosition, 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/unit-position/middleware-runner.go b/internal/use-case/main-use-case/unit-position/middleware-runner.go new file mode 100644 index 00000000..73092025 --- /dev/null +++ b/internal/use-case/main-use-case/unit-position/middleware-runner.go @@ -0,0 +1,103 @@ +package unit_position + +import ( + e "simrs-vx/internal/domain/main-entities/unit-position" + 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.UnitPosition) 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.UnitPosition) 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.UnitPosition) 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.UnitPosition) 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.UnitPosition) 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/unit-position/middleware.go b/internal/use-case/main-use-case/unit-position/middleware.go new file mode 100644 index 00000000..44c1e396 --- /dev/null +++ b/internal/use-case/main-use-case/unit-position/middleware.go @@ -0,0 +1,9 @@ +package unit_position + +// 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/unit-position/tycovar.go b/internal/use-case/main-use-case/unit-position/tycovar.go new file mode 100644 index 00000000..451d6445 --- /dev/null +++ b/internal/use-case/main-use-case/unit-position/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 unit_position + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/unit-position" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.UnitPosition, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.UnitPosition, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.UnitPosition, 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