From 5708f0c4140c2bf22a986e77f171a3afb208b5e1 Mon Sep 17 00:00:00 2001 From: Abolfazl Norzad Date: Mon, 22 Jan 2024 17:37:51 +0330 Subject: [PATCH] add validation for accepting kind-box-req --- .../http_server/admin/kind_box_req/accept.go | 19 ++-- pkg/err_msg/message.go | 1 + repository/mysql/kind_box_req/kind_box_req.go | 41 ++++++++- service/admin/kind_box_req/accept.go | 5 +- service/admin/kind_box_req/service.go | 3 +- service/admin/kind_box_req/update.go | 2 +- validator/admin/kind_box_req/accept.go | 42 +++++++++ validator/admin/kind_box_req/validator.go | 90 ++++++++++++------- 8 files changed, 155 insertions(+), 48 deletions(-) create mode 100644 validator/admin/kind_box_req/accept.go diff --git a/delivery/http_server/admin/kind_box_req/accept.go b/delivery/http_server/admin/kind_box_req/accept.go index b5f3075..85ab582 100644 --- a/delivery/http_server/admin/kind_box_req/accept.go +++ b/delivery/http_server/admin/kind_box_req/accept.go @@ -1,11 +1,11 @@ package adminkindboxreqhandler import ( - errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg" "net/http" "strconv" param "git.gocasts.ir/ebhomengo/niki/param/admin/kind_box_req" + errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg" httpmsg "git.gocasts.ir/ebhomengo/niki/pkg/http_msg" "github.com/labstack/echo/v4" ) @@ -20,14 +20,15 @@ func (h Handler) Accept(c echo.Context) error { return c.JSON(http.StatusBadRequest, errmsg.ErrorMsgInvalidInput) } req.ID = uint(num) - // if fieldErrors, err := h.adminKindBoxReqVld.ValidateGetRequest(req); err != nil { - // msg, code := httpmsg.Error(err) - // - // return c.JSON(code, echo.Map{ - // "message": msg, - // "errors": fieldErrors, - // }) - //} + if fieldErrors, err := h.adminKindBoxReqVld.ValidateAcceptRequest(req); err != nil { + msg, code := httpmsg.Error(err) + + return c.JSON(code, echo.Map{ + "message": msg, + "errors": fieldErrors, + }) + } + resp, sErr := h.adminKindBoxReqSvc.Accept(c.Request().Context(), req) if sErr != nil { msg, code := httpmsg.Error(sErr) diff --git a/pkg/err_msg/message.go b/pkg/err_msg/message.go index f716923..a7744c4 100644 --- a/pkg/err_msg/message.go +++ b/pkg/err_msg/message.go @@ -14,4 +14,5 @@ const ( ErrorMsgOtpCodeIsNotValid = "verification code is not valid" ErrorMsgCantScanQueryResult = "can't scan query result" ErrorMsgPhoneNumberOrPassIsIncorrect = "phone number or password is incorrect" + ErrorMsgReAcceptKindBoxReq = "accepted request cannot be re-accepted" ) diff --git a/repository/mysql/kind_box_req/kind_box_req.go b/repository/mysql/kind_box_req/kind_box_req.go index cbe7fea..ae937a8 100644 --- a/repository/mysql/kind_box_req/kind_box_req.go +++ b/repository/mysql/kind_box_req/kind_box_req.go @@ -2,6 +2,9 @@ package mysqlkindboxreq import ( "context" + "database/sql" + "errors" + "git.gocasts.ir/ebhomengo/niki/entity" errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg" richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error" @@ -29,6 +32,7 @@ func (d DB) AcceptKindBoxReq(ctx context.Context, kindBoxReqID uint, countAccept op := richerror.Op("mysqlkindboxreq.AcceptKindBoxReq") statement, err := d.conn.Conn(). Prepare(`update kind_box_reqs set count_accepted = ? , status = ? where id = ?`) + defer statement.Close() if err != nil { return richerror.New(op).WithErr(err). WithMessage(errmsg.ErrorMsgSomethingWentWrong).WithKind(richerror.KindUnexpected) @@ -42,13 +46,46 @@ func (d DB) AcceptKindBoxReq(ctx context.Context, kindBoxReqID uint, countAccept return nil } -func (d DB) FindByID(ctx context.Context, id uint) (entity.KindBoxReq, error) { - op := richerror.Op("mysqlkindboxreq.findByID") +func (d DB) GetByID(ctx context.Context, id uint) (entity.KindBoxReq, error) { + op := richerror.Op("mysqlkindboxreq.GetByID") row := d.conn.Conn().QueryRowContext(ctx, `select * from kind_box_reqs where id = ?`, id) k, err := scanKindBoxReq(row) if err != nil { return entity.KindBoxReq{}, richerror.New(op).WithErr(err). WithMessage(errmsg.ErrorMsgCantScanQueryResult).WithKind(richerror.KindUnexpected) } + return k, nil } + +func (d DB) KindBoxRequestExist(id uint) (bool, error) { + op := richerror.Op("mysqlkindboxreq.KindBoxRequestExist") + row := d.conn.Conn().QueryRow(`select * from kind_box_reqs where id = ?`, id) + _, sErr := scanKindBoxReq(row) + if sErr != nil { + if errors.Is(sErr, sql.ErrNoRows) { + return false, nil + } + + return false, richerror.New(op).WithErr(sErr).WithMessage(errmsg.ErrorMsgCantScanQueryResult). + WithKind(richerror.KindUnexpected).WithMeta(map[string]any{"id": id}) + } + + return true, nil +} + +func (d DB) CheckKindBoxReqStatusForAccepting(id uint) error { + op := richerror.Op("mysqlkindboxreq.CheckKindBoxReqStatusForAccepting") + + k, err := d.GetByID(context.Background(), id) + if err != nil { + return richerror.New(op).WithErr(err) + } + if k.Status == entity.KindBoxReqAcceptedStatus { + return richerror.New(op).WithMessage(errmsg.ErrorMsgReAcceptKindBoxReq).WithMeta(map[string]interface{}{ + "id": id, + }).WithKind(richerror.KindInvalid) + } + + return nil +} diff --git a/service/admin/kind_box_req/accept.go b/service/admin/kind_box_req/accept.go index 54f3960..f25116e 100644 --- a/service/admin/kind_box_req/accept.go +++ b/service/admin/kind_box_req/accept.go @@ -2,6 +2,7 @@ package adminkindboxreqservice import ( "context" + param "git.gocasts.ir/ebhomengo/niki/param/admin/kind_box_req" richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error" ) @@ -14,9 +15,9 @@ func (s Service) Accept(ctx context.Context, req param.KindBoxReqAcceptRequest) } // fire new event to create a kind-box. - //get kind box req + // get kind box req - kindBoxReq, gErr := s.repo.FindByID(ctx, req.ID) + kindBoxReq, gErr := s.repo.GetByID(ctx, req.ID) if gErr != nil { return param.KindBoxReqAcceptResponse{}, richerror.New(op).WithErr(err) } diff --git a/service/admin/kind_box_req/service.go b/service/admin/kind_box_req/service.go index 878b03e..077c203 100644 --- a/service/admin/kind_box_req/service.go +++ b/service/admin/kind_box_req/service.go @@ -2,6 +2,7 @@ package adminkindboxreqservice import ( "context" + "git.gocasts.ir/ebhomengo/niki/entity" ) @@ -13,7 +14,7 @@ type Repository interface { // GetAllKindBoxReq(ctx context.Context) ([]entity.KindBoxReq, error) // GetKindBoxReq(ctx context.Context, kindBoxReqID uint) (entity.KindBoxReq, error) AcceptKindBoxReq(ctx context.Context, kindBoxReqID uint, countAccepted uint) error - FindByID(ctx context.Context, id uint) (entity.KindBoxReq, error) + GetByID(ctx context.Context, id uint) (entity.KindBoxReq, error) } // TODO: check validation. diff --git a/service/admin/kind_box_req/update.go b/service/admin/kind_box_req/update.go index 0cd9d0e..72f6998 100644 --- a/service/admin/kind_box_req/update.go +++ b/service/admin/kind_box_req/update.go @@ -9,7 +9,7 @@ package adminkindboxreqservice // richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error" //) // -//func (s Service) Update(ctx context.Context, req param.KindBoxReqUpdateRequest) (param.KindBoxReqUpdateResponse, error) { +// func (s Service) Update(ctx context.Context, req param.KindBoxReqUpdateRequest) (param.KindBoxReqUpdateResponse, error) { // // TODO: can benefactor update its request ? // // TODO: Is Update Mothod Service Responsible to check which kindboxreqID belongs to benefactorID ? // // TODO: updating data(s) may have side-effect on other entities by masood-keshvary accepted -> rejected diff --git a/validator/admin/kind_box_req/accept.go b/validator/admin/kind_box_req/accept.go new file mode 100644 index 0000000..d41a40d --- /dev/null +++ b/validator/admin/kind_box_req/accept.go @@ -0,0 +1,42 @@ +package adminkindboxreqvalidator + +import ( + "errors" + + param "git.gocasts.ir/ebhomengo/niki/param/admin/kind_box_req" + errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg" + richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error" + validation "github.com/go-ozzo/ozzo-validation/v4" +) + +func (v Validator) ValidateAcceptRequest(req param.KindBoxReqAcceptRequest) (map[string]string, error) { + const op = "adminkindboxreqvalidator.ValidateAcceptRequest" + + if err := validation.ValidateStruct(&req, + validation.Field(&req.ID, validation.Required, validation.By(v.doesKindBoxRequestExist), validation.By(v.checkKindBoxReqStatus)), + + validation.Field(&req.CountAccepted, + validation.Required, + validation.Min(uint(MinKindBoxReq)), validation.Max(uint(MaxKindBoxReq)), + ), + ); err != nil { + fieldErrors := make(map[string]string) + + var errV validation.Errors + if errors.As(err, &errV) { + for key, value := range errV { + if value != nil { + fieldErrors[key] = value.Error() + } + } + } + + return fieldErrors, richerror.New(op). + WithMessage(errmsg.ErrorMsgInvalidInput). + WithKind(richerror.KindInvalid). + WithMeta(map[string]interface{}{"req": req}). + WithErr(err) + } + + return map[string]string{}, nil +} diff --git a/validator/admin/kind_box_req/validator.go b/validator/admin/kind_box_req/validator.go index d734d7f..515e34c 100644 --- a/validator/admin/kind_box_req/validator.go +++ b/validator/admin/kind_box_req/validator.go @@ -1,5 +1,12 @@ package adminkindboxreqvalidator +import ( + "errors" + "fmt" + + errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg" +) + const ( MinKindBoxReq = 1 MaxKindBoxReq = 100 @@ -7,10 +14,11 @@ const ( type Repository interface { // BenefactorExist(id int) (bool, error) - // KindBoxRequestExist(id int) (bool, error) + KindBoxRequestExist(id uint) (bool, error) // TypeExist(id int) (bool, error) // KindBoxBelongToBenefactor(benefactorID uint, kindboxID uint) (bool, error) // PendingStatus(id uint) (bool, error) + CheckKindBoxReqStatusForAccepting(id uint) error } type Validator struct { @@ -21,47 +29,63 @@ func New(repo Repository) Validator { return Validator{repo: repo} } -// -// func (v Validator) doesBenefactorExist(value interface{}) error { -// benefactorID, ok := value.(int) -// if !ok { -// return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong) -// } -// _, err := v.repo.BenefactorExist(benefactorID) -// if err != nil { -// return fmt.Errorf(errmsg.ErrorMsgNotFound) -// } -// -// return nil -//} -// -// func (v Validator) doesKindBoxBelongToBenefactor(benefactorID uint) validation.RuleFunc { -// return func(value interface{}) error { -// kbID, ok := value.(uint) +// func (v Validator) doesBenefactorExist(value interface{}) error { +// benefactorID, ok := value.(int) // if !ok { -// return fmt.Errorf(errmsg.ErrorMsgNotFound) +// return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong) // } -// _, err := v.repo.KindBoxBelongToBenefactor(benefactorID, kbID) +// _, err := v.repo.BenefactorExist(benefactorID) // if err != nil { // return fmt.Errorf(errmsg.ErrorMsgNotFound) // } // // return nil // } -//} // -// func (v Validator) doesKindBoxRequestExist(value interface{}) error { -// kindboxreqID, ok := value.(int) -// if !ok { -// return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong) -// } -// _, err := v.repo.KindBoxRequestExist(kindboxreqID) -// if err != nil { -// return fmt.Errorf(errmsg.ErrorMsgNotFound) -// } +// func (v Validator) doesKindBoxBelongToBenefactor(benefactorID uint) validation.RuleFunc { +// return func(value interface{}) error { +// kbID, ok := value.(uint) +// if !ok { +// return fmt.Errorf(errmsg.ErrorMsgNotFound) +// } +// _, err := v.repo.KindBoxBelongToBenefactor(benefactorID, kbID) +// if err != nil { +// return fmt.Errorf(errmsg.ErrorMsgNotFound) +// } // -// return nil -//} +// return nil +// } +// } +func (v Validator) doesKindBoxRequestExist(value interface{}) error { + kindboxreqID, ok := value.(uint) + if !ok { + return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong) + } + if isExist, err := v.repo.KindBoxRequestExist(kindboxreqID); !isExist || err != nil { + if err != nil { + return err + } + if !isExist { + return errors.New("kind box request is not exist") + } + } + + return nil +} + +func (v Validator) checkKindBoxReqStatus(value interface{}) error { + kindboxreqID, ok := value.(uint) + if !ok { + return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong) + } + err := v.repo.CheckKindBoxReqStatusForAccepting(kindboxreqID) + if err != nil { + return err + } + + return nil +} + // // func (v Validator) doesTypeExist(value interface{}) error { // typeID, ok := value.(int) @@ -76,7 +100,7 @@ func New(repo Repository) Validator { // return nil //} // -//func (v Validator) hasPendingStatus(value interface{}) error { +// func (v Validator) hasPendingStatus(value interface{}) error { // kindboxID, ok := value.(uint) // if !ok { // return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong)