using Admin.NET.Plugin.AiDOP.Infrastructure;
using Admin.NET.Plugin.AiDOP.Supply;
namespace Admin.NET.Plugin.AiDOP.WorkOrder;
///
/// 物料需求生成(MRP 入口,对接 S4 采购执行闭环)。
///
/// 【租户安全边界】需认证访问(已移除类级 [AllowAnonymous]);租户一律经
/// AidopTenantScope.ResolveOrThrow 从认证后 JWT 解析,无有效租户即拒绝,
/// 不读前端 tenantId/domain 数字、无默认回退(原实现:类级匿名 + ResolveTenantId(domain)
/// 信任前端直传的 domain 数字自选租户,否则回退宽松解析)。
///
[ApiDescriptionSettings(Order = 261, Description = "物料需求生成")]
[Route("api/WorkOrder")]
[NonUnify]
public class MaterialRequirementGenerationService : IDynamicApiController, ITransient
{
private readonly UserManager _userManager;
private readonly ProcurementPipelineService _pipeline;
private readonly AidopActionRunLogWriter _runLog;
public MaterialRequirementGenerationService(
UserManager userManager,
ProcurementPipelineService pipeline,
AidopActionRunLogWriter runLog)
{
_userManager = userManager;
_pipeline = pipeline;
_runLog = runLog;
}
/// 同步/生成物料需求并执行采购闭环。
[DisplayName("生成物料需求")]
[HttpPost("material-requirement/generate")]
public async Task Generate([FromQuery] string domain)
{
var tenantId = ResolveTenantId(domain);
var account = _userManager.Account ?? "system";
var logId = await _runLog.StartAsync("S4_MRP_GENERATE", tenantId, "tenant", tenantId, domain ?? tenantId.ToString());
try
{
var result = await _pipeline.ExecuteCoreAsync(tenantId, account, createFromShortage: true);
await _runLog.SuccessAsync(logId, result.Message, result);
return result;
}
catch (Exception ex)
{
await _runLog.FailedAsync(logId, ex.Message);
throw Oops.Oh(ex.Message);
}
}
private long ResolveTenantId(string? domain)
{
// 租户只信 JWT:不再从前端直传的 domain 数字解析(那是让调用方自选租户),
// domain 仅作为公司域业务参数用于日志归档。
return AidopTenantScope.ResolveOrThrow(_userManager);
}
}