using Dapper; using Npgsql; namespace Modules.WMS.Picking.Shared; public static class PickingTaskQueries { public static async Task GetAsync( NpgsqlConnection connection, NpgsqlTransaction? transaction, Guid taskId, CancellationToken ct) { const string taskSql = """ select id as TaskId, task_no as TaskNo, status as Status, version as Version from wms.picking_tasks where id = @TaskId; """; var task = await connection.QuerySingleOrDefaultAsync( new CommandDefinition(taskSql, new { TaskId = taskId }, transaction, cancellationToken: ct)); if (task is null) return null; const string linesSql = """ select l.id as LineId, l.line_no as LineNo, l.location_code as LocationCode, l.item_id as ItemId, i.code as ItemCode, i.name as ItemName, l.item_option as ItemOption, l.barcode as Barcode, l.required_qty as RequiredQty, l.picked_qty as PickedQty, greatest(l.required_qty - l.picked_qty, 0) as RemainingQty, l.status as Status, l.location_confirmed as LocationConfirmed from wms.picking_lines l join catalog.items i on i.id = l.item_id where l.task_id = @TaskId order by l.line_no; """; var lines = (await connection.QueryAsync( new CommandDefinition(linesSql, new { TaskId = taskId }, transaction, cancellationToken: ct))).AsList(); var current = lines.FirstOrDefault(x => x.Status != "COMPLETED"); var completedLines = lines.Count(x => x.Status == "COMPLETED"); var totalQty = lines.Sum(x => x.RequiredQty); var completedQty = lines.Sum(x => x.PickedQty); var stage = task.Status switch { "READY" => "ready", "COMPLETED" => "completed", "BLOCKED" => "blocked", _ when current is null => "completed", _ when current.LocationConfirmed => "await-item", _ => "await-location" }; return new PickingTaskDto( task.TaskId, task.TaskNo, stage, task.Status, completedLines, lines.Count, completedQty, totalQty, task.Version, current is null ? null : new PickingLineDto( current.LineId, current.LineNo, current.LocationCode, current.ItemId, current.ItemCode, current.ItemName, current.ItemOption, current.Barcode, current.RequiredQty, current.PickedQty, current.RemainingQty)); } private sealed record TaskRow(Guid TaskId, string TaskNo, string Status, long Version); private sealed record LineRow( Guid LineId, int LineNo, string LocationCode, Guid ItemId, string ItemCode, string ItemName, string? ItemOption, string Barcode, decimal RequiredQty, decimal PickedQty, decimal RemainingQty, string Status, bool LocationConfirmed = false); }