generated from PenaSide/GolangTemplate
Merge remote-tracking branch 'origin/2servers' into staging
This commit is contained in:
commit
d93ac3785b
@ -3,8 +3,10 @@ JWT_ISSUER="pena-auth-service"
|
|||||||
JWT_AUDIENCE="pena"
|
JWT_AUDIENCE="pena"
|
||||||
JWT_PUBLIC_KEY="-----BEGIN PUBLIC KEY-----\nMIGeMA0GCSqGSIb3DQEBAQUAA4GMADCBiAKBgHgnvr7O2tiApjJfid1orFnIGm69\n80fZp+Lpbjo+NC/0whMFga2Biw5b1G2Q/B2u0tpO1Fs/E8z7Lv1nYfr5jx2S8x6B\ndA4TS2kB9Kf0wn0+7wSlyikHoKhbtzwXHZl17GsyEi6wHnsqNBSauyIWhpha8i+Y\n+3GyaOY536H47qyXAgMBAAE=\n-----END PUBLIC KEY-----"
|
JWT_PUBLIC_KEY="-----BEGIN PUBLIC KEY-----\nMIGeMA0GCSqGSIb3DQEBAQUAA4GMADCBiAKBgHgnvr7O2tiApjJfid1orFnIGm69\n80fZp+Lpbjo+NC/0whMFga2Biw5b1G2Q/B2u0tpO1Fs/E8z7Lv1nYfr5jx2S8x6B\ndA4TS2kB9Kf0wn0+7wSlyikHoKhbtzwXHZl17GsyEi6wHnsqNBSauyIWhpha8i+Y\n+3GyaOY536H47qyXAgMBAAE=\n-----END PUBLIC KEY-----"
|
||||||
|
|
||||||
HTTP_HOST=0.0.0.0
|
EXTERNAL_HTTP_HOST=0.0.0.0
|
||||||
HTTP_PORT=8082
|
EXTERNAL_HTTP_PORT=8082
|
||||||
|
INTERNAL_HTTP_HOST=0.0.0.0
|
||||||
|
INTERNAL_HTTP_PORT=8083
|
||||||
|
|
||||||
GRPC_HOST=0.0.0.0
|
GRPC_HOST=0.0.0.0
|
||||||
GRPC_PORT=9001
|
GRPC_PORT=9001
|
||||||
|
|||||||
@ -118,7 +118,7 @@ paths:
|
|||||||
schema:
|
schema:
|
||||||
$ref: "#/components/schemas/Error"
|
$ref: "#/components/schemas/Error"
|
||||||
|
|
||||||
/accounts:
|
/getList:
|
||||||
get:
|
get:
|
||||||
tags:
|
tags:
|
||||||
- account
|
- account
|
||||||
|
|||||||
@ -169,14 +169,22 @@ func Run(config *models.Config, logger *zap.Logger, build Build) (appErr error)
|
|||||||
MiddleWare: middleWare,
|
MiddleWare: middleWare,
|
||||||
})
|
})
|
||||||
|
|
||||||
serverHTTP := server.NewServer(server.ServerConfig{
|
serverClientHTTP := server.NewServer(server.ServerConfig{
|
||||||
Logger: logger,
|
Logger: logger,
|
||||||
Hlog: loggerHlog,
|
Hlog: loggerHlog,
|
||||||
Controllers: []server.Controller{httpControllers.CurrencyController, httpControllers.HistoryController, httpControllers.CartController, httpControllers.WalletController, httpControllers.AccountController},
|
Controllers: []server.Controller{httpControllers.CurrencyClientController, httpControllers.HistoryClientController, httpControllers.CartClientController, httpControllers.WalletClientController, httpControllers.AccountClientController},
|
||||||
JWTConfig: &config.Service.JWT,
|
JWTConfig: &config.Service.JWT,
|
||||||
})
|
})
|
||||||
|
|
||||||
serverHTTP.ListRoutes()
|
serverAdminHTTP := server.NewServer(server.ServerConfig{
|
||||||
|
Logger: logger,
|
||||||
|
Hlog: loggerHlog,
|
||||||
|
Controllers: []server.Controller{httpControllers.AccountAdminController, httpControllers.CurrencyAdminController, httpControllers.HistoryAdminController},
|
||||||
|
JWTConfig: &config.Service.JWT,
|
||||||
|
})
|
||||||
|
|
||||||
|
serverClientHTTP.ListRoutes()
|
||||||
|
serverAdminHTTP.ListRoutes()
|
||||||
|
|
||||||
serverGRPC, grpcErr := server.NewGRPC(server.DepsGRPC{Logger: logger})
|
serverGRPC, grpcErr := server.NewGRPC(server.DepsGRPC{Logger: logger})
|
||||||
if grpcErr != nil {
|
if grpcErr != nil {
|
||||||
@ -186,8 +194,15 @@ func Run(config *models.Config, logger *zap.Logger, build Build) (appErr error)
|
|||||||
serverGRPC.Register(rpcControllers)
|
serverGRPC.Register(rpcControllers)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
if err := serverHTTP.Start(config.HTTP.Host + ":" + config.HTTP.Port); err != nil {
|
if err := serverClientHTTP.Start(config.HTTP.ClientHost + ":" + config.HTTP.ClientPort); err != nil {
|
||||||
logger.Error("Server startup error", zap.Error(err))
|
logger.Error("Server external startup error", zap.Error(err))
|
||||||
|
cancel()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
if err := serverAdminHTTP.Start(config.HTTP.AdminHost + ":" + config.HTTP.AdminPort); err != nil {
|
||||||
|
logger.Error("Server internal startup error", zap.Error(err))
|
||||||
cancel()
|
cancel()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@ -195,7 +210,8 @@ func Run(config *models.Config, logger *zap.Logger, build Build) (appErr error)
|
|||||||
go serverGRPC.Run(&config.GRPC)
|
go serverGRPC.Run(&config.GRPC)
|
||||||
|
|
||||||
closer.Add(mongoDB.Client().Disconnect)
|
closer.Add(mongoDB.Client().Disconnect)
|
||||||
closer.Add(serverHTTP.Shutdown)
|
closer.Add(serverClientHTTP.Shutdown)
|
||||||
|
closer.Add(serverAdminHTTP.Shutdown)
|
||||||
closer.Add(serverGRPC.Stop)
|
closer.Add(serverGRPC.Stop)
|
||||||
closer.Add(closer.Wrap(kafkaTariffClient.Close))
|
closer.Add(closer.Wrap(kafkaTariffClient.Close))
|
||||||
|
|
||||||
|
|||||||
@ -62,8 +62,10 @@ func setDefaultTestingENV(t *testing.T) *models.Config {
|
|||||||
|
|
||||||
defaultConfiguration := models.Config{
|
defaultConfiguration := models.Config{
|
||||||
HTTP: models.ConfigurationHTTP{
|
HTTP: models.ConfigurationHTTP{
|
||||||
Host: "localhost",
|
ClientHost: "localhost",
|
||||||
Port: "8080",
|
ClientPort: "8080",
|
||||||
|
AdminHost: "localhost",
|
||||||
|
AdminPort: "8081",
|
||||||
},
|
},
|
||||||
GRPC: models.ConfigurationGRPC{
|
GRPC: models.ConfigurationGRPC{
|
||||||
Host: "localhost",
|
Host: "localhost",
|
||||||
|
|||||||
@ -8,11 +8,14 @@ import (
|
|||||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/grpc/customer"
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/grpc/customer"
|
||||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/grpc/payment"
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/grpc/payment"
|
||||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/http"
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/http"
|
||||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/http/account"
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/http/account_admin"
|
||||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/http/cart"
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/http/account_client"
|
||||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/http/currency"
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/http/cart_client"
|
||||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/http/history"
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/http/currency_admin"
|
||||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/http/wallet"
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/http/currency_client"
|
||||||
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/http/history_admin"
|
||||||
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/http/history_client"
|
||||||
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/http/wallet_client"
|
||||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -20,7 +23,7 @@ type RpcControllersDeps struct {
|
|||||||
Logger *zap.Logger
|
Logger *zap.Logger
|
||||||
Services *Services
|
Services *Services
|
||||||
Repositories *Repositories
|
Repositories *Repositories
|
||||||
HLogger hlog.Logger
|
HLogger hlog.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
type RpcControllers struct {
|
type RpcControllers struct {
|
||||||
@ -54,23 +57,32 @@ type HttpControllersDeps struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type HttpController struct {
|
type HttpController struct {
|
||||||
AccountController *account.AccountController
|
AccountClientController *account_client.AccountController
|
||||||
CartController *cart.CartController
|
AccountAdminController *account_admin.AccountInternalController
|
||||||
HistoryController *history.HistoryController
|
CartClientController *cart_client.CartController
|
||||||
WalletController *wallet.WalletController
|
CurrencyClientController *currency_client.CurrencyController
|
||||||
CurrencyController *currency.CurrencyController
|
CurrencyAdminController *currency_admin.CurrencyController
|
||||||
|
HistoryAdminController *history_admin.HistoryController
|
||||||
|
HistoryClientController *history_client.HistoryController
|
||||||
|
WalletClientController *wallet_client.WalletController
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHttpControllers(deps HttpControllersDeps) *HttpController {
|
func NewHttpControllers(deps HttpControllersDeps) *HttpController {
|
||||||
return &HttpController{
|
return &HttpController{
|
||||||
AccountController: account.NewAccountController(account.Deps{
|
AccountClientController: account_client.NewAccountController(account_client.Deps{
|
||||||
MiddleWare: deps.MiddleWare,
|
MiddleWare: deps.MiddleWare,
|
||||||
AccountRepo: deps.Repositories.AccountRepository,
|
AccountRepo: deps.Repositories.AccountRepository,
|
||||||
Logger: deps.Logger,
|
Logger: deps.Logger,
|
||||||
Encrypt: deps.Encrypt,
|
Encrypt: deps.Encrypt,
|
||||||
AuthClient: deps.Clients.AuthClient,
|
AuthClient: deps.Clients.AuthClient,
|
||||||
}),
|
}),
|
||||||
CartController: cart.NewCartController(cart.Deps{
|
AccountAdminController: account_admin.NewAccountInternalController(
|
||||||
|
account_admin.Deps{
|
||||||
|
MiddleWare: deps.MiddleWare,
|
||||||
|
AccountRepo: deps.Repositories.AccountRepository,
|
||||||
|
Logger: deps.Logger,
|
||||||
|
}),
|
||||||
|
CartClientController: cart_client.NewCartController(cart_client.Deps{
|
||||||
MiddleWare: deps.MiddleWare,
|
MiddleWare: deps.MiddleWare,
|
||||||
Logger: deps.Logger,
|
Logger: deps.Logger,
|
||||||
AccountRepo: deps.Repositories.AccountRepository,
|
AccountRepo: deps.Repositories.AccountRepository,
|
||||||
@ -80,7 +92,17 @@ func NewHttpControllers(deps HttpControllersDeps) *HttpController {
|
|||||||
CurrencyClient: deps.Clients.CurrencyClient,
|
CurrencyClient: deps.Clients.CurrencyClient,
|
||||||
Producer: deps.Producer,
|
Producer: deps.Producer,
|
||||||
}),
|
}),
|
||||||
HistoryController: history.NewHistoryController(history.Deps{
|
CurrencyClientController: currency_client.NewCurrencyController(currency_client.Deps{
|
||||||
|
CurrencyRepo: deps.Repositories.CurrencyRepository,
|
||||||
|
MiddleWare: deps.MiddleWare,
|
||||||
|
Logger: deps.Logger,
|
||||||
|
}),
|
||||||
|
CurrencyAdminController: currency_admin.NewCurrencyController(currency_admin.Deps{
|
||||||
|
CurrencyRepo: deps.Repositories.CurrencyRepository,
|
||||||
|
MiddleWare: deps.MiddleWare,
|
||||||
|
Logger: deps.Logger,
|
||||||
|
}),
|
||||||
|
HistoryAdminController: history_admin.NewHistoryController(history_admin.Deps{
|
||||||
MiddleWare: deps.MiddleWare,
|
MiddleWare: deps.MiddleWare,
|
||||||
HistoryRepo: deps.Repositories.HistoryRepository,
|
HistoryRepo: deps.Repositories.HistoryRepository,
|
||||||
AccountRepo: deps.Repositories.AccountRepository,
|
AccountRepo: deps.Repositories.AccountRepository,
|
||||||
@ -90,7 +112,17 @@ func NewHttpControllers(deps HttpControllersDeps) *HttpController {
|
|||||||
CodewordClient: deps.Clients.CodewordClient,
|
CodewordClient: deps.Clients.CodewordClient,
|
||||||
Logger: deps.Logger,
|
Logger: deps.Logger,
|
||||||
}),
|
}),
|
||||||
WalletController: wallet.NewWalletController(wallet.Deps{
|
HistoryClientController: history_client.NewHistoryController(history_client.Deps{
|
||||||
|
MiddleWare: deps.MiddleWare,
|
||||||
|
HistoryRepo: deps.Repositories.HistoryRepository,
|
||||||
|
AccountRepo: deps.Repositories.AccountRepository,
|
||||||
|
VerifyClient: deps.Clients.VerificationClient,
|
||||||
|
AuthClient: deps.Clients.AuthClient,
|
||||||
|
TemplateClient: deps.Clients.TemplateClient,
|
||||||
|
CodewordClient: deps.Clients.CodewordClient,
|
||||||
|
Logger: deps.Logger,
|
||||||
|
}),
|
||||||
|
WalletClientController: wallet_client.NewWalletController(wallet_client.Deps{
|
||||||
MiddleWare: deps.MiddleWare,
|
MiddleWare: deps.MiddleWare,
|
||||||
AuthClient: deps.Clients.AuthClient,
|
AuthClient: deps.Clients.AuthClient,
|
||||||
PaymentClient: deps.Clients.PaymentClient,
|
PaymentClient: deps.Clients.PaymentClient,
|
||||||
@ -101,10 +133,5 @@ func NewHttpControllers(deps HttpControllersDeps) *HttpController {
|
|||||||
MailClient: deps.Clients.MailClient,
|
MailClient: deps.Clients.MailClient,
|
||||||
Logger: deps.Logger,
|
Logger: deps.Logger,
|
||||||
}),
|
}),
|
||||||
CurrencyController: currency.NewCurrencyController(currency.Deps{
|
|
||||||
CurrencyRepo: deps.Repositories.CurrencyRepository,
|
|
||||||
MiddleWare: deps.MiddleWare,
|
|
||||||
Logger: deps.Logger,
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/twmb/franz-go/pkg/kgo"
|
|
||||||
"go.mongodb.org/mongo-driver/mongo/integration/mtest"
|
"go.mongodb.org/mongo-driver/mongo/integration/mtest"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/initialize"
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/initialize"
|
||||||
@ -34,22 +33,10 @@ func TestNewControllers(t *testing.T) {
|
|||||||
MongoDB: t.Client.Database("test"),
|
MongoDB: t.Client.Database("test"),
|
||||||
})
|
})
|
||||||
|
|
||||||
brokers := initialize.NewBrokers(initialize.BrokersDeps{
|
controllers := initialize.NewHttpControllers(initialize.HttpControllersDeps{
|
||||||
Logger: logger,
|
Logger: logger,
|
||||||
TariffClient: &kgo.Client{},
|
Repositories: repositories,
|
||||||
})
|
Clients: clients,
|
||||||
|
|
||||||
services := initialize.NewServices(initialize.ServicesDeps{
|
|
||||||
Logger: logger,
|
|
||||||
Clients: clients,
|
|
||||||
Repositories: repositories,
|
|
||||||
Brokers: brokers,
|
|
||||||
ConfigurationGRPC: &models.ConfigurationGRPC{Domen: "http://test:8080"},
|
|
||||||
})
|
|
||||||
|
|
||||||
controllers := initialize.NewControllers(initialize.ControllersDeps{
|
|
||||||
Logger: logger,
|
|
||||||
Services: services,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
assert.NotNil(t, controllers)
|
assert.NotNil(t, controllers)
|
||||||
|
|||||||
@ -0,0 +1,99 @@
|
|||||||
|
package account_admin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"math"
|
||||||
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/http"
|
||||||
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/repository"
|
||||||
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Deps struct {
|
||||||
|
MiddleWare *http.MiddleWare
|
||||||
|
AccountRepo *repository.AccountRepository
|
||||||
|
Logger *zap.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
type AccountInternalController struct {
|
||||||
|
middleWare *http.MiddleWare
|
||||||
|
accountRepo *repository.AccountRepository
|
||||||
|
logger *zap.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAccountInternalController(deps Deps) *AccountInternalController {
|
||||||
|
return &AccountInternalController{
|
||||||
|
middleWare: deps.MiddleWare,
|
||||||
|
accountRepo: deps.AccountRepo,
|
||||||
|
logger: deps.Logger,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (receiver *AccountInternalController) DeleteCurrent(ctx *fiber.Ctx) error {
|
||||||
|
userID := ctx.Params("userId")
|
||||||
|
if userID == "" {
|
||||||
|
return receiver.middleWare.Error(ctx, fiber.StatusBadRequest, "invalid format for parameter userId")
|
||||||
|
}
|
||||||
|
|
||||||
|
account, err := receiver.accountRepo.Remove(ctx.Context(), userID)
|
||||||
|
if err != nil {
|
||||||
|
return receiver.middleWare.ErrorOld(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx.Status(fiber.StatusOK).JSON(account)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (receiver *AccountInternalController) GetCurrent(ctx *fiber.Ctx) error {
|
||||||
|
userID := ctx.Params("userId")
|
||||||
|
if userID == "" {
|
||||||
|
return receiver.middleWare.Error(ctx, fiber.StatusBadRequest, "invalid format for parameter userId")
|
||||||
|
}
|
||||||
|
|
||||||
|
account, err := receiver.accountRepo.FindByUserID(ctx.Context(), userID)
|
||||||
|
if err != nil {
|
||||||
|
return receiver.middleWare.ErrorOld(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx.Status(fiber.StatusOK).JSON(account)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (receiver *AccountInternalController) Pagination(ctx *fiber.Ctx) error {
|
||||||
|
pageStr := ctx.Query("page", "1")
|
||||||
|
limitStr := ctx.Query("limit", "100")
|
||||||
|
|
||||||
|
page, err := strconv.ParseInt(pageStr, 10, 64)
|
||||||
|
if err != nil || page < 1 {
|
||||||
|
page = 1
|
||||||
|
}
|
||||||
|
limit, err := strconv.ParseInt(limitStr, 10, 64)
|
||||||
|
if err != nil || limit < 1 {
|
||||||
|
limit = models.DefaultLimit
|
||||||
|
} else {
|
||||||
|
limit = int64(math.Min(float64(limit), float64(models.DefaultLimit)))
|
||||||
|
}
|
||||||
|
|
||||||
|
count, err := receiver.accountRepo.CountAll(ctx.Context())
|
||||||
|
if err != nil {
|
||||||
|
return receiver.middleWare.ErrorOld(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if count == 0 {
|
||||||
|
response := models.PaginationResponse[models.Account]{TotalPages: 0, Records: []models.Account{}}
|
||||||
|
return ctx.Status(fiber.StatusOK).JSON(response)
|
||||||
|
}
|
||||||
|
|
||||||
|
totalPages := int64(math.Ceil(float64(count) / float64(limit)))
|
||||||
|
|
||||||
|
accounts, err := receiver.accountRepo.FindMany(ctx.Context(), page, limit)
|
||||||
|
if err != nil {
|
||||||
|
return receiver.middleWare.ErrorOld(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
response := models.PaginationResponse[models.Account]{
|
||||||
|
TotalPages: totalPages,
|
||||||
|
Records: accounts,
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx.Status(fiber.StatusOK).JSON(response)
|
||||||
|
}
|
||||||
13
internal/interface/controller/http/account_admin/route.go
Normal file
13
internal/interface/controller/http/account_admin/route.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package account_admin
|
||||||
|
|
||||||
|
import "github.com/gofiber/fiber/v2"
|
||||||
|
|
||||||
|
func (receiver *AccountInternalController) Register(router fiber.Router) {
|
||||||
|
router.Delete("/account/:userId", receiver.DeleteCurrent)
|
||||||
|
router.Get("/account/:userId", receiver.GetCurrent)
|
||||||
|
router.Get("/getList", receiver.Pagination)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (receiver *AccountInternalController) Name() string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package account
|
package account_client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
@ -7,7 +7,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"math"
|
|
||||||
"penahub.gitlab.yandexcloud.net/backend/penahub_common/log_mw"
|
"penahub.gitlab.yandexcloud.net/backend/penahub_common/log_mw"
|
||||||
qutils "penahub.gitlab.yandexcloud.net/backend/quiz/common.git/utils"
|
qutils "penahub.gitlab.yandexcloud.net/backend/quiz/common.git/utils"
|
||||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
|
||||||
@ -15,8 +14,6 @@ import (
|
|||||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/http"
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/http"
|
||||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/repository"
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/repository"
|
||||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Deps struct {
|
type Deps struct {
|
||||||
@ -181,74 +178,6 @@ func (receiver *AccountController) Create(ctx *fiber.Ctx) error {
|
|||||||
return ctx.Status(fiber.StatusOK).JSON(account)
|
return ctx.Status(fiber.StatusOK).JSON(account)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (receiver *AccountController) DeleteCurrent(ctx *fiber.Ctx) error {
|
|
||||||
userID := ctx.Params("userId")
|
|
||||||
if userID == "" {
|
|
||||||
return receiver.middleWare.Error(ctx, fiber.StatusBadRequest, "invalid format for parameter userId")
|
|
||||||
}
|
|
||||||
|
|
||||||
account, err := receiver.accountRepo.Remove(ctx.Context(), userID)
|
|
||||||
if err != nil {
|
|
||||||
return receiver.middleWare.ErrorOld(ctx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ctx.Status(fiber.StatusOK).JSON(account)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (receiver *AccountController) GetCurrent(ctx *fiber.Ctx) error {
|
|
||||||
userID := ctx.Params("userId")
|
|
||||||
if userID == "" {
|
|
||||||
return receiver.middleWare.Error(ctx, fiber.StatusBadRequest, "invalid format for parameter userId")
|
|
||||||
}
|
|
||||||
|
|
||||||
account, err := receiver.accountRepo.FindByUserID(ctx.Context(), userID)
|
|
||||||
if err != nil {
|
|
||||||
return receiver.middleWare.ErrorOld(ctx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ctx.Status(fiber.StatusOK).JSON(account)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (receiver *AccountController) Pagination(ctx *fiber.Ctx) error {
|
|
||||||
pageStr := ctx.Query("page", "1")
|
|
||||||
limitStr := ctx.Query("limit", "100")
|
|
||||||
|
|
||||||
page, err := strconv.ParseInt(pageStr, 10, 64)
|
|
||||||
if err != nil || page < 1 {
|
|
||||||
page = 1
|
|
||||||
}
|
|
||||||
limit, err := strconv.ParseInt(limitStr, 10, 64)
|
|
||||||
if err != nil || limit < 1 {
|
|
||||||
limit = models.DefaultLimit
|
|
||||||
} else {
|
|
||||||
limit = int64(math.Min(float64(limit), float64(models.DefaultLimit)))
|
|
||||||
}
|
|
||||||
|
|
||||||
count, err := receiver.accountRepo.CountAll(ctx.Context())
|
|
||||||
if err != nil {
|
|
||||||
return receiver.middleWare.ErrorOld(ctx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if count == 0 {
|
|
||||||
response := models.PaginationResponse[models.Account]{TotalPages: 0, Records: []models.Account{}}
|
|
||||||
return ctx.Status(fiber.StatusOK).JSON(response)
|
|
||||||
}
|
|
||||||
|
|
||||||
totalPages := int64(math.Ceil(float64(count) / float64(limit)))
|
|
||||||
|
|
||||||
accounts, err := receiver.accountRepo.FindMany(ctx.Context(), page, limit)
|
|
||||||
if err != nil {
|
|
||||||
return receiver.middleWare.ErrorOld(ctx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
response := models.PaginationResponse[models.Account]{
|
|
||||||
TotalPages: totalPages,
|
|
||||||
Records: accounts,
|
|
||||||
}
|
|
||||||
|
|
||||||
return ctx.Status(fiber.StatusOK).JSON(response)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (receiver *AccountController) AccountPipe(ctx *fiber.Ctx) error {
|
func (receiver *AccountController) AccountPipe(ctx *fiber.Ctx) error {
|
||||||
userID, ok := receiver.middleWare.ExtractUserID(ctx)
|
userID, ok := receiver.middleWare.ExtractUserID(ctx)
|
||||||
if !ok || userID == "" {
|
if !ok || userID == "" {
|
||||||
@ -271,8 +200,6 @@ func (receiver *AccountController) AccountPipe(ctx *fiber.Ctx) error {
|
|||||||
}(cancelCtx)
|
}(cancelCtx)
|
||||||
|
|
||||||
ctx.Status(fiber.StatusOK).Context().SetBodyStreamWriter(func(w *bufio.Writer) {
|
ctx.Status(fiber.StatusOK).Context().SetBodyStreamWriter(func(w *bufio.Writer) {
|
||||||
pingTicker := time.NewTicker(5 * time.Second)
|
|
||||||
defer pingTicker.Stop()
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case account, ok := <-accountCh:
|
case account, ok := <-accountCh:
|
||||||
@ -288,14 +215,6 @@ func (receiver *AccountController) AccountPipe(ctx *fiber.Ctx) error {
|
|||||||
if err := w.Flush(); err != nil {
|
if err := w.Flush(); err != nil {
|
||||||
receiver.logger.Error("error flushing", zap.Error(err))
|
receiver.logger.Error("error flushing", zap.Error(err))
|
||||||
cancel()
|
cancel()
|
||||||
receiver.logger.Info("Close connection Account Pipe sse")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
case <-pingTicker.C:
|
|
||||||
fmt.Fprintf(w, "data: %s\n\n", `{"event": "ping"}`)
|
|
||||||
if err := w.Flush(); err != nil {
|
|
||||||
receiver.logger.Error("error sending ping Account Pipe sse, close connection", zap.Error(err))
|
|
||||||
cancel()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package account
|
package account_client
|
||||||
|
|
||||||
import "github.com/gofiber/fiber/v2"
|
import "github.com/gofiber/fiber/v2"
|
||||||
|
|
||||||
@ -8,10 +8,7 @@ func (receiver *AccountController) Register(router fiber.Router) {
|
|||||||
router.Patch("/account", receiver.Update)
|
router.Patch("/account", receiver.Update)
|
||||||
router.Post("/account", receiver.Create)
|
router.Post("/account", receiver.Create)
|
||||||
router.Get("/account/pipe", receiver.AccountPipe)
|
router.Get("/account/pipe", receiver.AccountPipe)
|
||||||
router.Delete("/account/:userId", receiver.DeleteCurrent)
|
|
||||||
router.Get("/account/:userId", receiver.GetCurrent)
|
|
||||||
router.Patch("/account/:userId", receiver.SetVerificationStatus)
|
router.Patch("/account/:userId", receiver.SetVerificationStatus)
|
||||||
router.Get("/accounts", receiver.Pagination)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (receiver *AccountController) Name() string {
|
func (receiver *AccountController) Name() string {
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package cart
|
package cart_client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package cart
|
package cart_client
|
||||||
|
|
||||||
import "github.com/gofiber/fiber/v2"
|
import "github.com/gofiber/fiber/v2"
|
||||||
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package currency
|
package currency_admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
@ -29,19 +29,6 @@ func NewCurrencyController(deps Deps) *CurrencyController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (receiver *CurrencyController) Get(ctx *fiber.Ctx) error {
|
|
||||||
currencyList, err := receiver.currencyRepo.FindCurrenciesList(ctx.Context(), models.DefaultCurrencyListName)
|
|
||||||
if err != nil && err.Type() != errors.ErrNotFound {
|
|
||||||
return receiver.middleWare.ErrorOld(ctx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil && err.Type() == errors.ErrNotFound {
|
|
||||||
return ctx.Status(fiber.StatusOK).JSON([]string{})
|
|
||||||
}
|
|
||||||
|
|
||||||
return ctx.Status(fiber.StatusOK).JSON(currencyList)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (receiver *CurrencyController) Update(ctx *fiber.Ctx) error {
|
func (receiver *CurrencyController) Update(ctx *fiber.Ctx) error {
|
||||||
var req struct {
|
var req struct {
|
||||||
items []string
|
items []string
|
||||||
@ -1,9 +1,8 @@
|
|||||||
package currency
|
package currency_admin
|
||||||
|
|
||||||
import "github.com/gofiber/fiber/v2"
|
import "github.com/gofiber/fiber/v2"
|
||||||
|
|
||||||
func (receiver *CurrencyController) Register(router fiber.Router) {
|
func (receiver *CurrencyController) Register(router fiber.Router) {
|
||||||
router.Get("/currencies", receiver.Get)
|
|
||||||
router.Put("/currencies", receiver.Update)
|
router.Put("/currencies", receiver.Update)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
package currency_client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
|
||||||
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/http"
|
||||||
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/repository"
|
||||||
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Deps struct {
|
||||||
|
CurrencyRepo *repository.CurrencyRepository
|
||||||
|
MiddleWare *http.MiddleWare
|
||||||
|
Logger *zap.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
type CurrencyController struct {
|
||||||
|
currencyRepo *repository.CurrencyRepository
|
||||||
|
middleWare *http.MiddleWare
|
||||||
|
logger *zap.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCurrencyController(deps Deps) *CurrencyController {
|
||||||
|
return &CurrencyController{
|
||||||
|
currencyRepo: deps.CurrencyRepo,
|
||||||
|
middleWare: deps.MiddleWare,
|
||||||
|
logger: deps.Logger,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (receiver *CurrencyController) Get(ctx *fiber.Ctx) error {
|
||||||
|
currencyList, err := receiver.currencyRepo.FindCurrenciesList(ctx.Context(), models.DefaultCurrencyListName)
|
||||||
|
if err != nil && err.Type() != errors.ErrNotFound {
|
||||||
|
return receiver.middleWare.ErrorOld(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil && err.Type() == errors.ErrNotFound {
|
||||||
|
return ctx.Status(fiber.StatusOK).JSON([]string{})
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx.Status(fiber.StatusOK).JSON(currencyList)
|
||||||
|
}
|
||||||
11
internal/interface/controller/http/currency_client/route.go
Normal file
11
internal/interface/controller/http/currency_client/route.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package currency_client
|
||||||
|
|
||||||
|
import "github.com/gofiber/fiber/v2"
|
||||||
|
|
||||||
|
func (receiver *CurrencyController) Register(router fiber.Router) {
|
||||||
|
router.Get("/currencies", receiver.Get)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (receiver *CurrencyController) Name() string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
166
internal/interface/controller/http/history_admin/controllers.go
Normal file
166
internal/interface/controller/http/history_admin/controllers.go
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
package history_admin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/client"
|
||||||
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/http"
|
||||||
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/repository"
|
||||||
|
codeword_rpc "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/proto/codeword"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Deps struct {
|
||||||
|
MiddleWare *http.MiddleWare
|
||||||
|
HistoryRepo *repository.HistoryRepository
|
||||||
|
AccountRepo *repository.AccountRepository
|
||||||
|
VerifyClient *client.VerificationClient
|
||||||
|
AuthClient *client.AuthClient
|
||||||
|
TemplateClient *client.TemplateClient
|
||||||
|
CodewordClient *client.CodewordClient
|
||||||
|
Logger *zap.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
type HistoryController struct {
|
||||||
|
middleWare *http.MiddleWare
|
||||||
|
historyRepo *repository.HistoryRepository
|
||||||
|
accountRepo *repository.AccountRepository
|
||||||
|
verifyClient *client.VerificationClient
|
||||||
|
authClient *client.AuthClient
|
||||||
|
templateClient *client.TemplateClient
|
||||||
|
codewordClient *client.CodewordClient
|
||||||
|
logger *zap.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHistoryController(deps Deps) *HistoryController {
|
||||||
|
return &HistoryController{
|
||||||
|
middleWare: deps.MiddleWare,
|
||||||
|
historyRepo: deps.HistoryRepo,
|
||||||
|
authClient: deps.AuthClient,
|
||||||
|
accountRepo: deps.AccountRepo,
|
||||||
|
verifyClient: deps.VerifyClient,
|
||||||
|
templateClient: deps.TemplateClient,
|
||||||
|
codewordClient: deps.CodewordClient,
|
||||||
|
logger: deps.Logger,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (receiver *HistoryController) CalculateLTV(ctx *fiber.Ctx) error {
|
||||||
|
var req struct {
|
||||||
|
From int64 `json:"from"`
|
||||||
|
To int64 `json:"to"`
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.BodyParser(&req); err != nil {
|
||||||
|
receiver.logger.Error("failed to bind request", zap.Error(err))
|
||||||
|
return receiver.middleWare.Error(ctx, fiber.StatusBadRequest, "failed to bind request")
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.From > req.To && req.To != 0 {
|
||||||
|
receiver.logger.Error("From timestamp must be less than To timestamp unless To is 0")
|
||||||
|
return receiver.middleWare.Error(ctx, fiber.StatusBadRequest, "From timestamp must be less than To timestamp unless To is 0")
|
||||||
|
}
|
||||||
|
|
||||||
|
ltv, err := receiver.historyRepo.CalculateCustomerLTV(ctx.Context(), req.From, req.To)
|
||||||
|
if err != nil {
|
||||||
|
receiver.logger.Error("failed to calculate LTV", zap.Error(err))
|
||||||
|
return receiver.middleWare.ErrorOld(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
response := struct {
|
||||||
|
LTV int64 `json:"LTV"`
|
||||||
|
}{
|
||||||
|
LTV: ltv,
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx.Status(fiber.StatusOK).JSON(response)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (receiver *HistoryController) QuizLogoStat(ctx *fiber.Ctx) error {
|
||||||
|
var req struct {
|
||||||
|
From *int `json:"from,omitempty"`
|
||||||
|
Limit *int `json:"limit,omitempty"`
|
||||||
|
Page *int `json:"page,omitempty"`
|
||||||
|
To *int `json:"to,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.BodyParser(&req); err != nil {
|
||||||
|
receiver.logger.Error("failed to bind request", zap.Error(err))
|
||||||
|
return receiver.middleWare.Error(ctx, fiber.StatusBadRequest, "failed to bind request")
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := receiver.accountRepo.QuizLogoStat(ctx.Context(), repository.QuizLogoStatDeps{
|
||||||
|
Page: req.Page,
|
||||||
|
Limit: req.Limit,
|
||||||
|
From: req.From,
|
||||||
|
To: req.To,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return receiver.middleWare.Error(ctx, fiber.StatusInternalServerError, fmt.Sprint("failed getting quiz logo stat", err.Error()))
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx.Status(fiber.StatusOK).JSON(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (receiver *HistoryController) PromocodeLTV(ctx *fiber.Ctx) error {
|
||||||
|
var req struct {
|
||||||
|
From int `json:"from"`
|
||||||
|
To int `json:"to"`
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.BodyParser(&req); err != nil {
|
||||||
|
receiver.logger.Error("failed to bind request", zap.Error(err))
|
||||||
|
return receiver.middleWare.Error(ctx, fiber.StatusBadRequest, "failed to bind request")
|
||||||
|
}
|
||||||
|
|
||||||
|
// получаем мапу вида [promoID] = []{userid,timeActivate}
|
||||||
|
// отдаются только первые использованые на аккаунте промокоды, соответсвенно подсчет идет сугубо по ним
|
||||||
|
// если в запросе время различается с временем активации - если меньше, то учитывается только после применения
|
||||||
|
// если больше, то учитывается только с начала переданного from
|
||||||
|
codewordData, err := receiver.codewordClient.GetAllPromoActivations(ctx.Context(), &codeword_rpc.Time{
|
||||||
|
To: int64(req.To),
|
||||||
|
From: int64(req.From),
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return receiver.middleWare.Error(ctx, fiber.StatusInternalServerError, fmt.Sprint("failed getting codeword data", err.Error()))
|
||||||
|
}
|
||||||
|
|
||||||
|
userSumMap, er := receiver.historyRepo.GetPayUsersPromoHistory(ctx.Context(), codewordData, int64(req.From), int64(req.To))
|
||||||
|
if er != nil {
|
||||||
|
return receiver.middleWare.Error(ctx, fiber.StatusInternalServerError, fmt.Sprint("failed calculate promo users paid sum", er.Error()))
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := make(map[string]struct {
|
||||||
|
Regs int
|
||||||
|
Money int64
|
||||||
|
})
|
||||||
|
|
||||||
|
for promoID, data := range codewordData {
|
||||||
|
fmt.Println("PROTOMOTO", promoID, data)
|
||||||
|
for _, value := range data {
|
||||||
|
|
||||||
|
paids, ok := userSumMap[value.UserID]
|
||||||
|
if !ok {
|
||||||
|
paids = 0
|
||||||
|
}
|
||||||
|
fmt.Println("PROTOMOTO1", paids, value)
|
||||||
|
|
||||||
|
if value.Time >= int64(req.From) && value.Time <= int64(req.To) {
|
||||||
|
if _, ok := resp[promoID]; !ok {
|
||||||
|
resp[promoID] = struct {
|
||||||
|
Regs int
|
||||||
|
Money int64
|
||||||
|
}{Regs: 1, Money: paids}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
current := resp[promoID]
|
||||||
|
current.Regs += 1
|
||||||
|
current.Money += paids
|
||||||
|
resp[promoID] = current
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx.Status(fiber.StatusOK).JSON(resp)
|
||||||
|
}
|
||||||
@ -1,14 +1,11 @@
|
|||||||
package history
|
package history_admin
|
||||||
|
|
||||||
import "github.com/gofiber/fiber/v2"
|
import "github.com/gofiber/fiber/v2"
|
||||||
|
|
||||||
func (receiver *HistoryController) Register(router fiber.Router) {
|
func (receiver *HistoryController) Register(router fiber.Router) {
|
||||||
router.Get("/history", receiver.Get)
|
|
||||||
router.Post("/history/ltv", receiver.CalculateLTV)
|
router.Post("/history/ltv", receiver.CalculateLTV)
|
||||||
router.Post("/promocode/ltv", receiver.PromocodeLTV)
|
router.Post("/promocode/ltv", receiver.PromocodeLTV)
|
||||||
router.Post("/quizlogo/stat", receiver.QuizLogoStat)
|
router.Post("/quizlogo/stat", receiver.QuizLogoStat)
|
||||||
router.Get("/recent", receiver.GetRecentTariffs)
|
|
||||||
router.Post("/sendReport", receiver.SendReport)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (receiver *HistoryController) Name() string {
|
func (receiver *HistoryController) Name() string {
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package history
|
package history_client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -11,7 +11,6 @@ import (
|
|||||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/http"
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/http"
|
||||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/repository"
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/repository"
|
||||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
|
||||||
codeword_rpc "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/proto/codeword"
|
|
||||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/service/history"
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/service/history"
|
||||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/utils"
|
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/utils"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -117,37 +116,6 @@ func (receiver *HistoryController) Get(ctx *fiber.Ctx) error {
|
|||||||
return ctx.Status(fiber.StatusOK).JSON(returnHistories)
|
return ctx.Status(fiber.StatusOK).JSON(returnHistories)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (receiver *HistoryController) CalculateLTV(ctx *fiber.Ctx) error {
|
|
||||||
var req struct {
|
|
||||||
From int64 `json:"from"`
|
|
||||||
To int64 `json:"to"`
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := ctx.BodyParser(&req); err != nil {
|
|
||||||
receiver.logger.Error("failed to bind request", zap.Error(err))
|
|
||||||
return receiver.middleWare.Error(ctx, fiber.StatusBadRequest, "failed to bind request")
|
|
||||||
}
|
|
||||||
|
|
||||||
if req.From > req.To && req.To != 0 {
|
|
||||||
receiver.logger.Error("From timestamp must be less than To timestamp unless To is 0")
|
|
||||||
return receiver.middleWare.Error(ctx, fiber.StatusBadRequest, "From timestamp must be less than To timestamp unless To is 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
ltv, err := receiver.historyRepo.CalculateCustomerLTV(ctx.Context(), req.From, req.To)
|
|
||||||
if err != nil {
|
|
||||||
receiver.logger.Error("failed to calculate LTV", zap.Error(err))
|
|
||||||
return receiver.middleWare.ErrorOld(ctx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
response := struct {
|
|
||||||
LTV int64 `json:"LTV"`
|
|
||||||
}{
|
|
||||||
LTV: ltv,
|
|
||||||
}
|
|
||||||
|
|
||||||
return ctx.Status(fiber.StatusOK).JSON(response)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (receiver *HistoryController) GetRecentTariffs(ctx *fiber.Ctx) error {
|
func (receiver *HistoryController) GetRecentTariffs(ctx *fiber.Ctx) error {
|
||||||
userID, ok := receiver.middleWare.ExtractUserID(ctx)
|
userID, ok := receiver.middleWare.ExtractUserID(ctx)
|
||||||
if !ok || userID == "" {
|
if !ok || userID == "" {
|
||||||
@ -294,92 +262,3 @@ func (receiver *HistoryController) SendReport(ctx *fiber.Ctx) error {
|
|||||||
|
|
||||||
return ctx.SendStatus(fiber.StatusOK)
|
return ctx.SendStatus(fiber.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (receiver *HistoryController) QuizLogoStat(ctx *fiber.Ctx) error {
|
|
||||||
var req struct {
|
|
||||||
From *int `json:"from,omitempty"`
|
|
||||||
Limit *int `json:"limit,omitempty"`
|
|
||||||
Page *int `json:"page,omitempty"`
|
|
||||||
To *int `json:"to,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := ctx.BodyParser(&req); err != nil {
|
|
||||||
receiver.logger.Error("failed to bind request", zap.Error(err))
|
|
||||||
return receiver.middleWare.Error(ctx, fiber.StatusBadRequest, "failed to bind request")
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err := receiver.accountRepo.QuizLogoStat(ctx.Context(), repository.QuizLogoStatDeps{
|
|
||||||
Page: req.Page,
|
|
||||||
Limit: req.Limit,
|
|
||||||
From: req.From,
|
|
||||||
To: req.To,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return receiver.middleWare.Error(ctx, fiber.StatusInternalServerError, fmt.Sprint("failed getting quiz logo stat", err.Error()))
|
|
||||||
}
|
|
||||||
|
|
||||||
return ctx.Status(fiber.StatusOK).JSON(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (receiver *HistoryController) PromocodeLTV(ctx *fiber.Ctx) error {
|
|
||||||
var req struct {
|
|
||||||
From int `json:"from"`
|
|
||||||
To int `json:"to"`
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := ctx.BodyParser(&req); err != nil {
|
|
||||||
receiver.logger.Error("failed to bind request", zap.Error(err))
|
|
||||||
return receiver.middleWare.Error(ctx, fiber.StatusBadRequest, "failed to bind request")
|
|
||||||
}
|
|
||||||
|
|
||||||
// получаем мапу вида [promoID] = []{userid,timeActivate}
|
|
||||||
// отдаются только первые использованые на аккаунте промокоды, соответсвенно подсчет идет сугубо по ним
|
|
||||||
// если в запросе время различается с временем активации - если меньше, то учитывается только после применения
|
|
||||||
// если больше, то учитывается только с начала переданного from
|
|
||||||
codewordData, err := receiver.codewordClient.GetAllPromoActivations(ctx.Context(), &codeword_rpc.Time{
|
|
||||||
To: int64(req.To),
|
|
||||||
From: int64(req.From),
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return receiver.middleWare.Error(ctx, fiber.StatusInternalServerError, fmt.Sprint("failed getting codeword data", err.Error()))
|
|
||||||
}
|
|
||||||
|
|
||||||
userSumMap, er := receiver.historyRepo.GetPayUsersPromoHistory(ctx.Context(), codewordData, int64(req.From), int64(req.To))
|
|
||||||
if er != nil {
|
|
||||||
return receiver.middleWare.Error(ctx, fiber.StatusInternalServerError, fmt.Sprint("failed calculate promo users paid sum", er.Error()))
|
|
||||||
}
|
|
||||||
|
|
||||||
resp := make(map[string]struct {
|
|
||||||
Regs int
|
|
||||||
Money int64
|
|
||||||
})
|
|
||||||
|
|
||||||
for promoID, data := range codewordData {
|
|
||||||
fmt.Println("PROTOMOTO", promoID, data)
|
|
||||||
for _, value := range data {
|
|
||||||
|
|
||||||
paids, ok := userSumMap[value.UserID]
|
|
||||||
if !ok {
|
|
||||||
paids = 0
|
|
||||||
}
|
|
||||||
fmt.Println("PROTOMOTO1", paids, value)
|
|
||||||
|
|
||||||
if value.Time >= int64(req.From) && value.Time <= int64(req.To) {
|
|
||||||
if _, ok := resp[promoID]; !ok {
|
|
||||||
resp[promoID] = struct {
|
|
||||||
Regs int
|
|
||||||
Money int64
|
|
||||||
}{Regs: 1, Money: paids}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
current := resp[promoID]
|
|
||||||
current.Regs += 1
|
|
||||||
current.Money += paids
|
|
||||||
resp[promoID] = current
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ctx.Status(fiber.StatusOK).JSON(resp)
|
|
||||||
}
|
|
||||||
13
internal/interface/controller/http/history_client/route.go
Normal file
13
internal/interface/controller/http/history_client/route.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package history_client
|
||||||
|
|
||||||
|
import "github.com/gofiber/fiber/v2"
|
||||||
|
|
||||||
|
func (receiver *HistoryController) Register(router fiber.Router) {
|
||||||
|
router.Get("/history", receiver.Get)
|
||||||
|
router.Get("/recent", receiver.GetRecentTariffs)
|
||||||
|
router.Post("/sendReport", receiver.SendReport)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (receiver *HistoryController) Name() string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package wallet
|
package wallet_client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package wallet
|
package wallet_client
|
||||||
|
|
||||||
import "github.com/gofiber/fiber/v2"
|
import "github.com/gofiber/fiber/v2"
|
||||||
|
|
||||||
@ -15,8 +15,10 @@ type Config struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ConfigurationHTTP struct {
|
type ConfigurationHTTP struct {
|
||||||
Host string `env:"HTTP_HOST,default=localhost"`
|
ClientHost string `env:"CLIENT_HTTP_HOST,default=localhost"`
|
||||||
Port string `env:"HTTP_PORT,default=8080"`
|
ClientPort string `env:"CLIENT_HTTP_PORT,default=8080"`
|
||||||
|
AdminHost string `env:"ADMIN_HTTP_HOST,default=localhost"`
|
||||||
|
AdminPort string `env:"ADMIN_HTTP_PORT,default=8081"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ConfigurationGRPC struct {
|
type ConfigurationGRPC struct {
|
||||||
|
|||||||
@ -94,18 +94,18 @@ func (receiver *PaymentCallbackService) SuccessEvent(ctx context.Context, event
|
|||||||
}
|
}
|
||||||
|
|
||||||
//go func() {
|
//go func() {
|
||||||
if _, err := receiver.historyService.CreateHistory(ctx, &models.History{
|
if _, err := receiver.historyService.CreateHistory(ctx, &models.History{
|
||||||
UserID: account.UserID,
|
UserID: account.UserID,
|
||||||
Comment: event.Message,
|
Comment: event.Message,
|
||||||
Key: event.Key,
|
Key: event.Key,
|
||||||
RawDetails: models.RawDetails{
|
RawDetails: models.RawDetails{
|
||||||
Price: event.Amount,
|
Price: event.Amount,
|
||||||
Comment: event.Type + ":" + event.Currency,
|
Comment: event.Type + ":" + event.Currency,
|
||||||
},
|
},
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
receiver.logger.Error("failed to create history on <SuccessEvent> of <PaymentCallbackService>", zap.Error(err))
|
receiver.logger.Error("failed to create history on <SuccessEvent> of <PaymentCallbackService>", zap.Error(err))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
//}()
|
//}()
|
||||||
go func () {
|
go func () {
|
||||||
if _, err := receiver.notifier.Send(tb.ChatID(receiver.notifyChannel), fmt.Sprintf(`Внесены деньги %.2f, пользователем %s`,float64(event.Amount/100), receiver.adminURL + "/users/" + account.UserID)); err != nil {
|
if _, err := receiver.notifier.Send(tb.ChatID(receiver.notifyChannel), fmt.Sprintf(`Внесены деньги %.2f, пользователем %s`,float64(event.Amount/100), receiver.adminURL + "/users/" + account.UserID)); err != nil {
|
||||||
@ -117,10 +117,10 @@ go func () {
|
|||||||
|
|
||||||
func (receiver *PaymentCallbackService) FailureEvent(ctx context.Context, event *models.PaymentEvent) errors.Error {
|
func (receiver *PaymentCallbackService) FailureEvent(ctx context.Context, event *models.PaymentEvent) errors.Error {
|
||||||
if _, err := receiver.historyService.CreateHistory(ctx, &models.History{
|
if _, err := receiver.historyService.CreateHistory(ctx, &models.History{
|
||||||
UserID: event.UserID,
|
UserID: event.UserID,
|
||||||
Comment: event.Message,
|
Comment: event.Message,
|
||||||
Key: event.Key,
|
Key: event.Key,
|
||||||
// RawDetails: fmt.Sprintf("%d%s", event.Amount, event.Currency),
|
// RawDetails: fmt.Sprintf("%d%s", event.Amount, event.Currency),
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
receiver.logger.Error("failed to create history on <FailureEvent> of <PaymentCallbackService>", zap.Error(err))
|
receiver.logger.Error("failed to create history on <FailureEvent> of <PaymentCallbackService>", zap.Error(err))
|
||||||
return err
|
return err
|
||||||
|
|||||||
@ -116,7 +116,7 @@ func (receiver *Service) ReplenishAccountWallet(ctx context.Context, request *mo
|
|||||||
updatedAccount, changeErr := receiver.repository.ChangeWallet(ctx, request.Account.UserID, &models.Wallet{
|
updatedAccount, changeErr := receiver.repository.ChangeWallet(ctx, request.Account.UserID, &models.Wallet{
|
||||||
Cash: request.Account.Wallet.Cash + cash,
|
Cash: request.Account.Wallet.Cash + cash,
|
||||||
Money: request.Account.Wallet.Money + request.Cash,
|
Money: request.Account.Wallet.Money + request.Cash,
|
||||||
Spent: request.Account.Wallet.Spent,
|
Spent: request.Account.Wallet.Spent,
|
||||||
PurchasesAmount: request.Account.Wallet.PurchasesAmount,
|
PurchasesAmount: request.Account.Wallet.PurchasesAmount,
|
||||||
Currency: request.Account.Wallet.Currency,
|
Currency: request.Account.Wallet.Currency,
|
||||||
LastPaymentID: request.PaymentID,
|
LastPaymentID: request.PaymentID,
|
||||||
|
|||||||
@ -19,7 +19,7 @@ func TestChangeAccount(t *testing.T) {
|
|||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
assert.NotPanics(t, func() {
|
assert.NotPanics(t, func() {
|
||||||
token, tokenErr := jwtUtil.Create("64e5d9830fcca0596d82c0c7")
|
token, tokenErr := jwtUtil.Create("64ebda4387392e122e5d411f")
|
||||||
if isNoError := assert.NoError(t, tokenErr); !isNoError {
|
if isNoError := assert.NoError(t, tokenErr); !isNoError {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -43,7 +43,7 @@ func TestChangeAccount(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.Equal(t, "64e5d9830fcca0596d82c0c7", responseChangeAccount.Body.UserID)
|
assert.Equal(t, "64ebda4387392e122e5d411f", responseChangeAccount.Body.UserID)
|
||||||
assert.Equal(t, "Aloha", responseChangeAccount.Body.Name.Middlename)
|
assert.Equal(t, "Aloha", responseChangeAccount.Body.Name.Middlename)
|
||||||
assert.Equal(t, "Holla", responseChangeAccount.Body.Name.FirstName)
|
assert.Equal(t, "Holla", responseChangeAccount.Body.Name.FirstName)
|
||||||
assert.Equal(t, "Adios payasos", responseChangeAccount.Body.Name.Orgname)
|
assert.Equal(t, "Adios payasos", responseChangeAccount.Body.Name.Orgname)
|
||||||
@ -54,7 +54,7 @@ func TestChangeAccount(t *testing.T) {
|
|||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
assert.NotPanics(t, func() {
|
assert.NotPanics(t, func() {
|
||||||
token, tokenErr := jwtUtil.Create("64e5d9830fcca0596d82c0c7")
|
token, tokenErr := jwtUtil.Create("64ebda4387392e122e5d411f")
|
||||||
if isNoError := assert.NoError(t, tokenErr); !isNoError {
|
if isNoError := assert.NoError(t, tokenErr); !isNoError {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -64,7 +64,7 @@ func TestChangeAccount(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
responseStatusAccount, errStatusAccount := client.Patch[models.Account, models.ResponseErrorHTTP](ctx, &client.RequestSettings{
|
responseStatusAccount, errStatusAccount := client.Patch[models.Account, models.ResponseErrorHTTP](ctx, &client.RequestSettings{
|
||||||
URL: "http://localhost:8082/account/64e5d9830fcca0596d82c0c7",
|
URL: "http://localhost:8083/account/64ebda4387392e122e5d411f",
|
||||||
Headers: map[string]string{"Authorization": fmt.Sprintf("Bearer %s", token)},
|
Headers: map[string]string{"Authorization": fmt.Sprintf("Bearer %s", token)},
|
||||||
Body: statusRequest,
|
Body: statusRequest,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -47,7 +47,7 @@ func TestGetAccount(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
responseGetAccount, errGetAccount := client.Get[models.Account, models.ResponseErrorHTTP](ctx, &client.RequestSettings{
|
responseGetAccount, errGetAccount := client.Get[models.Account, models.ResponseErrorHTTP](ctx, &client.RequestSettings{
|
||||||
URL: "http://localhost:8082/account/64e5e1ca87392e122e5d3de7",
|
URL: "http://localhost:8083/account/64e5e1ca87392e122e5d3de7",
|
||||||
Headers: map[string]string{"Authorization": fmt.Sprintf("Bearer %s", token)},
|
Headers: map[string]string{"Authorization": fmt.Sprintf("Bearer %s", token)},
|
||||||
})
|
})
|
||||||
if isNoError := assert.NoError(t, errGetAccount); !isNoError {
|
if isNoError := assert.NoError(t, errGetAccount); !isNoError {
|
||||||
@ -61,6 +61,10 @@ func TestGetAccount(t *testing.T) {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
t.Run("Получение аккаунтов с пагинацией", func(t *testing.T) {
|
t.Run("Получение аккаунтов с пагинацией", func(t *testing.T) {
|
||||||
|
token, tokenErr := jwtUtil.Create("64e5e1ca87392e122e5d3de7")
|
||||||
|
if isNoError := assert.NoError(t, tokenErr); !isNoError {
|
||||||
|
return
|
||||||
|
}
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
assert.NotPanics(t, func() {
|
assert.NotPanics(t, func() {
|
||||||
@ -77,8 +81,9 @@ func TestGetAccount(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
responseGetAccount, errGetAccount := client.Get[models.PaginationResponse[models.Account], models.ResponseErrorHTTP](ctx, &client.RequestSettings{
|
responseGetAccount, errGetAccount := client.Get[models.PaginationResponse[models.Account], models.ResponseErrorHTTP](ctx, &client.RequestSettings{
|
||||||
URL: "http://localhost:8082/accounts",
|
URL: "http://localhost:8083/accounts",
|
||||||
Body: params,
|
Body: params,
|
||||||
|
Headers: map[string]string{"Authorization": fmt.Sprintf("Bearer %s", token)},
|
||||||
})
|
})
|
||||||
if isNoError := assert.NoError(t, errGetAccount); !isNoError {
|
if isNoError := assert.NoError(t, errGetAccount); !isNoError {
|
||||||
return
|
return
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user