diff --git a/delivery/http_server/benefactor/kind_box/get_all.go b/delivery/http_server/benefactor/kind_box/get_all.go index 3a47bdc..dca7da8 100644 --- a/delivery/http_server/benefactor/kind_box/get_all.go +++ b/delivery/http_server/benefactor/kind_box/get_all.go @@ -16,7 +16,7 @@ import ( // @Success 200 {object} param.KindBoxGetResponse // @Failure 400 {string} "Bad request" // @Security AuthBearerBenefactor -// @Router /benefactor/kindboxes/ [get] +// @Router /benefactor/kindboxes [get] func (h Handler) GetAll(c echo.Context) error { var req param.KindBoxGetAllRequest if bErr := c.Bind(&req); bErr != nil { diff --git a/delivery/http_server/benefactor/kind_box/register_emptying_request.go b/delivery/http_server/benefactor/kind_box/register_emptying_request.go new file mode 100644 index 0000000..ffff042 --- /dev/null +++ b/delivery/http_server/benefactor/kind_box/register_emptying_request.go @@ -0,0 +1,48 @@ +package benefactorkindboxhandler + +import ( + "net/http" + + param "git.gocasts.ir/ebhomengo/niki/param/benefactor/kind_box" + "git.gocasts.ir/ebhomengo/niki/pkg/claim" + httpmsg "git.gocasts.ir/ebhomengo/niki/pkg/http_msg" + "github.com/labstack/echo/v4" +) + +// RegisterEmptyingRequest godoc +// @Summary Register a new emptying request for a kind box by benefactor +// @Tags Benefactor +// @Accept json +// @Produce json +// @Param id path int true "KindBox ID" +// @Param Request body param.KindBoxRegisterEmptyingRequest true "Request body" +// @Success 204 {string} "No content" +// @Failure 400 {string} "Bad request" +// @Security AuthBearerBenefactor +// @Router /benefactor/kindboxes/{id}/emptying-requests [patch]. +func (h Handler) RegisterEmptyingRequest(c echo.Context) error { + var req param.KindBoxRegisterEmptyingRequest + if bErr := c.Bind(&req); bErr != nil { + return echo.NewHTTPError(http.StatusBadRequest) + } + + claims := claim.GetClaimsFromEchoContext(c) + req.BenefactorID = claims.UserID + + if fieldErrors, err := h.benefactorKindBoxVld.ValidateRegisterEmptyingRequest(req); err != nil { + msg, code := httpmsg.Error(err) + + return c.JSON(code, echo.Map{ + "message": msg, + "errors": fieldErrors, + }) + } + sErr := h.benefactorKindBoxSvc.RegisterEmptyingRequest(c.Request().Context(), req) + if sErr != nil { + msg, code := httpmsg.Error(sErr) + + return echo.NewHTTPError(code, msg) + } + + return c.JSON(http.StatusNoContent, nil) +} diff --git a/delivery/http_server/benefactor/kind_box/route.go b/delivery/http_server/benefactor/kind_box/route.go index f21eec6..958d5ac 100644 --- a/delivery/http_server/benefactor/kind_box/route.go +++ b/delivery/http_server/benefactor/kind_box/route.go @@ -1,12 +1,20 @@ package benefactorkindboxhandler import ( - echo "github.com/labstack/echo/v4" + "git.gocasts.ir/ebhomengo/niki/delivery/http_server/middleware" + "git.gocasts.ir/ebhomengo/niki/entity" + "github.com/labstack/echo/v4" ) func (h Handler) SetRoutes(e *echo.Echo) { r := e.Group("/benefactor/kindboxes") - r.GET("/:id", h.Get).Name = "benefactor-getkindboxbyid" - r.GET("/", h.GetAll).Name = "benefactor-getallkindbox" + r.Use( + middleware.Auth(h.authSvc, h.authConfig), + middleware.BenefactorAuthorization(entity.UserBenefactorRole), + ) + + r.GET("/:id", h.Get) + r.GET("", h.GetAll) + r.PATCH("/:id/emptying-requests", h.RegisterEmptyingRequest) } diff --git a/delivery/http_server/server.go b/delivery/http_server/server.go index 2a05a5e..c79cd31 100644 --- a/delivery/http_server/server.go +++ b/delivery/http_server/server.go @@ -7,6 +7,7 @@ import ( adminkindboxreqhandler "git.gocasts.ir/ebhomengo/niki/delivery/http_server/admin/kind_box_req" benefactoraddresshandler "git.gocasts.ir/ebhomengo/niki/delivery/http_server/benefactor/address" benefactorhandler "git.gocasts.ir/ebhomengo/niki/delivery/http_server/benefactor/benefactor" + benefactorkindboxhandler "git.gocasts.ir/ebhomengo/niki/delivery/http_server/benefactor/kind_box" benefactorkindboxreqhandler "git.gocasts.ir/ebhomengo/niki/delivery/http_server/benefactor/kind_box_req" "git.gocasts.ir/ebhomengo/niki/docs" adminservice "git.gocasts.ir/ebhomengo/niki/service/admin/admin" @@ -15,11 +16,13 @@ import ( authservice "git.gocasts.ir/ebhomengo/niki/service/auth" benefactoraddressservice "git.gocasts.ir/ebhomengo/niki/service/benefactor/address" benefactorservice "git.gocasts.ir/ebhomengo/niki/service/benefactor/benefactor" + benefactorkindboxservice "git.gocasts.ir/ebhomengo/niki/service/benefactor/kind_box" benefactorkindboxreqservice "git.gocasts.ir/ebhomengo/niki/service/benefactor/kind_box_req" adminvalidator "git.gocasts.ir/ebhomengo/niki/validator/admin/admin" adminkindboxreqvalidator "git.gocasts.ir/ebhomengo/niki/validator/admin/kind_box_req" benefactoraddressvalidator "git.gocasts.ir/ebhomengo/niki/validator/benefactor/address" benefactorvalidator "git.gocasts.ir/ebhomengo/niki/validator/benefactor/benefactor" + benefactorkindboxvalidator "git.gocasts.ir/ebhomengo/niki/validator/benefactor/kind_box" benefactorkindboxreqvalidator "git.gocasts.ir/ebhomengo/niki/validator/benefactor/kind_box_req" echo "github.com/labstack/echo/v4" middleware "github.com/labstack/echo/v4/middleware" @@ -32,6 +35,7 @@ type Server struct { benefactorHandler benefactorhandler.Handler benefactorKindBoxReqHandler benefactorkindboxreqhandler.Handler benefactorAddressHandler benefactoraddresshandler.Handler + benefactorKindBoxHandler benefactorkindboxhandler.Handler adminHandler adminhandler.Handler adminKindBoxReqHandler adminkindboxreqhandler.Handler } @@ -45,6 +49,8 @@ func New( benefactorKindBoxReqVld benefactorkindboxreqvalidator.Validator, benefactorAddressSvc benefactoraddressservice.Service, benefactorAddressVld benefactoraddressvalidator.Validator, + benefactorKindBoxSvc benefactorkindboxservice.Service, + benefactorKindBoxVld benefactorkindboxvalidator.Validator, adminSvc adminservice.Service, adminVld adminvalidator.Validator, adminAuthSvc authservice.Service, @@ -58,6 +64,7 @@ func New( benefactorHandler: benefactorhandler.New(cfg.Auth, benefactorAuthSvc, benefactorSvc, benefactorVld), benefactorKindBoxReqHandler: benefactorkindboxreqhandler.New(cfg.Auth, benefactorAuthSvc, benefactorKindBoxReqSvc, benefactorKindBoxReqVld), benefactorAddressHandler: benefactoraddresshandler.New(cfg.Auth, benefactorAuthSvc, benefactorAddressSvc, benefactorAddressVld), + benefactorKindBoxHandler: benefactorkindboxhandler.New(cfg.Auth, benefactorAuthSvc, benefactorKindBoxSvc, benefactorKindBoxVld), adminHandler: adminhandler.New(cfg.AdminAuth, adminAuthSvc, adminSvc, adminVld, adminAuthorizeSvc), adminKindBoxReqHandler: adminkindboxreqhandler.New(cfg.Auth, adminAuthSvc, adminKinBoxReqSvc, adminKinBoxReqVld, adminAuthorizeSvc), } @@ -73,6 +80,7 @@ func (s Server) Serve() { s.benefactorHandler.SetRoutes(s.Router) s.benefactorKindBoxReqHandler.SetRoutes(s.Router) s.benefactorAddressHandler.SetRoutes(s.Router) + s.benefactorKindBoxHandler.SetRoutes(s.Router) s.adminHandler.SetRoutes(s.Router) s.adminKindBoxReqHandler.SetRoutes(s.Router) // Start server diff --git a/docs/docs.go b/docs/docs.go index a20fb41..780f266 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -796,7 +796,7 @@ const docTemplate = `{ } } }, - "/benefactor/kindboxes/": { + "/benefactor/kindboxes": { "get": { "security": [ { @@ -872,6 +872,57 @@ const docTemplate = `{ } } }, + "/benefactor/kindboxes/{id}/emptying-requests": { + "patch": { + "security": [ + { + "AuthBearerBenefactor": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Benefactor" + ], + "summary": "Register a new emptying request for a kind box by benefactor", + "parameters": [ + { + "type": "integer", + "description": "KindBox ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Request body", + "name": "Request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/benefactorkindboxparam.KindBoxRegisterEmptyingRequest" + } + } + ], + "responses": { + "204": { + "description": "No content", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Bad request", + "schema": { + "type": "string" + } + } + } + } + }, "/benefactor/kindboxreqs/": { "post": { "security": [ @@ -1648,6 +1699,9 @@ const docTemplate = `{ "returnReferDate": { "type": "string" }, + "returnReferTimeID": { + "type": "integer" + }, "returnedAt": { "type": "string" }, @@ -1665,6 +1719,23 @@ const docTemplate = `{ } } }, + "benefactorkindboxparam.KindBoxRegisterEmptyingRequest": { + "type": "object", + "properties": { + "return_address_id": { + "type": "integer", + "example": 1 + }, + "return_refer_date": { + "type": "string", + "example": "2025-01-02T15:04:05Z" + }, + "return_refer_time_id": { + "type": "integer", + "example": 1 + } + } + }, "benefactorkindboxreqparam.KindBoxReqAddRequest": { "type": "object", "properties": { diff --git a/docs/swagger.json b/docs/swagger.json index a0d8720..e095c3d 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -785,7 +785,7 @@ } } }, - "/benefactor/kindboxes/": { + "/benefactor/kindboxes": { "get": { "security": [ { @@ -861,6 +861,57 @@ } } }, + "/benefactor/kindboxes/{id}/emptying-requests": { + "patch": { + "security": [ + { + "AuthBearerBenefactor": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Benefactor" + ], + "summary": "Register a new emptying request for a kind box by benefactor", + "parameters": [ + { + "type": "integer", + "description": "KindBox ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Request body", + "name": "Request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/benefactorkindboxparam.KindBoxRegisterEmptyingRequest" + } + } + ], + "responses": { + "204": { + "description": "No content", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Bad request", + "schema": { + "type": "string" + } + } + } + } + }, "/benefactor/kindboxreqs/": { "post": { "security": [ @@ -1637,6 +1688,9 @@ "returnReferDate": { "type": "string" }, + "returnReferTimeID": { + "type": "integer" + }, "returnedAt": { "type": "string" }, @@ -1654,6 +1708,23 @@ } } }, + "benefactorkindboxparam.KindBoxRegisterEmptyingRequest": { + "type": "object", + "properties": { + "return_address_id": { + "type": "integer", + "example": 1 + }, + "return_refer_date": { + "type": "string", + "example": "2025-01-02T15:04:05Z" + }, + "return_refer_time_id": { + "type": "integer", + "example": 1 + } + } + }, "benefactorkindboxreqparam.KindBoxReqAddRequest": { "type": "object", "properties": { diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 70d2a08..b8a344d 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -372,6 +372,8 @@ definitions: type: integer returnReferDate: type: string + returnReferTimeID: + type: integer returnedAt: type: string senderAgentID: @@ -383,6 +385,18 @@ definitions: type: $ref: '#/definitions/entity.KindBoxType' type: object + benefactorkindboxparam.KindBoxRegisterEmptyingRequest: + properties: + return_address_id: + example: 1 + type: integer + return_refer_date: + example: "2025-01-02T15:04:05Z" + type: string + return_refer_time_id: + example: 1 + type: integer + type: object benefactorkindboxreqparam.KindBoxReqAddRequest: properties: benefactor_id: @@ -1080,7 +1094,7 @@ paths: summary: Register an admin by super-admin tags: - Admin - /benefactor/kindboxes/: + /benefactor/kindboxes: get: consumes: - application/json @@ -1128,6 +1142,38 @@ paths: summary: Get a specific kind box for a benefactor tags: - KindBox + /benefactor/kindboxes/{id}/emptying-requests: + patch: + consumes: + - application/json + parameters: + - description: KindBox ID + in: path + name: id + required: true + type: integer + - description: Request body + in: body + name: Request + required: true + schema: + $ref: '#/definitions/benefactorkindboxparam.KindBoxRegisterEmptyingRequest' + produces: + - application/json + responses: + "204": + description: No content + schema: + type: string + "400": + description: Bad request + schema: + type: string + security: + - AuthBearerBenefactor: [] + summary: Register a new emptying request for a kind box by benefactor + tags: + - Benefactor /benefactor/kindboxreqs/: post: consumes: diff --git a/entity/kind_box.go b/entity/kind_box.go index cfb2957..397c1df 100644 --- a/entity/kind_box.go +++ b/entity/kind_box.go @@ -3,19 +3,20 @@ package entity import "time" type KindBox struct { - ID uint - KindBoxReqID uint - BenefactorID uint - Type KindBoxType - Amount uint - SerialNumber string - Status KindBoxStatus - DeliverReferDate time.Time - DeliverAddressID uint - SenderAgentID uint - DeliveredAt time.Time - ReturnReferDate time.Time - ReturnAddressID uint - ReceiverAgentID uint - ReturnedAt time.Time + ID uint + KindBoxReqID uint + BenefactorID uint + Type KindBoxType + Amount uint + SerialNumber string + Status KindBoxStatus + DeliverReferDate time.Time + DeliverAddressID uint + SenderAgentID uint + DeliveredAt time.Time + ReturnReferTimeID uint + ReturnReferDate time.Time + ReturnAddressID uint + ReceiverAgentID uint + ReturnedAt time.Time } diff --git a/internal/initial/service.go b/internal/initial/service.go index 3a7d6a4..6cf352a 100644 --- a/internal/initial/service.go +++ b/internal/initial/service.go @@ -8,6 +8,7 @@ import ( "git.gocasts.ir/ebhomengo/niki/repository/mysql" mysqladdress "git.gocasts.ir/ebhomengo/niki/repository/mysql/address" mysqlbenefactor "git.gocasts.ir/ebhomengo/niki/repository/mysql/benefactor" + mysqlkindbox "git.gocasts.ir/ebhomengo/niki/repository/mysql/kind_box" 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" @@ -16,6 +17,7 @@ import ( adminrefertimeservice "git.gocasts.ir/ebhomengo/niki/service/admin/refer_time" benefactoraddressservice "git.gocasts.ir/ebhomengo/niki/service/benefactor/address" benefactorservice "git.gocasts.ir/ebhomengo/niki/service/benefactor/benefactor" + benefactorkindboxservice "git.gocasts.ir/ebhomengo/niki/service/benefactor/kind_box" benefactorkindboxreqservice "git.gocasts.ir/ebhomengo/niki/service/benefactor/kind_box_req" ) @@ -23,6 +25,7 @@ type Services struct { BenefactorSvc benefactorservice.Service BenefactorKindBoxReqSvc benefactorkindboxreqservice.Service BenefactorAddressSvc benefactoraddressservice.Service + BenefactorKindBoxSvc benefactorkindboxservice.Service AdminKindBoxSvc adminkindboxservice.Service AdminSvc adminservice.Service AdminKindBoxReqSvc adminkindboxreqservice.Service @@ -62,8 +65,13 @@ func InitAdminKindBoxService(db *mysql.DB) adminkindboxservice.Service { func InitAdminKindBoxReqService(db *mysql.DB) adminkindboxreqservice.Service { return adminkindboxreqservice.New(InitBenefactorKindBoxReqDB(db), InitAdminKindBoxService(db)) } + func InitAdminReferTimeService(db *mysql.DB) adminrefertimeservice.Service { return adminrefertimeservice.New( InitAdminReferTimeDB(db), ) } + +func InitBenefactorKindBoxService(db *mysql.DB) benefactorkindboxservice.Service { + return benefactorkindboxservice.New(mysqlkindbox.New(db)) +} diff --git a/internal/initial/validator.go b/internal/initial/validator.go index bc898e4..b797f60 100644 --- a/internal/initial/validator.go +++ b/internal/initial/validator.go @@ -8,6 +8,7 @@ import ( adminkindboxreqvalidator "git.gocasts.ir/ebhomengo/niki/validator/admin/kind_box_req" benefactoraddressvalidator "git.gocasts.ir/ebhomengo/niki/validator/benefactor/address" benefactorvalidator "git.gocasts.ir/ebhomengo/niki/validator/benefactor/benefactor" + benefactorkindboxvalidator "git.gocasts.ir/ebhomengo/niki/validator/benefactor/kind_box" benefactorkindboxreqvalidator "git.gocasts.ir/ebhomengo/niki/validator/benefactor/kind_box_req" ) @@ -15,6 +16,7 @@ type Validators struct { BenefactorVld benefactorvalidator.Validator BenefactorKindBoxReqVld benefactorkindboxreqvalidator.Validator BenefactorAddressVld benefactoraddressvalidator.Validator + BenefactorKindBoxVld benefactorkindboxvalidator.Validator AdminKindBoxReqVld adminkindboxreqvalidator.Validator AdminVld adminvalidator.Validator } @@ -46,3 +48,12 @@ func InitBenefactorAddressValidator(cfg config.Config, redisAdapter redis.Adapte InitBenefactorAddressDB(db), ) } + +func InitBenefactorKindBoxValidator(cfg config.Config, redisAdapter redis.Adapter, db *mysql.DB) benefactorkindboxvalidator.Validator { + return benefactorkindboxvalidator.New( + InitKindBoxRepo(db), + InitBenefactorService(cfg, redisAdapter, db), + InitBenefactorAddressService(db), + InitAdminReferTimeService(db), + ) +} diff --git a/main.go b/main.go index be5e53a..7613137 100644 --- a/main.go +++ b/main.go @@ -62,6 +62,7 @@ func initDependencies(cfg config.Config, redisAdapter redis.Adapter, db *mysql.D BenefactorVld: initial.InitBenefactorValidator(), BenefactorKindBoxReqVld: initial.InitBenefactorKindBoxReqValidator(cfg, redisAdapter, db), BenefactorAddressVld: initial.InitBenefactorAddressValidator(cfg, redisAdapter, db), + BenefactorKindBoxVld: initial.InitBenefactorKindBoxValidator(cfg, redisAdapter, db), AdminKindBoxReqVld: initial.InitAdminKindBoxReqValidator(db, cfg), AdminVld: initial.InitAdminValidator(db), }, @@ -69,6 +70,7 @@ func initDependencies(cfg config.Config, redisAdapter redis.Adapter, db *mysql.D BenefactorSvc: initial.InitBenefactorService(cfg, redisAdapter, db), BenefactorKindBoxReqSvc: initial.InitBenefactorKindBoxReqService(db), BenefactorAddressSvc: initial.InitBenefactorAddressService(db), + BenefactorKindBoxSvc: initial.InitBenefactorKindBoxService(db), AdminKindBoxSvc: initial.InitAdminKindBoxService(db), AdminKindBoxReqSvc: initial.InitAdminKindBoxReqService(db), AdminSvc: initial.InitAdminService(cfg, db), @@ -85,6 +87,7 @@ func initAndRunServer(cfg config.Config, dependencies *Dependencies) { dependencies.BenefactorSvc, dependencies.BenefactorVld, dependencies.BenefactorAuthSvc, dependencies.BenefactorKindBoxReqSvc, dependencies.BenefactorKindBoxReqVld, dependencies.BenefactorAddressSvc, dependencies.BenefactorAddressVld, + dependencies.BenefactorKindBoxSvc, dependencies.BenefactorKindBoxVld, dependencies.AdminSvc, dependencies.AdminVld, dependencies.AdminAuthSvc, dependencies.AdminKindBoxReqSvc, dependencies.AdminKindBoxReqVld, dependencies.AdminAuthorizationSvc) diff --git a/param/benefactor/kind_box/register_emptying_request.go b/param/benefactor/kind_box/register_emptying_request.go new file mode 100644 index 0000000..e45a828 --- /dev/null +++ b/param/benefactor/kind_box/register_emptying_request.go @@ -0,0 +1,19 @@ +package benefactorkindboxparam + +import ( + "time" + + "git.gocasts.ir/ebhomengo/niki/entity" +) + +type KindBoxRegisterEmptyingRequest struct { + KindBoxID uint `json:"-" param:"id"` + BenefactorID uint `json:"-"` + ReturnAddressID uint `json:"return_address_id" example:"1"` + ReturnReferTimeID uint `json:"return_refer_time_id" example:"1"` + ReturnReferDate time.Time `json:"return_refer_date" example:"2025-01-02T15:04:05Z"` +} + +type KindBoxRegisterEmptyingRequestResponse struct { + entity.KindBox `json:"kind_box"` +} diff --git a/repository/mysql/kind_box/exist_kindbox.go b/repository/mysql/kind_box/exist_kindbox.go new file mode 100644 index 0000000..4276f85 --- /dev/null +++ b/repository/mysql/kind_box/exist_kindbox.go @@ -0,0 +1,21 @@ +package mysqlkindbox + +import ( + "context" + + errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg" + richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error" +) + +func (d DB) BenefactorKindBoxExist(ctx context.Context, benefactorID, kindBoxID uint) (bool, error) { + const op = "mysqlkindbox.BenefactorKindBoxExist" + + var count int + if err := d.conn.Conn().QueryRowContext(ctx, `SELECT COUNT(*) FROM kind_boxes WHERE benefactor_id = ? AND id = ?`, benefactorID, kindBoxID).Scan(&count); err != nil { + + return false, richerror.New(op).WithErr(err). + WithMessage(errmsg.ErrorMsgSomethingWentWrong).WithKind(richerror.KindUnexpected) + } + + return count > 0, nil +} diff --git a/repository/mysql/kind_box/get.go b/repository/mysql/kind_box/get.go new file mode 100644 index 0000000..e4a37e6 --- /dev/null +++ b/repository/mysql/kind_box/get.go @@ -0,0 +1,34 @@ +package mysqlkindbox + +import ( + "context" + "database/sql" + + "git.gocasts.ir/ebhomengo/niki/entity" + errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg" + richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error" +) + +func (d DB) GetKindBox(ctx context.Context, kindBoxID uint) (entity.KindBox, error) { + const op = "mysqlkindbox.GetKindBox" + + query := `SELECT * FROM kind_boxes WHERE id = ? AND deleted_at IS NULL` + row := d.conn.Conn().QueryRowContext(ctx, query, kindBoxID) + k, err := scanKindBox(row) + if err != nil { + if err == sql.ErrNoRows { + return entity.KindBox{}, richerror.New(op).WithErr(err). + WithMessage(errmsg.ErrorMsgNotFound).WithKind(richerror.KindNotFound) + } + + return entity.KindBox{}, richerror.New(op).WithErr(err). + WithMessage(errmsg.ErrorMsgCantScanQueryResult).WithKind(richerror.KindUnexpected) + } + + return k, nil +} + +func (d DB) GetAllKindBox(ctx context.Context, benefactorID uint) ([]entity.KindBox, error) { + // TODO implement me + panic("implement me") +} diff --git a/repository/mysql/kind_box/register_emptying_request.go b/repository/mysql/kind_box/register_emptying_request.go new file mode 100644 index 0000000..db371b4 --- /dev/null +++ b/repository/mysql/kind_box/register_emptying_request.go @@ -0,0 +1,27 @@ +package mysqlkindbox + +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" +) + +func (d DB) RegisterEmptyingRequestForKindBox(ctx context.Context, kindBox entity.KindBox) error { + const op = "mysqlkindbox.RegisterEmptyingRequest" + + query := `UPDATE kind_boxes + SET return_address_id = ?, return_refer_time_id = ?, return_refer_date = ?, status = ? + WHERE id = ? AND benefactor_id = ? AND status = ? AND deleted_at IS NULL` + + _, err := d.conn.Conn().ExecContext(ctx, query, + kindBox.ReturnAddressID, kindBox.ReturnReferTimeID, kindBox.ReturnReferDate, kindBox.Status.String(), + kindBox.ID, kindBox.BenefactorID, entity.KindBoxDeliveredStatus.String()) + if err != nil { + return richerror.New(op).WithErr(err).WithMessage(errmsg.ErrorMsgSomethingWentWrong). + WithKind(richerror.KindUnexpected) + } + + return nil +} diff --git a/repository/mysql/kind_box/scan.go b/repository/mysql/kind_box/scan.go new file mode 100644 index 0000000..81e01d9 --- /dev/null +++ b/repository/mysql/kind_box/scan.go @@ -0,0 +1,86 @@ +package mysqlkindbox + +import ( + "database/sql" + "time" + + "git.gocasts.ir/ebhomengo/niki/entity" + "git.gocasts.ir/ebhomengo/niki/repository/mysql" +) + +func scanKindBox(scanner mysql.Scanner) (entity.KindBox, error) { + var kindBox entity.KindBox + var ( + kindBoxType string + amount sql.NullInt64 + serialNumber sql.NullString + status string + senderAgentID sql.NullInt64 + deliveredAt sql.NullTime + returnReferTimeID sql.NullInt64 + returnReferDate sql.NullTime + returnAddressID sql.NullInt64 + receiverAgentID sql.NullInt64 + returnedAt sql.NullTime + createdAt time.Time + updatedAt time.Time + deletedAt sql.NullTime + ) + + err := scanner.Scan( + &kindBox.ID, + &kindBox.KindBoxReqID, + &kindBox.BenefactorID, + &kindBoxType, + &amount, + &serialNumber, + &status, + &kindBox.DeliverReferDate, + &kindBox.DeliverAddressID, + &kindBox.SenderAgentID, + &kindBox.DeliveredAt, + &returnReferTimeID, + &returnReferDate, + &returnAddressID, + &receiverAgentID, + &returnedAt, + &createdAt, + &updatedAt, + &deletedAt, + ) + if err != nil { + return entity.KindBox{}, err + } + + kindBox.Type = entity.MapToKindBoxType(kindBoxType) + if amount.Valid { + kindBox.Amount = uint(amount.Int64) + } + if serialNumber.Valid { + kindBox.SerialNumber = serialNumber.String + } + kindBox.Status = entity.MapToKindBoxStatus(status) + if senderAgentID.Valid { + kindBox.SenderAgentID = uint(senderAgentID.Int64) + } + if deliveredAt.Valid { + kindBox.DeliveredAt = deliveredAt.Time + } + if returnReferTimeID.Valid { + kindBox.ReturnReferTimeID = uint(returnReferTimeID.Int64) + } + if returnReferDate.Valid { + kindBox.ReturnReferDate = returnReferDate.Time + } + if returnAddressID.Valid { + kindBox.ReturnAddressID = uint(returnAddressID.Int64) + } + if receiverAgentID.Valid { + kindBox.ReceiverAgentID = uint(receiverAgentID.Int64) + } + if returnedAt.Valid { + kindBox.ReturnedAt = returnedAt.Time + } + + return kindBox, nil +} diff --git a/repository/mysql/migration/1705992494_create_kind_boxes_table.sql b/repository/mysql/migration/1705992494_create_kind_boxes_table.sql index dc5054e..3dae14c 100644 --- a/repository/mysql/migration/1705992494_create_kind_boxes_table.sql +++ b/repository/mysql/migration/1705992494_create_kind_boxes_table.sql @@ -11,6 +11,7 @@ CREATE TABLE `kind_boxes` ( `deliver_address_id` INT NOT NULL, `sender_agent_id` INT NOT NULL, `delivered_at` DATETIME NOT NULL, + `return_refer_time_id` INT, `return_refer_date` DATETIME, `return_address_id` INT, `receiver_agent_id` INT, @@ -18,10 +19,12 @@ CREATE TABLE `kind_boxes` ( `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `deleted_at` TIMESTAMP NULL, FOREIGN KEY (`kind_box_req_id`) REFERENCES `kind_box_reqs` (`id`), FOREIGN KEY (`benefactor_id`) REFERENCES `benefactors` (`id`), FOREIGN KEY (`deliver_address_id`) REFERENCES `addresses` (`id`), FOREIGN KEY (`sender_agent_id`) REFERENCES `admins` (`id`), + FOREIGN KEY (`return_refer_time_id`)REFERENCES `refer_times` (`id`), FOREIGN KEY (`return_address_id`) REFERENCES `addresses` (`id`), FOREIGN KEY (`receiver_agent_id`) REFERENCES `admins` (`id`), INDEX `index_serial_number` (`serial_number`) diff --git a/service/benefactor/kind_box/register_emptying_request.go b/service/benefactor/kind_box/register_emptying_request.go new file mode 100644 index 0000000..3b1c633 --- /dev/null +++ b/service/benefactor/kind_box/register_emptying_request.go @@ -0,0 +1,27 @@ +package benefactorkindboxservice + +import ( + "context" + + "git.gocasts.ir/ebhomengo/niki/entity" + param "git.gocasts.ir/ebhomengo/niki/param/benefactor/kind_box" + richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error" +) + +func (s Service) RegisterEmptyingRequest(ctx context.Context, req param.KindBoxRegisterEmptyingRequest) error { + const op = "benefactorKindBoxService.RegisterEmptyingRequest" + + err := s.repo.RegisterEmptyingRequestForKindBox(ctx, entity.KindBox{ + ID: req.KindBoxID, + ReturnAddressID: req.ReturnAddressID, + ReturnReferTimeID: req.ReturnReferTimeID, + ReturnReferDate: req.ReturnReferDate, + Status: entity.KindBoxReadyToReturnStatus, + BenefactorID: req.BenefactorID, + }) + if err != nil { + return richerror.New(op).WithErr(err) + } + + return nil +} diff --git a/service/benefactor/kind_box/service.go b/service/benefactor/kind_box/service.go index 0970f9e..fe7a0d0 100644 --- a/service/benefactor/kind_box/service.go +++ b/service/benefactor/kind_box/service.go @@ -9,6 +9,7 @@ import ( type Repository interface { GetAllKindBox(ctx context.Context, benefactorID uint) ([]entity.KindBox, error) GetKindBox(ctx context.Context, kindBoxID uint) (entity.KindBox, error) + RegisterEmptyingRequestForKindBox(ctx context.Context, kindBox entity.KindBox) error } type Service struct { diff --git a/validator/benefactor/kind_box/get.go b/validator/benefactor/kind_box/get.go index cd303de..eb6a456 100644 --- a/validator/benefactor/kind_box/get.go +++ b/validator/benefactor/kind_box/get.go @@ -17,10 +17,8 @@ func (v Validator) ValidateGetRequest(req param.KindBoxGetRequest) (map[string]s validation.Required, validation.By(v.doesBenefactorExist)), - validation.Field(&req.KindBoxID, - validation.Required, - validation.By(v.doesKindBoxExist), - validation.By(v.doesKindBoxBelongToBenefactor(req.BenefactorID))), + validation.Field(&req.KindBoxID, validation.Required, + validation.By(v.doesBenefactorKindBoxExist(req.BenefactorID))), ); err != nil { fieldErrors := make(map[string]string) diff --git a/validator/benefactor/kind_box/register_emptying_request.go b/validator/benefactor/kind_box/register_emptying_request.go new file mode 100644 index 0000000..cb483da --- /dev/null +++ b/validator/benefactor/kind_box/register_emptying_request.go @@ -0,0 +1,51 @@ +package benefactorkindboxvalidator + +import ( + "errors" + + param "git.gocasts.ir/ebhomengo/niki/param/benefactor/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) ValidateRegisterEmptyingRequest(req param.KindBoxRegisterEmptyingRequest) (map[string]string, error) { + const op = "benefactorkindboxvalidator.ValidateRegisterEmptyingRequest" + + if err := validation.ValidateStruct(&req, + validation.Field(&req.BenefactorID, validation.Required, + validation.By(v.doesBenefactorExist)), + + validation.Field(&req.KindBoxID, validation.Required, + validation.By(v.doesBenefactorKindBoxExist(req.BenefactorID)), + validation.By(v.doesKindBoxHaveDeliveredStatus)), + + validation.Field(&req.ReturnAddressID, validation.Required, + validation.By(v.doesAddressExist(req.BenefactorID))), + + validation.Field(&req.ReturnReferDate, validation.Required, + validation.By(v.isDateValid)), + + validation.Field(&req.ReturnReferTimeID, validation.Required, + validation.By(v.isReferTimeIDValid)), + ); 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/benefactor/kind_box/validator.go b/validator/benefactor/kind_box/validator.go index 6d26bd4..c19a50a 100644 --- a/validator/benefactor/kind_box/validator.go +++ b/validator/benefactor/kind_box/validator.go @@ -1,24 +1,44 @@ package benefactorkindboxvalidator import ( + "context" "fmt" + "time" + "git.gocasts.ir/ebhomengo/niki/entity" + refertimeparam "git.gocasts.ir/ebhomengo/niki/param/admin/refer_time" + addressparam "git.gocasts.ir/ebhomengo/niki/param/benefactor/address" + param "git.gocasts.ir/ebhomengo/niki/param/benefactor/benefactore" errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg" validation "github.com/go-ozzo/ozzo-validation/v4" ) type Repository interface { - BenefactorExist(id uint) (bool, error) - KindBoxExist(id uint) (bool, error) - KindBoxBelongToBenefactor(bID uint, kbID uint) (bool, error) + BenefactorKindBoxExist(ctx context.Context, benefactorID uint, kindBoxID uint) (bool, error) + GetKindBox(ctx context.Context, kindBoxID uint) (entity.KindBox, error) +} + +type BenefactorSvc interface { + BenefactorExistByID(ctx context.Context, request param.BenefactorExistByIDRequest) (param.BenefactorExistByIDResponse, error) +} + +type AddressSvc interface { + AddressExistByID(ctx context.Context, request addressparam.GetAddressByIDRequest) (addressparam.GetAddressByIDResponse, error) +} + +type ReferTimeSvc interface { + GetReferTimeByID(ctx context.Context, req refertimeparam.GetReferTimeRequest) (refertimeparam.GetReferTimeResponse, error) } type Validator struct { - repo Repository + repo Repository + benefactorSvc BenefactorSvc + addressSvc AddressSvc + referTimeSvc ReferTimeSvc } -func New(repo Repository) Validator { - return Validator{repo: repo} +func New(repo Repository, benefactorSvc BenefactorSvc, addressSvc AddressSvc, referTimeSvc ReferTimeSvc) Validator { + return Validator{repo: repo, benefactorSvc: benefactorSvc, addressSvc: addressSvc, referTimeSvc: referTimeSvc} } func (v Validator) doesBenefactorExist(value interface{}) error { @@ -26,7 +46,7 @@ func (v Validator) doesBenefactorExist(value interface{}) error { if !ok { return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong) } - _, err := v.repo.BenefactorExist(benefactorID) + _, err := v.benefactorSvc.BenefactorExistByID(context.Background(), param.BenefactorExistByIDRequest{ID: benefactorID}) if err != nil { return fmt.Errorf(errmsg.ErrorMsgNotFound) } @@ -34,30 +54,86 @@ func (v Validator) doesBenefactorExist(value interface{}) error { return nil } -func (v Validator) doesKindBoxExist(value interface{}) error { - kindBoxID, ok := value.(uint) - if !ok { - return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong) - } - _, err := v.repo.KindBoxExist(kindBoxID) - if err != nil { - return fmt.Errorf(errmsg.ErrorMsgNotFound) - } - - return nil -} - -func (v Validator) doesKindBoxBelongToBenefactor(benefactorID uint) validation.RuleFunc { +func (v Validator) doesBenefactorKindBoxExist(benefactorID uint) validation.RuleFunc { return func(value interface{}) error { kbID, ok := value.(uint) if !ok { return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong) } - _, err := v.repo.KindBoxBelongToBenefactor(benefactorID, kbID) + exist, err := v.repo.BenefactorKindBoxExist(context.Background(), benefactorID, kbID) if err != nil { + return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong) + } + if !exist { 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.addressSvc.AddressExistByID(context.Background(), addressparam.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.(time.Time) + if !ok { + return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong) + } + if date.Before(time.Now()) { + return fmt.Errorf(errmsg.ErrorMsgInvalidInput) + } + + return nil +} + +func (v Validator) isReferTimeIDValid(value interface{}) error { + referTimeID, ok := value.(uint) + if !ok { + return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong) + } + resp, gErr := v.referTimeSvc.GetReferTimeByID(context.Background(), refertimeparam.GetReferTimeRequest{ + ReferTimeID: referTimeID, + }) + if gErr != nil { + return fmt.Errorf(errmsg.ErrorMsgReferTimeNotFound) + } + if resp.ReferTime.Status != entity.ReferTimeActiveStatus { + return fmt.Errorf(errmsg.ErrorMsgReferTimeIsNotActive) + } + return nil +} + +func (v Validator) doesKindBoxHaveDeliveredStatus(value interface{}) error { + kindBoxID, ok := value.(uint) + if !ok { + return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong) + } + kindBox, err := v.repo.GetKindBox(context.Background(), kindBoxID) + if err != nil { + return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong) + } + if kindBox.Status != entity.KindBoxDeliveredStatus { + return fmt.Errorf(errmsg.ErrorMsgInvalidStatus) + } + + return nil +}