149 lines
5.4 KiB
C#
149 lines
5.4 KiB
C#
using Fitness_core_BE.Interfaces;
|
|
using Fitness_core_BE.Models;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace Fitness_core_BE.Repos
|
|
{
|
|
public class CustomerPlanRepository : ICustomerPlanRepository
|
|
{
|
|
// Client is central-bucket -- CustomerPlan.Client can't be a same-context Include once
|
|
// central/tenant are physically separate (see TenantDbContext.OnModelCreating). Loaded
|
|
// separately here and attached in memory, same convention as StaffRepository.User.
|
|
private readonly TenantDbContext _context;
|
|
private readonly CentralDbContext _central;
|
|
|
|
public CustomerPlanRepository(TenantDbContext context, CentralDbContext central)
|
|
{
|
|
_context = context;
|
|
_central = central;
|
|
}
|
|
|
|
private async Task AttachClientsAsync(IEnumerable<CustomerPlan> plans)
|
|
{
|
|
var clientIds = plans.Select(p => p.FKClientId).Distinct().ToList();
|
|
if (clientIds.Count == 0) return;
|
|
|
|
var clients = await _central.Client
|
|
.AsNoTracking()
|
|
.Where(c => clientIds.Contains(c.ClientId))
|
|
.ToDictionaryAsync(c => c.ClientId);
|
|
|
|
foreach (var plan in plans)
|
|
{
|
|
if (clients.TryGetValue(plan.FKClientId, out var client))
|
|
plan.Client = client;
|
|
}
|
|
}
|
|
|
|
public async Task<List<CustomerPlan>> GetAllCustomerPlans(bool includeInactive = false, Guid? clientId = null)
|
|
{
|
|
var query = _context.CustomerPlans.AsQueryable();
|
|
|
|
if (clientId.HasValue)
|
|
{
|
|
query = query.Where(cp => cp.FKClientId == clientId.Value);
|
|
}
|
|
|
|
if (!includeInactive)
|
|
{
|
|
query = query.Where(cp => cp.IsActive);
|
|
}
|
|
|
|
var plans = await query
|
|
.OrderBy(cp => cp.PlanName)
|
|
.ToListAsync();
|
|
|
|
await AttachClientsAsync(plans);
|
|
return plans;
|
|
}
|
|
|
|
public async Task<CustomerPlan?> GetCustomerPlanById(Guid customerPlanId)
|
|
{
|
|
var plan = await _context.CustomerPlans
|
|
.FirstOrDefaultAsync(cp => cp.CustomerPlanId == customerPlanId);
|
|
if (plan != null)
|
|
await AttachClientsAsync(new[] { plan });
|
|
return plan;
|
|
}
|
|
|
|
public async Task<CustomerPlan> CreateCustomerPlan(CustomerPlan customerPlan)
|
|
{
|
|
customerPlan.CustomerPlanId = Guid.NewGuid();
|
|
customerPlan.CreatedAt = DateTime.UtcNow;
|
|
customerPlan.IsActive = true;
|
|
|
|
_context.CustomerPlans.Add(customerPlan);
|
|
|
|
return customerPlan;
|
|
}
|
|
|
|
public async Task<CustomerPlan> UpdateCustomerPlan(CustomerPlan customerPlan)
|
|
{
|
|
var existingPlan = await _context.CustomerPlans.FindAsync(customerPlan.CustomerPlanId);
|
|
|
|
if (existingPlan == null)
|
|
{
|
|
throw new Exception("Customer Plan not found");
|
|
}
|
|
|
|
// The service merges provided keys onto the loaded entity and validates
|
|
// the combined configuration, so this is a direct full assignment.
|
|
existingPlan.PlanName = customerPlan.PlanName;
|
|
existingPlan.PlanDescription = customerPlan.PlanDescription;
|
|
existingPlan.PlanPrice = customerPlan.PlanPrice;
|
|
existingPlan.DurationInDays = customerPlan.DurationInDays;
|
|
existingPlan.PlanScope = customerPlan.PlanScope;
|
|
existingPlan.MemberLimit = customerPlan.MemberLimit;
|
|
existingPlan.DurationMode = customerPlan.DurationMode;
|
|
existingPlan.ValidFrom = customerPlan.ValidFrom;
|
|
existingPlan.ValidTo = customerPlan.ValidTo;
|
|
existingPlan.AllowSplitPayments = customerPlan.AllowSplitPayments;
|
|
existingPlan.InstallmentCount = customerPlan.InstallmentCount;
|
|
existingPlan.SessionsPerCycle = customerPlan.SessionsPerCycle;
|
|
existingPlan.SessionRolloverPolicy = customerPlan.SessionRolloverPolicy;
|
|
existingPlan.RolloverGraceDays = customerPlan.RolloverGraceDays;
|
|
existingPlan.BillingTiming = customerPlan.BillingTiming;
|
|
existingPlan.IsActive = customerPlan.IsActive;
|
|
|
|
return existingPlan;
|
|
}
|
|
|
|
public async Task<CustomerPlan?> SetCustomerPlanActive(Guid customerPlanId, Guid clientId, bool isActive)
|
|
{
|
|
var plan = await _context.CustomerPlans
|
|
.FirstOrDefaultAsync(cp => cp.CustomerPlanId == customerPlanId && cp.FKClientId == clientId);
|
|
|
|
if (plan == null)
|
|
return null;
|
|
|
|
plan.IsActive = isActive;
|
|
|
|
await AttachClientsAsync(new[] { plan });
|
|
return plan;
|
|
}
|
|
|
|
public async Task<bool> DeleteCustomerPlan(Guid customerPlanId, bool softDelete = true)
|
|
{
|
|
var customerPlan = await _context.CustomerPlans.FindAsync(customerPlanId);
|
|
|
|
if (customerPlan == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (softDelete)
|
|
{
|
|
// Soft delete: just mark as inactive
|
|
customerPlan.IsActive = false;
|
|
}
|
|
else
|
|
{
|
|
// Hard delete: remove from database
|
|
_context.CustomerPlans.Remove(customerPlan);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
}
|