first commit
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user