diff --git a/delivery/http_server/agent/kind_box/return.go b/delivery/http_server/agent/kind_box/return.go new file mode 100644 index 0000000..746227f --- /dev/null +++ b/delivery/http_server/agent/kind_box/return.go @@ -0,0 +1,53 @@ +package agentkindboxhandler + +import ( + param "git.gocasts.ir/ebhomengo/niki/param/agent/kind_box" + "git.gocasts.ir/ebhomengo/niki/pkg/claim" + httpmsg "git.gocasts.ir/ebhomengo/niki/pkg/http_msg" + echo "github.com/labstack/echo/v4" + "net/http" +) + +// Return godoc +// @Summary Return KindBox from benefactor by agent +// @Tags KindBox +// @Accept json +// @Produce json +// @Param id path int true "KindBox ID" +// @Param Request body param.ReturnKindBoxRequest true "Return KindBox Request Body" +// @Success 204 +// @Failure 400 {string} "Bad Request" +// @Failure 401 {string} "invalid or expired jwt" +// @Failure 403 {string} "user not allowed" +// @Failure 422 {object} httpmsg.ErrorResponse +// @Failure 500 {string} "something went wrong" +// @Security AuthBearerAdmin +// @Router /agents/kindboxes/return/{id} [patch]. +func (h Handler) Return(c echo.Context) error { + var req param.ReturnKindBoxRequest + if err := c.Bind(&req); err != nil { + return echo.NewHTTPError(http.StatusBadRequest) + } + + claims := claim.GetClaimsFromEchoContext(c) + req.AgentID = claims.UserID + + if fieldErrors, err := h.agentKindBoxVld.ValidateReturn(req); err != nil { + msg, code := httpmsg.Error(err) + + return c.JSON(code, httpmsg.ErrorResponse{ + Message: msg, + Errors: fieldErrors, + }) + } + + err := h.agentKindBoxSvc.Return(c.Request().Context(), req) + + if err != nil { + msg, code := httpmsg.Error(err) + + return echo.NewHTTPError(code, msg) + } + + return c.NoContent(http.StatusNoContent) +} diff --git a/delivery/http_server/agent/kind_box/route.go b/delivery/http_server/agent/kind_box/route.go index baef1ef..be2ec49 100644 --- a/delivery/http_server/agent/kind_box/route.go +++ b/delivery/http_server/agent/kind_box/route.go @@ -13,4 +13,5 @@ func (h Handler) SetRoutes(e *echo.Echo) { r.GET("/:id", h.Get, middleware.AdminAuthorization(h.adminAuthorizeSvc, entity.AdminKindBoxGetAwaitingReturnPermission)) r.GET("", h.GetAll, middleware.AdminAuthorization(h.adminAuthorizeSvc, entity.AdminKindBoxGetAwaitingReturnPermission)) + r.PATCH("/return/:id", h.Return, middleware.AdminAuthorization(h.adminAuthorizeSvc, entity.AdminKindBoxReturnPermission)) } diff --git a/docs/docs.go b/docs/docs.go index 0cf5d62..8d91496 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -1537,6 +1537,78 @@ const docTemplate = `{ } } }, + "/agents/kindboxes/return/{id}": { + "patch": { + "security": [ + { + "AuthBearerAdmin": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "KindBox" + ], + "summary": "Return KindBox from benefactor by agent", + "parameters": [ + { + "type": "integer", + "description": "KindBox ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Return KindBox Request Body", + "name": "Request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/agentkindboxparam.ReturnKindBoxRequest" + } + } + ], + "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" + } + }, + "422": { + "description": "Unprocessable Entity", + "schema": { + "$ref": "#/definitions/httpmsg.ErrorResponse" + } + }, + "500": { + "description": "something went wrong", + "schema": { + "type": "string" + } + } + } + } + }, "/agents/kindboxes/{id}": { "get": { "security": [ @@ -1567,7 +1639,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/kind_box.GetKindBoxResponse" + "$ref": "#/definitions/agentkindboxparam.GetKindBoxResponse" } }, "400": { @@ -2930,6 +3002,70 @@ const docTemplate = `{ } } }, + "agentkindboxparam.GetKindBoxResponse": { + "type": "object", + "properties": { + "amount": { + "type": "integer" + }, + "benefactorID": { + "type": "integer" + }, + "deliverAddressID": { + "type": "integer" + }, + "deliverReferDate": { + "type": "string" + }, + "deliverReferTimeID": { + "type": "integer" + }, + "deliveredAt": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "kindBoxReqID": { + "type": "integer" + }, + "kindBoxType": { + "$ref": "#/definitions/entity.KindBoxType" + }, + "receiverAgentID": { + "type": "integer" + }, + "returnAddressID": { + "type": "integer" + }, + "returnReferDate": { + "type": "string" + }, + "returnReferTimeID": { + "type": "integer" + }, + "returnedAt": { + "type": "string" + }, + "senderAgentID": { + "type": "integer" + }, + "serialNumber": { + "type": "string" + }, + "status": { + "$ref": "#/definitions/entity.KindBoxStatus" + } + } + }, + "agentkindboxparam.ReturnKindBoxRequest": { + "type": "object", + "properties": { + "serial_number": { + "type": "string" + } + } + }, "benefactoreparam.BenefactroInfo": { "type": "object", "properties": { @@ -3446,62 +3582,6 @@ const docTemplate = `{ } } }, - "kind_box.GetKindBoxResponse": { - "type": "object", - "properties": { - "amount": { - "type": "integer" - }, - "benefactorID": { - "type": "integer" - }, - "deliverAddressID": { - "type": "integer" - }, - "deliverReferDate": { - "type": "string" - }, - "deliverReferTimeID": { - "type": "integer" - }, - "deliveredAt": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "kindBoxReqID": { - "type": "integer" - }, - "kindBoxType": { - "$ref": "#/definitions/entity.KindBoxType" - }, - "receiverAgentID": { - "type": "integer" - }, - "returnAddressID": { - "type": "integer" - }, - "returnReferDate": { - "type": "string" - }, - "returnReferTimeID": { - "type": "integer" - }, - "returnedAt": { - "type": "string" - }, - "senderAgentID": { - "type": "integer" - }, - "serialNumber": { - "type": "string" - }, - "status": { - "$ref": "#/definitions/entity.KindBoxStatus" - } - } - }, "param.PaginationResponse": { "type": "object", "properties": { diff --git a/docs/swagger.json b/docs/swagger.json index 2c42313..3ae5d09 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -1526,6 +1526,78 @@ } } }, + "/agents/kindboxes/return/{id}": { + "patch": { + "security": [ + { + "AuthBearerAdmin": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "KindBox" + ], + "summary": "Return KindBox from benefactor by agent", + "parameters": [ + { + "type": "integer", + "description": "KindBox ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Return KindBox Request Body", + "name": "Request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/agentkindboxparam.ReturnKindBoxRequest" + } + } + ], + "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" + } + }, + "422": { + "description": "Unprocessable Entity", + "schema": { + "$ref": "#/definitions/httpmsg.ErrorResponse" + } + }, + "500": { + "description": "something went wrong", + "schema": { + "type": "string" + } + } + } + } + }, "/agents/kindboxes/{id}": { "get": { "security": [ @@ -1556,7 +1628,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/kind_box.GetKindBoxResponse" + "$ref": "#/definitions/agentkindboxparam.GetKindBoxResponse" } }, "400": { @@ -2919,6 +2991,70 @@ } } }, + "agentkindboxparam.GetKindBoxResponse": { + "type": "object", + "properties": { + "amount": { + "type": "integer" + }, + "benefactorID": { + "type": "integer" + }, + "deliverAddressID": { + "type": "integer" + }, + "deliverReferDate": { + "type": "string" + }, + "deliverReferTimeID": { + "type": "integer" + }, + "deliveredAt": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "kindBoxReqID": { + "type": "integer" + }, + "kindBoxType": { + "$ref": "#/definitions/entity.KindBoxType" + }, + "receiverAgentID": { + "type": "integer" + }, + "returnAddressID": { + "type": "integer" + }, + "returnReferDate": { + "type": "string" + }, + "returnReferTimeID": { + "type": "integer" + }, + "returnedAt": { + "type": "string" + }, + "senderAgentID": { + "type": "integer" + }, + "serialNumber": { + "type": "string" + }, + "status": { + "$ref": "#/definitions/entity.KindBoxStatus" + } + } + }, + "agentkindboxparam.ReturnKindBoxRequest": { + "type": "object", + "properties": { + "serial_number": { + "type": "string" + } + } + }, "benefactoreparam.BenefactroInfo": { "type": "object", "properties": { @@ -3435,62 +3571,6 @@ } } }, - "kind_box.GetKindBoxResponse": { - "type": "object", - "properties": { - "amount": { - "type": "integer" - }, - "benefactorID": { - "type": "integer" - }, - "deliverAddressID": { - "type": "integer" - }, - "deliverReferDate": { - "type": "string" - }, - "deliverReferTimeID": { - "type": "integer" - }, - "deliveredAt": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "kindBoxReqID": { - "type": "integer" - }, - "kindBoxType": { - "$ref": "#/definitions/entity.KindBoxType" - }, - "receiverAgentID": { - "type": "integer" - }, - "returnAddressID": { - "type": "integer" - }, - "returnReferDate": { - "type": "string" - }, - "returnReferTimeID": { - "type": "integer" - }, - "returnedAt": { - "type": "string" - }, - "senderAgentID": { - "type": "integer" - }, - "serialNumber": { - "type": "string" - }, - "status": { - "$ref": "#/definitions/entity.KindBoxStatus" - } - } - }, "param.PaginationResponse": { "type": "object", "properties": { diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 188b0f3..dd5c482 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -447,6 +447,48 @@ definitions: pagination: $ref: '#/definitions/param.PaginationResponse' type: object + agentkindboxparam.GetKindBoxResponse: + properties: + amount: + type: integer + benefactorID: + type: integer + deliverAddressID: + type: integer + deliverReferDate: + type: string + deliverReferTimeID: + type: integer + deliveredAt: + type: string + id: + type: integer + kindBoxReqID: + type: integer + kindBoxType: + $ref: '#/definitions/entity.KindBoxType' + receiverAgentID: + type: integer + returnAddressID: + type: integer + returnReferDate: + type: string + returnReferTimeID: + type: integer + returnedAt: + type: string + senderAgentID: + type: integer + serialNumber: + type: string + status: + $ref: '#/definitions/entity.KindBoxStatus' + type: object + agentkindboxparam.ReturnKindBoxRequest: + properties: + serial_number: + type: string + type: object benefactoreparam.BenefactroInfo: properties: first_name: @@ -798,43 +840,6 @@ definitions: message: type: string type: object - kind_box.GetKindBoxResponse: - properties: - amount: - type: integer - benefactorID: - type: integer - deliverAddressID: - type: integer - deliverReferDate: - type: string - deliverReferTimeID: - type: integer - deliveredAt: - type: string - id: - type: integer - kindBoxReqID: - type: integer - kindBoxType: - $ref: '#/definitions/entity.KindBoxType' - receiverAgentID: - type: integer - returnAddressID: - type: integer - returnReferDate: - type: string - returnReferTimeID: - type: integer - returnedAt: - type: string - senderAgentID: - type: integer - serialNumber: - type: string - status: - $ref: '#/definitions/entity.KindBoxStatus' - type: object param.PaginationResponse: properties: page_number: @@ -1866,7 +1871,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/kind_box.GetKindBoxResponse' + $ref: '#/definitions/agentkindboxparam.GetKindBoxResponse' "400": description: Bad Request schema: @@ -1892,6 +1897,52 @@ paths: summary: Get a kind box that is awaiting return by agent tags: - KindBox + /agents/kindboxes/return/{id}: + patch: + consumes: + - application/json + parameters: + - description: KindBox ID + in: path + name: id + required: true + type: integer + - description: Return KindBox Request Body + in: body + name: Request + required: true + schema: + $ref: '#/definitions/agentkindboxparam.ReturnKindBoxRequest' + 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 + "422": + description: Unprocessable Entity + schema: + $ref: '#/definitions/httpmsg.ErrorResponse' + "500": + description: something went wrong + schema: + type: string + security: + - AuthBearerAdmin: [] + summary: Return KindBox from benefactor by agent + tags: + - KindBox /benefactor/kindboxes: get: consumes: diff --git a/entity/admin_permission.go b/entity/admin_permission.go index a3fae89..6b1b56a 100644 --- a/entity/admin_permission.go +++ b/entity/admin_permission.go @@ -18,4 +18,5 @@ const ( AdminKindBoxReqUpdatePermission = AdminPermission("kindboxreq-update") AdminKindBoxReqGetPermission = AdminPermission("kindboxreq-get") AdminKindBoxGetAwaitingReturnPermission = AdminPermission("kindbox-get_awaiting_return") + AdminKindBoxReturnPermission = AdminPermission("kindbox-return") ) diff --git a/param/agent/kind_box/return.go b/param/agent/kind_box/return.go new file mode 100644 index 0000000..0536fe3 --- /dev/null +++ b/param/agent/kind_box/return.go @@ -0,0 +1,7 @@ +package agentkindboxparam + +type ReturnKindBoxRequest struct { + KindBoxID uint `json:"-" param:"id"` + AgentID uint `json:"-"` + SerialNumber string `json:"serial_number"` +} diff --git a/repository/mysql/kind_box/return.go b/repository/mysql/kind_box/return.go new file mode 100644 index 0000000..546b811 --- /dev/null +++ b/repository/mysql/kind_box/return.go @@ -0,0 +1,29 @@ +package mysqlkindbox + +import ( + "context" + "git.gocasts.ir/ebhomengo/niki/entity" + "time" + + errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg" + richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error" +) + +func (d DB) ReturnKindBox(ctx context.Context, kindBoxID uint, serialNumber string) error { + const op = "mysqlkindbox.ReturnKindBox" + + query := `update kind_boxes set serial_number = ?, status = ?, returned_at = ? where id = ?` + stmt, err := d.conn.PrepareStatement(op, query) + if err != nil { + return richerror.New(op).WithErr(err). + WithMessage(errmsg.ErrorMsgCantPrepareStatement).WithKind(richerror.KindUnexpected) + } + + _, err = stmt.ExecContext(ctx, serialNumber, entity.KindBoxReturnedStatus.String(), time.Now(), kindBoxID) + if err != nil { + return richerror.New(op).WithErr(err). + WithMessage(errmsg.ErrorMsgSomethingWentWrong).WithKind(richerror.KindUnexpected) + } + + return nil +} diff --git a/repository/mysql/migration/1708712564_alter_admin_access_controls_table_permission_enum_field.sql b/repository/mysql/migration/1708712564_alter_admin_access_controls_table_permission_enum_field.sql index 14179c8..fc0e907 100644 --- a/repository/mysql/migration/1708712564_alter_admin_access_controls_table_permission_enum_field.sql +++ b/repository/mysql/migration/1708712564_alter_admin_access_controls_table_permission_enum_field.sql @@ -15,7 +15,8 @@ ALTER TABLE `admin_access_controls` MODIFY COLUMN `permission` 'kindbox-getall', 'kindboxreq-update', 'kindboxreq-get', - 'kindbox-get_awaiting_return' + 'kindbox-get_awaiting_return', + 'kindbox-return' ) NOT NULL; -- +migrate Down \ No newline at end of file diff --git a/repository/mysql/migration/1708712565_insert_admin_access_controls_table.sql b/repository/mysql/migration/1708712565_insert_admin_access_controls_table.sql index a158238..a4e3993 100644 --- a/repository/mysql/migration/1708712565_insert_admin_access_controls_table.sql +++ b/repository/mysql/migration/1708712565_insert_admin_access_controls_table.sql @@ -33,7 +33,9 @@ VALUES (DEFAULT, 1 , 'role','kindbox-getall'), (DEFAULT, 2 , 'role','kindbox-getall'), (DEFAULT, 1 , 'role','kindbox-get_awaiting_return'), - (DEFAULT, 3 , 'role','kindbox-get_awaiting_return'); + (DEFAULT, 3 , 'role','kindbox-get_awaiting_return'), + (DEFAULT, 1 , 'role','kindbox-return'), + (DEFAULT, 3 , 'role','kindbox-return'); diff --git a/service/agent/kind_box/return.go b/service/agent/kind_box/return.go new file mode 100644 index 0000000..b374a7f --- /dev/null +++ b/service/agent/kind_box/return.go @@ -0,0 +1,18 @@ +package agentkindboxservice + +import ( + "context" + param "git.gocasts.ir/ebhomengo/niki/param/agent/kind_box" + richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error" +) + +func (s Service) Return(ctx context.Context, req param.ReturnKindBoxRequest) error { + const op = "agentkindboxservice.Return" + + err := s.repo.ReturnKindBox(ctx, req.KindBoxID, req.SerialNumber) + if err != nil { + return richerror.New(op).WithErr(err) + } + + return nil +} diff --git a/service/agent/kind_box/service.go b/service/agent/kind_box/service.go index eb6b219..9e69a19 100644 --- a/service/agent/kind_box/service.go +++ b/service/agent/kind_box/service.go @@ -9,6 +9,7 @@ import ( type Repository interface { GetAwaitingReturnByAgent(ctx context.Context, kindBoxID uint, agentID uint) (entity.KindBox, error) GetAllKindBox(ctx context.Context, filter params.FilterRequest, pagination params.PaginationRequest, sort params.SortRequest) ([]entity.KindBox, uint, error) + ReturnKindBox(ctx context.Context, kindBoxID uint, serialNumber string) error } type Service struct { diff --git a/validator/agent/kind_box/return.go b/validator/agent/kind_box/return.go new file mode 100644 index 0000000..afc68e9 --- /dev/null +++ b/validator/agent/kind_box/return.go @@ -0,0 +1,38 @@ +package agentkindboxvalidator + +import ( + "errors" + param "git.gocasts.ir/ebhomengo/niki/param/agent/kind_box" + 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) ValidateReturn(req param.ReturnKindBoxRequest) (map[string]string, error) { + const op = "agentkindboxvalidator.ValidateReturn" + + // TODO: add regex for serial number + if err := validation.ValidateStruct(&req, + validation.Field(&req.KindBoxID, validation.Required, validation.By(v.doesKindBoxExistForAgent(req.AgentID))), + validation.Field(&req.SerialNumber, validation.Required), + ); 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 +}