forked from ebhomengo/niki
1
0
Fork 0

feat(niki): implement notification for benefactor (#119)

This commit is contained in:
Ruhollah 2024-08-16 21:07:37 +03:30
parent 3ff9d13da1
commit 41164f6cee
15 changed files with 114 additions and 16 deletions

View File

@ -6,6 +6,7 @@ import (
"git.gocasts.ir/ebhomengo/niki/repository/mysql" "git.gocasts.ir/ebhomengo/niki/repository/mysql"
authservice "git.gocasts.ir/ebhomengo/niki/service/auth" authservice "git.gocasts.ir/ebhomengo/niki/service/auth"
benefactorservice "git.gocasts.ir/ebhomengo/niki/service/benefactor/benefactor" benefactorservice "git.gocasts.ir/ebhomengo/niki/service/benefactor/benefactor"
"git.gocasts.ir/ebhomengo/niki/service/notification"
) )
type HTTPServer struct { type HTTPServer struct {
@ -20,4 +21,5 @@ type Config struct {
Redis redis.Config `koanf:"redis"` Redis redis.Config `koanf:"redis"`
KavenegarSmsProvider smsprovider.Config `koanf:"kavenegar_sms_provider"` KavenegarSmsProvider smsprovider.Config `koanf:"kavenegar_sms_provider"`
BenefactorSvc benefactorservice.Config `koanf:"benefactor_service"` BenefactorSvc benefactorservice.Config `koanf:"benefactor_service"`
NotificationSvc notification.Config `koanf:"notification_service"`
} }

View File

@ -6,11 +6,12 @@ const (
OtpChars = "0123456789" OtpChars = "0123456789"
OtpExpireTime time.Duration = 2 * 60 * 1000 * 1000000 // 2 minutes OtpExpireTime time.Duration = 2 * 60 * 1000 * 1000000 // 2 minutes
JwtSignKey = "jwt_secret"
AccessTokenSubject = "ac" AccessTokenSubject = "ac"
RefreshTokenSubject = "rt" RefreshTokenSubject = "rt"
AccessTokenExpireDuration = time.Hour * 24 AccessTokenExpireDuration = time.Hour * 24
RefreshTokenExpireDuration = time.Hour * 24 * 7 RefreshTokenExpireDuration = time.Hour * 24 * 7
AuthMiddlewareContextKey = "claims" AuthMiddlewareContextKey = "claims"
BcryptCost = 3 BcryptCost = 3
NotificationTimeout = time.Second * 10
) )

View File

@ -3,6 +3,7 @@ package config
import ( import (
authservice "git.gocasts.ir/ebhomengo/niki/service/auth" authservice "git.gocasts.ir/ebhomengo/niki/service/auth"
benefactorservice "git.gocasts.ir/ebhomengo/niki/service/benefactor/benefactor" benefactorservice "git.gocasts.ir/ebhomengo/niki/service/benefactor/benefactor"
"git.gocasts.ir/ebhomengo/niki/service/notification"
) )
func Default() Config { func Default() Config {
@ -19,11 +20,13 @@ func Default() Config {
AccessSubject: AccessTokenSubject, AccessSubject: AccessTokenSubject,
RefreshSubject: RefreshTokenSubject, RefreshSubject: RefreshTokenSubject,
}, },
BenefactorSvc: benefactorservice.Config{ BenefactorSvc: benefactorservice.Config{
OtpChars: OtpChars, OtpChars: OtpChars,
OtpExpireTime: OtpExpireTime, OtpExpireTime: OtpExpireTime,
}, },
NotificationSvc: notification.Config{
Timeout: NotificationTimeout,
},
} }
return cfx return cfx

View File

