using CoreCms.Net.Caching.AutoMate.RedisCache; using CoreCms.Net.Configuration; using CoreCms.Net.IServices; using CoreCms.Net.Model.Entities; using DotLiquid.Tags; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using SqlSugar; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using static SKIT.FlurlHttpClient.Wechat.Api.Models.CgibinUserInfoBatchGetRequest.Types; namespace CoreCms.Net.Task; /// /// 预约定时清理 /// public class SQReservationJob { private readonly ISQReservationsServices _reservationsServices; private readonly ISQReservationParticipantsServices _participantsServices; private readonly IRedisOperationRepository _redisOperationRepository; public SQReservationJob(ISQReservationsServices reservationsServices, ISQReservationParticipantsServices participantsServices, IRedisOperationRepository redisOperationRepository) { _reservationsServices = reservationsServices; _participantsServices = participantsServices; _redisOperationRepository = redisOperationRepository; } public async System.Threading.Tasks.Task Execute() { Console.WriteLine($"[SQReservationJob] 执行开始 @ {DateTime.Now:yyyy-MM-dd HH:mm:ss}"); var now = DateTime.Now; Console.WriteLine("[SQReservationJob] 步骤1:将已到结束时间的预约置为已结束(3)"); // 1) 将已到结束时间的预约置为已结束(3) var endedList = await _reservationsServices.QueryListByClauseAsync( r => r.status == 2 && r.end_time <= now, r => r.id, OrderByType.Asc); Console.WriteLine($"[SQReservationJob] 步骤1:查询到待结束记录数量 = {endedList?.Count ?? 0}"); if (endedList != null && endedList.Count > 0) { var changedCount = 0; foreach (var item in endedList) { Console.WriteLine($"[SQReservationJob] 步骤1:预约ID={item.id} 从状态2->3,end_time={item.end_time:yyyy-MM-dd HH:mm:ss}"); item.status = 3; item.updated_at = now; changedCount++; } Console.WriteLine($"[SQReservationJob] 步骤1:批量更新记录数 = {changedCount}"); await _reservationsServices.UpdateAsync(endedList); } //Console.WriteLine("[SQReservationJob] 步骤2:将开始时间已到且未结束的预约置为进行中(2)"); //// 2) 将开始时间已到且未结束的预约置为进行中(2) //var startedList = await _reservationsServices.QueryListByClauseAsync( // r => r.status == 1 && r.start_time <= now && r.end_time > now, // r => r.id, OrderByType.Asc); //Console.WriteLine($"[SQReservationJob] 步骤2:查询到待置为进行中记录数量 = {startedList?.Count ?? 0}"); //if (startedList != null && startedList.Count > 0) //{ // var changedCount = 0; // foreach (var item in startedList) // { // Console.WriteLine($"[SQReservationJob] 步骤2:预约ID={item.id} 从状态1->2,start_time={item.start_time:yyyy-MM-dd HH:mm:ss} end_time={item.end_time:yyyy-MM-dd HH:mm:ss}"); // item.status = 2; // item.updated_at = now; // changedCount++; // } // Console.WriteLine($"[SQReservationJob] 步骤2:批量更新记录数 = {changedCount}"); // await _reservationsServices.UpdateAsync(startedList); //} // 2.5) 到达开始时间但人数未满的预约置为取消(4) Console.WriteLine("[SQReservationJob] 步骤2.5:到达开始时间但人数未满的预约置为取消(4)"); var toCancelList = await _reservationsServices.QueryListByClauseAsync( r => r.status == 0 && r.start_time <= now && r.end_time > now, r => r.id, OrderByType.Asc); Console.WriteLine($"[SQReservationJob] 步骤2.5:查询到候选取消记录数量 = {toCancelList?.Count ?? 0}"); if (toCancelList != null && toCancelList.Count > 0) { var examineCount = 0; foreach (var item in toCancelList) { var count = await _participantsServices.GetCountAsync(p => p.reservation_id == item.id && p.status == 0); Console.WriteLine($"[SQReservationJob] 步骤2.5:预约ID={item.id} 参与人数={count}/{item.player_count},start_time={item.start_time:yyyy-MM-dd HH:mm:ss}"); if (count < item.player_count) { Console.WriteLine($"[SQReservationJob] 步骤2.5:预约ID={item.id} 人数未满,置为取消(4)"); item.status = 4; item.updated_at = now; } examineCount++; } var toCancelChanged = toCancelList.Where(x => x.status == 4).ToList(); Console.WriteLine($"[SQReservationJob] 步骤2.5:需要更新为取消的记录数 = {toCancelChanged.Count}"); if (toCancelChanged.Count > 0) { await _reservationsServices.UpdateAsync(toCancelChanged); Console.WriteLine($"[SQReservationJob] 步骤2.5:已更新为取消的记录数 = {toCancelChanged.Count}"); foreach (var item in toCancelChanged) { Console.WriteLine($"[SQReservationJob] 步骤2.5:准备通知预约ID={item.id} 的参与用户"); var userList = await _participantsServices.QueryListByClauseAsync(p => p.reservation_id == item.id && p.status == 0); Console.WriteLine($"[SQReservationJob] 步骤2.5:预约ID={item.id} 需通知用户数量 = {userList.Count}"); await _reservationsServices.NotifyReservationFailedAsync(item, userList); Console.WriteLine($"[SQReservationJob] 步骤2.5:预约ID={item.id} 组局失败通知入队完成"); // 解散(取消)的预约,标记需要退款押金的参与者为“待退款(3)” // 条件:未退出(status=0) 且 押金已支付(is_refund=2) 且 有有效支付单号 await _participantsServices.UpdateAsync( it => new SQReservationParticipants { is_refund = 3 }, it => it.reservation_id == item.id && it.status == 0 && it.is_refund == 2 && it.paymentId != null && it.paymentId != ""); Console.WriteLine($"[SQReservationJob] 步骤2.5:预约ID={item.id} 已标记需要退款的参与者为待退款(3)"); } } } // 3) 开始前30分钟内,人数已凑齐则置为锁定(1) Console.WriteLine("[SQReservationJob] 步骤3:开始前30分钟内,人数已凑齐则置为锁定(1)"); var threshold = now.AddMinutes(30); var toLockList = await _reservationsServices.QueryListByClauseAsync( r => r.status == 0 && r.start_time > now && r.start_time <= threshold, r => r.id, OrderByType.Asc); Console.WriteLine($"[SQReservationJob] 步骤3:查询到候选锁定记录数量 = {toLockList?.Count ?? 0},阈值时间={threshold:yyyy-MM-dd HH:mm:ss}"); if (toLockList != null && toLockList.Count > 0) { foreach (var item in toLockList) { // 当前有效参与人数(未退出) var count = await _participantsServices.GetCountAsync(p => p.reservation_id == item.id && p.status == 0); Console.WriteLine($"[SQReservationJob] 步骤3:预约ID={item.id} 参与人数={count}/{item.player_count},start_time={item.start_time:yyyy-MM-dd HH:mm:ss}"); if (count >= item.player_count) { Console.WriteLine($"[SQReservationJob] 步骤3:预约ID={item.id} 人数已满,置为锁定(1)"); item.status = 1; item.updated_at = now; } } // 仅更新被修改的项 var changed = toLockList.Where(x => x.status == 1).ToList(); Console.WriteLine($"[SQReservationJob] 步骤3:需要更新为锁定的记录数 = {changed.Count}"); if (changed.Count > 0) { await _reservationsServices.UpdateAsync(changed); Console.WriteLine($"[SQReservationJob] 步骤3:已更新为锁定的记录数 = {changed.Count}"); foreach (var item in changed) { Console.WriteLine($"[SQReservationJob] 步骤3:准备通知预约ID={item.id} 的参与用户"); var userList = await _participantsServices.QueryListByClauseAsync(p => p.reservation_id == item.id && p.status == 0); Console.WriteLine($"[SQReservationJob] 步骤3:预约ID={item.id} 需通知用户数量 = {userList.Count}"); await _reservationsServices.NotifyReservationSuccessAsync(item, userList); Console.WriteLine($"[SQReservationJob] 步骤3:预约ID={item.id} 组局成功通知入队完成"); } } } Console.WriteLine($"[SQReservationJob] 执行结束 @ {DateTime.Now:yyyy-MM-dd HH:mm:ss}"); } }