forked from ebhomengo/niki
1
0
Fork 0

Merge pull request 'feat(kindboxreq): added edit kindboxreq by benefactor' (#100) from stage/fatemeh/93-benefactor-edit-kindboxreq into develop

Reviewed-on: ebhomengo/niki#100
This commit is contained in:
hossein 2024-07-24 06:30:17 +00:00
commit 3c0d1fe347
11 changed files with 504 additions and 69 deletions

View File

@ -18,4 +18,5 @@ func (h Handler) SetRoutes(e *echo.Echo) {
r.GET("/:id", h.Get)
r.DELETE("/:id", h.Delete)
r.GET("/", h.GetAll)
r.PUT("/:id", h.Update)
}

View File

@ -0,0 +1,53 @@
package benefactorkindboxreqhandler
import (
param "git.gocasts.ir/ebhomengo/niki/param/benefactor/kind_box_req"
httpmsg "git.gocasts.ir/ebhomengo/niki/pkg/http_msg"
"git.gocasts.ir/ebhomengo/niki/pkg/claim"
"github.com/labstack/echo/v4"
"net/http"
)
// Update godoc
// @Summary Update kind box request by benefactor
// @Tags KindBoxReq
// @Accept json
// @Produce json
// @Param id path int true "KindBoxReq ID"
// @Param Request body param.KindBoxReqUpdateRequest true "Update KindBoxReq 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 AuthBearerBenefactor
// @Router /benefactor/kindboxreqs/{id} [put]
func (h Handler) Update(c echo.Context) error {
var req param.KindBoxReqUpdateRequest
if bErr := c.Bind(&req); bErr != nil {
return echo.NewHTTPError(http.StatusBadRequest)
}
claims := claim.GetClaimsFromEchoContext(c)
req.BenefactorID = claims.UserID
if fieldErrors, err := h.benefactorKindBoxReqVld.ValidateUpdateRequest(req); err != nil {
msg, code := httpmsg.Error(err)
return c.JSON(code, echo.Map{
"message": msg,
"errors": fieldErrors,
})
}
sErr := h.benefactorKindBoxReqSvc.Update(c.Request().Context(), req)
if sErr != nil {
msg, code := httpmsg.Error(sErr)
return echo.NewHTTPError(code, msg)
}
return c.JSON(http.StatusNoContent, nil)
}

View File

@ -2267,6 +2267,76 @@ const docTemplate = `{
}
}
},
"put": {
"security": [
{
"AuthBearerBenefactor": []
}
],
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"KindBoxReq"
],
"summary": "Update kind box request by benefactor",
"parameters": [
{
"type": "integer",
"description": "KindBoxReq ID",
"name": "id",
"in": "path",
"required": true
},
{
"description": "Update KindBoxReq Request Body",
"name": "Request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/benefactorkindboxreqparam.KindBoxReqUpdateRequest"
}
}
],
"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"
}
}
}
},
"delete": {
"security": [
{
@ -3377,6 +3447,39 @@ const docTemplate = `{
}
}
},
"benefactorkindboxreqparam.KindBoxReqUpdateRequest": {
"type": "object",
"properties": {
"count_requested": {
"type": "integer",
"example": 5
},
"deliver_address_id": {
"type": "integer",
"example": 1
},
"deliver_refer_date": {
"type": "string",
"example": "2025-01-02T15:04:05Z"
},
"deliver_refer_time_id": {
"type": "integer",
"example": 1
},
"description": {
"type": "string",
"example": "description"
},
"kind_box_type": {
"allOf": [
{
"$ref": "#/definitions/entity.KindBoxType"
}
],
"example": 2
}
}
},
"entity.Address": {
"type": "object",
"properties": {

View File

@ -2256,6 +2256,76 @@
}
}
},
"put": {
"security": [
{
"AuthBearerBenefactor": []
}
],
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"KindBoxReq"
],
"summary": "Update kind box request by benefactor",
"parameters": [
{
"type": "integer",
"description": "KindBoxReq ID",
"name": "id",
"in": "path",
"required": true
},
{
"description": "Update KindBoxReq Request Body",
"name": "Request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/benefactorkindboxreqparam.KindBoxReqUpdateRequest"
}
}
],
"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"
}
}
}
},
"delete": {
"security": [
{
@ -3366,6 +3436,39 @@
}
}
},
"benefactorkindboxreqparam.KindBoxReqUpdateRequest": {
"type": "object",
"properties": {
"count_requested": {
"type": "integer",
"example": 5
},
"deliver_address_id": {
"type": "integer",
"example": 1
},
"deliver_refer_date": {
"type": "string",
"example": "2025-01-02T15:04:05Z"
},
"deliver_refer_time_id": {
"type": "integer",
"example": 1
},
"description": {
"type": "string",
"example": "description"
},
"kind_box_type": {
"allOf": [
{
"$ref": "#/definitions/entity.KindBoxType"
}
],
"example": 2
}
}
},
"entity.Address": {
"type": "object",
"properties": {

View File

@ -648,6 +648,28 @@ definitions:
kind_box_req:
$ref: '#/definitions/entity.KindBoxReq'
type: object
benefactorkindboxreqparam.KindBoxReqUpdateRequest:
properties:
count_requested:
example: 5
type: integer
deliver_address_id:
example: 1
type: integer
deliver_refer_date:
example: "2025-01-02T15:04:05Z"
type: string
deliver_refer_time_id:
example: 1
type: integer
description:
example: description
type: string
kind_box_type:
allOf:
- $ref: '#/definitions/entity.KindBoxType'
example: 2
type: object
entity.Address:
properties:
address:
@ -2374,6 +2396,51 @@ paths:
summary: Get a kind box request for a benefactor
tags:
- KindBoxReq
put:
consumes:
- application/json
parameters:
- description: KindBoxReq ID
in: path
name: id
required: true
type: integer
- description: Update KindBoxReq Request Body
in: body
name: Request
required: true
schema:
$ref: '#/definitions/benefactorkindboxreqparam.KindBoxReqUpdateRequest'
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:
- AuthBearerBenefactor: []
summary: Update kind box request by benefactor
tags:
- KindBoxReq
/benefactor/login-register:
post:
consumes:

View File

@ -1,14 +1,23 @@
package benefactorkindboxreqparam
import entity "git.gocasts.ir/ebhomengo/niki/entity"
import (
"time"
"git.gocasts.ir/ebhomengo/niki/entity"
)
type KindBoxReqUpdateRequest struct {
BenefactorID uint
KindBoxReqID uint
KindBoxType entity.KindBoxType
CountRequested uint
KindBoxReqID uint `json:"-" param:"id" example:"1"`
BenefactorID uint `json:"-" example: "1"`
KindBoxType entity.KindBoxType `json:"kind_box_type" example:"2"`
CountRequested uint `json:"count_requested" example:"5"`
Description string `json:"description" example:"description"`
DeliverReferTimeID uint `json:"deliver_refer_time_id" example:"1"`
DeliverReferDate time.Time `json:"deliver_refer_date" example:"2025-01-02T15:04:05Z"`
DeliverAddressID uint `json:"deliver_address_id" example:"1"`
}
type KindBoxReqUpdateResponse struct {
KindBoxReq entity.KindBoxReq
}

View File

@ -1,81 +1,89 @@
package mysql
import (
"database/sql"
"fmt"
querier "git.gocasts.ir/ebhomengo/niki/pkg/query_transaction/sql"
"sync"
"time"
"database/sql"
"fmt"
querier "git.gocasts.ir/ebhomengo/niki/pkg/query_transaction/sql"
"sync"
"time"
)
type Config struct {
Username string `koanf:"username"`
Password string `koanf:"password"`
Port int `koanf:"port"`
Host string `koanf:"host"`
DBName string `koanf:"db_name"`
Username string `koanf:"username"`
Password string `koanf:"password"`
Port int `koanf:"port"`
Host string `koanf:"host"`
DBName string `koanf:"db_name"`
}
type DB struct {
config Config
db *querier.SqlDB
mu sync.Mutex
statements map[string]*sql.Stmt
config Config
db *querier.SqlDB
mu sync.Mutex
statements map[string]*sql.Stmt
}
func (db *DB) Conn() *querier.SqlDB {
return db.db
return db.db
}
// TODO: this temperary to ignore linter error (magic number).
// TODO: this temporary to ignore linter error (magic number).
const (
dbMaxConnLifetime = time.Minute * 3
dbMaxOpenConns = 10
dbMaxIdleConns = 10
dbMaxConnLifetime = time.Minute * 3
dbMaxOpenConns = 10
dbMaxIdleConns = 10
)
func New(config Config) *DB {
// parseTime=true changes the output type of DATE and DATETIME values to time.Time
// instead of []byte / string
// The date or datetime like 0000-00-00 00:00:00 is converted into zero value of time.Time
db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@(%s:%d)/%s?parseTime=true",
config.Username, config.Password, config.Host, config.Port, config.DBName))
if err != nil {
panic(fmt.Errorf("can't open mysql db: %w", err))
}
// parseTime=true changes the output type of DATE and DATETIME values to time.Time
// instead of []byte / string
// The date or datetime like 0000-00-00 00:00:00 is converted into zero value of time.Time
db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@(%s:%d)/%s?parseTime=true",
config.Username, config.Password, config.Host, config.Port, config.DBName))
if err != nil {
panic(fmt.Errorf("can't open mysql db: %w", err))
}
// See "Important settings" section.
db.SetConnMaxLifetime(dbMaxConnLifetime)
db.SetMaxOpenConns(dbMaxOpenConns)
db.SetMaxIdleConns(dbMaxIdleConns)
// See "Important settings" section.
db.SetConnMaxLifetime(dbMaxConnLifetime)
db.SetMaxOpenConns(dbMaxOpenConns)
db.SetMaxIdleConns(dbMaxIdleConns)
return &DB{config: config, db: &querier.SqlDB{db}}
return &DB{
config: config,
db: &querier.SqlDB{DB: db},
statements: make(map[string]*sql.Stmt),
}
}
func (p *DB) PrepareStatement(key string, query string) (*sql.Stmt, error) {
p.mu.Lock()
defer p.mu.Unlock()
p.mu.Lock()
defer p.mu.Unlock()
if stmt, ok := p.statements[key]; ok {
return stmt, nil
}
if stmt, ok := p.statements[key]; ok {
return stmt, nil
}
stmt, err := p.db.Prepare(query)
if err != nil {
return nil, err
}
p.statements[key] = stmt
stmt, err := p.db.Prepare(query)
if err != nil {
return nil, err
}
p.statements[key] = stmt
return stmt, nil
return stmt, nil
}
func (p *DB) CloseStatements() error {
for _, stmt := range p.statements {
err := stmt.Close()
if err != nil {
return err
}
}
p.mu.Lock()
defer p.mu.Unlock()
return nil
for _, stmt := range p.statements {
err := stmt.Close()
if err != nil {
return err
}
}
p.statements = make(map[string]*sql.Stmt)
return nil
}