@ -3,18 +3,22 @@ package benefactorkindboxhandler
import ( import (
authservice "git.gocasts.ir/ebhomengo/niki/service/auth" authservice "git.gocasts.ir/ebhomengo/niki/service/auth"
benefactorkindboxservice "git.gocasts.ir/ebhomengo/niki/service/benefactor/kind_box" benefactorkindboxservice "git.gocasts.ir/ebhomengo/niki/service/benefactor/kind_box"
"git.gocasts.ir/ebhomengo/niki/service/notification"
) )
type Handler struct { type Handler struct {
authSvc authservice.Service authSvc authservice.Service
benefactorKindBoxSvc benefactorkindboxservice.Service benefactorKindBoxSvc benefactorkindboxservice.Service
notificationSvc notification.Service
} }
func New(authSvc authservice.Service, func New(authSvc authservice.Service,
benefactorKindBoxSvc benefactorkindboxservice.Service, benefactorKindBoxSvc benefactorkindboxservice.Service,
notificationSvc notification.Service,
) Handler { ) Handler {
return Handler{ return Handler{
authSvc: authSvc, authSvc: authSvc,
benefactorKindBoxSvc: benefactorKindBoxSvc, benefactorKindBoxSvc: benefactorKindBoxSvc,
notificationSvc: notificationSvc,
} }
} }

View File

@ -3,6 +3,7 @@ package benefactorkindboxhandler
import ( import (
"net/http" "net/http"
params "git.gocasts.ir/ebhomengo/niki/param"
param "git.gocasts.ir/ebhomengo/niki/param/benefactor/kind_box" param "git.gocasts.ir/ebhomengo/niki/param/benefactor/kind_box"
"git.gocasts.ir/ebhomengo/niki/pkg/claim" "git.gocasts.ir/ebhomengo/niki/pkg/claim"
httpmsg "git.gocasts.ir/ebhomengo/niki/pkg/http_msg" httpmsg "git.gocasts.ir/ebhomengo/niki/pkg/http_msg"
@ -42,5 +43,9 @@ func (h Handler) RegisterEmptyingRequest(c echo.Context) error {
return echo.NewHTTPError(code, msg) return echo.NewHTTPError(code, msg)
} }
go h.notificationSvc.KindBoxRegisteredEmptyingRequest(params.NotificationKindBoxRegisteredEmptyingRequest{
KindBoxID: resp.ID,
})
return c.JSON(http.StatusNoContent, nil) return c.JSON(http.StatusNoContent, nil)
} }

View File

@ -3,6 +3,7 @@ package benefactorkindboxreqhandler
import ( import (
"net/http" "net/http"
params "git.gocasts.ir/ebhomengo/niki/param"
param "git.gocasts.ir/ebhomengo/niki/param/benefactor/kind_box_req" param "git.gocasts.ir/ebhomengo/niki/param/benefactor/kind_box_req"
"git.gocasts.ir/ebhomengo/niki/pkg/claim" "git.gocasts.ir/ebhomengo/niki/pkg/claim"
errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg" errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg"
@ -44,5 +45,9 @@ func (h Handler) Add(c echo.Context) error {
return echo.NewHTTPError(code, msg) return echo.NewHTTPError(code, msg)
} }
go h.notificationSvc.KindBoxReqAdded(params.NotificationKindBoxReqAdded{
KindBoxReqID: resp.KindBoxReq.ID,
})
return c.JSON(http.StatusCreated, resp) return c.JSON(http.StatusCreated, resp)
} }

View File

@ -3,18 +3,22 @@ package benefactorkindboxreqhandler
import ( import (
authservice "git.gocasts.ir/ebhomengo/niki/service/auth" authservice "git.gocasts.ir/ebhomengo/niki/service/auth"
benefactorkindboxreqservice "git.gocasts.ir/ebhomengo/niki/service/benefactor/kind_box_req" benefactorkindboxreqservice "git.gocasts.ir/ebhomengo/niki/service/benefactor/kind_box_req"
"git.gocasts.ir/ebhomengo/niki/service/notification"
) )
type Handler struct { type Handler struct {
authSvc authservice.Service authSvc authservice.Service
benefactorKindBoxReqSvc benefactorkindboxreqservice.Service benefactorKindBoxReqSvc benefactorkindboxreqservice.Service
notificationSvc notification.Service
} }
func New(authSvc authservice.Service, func New(authSvc authservice.Service,
benefactorKindBoxReqSvc benefactorkindboxreqservice.Service, benefactorKindBoxReqSvc benefactorkindboxreqservice.Service,
notificationSvc notification.Service,
) Handler { ) Handler {
return Handler{ return Handler{
authSvc: authSvc, authSvc: authSvc,
benefactorKindBoxReqSvc: benefactorKindBoxReqSvc, benefactorKindBoxReqSvc: benefactorKindBoxReqSvc,
notificationSvc: notificationSvc,
} }
} }

