using FoodLabeling.Application.Services.DbModels; using SqlSugar; namespace FoodLabeling.Application.Helpers; /// /// Print Log「Label ID」:按门店 + 自然日对打印任务排序,格式 yyyyMMdd-n(非 fl_label.LabelCode)。 /// public static class ReportsPrintLogDailyLabelIdHelper { /// /// 为列表/导出行计算门店当日打印序号。 /// public static async Task> ResolveDailyLabelIdsAsync( ISqlSugarClient db, IReadOnlyList tasks) { var result = new Dictionary(StringComparer.Ordinal); if (tasks.Count == 0) { return result; } foreach (var task in tasks) { if (string.IsNullOrWhiteSpace(task.TaskId)) { continue; } result.TryAdd(task.TaskId.Trim(), "无"); } var buckets = tasks .Where(t => !string.IsNullOrWhiteSpace(t.TaskId) && !string.IsNullOrWhiteSpace(t.LocationId) && t.PrintedAt != default) .GroupBy(t => (LocationId: t.LocationId!.Trim(), Day: t.PrintedAt.Date)) .ToList(); foreach (var bucket in buckets) { var locId = bucket.Key.LocationId; var dayStart = bucket.Key.Day; var dayEnd = dayStart.AddDays(1); var dayTasks = await db.Queryable() .Where(t => t.LocationId == locId) .Where(t => SqlFunc.IsNull(t.PrintedAt, t.CreationTime) >= dayStart && SqlFunc.IsNull(t.PrintedAt, t.CreationTime) < dayEnd) .OrderBy(t => SqlFunc.IsNull(t.PrintedAt, t.CreationTime), OrderByType.Asc) .OrderBy(t => t.Id, OrderByType.Asc) .Select(t => new { t.Id, PrintedAt = SqlFunc.IsNull(t.PrintedAt, t.CreationTime) }) .ToListAsync(); for (var i = 0; i < dayTasks.Count; i++) { result[dayTasks[i].Id] = Format(dayStart, i + 1); } } return result; } /// /// 预览/即将打印:取门店在指定自然日的下一个打印序号(不落库)。 /// public static async Task ResolveNextDailyLabelIdAsync( ISqlSugarClient db, string locationId, DateTime referenceTime) { var locId = locationId?.Trim(); if (string.IsNullOrWhiteSpace(locId)) { return "无"; } var dayStart = referenceTime.Date; var dayEnd = dayStart.AddDays(1); var count = await db.Queryable() .Where(t => t.LocationId == locId) .Where(t => SqlFunc.IsNull(t.PrintedAt, t.CreationTime) >= dayStart && SqlFunc.IsNull(t.PrintedAt, t.CreationTime) < dayEnd) .CountAsync(); return Format(dayStart, count + 1); } public static string Format(DateTime printDay, int sequence) => $"{printDay:yyyyMMdd}-{sequence}"; /// /// 为门店当日后续打印任务预留连续序号(不含已存在任务之外的并发锁,与列表展示规则一致)。 /// public static async Task> ResolveNextDailyLabelIdsAsync( ISqlSugarClient db, string locationId, DateTime day, int count) { var result = new List(); if (count <= 0 || string.IsNullOrWhiteSpace(locationId)) { return result; } var locId = locationId.Trim(); var dayStart = day.Date; var dayEnd = dayStart.AddDays(1); var existingCount = await db.Queryable() .Where(t => t.LocationId == locId) .Where(t => SqlFunc.IsNull(t.PrintedAt, t.CreationTime) >= dayStart && SqlFunc.IsNull(t.PrintedAt, t.CreationTime) < dayEnd) .CountAsync(); for (var i = 1; i <= count; i++) { result.Add(Format(dayStart, existingCount + i)); } return result; } public readonly struct PrintTaskScopeKey { public PrintTaskScopeKey(string taskId, string? locationId, DateTime printedAt) { TaskId = taskId; LocationId = locationId; PrintedAt = printedAt; } public string TaskId { get; } public string? LocationId { get; } public DateTime PrintedAt { get; } } }