feat(member): implement member center management module
Some checks failed
Build and Deploy TenantApi + SkuWorker / build-and-deploy (push) Failing after 1m54s
Some checks failed
Build and Deploy TenantApi + SkuWorker / build-and-deploy (push) Failing after 1m54s
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user