197 lines
6.5 KiB
C#
197 lines
6.5 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
using TakeoutSaaS.Domain.Membership.Entities;
|
|
using TakeoutSaaS.Domain.Membership.Repositories;
|
|
using TakeoutSaaS.Infrastructure.App.Persistence;
|
|
|
|
namespace TakeoutSaaS.Infrastructure.App.Repositories;
|
|
|
|
/// <summary>
|
|
/// 会员聚合 EF Core 仓储实现。
|
|
/// </summary>
|
|
public sealed class EfMemberRepository(TakeoutAppDbContext context) : IMemberRepository
|
|
{
|
|
/// <inheritdoc />
|
|
public async Task<IReadOnlyList<MemberProfile>> GetProfilesAsync(long tenantId, CancellationToken cancellationToken = default)
|
|
{
|
|
return await context.MemberProfiles
|
|
.Where(x => x.TenantId == tenantId)
|
|
.OrderByDescending(x => x.UpdatedAt ?? x.CreatedAt)
|
|
.ThenByDescending(x => x.Id)
|
|
.ToListAsync(cancellationToken);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public async Task<IReadOnlyList<MemberProfile>> GetProfilesByMobilesAsync(
|
|
long tenantId,
|
|
IReadOnlyCollection<string> mobiles,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
if (mobiles.Count == 0)
|
|
{
|
|
return [];
|
|
}
|
|
|
|
return await context.MemberProfiles
|
|
.Where(x => x.TenantId == tenantId && mobiles.Contains(x.Mobile))
|
|
.ToListAsync(cancellationToken);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public Task<MemberProfile?> FindProfileByIdAsync(long tenantId, long memberId, CancellationToken cancellationToken = default)
|
|
{
|
|
return context.MemberProfiles
|
|
.Where(x => x.TenantId == tenantId && x.Id == memberId)
|
|
.FirstOrDefaultAsync(cancellationToken);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public async Task AddProfilesAsync(IEnumerable<MemberProfile> profiles, CancellationToken cancellationToken = default)
|
|
{
|
|
var profileList = profiles?.ToList() ?? [];
|
|
if (profileList.Count == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
await context.MemberProfiles.AddRangeAsync(profileList, cancellationToken);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public Task UpdateProfileAsync(MemberProfile profile, CancellationToken cancellationToken = default)
|
|
{
|
|
context.MemberProfiles.Update(profile);
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public async Task<IReadOnlyList<MemberTier>> GetTiersAsync(long tenantId, CancellationToken cancellationToken = default)
|
|
{
|
|
return await context.MemberTiers
|
|
.Where(x => x.TenantId == tenantId)
|
|
.OrderBy(x => x.SortOrder)
|
|
.ThenBy(x => x.Id)
|
|
.ToListAsync(cancellationToken);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public Task<MemberTier?> FindTierByIdAsync(long tenantId, long tierId, CancellationToken cancellationToken = default)
|
|
{
|
|
return context.MemberTiers
|
|
.Where(x => x.TenantId == tenantId && x.Id == tierId)
|
|
.FirstOrDefaultAsync(cancellationToken);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public Task AddTierAsync(MemberTier tier, CancellationToken cancellationToken = default)
|
|
{
|
|
return context.MemberTiers.AddAsync(tier, cancellationToken).AsTask();
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public Task UpdateTierAsync(MemberTier tier, CancellationToken cancellationToken = default)
|
|
{
|
|
context.MemberTiers.Update(tier);
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public Task DeleteTierAsync(MemberTier tier, CancellationToken cancellationToken = default)
|
|
{
|
|
context.MemberTiers.Remove(tier);
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public Task<MemberDaySetting?> GetMemberDaySettingAsync(long tenantId, CancellationToken cancellationToken = default)
|
|
{
|
|
return context.MemberDaySettings
|
|
.Where(x => x.TenantId == tenantId)
|
|
.FirstOrDefaultAsync(cancellationToken);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public Task AddMemberDaySettingAsync(MemberDaySetting setting, CancellationToken cancellationToken = default)
|
|
{
|
|
return context.MemberDaySettings.AddAsync(setting, cancellationToken).AsTask();
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public Task UpdateMemberDaySettingAsync(MemberDaySetting setting, CancellationToken cancellationToken = default)
|
|
{
|
|
context.MemberDaySettings.Update(setting);
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public async Task<IReadOnlyList<MemberProfileTag>> GetProfileTagsAsync(
|
|
long tenantId,
|
|
long memberProfileId,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
return await context.MemberProfileTags
|
|
.AsNoTracking()
|
|
.Where(x => x.TenantId == tenantId && x.MemberProfileId == memberProfileId)
|
|
.OrderBy(x => x.TagName)
|
|
.ToListAsync(cancellationToken);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public async Task<IReadOnlyList<MemberProfileTag>> GetProfileTagsByMemberIdsAsync(
|
|
long tenantId,
|
|
IReadOnlyCollection<long> memberProfileIds,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
if (memberProfileIds.Count == 0)
|
|
{
|
|
return [];
|
|
}
|
|
|
|
return await context.MemberProfileTags
|
|
.AsNoTracking()
|
|
.Where(x => x.TenantId == tenantId && memberProfileIds.Contains(x.MemberProfileId))
|
|
.OrderBy(x => x.MemberProfileId)
|
|
.ThenBy(x => x.TagName)
|
|
.ToListAsync(cancellationToken);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public async Task ReplaceProfileTagsAsync(
|
|
long tenantId,
|
|
long memberProfileId,
|
|
IReadOnlyCollection<string> tags,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
var normalizedTags = (tags ?? Array.Empty<string>())
|
|
.Select(x => (x ?? string.Empty).Trim())
|
|
.Where(x => !string.IsNullOrWhiteSpace(x))
|
|
.Distinct(StringComparer.OrdinalIgnoreCase)
|
|
.OrderBy(x => x, StringComparer.OrdinalIgnoreCase)
|
|
.ToList();
|
|
|
|
var existing = await context.MemberProfileTags
|
|
.Where(x => x.TenantId == tenantId && x.MemberProfileId == memberProfileId)
|
|
.ToListAsync(cancellationToken);
|
|
|
|
context.MemberProfileTags.RemoveRange(existing);
|
|
|
|
if (normalizedTags.Count == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var entities = normalizedTags.Select(tag => new MemberProfileTag
|
|
{
|
|
MemberProfileId = memberProfileId,
|
|
TagName = tag
|
|
});
|
|
|
|
await context.MemberProfileTags.AddRangeAsync(entities, cancellationToken);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public Task SaveChangesAsync(CancellationToken cancellationToken = default)
|
|
{
|
|
return context.SaveChangesAsync(cancellationToken);
|
|
}
|
|
}
|