using System.Globalization;
using System.Text.Json;
using Admin.NET.Plugin.AiDOP.DataPlatform.Wms;
using Admin.NET.Plugin.AiDOP.Infrastructure;
using Admin.NET.Plugin.AiDOP.Order;
using Admin.NET.Plugin.AiDOP.WorkOrder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace Admin.NET.Plugin.AiDOP.Production;
///
/// 工单排产动作:生成排程、优先级调整并重检。
///
/// 【租户安全边界】租户一律经 从认证后 JWT 解析,
/// 无有效租户即拒绝,不读前端 tenantId/domain、无默认回退。
///
/// 原实现:类级 [AllowAnonymous] + AidopTenantHelper.Resolve(App.HttpContext) 宽松解析
/// (解析链含 query 参数 tenantId 与 DefaultTenantId 兜底),且 ResolveTenantId 还接受前端直传 domain
/// 数字直接充当租户 ID。叠加后果:未认证方可指定任意租户触发生产排程等写操作。
///
///
[ApiDescriptionSettings(Order = 264, Description = "工单排产动作")]
[Route("api/Production")]
[NonUnify]
public class ProductionSchedulingActionService : IDynamicApiController, ITransient
{
private readonly ISqlSugarClient _db;
private readonly UserManager _userManager;
private readonly ProductionScheduleGenerationService _scheduleGen;
private readonly WorkOrderRoutingSyncService _routingSync;
private readonly AidopActionRunLogWriter _runLog;
private readonly MdpRefreshDispatcher _dispatcher;
private readonly PickBillNbrSyncService _pickNbrSync;
private readonly ILogger _logger;
/// RUNNING 超过此时长视为僵死并自动关闭(防单飞永久堵死)。
private static readonly TimeSpan StaleRunningAge = TimeSpan.FromHours(3);
public ProductionSchedulingActionService(
ISqlSugarClient db,
UserManager userManager,
ProductionScheduleGenerationService scheduleGen,
WorkOrderRoutingSyncService routingSync,
AidopActionRunLogWriter runLog,
MdpRefreshDispatcher dispatcher,
PickBillNbrSyncService pickNbrSync,
ILogger logger)
{
_db = db;
_userManager = userManager;
_scheduleGen = scheduleGen;
_routingSync = routingSync;
_runLog = runLog;
_dispatcher = dispatcher;
_pickNbrSync = pickNbrSync;
_logger = logger;
}
public const string ActionScheduleGenerate = "S2_SCHEDULE_GENERATE";
///
/// 提交全量生产排程(异步)。立即返回 runId,后台执行;前端轮询 status。
///
[DisplayName("生成生产排程")]
[HttpPost("scheduling/generate")]
public async Task