feat: implement system statistics tracking, commit management controllers, and associated database migrations
All checks were successful
Build and Release / release (push) Successful in 1m49s

This commit is contained in:
2026-05-07 11:31:53 +07:00
parent ca05785a24
commit bdaac7ddd8
29 changed files with 1347 additions and 2 deletions

View File

@@ -129,6 +129,30 @@ type Submission struct {
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
type SystemStatistic struct {
ID pgtype.UUID `json:"id"`
Date pgtype.Date `json:"date"`
TotalUsers int32 `json:"total_users"`
TotalProjects int32 `json:"total_projects"`
TotalCommits int32 `json:"total_commits"`
TotalSubmissions int32 `json:"total_submissions"`
TotalMedias int32 `json:"total_medias"`
TotalWikis int32 `json:"total_wikis"`
TotalEntities int32 `json:"total_entities"`
TotalGeometries int32 `json:"total_geometries"`
TotalStorageBytes int64 `json:"total_storage_bytes"`
NewUsers int32 `json:"new_users"`
NewProjects int32 `json:"new_projects"`
NewCommits int32 `json:"new_commits"`
NewSubmissions int32 `json:"new_submissions"`
NewMedias int32 `json:"new_medias"`
NewWikis int32 `json:"new_wikis"`
NewEntities int32 `json:"new_entities"`
NewGeometries int32 `json:"new_geometries"`
NewStorageBytes int64 `json:"new_storage_bytes"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
type User struct {
ID pgtype.UUID `json:"id"`
Email string `json:"email"`

View File

@@ -0,0 +1,224 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.30.0
// source: statistic.sql
package sqlc
import (
"context"
"github.com/jackc/pgx/v5/pgtype"
)
const getSystemStatisticsByDate = `-- name: GetSystemStatisticsByDate :one
SELECT id, date, total_users, total_projects, total_commits, total_submissions, total_medias, total_wikis, total_entities, total_geometries, total_storage_bytes, new_users, new_projects, new_commits, new_submissions, new_medias, new_wikis, new_entities, new_geometries, new_storage_bytes, created_at FROM system_statistics WHERE date = $1 LIMIT 1
`
func (q *Queries) GetSystemStatisticsByDate(ctx context.Context, date pgtype.Date) (SystemStatistic, error) {
row := q.db.QueryRow(ctx, getSystemStatisticsByDate, date)
var i SystemStatistic
err := row.Scan(
&i.ID,
&i.Date,
&i.TotalUsers,
&i.TotalProjects,
&i.TotalCommits,
&i.TotalSubmissions,
&i.TotalMedias,
&i.TotalWikis,
&i.TotalEntities,
&i.TotalGeometries,
&i.TotalStorageBytes,
&i.NewUsers,
&i.NewProjects,
&i.NewCommits,
&i.NewSubmissions,
&i.NewMedias,
&i.NewWikis,
&i.NewEntities,
&i.NewGeometries,
&i.NewStorageBytes,
&i.CreatedAt,
)
return i, err
}
const getSystemStatisticsByIDs = `-- name: GetSystemStatisticsByIDs :many
SELECT id, date, total_users, total_projects, total_commits, total_submissions, total_medias, total_wikis, total_entities, total_geometries, total_storage_bytes, new_users, new_projects, new_commits, new_submissions, new_medias, new_wikis, new_entities, new_geometries, new_storage_bytes, created_at FROM system_statistics WHERE id = ANY($1::UUID[])
`
func (q *Queries) GetSystemStatisticsByIDs(ctx context.Context, dollar_1 []pgtype.UUID) ([]SystemStatistic, error) {
rows, err := q.db.Query(ctx, getSystemStatisticsByIDs, dollar_1)
if err != nil {
return nil, err
}
defer rows.Close()
items := []SystemStatistic{}
for rows.Next() {
var i SystemStatistic
if err := rows.Scan(
&i.ID,
&i.Date,
&i.TotalUsers,
&i.TotalProjects,
&i.TotalCommits,
&i.TotalSubmissions,
&i.TotalMedias,
&i.TotalWikis,
&i.TotalEntities,
&i.TotalGeometries,
&i.TotalStorageBytes,
&i.NewUsers,
&i.NewProjects,
&i.NewCommits,
&i.NewSubmissions,
&i.NewMedias,
&i.NewWikis,
&i.NewEntities,
&i.NewGeometries,
&i.NewStorageBytes,
&i.CreatedAt,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const searchSystemStatistics = `-- name: SearchSystemStatistics :many
SELECT id, date, total_users, total_projects, total_commits, total_submissions, total_medias, total_wikis, total_entities, total_geometries, total_storage_bytes, new_users, new_projects, new_commits, new_submissions, new_medias, new_wikis, new_entities, new_geometries, new_storage_bytes, created_at FROM system_statistics
WHERE
($1::DATE IS NULL OR date >= $1::DATE) AND
($2::DATE IS NULL OR date <= $2::DATE)
ORDER BY date DESC
`
type SearchSystemStatisticsParams struct {
StartDate pgtype.Date `json:"start_date"`
EndDate pgtype.Date `json:"end_date"`
}
func (q *Queries) SearchSystemStatistics(ctx context.Context, arg SearchSystemStatisticsParams) ([]SystemStatistic, error) {
rows, err := q.db.Query(ctx, searchSystemStatistics, arg.StartDate, arg.EndDate)
if err != nil {
return nil, err
}
defer rows.Close()
items := []SystemStatistic{}
for rows.Next() {
var i SystemStatistic
if err := rows.Scan(
&i.ID,
&i.Date,
&i.TotalUsers,
&i.TotalProjects,
&i.TotalCommits,
&i.TotalSubmissions,
&i.TotalMedias,
&i.TotalWikis,
&i.TotalEntities,
&i.TotalGeometries,
&i.TotalStorageBytes,
&i.NewUsers,
&i.NewProjects,
&i.NewCommits,
&i.NewSubmissions,
&i.NewMedias,
&i.NewWikis,
&i.NewEntities,
&i.NewGeometries,
&i.NewStorageBytes,
&i.CreatedAt,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const upsertSystemStatistics = `-- name: UpsertSystemStatistics :one
INSERT INTO system_statistics (
date,
total_users, total_projects, total_commits, total_submissions, total_medias, total_wikis, total_entities, total_geometries, total_storage_bytes,
new_users, new_projects, new_commits, new_submissions, new_medias, new_wikis, new_entities, new_geometries, new_storage_bytes
) VALUES (
$1,
(SELECT COUNT(*)::INT FROM users),
(SELECT COUNT(*)::INT FROM projects),
(SELECT COUNT(*)::INT FROM commits),
(SELECT COUNT(*)::INT FROM submissions),
(SELECT COUNT(*)::INT FROM medias),
(SELECT COUNT(*)::INT FROM wikis),
(SELECT COUNT(*)::INT FROM entities),
(SELECT COUNT(*)::INT FROM geometries),
COALESCE((SELECT SUM(size)::BIGINT FROM medias), 0),
(SELECT COUNT(*)::INT FROM users WHERE created_at >= $1::DATE AND created_at < $1::DATE + INTERVAL '1 day'),
(SELECT COUNT(*)::INT FROM projects WHERE created_at >= $1::DATE AND created_at < $1::DATE + INTERVAL '1 day'),
(SELECT COUNT(*)::INT FROM commits WHERE created_at >= $1::DATE AND created_at < $1::DATE + INTERVAL '1 day'),
(SELECT COUNT(*)::INT FROM submissions WHERE created_at >= $1::DATE AND created_at < $1::DATE + INTERVAL '1 day'),
(SELECT COUNT(*)::INT FROM medias WHERE created_at >= $1::DATE AND created_at < $1::DATE + INTERVAL '1 day'),
(SELECT COUNT(*)::INT FROM wikis WHERE created_at >= $1::DATE AND created_at < $1::DATE + INTERVAL '1 day'),
(SELECT COUNT(*)::INT FROM entities WHERE created_at >= $1::DATE AND created_at < $1::DATE + INTERVAL '1 day'),
(SELECT COUNT(*)::INT FROM geometries WHERE created_at >= $1::DATE AND created_at < $1::DATE + INTERVAL '1 day'),
COALESCE((SELECT SUM(size)::BIGINT FROM medias WHERE created_at >= $1::DATE AND created_at < $1::DATE + INTERVAL '1 day'), 0)
)
ON CONFLICT (date) DO UPDATE SET
total_users = EXCLUDED.total_users,
total_projects = EXCLUDED.total_projects,
total_commits = EXCLUDED.total_commits,
total_submissions = EXCLUDED.total_submissions,
total_medias = EXCLUDED.total_medias,
total_wikis = EXCLUDED.total_wikis,
total_entities = EXCLUDED.total_entities,
total_geometries = EXCLUDED.total_geometries,
total_storage_bytes = EXCLUDED.total_storage_bytes,
new_users = EXCLUDED.new_users,
new_projects = EXCLUDED.new_projects,
new_commits = EXCLUDED.new_commits,
new_submissions = EXCLUDED.new_submissions,
new_medias = EXCLUDED.new_medias,
new_wikis = EXCLUDED.new_wikis,
new_entities = EXCLUDED.new_entities,
new_geometries = EXCLUDED.new_geometries,
new_storage_bytes = EXCLUDED.new_storage_bytes
RETURNING id, date, total_users, total_projects, total_commits, total_submissions, total_medias, total_wikis, total_entities, total_geometries, total_storage_bytes, new_users, new_projects, new_commits, new_submissions, new_medias, new_wikis, new_entities, new_geometries, new_storage_bytes, created_at
`
func (q *Queries) UpsertSystemStatistics(ctx context.Context, date pgtype.Date) (SystemStatistic, error) {
row := q.db.QueryRow(ctx, upsertSystemStatistics, date)
var i SystemStatistic
err := row.Scan(
&i.ID,
&i.Date,
&i.TotalUsers,
&i.TotalProjects,
&i.TotalCommits,
&i.TotalSubmissions,
&i.TotalMedias,
&i.TotalWikis,
&i.TotalEntities,
&i.TotalGeometries,
&i.TotalStorageBytes,
&i.NewUsers,
&i.NewProjects,
&i.NewCommits,
&i.NewSubmissions,
&i.NewMedias,
&i.NewWikis,
&i.NewEntities,
&i.NewGeometries,
&i.NewStorageBytes,
&i.CreatedAt,
)
return i, err
}