162 lines
5.7 KiB
C#
162 lines
5.7 KiB
C#
using System.Linq;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using TakeoutSaaS.Domain.Tenants.Entities;
|
|
using TakeoutSaaS.Domain.Tenants.Enums;
|
|
using TakeoutSaaS.Domain.Tenants.Repositories;
|
|
using TakeoutSaaS.Infrastructure.App.Persistence;
|
|
|
|
namespace TakeoutSaaS.Infrastructure.App.Repositories;
|
|
|
|
/// <summary>
|
|
/// 租户聚合的 EF Core 仓储实现。
|
|
/// </summary>
|
|
public sealed class EfTenantRepository(TakeoutAppDbContext context) : ITenantRepository
|
|
{
|
|
/// <inheritdoc />
|
|
public Task<Tenant?> FindByIdAsync(long tenantId, CancellationToken cancellationToken = default)
|
|
{
|
|
return context.Tenants
|
|
.AsNoTracking()
|
|
.FirstOrDefaultAsync(x => x.Id == tenantId, cancellationToken);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public async Task<IReadOnlyList<Tenant>> SearchAsync(
|
|
TenantStatus? status,
|
|
string? keyword,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
var query = context.Tenants.AsNoTracking();
|
|
|
|
if (status.HasValue)
|
|
{
|
|
query = query.Where(x => x.Status == status.Value);
|
|
}
|
|
|
|
if (!string.IsNullOrWhiteSpace(keyword))
|
|
{
|
|
keyword = keyword.Trim();
|
|
query = query.Where(x =>
|
|
EF.Functions.ILike(x.Name, $"%{keyword}%") ||
|
|
EF.Functions.ILike(x.Code, $"%{keyword}%") ||
|
|
EF.Functions.ILike(x.ContactName ?? string.Empty, $"%{keyword}%"));
|
|
}
|
|
|
|
return await query
|
|
.OrderByDescending(x => x.CreatedAt)
|
|
.ToListAsync(cancellationToken);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public Task AddTenantAsync(Tenant tenant, CancellationToken cancellationToken = default)
|
|
{
|
|
return context.Tenants.AddAsync(tenant, cancellationToken).AsTask();
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public Task UpdateTenantAsync(Tenant tenant, CancellationToken cancellationToken = default)
|
|
{
|
|
context.Tenants.Update(tenant);
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public Task<bool> ExistsByCodeAsync(string code, CancellationToken cancellationToken = default)
|
|
{
|
|
var normalized = code.Trim();
|
|
return context.Tenants.AnyAsync(x => x.Code == normalized, cancellationToken);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public Task<TenantVerificationProfile?> GetVerificationProfileAsync(long tenantId, CancellationToken cancellationToken = default)
|
|
{
|
|
return context.TenantVerificationProfiles
|
|
.AsNoTracking()
|
|
.FirstOrDefaultAsync(x => x.TenantId == tenantId, cancellationToken);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public async Task UpsertVerificationProfileAsync(TenantVerificationProfile profile, CancellationToken cancellationToken = default)
|
|
{
|
|
var existing = await context.TenantVerificationProfiles
|
|
.FirstOrDefaultAsync(x => x.TenantId == profile.TenantId, cancellationToken);
|
|
|
|
if (existing == null)
|
|
{
|
|
await context.TenantVerificationProfiles.AddAsync(profile, cancellationToken);
|
|
return;
|
|
}
|
|
|
|
profile.Id = existing.Id;
|
|
context.Entry(existing).CurrentValues.SetValues(profile);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public Task<TenantSubscription?> GetActiveSubscriptionAsync(long tenantId, CancellationToken cancellationToken = default)
|
|
{
|
|
return context.TenantSubscriptions
|
|
.AsNoTracking()
|
|
.Where(x => x.TenantId == tenantId)
|
|
.OrderByDescending(x => x.EffectiveTo)
|
|
.FirstOrDefaultAsync(cancellationToken);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public Task<TenantSubscription?> FindSubscriptionByIdAsync(long tenantId, long subscriptionId, CancellationToken cancellationToken = default)
|
|
{
|
|
return context.TenantSubscriptions
|
|
.FirstOrDefaultAsync(x => x.TenantId == tenantId && x.Id == subscriptionId, cancellationToken);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public Task AddSubscriptionAsync(TenantSubscription subscription, CancellationToken cancellationToken = default)
|
|
{
|
|
return context.TenantSubscriptions.AddAsync(subscription, cancellationToken).AsTask();
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public Task UpdateSubscriptionAsync(TenantSubscription subscription, CancellationToken cancellationToken = default)
|
|
{
|
|
context.TenantSubscriptions.Update(subscription);
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public Task AddSubscriptionHistoryAsync(TenantSubscriptionHistory history, CancellationToken cancellationToken = default)
|
|
{
|
|
return context.TenantSubscriptionHistories.AddAsync(history, cancellationToken).AsTask();
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public async Task<IReadOnlyList<TenantSubscriptionHistory>> GetSubscriptionHistoryAsync(long tenantId, CancellationToken cancellationToken = default)
|
|
{
|
|
return await context.TenantSubscriptionHistories
|
|
.AsNoTracking()
|
|
.Where(x => x.TenantId == tenantId)
|
|
.OrderByDescending(x => x.EffectiveFrom)
|
|
.ToListAsync(cancellationToken);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public Task AddAuditLogAsync(TenantAuditLog log, CancellationToken cancellationToken = default)
|
|
{
|
|
return context.TenantAuditLogs.AddAsync(log, cancellationToken).AsTask();
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public async Task<IReadOnlyList<TenantAuditLog>> GetAuditLogsAsync(long tenantId, CancellationToken cancellationToken = default)
|
|
{
|
|
return await context.TenantAuditLogs
|
|
.AsNoTracking()
|
|
.Where(x => x.TenantId == tenantId)
|
|
.OrderByDescending(x => x.CreatedAt)
|
|
.ToListAsync(cancellationToken);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public Task SaveChangesAsync(CancellationToken cancellationToken = default)
|
|
{
|
|
return context.SaveChangesAsync(cancellationToken);
|
|
}
|
|
}
|