apskel-pos-backend/internal/validator/customer_validator.go
aditya.siregar 4f5950543e init
2025-07-18 20:10:29 +07:00

177 lines
5.3 KiB
Go

package validator
import (
"apskel-pos-be/internal/contract"
"errors"
"strings"
"github.com/go-playground/validator/v10"
)
type CustomerValidator interface {
ValidateCreateCustomerRequest(req *contract.CreateCustomerRequest) (error, string)
ValidateUpdateCustomerRequest(req *contract.UpdateCustomerRequest) (error, string)
ValidateListCustomersRequest(req *contract.ListCustomersRequest) (error, string)
ValidateSetDefaultCustomerRequest(req *contract.SetDefaultCustomerRequest) (error, string)
}
type CustomerValidatorImpl struct {
validate *validator.Validate
}
func NewCustomerValidator() *CustomerValidatorImpl {
return &CustomerValidatorImpl{
validate: validator.New(),
}
}
// ValidateCreateCustomer validates create customer request
func (v *CustomerValidatorImpl) ValidateCreateCustomerRequest(req *contract.CreateCustomerRequest) (error, string) {
if err := v.validate.Struct(req); err != nil {
return err, "VALIDATION_ERROR"
}
// Additional custom validations
if req.Name != "" {
req.Name = strings.TrimSpace(req.Name)
if req.Name == "" {
return errors.New("name cannot be empty or whitespace only"), "INVALID_NAME"
}
if len(req.Name) > 255 {
return errors.New("name cannot exceed 255 characters"), "INVALID_NAME"
}
}
if req.Email != nil && *req.Email != "" {
*req.Email = strings.TrimSpace(strings.ToLower(*req.Email))
if *req.Email == "" {
return errors.New("email cannot be empty or whitespace only"), "INVALID_EMAIL"
}
if len(*req.Email) > 255 {
return errors.New("email cannot exceed 255 characters"), "INVALID_EMAIL"
}
}
if req.Phone != nil && *req.Phone != "" {
*req.Phone = strings.TrimSpace(*req.Phone)
if *req.Phone == "" {
return errors.New("phone cannot be empty or whitespace only"), "INVALID_PHONE"
}
if len(*req.Phone) > 20 {
return errors.New("phone cannot exceed 20 characters"), "INVALID_PHONE"
}
}
if req.Address != nil && *req.Address != "" {
*req.Address = strings.TrimSpace(*req.Address)
if *req.Address == "" {
return errors.New("address cannot be empty or whitespace only"), "INVALID_ADDRESS"
}
if len(*req.Address) > 500 {
return errors.New("address cannot exceed 500 characters"), "INVALID_ADDRESS"
}
}
return nil, ""
}
// ValidateUpdateCustomer validates update customer request
func (v *CustomerValidatorImpl) ValidateUpdateCustomerRequest(req *contract.UpdateCustomerRequest) (error, string) {
if err := v.validate.Struct(req); err != nil {
return err, "VALIDATION_ERROR"
}
// Check if at least one field is provided
if req.Name == nil && req.Email == nil && req.Phone == nil && req.Address == nil && req.IsActive == nil {
return errors.New("at least one field must be provided for update"), "MISSING_FIELDS"
}
// Additional custom validations
if req.Name != nil && *req.Name != "" {
*req.Name = strings.TrimSpace(*req.Name)
if *req.Name == "" {
return errors.New("name cannot be empty or whitespace only"), "INVALID_NAME"
}
if len(*req.Name) > 255 {
return errors.New("name cannot exceed 255 characters"), "INVALID_NAME"
}
}
if req.Email != nil && *req.Email != "" {
*req.Email = strings.TrimSpace(strings.ToLower(*req.Email))
if *req.Email == "" {
return errors.New("email cannot be empty or whitespace only"), "INVALID_EMAIL"
}
if len(*req.Email) > 255 {
return errors.New("email cannot exceed 255 characters"), "INVALID_EMAIL"
}
}
if req.Phone != nil && *req.Phone != "" {
*req.Phone = strings.TrimSpace(*req.Phone)
if *req.Phone == "" {
return errors.New("phone cannot be empty or whitespace only"), "INVALID_PHONE"
}
if len(*req.Phone) > 20 {
return errors.New("phone cannot exceed 20 characters"), "INVALID_PHONE"
}
}
if req.Address != nil && *req.Address != "" {
*req.Address = strings.TrimSpace(*req.Address)
if *req.Address == "" {
return errors.New("address cannot be empty or whitespace only"), "INVALID_ADDRESS"
}
if len(*req.Address) > 500 {
return errors.New("address cannot exceed 500 characters"), "INVALID_ADDRESS"
}
}
return nil, ""
}
// ValidateListCustomersRequest validates list customers request
func (v *CustomerValidatorImpl) ValidateListCustomersRequest(req *contract.ListCustomersRequest) (error, string) {
if err := v.validate.Struct(req); err != nil {
return err, "VALIDATION_ERROR"
}
// Additional custom validations
if req.Search != "" {
req.Search = strings.TrimSpace(req.Search)
if len(req.Search) > 100 {
return errors.New("search term cannot exceed 100 characters"), "INVALID_SEARCH"
}
}
if req.SortBy != "" {
req.SortBy = strings.ToLower(strings.TrimSpace(req.SortBy))
validSortFields := map[string]bool{
"name": true,
"email": true,
"created_at": true,
"updated_at": true,
}
if !validSortFields[req.SortBy] {
return errors.New("invalid sort field"), "INVALID_SORT_FIELD"
}
}
if req.SortOrder != "" {
req.SortOrder = strings.ToLower(strings.TrimSpace(req.SortOrder))
if req.SortOrder != "asc" && req.SortOrder != "desc" {
return errors.New("sort order must be 'asc' or 'desc'"), "INVALID_SORT_ORDER"
}
}
return nil, ""
}
// ValidateSetDefaultCustomer validates set default customer request
func (v *CustomerValidatorImpl) ValidateSetDefaultCustomerRequest(req *contract.SetDefaultCustomerRequest) (error, string) {
if err := v.validate.Struct(req); err != nil {
return err, "VALIDATION_ERROR"
}
return nil, ""
}