Add CRUDs and validation/controllers

This commit is contained in:
lumijiez
2025-06-17 15:16:02 +03:00
parent 922021d088
commit 40906bea78
48 changed files with 653 additions and 27 deletions

View File

@@ -0,0 +1,34 @@
using FluentValidation;
using Imprink.Application.Domains.Categories;
namespace Imprink.Application.Validation.Categories;
public class CreateCategoryCommandValidator : AbstractValidator<CreateCategoryCommand>
{
public CreateCategoryCommandValidator()
{
RuleFor(x => x.Name)
.NotEmpty().WithMessage("Name is required.")
.Length(1, 100).WithMessage("Name must be between 1 and 100 characters.");
RuleFor(x => x.Description)
.NotEmpty().WithMessage("Description is required.")
.Length(1, 500).WithMessage("Description must be between 1 and 500 characters.");
RuleFor(x => x.ImageUrl)
.Must(BeValidUrl).When(x => !string.IsNullOrWhiteSpace(x.ImageUrl))
.WithMessage("ImageUrl must be a valid URL.");
RuleFor(x => x.SortOrder)
.GreaterThanOrEqualTo(0).WithMessage("SortOrder cannot be negative.");
RuleFor(x => x.ParentCategoryId)
.NotEqual(Guid.Empty).When(x => x.ParentCategoryId.HasValue)
.WithMessage("ParentCategoryId must be a valid GUID.");
}
private static bool BeValidUrl(string? url)
{
return Uri.TryCreate(url, UriKind.Absolute, out _);
}
}

View File

@@ -0,0 +1,14 @@
using FluentValidation;
using Imprink.Application.Domains.Categories;
namespace Imprink.Application.Validation.Categories;
public class DeleteCategoryCommandValidator : AbstractValidator<DeleteCategoryCommand>
{
public DeleteCategoryCommandValidator()
{
RuleFor(x => x.Id)
.NotEmpty().WithMessage("Id is required.")
.NotEqual(Guid.Empty).WithMessage("Id must be a valid GUID.");
}
}

View File

@@ -0,0 +1,40 @@
using FluentValidation;
using Imprink.Application.Domains.Categories;
namespace Imprink.Application.Validation.Categories;
public class UpdateCategoryCommandValidator : AbstractValidator<UpdateCategoryCommand>
{
public UpdateCategoryCommandValidator()
{
RuleFor(x => x.Id)
.NotEmpty().WithMessage("Id is required.")
.NotEqual(Guid.Empty).WithMessage("Id must be a valid GUID.");
RuleFor(x => x.Name)
.NotEmpty().WithMessage("Name is required.")
.Length(1, 100).WithMessage("Name must be between 1 and 100 characters.");
RuleFor(x => x.Description)
.NotEmpty().WithMessage("Description is required.")
.Length(1, 500).WithMessage("Description must be between 1 and 500 characters.");
RuleFor(x => x.ImageUrl)
.Must(BeValidUrl).When(x => !string.IsNullOrWhiteSpace(x.ImageUrl))
.WithMessage("ImageUrl must be a valid URL.");
RuleFor(x => x.SortOrder)
.GreaterThanOrEqualTo(0).WithMessage("SortOrder cannot be negative.");
RuleFor(x => x.ParentCategoryId)
.NotEqual(Guid.Empty).When(x => x.ParentCategoryId.HasValue)
.WithMessage("ParentCategoryId must be a valid GUID.")
.Must((command, parentId) => parentId != command.Id).When(x => x.ParentCategoryId.HasValue)
.WithMessage("Category cannot be its own parent.");
}
private static bool BeValidUrl(string? url)
{
return Uri.TryCreate(url, UriKind.Absolute, out _);
}
}

View File

