Init
This commit is contained in:
95
Prefab.Catalog/Data/Services/UniqueChecker.cs
Normal file
95
Prefab.Catalog/Data/Services/UniqueChecker.cs
Normal file
@@ -0,0 +1,95 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Prefab.Catalog.Domain.Entities;
|
||||
using Prefab.Catalog.Domain.Services;
|
||||
|
||||
namespace Prefab.Catalog.Data.Services;
|
||||
|
||||
/// <inheritdoc cref="IUniqueChecker"/>
|
||||
public sealed class UniqueChecker(ICatalogDbContextFactory dbFactory) : IUniqueChecker
|
||||
{
|
||||
private static DbContext AsDbContext(IModuleDbReadOnly db)
|
||||
{
|
||||
if (db is not DbContext context)
|
||||
{
|
||||
throw new InvalidOperationException("Catalog context must derive from DbContext.");
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
public async Task<bool> CategoryNameIsUnique(string name, CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(name);
|
||||
|
||||
await using var db = await dbFactory.CreateReadOnlyAsync(cancellationToken);
|
||||
|
||||
var normalized = name.Trim();
|
||||
return !await db.Categories
|
||||
.Where(c => c.DeletedOn == null)
|
||||
.AnyAsync(c => c.Name == normalized, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<bool> ProductModelNameIsUnique(string name, CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(name);
|
||||
|
||||
await using var db = await dbFactory.CreateReadOnlyAsync(cancellationToken);
|
||||
var context = AsDbContext(db);
|
||||
|
||||
var normalized = name.Trim().ToUpperInvariant();
|
||||
return !await context.Set<Product>()
|
||||
.Where(p => p.DeletedOn == null && p.Kind == ProductKind.Model)
|
||||
.AnyAsync(p => p.Name != null && p.Name.ToUpper() == normalized, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<bool> ProductSlugIsUnique(string? slug, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(slug))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
await using var db = await dbFactory.CreateReadOnlyAsync(cancellationToken);
|
||||
var context = AsDbContext(db);
|
||||
|
||||
var normalized = slug.Trim().ToLowerInvariant();
|
||||
return !await context.Set<Product>()
|
||||
.Where(p => p.DeletedOn == null && p.Kind == ProductKind.Model && p.Slug != null)
|
||||
.AnyAsync(p => p.Slug!.ToLower() == normalized, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<bool> ProductSkuIsUnique(string sku, CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(sku);
|
||||
|
||||
await using var db = await dbFactory.CreateReadOnlyAsync(cancellationToken);
|
||||
var context = AsDbContext(db);
|
||||
|
||||
var normalized = sku.Trim().ToUpperInvariant();
|
||||
return !await context.Set<Product>()
|
||||
.Where(p => p.DeletedOn == null && p.Sku != null)
|
||||
.AnyAsync(p => p.Sku!.ToUpper() == normalized, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<bool> OptionCodeIsUniqueForProduct(Guid productId, string code, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (productId == Guid.Empty)
|
||||
{
|
||||
throw new ArgumentException("Product identifier is required.", nameof(productId));
|
||||
}
|
||||
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(code);
|
||||
|
||||
await using var db = await dbFactory.CreateReadOnlyAsync(cancellationToken);
|
||||
var context = AsDbContext(db);
|
||||
|
||||
var normalizedCode = code.Trim().ToUpperInvariant();
|
||||
return !await context.Set<OptionDefinition>()
|
||||
.Where(o => o.DeletedOn == null && o.ProductId == productId)
|
||||
.AnyAsync(o => o.Code.ToUpper() == normalizedCode, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user