96 lines
3.4 KiB
C#
96 lines
3.4 KiB
C#
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);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|