188 lines
4.8 KiB
Go
188 lines
4.8 KiB
Go
package bundb
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
|
|
"gitea.dwysokinski.me/twhelp/core/internal/domain"
|
|
"github.com/uptrace/bun"
|
|
"go.opentelemetry.io/otel/codes"
|
|
)
|
|
|
|
type Ennoblement struct {
|
|
db *bun.DB
|
|
}
|
|
|
|
func NewEnnoblement(db *bun.DB) *Ennoblement {
|
|
return &Ennoblement{db: db}
|
|
}
|
|
|
|
func (e *Ennoblement) Create(ctx context.Context, params ...domain.CreateEnnoblementParams) error {
|
|
ctx, span := tracer.Start(ctx, "Ennoblement.Create")
|
|
defer span.End()
|
|
|
|
if len(params) == 0 {
|
|
return nil
|
|
}
|
|
|
|
ennoblements := make([]model.Ennoblement, 0, len(params))
|
|
for _, p := range params {
|
|
ennoblements = append(ennoblements, model.NewEnnoblement(p))
|
|
}
|
|
if _, err := e.db.NewInsert().
|
|
Model(&ennoblements).
|
|
Returning("NULL").
|
|
Ignore().
|
|
Exec(ctx); err != nil {
|
|
span.RecordError(err)
|
|
span.SetStatus(codes.Error, err.Error())
|
|
return fmt.Errorf("something went wrong while inserting ennoblements into the db: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (e *Ennoblement) List(
|
|
ctx context.Context,
|
|
params domain.ListEnnoblementsParams,
|
|
) ([]domain.EnnoblementWithRelations, int64, error) {
|
|
ctx, span := tracer.Start(ctx, "Ennoblement.List")
|
|
defer span.End()
|
|
|
|
var ennoblements []model.Ennoblement
|
|
var count int
|
|
var err error
|
|
|
|
paramsApplier := listEnnoblementsParamsApplier{params}
|
|
|
|
base := e.db.NewSelect().
|
|
Model(&model.Ennoblement{}).
|
|
Order("ennoblement.server_key ASC").
|
|
Apply(paramsApplier.applyFilters).
|
|
Apply(paramsApplier.applyPagination)
|
|
base, err = paramsApplier.applySort(base)
|
|
if err != nil {
|
|
span.RecordError(err)
|
|
span.SetStatus(codes.Error, err.Error())
|
|
return nil, 0, fmt.Errorf("listEnnoblementsParamsApplier.applySort: %w", err)
|
|
}
|
|
|
|
q := e.db.NewSelect().
|
|
With("ennoblements_base", base).
|
|
Model(&ennoblements).
|
|
ModelTableExpr("ennoblements_base AS ennoblement").
|
|
Apply(paramsApplier.applyRelations)
|
|
|
|
if params.Count {
|
|
count, err = scanAndCount(ctx, base, q)
|
|
} else {
|
|
err = q.Scan(ctx)
|
|
}
|
|
if err != nil && !errors.Is(err, sql.ErrNoRows) {
|
|
span.RecordError(err)
|
|
span.SetStatus(codes.Error, err.Error())
|
|
return nil, 0, fmt.Errorf("couldn't select ennoblements from the db: %w", err)
|
|
}
|
|
|
|
result := make([]domain.EnnoblementWithRelations, 0, len(ennoblements))
|
|
for _, ennoblement := range ennoblements {
|
|
result = append(result, ennoblement.ToDomainWithRelations())
|
|
}
|
|
|
|
return result, int64(count), nil
|
|
}
|
|
|
|
type listEnnoblementsParamsApplier struct {
|
|
params domain.ListEnnoblementsParams
|
|
}
|
|
|
|
func (l listEnnoblementsParamsApplier) applyRelations(q *bun.SelectQuery) *bun.SelectQuery {
|
|
if l.params.IncludeVillage {
|
|
q = q.Relation("Village", func(q *bun.SelectQuery) *bun.SelectQuery {
|
|
return q.Column(villageMetaColumns...)
|
|
})
|
|
}
|
|
|
|
if l.params.IncludeNewOwner {
|
|
q = q.Relation("NewOwner", func(q *bun.SelectQuery) *bun.SelectQuery {
|
|
return q.Column(playerMetaColumns...)
|
|
})
|
|
}
|
|
|
|
if l.params.IncludeNewTribe {
|
|
q = q.Relation("NewTribe", func(q *bun.SelectQuery) *bun.SelectQuery {
|
|
return q.Column(tribeMetaColumns...)
|
|
})
|
|
}
|
|
|
|
if l.params.IncludeOldOwner {
|
|
q = q.Relation("OldOwner", func(q *bun.SelectQuery) *bun.SelectQuery {
|
|
return q.Column(playerMetaColumns...)
|
|
})
|
|
}
|
|
|
|
if l.params.IncludeOldTribe {
|
|
q = q.Relation("OldTribe", func(q *bun.SelectQuery) *bun.SelectQuery {
|
|
return q.Column(tribeMetaColumns...)
|
|
})
|
|
}
|
|
|
|
return q
|
|
}
|
|
|
|
func (l listEnnoblementsParamsApplier) applyFilters(q *bun.SelectQuery) *bun.SelectQuery {
|
|
if l.params.ServerKeys != nil {
|
|
q = q.Where("ennoblement.server_key IN (?)", bun.In(l.params.ServerKeys))
|
|
}
|
|
|
|
if l.params.CreatedAtGTE.Valid {
|
|
q = q.Where("ennoblement.created_at >= ?", l.params.CreatedAtGTE.Time)
|
|
}
|
|
|
|
if l.params.CreatedAtLTE.Valid {
|
|
q = q.Where("ennoblement.created_at <= ?", l.params.CreatedAtLTE.Time)
|
|
}
|
|
|
|
return q
|
|
}
|
|
|
|
func (l listEnnoblementsParamsApplier) applySort(q *bun.SelectQuery) (*bun.SelectQuery, error) {
|
|
if len(l.params.Sort) == 0 {
|
|
return q, nil
|
|
}
|
|
|
|
orders := make([]string, 0, len(l.params.Sort))
|
|
for i, s := range l.params.Sort {
|
|
column, err := ennoblementSortByToColumn(s.By)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("ennoblementSortByToColumn (index=%d): %w", i, err)
|
|
}
|
|
|
|
direction, err := sortDirectionToString(s.Direction)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("sortDirectionToString (index=%d): %w", i, err)
|
|
}
|
|
|
|
orders = append(orders, column+" "+direction)
|
|
}
|
|
|
|
return q.Order(orders...), nil
|
|
}
|
|
|
|
func (l listEnnoblementsParamsApplier) applyPagination(q *bun.SelectQuery) *bun.SelectQuery {
|
|
return (paginationApplier{pagination: l.params.Pagination}).apply(q)
|
|
}
|
|
|
|
func ennoblementSortByToColumn(sortBy domain.EnnoblementSortBy) (string, error) {
|
|
switch sortBy {
|
|
case domain.EnnoblementSortByID:
|
|
return "ennoblement.id", nil
|
|
case domain.EnnoblementSortByCreatedAt:
|
|
return "ennoblement.created_at", nil
|
|
}
|
|
return "", fmt.Errorf("%w: %d", domain.ErrUnsupportedSortBy, sortBy)
|
|
}
|