diff --git a/internal/delivery/api/api.go b/internal/delivery/api/api.go index 19ba6b5..2cecd91 100644 --- a/internal/delivery/api/api.go +++ b/internal/delivery/api/api.go @@ -2,6 +2,7 @@ package api import ( "gh5-backend/internal/delivery/api/auth" + "gh5-backend/internal/delivery/api/cases" "gh5-backend/internal/delivery/api/role" "gh5-backend/internal/delivery/api/user" @@ -14,6 +15,7 @@ func Init(e *echo.Echo, f factory.Factory) { prefix := "api" auth.NewDelivery(f).Route(e.Group(prefix + "/auth")) + cases.NewDelivery(f).Route(e.Group(prefix + "/cases")) user.NewDelivery(f).Route(e.Group(prefix + "/users")) role.NewDelivery(f).Route(e.Group(prefix + "/roles")) } diff --git a/internal/delivery/api/cases/case.go b/internal/delivery/api/cases/case.go new file mode 100644 index 0000000..1270610 --- /dev/null +++ b/internal/delivery/api/cases/case.go @@ -0,0 +1,67 @@ +package cases + +import ( + "gh5-backend/internal/factory" + "gh5-backend/internal/model/dto" + res "gh5-backend/pkg/utils/response" + + "github.com/labstack/echo/v4" +) + +type delivery struct { + Factory factory.Factory +} + +func NewDelivery(f factory.Factory) *delivery { + return &delivery{f} +} + +func (h *delivery) Route(g *echo.Group) { + g.GET("", h.Get) + g.GET("/:id", h.GetByID) + g.POST("/", h.Create) +} + +func (h *delivery) Get(c echo.Context) error { + result, err := h.Factory.Usecase.Case.Find(c.Request().Context()) + if err != nil { + return res.ErrorResponse(err).Send(c) + } + + return res.CustomSuccessBuilder(200, result, "Get all cases success").Send(c) +} + +func (h *delivery) GetByID(c echo.Context) error { + payload := new(dto.ByIDRequest) + if err := c.Bind(payload); err != nil { + return res.ErrorBuilder(&res.ErrorConstant.BadRequest, err).Send(c) + } + + if err := c.Validate(payload); err != nil { + return res.ErrorBuilder(&res.ErrorConstant.Validation, err).Send(c) + } + + result, err := h.Factory.Usecase.Case.FindByID(c.Request().Context(), *payload) + if err != nil { + return res.ErrorResponse(err).Send(c) + } + + return res.CustomSuccessBuilder(200, result, "Get case by id success").Send(c) +} + +func (h *delivery) Create(c echo.Context) error { + payload := new(dto.CreateCaseRequest) + if err := c.Bind(payload); err != nil { + return res.ErrorBuilder(&res.ErrorConstant.BadRequest, err).Send(c) + } + if err := c.Validate(payload); err != nil { + return res.ErrorBuilder(&res.ErrorConstant.Validation, err).Send(c) + } + + result, err := h.Factory.Usecase.Case.Create(c.Request().Context(), *payload) + if err != nil { + return res.ErrorResponse(err).Send(c) + } + + return res.SuccessResponse(result).Send(c) +} diff --git a/internal/driver/migration/migration.go b/internal/driver/migration/migration.go index 7c780a0..2a6b217 100644 --- a/internal/driver/migration/migration.go +++ b/internal/driver/migration/migration.go @@ -34,6 +34,7 @@ func Init() { &model.UserModel{}, &model.RoleModel{}, &model.LawyerModel{}, + &model.CaseModel{}, }, IsAutoMigrate: true, }, diff --git a/internal/factory/repository/repository.go b/internal/factory/repository/repository.go index e56b694..edcd355 100644 --- a/internal/factory/repository/repository.go +++ b/internal/factory/repository/repository.go @@ -19,6 +19,7 @@ type Factory struct { UserRepository dbRepository.UserRepository RoleRepository dbRepository.RoleRepository LawyerRepository dbRepository.LawyerRepository + CaseRepository dbRepository.CaseRepository } func Init() Factory { @@ -67,4 +68,5 @@ func (f *Factory) InitDbRepository() { f.UserRepository = *dbRepository.NewUserRepository(f.Db, f.Log) f.RoleRepository = *dbRepository.NewRoleRepository(f.Db, f.Log) f.LawyerRepository = *dbRepository.NewLawyerRepository(f.Db, f.Log) + f.CaseRepository = *dbRepository.NewCaseRepository(f.Db, f.Log) } diff --git a/internal/factory/usecase/usecase.go b/internal/factory/usecase/usecase.go index 1df6540..12f3ad9 100644 --- a/internal/factory/usecase/usecase.go +++ b/internal/factory/usecase/usecase.go @@ -20,6 +20,7 @@ type Factory struct { User usecase.UserUsecase Role usecase.RoleUsecase Lawyer usecase.LawyerUsecase + Case usecase.CaseUsecase } func Init(r repository.Factory) Factory { @@ -30,6 +31,7 @@ func Init(r repository.Factory) Factory { f.User = *usecase.NewUserUsecase(r) f.Role = *usecase.NewRoleUsecase(r) f.Lawyer = *usecase.NewLawyerUsecase(r) + f.Case = *usecase.NewCaseUsecase(r) return f } diff --git a/internal/model/dto/case.go b/internal/model/dto/case.go new file mode 100644 index 0000000..250fb10 --- /dev/null +++ b/internal/model/dto/case.go @@ -0,0 +1,39 @@ +package dto + +import ( + model "gh5-backend/internal/model/entity" + res "gh5-backend/pkg/utils/response" +) + +// request +type ( + CreateCaseRequest struct { + model.CaseEntity + } +) + +type ( + UpdateCaseRequest struct { + ID string `param:"id" validate:"required"` + CaseNumber string `json:"case_number"` + CaseDescription string `json:"case_description" validate:"required"` + CaseDetail string `json:"case_detail"` + Status string `json:"status" validate:"required"` + IsActive bool `json:"is_active"` + ContributorID string `json:"contributor_id"` + UploaderID string `json:"uploader_id"` + } +) + +// response +type ( + CaseResponse struct { + Data model.CaseModel + } + CaseResponseDoc struct { + Body struct { + Meta res.Meta `json:"meta"` + Data CaseResponse `json:"data"` + } `json:"body"` + } +) diff --git a/internal/model/entity/case.go b/internal/model/entity/case.go new file mode 100644 index 0000000..0d582c6 --- /dev/null +++ b/internal/model/entity/case.go @@ -0,0 +1,55 @@ +package entity + +import ( + "context" + + abstraction "gh5-backend/internal/model/base" + constant "gh5-backend/pkg/constants" + "gh5-backend/pkg/ctxval" + "gh5-backend/pkg/utils/date" + + "github.com/google/uuid" + "gorm.io/gorm" +) + +type CaseEntity struct { + CaseNumber string `json:"case_number" gorm:"size:50"` + CaseDescription string `json:"case_description" gorm:"not null"` + CaseDetail string `json:"case_detail"` + Status string `json:"status" validate:"required" gorm:"not null"` + IsActive bool `json:"is_active"` + ContributorID *string `json:"contributor_id"` + UploaderID *string `json:"uploader_id"` + + Contributor *UserModel `json:"contributor" gorm:"foreignkey:ContributorID"` + Uploader *UserModel `json:"uploader" gorm:"foreignkey:UploaderID"` +} + +type CaseModel struct { + abstraction.Entity + CaseEntity + Context context.Context `json:"-" gorm:"-"` +} + +func (CaseModel) TableName() string { + return "cases" +} + +func (m *CaseModel) BeforeCreate(tx *gorm.DB) (err error) { + m.ID = uuid.New().String() + m.IsActive = true + m.CreatedAt = *date.DateTodayLocal() + m.CreatedBy = constant.DB_DEFAULT_CREATED_BY + + return +} + +func (m *CaseModel) BeforeUpdate(tx *gorm.DB) (err error) { + m.ModifiedAt = date.DateTodayLocal() + + authCtx := ctxval.GetAuthValue(m.Context) + if authCtx != nil { + m.ModifiedBy = &authCtx.Name + } + return +} diff --git a/internal/repository/case_repository.go b/internal/repository/case_repository.go new file mode 100644 index 0000000..8800462 --- /dev/null +++ b/internal/repository/case_repository.go @@ -0,0 +1,22 @@ +package repository + +import ( + "gh5-backend/internal/model/entity" + + "github.com/sirupsen/logrus" + "gorm.io/gorm" +) + +type CaseRepository struct { + Repository[entity.CaseModel] + Log *logrus.Logger +} + +func NewCaseRepository(conn *gorm.DB, log *logrus.Logger) *CaseRepository { + model := entity.CaseModel{} + repository := NewRepository(conn, model, model.TableName()) + return &CaseRepository{ + Repository: *repository, + Log: log, + } +} diff --git a/internal/usecase/case_usecase.go b/internal/usecase/case_usecase.go new file mode 100644 index 0000000..84339b3 --- /dev/null +++ b/internal/usecase/case_usecase.go @@ -0,0 +1,78 @@ +package usecase + +import ( + "context" + "gh5-backend/internal/factory/repository" + "gh5-backend/internal/model/dto" + model "gh5-backend/internal/model/entity" +) + +type CaseUsecase struct { + RepositoryFactory repository.Factory +} + +func NewCaseUsecase(f repository.Factory) *CaseUsecase { + return &CaseUsecase{f} +} + +func (u *CaseUsecase) Find(ctx context.Context) ([]dto.CaseResponse, error) { + var result []dto.CaseResponse + + Cases, err := u.RepositoryFactory.CaseRepository.Find(ctx) + if err != nil { + u.RepositoryFactory.Log.Warnf("Failed find all cases : %+v", err) + return result, err + } + + for _, Case := range Cases { + result = append(result, dto.CaseResponse{ + Data: Case, + }) + } + + return result, nil +} + +func (u *CaseUsecase) FindByID(ctx context.Context, payload dto.ByIDRequest) (dto.CaseResponse, error) { + var result dto.CaseResponse + + data, err := u.RepositoryFactory.CaseRepository.FindByID(ctx, payload.ID) + if err != nil { + u.RepositoryFactory.Log.Warnf("Failed find case by id : %+v", err) + return result, err + } + + result = dto.CaseResponse{ + Data: *data, + } + + return result, nil +} + +func (u *CaseUsecase) Create(ctx context.Context, payload dto.CreateCaseRequest) (dto.CaseResponse, error) { + var ( + result dto.CaseResponse + data model.CaseModel + Case = model.CaseModel{ + CaseEntity: model.CaseEntity{ + CaseNumber: payload.CaseNumber, + CaseDetail: payload.CaseDetail, + Status: payload.Status, + UploaderID: payload.UploaderID, + }, + Context: ctx, + } + ) + + data, err := u.RepositoryFactory.CaseRepository.Create(ctx, Case) + if err != nil { + u.RepositoryFactory.Log.Warnf("Failed create case : %+v", err) + return result, err + } + + result = dto.CaseResponse{ + Data: data, + } + + return result, nil +}