Do Pagination missing sortBy and sortDirection parameters
This commit is contained in:
@@ -6,14 +6,15 @@ public class BatchService : IBatchService
|
||||
{
|
||||
private static readonly Dictionary<BatchStatus, HashSet<BatchStatus>> _allowedTransitions = new()
|
||||
{
|
||||
[BatchStatus.Uploaded] = new() { BatchStatus.InEntry },
|
||||
[BatchStatus.InEntry] = new() { BatchStatus.PendingVerification },
|
||||
[BatchStatus.Uploaded] = new() { BatchStatus.InEntry, BatchStatus.Cancelled },
|
||||
[BatchStatus.InEntry] = new() { BatchStatus.PendingVerification, BatchStatus.Cancelled },
|
||||
[BatchStatus.PendingVerification] = new() { BatchStatus.Verified, BatchStatus.Rejected, BatchStatus.AwaitingClinicalApproval },
|
||||
[BatchStatus.Rejected] = new() { BatchStatus.InEntry },
|
||||
[BatchStatus.Rejected] = new() { BatchStatus.InEntry, BatchStatus.Cancelled },
|
||||
[BatchStatus.Verified] = new() { BatchStatus.Approved },
|
||||
[BatchStatus.AwaitingClinicalApproval] = new() { BatchStatus.Approved, BatchStatus.Rejected },
|
||||
[BatchStatus.Approved] = new() { BatchStatus.Promoted },
|
||||
[BatchStatus.Promoted] = new(),
|
||||
[BatchStatus.Cancelled] = new(),
|
||||
};
|
||||
|
||||
private readonly AppDbContext _db;
|
||||
@@ -179,9 +180,14 @@ public class BatchService : IBatchService
|
||||
return batch;
|
||||
}
|
||||
|
||||
private static readonly HashSet<string> _allowedSortFields = new(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
"createdAt", "updatedAt", "status", "batchType", "track"
|
||||
};
|
||||
|
||||
public async Task<PagedResult<DigitizationBatch>> ListAsync(
|
||||
BatchStatus? status, BatchType? batchType, Guid? assignedTo, BatchTrack? track,
|
||||
int page, int pageSize)
|
||||
int page, int pageSize, string sortBy = "createdAt", string sortDirection = "desc")
|
||||
{
|
||||
var query = _db.DigitizationBatches.AsQueryable();
|
||||
|
||||
@@ -194,9 +200,14 @@ public class BatchService : IBatchService
|
||||
if (track.HasValue)
|
||||
query = query.Where(b => b.Track == track.Value);
|
||||
|
||||
if (!_allowedSortFields.Contains(sortBy))
|
||||
throw new ValidationException(
|
||||
$"Invalid sortBy field '{sortBy}'. Allowed: {string.Join(", ", _allowedSortFields)}.",
|
||||
"INVALID_SORT_FIELD");
|
||||
|
||||
var total = await query.CountAsync();
|
||||
var items = await query
|
||||
.OrderByDescending(b => b.CreatedAt)
|
||||
var ordered = ApplySort(query, sortBy, sortDirection);
|
||||
var items = await ordered
|
||||
.Skip((page - 1) * pageSize)
|
||||
.Take(pageSize)
|
||||
.ToListAsync();
|
||||
@@ -204,6 +215,22 @@ public class BatchService : IBatchService
|
||||
return new PagedResult<DigitizationBatch>(items, page, pageSize, total);
|
||||
}
|
||||
|
||||
private static IOrderedQueryable<DigitizationBatch> ApplySort(
|
||||
IQueryable<DigitizationBatch> query, string sortBy, string sortDirection)
|
||||
{
|
||||
var desc = sortDirection.Equals("desc", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
return sortBy.ToLowerInvariant() switch
|
||||
{
|
||||
"createdat" => desc ? query.OrderByDescending(b => b.CreatedAt) : query.OrderBy(b => b.CreatedAt),
|
||||
"updatedat" => desc ? query.OrderByDescending(b => b.UpdatedAt) : query.OrderBy(b => b.UpdatedAt),
|
||||
"status" => desc ? query.OrderByDescending(b => b.Status) : query.OrderBy(b => b.Status),
|
||||
"batchtype" => desc ? query.OrderByDescending(b => b.BatchType) : query.OrderBy(b => b.BatchType),
|
||||
"track" => desc ? query.OrderByDescending(b => b.Track) : query.OrderBy(b => b.Track),
|
||||
_ => query.OrderByDescending(b => b.CreatedAt)
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<DigitizationBatch> AssignAsync(Guid batchId, Guid entryClerkUserId, Guid actorUserId)
|
||||
{
|
||||
var batch = await _db.DigitizationBatches.FindAsync(batchId);
|
||||
@@ -244,6 +271,46 @@ public class BatchService : IBatchService
|
||||
return batch;
|
||||
}
|
||||
|
||||
public async Task<DigitizationBatch> CancelAsync(Guid batchId, string reason, Guid actorUserId)
|
||||
{
|
||||
var batch = await _db.DigitizationBatches.FindAsync(batchId);
|
||||
if (batch is null)
|
||||
throw new NotFoundException("Batch not found.", "BATCH_NOT_FOUND");
|
||||
|
||||
if (!_allowedTransitions.TryGetValue(batch.Status, out var allowed)
|
||||
|| !allowed.Contains(BatchStatus.Cancelled))
|
||||
throw new ConflictException(
|
||||
$"Batch in '{batch.Status.ToDbString()}' status cannot be cancelled.",
|
||||
"ILLEGAL_STATUS_TRANSITION");
|
||||
|
||||
var previousStatus = batch.Status.ToDbString();
|
||||
batch.Status = BatchStatus.Cancelled;
|
||||
batch.UpdatedAt = DateTimeOffset.UtcNow;
|
||||
|
||||
_db.DigitizationEvents.Add(new DigitizationEvent
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
BatchId = batchId,
|
||||
EventType = DigitizationEventType.Cancelled,
|
||||
ActorUserId = actorUserId,
|
||||
OccurredAt = DateTimeOffset.UtcNow,
|
||||
MetadataJson = JsonSerializer.Serialize(new { previousStatus, reason })
|
||||
});
|
||||
|
||||
// Release Redis assignment lock if one exists
|
||||
var cache = _redis.GetDatabase();
|
||||
var lockKey = $"batch:assign:{batchId}";
|
||||
await cache.KeyDeleteAsync(lockKey);
|
||||
|
||||
await _db.SaveChangesAsync();
|
||||
|
||||
_logger.LogInformation(
|
||||
"Batch {BatchId} cancelled by {ActorUserId} from status {PreviousStatus}. Reason: {Reason}",
|
||||
batchId, actorUserId, previousStatus, reason);
|
||||
|
||||
return batch;
|
||||
}
|
||||
|
||||
public BatchStatus[] GetAllowedTransitions(BatchStatus current) =>
|
||||
_allowedTransitions.TryGetValue(current, out var targets)
|
||||
? targets.ToArray()
|
||||
|
||||
Reference in New Issue
Block a user