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

@ -10,6 +10,7 @@ type KindBoxReq struct {
CountAccepted uint
Description string
Status KindBoxReqStatus
DeliverReferTimeID uint
DeliverReferDate time.Time
DeliverAddressID uint
SenderAgentID uint

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,13 +2,15 @@ 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"`
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"`
}

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,
@ -16,6 +17,7 @@ CREATE TABLE `kind_box_reqs` (
`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_refer_time_id`) REFERENCES `refer_times` (`id`),
FOREIGN KEY (`deliver_address_id`) REFERENCES `addresses` (`id`),
FOREIGN KEY (`sender_agent_id`) REFERENCES `admins` (`id`)
);

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,15 +9,13 @@ 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,
DeliverReferDate: req.DeliverReferDate,
DeliverReferTimeID: req.DeliverReferTimeID,
CountRequested: req.CountRequested,
Status: entity.KindBoxReqPendingStatus,
})

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).
return fieldErrors, richerror.New(op).
WithMessage(errmsg.ErrorMsgInvalidInput).
WithKind(richerror.KindInvalid).
WithMeta(map[string]interface{}{"req": req}).
WithErr(err),
}
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)