fix: sidebar accordion + koja slug + support ticket LINQ crash
CI/CD / CI · API (dotnet build + test) (push) Successful in 5m50s
CI/CD / CI · Admin API (dotnet build) (push) Successful in 32s
CI/CD / CI · Dashboard (tsc) (push) Successful in 1m3s
CI/CD / CI · Admin Web (tsc) (push) Successful in 35s
CI/CD / CI · Website (tsc) (push) Successful in 44s
CI/CD / CI · Koja (tsc) (push) Successful in 48s
CI/CD / Deploy · all services (push) Has been cancelled
CI/CD / CI · API (dotnet build + test) (push) Successful in 5m50s
CI/CD / CI · Admin API (dotnet build) (push) Successful in 32s
CI/CD / CI · Dashboard (tsc) (push) Successful in 1m3s
CI/CD / CI · Admin Web (tsc) (push) Successful in 35s
CI/CD / CI · Website (tsc) (push) Successful in 44s
CI/CD / CI · Koja (tsc) (push) Successful in 48s
CI/CD / Deploy · all services (push) Has been cancelled
Sidebar:
- All groups start collapsed on first load (v4 storage key resets old state)
- Opening one group closes all others (accordion)
- Navigating to a section opens only that section's group
Koja slug:
- SlugHelper: Persian->Latin transliteration, slug validation
- Registration accepts optional custom slug; auto-derives from cafe name
- Slug can be updated from dashboard Settings -> Profile
- Settings PATCH validates uniqueness (SLUG_TAKEN) and format (INVALID_SLUG)
- koja.meezi.ir/{slug} now redirects to /fa/cafe/{slug} (short URL support)
Bug fix:
- SupportTicketService: cafeId/status filters applied before Select() projection
to fix EF "could not be translated" crash on the support tickets page
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -50,8 +50,10 @@ public class SupportTicketService : ISupportTicketService
|
||||
string cafeId,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await QueryTickets()
|
||||
.Where(t => t.CafeId == cafeId)
|
||||
// NOTE: The Where MUST be applied on the EF entity set BEFORE the Select projection.
|
||||
// Applying Where() after Select() onto a DTO record causes an EF translation error
|
||||
// because EF can't translate "new SupportTicketDto(...).CafeId == x".
|
||||
return await QueryTickets(cafeId)
|
||||
.OrderByDescending(t => t.UpdatedAt)
|
||||
.ToListAsync(cancellationToken);
|
||||
}
|
||||
@@ -119,11 +121,10 @@ public class SupportTicketService : ISupportTicketService
|
||||
SupportTicketStatus? status,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var q = QueryTickets();
|
||||
if (status.HasValue)
|
||||
q = q.Where(t => t.Status == status.Value);
|
||||
|
||||
return await q.OrderByDescending(t => t.UpdatedAt).ToListAsync(cancellationToken);
|
||||
// status filter is applied on the entity before projection — safe for EF translation.
|
||||
return await QueryTickets(cafeId: null, status: status)
|
||||
.OrderByDescending(t => t.UpdatedAt)
|
||||
.ToListAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<SupportTicketDetailDto?> GetAdminAsync(
|
||||
@@ -185,22 +186,36 @@ public class SupportTicketService : ISupportTicketService
|
||||
return await GetAdminAsync(ticketId, cancellationToken);
|
||||
}
|
||||
|
||||
private IQueryable<SupportTicketDto> QueryTickets() =>
|
||||
_db.SupportTickets
|
||||
.AsNoTracking()
|
||||
.Select(t => new SupportTicketDto(
|
||||
t.Id,
|
||||
t.CafeId,
|
||||
t.Cafe != null ? t.Cafe.Name : "",
|
||||
t.Subject,
|
||||
t.Status,
|
||||
t.Priority,
|
||||
t.CreatedByEmployeeId,
|
||||
t.CreatedByEmployee != null ? t.CreatedByEmployee.Name : null,
|
||||
t.AssignedAdminId,
|
||||
t.CreatedAt,
|
||||
t.UpdatedAt,
|
||||
t.Messages.Count));
|
||||
/// <summary>
|
||||
/// Builds an EF-translatable query for support ticket list rows.
|
||||
/// Filters are applied on the entity BEFORE the Select projection to avoid EF translation errors.
|
||||
/// </summary>
|
||||
private IQueryable<SupportTicketDto> QueryTickets(
|
||||
string? cafeId = null,
|
||||
SupportTicketStatus? status = null)
|
||||
{
|
||||
var q = _db.SupportTickets.AsNoTracking().AsQueryable();
|
||||
|
||||
// Apply entity-level filters BEFORE Select so EF can translate them.
|
||||
if (cafeId is not null)
|
||||
q = q.Where(t => t.CafeId == cafeId);
|
||||
if (status.HasValue)
|
||||
q = q.Where(t => t.Status == status.Value);
|
||||
|
||||
return q.Select(t => new SupportTicketDto(
|
||||
t.Id,
|
||||
t.CafeId,
|
||||
t.Cafe != null ? t.Cafe.Name : "",
|
||||
t.Subject,
|
||||
t.Status,
|
||||
t.Priority,
|
||||
t.CreatedByEmployeeId,
|
||||
t.CreatedByEmployee != null ? t.CreatedByEmployee.Name : null,
|
||||
t.AssignedAdminId,
|
||||
t.CreatedAt,
|
||||
t.UpdatedAt,
|
||||
t.Messages.Count));
|
||||
}
|
||||
|
||||
private static SupportTicketDto MapTicket(SupportTicket t) =>
|
||||
new(
|
||||
|
||||
Reference in New Issue
Block a user