add stats fixes

This commit is contained in:
harold 2025-03-09 19:40:47 +05:00
parent 476e6ff59c
commit 31a2d2ec58
9 changed files with 188 additions and 9 deletions

View File

@ -464,7 +464,7 @@ func UpdateModerationSettings(donatService model.DonatService) echo.HandlerFunc
// @Produce json // @Produce json
// @Security BearerAuth // @Security BearerAuth
// @Param period query string true "Period for statistics" Enums(24h, 7d, 1m, 1y) // @Param period query string true "Period for statistics" Enums(24h, 7d, 1m, 1y)
// @Success 200 {array} model.DonationStatResponse "Donations statistics" // @Success 200 {array} model.DonationSummaryResponse "Donations statistics"
// @Failure 400 {object} echo.HTTPError "Bad request" // @Failure 400 {object} echo.HTTPError "Bad request"
// @Failure 401 {object} echo.HTTPError "Unauthorized or expired token" // @Failure 401 {object} echo.HTTPError "Unauthorized or expired token"
// @Failure 422 {object} echo.HTTPError "Validation error" // @Failure 422 {object} echo.HTTPError "Validation error"

View File

@ -132,7 +132,7 @@ const docTemplate = `{
"schema": { "schema": {
"type": "array", "type": "array",
"items": { "items": {
"$ref": "#/definitions/donat-widget_internal_model.DonationStatResponse" "$ref": "#/definitions/donat-widget_internal_model.DonationSummaryResponse"
} }
} }
}, },
@ -1057,6 +1057,33 @@ const docTemplate = `{
} }
} }
}, },
"donat-widget_internal_model.DonationSummary": {
"type": "object",
"properties": {
"donations_count": {
"description": "Общее количество донатов",
"type": "integer"
},
"total_amount": {
"description": "Общая сумма донатов",
"type": "integer"
}
}
},
"donat-widget_internal_model.DonationSummaryResponse": {
"type": "object",
"properties": {
"donation_sum": {
"$ref": "#/definitions/donat-widget_internal_model.DonationSummary"
},
"donations": {
"type": "array",
"items": {
"$ref": "#/definitions/donat-widget_internal_model.DonationStatResponse"
}
}
}
},
"donat-widget_internal_model.FilterSettingResponse": { "donat-widget_internal_model.FilterSettingResponse": {
"type": "object", "type": "object",
"properties": { "properties": {

View File

@ -125,7 +125,7 @@
"schema": { "schema": {
"type": "array", "type": "array",
"items": { "items": {
"$ref": "#/definitions/donat-widget_internal_model.DonationStatResponse" "$ref": "#/definitions/donat-widget_internal_model.DonationSummaryResponse"
} }
} }
}, },
@ -1050,6 +1050,33 @@
} }
} }
}, },
"donat-widget_internal_model.DonationSummary": {
"type": "object",
"properties": {
"donations_count": {
"description": "Общее количество донатов",
"type": "integer"
},
"total_amount": {
"description": "Общая сумма донатов",
"type": "integer"
}
}
},
"donat-widget_internal_model.DonationSummaryResponse": {
"type": "object",
"properties": {
"donation_sum": {
"$ref": "#/definitions/donat-widget_internal_model.DonationSummary"
},
"donations": {
"type": "array",
"items": {
"$ref": "#/definitions/donat-widget_internal_model.DonationStatResponse"
}
}
}
},
"donat-widget_internal_model.FilterSettingResponse": { "donat-widget_internal_model.FilterSettingResponse": {
"type": "object", "type": "object",
"properties": { "properties": {

View File

@ -75,6 +75,24 @@ definitions:
donations_count: donations_count:
type: integer type: integer
type: object type: object
donat-widget_internal_model.DonationSummary:
properties:
donations_count:
description: Общее количество донатов
type: integer
total_amount:
description: Общая сумма донатов
type: integer
type: object
donat-widget_internal_model.DonationSummaryResponse:
properties:
donation_sum:
$ref: '#/definitions/donat-widget_internal_model.DonationSummary'
donations:
items:
$ref: '#/definitions/donat-widget_internal_model.DonationStatResponse'
type: array
type: object
donat-widget_internal_model.FilterSettingResponse: donat-widget_internal_model.FilterSettingResponse:
properties: properties:
enable_links: enable_links:
@ -456,7 +474,7 @@ paths:
description: Donations statistics description: Donations statistics
schema: schema:
items: items:
$ref: '#/definitions/donat-widget_internal_model.DonationStatResponse' $ref: '#/definitions/donat-widget_internal_model.DonationSummaryResponse'
type: array type: array
"400": "400":
description: Bad request description: Bad request

View File

@ -99,7 +99,7 @@ type DonatService interface {
GetModerationSettings(ctx context.Context, streamerID int) (ModerationResponse, error) GetModerationSettings(ctx context.Context, streamerID int) (ModerationResponse, error)
UpdateModerationSettings(ctx context.Context, streamerID int, updateModel UpdateModeration) error UpdateModerationSettings(ctx context.Context, streamerID int, updateModel UpdateModeration) error
GetDonationsStats(ctx context.Context, streamerID int, period string) ([]DonationStatResponse, error) GetDonationsStats(ctx context.Context, streamerID int, period string) (DonationSummaryResponse, error)
} }
type DonatRepo interface { type DonatRepo interface {
@ -151,6 +151,7 @@ type DonatRepo interface {
UpdateModeration(ctx context.Context, streamerID int, enable *bool, duration *int) error UpdateModeration(ctx context.Context, streamerID int, enable *bool, duration *int) error
GetDonationsStats(ctx context.Context, streamerID int, period string) ([]DonationStat, error) GetDonationsStats(ctx context.Context, streamerID int, period string) ([]DonationStat, error)
GetDonationsSummary(ctx context.Context, streamerID int, period string) (DonationSummary, error)
} }
type TargetService interface { type TargetService interface {

View File

@ -261,12 +261,22 @@ type DonationStat struct {
DonationsCount int `db:"donations_count"` DonationsCount int `db:"donations_count"`
} }
type DonationSummary struct {
TotalAmount int `db:"total_amount" json:"total_amount"` // Общая сумма донатов
DonationsCount int `db:"donations_count" json:"donations_count"` // Общее количество донатов
}
type DonationStatResponse struct { type DonationStatResponse struct {
Date time.Time `json:"date"` Date time.Time `json:"date"`
AmountCollected int `json:"amount_collected"` AmountCollected int `json:"amount_collected"`
DonationsCount int `json:"donations_count"` DonationsCount int `json:"donations_count"`
} }
type DonationSummaryResponse struct {
DonationSum DonationSummary `json:"donation_sum"`
Donations []DonationStatResponse `json:"donations"`
}
//func (widget *GetWidgetDb) GetMediaUrl(mediaType MediaType) MediaUrl { //func (widget *GetWidgetDb) GetMediaUrl(mediaType MediaType) MediaUrl {
// var mediaUrl MediaUrl // var mediaUrl MediaUrl
// if mediaType == "background_url" { // if mediaType == "background_url" {

View File

@ -377,3 +377,47 @@ GROUP BY
ORDER BY ORDER BY
date; date;
` `
const GetDonationsSummaryLast24Hours = `
SELECT
SUM(amount) AS total_amount,
COUNT(*) AS donations_count
FROM
public.donats
WHERE
streamer_id = @streamer_id
AND created_at >= NOW() - INTERVAL '24 hours';
`
const GetDonationsSummaryLast7Days = `
SELECT
SUM(amount) AS total_amount,
COUNT(*) AS donations_count
FROM
public.donats
WHERE
streamer_id = @streamer_id
AND created_at >= NOW() - INTERVAL '7 days';
`
const GetDonationsSummaryLastMonth = `
SELECT
SUM(amount) AS total_amount,
COUNT(*) AS donations_count
FROM
public.donats
WHERE
streamer_id = @streamer_id
AND created_at >= NOW() - INTERVAL '1 month';
`
const GetDonationsSummaryLastYear = `
SELECT
SUM(amount) AS total_amount,
COUNT(*) AS donations_count
FROM
public.donats
WHERE
streamer_id = @streamer_id
AND created_at >= NOW() - INTERVAL '1 year';
`

View File

@ -643,3 +643,41 @@ func (repoDonat *RepoDonat) GetDonationsStats(
return stats, nil return stats, nil
} }
func (repoDonat *RepoDonat) GetDonationsSummary(
ctx context.Context,
streamerID int,
period string, // "24h", "7d", "1m", "1y"
) (model.DonationSummary, error) {
var query string
switch period {
case "24h":
query = sql.GetDonationsSummaryLast24Hours
case "7d":
query = sql.GetDonationsSummaryLast7Days
case "1m":
query = sql.GetDonationsSummaryLastMonth
case "1y":
query = sql.GetDonationsSummaryLastYear
default:
return model.DonationSummary{}, errors.New("invalid period")
}
args := pgx.NamedArgs{
"streamer_id": streamerID,
}
var summary model.DonationSummary
row, err := repoDonat.db.SelectOne(ctx, query, args)
if err != nil {
slog.Error("Failed to get donations summary", "error", err)
return model.DonationSummary{}, err
}
err = row.Scan(&summary.TotalAmount, &summary.DonationsCount)
if err != nil {
slog.Error("Failed to get donations summary", "error", err)
return model.DonationSummary{}, err
}
return summary, nil
}

View File

@ -460,21 +460,35 @@ func (donatService *ServiceDonat) GetDonationsStats(
ctx context.Context, ctx context.Context,
streamerID int, streamerID int,
period string, period string,
) ([]model.DonationStatResponse, error) { ) (model.DonationSummaryResponse, error) {
stats, err := donatService.donatRepo.GetDonationsStats(ctx, streamerID, period) stats, err := donatService.donatRepo.GetDonationsStats(ctx, streamerID, period)
if err != nil { if err != nil {
slog.Error(err.Error()) slog.Error(err.Error())
return nil, err return model.DonationSummaryResponse{}, err
} }
var response []model.DonationStatResponse var donationsStat []model.DonationStatResponse
var response model.DonationSummaryResponse
donationSummary, err := donatService.donatRepo.GetDonationsSummary(
ctx,
streamerID,
period,
)
if err != nil {
slog.Error(err.Error())
return model.DonationSummaryResponse{}, err
}
response.DonationSum = donationSummary
for _, stat := range stats { for _, stat := range stats {
response = append(response, model.DonationStatResponse{ donationsStat = append(donationsStat, model.DonationStatResponse{
Date: stat.Date, Date: stat.Date,
AmountCollected: stat.AmountCollected, AmountCollected: stat.AmountCollected,
DonationsCount: stat.DonationsCount, DonationsCount: stat.DonationsCount,
}) })
} }
response.Donations = donationsStat
return response, nil return response, nil
} }