2025-07-18 20:10:29 +07:00
|
|
|
package validator
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"errors"
|
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
|
|
"apskel-pos-be/internal/constants"
|
|
|
|
|
"apskel-pos-be/internal/contract"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type CategoryValidator interface {
|
|
|
|
|
ValidateCreateCategoryRequest(req *contract.CreateCategoryRequest) (error, string)
|
|
|
|
|
ValidateUpdateCategoryRequest(req *contract.UpdateCategoryRequest) (error, string)
|
|
|
|
|
ValidateListCategoriesRequest(req *contract.ListCategoriesRequest) (error, string)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type CategoryValidatorImpl struct{}
|
|
|
|
|
|
|
|
|
|
func NewCategoryValidator() *CategoryValidatorImpl {
|
|
|
|
|
return &CategoryValidatorImpl{}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (v *CategoryValidatorImpl) ValidateCreateCategoryRequest(req *contract.CreateCategoryRequest) (error, string) {
|
|
|
|
|
if req == nil {
|
|
|
|
|
return errors.New("request body is required"), constants.MissingFieldErrorCode
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if strings.TrimSpace(req.Name) == "" {
|
|
|
|
|
return errors.New("name is required"), constants.MissingFieldErrorCode
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(req.Name) < 1 || len(req.Name) > 255 {
|
|
|
|
|
return errors.New("name must be between 1 and 255 characters"), constants.MalformedFieldErrorCode
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if req.Description != nil && len(*req.Description) > 1000 {
|
|
|
|
|
return errors.New("description cannot exceed 1000 characters"), constants.MalformedFieldErrorCode
|
|
|
|
|
}
|
|
|
|
|
|
2026-10-02 23:30:03 +07:00
|
|
|
if req.OwnerFeePercent != nil && (*req.OwnerFeePercent < 0 || *req.OwnerFeePercent > 100) {
|
|
|
|
|
return errors.New("owner_fee_percent must be between 0 and 100"), constants.MalformedFieldErrorCode
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-18 20:10:29 +07:00
|
|
|
if req.BusinessType != nil && strings.TrimSpace(*req.BusinessType) != "" {
|
|
|
|
|
validBusinessTypes := map[string]bool{
|
|
|
|
|
"restaurant": true,
|
|
|
|
|
"cafe": true,
|
|
|
|
|
"bar": true,
|
|
|
|
|
"fastfood": true,
|
|
|
|
|
"retail": true,
|
|
|
|
|
}
|
|
|
|
|
if !validBusinessTypes[*req.BusinessType] {
|
|
|
|
|
return errors.New("invalid business_type"), constants.MalformedFieldErrorCode
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil, ""
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (v *CategoryValidatorImpl) ValidateUpdateCategoryRequest(req *contract.UpdateCategoryRequest) (error, string) {
|
|
|
|
|
if req == nil {
|
|
|
|
|
return errors.New("request body is required"), constants.MissingFieldErrorCode
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// At least one field should be provided for update
|
2026-10-04 21:54:13 +07:00
|
|
|
if req.Name == nil && req.Description == nil && req.BusinessType == nil && req.ParentID == nil && req.Metadata == nil && req.OwnerFeePercent == nil && req.IsTeam == nil && req.Order == nil && req.OutletID == nil && !req.ClearParentID && !req.ClearOwnerFeePercent {
|
2025-07-18 20:10:29 +07:00
|
|
|
return errors.New("at least one field must be provided for update"), constants.MissingFieldErrorCode
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if req.Name != nil {
|
|
|
|
|
if strings.TrimSpace(*req.Name) == "" {
|
|
|
|
|
return errors.New("name cannot be empty"), constants.MalformedFieldErrorCode
|
|
|
|
|
}
|
|
|
|
|
if len(*req.Name) < 1 || len(*req.Name) > 255 {
|
|
|
|
|
return errors.New("name must be between 1 and 255 characters"), constants.MalformedFieldErrorCode
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if req.Description != nil && len(*req.Description) > 1000 {
|
|
|
|
|
return errors.New("description cannot exceed 1000 characters"), constants.MalformedFieldErrorCode
|
|
|
|
|
}
|
|
|
|
|
|
2026-10-02 23:30:03 +07:00
|
|
|
if req.OwnerFeePercent != nil && (*req.OwnerFeePercent < 0 || *req.OwnerFeePercent > 100) {
|
|
|
|
|
return errors.New("owner_fee_percent must be between 0 and 100"), constants.MalformedFieldErrorCode
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-18 20:10:29 +07:00
|
|
|
if req.BusinessType != nil && strings.TrimSpace(*req.BusinessType) != "" {
|
|
|
|
|
validBusinessTypes := map[string]bool{
|
|
|
|
|
"restaurant": true,
|
|
|
|
|
"cafe": true,
|
|
|
|
|
"bar": true,
|
|
|
|
|
"fastfood": true,
|
|
|
|
|
"retail": true,
|
|
|
|
|
}
|
|
|
|
|
if !validBusinessTypes[*req.BusinessType] {
|
|
|
|
|
return errors.New("invalid business_type"), constants.MalformedFieldErrorCode
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil, ""
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (v *CategoryValidatorImpl) ValidateListCategoriesRequest(req *contract.ListCategoriesRequest) (error, string) {
|
|
|
|
|
if req == nil {
|
|
|
|
|
return errors.New("request is required"), constants.MissingFieldErrorCode
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if req.Page < 1 {
|
|
|
|
|
return errors.New("page must be at least 1"), constants.MalformedFieldErrorCode
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if req.Limit < 1 || req.Limit > 100 {
|
|
|
|
|
return errors.New("limit must be between 1 and 100"), constants.MalformedFieldErrorCode
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if req.BusinessType != "" {
|
|
|
|
|
validBusinessTypes := map[string]bool{
|
|
|
|
|
"restaurant": true,
|
|
|
|
|
"cafe": true,
|
|
|
|
|
"bar": true,
|
|
|
|
|
"fastfood": true,
|
|
|
|
|
"retail": true,
|
|
|
|
|
}
|
|
|
|
|
if !validBusinessTypes[req.BusinessType] {
|
|
|
|
|
return errors.New("invalid business_type"), constants.MalformedFieldErrorCode
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-06 21:21:41 +07:00
|
|
|
if req.Type != "" && req.Type != "parent" && req.Type != "child" {
|
|
|
|
|
return errors.New("type must be either 'parent' or 'child'"), constants.MalformedFieldErrorCode
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-18 20:10:29 +07:00
|
|
|
return nil, ""
|
|
|
|
|
}
|