171 lines
4.4 KiB
Go
171 lines
4.4 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
"github.com/Kichiyaki/gopgutil/v10"
|
|
"github.com/pkg/errors"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/go-pg/pg/v10"
|
|
|
|
"gitea.dwysokinski.me/zdam-egzamin-zawodowy/backend/fstorage"
|
|
"gitea.dwysokinski.me/zdam-egzamin-zawodowy/backend/internal/model"
|
|
"gitea.dwysokinski.me/zdam-egzamin-zawodowy/backend/internal/question"
|
|
"gitea.dwysokinski.me/zdam-egzamin-zawodowy/backend/util/errorutil"
|
|
)
|
|
|
|
type PGRepositoryConfig struct {
|
|
DB *pg.DB
|
|
FileStorage fstorage.FileStorage
|
|
}
|
|
|
|
type PGRepository struct {
|
|
*pg.DB
|
|
*repository
|
|
}
|
|
|
|
var _ question.Repository = &PGRepository{}
|
|
|
|
func NewPGRepository(cfg *PGRepositoryConfig) (*PGRepository, error) {
|
|
if cfg == nil || cfg.DB == nil {
|
|
return nil, errors.New("cfg.DB is required")
|
|
}
|
|
if cfg.FileStorage == nil {
|
|
return nil, errors.New("cfg.FileStorage is required")
|
|
}
|
|
return &PGRepository{
|
|
cfg.DB,
|
|
&repository{
|
|
fileStorage: cfg.FileStorage,
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
func (repo *PGRepository) Store(ctx context.Context, input *model.QuestionInput) (*model.Question, error) {
|
|
item := input.ToQuestion()
|
|
baseQuery := repo.
|
|
Model(item).
|
|
Context(ctx).
|
|
Returning("*")
|
|
if _, err := baseQuery.
|
|
Clone().
|
|
Insert(); err != nil {
|
|
return nil, handleInsertAndUpdateError(err)
|
|
}
|
|
|
|
repo.saveImages(item, input)
|
|
if _, err := baseQuery.
|
|
Clone().
|
|
WherePK().
|
|
Set("image = ?", item.Image).
|
|
Set("answer_a_image = ?", item.AnswerAImage).
|
|
Set("answer_b_image = ?", item.AnswerBImage).
|
|
Set("answer_c_image = ?", item.AnswerCImage).
|
|
Set("answer_d_image = ?", item.AnswerDImage).
|
|
Update(); err != nil && err != pg.ErrNoRows {
|
|
return nil, errorutil.Wrap(err, messageFailedToSaveModel)
|
|
}
|
|
|
|
return item, nil
|
|
}
|
|
|
|
func (repo *PGRepository) UpdateOneByID(ctx context.Context, id int, input *model.QuestionInput) (*model.Question, error) {
|
|
item := &model.Question{}
|
|
baseQuery := repo.
|
|
Model(item).
|
|
Context(ctx).
|
|
Returning("*").
|
|
Where(gopgutil.BuildConditionEquals("?"), gopgutil.AddAliasToColumnName("id", "question"), id).
|
|
Set("updated_at = ?", time.Now())
|
|
|
|
if _, err := baseQuery.
|
|
Clone().
|
|
Apply(input.ApplyUpdate).
|
|
Update(); err != nil && err != pg.ErrNoRows {
|
|
return nil, handleInsertAndUpdateError(err)
|
|
}
|
|
|
|
repo.saveImages(item, input)
|
|
repo.deleteImagesBasedOnInput(item, input)
|
|
|
|
if _, err := baseQuery.
|
|
Clone().
|
|
Set("image = ?", item.Image).
|
|
Set("answer_a_image = ?", item.AnswerAImage).
|
|
Set("answer_b_image = ?", item.AnswerBImage).
|
|
Set("answer_c_image = ?", item.AnswerCImage).
|
|
Set("answer_d_image = ?", item.AnswerDImage).
|
|
Update(); err != nil && err != pg.ErrNoRows {
|
|
return nil, handleInsertAndUpdateError(err)
|
|
}
|
|
|
|
return item, nil
|
|
}
|
|
|
|
func (repo *PGRepository) Delete(ctx context.Context, f *model.QuestionFilter) ([]*model.Question, error) {
|
|
items := make([]*model.Question, 0)
|
|
if _, err := repo.
|
|
Model(&items).
|
|
Context(ctx).
|
|
Returning("*").
|
|
Apply(f.Where).
|
|
Delete(); err != nil && err != pg.ErrNoRows {
|
|
return nil, errorutil.Wrap(err, messageFailedToDeleteModel)
|
|
}
|
|
|
|
go repo.getAllImagesAndDelete(items)
|
|
|
|
return items, nil
|
|
}
|
|
|
|
func (repo *PGRepository) Fetch(ctx context.Context, cfg *question.FetchConfig) ([]*model.Question, int, error) {
|
|
var err error
|
|
items := make([]*model.Question, 0)
|
|
total := 0
|
|
query := repo.
|
|
Model(&items).
|
|
Context(ctx).
|
|
Limit(cfg.Limit).
|
|
Offset(cfg.Offset).
|
|
Apply(cfg.Filter.Where).
|
|
Apply(gopgutil.OrderAppender{
|
|
Orders: cfg.Sort,
|
|
}.Apply)
|
|
|
|
if cfg.Count {
|
|
total, err = query.SelectAndCount()
|
|
} else {
|
|
err = query.Select()
|
|
}
|
|
if err != nil && err != pg.ErrNoRows {
|
|
return nil, 0, errorutil.Wrap(err, messageFailedToFetchModel)
|
|
}
|
|
return items, total, nil
|
|
}
|
|
|
|
func (repo *PGRepository) GenerateTest(ctx context.Context, cfg *question.GenerateTestConfig) ([]*model.Question, error) {
|
|
subquery := repo.
|
|
Model(&model.Question{}).
|
|
Column("id").
|
|
Where(gopgutil.BuildConditionArray("qualification_id"), pg.Array(cfg.Qualifications)).
|
|
OrderExpr("random()").
|
|
Limit(cfg.Limit)
|
|
items := make([]*model.Question, 0)
|
|
if err := repo.
|
|
Model(&items).
|
|
Context(ctx).
|
|
Where(gopgutil.BuildConditionIn("id"), subquery).
|
|
Select(); err != nil && err != pg.ErrNoRows {
|
|
return nil, errorutil.Wrap(err, messageFailedToFetchModel)
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
func handleInsertAndUpdateError(err error) error {
|
|
if strings.Contains(err.Error(), "questions_from_content_correct_answer_qualification_id_key") {
|
|
return errorutil.Wrap(err, messageSimilarRecordExists)
|
|
}
|
|
return errorutil.Wrap(err, messageFailedToSaveModel)
|
|
}
|