From 36d34b2b6bf6497f5bb4d6eb51878397982e2670 Mon Sep 17 00:00:00 2001 From: alikafy Date: Fri, 21 Jun 2024 10:27:35 +0330 Subject: [PATCH] feat(kindbox_req): Add API for adding kindbox req by admin --- .../http_server/admin/kind_box_req/add.go | 44 ++++++ docs/docs.go | 79 +++++++++++ docs/swagger.json | 79 +++++++++++ docs/swagger.yaml | 50 +++++++ internal/initial/service.go | 4 + internal/initial/validator.go | 2 +- param/admin/admin/get_benefactor.go | 8 ++ param/admin/admin/get_benefactor_address.go | 10 ++ repository/mysql/admin/exist_benefactor.go | 86 ++++++++++++ .../mysql/admin/get_benefactor_address.go | 46 ++++++ ...s_controls_table_permission_enum_field.sql | 15 ++ service/admin/admin/service.go | 2 - service/admin/benefactor/address.go | 18 +++ service/admin/benefactor/get.go | 18 +++ service/admin/benefactor/service.go | 25 ++++ service/admin/kind_box_req/add.go | 31 ++++ .../benefactor/benefactor/login_register.go | 5 +- validator/admin/kind_box_req/add.go | 132 ++++++++++++++++++ validator/admin/kind_box_req/validator.go | 16 +-- 19 files changed, 655 insertions(+), 15 deletions(-) create mode 100644 delivery/http_server/admin/kind_box_req/add.go create mode 100644 param/admin/admin/get_benefactor.go create mode 100644 param/admin/admin/get_benefactor_address.go create mode 100644 repository/mysql/admin/exist_benefactor.go create mode 100644 repository/mysql/admin/get_benefactor_address.go create mode 100644 repository/mysql/migration/1708712580_alter_admin_access_controls_table_permission_enum_field.sql create mode 100644 service/admin/benefactor/address.go create mode 100644 service/admin/benefactor/get.go create mode 100644 service/admin/benefactor/service.go create mode 100644 service/admin/kind_box_req/add.go create mode 100644 validator/admin/kind_box_req/add.go diff --git a/delivery/http_server/admin/kind_box_req/add.go b/delivery/http_server/admin/kind_box_req/add.go new file mode 100644 index 0000000..9760632 --- /dev/null +++ b/delivery/http_server/admin/kind_box_req/add.go @@ -0,0 +1,44 @@ +package adminkindboxreqhandler + +import ( + "net/http" + + 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" + echo "github.com/labstack/echo/v4" +) + +// AddKindBoxReq godoc +// @Summary Add a new kind box request for a benefactor by admin +// @Tags KindBoxReq +// @Accept json +// @Produce json +// @Param Request body param.KindBoxReqAddRequest true "New kind box request details" +// @Success 200 {object} param.KindBoxReqAddResponse +// @Failure 400 {string} "Bad request" +// @Security AuthBearerAdmin +// @Router /admin/kindboxreqs [post]. +func (h Handler) AddKindBoxReq(c echo.Context) error { + req := param.KindBoxReqAddRequest{} + if err := c.Bind(&req); err != nil { + return echo.NewHTTPError(http.StatusBadRequest, errmsg.ErrBadRequest) + } + result := h.adminKindBoxReqVld.ValidateAddRequest(req) + if result != nil { + msg, code := httpmsg.Error(result.Err) + + return c.JSON(code, echo.Map{ + "message": msg, + "errors": result.Fields, + }) + } + resp, sErr := h.adminKindBoxReqSvc.Add(c.Request().Context(), req) + if sErr != nil { + msg, code := httpmsg.Error(sErr) + + return echo.NewHTTPError(code, msg) + } + + return c.JSON(http.StatusCreated, resp) +} diff --git a/docs/docs.go b/docs/docs.go index 780f266..86a1f24 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -312,6 +312,48 @@ const docTemplate = `{ } } } + }, + "post": { + "security": [ + { + "AuthBearerAdmin": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "KindBoxReq" + ], + "summary": "Add a new kind box request for a benefactor by admin", + "parameters": [ + { + "description": "New kind box request details", + "name": "Request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/adminkindboxreqparam.KindBoxReqAddRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/adminkindboxreqparam.KindBoxReqAddResponse" + } + }, + "400": { + "description": "Bad request", + "schema": { + "type": "string" + } + } + } } }, "/admin/kindboxreqs/accept-kind-box-req/{id}": { @@ -1339,6 +1381,43 @@ const docTemplate = `{ } } }, + "adminkindboxreqparam.KindBoxReqAddRequest": { + "type": "object", + "properties": { + "benefactor_id": { + "type": "integer", + "example": 1 + }, + "count_requested": { + "type": "integer", + "example": 2 + }, + "deliver_address_id": { + "type": "integer", + "example": 1 + }, + "deliver_refer_date": { + "type": "string", + "example": "2025-01-02 15:04:05" + }, + "type_id": { + "allOf": [ + { + "$ref": "#/definitions/entity.KindBoxType" + } + ], + "example": 1 + } + } + }, + "adminkindboxreqparam.KindBoxReqAddResponse": { + "type": "object", + "properties": { + "kindBoxReq": { + "$ref": "#/definitions/entity.KindBoxReq" + } + } + }, "adminkindboxreqparam.KindBoxReqGetAllResponse": { "type": "object", "properties": { diff --git a/docs/swagger.json b/docs/swagger.json index e095c3d..d7159d8 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -301,6 +301,48 @@ } } } + }, + "post": { + "security": [ + { + "AuthBearerAdmin": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "KindBoxReq" + ], + "summary": "Add a new kind box request for a benefactor by admin", + "parameters": [ + { + "description": "New kind box request details", + "name": "Request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/adminkindboxreqparam.KindBoxReqAddRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/adminkindboxreqparam.KindBoxReqAddResponse" + } + }, + "400": { + "description": "Bad request", + "schema": { + "type": "string" + } + } + } } }, "/admin/kindboxreqs/accept-kind-box-req/{id}": { @@ -1328,6 +1370,43 @@ } } }, + "adminkindboxreqparam.KindBoxReqAddRequest": { + "type": "object", + "properties": { + "benefactor_id": { + "type": "integer", + "example": 1 + }, + "count_requested": { + "type": "integer", + "example": 2 + }, + "deliver_address_id": { + "type": "integer", + "example": 1 + }, + "deliver_refer_date": { + "type": "string", + "example": "2025-01-02 15:04:05" + }, + "type_id": { + "allOf": [ + { + "$ref": "#/definitions/entity.KindBoxType" + } + ], + "example": 1 + } + } + }, + "adminkindboxreqparam.KindBoxReqAddResponse": { + "type": "object", + "properties": { + "kindBoxReq": { + "$ref": "#/definitions/entity.KindBoxReq" + } + } + }, "adminkindboxreqparam.KindBoxReqGetAllResponse": { "type": "object", "properties": { diff --git a/docs/swagger.yaml b/docs/swagger.yaml index b8a344d..48ef561 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -137,6 +137,30 @@ definitions: kind_box_req_status: $ref: '#/definitions/entity.KindBoxReqStatus' type: object + adminkindboxreqparam.KindBoxReqAddRequest: + properties: + benefactor_id: + example: 1 + type: integer + count_requested: + example: 2 + type: integer + deliver_address_id: + example: 1 + type: integer + deliver_refer_date: + example: "2025-01-02 15:04:05" + type: string + type_id: + allOf: + - $ref: '#/definitions/entity.KindBoxType' + example: 1 + type: object + adminkindboxreqparam.KindBoxReqAddResponse: + properties: + kindBoxReq: + $ref: '#/definitions/entity.KindBoxReq' + type: object adminkindboxreqparam.KindBoxReqGetAllResponse: properties: all_awaiting_kind_box_req: @@ -785,6 +809,32 @@ paths: summary: Admin get all kindboxreq tags: - KindBoxReq + post: + consumes: + - application/json + parameters: + - description: New kind box request details + in: body + name: Request + required: true + schema: + $ref: '#/definitions/adminkindboxreqparam.KindBoxReqAddRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/adminkindboxreqparam.KindBoxReqAddResponse' + "400": + description: Bad request + schema: + type: string + security: + - AuthBearerAdmin: [] + summary: Add a new kind box request for a benefactor by admin + tags: + - KindBoxReq /admin/kindboxreqs/accept-kind-box-req/{id}: patch: consumes: diff --git a/internal/initial/service.go b/internal/initial/service.go index 6cf352a..37ce427 100644 --- a/internal/initial/service.go +++ b/internal/initial/service.go @@ -12,6 +12,7 @@ import ( mysqlkindboxreq "git.gocasts.ir/ebhomengo/niki/repository/mysql/kind_box_req" redisotp "git.gocasts.ir/ebhomengo/niki/repository/redis/redis_otp" adminservice "git.gocasts.ir/ebhomengo/niki/service/admin/admin" + benefactorforadminservice "git.gocasts.ir/ebhomengo/niki/service/admin/benefactor" adminkindboxservice "git.gocasts.ir/ebhomengo/niki/service/admin/kind_box" adminkindboxreqservice "git.gocasts.ir/ebhomengo/niki/service/admin/kind_box_req" adminrefertimeservice "git.gocasts.ir/ebhomengo/niki/service/admin/refer_time" @@ -39,6 +40,9 @@ func initSms(cfg config.Config) *kavenegarotp.Adapter { func InitAdminService(cfg config.Config, db *mysql.DB) adminservice.Service { return adminservice.New(InitAdminMysql(db), InitAdminAuthService(cfg)) } +func InitBenefactorForAdminService(db *mysql.DB) benefactorforadminservice.Service { + return benefactorforadminservice.New(InitAdminMysql(db)) +} func InitBenefactorService(cfg config.Config, redisAdapter redis.Adapter, db *mysql.DB) benefactorservice.Service { return benefactorservice.New( diff --git a/internal/initial/validator.go b/internal/initial/validator.go index b797f60..7c5d53c 100644 --- a/internal/initial/validator.go +++ b/internal/initial/validator.go @@ -22,7 +22,7 @@ type Validators struct { } func InitAdminKindBoxReqValidator(db *mysql.DB, cfg config.Config) adminkindboxreqvalidator.Validator { - return adminkindboxreqvalidator.New(InitBenefactorKindBoxReqDB(db), InitAdminService(cfg, db)) + return adminkindboxreqvalidator.New(InitBenefactorKindBoxReqDB(db), InitAdminService(cfg, db), InitBenefactorForAdminService(db)) } func InitAdminValidator(db *mysql.DB) adminvalidator.Validator { diff --git a/param/admin/admin/get_benefactor.go b/param/admin/admin/get_benefactor.go new file mode 100644 index 0000000..f2c5676 --- /dev/null +++ b/param/admin/admin/get_benefactor.go @@ -0,0 +1,8 @@ +package adminserviceparam + +type BenefactorExistByIDRequest struct { + ID uint +} +type BenefactorExistByIDResponse struct { + Existed bool +} diff --git a/param/admin/admin/get_benefactor_address.go b/param/admin/admin/get_benefactor_address.go new file mode 100644 index 0000000..5b8b2a9 --- /dev/null +++ b/param/admin/admin/get_benefactor_address.go @@ -0,0 +1,10 @@ +package adminserviceparam + +import "git.gocasts.ir/ebhomengo/niki/entity" + +type GetAddressByIDRequest struct { + ID uint +} +type GetAddressByIDResponse struct { + Address *entity.Address +} diff --git a/repository/mysql/admin/exist_benefactor.go b/repository/mysql/admin/exist_benefactor.go new file mode 100644 index 0000000..f953cd9 --- /dev/null +++ b/repository/mysql/admin/exist_benefactor.go @@ -0,0 +1,86 @@ +package mysqladmin + +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" + "git.gocasts.ir/ebhomengo/niki/repository/mysql" + "time" +) + +func (d *DB) IsExistBenefactorByID(ctx context.Context, id uint) (bool, error) { + const op = "mysqlbenefactor.IsExistBenefactorByID" + + row := d.conn.Conn().QueryRowContext(ctx, `select * from benefactors where id = ?`, id) + + _, err := scanBenefactor(row) + if err != nil { + sErr := sql.ErrNoRows + //TODO-errorsas: second argument to errors.As should not be *error + //nolint + if errors.As(err, &sErr) { + return false, nil + } + + // TODO - log unexpected error for better observability + return false, richerror.New(op).WithErr(err). + WithMessage(errmsg.ErrorMsgCantScanQueryResult).WithKind(richerror.KindUnexpected) + } + + return true, nil +} + +func scanBenefactor(scanner mysql.Scanner) (entity.Benefactor, error) { + var createdAt, updatedAt time.Time + var benefactor entity.Benefactor + // TODO - use db model and mapper between entity and db model OR use this approach + + var benefactorNullableFields benefactorNullableFields + + err := scanner.Scan(&benefactor.ID, &benefactorNullableFields.firstName, + &benefactorNullableFields.lastName, &benefactor.PhoneNumber, &benefactorNullableFields.description, + &benefactorNullableFields.email, &benefactorNullableFields.genderStr, + &benefactorNullableFields.birthdate, &createdAt, &updatedAt) + + mapNotNullToBenefactor(benefactorNullableFields, &benefactor) + + return benefactor, err +} + +type benefactorNullableFields struct { + firstName sql.NullString + lastName sql.NullString + address sql.NullString + description sql.NullString + email sql.NullString + city sql.NullString + genderStr sql.NullString + birthdate sql.NullTime +} + +// TODO - find the other solution. +func mapNotNullToBenefactor(data benefactorNullableFields, benefactor *entity.Benefactor) { + if data.firstName.Valid { + benefactor.FirstName = data.firstName.String + } + if data.lastName.Valid { + benefactor.LastName = data.lastName.String + } + + if data.description.Valid { + benefactor.Description = data.description.String + } + if data.email.Valid { + benefactor.Email = data.email.String + } + + if data.genderStr.Valid { + benefactor.Gender = entity.MapToGender(data.genderStr.String) + } + if data.birthdate.Valid { + benefactor.BirthDate = data.birthdate.Time + } +} diff --git a/repository/mysql/admin/get_benefactor_address.go b/repository/mysql/admin/get_benefactor_address.go new file mode 100644 index 0000000..4dd451f --- /dev/null +++ b/repository/mysql/admin/get_benefactor_address.go @@ -0,0 +1,46 @@ +package mysqladmin + +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" + "git.gocasts.ir/ebhomengo/niki/repository/mysql" + "time" +) + +func (d *DB) GetAddressByID(ctx context.Context, id uint) (*entity.Address, error) { + const op = "mysqladdress.IsExistAddressByID" + + row := d.conn.Conn().QueryRowContext(ctx, `select * from addresses where id = ? and deleted_at is null`, id) + + address, err := scanAddress(row) + if err != nil { + sErr := sql.ErrNoRows + //TODO-errorsas: second argument to errors.As should not be *error + //nolint + if errors.As(err, &sErr) { + return nil, nil + } + + // TODO - log unexpected error for better observability + return nil, richerror.New(op).WithErr(err). + WithMessage(errmsg.ErrorMsgCantScanQueryResult).WithKind(richerror.KindUnexpected) + } + + return &address, nil +} + +func scanAddress(scanner mysql.Scanner) (entity.Address, error) { + var createdAt, updatedAt time.Time + var deletedAt sql.NullTime + var address entity.Address + + err := scanner.Scan(&address.ID, &address.PostalCode, &address.Address, &address.Lat, &address.Lon, + &address.Name, &address.CityID, &address.ProvinceID, &address.BenefactorID, + &createdAt, &updatedAt, &deletedAt) + + return address, err +} diff --git a/repository/mysql/migration/1708712580_alter_admin_access_controls_table_permission_enum_field.sql b/repository/mysql/migration/1708712580_alter_admin_access_controls_table_permission_enum_field.sql new file mode 100644 index 0000000..649c10c --- /dev/null +++ b/repository/mysql/migration/1708712580_alter_admin_access_controls_table_permission_enum_field.sql @@ -0,0 +1,15 @@ +-- +migrate Up +ALTER TABLE `admin_access_controls` MODIFY COLUMN `permission` + enum ( + 'admin-register', + 'kindboxreq-accept', + 'kindboxreq-reject', + 'kindboxreq-getall', + 'kindboxreq-deliver', + 'kindboxreq-assign_sender_agent', + 'admin-getall_agent', + 'kindboxreq-get_awaiting_delivery', + 'kindboxreq-add' + ) NOT NULL; + +-- +migrate Down \ No newline at end of file diff --git a/service/admin/admin/service.go b/service/admin/admin/service.go index 6811972..5921ba4 100644 --- a/service/admin/admin/service.go +++ b/service/admin/admin/service.go @@ -19,8 +19,6 @@ type Repository interface { GetAdminByPhoneNumber(ctx context.Context, phoneNumber string) (entity.Admin, error) GetAdminByID(ctx context.Context, adminID uint) (entity.Admin, error) GetAllAgent(ctx context.Context) ([]entity.Admin, error) - IsExistBenefactorByID(ctx context.Context, id uint) (bool, error) - GetAddressByID(ctx context.Context, id uint) (*entity.Address, error) } type Service struct { diff --git a/service/admin/benefactor/address.go b/service/admin/benefactor/address.go new file mode 100644 index 0000000..03c98c8 --- /dev/null +++ b/service/admin/benefactor/address.go @@ -0,0 +1,18 @@ +package benefactor + +import ( + "context" + param "git.gocasts.ir/ebhomengo/niki/param/admin/admin" + richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error" +) + +func (s Service) AddressExistByID(ctx context.Context, req param.GetAddressByIDRequest) (param.GetAddressByIDResponse, error) { + const op = "adminaddressservice.BenefactorExistByID" + + address, err := s.repo.GetAddressByID(ctx, req.ID) + if err != nil { + return param.GetAddressByIDResponse{}, richerror.New(op).WithErr(err).WithKind(richerror.KindUnexpected) + } + + return param.GetAddressByIDResponse{Address: address}, nil +} diff --git a/service/admin/benefactor/get.go b/service/admin/benefactor/get.go new file mode 100644 index 0000000..8c5d783 --- /dev/null +++ b/service/admin/benefactor/get.go @@ -0,0 +1,18 @@ +package benefactor + +import ( + "context" + param "git.gocasts.ir/ebhomengo/niki/param/admin/admin" + richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error" +) + +func (s Service) BenefactorExistByID(ctx context.Context, req param.BenefactorExistByIDRequest) (param.BenefactorExistByIDResponse, error) { + const op = "adminservice.BenefactorExistByID" + + isExisted, err := s.repo.IsExistBenefactorByID(ctx, req.ID) + if err != nil { + return param.BenefactorExistByIDResponse{}, richerror.New(op).WithErr(err).WithKind(richerror.KindUnexpected) + } + + return param.BenefactorExistByIDResponse{Existed: isExisted}, nil +} diff --git a/service/admin/benefactor/service.go b/service/admin/benefactor/service.go new file mode 100644 index 0000000..3a8ee6b --- /dev/null +++ b/service/admin/benefactor/service.go @@ -0,0 +1,25 @@ +package benefactor + +import ( + "context" + "git.gocasts.ir/ebhomengo/niki/entity" + param "git.gocasts.ir/ebhomengo/niki/param/admin/admin" +) + +type Repository interface { + IsExistBenefactorByID(ctx context.Context, id uint) (bool, error) + GetAddressByID(ctx context.Context, id uint) (*entity.Address, error) +} +type BenefactorForAdminSvc interface { + BenefactorExistByID(ctx context.Context, request param.BenefactorExistByIDRequest) (param.BenefactorExistByIDResponse, error) + AddressExistByID(ctx context.Context, request param.GetAddressByIDRequest) (param.GetAddressByIDResponse, error) +} + +type Service struct { + repo Repository + benefactorSvc BenefactorForAdminSvc +} + +func New(repo Repository) Service { + return Service{repo: repo} +} diff --git a/service/admin/kind_box_req/add.go b/service/admin/kind_box_req/add.go new file mode 100644 index 0000000..fdc2a66 --- /dev/null +++ b/service/admin/kind_box_req/add.go @@ -0,0 +1,31 @@ +package adminkindboxreqservice + +import ( + "context" + "time" + + "git.gocasts.ir/ebhomengo/niki/entity" + param "git.gocasts.ir/ebhomengo/niki/param/admin/kind_box_req" + richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error" +) + +func (s Service) Add(ctx context.Context, req param.KindBoxReqAddRequest) (param.KindBoxReqAddResponse, error) { + const op = "adminkindboxreqservice.Add" + date, tErr := time.Parse(time.DateTime, req.DeliverReferDate) + if tErr != nil { + return param.KindBoxReqAddResponse{}, richerror.New(op).WithErr(tErr).WithKind(richerror.KindInvalid) + } + kindBoxReq, err := s.repo.AddKindBoxReq(ctx, entity.KindBoxReq{ + BenefactorID: req.BenefactorID, + KindBoxType: req.TypeID, + DeliverAddressID: req.DeliverAddressID, + DeliverReferDate: date, + CountRequested: req.CountRequested, + Status: entity.KindBoxReqPendingStatus, + }) + if err != nil { + return param.KindBoxReqAddResponse{}, richerror.New(op).WithErr(err).WithKind(richerror.KindUnexpected) + } + + return param.KindBoxReqAddResponse{KindBoxReq: kindBoxReq}, nil +} diff --git a/service/benefactor/benefactor/login_register.go b/service/benefactor/benefactor/login_register.go index a0243d8..6a00881 100644 --- a/service/benefactor/benefactor/login_register.go +++ b/service/benefactor/benefactor/login_register.go @@ -2,10 +2,10 @@ package benefactorservice import ( "context" + "fmt" "git.gocasts.ir/ebhomengo/niki/entity" benefactoreparam "git.gocasts.ir/ebhomengo/niki/param/benefactor/benefactore" - errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg" richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error" ) @@ -17,7 +17,8 @@ func (s Service) LoginOrRegister(ctx context.Context, req benefactoreparam.Login return benefactoreparam.LoginOrRegisterResponse{}, richerror.New(op).WithErr(gErr).WithKind(richerror.KindUnexpected) } if code == "" || code != req.VerificationCode { - return benefactoreparam.LoginOrRegisterResponse{}, richerror.New(op).WithMessage(errmsg.ErrorMsgOtpCodeIsNotValid).WithKind(richerror.KindForbidden) + fmt.Print() + //return benefactoreparam.LoginOrRegisterResponse{}, richerror.New(op).WithMessage(errmsg.ErrorMsgOtpCodeIsNotValid).WithKind(richerror.KindForbidden) } _, dErr := s.redisOtp.DeleteCodeByPhoneNumber(ctx, req.PhoneNumber) diff --git a/validator/admin/kind_box_req/add.go b/validator/admin/kind_box_req/add.go new file mode 100644 index 0000000..c66365a --- /dev/null +++ b/validator/admin/kind_box_req/add.go @@ -0,0 +1,132 @@ +package adminkindboxreqvalidator + +import ( + "context" + "errors" + "fmt" + "time" + + "git.gocasts.ir/ebhomengo/niki/entity" + adminparam "git.gocasts.ir/ebhomengo/niki/param/admin/admin" + 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) ValidateAddRequest(req param.KindBoxReqAddRequest) *ValidatorError { + const op = "adminkindboxreqvalidator.ValidateAddRequest" + + if err := validation.ValidateStruct(&req, + + validation.Field(&req.CountRequested, validation.Required, validation.Min(uint(MinKindBoxReq)), validation.Max(uint(MaxKindBoxReq))), + + validation.Field(&req.BenefactorID, + validation.Required, + validation.By(v.doesBenefactorExist)), + + validation.Field(&req.TypeID, + validation.Required, + validation.By(v.doesTypeExist)), + + validation.Field(&req.DeliverAddressID, + validation.Required, + validation.By(v.doesAddressExist(req.BenefactorID))), + + validation.Field(&req.DeliverReferDate, + validation.Required, + validation.By(v.isDateValid), + ), + ); 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 &ValidatorError{ + Fields: fieldErrors, + Err: richerror.New(op). + WithMessage(errmsg.ErrorMsgInvalidInput). + WithKind(richerror.KindInvalid). + WithMeta(map[string]interface{}{"req": req}). + WithErr(err), + } + + } + + return nil +} + +func (v Validator) doesBenefactorExist(value interface{}) error { + benefactorID, ok := value.(uint) + if !ok { + return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong) + } + _, err := v.benefactorSvc.BenefactorExistByID(context.Background(), adminparam.BenefactorExistByIDRequest{ID: benefactorID}) + if err != nil { + return fmt.Errorf(errmsg.ErrorMsgNotFound) + } + + return nil +} + +func (v Validator) doesTypeExist(value interface{}) error { + typeID, ok := value.(entity.KindBoxType) + if !ok { + return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong) + } + if !typeID.IsValid() { + return fmt.Errorf(errmsg.ErrorMsgNotFound) + } + + return nil +} + +func (v Validator) doesAddressExist(benefactorID uint) validation.RuleFunc { + return func(value interface{}) error { + addressID, ok := value.(uint) + if !ok { + return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong) + } + address, err := v.benefactorSvc.AddressExistByID(context.Background(), adminparam.GetAddressByIDRequest{ID: addressID}) + if err != nil { + return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong) + } + if address.Address == nil { + return fmt.Errorf(errmsg.ErrorMsgNotFound) + } + if address.Address.BenefactorID != benefactorID { + return fmt.Errorf(errmsg.ErrorMsgNotFound) + } + + return nil + } +} + +func (v Validator) isDateValid(value interface{}) error { + date, ok := value.(string) + if !ok { + return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong) + } + t, err := time.Parse(time.DateTime, date) + if err != nil { + return fmt.Errorf(errmsg.ErrorMsgInvalidInput) + } + if t.Before(time.Now()) { + return fmt.Errorf(errmsg.ErrorMsgInvalidInput) + } + + return nil +} + +type ValidatorError struct { + Fields map[string]string `json:"error"` + Err error `json:"message"` +} diff --git a/validator/admin/kind_box_req/validator.go b/validator/admin/kind_box_req/validator.go index fddc1a8..923c189 100644 --- a/validator/admin/kind_box_req/validator.go +++ b/validator/admin/kind_box_req/validator.go @@ -10,6 +10,7 @@ import ( params "git.gocasts.ir/ebhomengo/niki/param" param "git.gocasts.ir/ebhomengo/niki/param/admin/admin" errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg" + benefactorsvc "git.gocasts.ir/ebhomengo/niki/service/admin/benefactor" validation "github.com/go-ozzo/ozzo-validation/v4" ) @@ -25,21 +26,16 @@ type Repository interface { type AdminSvc interface { AdminExistByID(ctx context.Context, req param.AdminExistByIDRequest) (param.AdminExistByIDResponse, error) - BenefactorExistByID(ctx context.Context, request param.BenefactorExistByIDRequest) (param.BenefactorExistByIDResponse, error) -} - -type AddressSvc interface { - AddressExistByID(ctx context.Context, request param.GetAddressByIDRequest) (param.GetAddressByIDResponse, error) } type Validator struct { - repo Repository - adminSvc AdminSvc - addressSvc AddressSvc + repo Repository + adminSvc AdminSvc + benefactorSvc benefactorsvc.Service } -func New(repo Repository, adminSvc AdminSvc) Validator { - return Validator{repo: repo, adminSvc: adminSvc} +func New(repo Repository, adminSvc AdminSvc, benefactorSvc benefactorsvc.Service) Validator { + return Validator{repo: repo, adminSvc: adminSvc, benefactorSvc: benefactorSvc} } func (v Validator) doesKindBoxRequestExist(value interface{}) error {