165 lines
7.2 KiB
C#
165 lines
7.2 KiB
C#
using Marco.Pms.Model.Filters;
|
|
using System.Data;
|
|
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, string defaultSortColumn)
|
|
{
|
|
// 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));
|
|
}
|
|
else
|
|
{
|
|
// Default sorting
|
|
query = query.OrderBy($"{defaultSortColumn} desc");
|
|
}
|
|
|
|
|
|
// 3.Apply GroupBy
|
|
if (!string.IsNullOrEmpty(filter?.GroupByColumn))
|
|
{
|
|
query.GroupBy(filter.GroupByColumn, "it")
|
|
.Select("new (Key, it as Items)"); // Reshape to { Key: "Value", Items: [...] }
|
|
}
|
|
return query;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Applies search filters to the given IQueryable.
|
|
/// </summary>
|
|
/// <typeparam name="T">The type of the elements in the IQueryable.</typeparam>
|
|
/// <param name="query">The IQueryable to apply the filters to.</param>
|
|
/// <param name="searchFilters">The list of search filters to apply.</param>
|
|
/// <returns>The filtered IQueryable.</returns>
|
|
public static IQueryable<T> ApplySearchFilters<T>(this IQueryable<T> query, List<SearchItem> searchFilters)
|
|
{
|
|
// Apply search filters to the query
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Applies group by filters to the given IQueryable.
|
|
/// </summary>
|
|
/// <typeparam name="T">The type of the elements in the IQueryable.</typeparam>
|
|
/// <param name="query">The IQueryable to apply the filters to.</param>
|
|
/// <param name="groupByColumn">The column to group by.</param>
|
|
/// <returns>The grouped IQueryable.</returns>
|
|
public static IQueryable<T> ApplyGroupByFilters<T>(this IQueryable<T> query, string groupByColumn)
|
|
{
|
|
// Group the query by the specified column and reshape the result to { Key: "Value", Items: [...] }
|
|
query.GroupBy(groupByColumn, "it")
|
|
.Select("new (Key, it as Items)");
|
|
return query;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Applies list filters to the given IQueryable.
|
|
/// </summary>
|
|
/// <typeparam name="T">The type of the elements in the IQueryable.</typeparam>
|
|
/// <param name="query">The IQueryable to apply the filters to.</param>
|
|
/// <param name="filters">The list of filters to apply.</param>
|
|
/// <returns>The filtered IQueryable.</returns>
|
|
public static IQueryable<T> ApplyListFilters<T>(this IQueryable<T> query, List<ListDynamicFilter> filters)
|
|
{
|
|
// Check if there are any filters
|
|
if (filters == null || !filters.Any()) return query;
|
|
|
|
// Apply filters to the query
|
|
foreach (var filter in filters)
|
|
{
|
|
// Skip if column is empty or values are null or empty
|
|
if (string.IsNullOrWhiteSpace(filter.Column) || filter.Values == null || !filter.Values.Any()) continue;
|
|
|
|
// Apply filter to the query
|
|
query = query.Where($"@0.Contains({filter.Column})", filter.Values);
|
|
}
|
|
|
|
// Return the filtered query
|
|
return query;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Applies date filters to the given IQueryable.
|
|
/// </summary>
|
|
/// <typeparam name="T">The type of the elements in the IQueryable.</typeparam>
|
|
/// <param name="query">The IQueryable to apply the filters to.</param>
|
|
/// <param name="dateFilter">The date filter to apply.</param>
|
|
/// <returns>The filtered IQueryable.</returns>
|
|
public static IQueryable<T> ApplyDateFilter<T>(this IQueryable<T> query, DateDynamicFilter dateFilter)
|
|
{
|
|
// Check if date filter is null or column is empty
|
|
if (dateFilter == null || string.IsNullOrWhiteSpace(dateFilter.Column)) return query;
|
|
|
|
// Convert start and end values to date
|
|
var startValue = dateFilter.StartValue.Date;
|
|
var endValue = dateFilter.EndValue.Date.AddDays(1);
|
|
|
|
// Apply a filter to include items with a date greater than or equal to the start value
|
|
query = query.Where($"{dateFilter.Column} >= @0", startValue);
|
|
|
|
// Apply a filter to include items with a date less than or equal to the end value
|
|
query = query.Where($"{dateFilter.Column} < @0", endValue);
|
|
|
|
// Return the filtered IQueryable
|
|
return query;
|
|
}
|
|
}
|
|
}
|