85 lines
3.5 KiB
C#

using Marco.Pms.Model.Filters;
using System.Linq.Dynamic.Core;
namespace Marco.Pms.Services.Extensions
{
/// <summary>
/// Enterprise-grade extension methods for applying dynamic filters and sorting to IQueryable sources.
/// </summary>
public static class QueryableExtensions
{
public static IQueryable<T> ApplyCustomFilters<T>(this IQueryable<T> query, AdvanceFilter filter)
{
// 1. Apply Advanced Filters (Arithmetic/Logic)
if (filter.AdvanceFilters != null && filter.AdvanceFilters.Any())
{
foreach (var advanceFilter in filter.AdvanceFilters)
{
if (string.IsNullOrWhiteSpace(advanceFilter.Column)) continue;
string op = advanceFilter.Opration.ToLower().Trim();
string predicate = "";
// Map your custom strings to Dynamic LINQ operators
switch (op)
{
case "greater than": predicate = $"{advanceFilter.Column} > @0"; break;
case "less than": predicate = $"{advanceFilter.Column} < @0"; break;
case "equal to": predicate = $"{advanceFilter.Column} == @0"; break;
case "not equal": predicate = $"{advanceFilter.Column} != @0"; break;
case "greater or equal": predicate = $"{advanceFilter.Column} >= @0"; break;
case "smaller or equal": predicate = $"{advanceFilter.Column} <= @0"; break;
default: continue;
}
if (!string.IsNullOrEmpty(predicate))
{
// Dynamic LINQ handles type conversion (string "100" to int 100) automatically
query = query.Where(predicate, advanceFilter.Value);
}
}
}
// 2. Apply Sorting
if (filter.SortFilters != null && filter.SortFilters.Any())
{
// Build a comma-separated sort string: "Column1 desc, Column2 asc"
var sortExpressions = new List<string>();
foreach (var sort in filter.SortFilters)
{
string direction = sort.SortDescending ? "desc" : "asc";
sortExpressions.Add($"{sort.Column} {direction}");
}
query = query.OrderBy(string.Join(", ", sortExpressions));
}
return query;
}
public static IQueryable<T> ApplySearchFilters<T>(this IQueryable<T> query, List<SearchItem> searchFilters)
{
// 1. Apply Search Filters (Contains/Text search)
if (searchFilters.Any())
{
foreach (var search in searchFilters)
{
if (string.IsNullOrWhiteSpace(search.Column) || string.IsNullOrWhiteSpace(search.Value)) continue;
// Generates: x.Column.Contains("Value")
// Case insensitive logic can be handled here if needed
query = query.Where($"{search.Column}.Contains(@0)", search.Value);
}
}
return query;
}
public static IQueryable<T> ApplyGroupByFilters<T>(this IQueryable<T> query, string groupByColumn)
{
query.GroupBy(groupByColumn).Select("new (Key, ToList() as Items)"); // Reshape to { Key: "Value", Items: [...] }
return query;
}
}
}