View File

@ -47,9 +47,9 @@ func New(
adminAgentHandler: adminagenthandler.New(svc.AdminAuthSvc, svc.AdminAgentSvc, svc.AdminAuthorizeSvc), adminAgentHandler: adminagenthandler.New(svc.AdminAuthSvc, svc.AdminAgentSvc, svc.AdminAuthorizeSvc),
agentKindBoxHandler: agentkindboxhandler.New(svc.AdminAuthSvc, svc.AgentKindBoxSvc, svc.AdminAuthorizeSvc), agentKindBoxHandler: agentkindboxhandler.New(svc.AdminAuthSvc, svc.AgentKindBoxSvc, svc.AdminAuthorizeSvc),
benefactorHandler: benefactorhandler.New(svc.BenefactorAuthSvc, svc.BenefactorSvc), benefactorHandler: benefactorhandler.New(svc.BenefactorAuthSvc, svc.BenefactorSvc),
benefactorKindBoxReqHandler: benefactorkindboxreqhandler.New(svc.BenefactorAuthSvc, svc.BenefactorKindBoxReqSvc), benefactorKindBoxReqHandler: benefactorkindboxreqhandler.New(svc.BenefactorAuthSvc, svc.BenefactorKindBoxReqSvc, svc.NotificationSvc),
benefactorAddressHandler: benefactoraddresshandler.New(svc.BenefactorAuthSvc, svc.BenefactorAddressSvc), benefactorAddressHandler: benefactoraddresshandler.New(svc.BenefactorAuthSvc, svc.BenefactorAddressSvc),
benefactorKindBoxHandler: benefactorkindboxhandler.New(svc.BenefactorAuthSvc, svc.BenefactorKindBoxSvc), benefactorKindBoxHandler: benefactorkindboxhandler.New(svc.BenefactorAuthSvc, svc.BenefactorKindBoxSvc, svc.NotificationSvc),
} }
} }

View File

@ -1,5 +1,9 @@
package param package param
type NotificationKindBoxReqAdded struct {
KindBoxReqID uint
}
type NotificationKindBoxReqAccepted struct { type NotificationKindBoxReqAccepted struct {
KindBoxReqID uint KindBoxReqID uint
} }
@ -13,6 +17,10 @@ type NotificationKindBoxReqAssigned struct {
KindBoxReqID uint KindBoxReqID uint
} }
type NotificationKindBoxRegisteredEmptyingRequest struct {
KindBoxID uint
}
type NotificationKindBoxAssigned struct { type NotificationKindBoxAssigned struct {
ReceiverAgentID uint ReceiverAgentID uint
} }

View File

@ -1,9 +1,11 @@
package smsmsg package smsmsg
const ( const (
SmsMsgKindBoxReqAccepted = "%s عزیز، درخواست قلک شما پذیرفته شد" SmsMsgKindBoxReqAdded = "%s عزیز، درخواست قلک شما ثبت شد"
SmsMsgKindBoxReqRejected = "%s عزیز، درخواست قلک شما به دلیل %s پذیرفته نشد" SmsMsgKindBoxReqAccepted = "%s عزیز، درخواست قلک شما پذیرفته شد"
SmsMsgKindBoxReqAssigned = "%s عزیز، درخواست قلک شماره %d جهت تحویل به نیکوکار به شما اختصاص داده شد" SmsMsgKindBoxReqRejected = "%s عزیز، درخواست قلک شما به دلیل %s پذیرفته نشد"
SmsMsgKindBoxAssigned = "%s عزیز، قلکی جهت تخلیه به شما اختصاص داده شد" SmsMsgKindBoxReqAssigned = "%s عزیز، درخواست قلک شماره %d جهت تحویل به نیکوکار به شما اختصاص داده شد"
SmsMsgKindBoxEnumerated = "%s عزیز، قلک شما با شماره سریال %s و مبلغ %d تومان شمارش شد. از مشارکت شما سپاسگزاریم." SmsMsgKindBoxRegistedEmptyingRequest = "%s عزیز، درخواست خالی کردن قلک شما ثبت شد"
SmsMsgKindBoxAssigned = "%s عزیز، قلکی جهت تخلیه به شما اختصاص داده شد"
SmsMsgKindBoxEnumerated = "%s عزیز، قلک شما با شماره سریال %s و مبلغ %d تومان شمارش شد. از مشارکت شما سپاسگزاریم."
) )

