using LanguageExt.Common;
using ParticipantGroupModule.DTOs;
namespace ParticipantGroupModule.Services;
public class ParticipantGroupFilterService : IParticipantGroupFilterService
{
private readonly CommonContext _commonContext;
private readonly IUserAccessControlService _userAccessControlService;
private readonly ILoggedInUserService _loggedInUserService;
public ParticipantGroupFilterService(
CommonContext commonContext,
IUserAccessControlService userAccessControlService,
ILoggedInUserService loggedInUserService)
{
_commonContext = commonContext;
_userAccessControlService = userAccessControlService;
_loggedInUserService = loggedInUserService;
}
private bool GroupFilterHasAnyValue(object model)
{
if (model == null) return false;
var properties = model.GetType().GetProperties();
foreach (var property in properties)
{
var value = property.GetValue(model);
if (value != null && property
.PropertyType == typeof(string) && !string.IsNullOrWhiteSpace((string)value))
{
return true;
}
}
return false;
}
public object GetFilteredParticipantGroups(ParticipantGroupFilterDto participantGroupFilterDto)
{
var hasData = GroupFilterHasAnyValue(participantGroupFilterDto);
var participantGroups = _commonContext.ParticipantGroups.AsQueryable();
if (string.IsNullOrEmpty(participantGroupFilterDto.CountryId))
{
participantGroups = FilterByCountryAccess(participantGroups);
}
if (string.IsNullOrEmpty(participantGroupFilterDto.ProjectId))
{
participantGroups = FilterByProjectAccess(participantGroups);
}
if (string.IsNullOrEmpty(participantGroupFilterDto.CatchmentId))
{
participantGroups = FilterByVillageAccess(participantGroups);
}
participantGroups = participantGroups.Where(participantGroup =>
(string.IsNullOrEmpty(participantGroupFilterDto.CountryId) || participantGroup.CountryId == participantGroupFilterDto.CountryId) &&
(string.IsNullOrEmpty(participantGroupFilterDto.ProjectId) || participantGroup.ProjectId == participantGroupFilterDto.ProjectId) &&
(string.IsNullOrEmpty(participantGroupFilterDto.CatchmentId) || participantGroup.CatchmentId == participantGroupFilterDto.CatchmentId) &&
(string.IsNullOrEmpty(participantGroupFilterDto.ServicePointId) || participantGroup.ServicePointId == participantGroupFilterDto.ServicePointId) &&
(string.IsNullOrEmpty(participantGroupFilterDto.GroupTypeId) || participantGroup.ParticipantGroupTypeId == participantGroupFilterDto.GroupTypeId)
);
var totalParticipantGroups = GetFinalParticipantGroups(participantGroups);
if (!hasData)
{
{
ParticipantGroups = totalParticipantGroups.Take(200).AsEnumerable(),
totalGroups = totalParticipantGroups.Count()
};
}
{
ParticipantGroups = totalParticipantGroups.AsEnumerable(),
totalGroups = totalParticipantGroups.Count()
};
}
private IQueryable<ParticipantGroup> FilterByCountryAccess(IQueryable<ParticipantGroup> participantGroups)
{
if (_loggedInUserService.IsSystemAdmin())
{
// System admin can get all participant groups. Hence, don't need to check accessed countries.
return participantGroups;
}
var permittedCountryIds = _userAccessControlService.GetAllCountry()
.Select(x => x.Id)
.Distinct();
return participantGroups.Join(
permittedCountryIds,
p => p.CountryId,
countryId => countryId,
(p, c) => p);
}
private IQueryable<ParticipantGroup> FilterByProjectAccess(IQueryable<ParticipantGroup> participantGroups)
{
if (_loggedInUserService.IsSystemAdmin())
{
// System admin can get all participant groups. Hence, don't need to check accessed projects.
return participantGroups;
}
var permittedProjectIds = _userAccessControlService.GetAllProject()
.Select(x => x.Id)
.Distinct();
return participantGroups.Join(
permittedProjectIds,
participantGroup => participantGroup.ProjectId,
projectId => projectId,
(participantGroup, projectId) => participantGroup);
}
private IQueryable<ParticipantGroup> FilterByVillageAccess(IQueryable<ParticipantGroup> participantGroups)
{
if (_loggedInUserService.IsSystemAdmin())
{
// System admin can get all participant groups. Hence, don't need to check accessed villages.
return participantGroups;
}
var permittedVillageIds = _userAccessControlService.GetPermittedVillageIdsAsQueryable();
return participantGroups.
Where(x => permittedVillageIds.Contains(x.CatchmentId!));
}
private IQueryable<object> GetFinalParticipantGroups(IQueryable<ParticipantGroup> participantGroups)
{
return
(from pg in participantGroups
join b in _commonContext.BranchOfficeVillageMappings
on
new { pg
.CatchmentId, pg
.ProjectId } equals
new { b
.CatchmentId, b
.ProjectId }
into branchOffices
from branchOffice in branchOffices.DefaultIfEmpty()
join pgm in _commonContext.ParticipantGroupMembers
on pg.Id equals pgm.GroupId
into pgMembers
{
pg.Id,
pg.Name,
pg.ParticipantGroupTypeId,
pg.StakeholderTypeId,
pg.CatchmentId,
pg.ServicePointId,
pg.CatchmentIdsForMemberSelection,
pg.CountryId,
pg.ProjectId,
pg.FiscalYearId,
branchOffice.BranchOfficeId,
NumberOfParticipant = pgMembers.Count()
} into pgGrouped
{
pgGrouped.Key.Id,
pgGrouped.Key.Name,
pgGrouped.Key.ParticipantGroupTypeId,
pgGrouped.Key.StakeholderTypeId,
pgGrouped.Key.CatchmentId,
pgGrouped.Key.ServicePointId,
pgGrouped.Key.CatchmentIdsForMemberSelection,
pgGrouped.Key.CountryId,
pgGrouped.Key.ProjectId,
pgGrouped.Key.FiscalYearId,
pgGrouped.Key.BranchOfficeId,
pgGrouped.Key.NumberOfParticipant
});
}
}