refactor, add question.Usecase implementation
This commit is contained in:
parent
4746b4c153
commit
838a93b8b5
|
@ -8,7 +8,7 @@ import (
|
||||||
|
|
||||||
type Usecase interface {
|
type Usecase interface {
|
||||||
Store(ctx context.Context, input *models.ProfessionInput) (*models.Profession, error)
|
Store(ctx context.Context, input *models.ProfessionInput) (*models.Profession, error)
|
||||||
UpdateOne(ctx context.Context, id int, input *models.ProfessionInput) (*models.Profession, error)
|
UpdateOneByID(ctx context.Context, id int, input *models.ProfessionInput) (*models.Profession, error)
|
||||||
Delete(ctx context.Context, f *models.ProfessionFilter) ([]*models.Profession, error)
|
Delete(ctx context.Context, f *models.ProfessionFilter) ([]*models.Profession, error)
|
||||||
Fetch(ctx context.Context, cfg *FetchConfig) ([]*models.Profession, int, error)
|
Fetch(ctx context.Context, cfg *FetchConfig) ([]*models.Profession, int, error)
|
||||||
GetByID(ctx context.Context, id int) (*models.Profession, error)
|
GetByID(ctx context.Context, id int) (*models.Profession, error)
|
||||||
|
|
|
@ -3,7 +3,6 @@ package usecase
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/zdam-egzamin-zawodowy/backend/internal/models"
|
"github.com/zdam-egzamin-zawodowy/backend/internal/models"
|
||||||
"github.com/zdam-egzamin-zawodowy/backend/internal/profession"
|
"github.com/zdam-egzamin-zawodowy/backend/internal/profession"
|
||||||
|
@ -34,7 +33,7 @@ func (ucase *usecase) Store(ctx context.Context, input *models.ProfessionInput)
|
||||||
return ucase.professionRepository.Store(ctx, input)
|
return ucase.professionRepository.Store(ctx, input)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ucase *usecase) UpdateOne(ctx context.Context, id int, input *models.ProfessionInput) (*models.Profession, error) {
|
func (ucase *usecase) UpdateOneByID(ctx context.Context, id int, input *models.ProfessionInput) (*models.Profession, error) {
|
||||||
if id <= 0 {
|
if id <= 0 {
|
||||||
return nil, fmt.Errorf(messageInvalidID)
|
return nil, fmt.Errorf(messageInvalidID)
|
||||||
}
|
}
|
||||||
|
@ -114,11 +113,9 @@ func (ucase *usecase) validateInput(input *models.ProfessionInput, opts validate
|
||||||
}
|
}
|
||||||
|
|
||||||
if input.Name != nil {
|
if input.Name != nil {
|
||||||
trimmedName := strings.TrimSpace(*input.Name)
|
if *input.Name == "" {
|
||||||
input.Name = &trimmedName
|
|
||||||
if trimmedName == "" {
|
|
||||||
return fmt.Errorf(messageNameIsRequired)
|
return fmt.Errorf(messageNameIsRequired)
|
||||||
} else if len(trimmedName) > profession.MaxNameLength {
|
} else if len(*input.Name) > profession.MaxNameLength {
|
||||||
return fmt.Errorf(messageNameIsTooLong, profession.MaxNameLength)
|
return fmt.Errorf(messageNameIsTooLong, profession.MaxNameLength)
|
||||||
}
|
}
|
||||||
} else if !opts.nameCanBeNil {
|
} else if !opts.nameCanBeNil {
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
|
|
||||||
type Usecase interface {
|
type Usecase interface {
|
||||||
Store(ctx context.Context, input *models.QualificationInput) (*models.Qualification, error)
|
Store(ctx context.Context, input *models.QualificationInput) (*models.Qualification, error)
|
||||||
UpdateOne(ctx context.Context, id int, input *models.QualificationInput) (*models.Qualification, error)
|
UpdateOneByID(ctx context.Context, id int, input *models.QualificationInput) (*models.Qualification, error)
|
||||||
Delete(ctx context.Context, f *models.QualificationFilter) ([]*models.Qualification, error)
|
Delete(ctx context.Context, f *models.QualificationFilter) ([]*models.Qualification, error)
|
||||||
Fetch(ctx context.Context, cfg *FetchConfig) ([]*models.Qualification, int, error)
|
Fetch(ctx context.Context, cfg *FetchConfig) ([]*models.Qualification, int, error)
|
||||||
GetByID(ctx context.Context, id int) (*models.Qualification, error)
|
GetByID(ctx context.Context, id int) (*models.Qualification, error)
|
||||||
|
|
|
@ -3,7 +3,6 @@ package usecase
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/zdam-egzamin-zawodowy/backend/internal/models"
|
"github.com/zdam-egzamin-zawodowy/backend/internal/models"
|
||||||
"github.com/zdam-egzamin-zawodowy/backend/internal/qualification"
|
"github.com/zdam-egzamin-zawodowy/backend/internal/qualification"
|
||||||
|
@ -34,7 +33,7 @@ func (ucase *usecase) Store(ctx context.Context, input *models.QualificationInpu
|
||||||
return ucase.qualificationRepository.Store(ctx, input)
|
return ucase.qualificationRepository.Store(ctx, input)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ucase *usecase) UpdateOne(ctx context.Context, id int, input *models.QualificationInput) (*models.Qualification, error) {
|
func (ucase *usecase) UpdateOneByID(ctx context.Context, id int, input *models.QualificationInput) (*models.Qualification, error) {
|
||||||
if id <= 0 {
|
if id <= 0 {
|
||||||
return nil, fmt.Errorf(messageInvalidID)
|
return nil, fmt.Errorf(messageInvalidID)
|
||||||
}
|
}
|
||||||
|
@ -114,11 +113,9 @@ func (ucase *usecase) validateInput(input *models.QualificationInput, opts valid
|
||||||
}
|
}
|
||||||
|
|
||||||
if input.Name != nil {
|
if input.Name != nil {
|
||||||
trimmedName := strings.TrimSpace(*input.Name)
|
if *input.Name == "" {
|
||||||
input.Name = &trimmedName
|
|
||||||
if trimmedName == "" {
|
|
||||||
return fmt.Errorf(messageNameIsRequired)
|
return fmt.Errorf(messageNameIsRequired)
|
||||||
} else if len(trimmedName) > qualification.MaxNameLength {
|
} else if len(*input.Name) > qualification.MaxNameLength {
|
||||||
return fmt.Errorf(messageNameIsTooLong, qualification.MaxNameLength)
|
return fmt.Errorf(messageNameIsTooLong, qualification.MaxNameLength)
|
||||||
}
|
}
|
||||||
} else if !opts.allowNilValues {
|
} else if !opts.allowNilValues {
|
||||||
|
@ -126,9 +123,7 @@ func (ucase *usecase) validateInput(input *models.QualificationInput, opts valid
|
||||||
}
|
}
|
||||||
|
|
||||||
if input.Code != nil {
|
if input.Code != nil {
|
||||||
trimmedCode := strings.TrimSpace(*input.Code)
|
if *input.Code == "" {
|
||||||
input.Code = &trimmedCode
|
|
||||||
if trimmedCode == "" {
|
|
||||||
return fmt.Errorf(messageCodeIsRequired)
|
return fmt.Errorf(messageCodeIsRequired)
|
||||||
}
|
}
|
||||||
} else if !opts.allowNilValues {
|
} else if !opts.allowNilValues {
|
||||||
|
|
|
@ -2,4 +2,5 @@ package question
|
||||||
|
|
||||||
const (
|
const (
|
||||||
DefaultLimit = 100
|
DefaultLimit = 100
|
||||||
|
TestMaxLimit = 40
|
||||||
)
|
)
|
||||||
|
|
|
@ -102,7 +102,7 @@ func (repo *pgRepository) Delete(ctx context.Context, f *models.QuestionFilter)
|
||||||
return nil, errorutils.Wrap(err, messageFailedToDeleteModel)
|
return nil, errorutils.Wrap(err, messageFailedToDeleteModel)
|
||||||
}
|
}
|
||||||
|
|
||||||
go repo.getAllFilenamesAndDeleteImages(items)
|
go repo.getAllImagesAndDelete(items)
|
||||||
|
|
||||||
return items, nil
|
return items, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,20 +50,20 @@ func (repo *repository) saveImages(destination *models.Question, input *models.Q
|
||||||
destination.AnswerDImage = filenames[4]
|
destination.AnswerDImage = filenames[4]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *repository) deleteImages(filenames []string) {
|
func (repo *repository) deleteImages(images []string) {
|
||||||
for _, filename := range filenames {
|
for _, image := range images {
|
||||||
repo.fileStorage.Remove(filename)
|
repo.fileStorage.Remove(image)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *repository) deleteImagesBasedOnInput(question *models.Question, input *models.QuestionInput) {
|
func (repo *repository) deleteImagesBasedOnInput(question *models.Question, input *models.QuestionInput) {
|
||||||
filenames := []string{}
|
images := []string{}
|
||||||
|
|
||||||
if input.DeleteImage != nil &&
|
if input.DeleteImage != nil &&
|
||||||
*input.DeleteImage &&
|
*input.DeleteImage &&
|
||||||
input.Image == nil &&
|
input.Image == nil &&
|
||||||
question.Image != "" {
|
question.Image != "" {
|
||||||
filenames = append(filenames, question.Image)
|
images = append(images, question.Image)
|
||||||
question.Image = ""
|
question.Image = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ func (repo *repository) deleteImagesBasedOnInput(question *models.Question, inpu
|
||||||
*input.DeleteAnswerAImage &&
|
*input.DeleteAnswerAImage &&
|
||||||
input.AnswerAImage == nil &&
|
input.AnswerAImage == nil &&
|
||||||
question.AnswerAImage != "" {
|
question.AnswerAImage != "" {
|
||||||
filenames = append(filenames, question.AnswerAImage)
|
images = append(images, question.AnswerAImage)
|
||||||
question.AnswerAImage = ""
|
question.AnswerAImage = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ func (repo *repository) deleteImagesBasedOnInput(question *models.Question, inpu
|
||||||
*input.DeleteAnswerBImage &&
|
*input.DeleteAnswerBImage &&
|
||||||
input.AnswerBImage == nil &&
|
input.AnswerBImage == nil &&
|
||||||
question.AnswerBImage != "" {
|
question.AnswerBImage != "" {
|
||||||
filenames = append(filenames, question.AnswerBImage)
|
images = append(images, question.AnswerBImage)
|
||||||
question.AnswerBImage = ""
|
question.AnswerBImage = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ func (repo *repository) deleteImagesBasedOnInput(question *models.Question, inpu
|
||||||
*input.DeleteAnswerCImage &&
|
*input.DeleteAnswerCImage &&
|
||||||
input.AnswerCImage == nil &&
|
input.AnswerCImage == nil &&
|
||||||
question.AnswerCImage != "" {
|
question.AnswerCImage != "" {
|
||||||
filenames = append(filenames, question.AnswerCImage)
|
images = append(images, question.AnswerCImage)
|
||||||
question.AnswerCImage = ""
|
question.AnswerCImage = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,33 +95,33 @@ func (repo *repository) deleteImagesBasedOnInput(question *models.Question, inpu
|
||||||
*input.DeleteAnswerDImage &&
|
*input.DeleteAnswerDImage &&
|
||||||
input.AnswerDImage == nil &&
|
input.AnswerDImage == nil &&
|
||||||
question.AnswerDImage != "" {
|
question.AnswerDImage != "" {
|
||||||
filenames = append(filenames, question.AnswerDImage)
|
images = append(images, question.AnswerDImage)
|
||||||
question.AnswerDImage = ""
|
question.AnswerDImage = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
repo.deleteImages(filenames)
|
repo.deleteImages(images)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *repository) getAllFilenamesAndDeleteImages(questions []*models.Question) {
|
func (repo *repository) getAllImagesAndDelete(questions []*models.Question) {
|
||||||
filenames := []string{}
|
images := []string{}
|
||||||
|
|
||||||
for _, question := range questions {
|
for _, question := range questions {
|
||||||
if question.Image != "" {
|
if question.Image != "" {
|
||||||
filenames = append(filenames, question.Image)
|
images = append(images, question.Image)
|
||||||
}
|
}
|
||||||
if question.AnswerAImage != "" {
|
if question.AnswerAImage != "" {
|
||||||
filenames = append(filenames, question.AnswerAImage)
|
images = append(images, question.AnswerAImage)
|
||||||
}
|
}
|
||||||
if question.AnswerBImage != "" {
|
if question.AnswerBImage != "" {
|
||||||
filenames = append(filenames, question.AnswerBImage)
|
images = append(images, question.AnswerBImage)
|
||||||
}
|
}
|
||||||
if question.AnswerCImage != "" {
|
if question.AnswerCImage != "" {
|
||||||
filenames = append(filenames, question.AnswerCImage)
|
images = append(images, question.AnswerCImage)
|
||||||
}
|
}
|
||||||
if question.AnswerDImage != "" {
|
if question.AnswerDImage != "" {
|
||||||
filenames = append(filenames, question.AnswerDImage)
|
images = append(images, question.AnswerDImage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
repo.deleteImages(filenames)
|
repo.deleteImages(images)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,9 @@ import (
|
||||||
|
|
||||||
type Usecase interface {
|
type Usecase interface {
|
||||||
Store(ctx context.Context, input *models.QuestionInput) (*models.Question, error)
|
Store(ctx context.Context, input *models.QuestionInput) (*models.Question, error)
|
||||||
UpdateOne(ctx context.Context, id int, input *models.QuestionInput) (*models.Question, error)
|
UpdateOneByID(ctx context.Context, id int, input *models.QuestionInput) (*models.Question, error)
|
||||||
Delete(ctx context.Context, f *models.QuestionFilter) ([]*models.Question, error)
|
Delete(ctx context.Context, f *models.QuestionFilter) ([]*models.Question, error)
|
||||||
Fetch(ctx context.Context, cfg *FetchConfig) ([]*models.Question, int, error)
|
Fetch(ctx context.Context, cfg *FetchConfig) ([]*models.Question, int, error)
|
||||||
GetByID(ctx context.Context, id int) (*models.Question, error)
|
GetByID(ctx context.Context, id int) (*models.Question, error)
|
||||||
|
GenerateTest(ctx context.Context, cfg *GenerateTestConfig) ([]*models.Question, error)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
package usecase
|
package usecase
|
||||||
|
|
||||||
const (
|
const (
|
||||||
messageInvalidID = "Niepoprawne ID."
|
messageInvalidID = "Niepoprawne ID."
|
||||||
messageItemNotFound = "Nie znaleziono zawodu."
|
messageItemNotFound = "Nie znaleziono pytania."
|
||||||
messageEmptyPayload = "Nie wprowadzono jakichkolwiek danych."
|
messageEmptyPayload = "Nie wprowadzono jakichkolwiek danych."
|
||||||
messageNameIsRequired = "Nazwa zawodu jest wymagana."
|
messageContentIsRequired = "Treść pytania jest wymagana."
|
||||||
messageNameIsTooLong = "Nazwa zawodu może się składać z maksymalnie %d znaków."
|
messageCorrectAnswerIsInvalid = "Odpowiedź poprawna na pytanie jest nieprawidłowa."
|
||||||
|
messageQualificationIDIsRequired = "ID kwalifikacji jest wymagane."
|
||||||
|
messageAnswerIsRequired = "Odpowiedź %s jest wymagana."
|
||||||
|
messageAnswerIsInvalid = "Odpowiedź %s jest nieprawidłowa."
|
||||||
|
messageImageNotAcceptableMIMEType = "%s: Oczekiwany jest obrazek w formacie png or jpg."
|
||||||
|
messageCannotDeleteImageWithoutNewAnswer = "%s: Nie możesz usunąć obrazka i nie wprowadzić żadnej odpowiedzi."
|
||||||
)
|
)
|
||||||
|
|
|
@ -3,78 +3,83 @@ package usecase
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/zdam-egzamin-zawodowy/backend/internal/models"
|
"github.com/zdam-egzamin-zawodowy/backend/internal/models"
|
||||||
"github.com/zdam-egzamin-zawodowy/backend/internal/profession"
|
"github.com/zdam-egzamin-zawodowy/backend/internal/question"
|
||||||
sqlutils "github.com/zdam-egzamin-zawodowy/backend/pkg/utils/sql"
|
sqlutils "github.com/zdam-egzamin-zawodowy/backend/pkg/utils/sql"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
imageAcceptedMIMETypes = map[string]bool{
|
||||||
|
"image/jpeg": true,
|
||||||
|
"image/jpg": true,
|
||||||
|
"image/png": true,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
type usecase struct {
|
type usecase struct {
|
||||||
professionRepository profession.Repository
|
questionRepository question.Repository
|
||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
ProfessionRepository profession.Repository
|
QuestionRepository question.Repository
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(cfg *Config) (profession.Usecase, error) {
|
func New(cfg *Config) (question.Usecase, error) {
|
||||||
if cfg == nil || cfg.ProfessionRepository == nil {
|
if cfg == nil || cfg.QuestionRepository == nil {
|
||||||
return nil, fmt.Errorf("profession/usecase: ProfessionRepository is required")
|
return nil, fmt.Errorf("question/usecase: cfg.QuestionRepository is required")
|
||||||
}
|
}
|
||||||
return &usecase{
|
return &usecase{
|
||||||
cfg.ProfessionRepository,
|
cfg.QuestionRepository,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ucase *usecase) Store(ctx context.Context, input *models.ProfessionInput) (*models.Profession, error) {
|
func (ucase *usecase) Store(ctx context.Context, input *models.QuestionInput) (*models.Question, error) {
|
||||||
if err := ucase.validateInput(input, validateOptions{false}); err != nil {
|
if err := ucase.validateInput(input, validateOptions{false}); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return ucase.professionRepository.Store(ctx, input)
|
return ucase.questionRepository.Store(ctx, input)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ucase *usecase) UpdateOne(ctx context.Context, id int, input *models.ProfessionInput) (*models.Profession, error) {
|
func (ucase *usecase) UpdateOneByID(ctx context.Context, id int, input *models.QuestionInput) (*models.Question, error) {
|
||||||
if id <= 0 {
|
if id <= 0 {
|
||||||
return nil, fmt.Errorf(messageInvalidID)
|
return nil, fmt.Errorf(messageInvalidID)
|
||||||
}
|
}
|
||||||
if err := ucase.validateInput(input, validateOptions{true}); err != nil {
|
if err := ucase.validateInput(input, validateOptions{true}); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
items, err := ucase.professionRepository.UpdateMany(ctx,
|
item, err := ucase.questionRepository.UpdateOneByID(ctx,
|
||||||
&models.ProfessionFilter{
|
id,
|
||||||
ID: []int{id},
|
|
||||||
},
|
|
||||||
input)
|
input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if len(items) == 0 {
|
if item == nil {
|
||||||
return nil, fmt.Errorf(messageItemNotFound)
|
return nil, fmt.Errorf(messageItemNotFound)
|
||||||
}
|
}
|
||||||
return items[0], nil
|
return item, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ucase *usecase) Delete(ctx context.Context, f *models.ProfessionFilter) ([]*models.Profession, error) {
|
func (ucase *usecase) Delete(ctx context.Context, f *models.QuestionFilter) ([]*models.Question, error) {
|
||||||
return ucase.professionRepository.Delete(ctx, f)
|
return ucase.questionRepository.Delete(ctx, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ucase *usecase) Fetch(ctx context.Context, cfg *profession.FetchConfig) ([]*models.Profession, int, error) {
|
func (ucase *usecase) Fetch(ctx context.Context, cfg *question.FetchConfig) ([]*models.Question, int, error) {
|
||||||
if cfg == nil {
|
if cfg == nil {
|
||||||
cfg = &profession.FetchConfig{
|
cfg = &question.FetchConfig{
|
||||||
Limit: profession.DefaultLimit,
|
Limit: question.DefaultLimit,
|
||||||
Count: true,
|
Count: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cfg.Sort = sqlutils.SanitizeSortExpressions(cfg.Sort)
|
cfg.Sort = sqlutils.SanitizeSortExpressions(cfg.Sort)
|
||||||
return ucase.professionRepository.Fetch(ctx, cfg)
|
return ucase.questionRepository.Fetch(ctx, cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ucase *usecase) GetByID(ctx context.Context, id int) (*models.Profession, error) {
|
func (ucase *usecase) GetByID(ctx context.Context, id int) (*models.Question, error) {
|
||||||
items, _, err := ucase.Fetch(ctx, &profession.FetchConfig{
|
items, _, err := ucase.Fetch(ctx, &question.FetchConfig{
|
||||||
Limit: 1,
|
Limit: 1,
|
||||||
Count: false,
|
Count: false,
|
||||||
Filter: &models.ProfessionFilter{
|
Filter: &models.QuestionFilter{
|
||||||
ID: []int{id},
|
ID: []int{id},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -87,42 +92,138 @@ func (ucase *usecase) GetByID(ctx context.Context, id int) (*models.Profession,
|
||||||
return items[0], nil
|
return items[0], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ucase *usecase) GetBySlug(ctx context.Context, slug string) (*models.Profession, error) {
|
func (ucase *usecase) GenerateTest(ctx context.Context, cfg *question.GenerateTestConfig) ([]*models.Question, error) {
|
||||||
items, _, err := ucase.Fetch(ctx, &profession.FetchConfig{
|
if cfg == nil {
|
||||||
Limit: 1,
|
cfg = &question.GenerateTestConfig{
|
||||||
Count: false,
|
Limit: question.TestMaxLimit,
|
||||||
Filter: &models.ProfessionFilter{
|
}
|
||||||
Slug: []string{slug},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
if len(items) == 0 {
|
if cfg.Limit > question.TestMaxLimit {
|
||||||
return nil, fmt.Errorf(messageItemNotFound)
|
cfg.Limit = question.TestMaxLimit
|
||||||
}
|
}
|
||||||
return items[0], nil
|
return ucase.questionRepository.GenerateTest(ctx, cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
type validateOptions struct {
|
type validateOptions struct {
|
||||||
nameCanBeNil bool
|
allowNilValues bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ucase *usecase) validateInput(input *models.ProfessionInput, opts validateOptions) error {
|
func (ucase *usecase) validateInput(input *models.QuestionInput, opts validateOptions) error {
|
||||||
if input.IsEmpty() {
|
if input.IsEmpty() {
|
||||||
return fmt.Errorf(messageEmptyPayload)
|
return fmt.Errorf(messageEmptyPayload)
|
||||||
}
|
}
|
||||||
|
|
||||||
if input.Name != nil {
|
if input.Content != nil {
|
||||||
trimmedName := strings.TrimSpace(*input.Name)
|
if *input.Content == "" {
|
||||||
input.Name = &trimmedName
|
return fmt.Errorf(messageContentIsRequired)
|
||||||
if trimmedName == "" {
|
}
|
||||||
return fmt.Errorf(messageNameIsRequired)
|
} else if !opts.allowNilValues {
|
||||||
} else if len(trimmedName) > profession.MaxNameLength {
|
return fmt.Errorf(messageContentIsRequired)
|
||||||
return fmt.Errorf(messageNameIsTooLong, profession.MaxNameLength)
|
}
|
||||||
|
|
||||||
|
if input.CorrectAnswer != nil {
|
||||||
|
if !input.CorrectAnswer.IsValid() {
|
||||||
|
return fmt.Errorf(messageCorrectAnswerIsInvalid)
|
||||||
|
}
|
||||||
|
} else if !opts.allowNilValues {
|
||||||
|
return fmt.Errorf(messageCorrectAnswerIsInvalid)
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.QualificationID != nil {
|
||||||
|
if *input.QualificationID <= 0 {
|
||||||
|
return fmt.Errorf(messageQualificationIDIsRequired)
|
||||||
|
}
|
||||||
|
} else if !opts.allowNilValues {
|
||||||
|
return fmt.Errorf(messageQualificationIDIsRequired)
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.AnswerA != nil {
|
||||||
|
if !input.AnswerA.IsValid() {
|
||||||
|
return fmt.Errorf(messageAnswerIsInvalid, "A")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.AnswerB != nil {
|
||||||
|
if !input.AnswerB.IsValid() {
|
||||||
|
return fmt.Errorf(messageAnswerIsInvalid, "B")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.AnswerC != nil {
|
||||||
|
if !input.AnswerC.IsValid() {
|
||||||
|
return fmt.Errorf(messageAnswerIsInvalid, "C")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.AnswerD != nil {
|
||||||
|
if !input.AnswerD.IsValid() {
|
||||||
|
return fmt.Errorf(messageAnswerIsInvalid, "D")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.Image != nil {
|
||||||
|
if !imageAcceptedMIMETypes[input.Image.ContentType] {
|
||||||
|
return fmt.Errorf(messageImageNotAcceptableMIMEType, "Obrazek pytanie")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.AnswerAImage != nil {
|
||||||
|
if !imageAcceptedMIMETypes[input.AnswerAImage.ContentType] {
|
||||||
|
return fmt.Errorf(messageAnswerIsInvalid, "Obrazek odpowiedź A")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.AnswerBImage != nil {
|
||||||
|
if !imageAcceptedMIMETypes[input.AnswerBImage.ContentType] {
|
||||||
|
return fmt.Errorf(messageAnswerIsInvalid, "Obrazek odpowiedź B")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.AnswerCImage != nil {
|
||||||
|
if !imageAcceptedMIMETypes[input.AnswerCImage.ContentType] {
|
||||||
|
return fmt.Errorf(messageAnswerIsInvalid, "Obrazek odpowiedź C")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.AnswerDImage != nil {
|
||||||
|
if !imageAcceptedMIMETypes[input.AnswerDImage.ContentType] {
|
||||||
|
return fmt.Errorf(messageAnswerIsInvalid, "Obrazek odpowiedź D")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.DeleteAnswerAImage != nil && input.AnswerA == nil && input.AnswerAImage == nil {
|
||||||
|
return fmt.Errorf(messageCannotDeleteImageWithoutNewAnswer, "Obrazek odpowiedź A")
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.DeleteAnswerBImage != nil && input.AnswerB == nil && input.AnswerBImage == nil {
|
||||||
|
return fmt.Errorf(messageCannotDeleteImageWithoutNewAnswer, "Obrazek odpowiedź B")
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.DeleteAnswerCImage != nil && input.AnswerC == nil && input.AnswerCImage == nil {
|
||||||
|
return fmt.Errorf(messageCannotDeleteImageWithoutNewAnswer, "Obrazek odpowiedź C")
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.DeleteAnswerDImage != nil && input.AnswerD == nil && input.AnswerDImage == nil {
|
||||||
|
return fmt.Errorf(messageCannotDeleteImageWithoutNewAnswer, "Obrazek odpowiedź D")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if !opts.allowNilValues {
|
||||||
|
if input.AnswerA == nil && input.AnswerAImage == nil {
|
||||||
|
return fmt.Errorf(messageAnswerIsRequired, "A")
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.AnswerB == nil && input.AnswerBImage == nil {
|
||||||
|
return fmt.Errorf(messageAnswerIsRequired, "B")
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.AnswerC == nil && input.AnswerCImage == nil {
|
||||||
|
return fmt.Errorf(messageAnswerIsRequired, "C")
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.AnswerD == nil && input.AnswerDImage == nil {
|
||||||
|
return fmt.Errorf(messageAnswerIsRequired, "D")
|
||||||
}
|
}
|
||||||
} else if !opts.nameCanBeNil {
|
|
||||||
return fmt.Errorf(messageNameIsRequired)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
|
|
||||||
type Usecase interface {
|
type Usecase interface {
|
||||||
Store(ctx context.Context, input *models.UserInput) (*models.User, error)
|
Store(ctx context.Context, input *models.UserInput) (*models.User, error)
|
||||||
UpdateOne(ctx context.Context, id int, input *models.UserInput) (*models.User, error)
|
UpdateOneByID(ctx context.Context, id int, input *models.UserInput) (*models.User, error)
|
||||||
UpdateMany(ctx context.Context, f *models.UserFilter, input *models.UserInput) ([]*models.User, error)
|
UpdateMany(ctx context.Context, f *models.UserFilter, input *models.UserInput) ([]*models.User, error)
|
||||||
Delete(ctx context.Context, f *models.UserFilter) ([]*models.User, error)
|
Delete(ctx context.Context, f *models.UserFilter) ([]*models.User, error)
|
||||||
Fetch(ctx context.Context, cfg *FetchConfig) ([]*models.User, int, error)
|
Fetch(ctx context.Context, cfg *FetchConfig) ([]*models.User, int, error)
|
||||||
|
|
|
@ -3,7 +3,6 @@ package usecase
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/zdam-egzamin-zawodowy/backend/internal/models"
|
"github.com/zdam-egzamin-zawodowy/backend/internal/models"
|
||||||
"github.com/zdam-egzamin-zawodowy/backend/internal/user"
|
"github.com/zdam-egzamin-zawodowy/backend/internal/user"
|
||||||
|
@ -35,7 +34,7 @@ func (ucase *usecase) Store(ctx context.Context, input *models.UserInput) (*mode
|
||||||
return ucase.userRepository.Store(ctx, input)
|
return ucase.userRepository.Store(ctx, input)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ucase *usecase) UpdateOne(ctx context.Context, id int, input *models.UserInput) (*models.User, error) {
|
func (ucase *usecase) UpdateOneByID(ctx context.Context, id int, input *models.UserInput) (*models.User, error) {
|
||||||
if id <= 0 {
|
if id <= 0 {
|
||||||
return nil, fmt.Errorf(messageInvalidID)
|
return nil, fmt.Errorf(messageInvalidID)
|
||||||
}
|
}
|
||||||
|
@ -131,11 +130,10 @@ func (ucase *usecase) validateInput(input *models.UserInput, opts validateOption
|
||||||
}
|
}
|
||||||
|
|
||||||
if input.DisplayName != nil {
|
if input.DisplayName != nil {
|
||||||
trimmedDisplayName := strings.TrimSpace(*input.DisplayName)
|
displayNameLength := len(*input.DisplayName)
|
||||||
input.DisplayName = &trimmedDisplayName
|
if displayNameLength < user.MinDisplayNameLength {
|
||||||
if len(trimmedDisplayName) < user.MinDisplayNameLength {
|
|
||||||
return fmt.Errorf(messageDisplayNameIsRequired)
|
return fmt.Errorf(messageDisplayNameIsRequired)
|
||||||
} else if len(trimmedDisplayName) > user.MaxDisplayNameLength {
|
} else if displayNameLength > user.MaxDisplayNameLength {
|
||||||
return fmt.Errorf(messageDisplayNameIsTooLong, user.MaxDisplayNameLength)
|
return fmt.Errorf(messageDisplayNameIsTooLong, user.MaxDisplayNameLength)
|
||||||
}
|
}
|
||||||
} else if !opts.acceptNilValues {
|
} else if !opts.acceptNilValues {
|
||||||
|
@ -143,9 +141,7 @@ func (ucase *usecase) validateInput(input *models.UserInput, opts validateOption
|
||||||
}
|
}
|
||||||
|
|
||||||
if input.Email != nil {
|
if input.Email != nil {
|
||||||
trimmedEmail := strings.TrimSpace(*input.Email)
|
if !utils.IsEmailValid(*input.Email) {
|
||||||
input.Email = &trimmedEmail
|
|
||||||
if !utils.IsEmailValid(trimmedEmail) {
|
|
||||||
return fmt.Errorf(messageEmailIsInvalid)
|
return fmt.Errorf(messageEmailIsInvalid)
|
||||||
}
|
}
|
||||||
} else if !opts.acceptNilValues {
|
} else if !opts.acceptNilValues {
|
||||||
|
@ -153,9 +149,9 @@ func (ucase *usecase) validateInput(input *models.UserInput, opts validateOption
|
||||||
}
|
}
|
||||||
|
|
||||||
if input.Password != nil {
|
if input.Password != nil {
|
||||||
trimmedPassword := strings.ToLower(strings.TrimSpace(*input.Password))
|
password := *input.Password
|
||||||
input.Password = &trimmedPassword
|
passwordLength := len(password)
|
||||||
if len(trimmedPassword) > user.MaxPasswordLength || len(trimmedPassword) < user.MinPasswordLength {
|
if passwordLength > user.MaxPasswordLength || passwordLength < user.MinPasswordLength {
|
||||||
return fmt.Errorf(messagePasswordInvalidLength, user.MinPasswordLength, user.MaxPasswordLength)
|
return fmt.Errorf(messagePasswordInvalidLength, user.MinPasswordLength, user.MaxPasswordLength)
|
||||||
}
|
}
|
||||||
} else if !opts.acceptNilValues {
|
} else if !opts.acceptNilValues {
|
||||||
|
|
Reference in New Issue
Block a user