View File

@ -0,0 +1,30 @@
package notification
import (
"context"
"fmt"
params "git.gocasts.ir/ebhomengo/niki/param"
bnfparam "git.gocasts.ir/ebhomengo/niki/param/admin/benefactor"
kbp "git.gocasts.ir/ebhomengo/niki/param/admin/kind_box"
smsmsg "git.gocasts.ir/ebhomengo/niki/pkg/sms_msg"
)
func (s Service) KindBoxRegisteredEmptyingRequest(req params.NotificationKindBoxRegisteredEmptyingRequest) {
const op = "notification.KindBoxRegisteredEmptyingRequest"
ctx, cancel := context.WithTimeout(context.Background(), s.cfg.Timeout)
defer cancel()
kb, err := s.KindBoxSvc.Get(ctx, kbp.KindBoxGetRequest{
KindBoxID: req.KindBoxID,
})
if err != nil {
fmt.Println(fmt.Errorf("error(%s):%w", op, err))
}
bnf, gErr := s.BenefactorSvc.GetByID(ctx, bnfparam.GetBenefactorByIDRequest{BenefactorID: kb.BenefactorID})
if gErr != nil {
fmt.Println(fmt.Errorf("error(%s):%w", op, gErr))
}
s.smsAdapter.Send(bnf.PhoneNumber, fmt.Sprintf(smsmsg.SmsMsgKindBoxRegistedEmptyingRequest, bnf.FirstName))
}

View File

@ -0,0 +1,30 @@
package notification
import (
"context"
"fmt"
params "git.gocasts.ir/ebhomengo/niki/param"
bnfparam "git.gocasts.ir/ebhomengo/niki/param/admin/benefactor"
kbparam "git.gocasts.ir/ebhomengo/niki/param/admin/kind_box_req"
smsmsg "git.gocasts.ir/ebhomengo/niki/pkg/sms_msg"
)
func (s Service) KindBoxReqAdded(req params.NotificationKindBoxReqAdded) {
const op = "notification.KindBoxReqAdded"
ctx, cancel := context.WithTimeout(context.Background(), s.cfg.Timeout)
defer cancel()
kb, err := s.KindBoxReqSvc.Get(ctx, kbparam.GetKindBoxReqRequest{
KindBoxID: req.KindBoxReqID,
})
if err != nil {
fmt.Println(fmt.Errorf("error(%s):%w", op, err))
}
bnf, gErr := s.BenefactorSvc.GetByID(ctx, bnfparam.GetBenefactorByIDRequest{BenefactorID: kb.BenefactorID})
if gErr != nil {
fmt.Println(fmt.Errorf("error(%s):%w", op, gErr))
}
s.smsAdapter.Send(bnf.PhoneNumber, fmt.Sprintf(smsmsg.SmsMsgKindBoxReqAdded, bnf.FirstName))
}

View File