View File

@ -12,6 +12,7 @@ type Repository interface {
GetKindBoxReqByID(ctx context.Context, kindBoxReqID uint) (entity.KindBoxReq, error)
DeleteKindBoxReqByID(ctx context.Context, kindBoxReqID uint) error
GetAllKindBoxReq(ctx context.Context, filter params.FilterRequest, pagination params.PaginationRequest, sort params.SortRequest) ([]entity.KindBoxReq, uint, error)
UpdateKindBoxReq(ctx context.Context, kindBoxReq entity.KindBoxReq) error
}
type Service struct {

View File

@ -0,0 +1,31 @@
package benefactorkindboxreqservice
import (
"context"
param "git.gocasts.ir/ebhomengo/niki/param/benefactor/kind_box_req"
richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"
)
func (s Service) Update(ctx context.Context, req param.KindBoxReqUpdateRequest) error {
const op = "benefactorkindboxreqservice.Update"
kindBoxReq, err := s.repo.GetKindBoxReqByID(ctx, req.KindBoxReqID)
if err != nil {
return richerror.New(op).WithErr(err)
}
kindBoxReq.KindBoxType = req.KindBoxType
kindBoxReq.CountRequested = req.CountRequested
kindBoxReq.Description = req.Description
kindBoxReq.DeliverReferTimeID = req.DeliverReferTimeID
kindBoxReq.DeliverReferDate = req.DeliverReferDate
kindBoxReq.DeliverAddressID = req.DeliverAddressID
uErr := s.repo.UpdateKindBoxReq(ctx, kindBoxReq)
if uErr != nil {
return richerror.New(op).WithErr(err)
}
return nil
}

View File

@ -10,24 +10,37 @@ import (
)
func (v Validator) ValidateUpdateRequest(req param.KindBoxReqUpdateRequest) (map[string]string, error) {
const op = "userkindboxreqvalidator.ValidateUpdateRequest"
const op = "benefactorkindboxreqvalidator.ValidateUpdateRequest"
if err := validation.ValidateStruct(&req,
validation.Field(&req.CountRequested, validation.Required, validation.Min(MinKindBoxReq), validation.Max(MaxKindBoxReq)),
validation.Field(&req.BenefactorID,
validation.Field(&req.KindBoxReqID,
validation.Required,
validation.By(v.doesBenefactorExist)),
// validation.Field(&req.KindBoxReqID,
// validation.Required,
// validation.By(v.doesKindBoxRequestExist),
// validation.By(v.hasPendingStatus),
// validation.By(v.doesKindBoxBelongToBenefactor(req.BenefactorID))),
validation.By(v.doesKindBoxRequestExist),
validation.By(v.doesKindBoxRequestHavePendingStatus),
validation.By(v.doesKindBoxBelongToBenefactor(req.BenefactorID)),
),
validation.Field(&req.CountRequested,
validation.Required,
validation.Min(uint(MinKindBoxReq)),
validation.Max(uint(MaxKindBoxReq)),
),
validation.Field(&req.KindBoxType,
validation.Required,
validation.By(v.doesTypeExist)),
validation.By(v.doesTypeExist),
),
validation.Field(&req.DeliverAddressID,
validation.Required,
validation.By(v.doesBenefactorAddressExist(req.KindBoxReqID)),
),
validation.Field(&req.DeliverReferDate,
validation.Required,
validation.By(v.isDateValid),
),
validation.Field(&req.DeliverReferTimeID,
validation.Required,
validation.By(v.isReferTimeIDValid),
),
); err != nil {
fieldErrors := make(map[string]string)

View File

@ -6,6 +6,7 @@ import (
params "git.gocasts.ir/ebhomengo/niki/param"
"slices"
"time"
"errors"
"git.gocasts.ir/ebhomengo/niki/entity"
refertimeparam "git.gocasts.ir/ebhomengo/niki/param/admin/refer_time"
@ -33,6 +34,7 @@ type ReferTimeSvc interface {
}
type Repository interface {
KindBoxRequestExist(id uint) (bool, error)
GetKindBoxReqByID(ctx context.Context, kindBoxReqID uint) (entity.KindBoxReq, error)
}
@ -202,3 +204,47 @@ func (v Validator) areSortFieldsValid(validSortFields []string) validation.RuleF
return nil
}
}
func (v Validator) doesKindBoxRequestExist(value interface{}) error {
kindboxreqID, ok := value.(uint)
if !ok {
return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong)
}
if isExist, err := v.repo.KindBoxRequestExist(kindboxreqID); !isExist || err != nil {
if err != nil {
return err
}
if !isExist {
return errors.New("kind box request is not exist")
}
}
return nil
}
func (v Validator) doesBenefactorAddressExist(kindBoxReqID uint) validation.RuleFunc {
return func(value interface{}) error {
addressID, ok := value.(uint)
if !ok {
return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong)
}
kindBoxReq, err := v.repo.GetKindBoxReqByID(context.Background(), kindBoxReqID)
if err != nil {
return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong)
}
address, aErr := v.addressSvc.AddressExistByID(context.Background(), addressparam.GetAddressByIDRequest{ID: addressID})
if aErr != nil {
return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong)
}
if address.Address == nil {
return fmt.Errorf(errmsg.ErrorMsgNotFound)
}
if address.Address.BenefactorID != kindBoxReq.BenefactorID {
return fmt.Errorf(errmsg.ErrorMsgNotFound)
}
return nil
}
}