Files
Core_Be/Repos/OverdueLockRepository.cs
T
Dhananjaya99 bffc9b1686 first commit
2026-09-28 11:44:26 +05:30

114 lines
4.8 KiB
C#

using Fitness_core_BE.Interfaces;
using Fitness_core_BE.Models;
using Microsoft.EntityFrameworkCore;
namespace Fitness_core_BE.Repos
{
public class OverdueLockRepository : IOverdueLockRepository
{
private readonly TenantDbContext _context;
private readonly CentralDbContext _central;
public OverdueLockRepository(TenantDbContext context, CentralDbContext central)
{
_context = context;
_central = central;
}
// A null policy now means "use the platform default" (see Client.DefaultLockAfterDaysOverdue)
// rather than "auto-lock is off" -- only an explicit 0 disables it for a client.
public Task<List<Client>> GetClientsWithOverdueLockPolicyAsync(
CancellationToken ct = default)
{
return _central.Client
.AsNoTracking()
.Where(client =>
client.LockAfterDaysOverdue == null ||
client.LockAfterDaysOverdue > 0)
.ToListAsync(ct);
}
public async Task<List<Guid>> GetOverdueCustomerIdsAsync(
Guid clientId,
DateTime thresholdDate,
CancellationToken ct = default)
{
// IsActive filter: an unapproved renewal invoice (daily sweep, awaiting staff
// approve/change-plan/reject) must never count toward auto-locking a member -- they
// have no way to pay an invoice that isn't even approved for billing yet. Once it's
// approved (IsActive=true) it's a normal invoice and ages into "overdue" like any
// other; RolledOver invoices are also excluded since their debt now lives on the
// invoice that superseded them, not on this one.
var overdueSubscriptionIds = await _context.CustomerInvoices
.AsNoTracking()
.Where(invoice =>
invoice.FKClientId == clientId &&
invoice.Status != "Paid" &&
invoice.Status != "Cancelled" &&
invoice.Status != "RolledOver" &&
invoice.IsActive &&
invoice.CustomerInvoiceDate <= thresholdDate)
.Select(invoice => invoice.FKCustomerSubscriptionId)
.Distinct()
.ToListAsync(ct);
if (overdueSubscriptionIds.Count == 0)
return new List<Guid>();
// One invoice covers the whole subscription, so an unpaid one locks every active
// member on it -- not just the primary. On a group/couple plan the secondaries
// never hold an invoice of their own, so selecting the subscription's owner alone
// would leave them with working access while the plan they share is in arrears
// (and would then have them auto-unlocked again by the Except() in OverdueLockJob).
return await _context.SubscriptionMembers
.AsNoTracking()
.Where(member =>
member.IsActive &&
overdueSubscriptionIds.Contains(member.FKSubscriptionId))
.Select(member => member.FKCustomerId)
.Distinct()
.ToListAsync(ct);
}
public Task<Customer?> GetCustomerByIdAsync(
Guid customerId,
CancellationToken ct = default)
{
return _central.Customer
.AsNoTracking()
.FirstOrDefaultAsync(customer => customer.CusId == customerId, ct);
}
public Task<bool> IsCustomerAccessDisabledAsync(
Guid clientId,
Guid userId,
CancellationToken ct = default)
{
return _context.AccessProfiles.AnyAsync(profile =>
profile.FKClientId == clientId &&
profile.FKUserId == userId &&
profile.DesiredAccessState == "Disabled", ct);
}
public Task<List<Guid>> GetCustomersLockedForOverdueAsync(
Guid clientId,
CancellationToken ct = default)
{
return _context.SubscriptionMembers
.AsNoTracking()
.Where(member =>
member.IsActive &&
member.Subscription.IsActive &&
member.Subscription.CustomerPlan.FKClientId == clientId &&
_context.AccessProfiles.Any(profile =>
profile.FKClientId == clientId &&
profile.FKUserId == member.TenantCustomerLink.CentralUserId &&
profile.DesiredAccessState == "Disabled" &&
profile.LockReason == "Overdue"))
.Select(member => member.FKCustomerId)
.Distinct()
.ToListAsync(ct);
}
}
}