@@ -0,0 +1,41 @@
using FluentValidation;
using Imprink.Application.Domains.ProductVariants;
namespace Imprink.Application.Validation.ProductVariants;
public class CreateProductVariantCommandValidator : AbstractValidator<CreateProductVariantCommand>
{
public CreateProductVariantCommandValidator()
{
RuleFor(x => x.ProductId)
.NotEmpty().WithMessage("ProductId is required.")
.NotEqual(Guid.Empty).WithMessage("ProductId must be a valid GUID.");
RuleFor(x => x.Size)
.NotEmpty().WithMessage("Size is required.")
.Length(1, 50).WithMessage("Size must be between 1 and 50 characters.");
RuleFor(x => x.Color)
.Length(1, 50).WithMessage("Color must be between 1 and 50 characters.")
.When(x => !string.IsNullOrWhiteSpace(x.Color));
RuleFor(x => x.Price)
.GreaterThan(0).WithMessage("Price must be greater than 0.");
RuleFor(x => x.ImageUrl)
.Must(BeValidUrl).When(x => !string.IsNullOrWhiteSpace(x.ImageUrl))
.WithMessage("ImageUrl must be a valid URL.");
RuleFor(x => x.Sku)
.NotEmpty().WithMessage("SKU is required.")
.Length(1, 50).WithMessage("SKU must be between 1 and 50 characters.");
RuleFor(x => x.StockQuantity)
.GreaterThanOrEqualTo(0).WithMessage("StockQuantity cannot be negative.");
}
private static bool BeValidUrl(string? url)
{
return Uri.TryCreate(url, UriKind.Absolute, out _);
}
}

View File

@@ -0,0 +1,14 @@
using FluentValidation;
using Imprink.Application.Domains.ProductVariants;
namespace Imprink.Application.Validation.ProductVariants;
public class DeleteProductVariantCommandValidator : AbstractValidator<DeleteProductVariantCommand>
{
public DeleteProductVariantCommandValidator()
{
RuleFor(x => x.Id)
.NotEmpty().WithMessage("Id is required.")
.NotEqual(Guid.Empty).WithMessage("Id must be a valid GUID.");
}
}

View File

@@ -0,0 +1,14 @@
using FluentValidation;
using Imprink.Application.Domains.ProductVariants;
namespace Imprink.Application.Validation.ProductVariants;
public class GetProductVariantsQueryValidator : AbstractValidator<GetProductVariantsQuery>
{
public GetProductVariantsQueryValidator()
{
RuleFor(x => x.ProductId)
.NotEqual(Guid.Empty).When(x => x.ProductId.HasValue)
.WithMessage("ProductId must be a valid GUID when provided.");
}
}

View File

@@ -0,0 +1,45 @@
using FluentValidation;
using Imprink.Application.Domains.ProductVariants;
namespace Imprink.Application.Validation.ProductVariants;
public class UpdateProductVariantCommandValidator : AbstractValidator<UpdateProductVariantCommand>
{
public UpdateProductVariantCommandValidator()
{
RuleFor(x => x.Id)
.NotEmpty().WithMessage("Id is required.")
.NotEqual(Guid.Empty).WithMessage("Id must be a valid GUID.");
RuleFor(x => x.ProductId)
.NotEmpty().WithMessage("ProductId is required.")
.NotEqual(Guid.Empty).WithMessage("ProductId must be a valid GUID.");
RuleFor(x => x.Size)
.NotEmpty().WithMessage("Size is required.")
.Length(1, 50).WithMessage("Size must be between 1 and 50 characters.");
RuleFor(x => x.Color)
.Length(1, 50).WithMessage("Color must be between 1 and 50 characters.")
.When(x => !string.IsNullOrWhiteSpace(x.Color));
RuleFor(x => x.Price)
.GreaterThan(0).WithMessage("Price must be greater than 0.");
RuleFor(x => x.ImageUrl)
.Must(BeValidUrl).When(x => !string.IsNullOrWhiteSpace(x.ImageUrl))
.WithMessage("ImageUrl must be a valid URL.");
RuleFor(x => x.Sku)
.NotEmpty().WithMessage("SKU is required.")
.Length(1, 50).WithMessage("SKU must be between 1 and 50 characters.");
RuleFor(x => x.StockQuantity)
.GreaterThanOrEqualTo(0).WithMessage("StockQuantity cannot be negative.");
}
private static bool BeValidUrl(string? url)
{
return Uri.TryCreate(url, UriKind.Absolute, out _);
}
}

View File

