fix(niki): add refer time duration when creating kind box req by benefactor

This commit is contained in:
Iman Mirazimi 2024-05-31 16:06:48 +03:30
parent 4aec4d8ecb
commit b7d5eb522b
25 changed files with 297 additions and 59 deletions

View File

@ -1,13 +1,12 @@
package benefactorkindboxreqhandler
import (
"net/http"
param "git.gocasts.ir/ebhomengo/niki/param/benefactor/kind_box_req"
"git.gocasts.ir/ebhomengo/niki/pkg/claim"
errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg"
httpmsg "git.gocasts.ir/ebhomengo/niki/pkg/http_msg"
echo "github.com/labstack/echo/v4"
"net/http"
)
// Add godoc
@ -32,13 +31,12 @@ func (h Handler) Add(c echo.Context) error {
claims := claim.GetClaimsFromEchoContext(c)
req.BenefactorID = claims.UserID
result := h.benefactorKindBoxReqVld.ValidateAddRequest(req)
if result != nil {
msg, code := httpmsg.Error(result.Err)
if fieldErrors, err := h.benefactorKindBoxReqVld.ValidateAddRequest(req); err != nil {
msg, code := httpmsg.Error(err)
return c.JSON(code, echo.Map{
"message": msg,
"errors": result.Fields,
"errors": fieldErrors,
})
}
resp, sErr := h.benefactorKindBoxReqSvc.Add(c.Request().Context(), req)

View File

@ -1284,7 +1284,11 @@ const docTemplate = `{
},
"deliver_refer_date": {
"type": "string",
"example": "2025-01-02 15:04:05"
"example": "2025-01-02T15:04:05Z"
},
"deliver_refer_time_id": {
"type": "integer",
"example": 1
},
"type_id": {
"allOf": [
@ -1449,6 +1453,9 @@ const docTemplate = `{
"deliverReferDate": {
"type": "string"
},
"deliverReferTimeID": {
"type": "integer"
},
"deliveredAt": {
"type": "string"
},

View File

@ -1273,7 +1273,11 @@
},
"deliver_refer_date": {
"type": "string",
"example": "2025-01-02 15:04:05"
"example": "2025-01-02T15:04:05Z"
},
"deliver_refer_time_id": {
"type": "integer",
"example": 1
},
"type_id": {
"allOf": [
@ -1438,6 +1442,9 @@
"deliverReferDate": {
"type": "string"
},
"deliverReferTimeID": {
"type": "integer"
},
"deliveredAt": {
"type": "string"
},

View File

@ -316,8 +316,11 @@ definitions:
example: 1
type: integer
deliver_refer_date:
example: "2025-01-02 15:04:05"
example: "2025-01-02T15:04:05Z"
type: string
deliver_refer_time_id:
example: 1
type: integer
type_id:
allOf:
- $ref: '#/definitions/entity.KindBoxType'
@ -426,6 +429,8 @@ definitions:
type: integer
deliverReferDate:
type: string
deliverReferTimeID:
type: integer
deliveredAt:
type: string
description:

View File

@ -3,15 +3,16 @@ package entity
import "time"
type KindBoxReq struct {
ID uint
BenefactorID uint
KindBoxType KindBoxType
CountRequested uint
CountAccepted uint
Description string
Status KindBoxReqStatus
DeliverReferDate time.Time
DeliverAddressID uint
SenderAgentID uint
DeliveredAt time.Time
ID uint
BenefactorID uint
KindBoxType KindBoxType
CountRequested uint
CountAccepted uint
Description string
Status KindBoxReqStatus
DeliverReferTimeID uint
DeliverReferDate time.Time
DeliverAddressID uint
SenderAgentID uint
DeliveredAt time.Time
}

7
entity/refer_time.go Normal file
View File

@ -0,0 +1,7 @@
package entity
type ReferTime struct {
ID uint
Duration string
Status ReferTimeStatus
}

View File

@ -0,0 +1,42 @@
package entity
type ReferTimeStatus uint
const (
ReferTimeActiveStatus ReferTimeStatus = iota + 1
ReferTimeInactiveStatus
)
var ReferTimeStatusStrings = map[ReferTimeStatus]string{
ReferTimeActiveStatus: "active",
ReferTimeInactiveStatus: "inactive",
}
func (s ReferTimeStatus) String() string {
return ReferTimeStatusStrings[s]
}
func (s ReferTimeStatus) IsValid() bool {
return s > 0 && int(s) <= len(ReferTimeStatusStrings)
}
// AllReferTimeStatus returns a slice containing all string values of ReferTimeStatus.
func AllReferTimeStatus() []string {
statusStrings := make([]string, len(ReferTimeStatusStrings))
for status, str := range ReferTimeStatusStrings {
statusStrings[int(status)-1] = str
}
return statusStrings
}
// MapToReferTimeStatus converts a string to the corresponding ReferTimeStatus value.
func MapToReferTimeStatus(statusStr string) ReferTimeStatus {
for status, str := range ReferTimeStatusStrings {
if str == statusStr {
return status
}
}
return ReferTimeStatus(0)
}

View File

@ -7,6 +7,7 @@ import (
mysqladmin "git.gocasts.ir/ebhomengo/niki/repository/mysql/admin"
mysqlkindbox "git.gocasts.ir/ebhomengo/niki/repository/mysql/kind_box"
mysqlkindboxreq "git.gocasts.ir/ebhomengo/niki/repository/mysql/kind_box_req"
mysqlrefertime "git.gocasts.ir/ebhomengo/niki/repository/mysql/refer_time"
)
type Databases struct {
@ -35,3 +36,7 @@ func InitKindBoxRepo(db *mysql.DB) *mysqlkindbox.DB {
func InitAdminMysql(db *mysql.DB) *mysqladmin.DB {
return mysqladmin.New(db)
}
func InitAdminReferTimeDB(db *mysql.DB) *mysqlrefertime.DB {
return mysqlrefertime.New(db)
}

View File

@ -13,6 +13,7 @@ import (
adminservice "git.gocasts.ir/ebhomengo/niki/service/admin/admin"
adminkindboxservice "git.gocasts.ir/ebhomengo/niki/service/admin/kind_box"
adminkindboxreqservice "git.gocasts.ir/ebhomengo/niki/service/admin/kind_box_req"
adminrefertimeservice "git.gocasts.ir/ebhomengo/niki/service/admin/refer_time"
benefactoraddressservice "git.gocasts.ir/ebhomengo/niki/service/benefactor/address"
benefactorservice "git.gocasts.ir/ebhomengo/niki/service/benefactor/benefactor"
benefactorkindboxreqservice "git.gocasts.ir/ebhomengo/niki/service/benefactor/kind_box_req"
@ -25,6 +26,7 @@ type Services struct {
AdminKindBoxSvc adminkindboxservice.Service
AdminSvc adminservice.Service
AdminKindBoxReqSvc adminkindboxreqservice.Service
AdminReferTimeSvc adminrefertimeservice.Service
}
func initSms(cfg config.Config) *kavenegarotp.Adapter {
@ -60,3 +62,8 @@ 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),
)
}

View File

@ -35,6 +35,7 @@ func InitBenefactorKindBoxReqValidator(cfg config.Config, redisAdapter redis.Ada
return benefactorkindboxreqvalidator.New(
InitBenefactorService(cfg, redisAdapter, db),
InitBenefactorAddressService(db),
InitAdminReferTimeService(db),
InitBenefactorKindBoxReqDB(db),
)
}

View File

@ -72,6 +72,7 @@ func initDependencies(cfg config.Config, redisAdapter redis.Adapter, db *mysql.D
AdminKindBoxSvc: initial.InitAdminKindBoxService(db),
AdminKindBoxReqSvc: initial.InitAdminKindBoxReqService(db),
AdminSvc: initial.InitAdminService(cfg, db),
AdminReferTimeSvc: initial.InitAdminReferTimeService(db),
},
initial.AdminAuthorization{
AdminAuthorizationSvc: initial.InitAdminAuthorizationService(db),

View File

@ -0,0 +1,11 @@
package param
import "git.gocasts.ir/ebhomengo/niki/entity"
type GetReferTimeRequest struct {
ReferTimeID uint
}
type GetReferTimeResponse struct {
ReferTime entity.ReferTime
}

View File

@ -2,14 +2,16 @@ package benefactorkindboxreqparam
import (
entity "git.gocasts.ir/ebhomengo/niki/entity"
"time"
)
type KindBoxReqAddRequest struct {
BenefactorID uint `json:"benefactor_id" example:"1"`
TypeID entity.KindBoxType `json:"type_id" example:"1"`
DeliverAddressID uint `json:"deliver_address_id" example:"1"`
DeliverReferDate string `json:"deliver_refer_date" example:"2025-01-02 15:04:05"`
CountRequested uint `json:"count_requested" example:"2"`
BenefactorID uint `json:"benefactor_id" example:"1"`
TypeID entity.KindBoxType `json:"type_id" example:"1"`
DeliverAddressID uint `json:"deliver_address_id" example:"1"`
DeliverReferDate time.Time `json:"deliver_refer_date" example:"2025-01-02T15:04:05Z"`
DeliverReferTimeID uint `json:"deliver_refer_time_id" example:"1"`
CountRequested uint `json:"count_requested" example:"2"`
}
type KindBoxReqAddResponse struct {

View File

@ -9,7 +9,7 @@ import (
func (d DB) DeleteKindBoxReqByID(ctx context.Context, kindBoxReqID uint) error {
const op = richerror.Op("mysqlkindboxreq.DeleteKindBoxReqByID")
_, dErr := d.conn.Conn().ExecContext(ctx, "update kind_box_reqs set deleted_at = ? where id = ? ", time.Now(), kindBoxReqID)
_, dErr := d.conn.Conn().ExecContext(ctx, "update kind_box_reqs set deleted_at = ? where id = ? and deleted_at is null", time.Now(), kindBoxReqID)
if dErr != nil {
return richerror.New(op).WithErr(dErr).
WithMessage(errmsg.ErrorMsgSomethingWentWrong).WithKind(richerror.KindUnexpected)

View File

@ -0,0 +1,13 @@
-- +migrate Up
CREATE TABLE `refer_times` (
`id` INT PRIMARY KEY AUTO_INCREMENT,
`duration` VARCHAR(191) NOT NULL,
`status` ENUM('active','inactive') NOT NULL DEFAULT 'active',
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`deleted_at` TIMESTAMP
);
-- +migrate Down
DROP TABLE `refer_times`;

View File

@ -7,6 +7,7 @@ CREATE TABLE `kind_box_reqs` (
`count_accepted` INT UNSIGNED,
`description` TEXT,
`status` ENUM('pending','accepted','assigned-sender-agent','rejected','delivered') NOT NULL DEFAULT 'pending',
`deliver_refer_time_id` INT NOT NULL,
`deliver_refer_date` DATETIME NOT NULL,
`deliver_address_id` INT NOT NULL,
`sender_agent_id` INT,
@ -15,9 +16,10 @@ CREATE TABLE `kind_box_reqs` (
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`deleted_at` TIMESTAMP,
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 (`benefactor_id`) REFERENCES `benefactors` (`id`),
FOREIGN KEY (`deliver_refer_time_id`) REFERENCES `refer_times` (`id`),
FOREIGN KEY (`deliver_address_id`) REFERENCES `addresses` (`id`),
FOREIGN KEY (`sender_agent_id`) REFERENCES `admins` (`id`)
);
-- +migrate Down

View File

@ -0,0 +1,16 @@
-- +migrate Up
INSERT INTO `refer_times` (`id`,`duration`,`status`)
VALUES
(DEFAULT,'8-10 am',DEFAULT),
(DEFAULT,'10-12 am',DEFAULT),
(DEFAULT,'12-2 pm',DEFAULT),
(DEFAULT,'2-4 pm',DEFAULT),
(DEFAULT,'4-6 pm',DEFAULT),
(DEFAULT,'6-8 pm',DEFAULT),
(DEFAULT,'8-10 pm',DEFAULT),
(DEFAULT,'10-12 pm',DEFAULT);
-- +migrate Down
DELETE
FROM `refer_times`
WHERE id BETWEEN 1 AND 8;

View File

@ -0,0 +1,13 @@
package mysqlrefertime
import "git.gocasts.ir/ebhomengo/niki/repository/mysql"
type DB struct {
conn *mysql.DB
}
func New(conn *mysql.DB) *DB {
return &DB{
conn: conn,
}
}

View File

@ -0,0 +1,20 @@
package mysqlrefertime
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) Get(ctx context.Context, referTimeID uint) (entity.ReferTime, error) {
const op = richerror.Op("mysqlrefertime.Get")
row := d.conn.Conn().QueryRowContext(ctx, `select * from refer_times where id = ?`, referTimeID)
r, err := scanReferTime(row)
if err != nil {
return entity.ReferTime{}, richerror.New(op).WithErr(err).
WithMessage(errmsg.ErrorMsgCantScanQueryResult).WithKind(richerror.KindUnexpected)
}
return r, nil
}

View File

@ -0,0 +1,31 @@
package mysqlrefertime
import (
"database/sql"
"git.gocasts.ir/ebhomengo/niki/entity"
"git.gocasts.ir/ebhomengo/niki/repository/mysql"
"time"
)
func scanReferTime(scanner mysql.Scanner) (entity.ReferTime, error) {
var referTime entity.ReferTime
var (
status string
createdAt time.Time
updatedAt time.Time
deletedAt sql.NullTime
)
err := scanner.Scan(
&referTime.ID,
&referTime.Duration,
&status,
&createdAt,
&updatedAt,
&deletedAt,
)
if err != nil {
return entity.ReferTime{}, err
}
referTime.Status = entity.MapToReferTimeStatus(status)
return referTime, nil
}

View File

@ -0,0 +1,16 @@
package adminrefertimeservice
import (
"context"
param "git.gocasts.ir/ebhomengo/niki/param/admin/refer_time"
richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"
)
func (s Service) GetReferTimeByID(ctx context.Context, req param.GetReferTimeRequest) (param.GetReferTimeResponse, error) {
const op = richerror.Op("refertimeservice.GetReferTimeByID")
referTime, gErr := s.repo.Get(ctx, req.ReferTimeID)
if gErr != nil {
return param.GetReferTimeResponse{}, richerror.New(op).WithErr(gErr).WithKind(richerror.KindUnexpected)
}
return param.GetReferTimeResponse{ReferTime: referTime}, nil
}

View File

@ -0,0 +1,17 @@
package adminrefertimeservice
import (
"context"
"git.gocasts.ir/ebhomengo/niki/entity"
)
type Service struct {
repo Repository
}
type Repository interface {
Get(ctx context.Context, referTimeID uint) (entity.ReferTime, error)
}
func New(repo Repository) Service {
return Service{repo: repo}
}

View File

@ -2,8 +2,6 @@ package benefactorkindboxreqservice
import (
"context"
"time"
"git.gocasts.ir/ebhomengo/niki/entity"
param "git.gocasts.ir/ebhomengo/niki/param/benefactor/kind_box_req"
richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"
@ -11,17 +9,15 @@ import (
func (s Service) Add(ctx context.Context, req param.KindBoxReqAddRequest) (param.KindBoxReqAddResponse, error) {
const op = "userkindboxreqservice.Add"
t, tErr := time.Parse(time.DateTime, req.DeliverReferDate)
if tErr != nil {
return param.KindBoxReqAddResponse{}, richerror.New(op).WithErr(tErr).WithKind(richerror.KindInvalid)
}
kindBoxReq, err := s.repo.AddKindBoxReq(ctx, entity.KindBoxReq{
BenefactorID: req.BenefactorID,
KindBoxType: req.TypeID,
DeliverAddressID: req.DeliverAddressID,
DeliverReferDate: t,
CountRequested: req.CountRequested,
Status: entity.KindBoxReqPendingStatus,
BenefactorID: req.BenefactorID,
KindBoxType: req.TypeID,
DeliverAddressID: req.DeliverAddressID,
DeliverReferDate: req.DeliverReferDate,
DeliverReferTimeID: req.DeliverReferTimeID,
CountRequested: req.CountRequested,
Status: entity.KindBoxReqPendingStatus,
})
if err != nil {
return param.KindBoxReqAddResponse{}, richerror.New(op).WithErr(err).WithKind(richerror.KindUnexpected)

View File

@ -8,7 +8,7 @@ import (
validation "github.com/go-ozzo/ozzo-validation/v4"
)
func (v Validator) ValidateAddRequest(req param.KindBoxReqAddRequest) *ValidatorError {
func (v Validator) ValidateAddRequest(req param.KindBoxReqAddRequest) (map[string]string, error) {
const op = "userkindboxreqvalidator.ValidateAddRequest"
if err := validation.ValidateStruct(&req,
@ -31,6 +31,10 @@ func (v Validator) ValidateAddRequest(req param.KindBoxReqAddRequest) *Validator
validation.Required,
validation.By(v.isDateValid),
),
validation.Field(&req.DeliverReferTimeID,
validation.Required,
validation.By(v.isReferTimeIDValid),
),
); err != nil {
fieldErrors := make(map[string]string)
@ -44,16 +48,13 @@ func (v Validator) ValidateAddRequest(req param.KindBoxReqAddRequest) *Validator
}
}
return &ValidatorError{
Fields: fieldErrors,
Err: richerror.New(op).
WithMessage(errmsg.ErrorMsgInvalidInput).
WithKind(richerror.KindInvalid).
WithMeta(map[string]interface{}{"req": req}).
WithErr(err),
}
return fieldErrors, richerror.New(op).
WithMessage(errmsg.ErrorMsgInvalidInput).
WithKind(richerror.KindInvalid).
WithMeta(map[string]interface{}{"req": req}).
WithErr(err)
}
return nil
return map[string]string{}, nil
}

View File

@ -4,6 +4,7 @@ import (
"context"
"fmt"
"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"
@ -24,6 +25,10 @@ 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 Repository interface {
GetKindBoxReqByID(ctx context.Context, kindBoxReqID uint) (entity.KindBoxReq, error)
}
@ -31,6 +36,7 @@ type Repository interface {
type Validator struct {
benefactorSvc BenefactorSvc
addressSvc AddressSvc
referTimeSvc ReferTimeSvc
repo Repository
}
@ -49,8 +55,8 @@ func (v ValidatorError) Error() string {
return err
}
func New(benefactorSvc BenefactorSvc, addressSvc AddressSvc, repo Repository) Validator {
return Validator{benefactorSvc: benefactorSvc, addressSvc: addressSvc, repo: repo}
func New(benefactorSvc BenefactorSvc, addressSvc AddressSvc, referTimeSvc ReferTimeSvc,repo Repository) Validator {
return Validator{benefactorSvc: benefactorSvc, addressSvc: addressSvc, referTimeSvc: referTimeSvc,repo:repo}
}
func (v Validator) doesBenefactorExist(value interface{}) error {
@ -100,21 +106,34 @@ func (v Validator) doesAddressExist(benefactorID uint) validation.RuleFunc {
}
func (v Validator) isDateValid(value interface{}) error {
date, ok := value.(string)
date, ok := value.(time.Time)
if !ok {
return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong)
}
t, err := time.Parse(time.DateTime, date)
if err != nil {
return fmt.Errorf(errmsg.ErrorMsgInvalidInput)
}
if t.Before(time.Now()) {
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) doesKindBoxBelongToBenefactor(benefactorID uint) validation.RuleFunc {
return func(value interface{}) error {
kindBoxReqID, ok := value.(uint)