Init
This commit is contained in:
113
Prefab.Catalog/Domain/Entities/Category.cs
Normal file
113
Prefab.Catalog/Domain/Entities/Category.cs
Normal file
@@ -0,0 +1,113 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using Prefab.Base.Catalog.Categories;
|
||||
using Prefab.Catalog.Domain.Events;
|
||||
using Prefab.Catalog.Domain.Exceptions;
|
||||
using Prefab.Catalog.Domain.Services;
|
||||
using Prefab.Domain.Common;
|
||||
|
||||
namespace Prefab.Catalog.Domain.Entities;
|
||||
|
||||
public class Category : EntityWithAuditAndStatus<Guid>
|
||||
{
|
||||
private static readonly Regex SlugRegex = new("^[a-z0-9]+(?:-[a-z0-9]+)*$", RegexOptions.Compiled);
|
||||
|
||||
private Category()
|
||||
{
|
||||
}
|
||||
|
||||
public Guid? ParentId { get; private set; }
|
||||
|
||||
public string Name { get; private set; } = string.Empty;
|
||||
|
||||
public string? Description { get; private set; }
|
||||
|
||||
public string? Slug { get; private set; }
|
||||
|
||||
public int DisplayOrder { get; private set; }
|
||||
|
||||
public bool IsFeatured { get; private set; }
|
||||
|
||||
public string? HeroImageUrl { get; private set; }
|
||||
|
||||
public string? Icon { get; private set; }
|
||||
|
||||
public static async Task<Category> Create(string name, string? description, IUniqueChecker check, CancellationToken cancellationToken)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(name);
|
||||
ArgumentNullException.ThrowIfNull(check);
|
||||
|
||||
var trimmedName = name.Trim();
|
||||
var trimmedDescription = string.IsNullOrWhiteSpace(description) ? null : description.Trim();
|
||||
|
||||
if (!await check.CategoryNameIsUnique(trimmedName, cancellationToken))
|
||||
{
|
||||
throw new DuplicateNameException(trimmedName, nameof(Category));
|
||||
}
|
||||
|
||||
var category = new Category
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = trimmedName,
|
||||
Description = trimmedDescription
|
||||
};
|
||||
|
||||
category.AddEvent(new CategoryCreated(category.Id, category.Name));
|
||||
return category;
|
||||
}
|
||||
|
||||
public async Task Rename(string newName, IUniqueChecker check, CancellationToken cancellationToken)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(newName);
|
||||
ArgumentNullException.ThrowIfNull(check);
|
||||
|
||||
var trimmed = newName.Trim();
|
||||
if (string.Equals(trimmed, Name, StringComparison.Ordinal))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!await check.CategoryNameIsUnique(trimmed, cancellationToken))
|
||||
{
|
||||
throw new DuplicateNameException(trimmed, nameof(Category));
|
||||
}
|
||||
|
||||
var oldName = Name;
|
||||
Name = trimmed;
|
||||
|
||||
AddEvent(new CategoryRenamed(Id, oldName, Name));
|
||||
}
|
||||
|
||||
public void ConfigureMetadata(string slug, int displayOrder, bool isFeatured, string? heroImageUrl, string? icon)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(slug);
|
||||
|
||||
var trimmedSlug = slug.Trim();
|
||||
if (trimmedSlug.Length > CategoryRules.SlugMaxLength)
|
||||
{
|
||||
throw new DomainValidationException($"Category slug cannot exceed {CategoryRules.SlugMaxLength} characters.");
|
||||
}
|
||||
|
||||
if (!SlugRegex.IsMatch(trimmedSlug))
|
||||
{
|
||||
throw new DomainValidationException("Category slug must use lowercase letters, numbers, and hyphens.");
|
||||
}
|
||||
|
||||
var trimmedHeroImageUrl = string.IsNullOrWhiteSpace(heroImageUrl) ? null : heroImageUrl.Trim();
|
||||
if (trimmedHeroImageUrl is not null && trimmedHeroImageUrl.Length > CategoryRules.HeroImageUrlMaxLength)
|
||||
{
|
||||
throw new DomainValidationException($"Hero image URL cannot exceed {CategoryRules.HeroImageUrlMaxLength} characters.");
|
||||
}
|
||||
|
||||
var trimmedIcon = string.IsNullOrWhiteSpace(icon) ? null : icon.Trim();
|
||||
if (trimmedIcon is not null && trimmedIcon.Length > CategoryRules.IconMaxLength)
|
||||
{
|
||||
throw new DomainValidationException($"Icon cannot exceed {CategoryRules.IconMaxLength} characters.");
|
||||
}
|
||||
|
||||
Slug = trimmedSlug;
|
||||
DisplayOrder = displayOrder;
|
||||
IsFeatured = isFeatured;
|
||||
HeroImageUrl = trimmedHeroImageUrl;
|
||||
Icon = trimmedIcon;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user