@ -2,6 +2,7 @@ package notification
import ( import (
"context" "context"
"time"
smscontract "git.gocasts.ir/ebhomengo/niki/contract/sms" smscontract "git.gocasts.ir/ebhomengo/niki/contract/sms"
param "git.gocasts.ir/ebhomengo/niki/param/admin/admin" param "git.gocasts.ir/ebhomengo/niki/param/admin/admin"
@ -10,6 +11,10 @@ import (
adminkindboxreqparam "git.gocasts.ir/ebhomengo/niki/param/admin/kind_box_req" adminkindboxreqparam "git.gocasts.ir/ebhomengo/niki/param/admin/kind_box_req"
) )
type Config struct {
Timeout time.Duration `koanf:"timeout"`
}
type KindBoxReqSvc interface { type KindBoxReqSvc interface {
Get(ctx context.Context, request adminkindboxreqparam.GetKindBoxReqRequest) (adminkindboxreqparam.GetKindBoxReqResponse, error) Get(ctx context.Context, request adminkindboxreqparam.GetKindBoxReqRequest) (adminkindboxreqparam.GetKindBoxReqResponse, error)
} }
@ -27,6 +32,7 @@ type KindBoxSvc interface {
} }
type Service struct { type Service struct {
cfg Config
smsAdapter smscontract.SmsAdapter smsAdapter smscontract.SmsAdapter
KindBoxReqSvc KindBoxReqSvc KindBoxReqSvc KindBoxReqSvc
BenefactorSvc BenefactorSvc BenefactorSvc BenefactorSvc
@ -34,10 +40,11 @@ type Service struct {
KindBoxSvc KindBoxSvc KindBoxSvc KindBoxSvc
} }
func New(smsAdapter smscontract.SmsAdapter, kindBoxReqSvc KindBoxReqSvc, benefactorSvc BenefactorSvc, func New(cfg Config, smsAdapter smscontract.SmsAdapter, kindBoxReqSvc KindBoxReqSvc, benefactorSvc BenefactorSvc,
adminSvc AdminSvc, kindBoxSvc KindBoxSvc, adminSvc AdminSvc, kindBoxSvc KindBoxSvc,
) Service { ) Service {
return Service{ return Service{
cfg: cfg,
smsAdapter: smsAdapter, smsAdapter: smsAdapter,
KindBoxReqSvc: kindBoxReqSvc, KindBoxReqSvc: kindBoxReqSvc,
BenefactorSvc: benefactorSvc, BenefactorSvc: benefactorSvc,

View File

@ -98,7 +98,7 @@ func New(cfg config.Config, db *mysql.DB, rds *redis.Adapter, smsAdapter smscont
BenefactorKindBoxVld = benefactorkindboxvalidator.New(kindBoxRepo, BenefactorSvc, BenefactorAddressSvc, BenefactorReferTimeSvc) BenefactorKindBoxVld = benefactorkindboxvalidator.New(kindBoxRepo, BenefactorSvc, BenefactorAddressSvc, BenefactorReferTimeSvc)
BenefactorKindBoxSvc = benefactorkindboxservice.New(kindBoxRepo, BenefactorKindBoxVld) BenefactorKindBoxSvc = benefactorkindboxservice.New(kindBoxRepo, BenefactorKindBoxVld)
) )
NotificationSvc := notification.New(smsAdapter, AdminKindBoxReqSvc, AdminBenefactorSvc, AdminSvc, AdminKindBoxSvc) NotificationSvc := notification.New(cfg.NotificationSvc, smsAdapter, AdminKindBoxReqSvc, AdminBenefactorSvc, AdminSvc, AdminKindBoxSvc)
return &Service{ return &Service{
AdminAuthSvc: AdminAuthSvc, AdminAuthSvc: AdminAuthSvc,

View File

@ -3,10 +3,10 @@ package adminvalidator
import ( import (
"context" "context"
"errors" "errors"
adminserviceparam "git.gocasts.ir/ebhomengo/niki/param/admin/admin"
errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg"
"testing" "testing"
adminserviceparam "git.gocasts.ir/ebhomengo/niki/param/admin/admin"
errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -18,7 +18,6 @@ func TestValidateLoginWithPhoneNumberRequest(t *testing.T) {
validPassword := "validpassword" validPassword := "validpassword"
t.Run("Valid request", func(t *testing.T) { t.Run("Valid request", func(t *testing.T) {
req := adminserviceparam.LoginWithPhoneNumberRequest{ req := adminserviceparam.LoginWithPhoneNumberRequest{
PhoneNumber: validPhoneNumber, PhoneNumber: validPhoneNumber,
Password: validPassword, Password: validPassword,
@ -32,7 +31,6 @@ func TestValidateLoginWithPhoneNumberRequest(t *testing.T) {
}) })
t.Run("Empty phone number", func(t *testing.T) { t.Run("Empty phone number", func(t *testing.T) {
req := adminserviceparam.LoginWithPhoneNumberRequest{ req := adminserviceparam.LoginWithPhoneNumberRequest{
PhoneNumber: "", PhoneNumber: "",
Password: validPassword, Password: validPassword,
@ -45,7 +43,6 @@ func TestValidateLoginWithPhoneNumberRequest(t *testing.T) {
}) })
t.Run("Empty password", func(t *testing.T) { t.Run("Empty password", func(t *testing.T) {
req := adminserviceparam.LoginWithPhoneNumberRequest{ req := adminserviceparam.LoginWithPhoneNumberRequest{
PhoneNumber: validPhoneNumber, PhoneNumber: validPhoneNumber,
Password: "", Password: "",