Files
monorepo/LCU.API.Operations.IncentiveAPI/LCU.API.Internal.Operations.IncentiveApiLib/Repositories/ActivityRepository.cs
T
2026-03-17 09:53:09 -05:00

567 lines
22 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using LCU.API.Internal.Operations.IncentiveApiLib.Extensions;
using LCU.API.Internal.Operations.IncentiveApiLib.Persistence;
using LCU.Library.Internal.IncentiveApiModels.Common;
using LCU.Library.Internal.IncentiveApiModels.Entities;
using LCU.Library.Internal.IncentiveApiModels.Enums;
using Microsoft.EntityFrameworkCore;
namespace LCU.API.Internal.Operations.IncentiveApiLib.Repositories;
public class ActivityRepository : BaseRepository, IActivityRepository
{
public ActivityRepository(IApplicationDbContext context) : base(context)
{
}
public async Task<int> SaveActivityAsync(Activity activity)
{
await _context.Activities.AddAsync(activity);
return activity.Id;
}
public async Task SaveActivityRangeAsync(List<Activity> activities)
{
await _context.Activities.AddRangeAsync(activities);
}
public void UpdateActivityRangeAsync(List<Activity> activities)
{
var existing = activities.Where(x => _context.Activities.Contains(x));
_context.Activities.UpdateRange(activities);
}
public async Task<IReadOnlyCollection<Activity>> GetActivitiesAsync()
{
return await _context.Activities
.Include(activity => activity.Detail)
.Include(activity => activity.MetaData)
.OrderBy(t => t.Id)
.ToListAsync();
}
public async Task<PagedResult<Activity>> GetActivitiesAsync(int page, int limit)
{
var results = new PagedResult<Activity>();
var skip = (page - 1) * limit;
var activities = _context.Activities
.Include(activity => activity.Detail)
.Include(activity => activity.MetaData)
.OrderByDescending(t => t.Created);
results.Total = activities.Count();
results.Items = await activities.Skip(skip).Take(limit).ToListAsync();
return results;
}
public async Task<IReadOnlyCollection<Activity>> FindUnmatchedReferrals()
{
var activities = _context.Activities.Include(activity => activity.Detail).Include(activity => activity.MetaData);
IQueryable<Activity> querySet = activities
.Where(x => x.Type == ActivityType.Referral
&& x.State == ActivityState.PendingReferral)
.OrderByDescending(t => t.LastUpdated);
return await querySet.ToListAsync();
}
public async Task<IReadOnlyCollection<Activity>> FindPendingEStatementsReferrals()
{
var activities = _context.Activities.Include(activity => activity.Detail).Include(activity => activity.MetaData);
IQueryable<Activity> querySet = activities
.Where(x => x.Type == ActivityType.Referral
&& x.State == ActivityState.PendingReferral
&& x.Product == Product.eStatement
&& string.IsNullOrEmpty(x.Detail.AccountNumber))
.OrderByDescending(t => t.LastUpdated);
return await querySet.ToListAsync();
}
public async Task<Activity> FindUnmatchedSaleForReferral(Activity referral)
{
var activities = _context.Activities
.Include(activity => activity.Detail)
.Include(activity => activity.MetaData);
var matchOnMetaData = string.IsNullOrEmpty(referral.Detail.SubjectOrgNbr) && string.IsNullOrEmpty(referral.Detail.SubjectPersonNbr);
var matchedActivities = matchOnMetaData
? await activities.Where(MetaDataMatchPredicate(referral)).ToListAsync()
: await activities.Where(PersonDataMatchPredicate(referral)).ToListAsync();
if (matchOnMetaData && matchedActivities.Any())
{
matchedActivities = matchedActivities.Where(x =>
ListsContainMatchingItem(
x.MetaData.Where(e => e.MetaDataType == MetaDataType.Email).Select(e => e.MetaData).ToList(),
referral.MetaData.Where(r => r.MetaDataType == MetaDataType.Email).Select(e => e.MetaData).ToList()
)
||
ListsContainMatchingItem(
x.MetaData.Where(e => e.MetaDataType == MetaDataType.Phone).Select(e => e.MetaData).ToList(),
referral.MetaData.Where(r => r.MetaDataType == MetaDataType.Phone).Select(e => e.MetaData).ToList()
)
)
.ToList();
}
var matchingSaleActivityIds = matchedActivities.Select(x => x.Id);
var activityIDsAssociatedToStateChange = _context.ActivityStateChanges
.Where(change => matchingSaleActivityIds.Contains(change.ActivityMatchId))
.Select(x => x.ActivityMatchId);
var activityIDsNotAssociatedToStateChange = matchingSaleActivityIds.Except(activityIDsAssociatedToStateChange);
return matchedActivities.Where(x => activityIDsNotAssociatedToStateChange.Contains(x.Id))
.OrderByDescending(t => t.LastUpdated)
.FirstOrDefault();
}
public EStatementDeliveryMethod FindDeliveryMethodForEStatement(Activity referral, List<EStatementDeliveryMethod> deliveryMethods)
{
var matchedMethods = new List<EStatementDeliveryMethod>();
var nullReferralOrgNumber = "0";
var matchableDeliveryMethods = deliveryMethods.Where(x => x.ActivityDateTime.Date >= referral.SourceCreated.Date).ToList();
matchedMethods.AddRange(matchableDeliveryMethods.Where(x => x.PersonNumber == referral.Detail.SubjectPersonNbr
|| x.OrganizationNumber == (referral.Detail.SubjectOrgNbr ?? nullReferralOrgNumber)
&& x.OrganizationNumber != nullReferralOrgNumber
&& referral.Detail.SubjectOrgNbr != nullReferralOrgNumber));
matchedMethods.AddRange(matchableDeliveryMethods.Where(x =>
ListsContainMatchingItem(
x.MetaData.Where(e => e.MetaDataType == MetaDataType.Email).Select(e => e.MetaData).ToList(),
referral.MetaData.Where(r => r.MetaDataType == MetaDataType.Email).Select(e => e.MetaData).ToList()
)
||
ListsContainMatchingItem(
x.MetaData.Where(e => e.MetaDataType == MetaDataType.Phone).Select(e => e.MetaData).ToList(),
referral.MetaData.Where(r => r.MetaDataType == MetaDataType.Phone).Select(e => e.MetaData).ToList()
)
)
.ToList());
var matchedMethod = matchedMethods.OrderByDescending(a => a.ActivityDateTime).FirstOrDefault();
if (matchedMethod != null)
{
deliveryMethods.Remove(matchedMethod);
}
return matchedMethod;
}
private static Expression<Func<Activity, bool>> MetaDataMatchPredicate(Activity referral)
{
return x => (x.Type == ActivityType.Sale || x.Type == ActivityType.Other)
&& x.Product == referral.Product
&& x.MetaData != null && referral.MetaData != null
&& x.State == ActivityState.Accepted
&& x.SourceCreated.Date >= referral.SourceCreated.Date;
}
private static bool ListsContainMatchingItem(IReadOnlyList<string> list1, IReadOnlyList<string> list2)
{
if ((list1?.Any() ?? false) && (list2?.Any() ?? false))
{
return list1.Any(x => list2.Any(t => string.Equals(t, x, StringComparison.CurrentCultureIgnoreCase)));
}
return false;
}
private static Expression<Func<Activity, bool>> PersonDataMatchPredicate(Activity referral)
{
return x => (x.Type == ActivityType.Sale || x.Type == ActivityType.Other)
&& x.Product == referral.Product
&& x.Detail.SubjectPersonNbr == referral.Detail.SubjectPersonNbr
&& x.Detail.SubjectOrgNbr == referral.Detail.SubjectOrgNbr
&& x.State == ActivityState.Accepted
&& x.SourceCreated.Date >= referral.SourceCreated.Date;
}
public async Task<Activity> FindDuplicateSaleAsync(Activity queryActivity)
{
if (queryActivity.Detail == null || queryActivity.Type != ActivityType.Sale)
{
return null;
}
var activities = _context.Activities
.Include(activity => activity.Detail)
.Include(activity => activity.MetaData);
IQueryable<Activity> querySet = activities
.Where(x => x.Id != queryActivity.Id
&& x.Product == queryActivity.Product
&& x.Type == queryActivity.Type
&& x.Detail.AccountNumber == queryActivity.Detail.AccountNumber
&& x.Detail.SubAccountNumber == queryActivity.Detail.SubAccountNumber
&& x.Detail.SubjectOrgNbr == queryActivity.Detail.SubjectOrgNbr
&& x.Detail.SubjectPersonNbr == queryActivity.Detail.SubjectPersonNbr
&& (
queryActivity.SourceId == null
|| x.SourceId == queryActivity.SourceId)
)
.OrderByDescending(t => t.LastUpdated);
return await querySet.FirstOrDefaultAsync();
}
public async Task<Activity> FindDuplicateReferralAsync(Activity queryActivity)
{
if (queryActivity.Detail == null || queryActivity.Type != ActivityType.Referral)
{
return null;
}
var activities = _context.Activities
.Include(activity => activity.Detail);
IQueryable<Activity> querySet = activities
.Where(x => x.Id != queryActivity.Id
&& x.Type == queryActivity.Type && x.Product == queryActivity.Product
&& x.Detail.SubjectPersonNbr != null && queryActivity.Detail.SubjectPersonNbr != null
&& x.Detail.SubjectOrgNbr != null && queryActivity.Detail.SubjectOrgNbr != null
&& x.Detail.SubjectPersonNbr == queryActivity.Detail.SubjectPersonNbr
&& x.Detail.SubjectOrgNbr == queryActivity.Detail.SubjectOrgNbr
)
.OrderByDescending(t => t.LastUpdated);
return await querySet.FirstOrDefaultAsync();
}
public async Task<Activity> FindActivityForStateUpdate(Activity queryActivity)
{
if (queryActivity.Detail == null)
{
return null;
}
var activities = _context.Activities
.Include(activity => activity.Detail)
.Include(activity => activity.MetaData);
IQueryable<Activity> querySet = activities
.Where(x => x.EmployeeEmail == queryActivity.EmployeeEmail
&& x.EmployeeId == queryActivity.EmployeeId
&& x.DepartmentId == queryActivity.DepartmentId
&& x.Product == queryActivity.Product
&& x.SourceCreated.Date == queryActivity.SourceCreated.Date
&& x.SourceSystem == queryActivity.SourceSystem
&& x.Type == queryActivity.Type
&& x.Detail.AccountNumber == queryActivity.Detail.AccountNumber
&& x.Detail.SubAccountNumber == queryActivity.Detail.SubAccountNumber
)
.OrderByDescending(t => t.LastUpdated);
var returnedItems = await querySet.ToListAsync();
Func<Activity, bool> activityStateCondition = x => x.State != queryActivity.State;
var returnItem = returnedItems.Count(activityStateCondition) > 1
? returnedItems.FirstOrDefault(activityStateCondition)
: returnedItems.FirstOrDefault();
return returnItem;
}
public async Task<Activity> FindActivityForDetailUpdate(Activity queryActivity)
{
if (queryActivity.Detail == null)
{
return null;
}
var returnedItems = await GetActivityForDetailUpdate(queryActivity);
if (returnedItems.Count == 0)
{
returnedItems = await GetActivityForDetailUpdate(queryActivity, false);
}
if (returnedItems.Count == 0)
{
return null;
}
Func<Activity, bool> activityStatePredicate = x => x.State == ActivityState.Accepted;
var returnItem = returnedItems.Count(activityStatePredicate) >= 1
? returnedItems.FirstOrDefault(activityStatePredicate)
: returnedItems.FirstOrDefault();
return returnItem;
}
private async Task<List<Activity>> GetActivityForDetailUpdate(Activity queryActivity, bool filterOnSubAccountNumber = true)
{
var activities = _context.Activities
.Include(activity => activity.Detail)
.Include(activity => activity.MetaData);
IQueryable<Activity> querySet = activities
.Where(x => x.EmployeeEmail == queryActivity.EmployeeEmail
&& x.EmployeeId == queryActivity.EmployeeId
&& x.DepartmentId == queryActivity.DepartmentId
&& x.Product == queryActivity.Product
&& x.SourceSystem == queryActivity.SourceSystem
&& x.Type == queryActivity.Type
&& x.Detail.AccountNumber == queryActivity.Detail.AccountNumber
)
.OrderByDescending(t => t.LastUpdated);
if (filterOnSubAccountNumber)
{
return await querySet.Where(x => x.Detail.SubAccountNumber == queryActivity.Detail.SubAccountNumber).ToListAsync();
}
return await querySet.Where(x => x.State == ActivityState.Accepted).ToListAsync();
}
public async Task<PagedResult<Activity>> GetPagedFilteredActivities(ActivityFilter filter)
{
var results = new PagedResult<Activity>();
var skip = (filter.Page - 1) * filter.Limit;
var activities = _context.Activities.Include(activity => activity.Detail).Include(activity => activity.MetaData);
IQueryable<Activity> querySet = activities;
if (filter.Product != null && filter.Product.Any())
{
var products = filter.Product;
querySet = querySet.Where(x => products.Contains(x.Product));
}
if (filter.Type != null && filter.Type.Any())
{
var types = filter.Type;
querySet = querySet.Where(x => types.Contains(x.Type));
}
if (filter.State != null && filter.State.Any())
{
var states = filter.State;
querySet = querySet.Where(x => states.Contains(x.State));
}
if (filter.DateLow != null)
{
querySet = querySet.Where(x => x.Accepted.Date >= filter.DateLow);
}
if (filter.DateHigh != null)
{
querySet = querySet.Where(x => x.Accepted.Date <= filter.DateHigh);
}
if (filter.DepartmentId != 0)
{
querySet = querySet.Where(x => x.DepartmentId == filter.DepartmentId);
}
if (!string.IsNullOrWhiteSpace(filter.EmployeeId))
{
querySet = querySet.Where(x => x.EmployeeId == filter.EmployeeId);
}
if (!string.IsNullOrWhiteSpace(filter.Query))
{
var query = filter.Query.ToLower().Trim();
querySet = querySet.Where(x =>
x.Detail.MemberName.ToLower().Contains(query)
|| x.Detail.AccountNumber.ToLower().Contains(query)
|| x.Detail.SubjectPersonNbr.ToLower().Contains(query)
|| x.Detail.SubjectOrgNbr.ToLower().Contains(query)
|| x.SourceId.ToLower() == query
|| query == x.Id.ToString());
}
querySet = SortQuerySet(querySet, filter);
results.Total = querySet.Count();
results.Items = await querySet.Skip(skip).Take(filter.Limit).ToListAsync();
return results;
}
public async Task<List<Activity>> GetAllActivitiesWithPayoutsForEmployee(string employeeId)
{
return await _context.Activities.Include(activity => activity.ActivityPayouts).Where(x => x.EmployeeId == employeeId).ToListAsync();
}
private IQueryable<Activity> SortQuerySet(IQueryable<Activity> querySet, ActivityFilter filter)
{
if (string.IsNullOrWhiteSpace(filter.SortBy))
{
return querySet
.OrderByDescending(t => t.Accepted);
}
if (filter.SortDescending.HasValue && filter.SortDescending.Value)
{
return (IQueryable<Activity>)querySet.OrderByDescending<Activity>(filter.SortBy);
}
return (IQueryable<Activity>)querySet.OrderBy<Activity>(filter.SortBy);
}
public async Task<Activity> GetActivityById(int activityId)
{
return await _context.Activities.FindAsync(activityId);
}
public async Task<ICollection<Activity>> FindEmployeeActivityByMonthRange(AppUser appUser, MonthRange monthRange)
{
return await _context.Activities
.Include(activity => activity.Detail)
.Include(activity => activity.MetaData)
.Where(x => x.Accepted.Date >= monthRange.StartTime.Date &&
x.Accepted.Date <= monthRange.EndTime.Date &&
appUser.EmployeeId == x.EmployeeId)
.ToListAsync();
}
public async Task<ICollection<Activity>> FindDepartmentActivityByMonthRange(int departmentId, MonthRange monthRange)
{
return await _context.Activities
.Include(activity => activity.Detail)
.Include(activity => activity.MetaData)
.Where(x => x.Accepted.Date >= monthRange.StartTime.Date &&
x.Accepted.Date <= monthRange.EndTime.Date &&
x.DepartmentId == departmentId)
.ToListAsync();
}
public async Task<Activity> GetActivityIncludingPayouts(int activityId)
{
return await _context.Activities
.Include(activity => activity.Detail)
.Include(activity => activity.MetaData)
.Include(activity => activity.ActivityPayouts)
.ThenInclude(payouts => payouts.PayoutLineItem)
.FirstOrDefaultAsync(x => x.Id == activityId);
}
public async Task<List<Activity>> GetActivitiesBySourceId(List<string> sourceIds)
{
return await _context.Activities.Where(x => sourceIds.Contains(x.SourceId)).ToListAsync();
}
public async Task<Activity> FindDuplicateReferralBySourceIdAsync(Activity queryActivity)
{
if (queryActivity.Detail == null || queryActivity.Type != ActivityType.Referral)
{
return null;
}
var activities = _context.Activities
.Include(activity => activity.Detail)
.Include(activity => activity.MetaData);
IQueryable<Activity> querySet = activities
.Where(x => x.Id != queryActivity.Id
&& x.Type == queryActivity.Type
&& x.Product == queryActivity.Product
&& x.SourceId == queryActivity.SourceId)
.OrderByDescending(t => t.LastUpdated);
return await querySet.FirstOrDefaultAsync();
}
public async Task<List<Activity>> FindById(
List<int> ids,
bool withDetail = true,
bool withTracking = true
)
{
if (!ids.Any())
{
return new List<Activity>();
}
var query = withTracking
? _context.Activities
: _context.Activities.AsNoTracking();
if (withDetail)
{
query = query.Include(activity => activity.Detail);
}
query = query.Where(activity => ids.Contains(activity.Id));
return await query.ToListAsync();
}
public async Task<List<Activity>> FindLatestBySourceId(
List<string> sourceIds,
bool withDetail = true,
bool withTracking = true
)
{
if (!sourceIds.Any())
{
return new List<Activity>();
}
var query = withTracking
? _context.Activities
: _context.Activities.AsNoTracking();
if (withDetail)
{
query = query.Include(activity => activity.Detail);
}
return (await query
.Where(activity => sourceIds.Contains(activity.SourceId))
.GroupBy(activity => activity.SourceId)
.Select(group => group.OrderBy(activity => activity.Created).FirstOrDefault())
.ToListAsync())
.Where(activity => activity != null)
.ToList();
}
public async Task<List<Activity>> FindGapInsuranceEligible(
MonthRange monthRange,
bool withTracking = true
)
{
var query = withTracking
? _context.Activities
: _context.Activities.AsNoTracking();
return await query
.Include(activity => activity.Detail)
.Where(activity =>
activity.Detail != null &&
activity.Detail.IsGapInsuranceEligible &&
activity.Accepted.Date >= monthRange.StartTime.Date &&
activity.Accepted.Date <= monthRange.EndTime.Date)
.ToListAsync();
}
public async Task<List<Activity>> GetFilteredActivities(
MonthRange monthRange,
Product product,
ActivityState activityState,
bool withTracking = true
)
{
var querySet = withTracking
? _context.Activities
: _context.Activities.AsNoTracking();
return await querySet
.Include(activity => activity.Detail)
.Where(
activity =>
activity.Accepted.Date >= monthRange.StartTime.Date &&
activity.Accepted.Date <= monthRange.EndTime.Date &&
activity.Product == product &&
activity.State == activityState
)
.ToListAsync();
}
}