@@ -0,0 +1,34 @@
using FluentValidation;
using Imprink.Application.Domains.Products;
namespace Imprink.Application.Validation.Products;
public class CreateProductCommandValidator : AbstractValidator<CreateProductCommand>
{
public CreateProductCommandValidator()
{
RuleFor(x => x.Name)
.NotEmpty().WithMessage("Name is required.")
.Length(1, 100).WithMessage("Name must be between 1 and 100 characters.");
RuleFor(x => x.Description)
.Length(1, 1000).WithMessage("Description must be between 1 and 1000 characters.")
.When(x => !string.IsNullOrWhiteSpace(x.Description));
RuleFor(x => x.BasePrice)
.GreaterThan(0).WithMessage("BasePrice must be greater than 0.");
RuleFor(x => x.ImageUrl)
.Must(BeValidUrl).When(x => !string.IsNullOrWhiteSpace(x.ImageUrl))
.WithMessage("ImageUrl must be a valid URL.");
RuleFor(x => x.CategoryId)
.NotEqual(Guid.Empty).When(x => x.CategoryId.HasValue)
.WithMessage("CategoryId must be a valid GUID.");
}
private static bool BeValidUrl(string? url)
{
return Uri.TryCreate(url, UriKind.Absolute, out _);
}
}

View File

@@ -0,0 +1,14 @@
using FluentValidation;
using Imprink.Application.Domains.Products;
namespace Imprink.Application.Validation.Products;
public class DeleteProductCommandValidator : AbstractValidator<DeleteProductCommand>
{
public DeleteProductCommandValidator()
{
RuleFor(x => x.Id)
.NotEmpty().WithMessage("Id is required.")
.NotEqual(Guid.Empty).WithMessage("Id must be a valid GUID.");
}
}

View File

@@ -1,4 +1,5 @@
using FluentValidation;
using Imprink.Application.Domains.Products;
using Imprink.Application.Products;
using Imprink.Application.Validation.Models;

View File

@@ -0,0 +1,38 @@
using FluentValidation;
using Imprink.Application.Domains.Products;
namespace Imprink.Application.Validation.Products;
public class UpdateProductCommandValidator : AbstractValidator<UpdateProductCommand>
{
public UpdateProductCommandValidator()
{
RuleFor(x => x.Id)
.NotEmpty().WithMessage("Id is required.")
.NotEqual(Guid.Empty).WithMessage("Id must be a valid GUID.");
RuleFor(x => x.Name)
.NotEmpty().WithMessage("Name is required.")
.Length(1, 100).WithMessage("Name must be between 1 and 100 characters.");
RuleFor(x => x.Description)
.Length(1, 1000).WithMessage("Description must be between 1 and 1000 characters.")
.When(x => !string.IsNullOrWhiteSpace(x.Description));
RuleFor(x => x.BasePrice)
.GreaterThan(0).WithMessage("BasePrice must be greater than 0.");
RuleFor(x => x.ImageUrl)
.Must(BeValidUrl).When(x => !string.IsNullOrWhiteSpace(x.ImageUrl))
.WithMessage("ImageUrl must be a valid URL.");
RuleFor(x => x.CategoryId)
.NotEqual(Guid.Empty).When(x => x.CategoryId.HasValue)
.WithMessage("CategoryId must be a valid GUID.");
}
private static bool BeValidUrl(string? url)
{
return Uri.TryCreate(url, UriKind.Absolute, out _);
}
}

View File

@@ -0,0 +1,18 @@
using FluentValidation;
using Imprink.Application.Domains.Users;
namespace Imprink.Application.Validation.Users;
public class SetUserFullNameCommandValidator : AbstractValidator<SetUserFullNameCommand>
{
public SetUserFullNameCommandValidator()
{
RuleFor(x => x.FirstName)
.NotEmpty().WithMessage("FirstName is required.")
.Length(1, 50).WithMessage("FirstName must be between 1 and 50 characters.");
RuleFor(x => x.LastName)
.NotEmpty().WithMessage("LastName is required.")
.Length(1, 50).WithMessage("LastName must be between 1 and 50 characters.");
}
}

View File

@@ -0,0 +1,14 @@
using FluentValidation;
using Imprink.Application.Domains.Users;
namespace Imprink.Application.Validation.Users;
public class SetUserPhoneCommandValidator : AbstractValidator<SetUserPhoneCommand>
{
public SetUserPhoneCommandValidator()
{
RuleFor(x => x.PhoneNumber)
.NotEmpty().WithMessage("PhoneNumber is required.")
.Matches(@"^\+?[1-9]\d{1,14}$").WithMessage("PhoneNumber must be a valid phone number format.");
}
}