Coreshop/CoreCms.Net.Task/SQReservationJob.cs
2025-09-26 20:39:27 +08:00

176 lines
9.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
/// <summary>
/// 预约定时清理
/// </summary>
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->3end_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->2start_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}");
}
}