generated from PenaSide/GolangTemplate
add calculateltv route
This commit is contained in:
parent
f96851af5c
commit
962aa779a0
@ -578,6 +578,7 @@ paths:
|
||||
tags:
|
||||
- history
|
||||
summary: Получение недавних тарифов
|
||||
operationId: getRecentTariffs
|
||||
description: Возвращает список уникальных тарифов из истории. Айди аккаунта получается из заголовка.
|
||||
security:
|
||||
- Bearer: []
|
||||
@ -647,6 +648,65 @@ paths:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
|
||||
/history/ltv:
|
||||
post:
|
||||
tags:
|
||||
- history
|
||||
summary: Расчет среднего времени жизни платящего клиента (LTV)
|
||||
operationId: calculateLTV
|
||||
security:
|
||||
- Bearer: [ ]
|
||||
requestBody:
|
||||
description: Период для расчета LTV
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
from:
|
||||
type: integer
|
||||
format: int64
|
||||
description: Начальная дата в формате Unix timestamp. Если 0, устанавливает начало истории.
|
||||
to:
|
||||
type: integer
|
||||
format: int64
|
||||
description: Конечная дата в формате Unix timestamp. Если 0, устанавливает текущее время.
|
||||
required:
|
||||
- from
|
||||
- to
|
||||
responses:
|
||||
'200':
|
||||
description: Успешный расчет LTV
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
ltv:
|
||||
type: integer
|
||||
format: int64
|
||||
description: Среднее количество дней между первым и последним платежом
|
||||
'400':
|
||||
description: Неверный запрос, если from больше, чем to
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
'401':
|
||||
description: Неавторизован
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
'500':
|
||||
description: Внутренняя ошибка сервера
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
|
||||
|
||||
components:
|
||||
schemas:
|
||||
Account:
|
||||
|
@ -100,3 +100,38 @@ func (receiver *Controller) SendReport(ctx echo.Context) error {
|
||||
|
||||
return ctx.NoContent(http.StatusOK)
|
||||
}
|
||||
|
||||
// TODO:tests.
|
||||
func (receiver *Controller) CalculateLTV(ctx echo.Context) error {
|
||||
var req swagger.CalculateLTVJSONBody
|
||||
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
receiver.logger.Error("failed to bind request", zap.Error(err))
|
||||
return errors.HTTP(ctx, errors.New(
|
||||
fmt.Errorf("failed to bind request: %s", err),
|
||||
errors.ErrInvalidArgs,
|
||||
))
|
||||
}
|
||||
|
||||
if req.From > req.To && req.To != 0 {
|
||||
receiver.logger.Error("From timestamp must be less than To timestamp unless To is 0")
|
||||
return errors.HTTP(ctx, errors.New(
|
||||
fmt.Errorf("From timestamp must be less than To timestamp unless To is 0"),
|
||||
errors.ErrInvalidArgs,
|
||||
))
|
||||
}
|
||||
|
||||
ltv, err := receiver.historyService.CalculateCustomerLTV(ctx.Request().Context(), req.From, req.To)
|
||||
if err != nil {
|
||||
receiver.logger.Error("failed to calculate LTV", zap.Error(err))
|
||||
return errors.HTTP(ctx, err)
|
||||
}
|
||||
|
||||
response := struct {
|
||||
LTV int64 `json:"LTV"`
|
||||
}{
|
||||
LTV: ltv,
|
||||
}
|
||||
|
||||
return ctx.JSON(http.StatusOK, response)
|
||||
}
|
||||
|
@ -3,18 +3,18 @@ package repository
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
"go.uber.org/zap"
|
||||
"log"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/fields"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
|
||||
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/service/history"
|
||||
mongoWrapper "penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/mongo"
|
||||
"time"
|
||||
)
|
||||
|
||||
type HistoryRepositoryDeps struct {
|
||||
@ -273,3 +273,67 @@ func (receiver *HistoryRepository) GetDocNumber(ctx context.Context, userID stri
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (receiver *HistoryRepository) CalculateCustomerLTV(ctx context.Context, from, to int64) (int64, errors.Error) {
|
||||
timeFilter := bson.M{}
|
||||
if from != 0 || to != 0 {
|
||||
timeRange := bson.M{}
|
||||
if from != 0 {
|
||||
timeRange["$gte"] = time.Unix(from, 0)
|
||||
}
|
||||
if to != 0 {
|
||||
timeRange["$lte"] = time.Unix(to, 0)
|
||||
}
|
||||
timeFilter["createdAt"] = timeRange
|
||||
}
|
||||
|
||||
pipeline := mongo.Pipeline{
|
||||
{{"$match", bson.M{"key": models.CustomerHistoryKeyPayCart, "isDeleted": false}}},
|
||||
{{"$match", timeFilter}},
|
||||
{{"$group", bson.M{
|
||||
"_id": "$userId",
|
||||
"firstPayment": bson.M{"$first": "$createdAt"},
|
||||
"lastPayment": bson.M{"$last": "$createdAt"},
|
||||
}}},
|
||||
{{"$project", bson.M{
|
||||
"lifeTimeInDays": bson.M{"$divide": []interface{}{
|
||||
bson.M{"$subtract": []interface{}{"$lastPayment", "$firstPayment"}},
|
||||
86400000,
|
||||
}},
|
||||
}}},
|
||||
{{"$group", bson.M{
|
||||
"_id": nil,
|
||||
"averageLTV": bson.M{"$avg": "$lifeTimeInDays"},
|
||||
}}},
|
||||
}
|
||||
|
||||
cursor, err := receiver.mongoDB.Aggregate(ctx, pipeline)
|
||||
if err != nil {
|
||||
receiver.logger.Error("failed to calculate customer LTV <CalculateCustomerLTV> of <HistoryRepository>",
|
||||
zap.Error(err),
|
||||
)
|
||||
return 0, errors.New(
|
||||
fmt.Errorf("failed to calculate customer LTV <CalculateCustomerLTV> of <HistoryRepository>: %w", err),
|
||||
errors.ErrInternalError,
|
||||
)
|
||||
}
|
||||
defer cursor.Close(ctx)
|
||||
|
||||
var results []struct{ AverageLTV float64 }
|
||||
if err := cursor.All(ctx, &results); err != nil {
|
||||
receiver.logger.Error("failed to getting result LTV <CalculateCustomerLTV> of <HistoryRepository>",
|
||||
zap.Error(err),
|
||||
)
|
||||
return 0, errors.New(
|
||||
fmt.Errorf("failed to getting result LTV <CalculateCustomerLTV> of <HistoryRepository>: %w", err),
|
||||
errors.ErrInternalError,
|
||||
)
|
||||
}
|
||||
|
||||
if len(results) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
averageLTV := results[0].AverageLTV
|
||||
return int64(averageLTV), nil
|
||||
}
|
||||
|
@ -92,3 +92,7 @@ func (api *API2) ChangeCurrency(_ echo.Context) error {
|
||||
func (api *API2) RequestMoney(_ echo.Context) error {
|
||||
panic("TODO")
|
||||
}
|
||||
|
||||
func (api *API2) CalculateLTV(_ echo.Context) error {
|
||||
panic("TODO")
|
||||
}
|
||||
|
@ -62,6 +62,9 @@ type ServerInterface interface {
|
||||
// Получение лога событий связанных с аккаунтом
|
||||
// (GET /history)
|
||||
GetHistory(ctx echo.Context, params GetHistoryParams) error
|
||||
// Расчет среднего времени жизни платящего клиента (LTV)
|
||||
// (POST /history/ltv)
|
||||
CalculateLTV(ctx echo.Context) error
|
||||
// Получение недавних тарифов
|
||||
// (GET /recent)
|
||||
GetRecentTariffs(ctx echo.Context) error
|
||||
@ -309,6 +312,17 @@ func (w *ServerInterfaceWrapper) GetHistory(ctx echo.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// CalculateLTV converts echo context to params.
|
||||
func (w *ServerInterfaceWrapper) CalculateLTV(ctx echo.Context) error {
|
||||
var err error
|
||||
|
||||
ctx.Set(BearerScopes, []string{})
|
||||
|
||||
// Invoke the callback with all the unmarshaled arguments
|
||||
err = w.Handler.CalculateLTV(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// GetRecentTariffs converts echo context to params.
|
||||
func (w *ServerInterfaceWrapper) GetRecentTariffs(ctx echo.Context) error {
|
||||
var err error
|
||||
@ -395,6 +409,7 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL
|
||||
router.GET(baseURL+"/currencies", wrapper.GetCurrencies)
|
||||
router.PUT(baseURL+"/currencies", wrapper.UpdateCurrencies)
|
||||
router.GET(baseURL+"/history", wrapper.GetHistory)
|
||||
router.POST(baseURL+"/history/ltv", wrapper.CalculateLTV)
|
||||
router.GET(baseURL+"/recent", wrapper.GetRecentTariffs)
|
||||
router.POST(baseURL+"/sendReport", wrapper.SendReport)
|
||||
router.PATCH(baseURL+"/wallet", wrapper.ChangeCurrency)
|
||||
@ -405,74 +420,80 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL
|
||||
// Base64 encoded, gzipped, json marshaled Swagger object
|
||||
var swaggerSpec = []string{
|
||||
|
||||
"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",
|
||||
"aC42/y8AAP//Dabnb25UAAA=",
|
||||
}
|
||||
|
||||
// GetSwagger returns the content of the embedded swagger specification file
|
||||
|
@ -37,6 +37,7 @@ type historyController interface {
|
||||
GetHistoryList(ctx echo.Context, params GetHistoryParams) error
|
||||
GetRecentTariffs(ctx echo.Context) error
|
||||
SendReport(ctx echo.Context) error
|
||||
CalculateLTV(ctx echo.Context) error
|
||||
}
|
||||
|
||||
type Deps struct {
|
||||
@ -157,6 +158,10 @@ func (receiver *API) SendReport(ctx echo.Context) error {
|
||||
return receiver.historyController.SendReport(ctx)
|
||||
}
|
||||
|
||||
func (receiver *API) CalculateLTV(ctx echo.Context) error {
|
||||
return receiver.historyController.CalculateLTV(ctx)
|
||||
}
|
||||
|
||||
// Wallet
|
||||
|
||||
func (receiver *API) RequestMoney(ctx echo.Context) error {
|
||||
|
@ -100,6 +100,11 @@ type Name struct {
|
||||
// PaymentType defines model for PaymentType.
|
||||
type PaymentType string
|
||||
|
||||
// TariffID defines model for TariffID.
|
||||
type TariffID struct {
|
||||
ID *string `json:"ID,omitempty"`
|
||||
}
|
||||
|
||||
// Wallet defines model for Wallet.
|
||||
type Wallet struct {
|
||||
// Cash Сумма money переведённая на текущий курс
|
||||
@ -157,6 +162,20 @@ type GetHistoryParams struct {
|
||||
Type *string `form:"type,omitempty" json:"type,omitempty"`
|
||||
}
|
||||
|
||||
// CalculateLTVJSONBody defines parameters for CalculateLTV.
|
||||
type CalculateLTVJSONBody struct {
|
||||
// From Начальная дата в формате Unix timestamp. Если 0, устанавливает начало истории.
|
||||
From int64 `json:"from"`
|
||||
|
||||
// To Конечная дата в формате Unix timestamp. Если 0, устанавливает текущее время.
|
||||
To int64 `json:"to"`
|
||||
}
|
||||
|
||||
// GetRecentTariffsJSONBody defines parameters for GetRecentTariffs.
|
||||
type GetRecentTariffsJSONBody struct {
|
||||
Id string `json:"id"`
|
||||
}
|
||||
|
||||
// SendReportJSONBody defines parameters for SendReport.
|
||||
type SendReportJSONBody struct {
|
||||
Id string `json:"id"`
|
||||
@ -189,6 +208,12 @@ type SetAccountVerificationStatusJSONRequestBody SetAccountVerificationStatusJSO
|
||||
// UpdateCurrenciesJSONRequestBody defines body for UpdateCurrencies for application/json ContentType.
|
||||
type UpdateCurrenciesJSONRequestBody = UpdateCurrenciesJSONBody
|
||||
|
||||
// CalculateLTVJSONRequestBody defines body for CalculateLTV for application/json ContentType.
|
||||
type CalculateLTVJSONRequestBody CalculateLTVJSONBody
|
||||
|
||||
// GetRecentTariffsJSONRequestBody defines body for GetRecentTariffs for application/json ContentType.
|
||||
type GetRecentTariffsJSONRequestBody GetRecentTariffsJSONBody
|
||||
|
||||
// SendReportJSONRequestBody defines body for SendReport for application/json ContentType.
|
||||
type SendReportJSONRequestBody SendReportJSONBody
|
||||
|
||||
|
@ -37,6 +37,7 @@ type historyRepository interface {
|
||||
GetRecentTariffs(context.Context, string) ([]models.TariffID, errors.Error) // new
|
||||
GetHistoryByID(context.Context, string) (*models.ReportHistory, errors.Error)
|
||||
GetDocNumber(context.Context, string) (map[string]int, errors.Error)
|
||||
CalculateCustomerLTV(ctx context.Context, from, to int64) (int64, errors.Error)
|
||||
}
|
||||
|
||||
type authClient interface {
|
||||
@ -259,3 +260,13 @@ func (receiver *Service) GetHistoryByID(ctx context.Context, historyID string) e
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (receiver *Service) CalculateCustomerLTV(ctx context.Context, from, to int64) (int64, errors.Error) {
|
||||
ltv, err := receiver.repository.CalculateCustomerLTV(ctx, from, to)
|
||||
if err != nil {
|
||||
receiver.logger.Error("failed to calculate LTV", zap.Error(err))
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return ltv, nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user