2021-02-28 16:54:40 +00:00
|
|
|
package usecase
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2021-03-27 15:20:55 +00:00
|
|
|
"github.com/pkg/errors"
|
2021-05-09 09:59:37 +00:00
|
|
|
|
2022-09-20 16:46:47 +00:00
|
|
|
"gitea.dwysokinski.me/zdam-egzamin-zawodowy/backend/internal/model"
|
|
|
|
"gitea.dwysokinski.me/zdam-egzamin-zawodowy/backend/internal/question"
|
2021-02-28 16:54:40 +00:00
|
|
|
)
|
|
|
|
|
2021-03-05 18:52:15 +00:00
|
|
|
var (
|
2021-03-13 15:05:20 +00:00
|
|
|
imageValidMIMETypes = map[string]bool{
|
2021-03-05 18:52:15 +00:00
|
|
|
"image/jpeg": true,
|
|
|
|
"image/jpg": true,
|
|
|
|
"image/png": true,
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2021-02-28 16:54:40 +00:00
|
|
|
type Config struct {
|
2021-03-05 18:52:15 +00:00
|
|
|
QuestionRepository question.Repository
|
2021-02-28 16:54:40 +00:00
|
|
|
}
|
|
|
|
|
2021-07-14 05:13:51 +00:00
|
|
|
type Usecase struct {
|
|
|
|
questionRepository question.Repository
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ question.Usecase = &Usecase{}
|
|
|
|
|
|
|
|
func New(cfg *Config) (*Usecase, error) {
|
2021-03-05 18:52:15 +00:00
|
|
|
if cfg == nil || cfg.QuestionRepository == nil {
|
2021-05-14 13:34:26 +00:00
|
|
|
return nil, errors.New("cfg.QuestionRepository is required")
|
2021-02-28 16:54:40 +00:00
|
|
|
}
|
2021-07-14 05:13:51 +00:00
|
|
|
return &Usecase{
|
2021-03-05 18:52:15 +00:00
|
|
|
cfg.QuestionRepository,
|
2021-02-28 16:54:40 +00:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2021-07-14 05:13:51 +00:00
|
|
|
func (ucase *Usecase) Store(ctx context.Context, input *model.QuestionInput) (*model.Question, error) {
|
2021-03-13 15:05:20 +00:00
|
|
|
if err := validateInput(input.Sanitize(), validateOptions{false}); err != nil {
|
2021-02-28 16:54:40 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
2021-03-05 18:52:15 +00:00
|
|
|
return ucase.questionRepository.Store(ctx, input)
|
2021-02-28 16:54:40 +00:00
|
|
|
}
|
|
|
|
|
2021-07-14 05:13:51 +00:00
|
|
|
func (ucase *Usecase) UpdateOneByID(ctx context.Context, id int, input *model.QuestionInput) (*model.Question, error) {
|
2021-02-28 16:54:40 +00:00
|
|
|
if id <= 0 {
|
2021-03-27 15:20:55 +00:00
|
|
|
return nil, errors.New(messageInvalidID)
|
2021-02-28 16:54:40 +00:00
|
|
|
}
|
2021-03-13 15:05:20 +00:00
|
|
|
if err := validateInput(input.Sanitize(), validateOptions{true}); err != nil {
|
2021-02-28 16:54:40 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
2021-03-05 18:52:15 +00:00
|
|
|
item, err := ucase.questionRepository.UpdateOneByID(ctx,
|
|
|
|
id,
|
2021-02-28 16:54:40 +00:00
|
|
|
input)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2021-03-05 18:52:15 +00:00
|
|
|
if item == nil {
|
2021-03-27 15:20:55 +00:00
|
|
|
return nil, errors.New(messageItemNotFound)
|
2021-02-28 16:54:40 +00:00
|
|
|
}
|
2021-03-05 18:52:15 +00:00
|
|
|
return item, nil
|
2021-02-28 16:54:40 +00:00
|
|
|
}
|
|
|
|
|
2021-07-14 05:13:51 +00:00
|
|
|
func (ucase *Usecase) Delete(ctx context.Context, f *model.QuestionFilter) ([]*model.Question, error) {
|
2021-03-05 18:52:15 +00:00
|
|
|
return ucase.questionRepository.Delete(ctx, f)
|
2021-02-28 16:54:40 +00:00
|
|
|
}
|
|
|
|
|
2021-07-14 05:13:51 +00:00
|
|
|
func (ucase *Usecase) Fetch(ctx context.Context, cfg *question.FetchConfig) ([]*model.Question, int, error) {
|
2021-02-28 16:54:40 +00:00
|
|
|
if cfg == nil {
|
2021-03-05 18:52:15 +00:00
|
|
|
cfg = &question.FetchConfig{
|
2021-03-11 18:48:24 +00:00
|
|
|
Limit: question.FetchMaxLimit,
|
2021-02-28 16:54:40 +00:00
|
|
|
Count: true,
|
|
|
|
}
|
|
|
|
}
|
2021-03-11 18:48:24 +00:00
|
|
|
if cfg.Limit > question.FetchMaxLimit {
|
|
|
|
cfg.Limit = question.FetchMaxLimit
|
|
|
|
}
|
2021-05-09 09:59:37 +00:00
|
|
|
if len(cfg.Sort) > question.MaxOrders {
|
|
|
|
cfg.Sort = cfg.Sort[0:question.MaxOrders]
|
|
|
|
}
|
2021-03-05 18:52:15 +00:00
|
|
|
return ucase.questionRepository.Fetch(ctx, cfg)
|
2021-02-28 16:54:40 +00:00
|
|
|
}
|
|
|
|
|
2021-07-14 05:13:51 +00:00
|
|
|
func (ucase *Usecase) GetByID(ctx context.Context, id int) (*model.Question, error) {
|
2021-03-05 18:52:15 +00:00
|
|
|
items, _, err := ucase.Fetch(ctx, &question.FetchConfig{
|
2021-02-28 16:54:40 +00:00
|
|
|
Limit: 1,
|
|
|
|
Count: false,
|
2021-07-14 04:58:10 +00:00
|
|
|
Filter: &model.QuestionFilter{
|
2021-02-28 16:54:40 +00:00
|
|
|
ID: []int{id},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if len(items) == 0 {
|
2021-03-27 15:20:55 +00:00
|
|
|
return nil, errors.New(messageItemNotFound)
|
2021-02-28 16:54:40 +00:00
|
|
|
}
|
|
|
|
return items[0], nil
|
|
|
|
}
|
|
|
|
|
2021-07-14 05:13:51 +00:00
|
|
|
func (ucase *Usecase) GenerateTest(ctx context.Context, cfg *question.GenerateTestConfig) ([]*model.Question, error) {
|
2021-03-05 18:52:15 +00:00
|
|
|
if cfg == nil {
|
|
|
|
cfg = &question.GenerateTestConfig{
|
|
|
|
Limit: question.TestMaxLimit,
|
|
|
|
}
|
2021-02-28 16:54:40 +00:00
|
|
|
}
|
2021-03-05 18:52:15 +00:00
|
|
|
if cfg.Limit > question.TestMaxLimit {
|
|
|
|
cfg.Limit = question.TestMaxLimit
|
2021-02-28 16:54:40 +00:00
|
|
|
}
|
2021-03-05 18:52:15 +00:00
|
|
|
return ucase.questionRepository.GenerateTest(ctx, cfg)
|
2021-02-28 16:54:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type validateOptions struct {
|
2021-03-05 18:52:15 +00:00
|
|
|
allowNilValues bool
|
2021-02-28 16:54:40 +00:00
|
|
|
}
|
|
|
|
|
2021-07-14 04:58:10 +00:00
|
|
|
func validateInput(input *model.QuestionInput, opts validateOptions) error {
|
2021-02-28 16:54:40 +00:00
|
|
|
if input.IsEmpty() {
|
2021-03-27 15:20:55 +00:00
|
|
|
return errors.New(messageEmptyPayload)
|
2021-02-28 16:54:40 +00:00
|
|
|
}
|
|
|
|
|
2021-03-05 18:52:15 +00:00
|
|
|
if input.Content != nil {
|
|
|
|
if *input.Content == "" {
|
2021-03-27 15:20:55 +00:00
|
|
|
return errors.New(messageContentIsRequired)
|
2021-03-05 18:52:15 +00:00
|
|
|
}
|
|
|
|
} else if !opts.allowNilValues {
|
2021-03-27 15:20:55 +00:00
|
|
|
return errors.New(messageContentIsRequired)
|
2021-03-05 18:52:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if input.CorrectAnswer != nil {
|
|
|
|
if !input.CorrectAnswer.IsValid() {
|
2021-03-27 15:20:55 +00:00
|
|
|
return errors.New(messageCorrectAnswerIsInvalid)
|
2021-03-05 18:52:15 +00:00
|
|
|
}
|
|
|
|
} else if !opts.allowNilValues {
|
2021-03-27 15:20:55 +00:00
|
|
|
return errors.New(messageCorrectAnswerIsInvalid)
|
2021-03-05 18:52:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if input.QualificationID != nil {
|
|
|
|
if *input.QualificationID <= 0 {
|
2021-03-27 15:20:55 +00:00
|
|
|
return errors.New(messageQualificationIDIsRequired)
|
2021-03-05 18:52:15 +00:00
|
|
|
}
|
|
|
|
} else if !opts.allowNilValues {
|
2021-03-27 15:20:55 +00:00
|
|
|
return errors.New(messageQualificationIDIsRequired)
|
2021-03-05 18:52:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if input.AnswerA != nil {
|
2021-03-13 15:41:09 +00:00
|
|
|
if *input.AnswerA == "" {
|
2021-03-27 15:20:55 +00:00
|
|
|
return errors.Errorf(messageAnswerIsRequired, "A")
|
2021-03-05 18:52:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if input.AnswerB != nil {
|
2021-03-13 15:41:09 +00:00
|
|
|
if *input.AnswerA == "" {
|
2021-03-27 15:20:55 +00:00
|
|
|
return errors.Errorf(messageAnswerIsRequired, "B")
|
2021-03-05 18:52:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if input.AnswerC != nil {
|
2021-03-13 15:41:09 +00:00
|
|
|
if *input.AnswerC == "" {
|
2021-03-27 15:20:55 +00:00
|
|
|
return errors.Errorf(messageAnswerIsRequired, "C")
|
2021-03-05 18:52:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if input.AnswerD != nil {
|
2021-03-13 15:41:09 +00:00
|
|
|
if *input.AnswerD == "" {
|
2021-03-27 15:20:55 +00:00
|
|
|
return errors.Errorf(messageAnswerIsRequired, "D")
|
2021-03-05 18:52:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if input.Image != nil {
|
2021-03-14 09:37:56 +00:00
|
|
|
if !isValidMIMEType(input.Image.ContentType) {
|
2021-03-27 15:20:55 +00:00
|
|
|
return errors.Errorf(messageImageNotAcceptableMIMEType, "Obrazek pytanie")
|
2021-03-05 18:52:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if input.AnswerAImage != nil {
|
2021-03-14 09:37:56 +00:00
|
|
|
if !isValidMIMEType(input.AnswerAImage.ContentType) {
|
2021-03-27 15:20:55 +00:00
|
|
|
return errors.Errorf(messageImageNotAcceptableMIMEType, "Obrazek odpowiedź A")
|
2021-03-05 18:52:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if input.AnswerBImage != nil {
|
2021-03-14 09:37:56 +00:00
|
|
|
if !isValidMIMEType(input.AnswerBImage.ContentType) {
|
2021-03-27 15:20:55 +00:00
|
|
|
return errors.Errorf(messageImageNotAcceptableMIMEType, "Obrazek odpowiedź B")
|
2021-03-05 18:52:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if input.AnswerCImage != nil {
|
2021-03-14 09:37:56 +00:00
|
|
|
if !isValidMIMEType(input.AnswerCImage.ContentType) {
|
2021-03-27 15:20:55 +00:00
|
|
|
return errors.Errorf(messageImageNotAcceptableMIMEType, "Obrazek odpowiedź C")
|
2021-03-05 18:52:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if input.AnswerDImage != nil {
|
2021-03-14 09:37:56 +00:00
|
|
|
if !isValidMIMEType(input.AnswerDImage.ContentType) {
|
2021-03-27 15:20:55 +00:00
|
|
|
return errors.Errorf(messageImageNotAcceptableMIMEType, "Obrazek odpowiedź D")
|
2021-03-05 18:52:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if input.DeleteAnswerAImage != nil && input.AnswerA == nil && input.AnswerAImage == nil {
|
2021-03-27 15:20:55 +00:00
|
|
|
return errors.Errorf(messageCannotDeleteImageWithoutNewAnswer, "Obrazek odpowiedź A")
|
2021-03-05 18:52:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if input.DeleteAnswerBImage != nil && input.AnswerB == nil && input.AnswerBImage == nil {
|
2021-03-27 15:20:55 +00:00
|
|
|
return errors.Errorf(messageCannotDeleteImageWithoutNewAnswer, "Obrazek odpowiedź B")
|
2021-03-05 18:52:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if input.DeleteAnswerCImage != nil && input.AnswerC == nil && input.AnswerCImage == nil {
|
2021-03-27 15:20:55 +00:00
|
|
|
return errors.Errorf(messageCannotDeleteImageWithoutNewAnswer, "Obrazek odpowiedź C")
|
2021-03-05 18:52:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if input.DeleteAnswerDImage != nil && input.AnswerD == nil && input.AnswerDImage == nil {
|
2021-03-27 15:20:55 +00:00
|
|
|
return errors.Errorf(messageCannotDeleteImageWithoutNewAnswer, "Obrazek odpowiedź D")
|
2021-03-05 18:52:15 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if !opts.allowNilValues {
|
|
|
|
if input.AnswerA == nil && input.AnswerAImage == nil {
|
2021-03-27 15:20:55 +00:00
|
|
|
return errors.Errorf(messageAnswerIsRequired, "A")
|
2021-03-05 18:52:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if input.AnswerB == nil && input.AnswerBImage == nil {
|
2021-03-27 15:20:55 +00:00
|
|
|
return errors.Errorf(messageAnswerIsRequired, "B")
|
2021-03-05 18:52:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if input.AnswerC == nil && input.AnswerCImage == nil {
|
2021-03-27 15:20:55 +00:00
|
|
|
return errors.Errorf(messageAnswerIsRequired, "C")
|
2021-03-05 18:52:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if input.AnswerD == nil && input.AnswerDImage == nil {
|
2021-03-27 15:20:55 +00:00
|
|
|
return errors.Errorf(messageAnswerIsRequired, "D")
|
2021-02-28 16:54:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
2021-03-13 15:05:20 +00:00
|
|
|
|
2021-03-14 09:37:56 +00:00
|
|
|
func isValidMIMEType(contentType string) bool {
|
2021-03-13 15:05:20 +00:00
|
|
|
return imageValidMIMETypes[contentType]
|
|
|
|
}
|