diff --git a/delivery/http_server/admin/benefactor/get.go b/delivery/http_server/admin/benefactor/get.go index 1bd905e8..b0d2743f 100644 --- a/delivery/http_server/admin/benefactor/get.go +++ b/delivery/http_server/admin/benefactor/get.go @@ -1,13 +1,13 @@ package adminbenefactorhandler import ( - params "git.gocasts.ir/ebhomengo/niki/param" - adminaddressparam "git.gocasts.ir/ebhomengo/niki/param/admin/address" - adminkindboxparam "git.gocasts.ir/ebhomengo/niki/param/admin/kind_box" - adminkindboxreqparam "git.gocasts.ir/ebhomengo/niki/param/admin/kind_box_req" "net/http" + params "git.gocasts.ir/ebhomengo/niki/param" + adminaddressparam "git.gocasts.ir/ebhomengo/niki/param/admin/address" param "git.gocasts.ir/ebhomengo/niki/param/admin/benefactor" + adminkindboxparam "git.gocasts.ir/ebhomengo/niki/param/admin/kind_box" + adminkindboxreqparam "git.gocasts.ir/ebhomengo/niki/param/admin/kind_box_req" httpmsg "git.gocasts.ir/ebhomengo/niki/pkg/http_msg" "github.com/labstack/echo/v4" ) diff --git a/delivery/http_server/admin/benefactor/route.go b/delivery/http_server/admin/benefactor/route.go index b38be80d..a7be86ef 100644 --- a/delivery/http_server/admin/benefactor/route.go +++ b/delivery/http_server/admin/benefactor/route.go @@ -13,4 +13,6 @@ func (h Handler) SetRoutes(e *echo.Echo) { r.GET("", h.GetAllBenefactor, middleware.AdminAuthorization(h.authorizeSvc, entity.AdminBenefactorGetAllPermission)) r.GET("/:id", h.GetBenefactor, middleware.AdminAuthorization(h.authorizeSvc, entity.AdminBenefactorGetPermission)) + r.PUT("/:id", h.Update, middleware.AdminAuthorization(h.authorizeSvc, entity.AdminBenefactorUpdatePermission)) + r.PUT("/:id/status", h.UpdateStatus, middleware.AdminAuthorization(h.authorizeSvc, entity.AdminBenefactorUpdateStatusPermission)) } diff --git a/delivery/http_server/admin/benefactor/update.go b/delivery/http_server/admin/benefactor/update.go new file mode 100644 index 00000000..f5887522 --- /dev/null +++ b/delivery/http_server/admin/benefactor/update.go @@ -0,0 +1,47 @@ +package adminbenefactorhandler + +import ( + "net/http" + + param "git.gocasts.ir/ebhomengo/niki/param/admin/benefactor" + httpmsg "git.gocasts.ir/ebhomengo/niki/pkg/http_msg" + "github.com/labstack/echo/v4" +) + +// Update godoc +// @Summary Update benefactor details by admin +// @Description This endpoint update specific benefactor. +// @Tags Admins Benefactors +// @Accept json +// @Produce json +// @Param id path int true "Benefactor ID" +// @Param Request body param.BenefactorUpdateRequest true "Update Benefactor Body" +// @Success 204 +// @Failure 400 {string} "Bad request" +// @Failure 401 {string} "invalid or expired jwt" +// @Failure 403 {string} "user not allowed" +// @Failure 404 {string} "record not found" +// @Failure 500 {string} "something went wrong" +// @Security AuthBearerAdmin +// @Router /admins/benefactors/{id} [put]. +func (h Handler) Update(c echo.Context) error { + var req param.BenefactorUpdateRequest + if bErr := c.Bind(&req); bErr != nil { + return echo.NewHTTPError(http.StatusBadRequest) + } + + resp, sErr := h.benefactorSvc.Update(c.Request().Context(), req) + if sErr != nil { + msg, code := httpmsg.Error(sErr) + if resp.FieldErrors != nil { + return c.JSON(code, echo.Map{ + "message": msg, + "errors": resp.FieldErrors, + }) + } + + return echo.NewHTTPError(code, msg) + } + + return c.JSON(http.StatusNoContent, nil) +} diff --git a/delivery/http_server/admin/benefactor/update_status.go b/delivery/http_server/admin/benefactor/update_status.go new file mode 100644 index 00000000..a95941ea --- /dev/null +++ b/delivery/http_server/admin/benefactor/update_status.go @@ -0,0 +1,46 @@ +package adminbenefactorhandler + +import ( + "net/http" + + param "git.gocasts.ir/ebhomengo/niki/param/admin/benefactor" + httpmsg "git.gocasts.ir/ebhomengo/niki/pkg/http_msg" + "github.com/labstack/echo/v4" +) + +// UpdateStatus godoc +// @Summary Update benefactor status by admin +// @Description This endpoint update status (active/inactive) benefactor. +// @Tags Admins Benefactors +// @Accept json +// @Produce json +// @Param id path int true "Benefactor ID" +// @Param Request body param.BenefactorUpdateStatusRequest true "Update Benefactor Status" +// @Success 204 +// @Failure 400 {string} "Bad request" +// @Failure 401 {string} "invalid or expired jwt" +// @Failure 403 {string} "user not allowed" +// @Failure 404 {string} "record not found" +// @Failure 500 {string} "something went wrong" +// @Security AuthBearerAdmin +// @Router /admins/benefactors/{id}/status [put]. +func (h Handler) UpdateStatus(c echo.Context) error { + var req param.BenefactorUpdateStatusRequest + if bErr := c.Bind(&req); bErr != nil { + return echo.NewHTTPError(http.StatusBadRequest) + } + resp, sErr := h.benefactorSvc.UpdateStatus(c.Request().Context(), req) + if sErr != nil { + msg, code := httpmsg.Error(sErr) + if resp.FieldErrors != nil { + return c.JSON(code, echo.Map{ + "message": msg, + "errors": resp.FieldErrors, + }) + } + + return echo.NewHTTPError(code, msg) + } + + return c.JSON(http.StatusNoContent, nil) +} diff --git a/docker-compose.yaml b/docker-compose.yaml index 1cc1d13a..0d75fc25 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -33,7 +33,7 @@ services: MARIADB_PASSWORD: ${NIKI_STAGE_MARIADB_UR_PASSWORD} MARIADB_DATABASE: niki_db MARIADB_ROOT_PASSWORD: ${NIKI_STAGE_MARIADB_RT_PASSWORD} - ALLOW_EMPTY_PASSWORD: no + ALLOW_EMPTY_PASSWORD: "no" niki-redis: image: bitnami/redis:6.2 diff --git a/docs/docs.go b/docs/docs.go index 6d76c124..d98e121c 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -255,6 +255,150 @@ const docTemplate = `{ } } } + }, + "put": { + "security": [ + { + "AuthBearerAdmin": [] + } + ], + "description": "This endpoint update specific benefactor.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Admins Benefactors" + ], + "summary": "Update benefactor details by admin", + "parameters": [ + { + "type": "integer", + "description": "Benefactor ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Update Benefactor Body", + "name": "Request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/adminbenefactoreparam.BenefactorUpdateRequest" + } + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "description": "Bad request", + "schema": { + "type": "string" + } + }, + "401": { + "description": "invalid or expired jwt", + "schema": { + "type": "string" + } + }, + "403": { + "description": "user not allowed", + "schema": { + "type": "string" + } + }, + "404": { + "description": "record not found", + "schema": { + "type": "string" + } + }, + "500": { + "description": "something went wrong", + "schema": { + "type": "string" + } + } + } + } + }, + "/admins/benefactors/{id}/status": { + "put": { + "security": [ + { + "AuthBearerAdmin": [] + } + ], + "description": "This endpoint update status (active/inactive) benefactor.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Admins Benefactors" + ], + "summary": "Update benefactor status by admin", + "parameters": [ + { + "type": "integer", + "description": "Benefactor ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Update Benefactor Status", + "name": "Request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/adminbenefactoreparam.BenefactorUpdateStatusRequest" + } + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "description": "Bad request", + "schema": { + "type": "string" + } + }, + "401": { + "description": "invalid or expired jwt", + "schema": { + "type": "string" + } + }, + "403": { + "description": "user not allowed", + "schema": { + "type": "string" + } + }, + "404": { + "description": "record not found", + "schema": { + "type": "string" + } + }, + "500": { + "description": "something went wrong", + "schema": { + "type": "string" + } + } + } } }, "/admins/kindboxes": { @@ -3148,6 +3292,22 @@ const docTemplate = `{ } } }, + "adminbenefactoreparam.BenefactorUpdateRequest": { + "type": "object" + }, + "adminbenefactoreparam.BenefactorUpdateStatusRequest": { + "type": "object", + "properties": { + "status": { + "allOf": [ + { + "$ref": "#/definitions/entity.BenefactorStatus" + } + ], + "example": "inactive" + } + } + }, "adminbenefactoreparam.Data": { "type": "object", "properties": { @@ -4526,6 +4686,14 @@ const docTemplate = `{ } } }, + "param.Date": { + "type": "object", + "properties": { + "time.Time": { + "type": "string" + } + } + }, "param.PaginationResponse": { "type": "object", "properties": { diff --git a/docs/swagger.json b/docs/swagger.json index bf4fc117..428bc3c8 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -244,6 +244,150 @@ } } } + }, + "put": { + "security": [ + { + "AuthBearerAdmin": [] + } + ], + "description": "This endpoint update specific benefactor.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Admins Benefactors" + ], + "summary": "Update benefactor details by admin", + "parameters": [ + { + "type": "integer", + "description": "Benefactor ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Update Benefactor Body", + "name": "Request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/adminbenefactoreparam.BenefactorUpdateRequest" + } + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "description": "Bad request", + "schema": { + "type": "string" + } + }, + "401": { + "description": "invalid or expired jwt", + "schema": { + "type": "string" + } + }, + "403": { + "description": "user not allowed", + "schema": { + "type": "string" + } + }, + "404": { + "description": "record not found", + "schema": { + "type": "string" + } + }, + "500": { + "description": "something went wrong", + "schema": { + "type": "string" + } + } + } + } + }, + "/admins/benefactors/{id}/status": { + "put": { + "security": [ + { + "AuthBearerAdmin": [] + } + ], + "description": "This endpoint update status (active/inactive) benefactor.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Admins Benefactors" + ], + "summary": "Update benefactor status by admin", + "parameters": [ + { + "type": "integer", + "description": "Benefactor ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Update Benefactor Status", + "name": "Request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/adminbenefactoreparam.BenefactorUpdateStatusRequest" + } + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "description": "Bad request", + "schema": { + "type": "string" + } + }, + "401": { + "description": "invalid or expired jwt", + "schema": { + "type": "string" + } + }, + "403": { + "description": "user not allowed", + "schema": { + "type": "string" + } + }, + "404": { + "description": "record not found", + "schema": { + "type": "string" + } + }, + "500": { + "description": "something went wrong", + "schema": { + "type": "string" + } + } + } } }, "/admins/kindboxes": { @@ -3137,6 +3281,22 @@ } } }, + "adminbenefactoreparam.BenefactorUpdateRequest": { + "type": "object" + }, + "adminbenefactoreparam.BenefactorUpdateStatusRequest": { + "type": "object", + "properties": { + "status": { + "allOf": [ + { + "$ref": "#/definitions/entity.BenefactorStatus" + } + ], + "example": "inactive" + } + } + }, "adminbenefactoreparam.Data": { "type": "object", "properties": { @@ -4515,6 +4675,14 @@ } } }, + "param.Date": { + "type": "object", + "properties": { + "time.Time": { + "type": "string" + } + } + }, "param.PaginationResponse": { "type": "object", "properties": { diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 6ccdf047..99016405 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -157,6 +157,15 @@ definitions: pagination: $ref: '#/definitions/param.PaginationResponse' type: object + adminbenefactoreparam.BenefactorUpdateRequest: + type: object + adminbenefactoreparam.BenefactorUpdateStatusRequest: + properties: + status: + allOf: + - $ref: '#/definitions/entity.BenefactorStatus' + example: inactive + type: object adminbenefactoreparam.Data: properties: birth_date: @@ -1069,6 +1078,11 @@ definitions: message: type: string type: object + param.Date: + properties: + time.Time: + type: string + type: object param.PaginationResponse: properties: page_number: @@ -1242,6 +1256,99 @@ paths: summary: Get benefactor details by id tags: - Admins Benefactors + put: + consumes: + - application/json + description: This endpoint update specific benefactor. + parameters: + - description: Benefactor ID + in: path + name: id + required: true + type: integer + - description: Update Benefactor Body + in: body + name: Request + required: true + schema: + $ref: '#/definitions/adminbenefactoreparam.BenefactorUpdateRequest' + produces: + - application/json + responses: + "204": + description: No Content + "400": + description: Bad request + schema: + type: string + "401": + description: invalid or expired jwt + schema: + type: string + "403": + description: user not allowed + schema: + type: string + "404": + description: record not found + schema: + type: string + "500": + description: something went wrong + schema: + type: string + security: + - AuthBearerAdmin: [] + summary: Update benefactor details by admin + tags: + - Admins Benefactors + /admins/benefactors/{id}/status: + put: + consumes: + - application/json + description: This endpoint update status (active/inactive) benefactor. + parameters: + - description: Benefactor ID + in: path + name: id + required: true + type: integer + - description: Update Benefactor Status + in: body + name: Request + required: true + schema: + $ref: '#/definitions/adminbenefactoreparam.BenefactorUpdateStatusRequest' + produces: + - application/json + responses: + "204": + description: No Content + "400": + description: Bad request + schema: + type: string + "401": + description: invalid or expired jwt + schema: + type: string + "403": + description: user not allowed + schema: + type: string + "404": + description: record not found + schema: + type: string + "500": + description: something went wrong + schema: + type: string + security: + - AuthBearerAdmin: [] + summary: Update benefactor status by admin + tags: + - Admins Benefactors /admins/kindboxes: get: consumes: diff --git a/entity/admin_permission.go b/entity/admin_permission.go index 3fddee93..2b740275 100644 --- a/entity/admin_permission.go +++ b/entity/admin_permission.go @@ -23,5 +23,7 @@ const ( AdminKindBoxEnumeratePermission = AdminPermission("kindbox-enumerate") AdminKindBoxUpdatePermission = AdminPermission("kindbox-update") AdminBenefactorGetPermission = AdminPermission("benefactor-get") + AdminBenefactorUpdatePermission = AdminPermission("benefactor-update") + AdminBenefactorUpdateStatusPermission = AdminPermission("benefactor-update-status") AdminReferTimeGetAllPermission = AdminPermission("refertime-getall") ) diff --git a/param/admin/benefactor/update.go b/param/admin/benefactor/update.go new file mode 100644 index 00000000..ddeedf09 --- /dev/null +++ b/param/admin/benefactor/update.go @@ -0,0 +1,16 @@ +package adminbenefactoreparam + +import ( + "git.gocasts.ir/ebhomengo/niki/param" +) + +type BenefactorUpdateRequest struct { + ID uint `json:"-" param:"id" example:"1"` + FirstName string `json:"first_name" example:"name"` + LastName string `json:"last_name" example:"family"` + BirthDate param.Date `json:"birth_date" example:"2000-01-01"` +} + +type BenefactorUpdateResponse struct { + FieldErrors map[string]string `json:"field_errors,omitempty"` +} diff --git a/param/admin/benefactor/update_status.go b/param/admin/benefactor/update_status.go new file mode 100644 index 00000000..d71284a8 --- /dev/null +++ b/param/admin/benefactor/update_status.go @@ -0,0 +1,12 @@ +package adminbenefactoreparam + +import "git.gocasts.ir/ebhomengo/niki/entity" + +type BenefactorUpdateStatusRequest struct { + ID uint `json:"-" param:"id" example:"1"` + Status entity.BenefactorStatus `json:"status" example:"inactive"` +} + +type BenefactorUpdateStatusResponse struct { + FieldErrors map[string]string `json:"field_errors,omitempty"` +} diff --git a/param/date.go b/param/date.go new file mode 100644 index 00000000..1791460e --- /dev/null +++ b/param/date.go @@ -0,0 +1,29 @@ +package param + +import ( + "fmt" + "strings" + "time" +) + +type Date struct { + time.Time +} + +func (t Date) MarshalJSON() ([]byte, error) { + date := t.Time.Format("2006-01-02") + fmt.Println(date) + date = fmt.Sprintf(`"%s"`, date) + return []byte(date), nil +} + +func (t *Date) UnmarshalJSON(b []byte) (err error) { + s := strings.Trim(string(b), "\"") + + date, err := time.Parse("2006-01-02", s) + if err != nil { + return err + } + t.Time = date + return +} diff --git a/pkg/err_msg/message.go b/pkg/err_msg/message.go index 17a4773e..868cb462 100644 --- a/pkg/err_msg/message.go +++ b/pkg/err_msg/message.go @@ -39,4 +39,5 @@ const ( ErrorMsgInvalidSerialNumberRange = "invalid serial number range" ErrorMsgInvalidOrExpiredJwt = "invalid or expired jwt" ErrorMsgInvalidRefreshToken = "invalid refresh token" + ErrorMsgInvalidBenefactorStatus = "invalid benefactor status" ) diff --git a/repository/mysql/benefactor/update.go b/repository/mysql/benefactor/update.go new file mode 100644 index 00000000..14269acd --- /dev/null +++ b/repository/mysql/benefactor/update.go @@ -0,0 +1,33 @@ +package mysqlbenefactor + +import ( + "context" + + "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" +) + +func (d *DB) UpdateBenefactor(ctx context.Context, benefactor entity.Benefactor) error { + const op = "mysqlbenefactor.UpdateBenefactor" + + query := `UPDATE benefactors + SET first_name = ?, last_name = ?, birth_date = ? + WHERE id = ?` + //nolint + stmt, err := d.conn.PrepareStatement(ctx, mysql.StatementKeyBenefactorUpdate, query) + if err != nil { + return richerror.New(op).WithErr(err). + WithMessage(errmsg.ErrorMsgCantPrepareStatement).WithKind(richerror.KindUnexpected) + } + _, uErr := stmt.ExecContext(ctx, benefactor.FirstName, + benefactor.LastName, benefactor.BirthDate, benefactor.ID) + + if uErr != nil { + return richerror.New(op).WithErr(uErr).WithMessage(errmsg.ErrorMsgCantUpdateRecord). + WithKind(richerror.KindUnexpected) + } + + return nil +} diff --git a/repository/mysql/benefactor/update_status.go b/repository/mysql/benefactor/update_status.go new file mode 100644 index 00000000..4db7955d --- /dev/null +++ b/repository/mysql/benefactor/update_status.go @@ -0,0 +1,30 @@ +package mysqlbenefactor + +import ( + "context" + + "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" +) + +func (d *DB) UpdateStatusBenefactor(ctx context.Context, benefactor entity.Benefactor, status entity.BenefactorStatus) error { + const op = "mysqlbenefactor.UpdateStatusBenefactor" + + query := `UPDATE benefactors SET status = ? WHERE id = ?` + //nolint + stmt, err := d.conn.PrepareStatement(ctx, mysql.StatementKeyBenefactorUpdateStatus, query) + if err != nil { + return richerror.New(op).WithErr(err). + WithMessage(errmsg.ErrorMsgCantPrepareStatement).WithKind(richerror.KindUnexpected) + } + _, uErr := stmt.ExecContext(ctx, status, benefactor.ID) + + if uErr != nil { + return richerror.New(op).WithErr(uErr).WithMessage(errmsg.ErrorMsgCantUpdateRecord). + WithKind(richerror.KindUnexpected) + } + + return nil +} diff --git a/repository/mysql/migration/1730029129_add_update_benefactor_access.sql b/repository/mysql/migration/1730029129_add_update_benefactor_access.sql new file mode 100644 index 00000000..9ea7d774 --- /dev/null +++ b/repository/mysql/migration/1730029129_add_update_benefactor_access.sql @@ -0,0 +1,36 @@ +-- +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', + 'kindbox-get', + 'kindboxreq-add', + 'kindbox-assign_receiver_agent', + 'kindbox-getall', + 'kindboxreq-update', + 'kindboxreq-get', + 'kindbox-get_awaiting_return', + 'kindbox-return', + 'kindbox-enumerate', + 'kindbox-update', + 'benefactor-getall', + 'benefactor-get', + 'benefactor-update', + 'benefactor-update-status' + ) NOT NULL; + +INSERT INTO `admin_access_controls` (`actor_id`, `actor_type`, `permission`) +VALUES (1, 'role', 'benefactor-update'), +VALUES (2, 'role', 'benefactor-update'), +VALUES (1, 'role', 'benefactor-update-status'), +VALUES (2, 'role', 'benefactor-update-status'); + +-- +migrate Down +DELETE +FROM `admin_access_controls`; \ No newline at end of file diff --git a/repository/mysql/prepared_statement.go b/repository/mysql/prepared_statement.go index 7e954140..80c907d3 100644 --- a/repository/mysql/prepared_statement.go +++ b/repository/mysql/prepared_statement.go @@ -46,4 +46,6 @@ const ( StatementKeyKindBoxUpdate StatementKeyReferTimeGetByID StatementKeyReferTimeGetAll + StatementKeyBenefactorUpdate + StatementKeyBenefactorUpdateStatus ) diff --git a/service/admin/address/get_all.go b/service/admin/address/get_all.go index 7e220c3d..4d5d0007 100644 --- a/service/admin/address/get_all.go +++ b/service/admin/address/get_all.go @@ -2,6 +2,7 @@ package adminaddressservice import ( "context" + param "git.gocasts.ir/ebhomengo/niki/param/admin/address" richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error" ) diff --git a/service/admin/benefactor/service.go b/service/admin/benefactor/service.go index 8d1552ca..61e2eb9e 100644 --- a/service/admin/benefactor/service.go +++ b/service/admin/benefactor/service.go @@ -12,6 +12,8 @@ import ( type Repository interface { IsExistBenefactorByID(ctx context.Context, id uint) (bool, error) GetByID(ctx context.Context, id uint) (entity.Benefactor, error) + UpdateBenefactor(ctx context.Context, benefactor entity.Benefactor) error + UpdateStatusBenefactor(ctx context.Context, benefactor entity.Benefactor, status entity.BenefactorStatus) error GetAllBenefactor(ctx context.Context, filter param.FilterRequest, pagination param.PaginationRequest, sort param.SortRequest, searchParams *param.QuerySearch) ([]entity.Benefactor, uint, error) } type AddressSvc interface { diff --git a/service/admin/benefactor/update.go b/service/admin/benefactor/update.go new file mode 100644 index 00000000..b933afc8 --- /dev/null +++ b/service/admin/benefactor/update.go @@ -0,0 +1,31 @@ +package adminbenefactorservice + +import ( + "context" + + param "git.gocasts.ir/ebhomengo/niki/param/admin/benefactor" + richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error" +) + +func (s Service) Update(ctx context.Context, req param.BenefactorUpdateRequest) (param.BenefactorUpdateResponse, error) { + const op = "adminbenefactorservice.Update" + + if fieldErrors, vErr := s.vld.ValidateUpdateRequest(ctx, req); vErr != nil { + return param.BenefactorUpdateResponse{FieldErrors: fieldErrors}, richerror.New(op).WithErr(vErr) + } + + benefactor, err := s.repo.GetByID(ctx, req.ID) + if err != nil { + return param.BenefactorUpdateResponse{}, richerror.New(op).WithErr(err) + } + + benefactor.FirstName = req.FirstName + benefactor.LastName = req.LastName + benefactor.BirthDate = req.BirthDate.Time + + if uErr := s.repo.UpdateBenefactor(ctx, benefactor); uErr != nil { + return param.BenefactorUpdateResponse{}, richerror.New(op).WithErr(uErr) + } + + return param.BenefactorUpdateResponse{}, nil +} diff --git a/service/admin/benefactor/update_status.go b/service/admin/benefactor/update_status.go new file mode 100644 index 00000000..852ee5f6 --- /dev/null +++ b/service/admin/benefactor/update_status.go @@ -0,0 +1,27 @@ +package adminbenefactorservice + +import ( + "context" + + param "git.gocasts.ir/ebhomengo/niki/param/admin/benefactor" + richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error" +) + +func (s Service) UpdateStatus(ctx context.Context, req param.BenefactorUpdateStatusRequest) (param.BenefactorUpdateStatusResponse, error) { + const op = "adminbenefactorservice.UpdateStatus" + + if fieldErrors, vErr := s.vld.ValidateUpdateStatusRequest(ctx, req); vErr != nil { + return param.BenefactorUpdateStatusResponse{FieldErrors: fieldErrors}, richerror.New(op).WithErr(vErr) + } + + benefactor, err := s.repo.GetByID(ctx, req.ID) + if err != nil { + return param.BenefactorUpdateStatusResponse{}, richerror.New(op).WithErr(err) + } + + if uErr := s.repo.UpdateStatusBenefactor(ctx, benefactor, req.Status); uErr != nil { + return param.BenefactorUpdateStatusResponse{}, richerror.New(op).WithErr(uErr) + } + + return param.BenefactorUpdateStatusResponse{}, nil +} diff --git a/service/service.go b/service/service.go index 5ed3fe2c..a1698664 100644 --- a/service/service.go +++ b/service/service.go @@ -81,7 +81,7 @@ func New(cfg config.Config, db *mysql.DB, rds *redis.Adapter, smsAdapter smscont AdminReferTimeVld = adminrefertimevalidator.New() AdminReferTimeSvc = adminrefertimeservice.New(referTimeRepo, AdminReferTimeVld) AdminAddressSvc = adminaddressservice.New(addressRepo) - AdminBenefactorVld = adminbenefactorvalidator.New() + AdminBenefactorVld = adminbenefactorvalidator.New(benefactorRepo) AdminBenefactorSvc = adminbenefactorservice.New(benefactorRepo, AdminAddressSvc, AdminBenefactorVld) AdminAgentSvc = adminagentservice.New(agentRepo) diff --git a/validator/admin/benefactor/update.go b/validator/admin/benefactor/update.go new file mode 100644 index 00000000..55b16543 --- /dev/null +++ b/validator/admin/benefactor/update.go @@ -0,0 +1,46 @@ +package adminbenefactorvalidator + +import ( + "context" + "errors" + + param "git.gocasts.ir/ebhomengo/niki/param/admin/benefactor" + 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) ValidateUpdateRequest(ctx context.Context, req param.BenefactorUpdateRequest) (map[string]string, error) { + const op = "adminbenefactorvalidator.ValidateUpdateRequest" + + if err := validation.ValidateStruct(&req, + validation.Field(&req.ID, + validation.Required, + validation.By(v.doesBenefactorExist(ctx))), + validation.Field(&req.FirstName, + validation.Length(minLengthFirstName, maxLengthFirstName)), + validation.Field(&req.LastName, + validation.Length(minLengthLastName, maxLengthLastName)), + validation.Field(&req.BirthDate, + validation.Required, + validation.By(v.isDateValid), + ), + ); err != nil { + fieldErrors := make(map[string]string) + + vErr := validation.Errors{} + if errors.As(err, &vErr) { + for key, value := range vErr { + 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 nil, nil +} diff --git a/validator/admin/benefactor/update_status.go b/validator/admin/benefactor/update_status.go new file mode 100644 index 00000000..af25fc00 --- /dev/null +++ b/validator/admin/benefactor/update_status.go @@ -0,0 +1,40 @@ +package adminbenefactorvalidator + +import ( + "context" + "errors" + + param "git.gocasts.ir/ebhomengo/niki/param/admin/benefactor" + 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) ValidateUpdateStatusRequest(ctx context.Context, req param.BenefactorUpdateStatusRequest) (map[string]string, error) { + const op = "adminbenefactorvalidator.ValidateUpdateStatusRequest" + + if err := validation.ValidateStruct(&req, + validation.Field(&req.ID, + validation.Required, + validation.By(v.doesBenefactorExist(ctx))), + validation.Field(&req.Status, + validation.By(v.doesBenefactorStatusExist)), + ); err != nil { + fieldErrors := make(map[string]string) + + vErr := validation.Errors{} + if errors.As(err, &vErr) { + for key, value := range vErr { + 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 nil, nil +} diff --git a/validator/admin/benefactor/validator.go b/validator/admin/benefactor/validator.go index ba44a5ca..2c94b1cd 100644 --- a/validator/admin/benefactor/validator.go +++ b/validator/admin/benefactor/validator.go @@ -1,22 +1,36 @@ package adminbenefactorvalidator import ( + "context" + "errors" "fmt" "slices" + "time" + "git.gocasts.ir/ebhomengo/niki/entity" params "git.gocasts.ir/ebhomengo/niki/param" errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg" validation "github.com/go-ozzo/ozzo-validation/v4" ) const ( + minLengthFirstName = 3 + maxLengthFirstName = 40 + minLengthLastName = 3 + maxLengthLastName = 40 MaxLengthQuerySearch = 32 ) -type Validator struct{} +type Repository interface { + IsExistBenefactorByID(ctx context.Context, id uint) (bool, error) +} -func New() Validator { - return Validator{} +type Validator struct { + repo Repository +} + +func New(repo Repository) Validator { + return Validator{repo: repo} } func (v Validator) AreSortFieldsValid(validSortFields []string) validation.RuleFunc { @@ -55,6 +69,25 @@ func (v Validator) AreFilterFieldsValid(validFilters []string) validation.RuleFu } } +func (v Validator) doesBenefactorExist(ctx context.Context) validation.RuleFunc { + return func(value interface{}) error { + benefactor, ok := value.(uint) + if !ok { + return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong) + } + if isExist, err := v.repo.IsExistBenefactorByID(ctx, benefactor); !isExist || err != nil { + if err != nil { + return err + } + if !isExist { + return errors.New("benefactor is not exist") + } + } + + return nil + } +} + func (v Validator) AreSearchValid() validation.RuleFunc { return func(value interface{}) error { search, ok := value.(params.SearchRequest) @@ -63,8 +96,34 @@ func (v Validator) AreSearchValid() validation.RuleFunc { } if len(search.Query) > MaxLengthQuerySearch { return fmt.Errorf(errmsg.ErrorMsgInvalidInput) + } return nil } } + +func (v Validator) isDateValid(value interface{}) error { + date, ok := value.(params.Date) + if !ok { + return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong) + } + + if date.After(time.Now()) { + return fmt.Errorf(errmsg.ErrorMsgInvalidInput) + } + + return nil +} + +func (v Validator) doesBenefactorStatusExist(value interface{}) error { + BenefactorStatus, ok := value.(entity.BenefactorStatus) + if !ok { + return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong) + } + if !BenefactorStatus.IsValid() { + return fmt.Errorf(errmsg.ErrorMsgInvalidBenefactorStatus) + } + + return nil +}