@@ -1,5 +1,4 @@
|
||||
using System.Text.Json;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Tiku.Application.Catalog;
|
||||
@@ -20,9 +19,7 @@ public sealed partial class ScorelineQueryService(
|
||||
var query = dbContext.ScorelineFields.AsNoTracking()
|
||||
.Where(field => field.TenantId == filter.TenantId);
|
||||
if (filter.RegionId.HasValue)
|
||||
{
|
||||
query = query.Where(field => field.RegionId == filter.RegionId.Value || field.RegionId == null);
|
||||
}
|
||||
|
||||
var fields = await query
|
||||
.OrderBy(field => field.SortOrder)
|
||||
@@ -90,25 +87,13 @@ public sealed partial class ScorelineQueryService(
|
||||
{
|
||||
var query = dbContext.ScorelineRecords.AsNoTracking()
|
||||
.Where(record => record.TenantId == filter.TenantId);
|
||||
if (filter.RegionId.HasValue)
|
||||
{
|
||||
query = query.Where(record => record.RegionId == filter.RegionId.Value);
|
||||
}
|
||||
if (filter.RegionId.HasValue) query = query.Where(record => record.RegionId == filter.RegionId.Value);
|
||||
|
||||
if (filter.SchoolId.HasValue)
|
||||
{
|
||||
query = query.Where(record => record.SchoolId == filter.SchoolId.Value);
|
||||
}
|
||||
if (filter.SchoolId.HasValue) query = query.Where(record => record.SchoolId == filter.SchoolId.Value);
|
||||
|
||||
if (filter.MajorId.HasValue)
|
||||
{
|
||||
query = query.Where(record => record.MajorId == filter.MajorId.Value);
|
||||
}
|
||||
if (filter.MajorId.HasValue) query = query.Where(record => record.MajorId == filter.MajorId.Value);
|
||||
|
||||
if (filter.Year.HasValue)
|
||||
{
|
||||
query = query.Where(record => record.Year == filter.Year.Value);
|
||||
}
|
||||
if (filter.Year.HasValue) query = query.Where(record => record.Year == filter.Year.Value);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(filter.Keyword))
|
||||
{
|
||||
@@ -126,14 +111,12 @@ public sealed partial class ScorelineQueryService(
|
||||
foreach (var dynamicFilter in filters ?? [])
|
||||
{
|
||||
if (!FieldKeyRegex().IsMatch(dynamicFilter.FieldKey))
|
||||
{
|
||||
throw new ScorelineQueryException("Scoreline field filter key is invalid.", "scoreline_field_filter_key_invalid");
|
||||
}
|
||||
throw new ScorelineQueryException("Scoreline field filter key is invalid.",
|
||||
"scoreline_field_filter_key_invalid");
|
||||
|
||||
if (dynamicFilter.Operator is not ("field" or "min" or "max"))
|
||||
{
|
||||
throw new ScorelineQueryException("Scoreline field filter operator is invalid.", "scoreline_field_filter_operator_invalid");
|
||||
}
|
||||
throw new ScorelineQueryException("Scoreline field filter operator is invalid.",
|
||||
"scoreline_field_filter_operator_invalid");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,24 +135,19 @@ public sealed partial class ScorelineQueryService(
|
||||
|
||||
private static ScorelineCursorPosition? DecodeCursor(string? cursor)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(cursor))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(cursor)) return null;
|
||||
|
||||
try
|
||||
{
|
||||
var normalized = cursor.Replace('-', '+').Replace('_', '/');
|
||||
normalized = normalized.PadRight(normalized.Length + ((4 - normalized.Length % 4) % 4), '=');
|
||||
normalized = normalized.PadRight(normalized.Length + (4 - normalized.Length % 4) % 4, '=');
|
||||
using var document = JsonDocument.Parse(Convert.FromBase64String(normalized));
|
||||
var root = document.RootElement;
|
||||
if (root.GetProperty("v").GetInt32() != 1 ||
|
||||
!root.TryGetProperty("year", out var year) ||
|
||||
!root.TryGetProperty("id", out var id) ||
|
||||
!Guid.TryParse(id.GetString(), out var recordId))
|
||||
{
|
||||
throw new FormatException();
|
||||
}
|
||||
|
||||
return new ScorelineCursorPosition(
|
||||
year.GetInt32(),
|
||||
@@ -177,16 +155,20 @@ public sealed partial class ScorelineQueryService(
|
||||
ReadNullableString(root, "majorName"),
|
||||
recordId);
|
||||
}
|
||||
catch (Exception exception) when (exception is FormatException or JsonException or InvalidOperationException or KeyNotFoundException)
|
||||
catch (Exception exception) when (exception is FormatException or JsonException or InvalidOperationException
|
||||
or KeyNotFoundException)
|
||||
{
|
||||
throw new ScorelineQueryException("Scoreline cursor is invalid or unsupported.", "scoreline_cursor_invalid");
|
||||
throw new ScorelineQueryException("Scoreline cursor is invalid or unsupported.",
|
||||
"scoreline_cursor_invalid");
|
||||
}
|
||||
}
|
||||
|
||||
private static string? ReadNullableString(JsonElement root, string name) =>
|
||||
root.TryGetProperty(name, out var value) && value.ValueKind == JsonValueKind.String
|
||||
private static string? ReadNullableString(JsonElement root, string name)
|
||||
{
|
||||
return root.TryGetProperty(name, out var value) && value.ValueKind == JsonValueKind.String
|
||||
? value.GetString()
|
||||
: null;
|
||||
}
|
||||
|
||||
private static ScorelineFieldItem ToFieldItem(ScorelineField field)
|
||||
{
|
||||
@@ -229,4 +211,4 @@ public sealed partial class ScorelineQueryService(
|
||||
|
||||
[GeneratedRegex("^[A-Za-z][A-Za-z0-9_]{0,63}$")]
|
||||
private static partial Regex FieldKeyRegex();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user