You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
193 lines
4.6 KiB
193 lines
4.6 KiB
package mysql
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"encoding/json"
|
|
"git.aiterp.net/stufflog3/stufflog3/entities"
|
|
"git.aiterp.net/stufflog3/stufflog3/internal/genutils"
|
|
"git.aiterp.net/stufflog3/stufflog3/models"
|
|
"git.aiterp.net/stufflog3/stufflog3/ports/mysql/mysqlcore"
|
|
"github.com/Masterminds/squirrel"
|
|
)
|
|
|
|
type statsRepository struct {
|
|
db *sql.DB
|
|
q *mysqlcore.Queries
|
|
}
|
|
|
|
func (r *statsRepository) Find(ctx context.Context, scopeID, statID int) (*entities.Stat, error) {
|
|
row, err := r.q.GetStat(ctx, mysqlcore.GetStatParams{ScopeID: scopeID, ID: statID})
|
|
if err != nil {
|
|
if err == sql.ErrNoRows {
|
|
return nil, models.NotFoundError("Stat")
|
|
}
|
|
|
|
return nil, err
|
|
}
|
|
|
|
var allowedAmounts []models.StatAllowedAmount
|
|
if row.AllowedAmounts.Valid {
|
|
allowedAmounts = make([]models.StatAllowedAmount, 0, 8)
|
|
_ = json.Unmarshal(row.AllowedAmounts.RawMessage, &allowedAmounts)
|
|
if len(allowedAmounts) == 0 {
|
|
allowedAmounts = nil
|
|
}
|
|
}
|
|
|
|
return &entities.Stat{
|
|
ID: row.ID,
|
|
ScopeID: row.ScopeID,
|
|
Name: row.Name,
|
|
Weight: row.Weight,
|
|
Description: row.Description,
|
|
AllowedAmounts: allowedAmounts,
|
|
Primary: row.IsPrimary,
|
|
}, nil
|
|
}
|
|
|
|
func (r *statsRepository) List(ctx context.Context, scopeIDs ...int) ([]entities.Stat, error) {
|
|
if len(scopeIDs) == 0 {
|
|
return []entities.Stat{}, nil
|
|
} else if len(scopeIDs) == 1 {
|
|
rows, err := r.q.ListStats(ctx, scopeIDs[0])
|
|
if err != nil {
|
|
if err == sql.ErrNoRows {
|
|
return nil, models.NotFoundError("Stat")
|
|
}
|
|
|
|
return nil, err
|
|
}
|
|
|
|
res := make([]entities.Stat, 0, len(rows))
|
|
for _, row := range rows {
|
|
var allowedAmounts []models.StatAllowedAmount
|
|
if row.AllowedAmounts.Valid {
|
|
allowedAmounts = make([]models.StatAllowedAmount, 0, 8)
|
|
_ = json.Unmarshal(row.AllowedAmounts.RawMessage, &allowedAmounts)
|
|
if len(allowedAmounts) == 0 {
|
|
allowedAmounts = nil
|
|
}
|
|
}
|
|
|
|
res = append(res, entities.Stat{
|
|
ID: row.ID,
|
|
ScopeID: row.ScopeID,
|
|
Name: row.Name,
|
|
Weight: row.Weight,
|
|
Description: row.Description,
|
|
AllowedAmounts: allowedAmounts,
|
|
Primary: row.IsPrimary,
|
|
})
|
|
}
|
|
|
|
return res, nil
|
|
}
|
|
|
|
rows, err := squirrel.
|
|
Select("id, scope_id, name, description, weight, allowed_amounts, is_primary").
|
|
From("stat").
|
|
Where(squirrel.Eq{"scope_id": scopeIDs}).
|
|
RunWith(r.db).
|
|
Query()
|
|
if err == sql.ErrNoRows {
|
|
return []entities.Stat{}, nil
|
|
} else if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
stats := make([]entities.Stat, 0, 16)
|
|
for rows.Next() {
|
|
var row mysqlcore.Stat
|
|
if err := rows.Scan(
|
|
&row.ID,
|
|
&row.ScopeID,
|
|
&row.Name,
|
|
&row.Description,
|
|
&row.Weight,
|
|
&row.AllowedAmounts,
|
|
&row.IsPrimary,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
stats = append(stats, entities.Stat{
|
|
ID: row.ID,
|
|
ScopeID: row.ScopeID,
|
|
Name: row.Name,
|
|
Weight: row.Weight,
|
|
Description: row.Description,
|
|
Primary: row.IsPrimary,
|
|
AllowedAmounts: genutils.ParseJSONArray[models.StatAllowedAmount](row.AllowedAmounts.RawMessage),
|
|
})
|
|
}
|
|
|
|
if err := rows.Close(); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return stats, nil
|
|
}
|
|
|
|
func (r *statsRepository) Insert(ctx context.Context, stat entities.Stat) (*entities.Stat, error) {
|
|
res, err := r.q.InsertStat(ctx, mysqlcore.InsertStatParams{
|
|
ScopeID: stat.ScopeID,
|
|
Name: stat.Name,
|
|
Description: stat.Description,
|
|
Weight: stat.Weight,
|
|
IsPrimary: stat.Primary,
|
|
AllowedAmounts: sqlJsonPtr(stat.AllowedAmounts),
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
id, err := res.LastInsertId()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
stat.ID = int(id)
|
|
return &stat, nil
|
|
}
|
|
|
|
func (r *statsRepository) Update(ctx context.Context, stat entities.Stat, update models.StatUpdate) error {
|
|
stat.Update(update)
|
|
|
|
return r.q.UpdateStat(ctx, mysqlcore.UpdateStatParams{
|
|
Name: stat.Name,
|
|
Description: stat.Description,
|
|
Weight: stat.Weight,
|
|
AllowedAmounts: sqlJsonPtr(stat.AllowedAmounts),
|
|
IsPrimary: stat.Primary,
|
|
ID: stat.ID,
|
|
ScopeID: stat.ScopeID,
|
|
})
|
|
}
|
|
|
|
func (r *statsRepository) Delete(ctx context.Context, stat entities.Stat) error {
|
|
tx, err := r.db.BeginTx(ctx, nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer tx.Rollback()
|
|
q := r.q.WithTx(tx)
|
|
|
|
err = q.ClearItemStatProgressByStat(ctx, stat.ID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = q.ClearProjectRequirementStatsByStat(ctx, stat.ID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = q.DeleteStat(ctx, mysqlcore.DeleteStatParams{ScopeID: stat.ScopeID, ID: stat.ID})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return tx.Commit()
|
|
}
|