|
|
@@ -109,6 +109,26 @@ public class S8ManualReportService : ITransient
|
|
|
_logger = logger;
|
|
|
}
|
|
|
|
|
|
+ // S8-SLA-TIMEOUT-RUNTIME-1(P3):按 exception_type.sla_minutes 计算 sla_deadline。
|
|
|
+ // typeCode 空 / type 缺失 / sla_minutes <= 0 → 返回 null(不阻断建单,仅 LogWarning)。
|
|
|
+ // 不写 timeout_flag;timeout_flag 已降级为 legacy 字段,当前超时由读端基于 sla_deadline + status 在线计算。
|
|
|
+ private async Task<DateTime?> ResolveSlaDeadlineAsync(string? exceptionTypeCode, DateTime createdAt)
|
|
|
+ {
|
|
|
+ if (string.IsNullOrWhiteSpace(exceptionTypeCode)) return null;
|
|
|
+ var slaMinutes = await _typeRep.AsQueryable().ClearFilter()
|
|
|
+ .Where(t => t.TypeCode == exceptionTypeCode)
|
|
|
+ .OrderByDescending(t => t.FactoryId)
|
|
|
+ .Select(t => (int?)t.SlaMinutes)
|
|
|
+ .FirstAsync();
|
|
|
+ if (slaMinutes == null)
|
|
|
+ {
|
|
|
+ _logger.LogWarning("s8_sla_type_not_found exceptionTypeCode={TypeCode}", exceptionTypeCode);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ if (slaMinutes.Value <= 0) return null;
|
|
|
+ return createdAt.AddMinutes(slaMinutes.Value);
|
|
|
+ }
|
|
|
+
|
|
|
// S8-AUTO-WATCH-DEPT-RESOLVE-1(P2):自动建单部门解析顺序 hit → watch_rule.params_json default → 未归属。
|
|
|
// 单字段独立解析(occurrence / responsible 各自走优先级)。任一字段最终为 null → 调用方按"throw 让 scheduler 跳过"处理。
|
|
|
// 不允许写 0 作为最终值;不硬编码 1=质量部 / 2=生产部;不猜测业务对象部门派生(待后续增强)。
|
|
|
@@ -445,7 +465,10 @@ public class S8ManualReportService : ITransient
|
|
|
dto.SceneCode, inferredType, dto.Title);
|
|
|
}
|
|
|
|
|
|
- var code = $"EX-{DateTime.Now:yyyyMMdd}-{Guid.NewGuid().ToString("N")[..8].ToUpperInvariant()}";
|
|
|
+ // S8-SLA-TIMEOUT-RUNTIME-1(P3):CreatedAt 与 SlaDeadline 共用同一 now,避免漂移。
|
|
|
+ var now = DateTime.Now;
|
|
|
+ var slaDeadline = await ResolveSlaDeadlineAsync(inferredType, now);
|
|
|
+ var code = $"EX-{now:yyyyMMdd}-{Guid.NewGuid().ToString("N")[..8].ToUpperInvariant()}";
|
|
|
var entity = new AdoS8Exception
|
|
|
{
|
|
|
TenantId = dto.TenantId,
|
|
|
@@ -468,7 +491,9 @@ public class S8ManualReportService : ITransient
|
|
|
// S8-PROCESS-NODE-MODULE-CODE-ALIGNMENT-EXEC-1:当前阶段 process_node_code 留空,
|
|
|
// module_code 承担 S1-S7 主流程归属;process_node_code 留给未来更细流程节点。
|
|
|
ProcessNodeCode = null,
|
|
|
- CreatedAt = DateTime.Now,
|
|
|
+ CreatedAt = now,
|
|
|
+ // S8-SLA-TIMEOUT-RUNTIME-1:sla_deadline 由 exception_type.sla_minutes 决定;缺配置 → null。
|
|
|
+ SlaDeadline = slaDeadline,
|
|
|
IsDeleted = false
|
|
|
};
|
|
|
|
|
|
@@ -514,7 +539,9 @@ public class S8ManualReportService : ITransient
|
|
|
if (hit.SourceRuleId <= 0 || string.IsNullOrWhiteSpace(hit.RelatedObjectCode))
|
|
|
throw new S8BizException("自动建单缺失追溯键");
|
|
|
|
|
|
- var code = $"EX-{DateTime.Now:yyyyMMdd}-{Guid.NewGuid().ToString("N")[..8].ToUpperInvariant()}";
|
|
|
+ // S8-SLA-TIMEOUT-RUNTIME-1(P3):CreatedAt 与 SlaDeadline 共用同一 now。
|
|
|
+ var now = DateTime.Now;
|
|
|
+ var code = $"EX-{now:yyyyMMdd}-{Guid.NewGuid().ToString("N")[..8].ToUpperInvariant()}";
|
|
|
var title = $"[自动] 设备 {hit.RelatedObjectCode} {hit.TriggerCondition} {hit.ThresholdValue}(当前 {hit.CurrentValue})";
|
|
|
// S8-EXCEPTION-CREATION-MODULE-CODE-FIX-1:固定 SceneCode=S2 + ExceptionTypeCode=EQUIP_FAULT,
|
|
|
// 派生链路通过 ResolveModuleCodeAsync 严格按 S1-S7 走(结果稳定为 S2,但消除 FromScene 的 legacy 兼容路径)。
|
|
|
@@ -574,7 +601,9 @@ public class S8ManualReportService : ITransient
|
|
|
OccurrenceDeptId = deptResolution.OccurrenceDeptId.Value,
|
|
|
ResponsibleDeptId = deptResolution.ResponsibleDeptId.Value,
|
|
|
ReporterId = null,
|
|
|
- CreatedAt = DateTime.Now,
|
|
|
+ CreatedAt = now,
|
|
|
+ // S8-SLA-TIMEOUT-RUNTIME-1:sla_deadline 由 exception_type.sla_minutes 决定(EQUIP_FAULT)。
|
|
|
+ SlaDeadline = await ResolveSlaDeadlineAsync("EQUIP_FAULT", now),
|
|
|
IsDeleted = false,
|
|
|
// G-01 首版唯一异常类型映射(baseline 已迁后 EQUIP_FAULT 属 S2 制造协同场景)。
|
|
|
ExceptionTypeCode = "EQUIP_FAULT",
|
|
|
@@ -669,7 +698,10 @@ public class S8ManualReportService : ITransient
|
|
|
throw new S8BizException($"自动建单部门解析失败:缺少未归属部门基线(factory_ref_id={fixedFactoryId}, codename={UnassignedDepartmentCode})");
|
|
|
}
|
|
|
|
|
|
- var code = $"EX-{DateTime.Now:yyyyMMdd}-{Guid.NewGuid().ToString("N")[..8].ToUpperInvariant()}";
|
|
|
+ // S8-SLA-TIMEOUT-RUNTIME-1(P3):CreatedAt 与 SlaDeadline 共用同一 now。
|
|
|
+ var now = DateTime.Now;
|
|
|
+ var code = $"EX-{now:yyyyMMdd}-{Guid.NewGuid().ToString("N")[..8].ToUpperInvariant()}";
|
|
|
+ var slaDeadline = await ResolveSlaDeadlineAsync(hit.ExceptionTypeCode, now);
|
|
|
var entity = new AdoS8Exception
|
|
|
{
|
|
|
// 与 CreateFromWatchAsync 当前固定上下文一致;R2 不变更租户/工厂上下文语义。
|
|
|
@@ -690,7 +722,9 @@ public class S8ManualReportService : ITransient
|
|
|
OccurrenceDeptId = deptResolution.OccurrenceDeptId.Value,
|
|
|
ResponsibleDeptId = deptResolution.ResponsibleDeptId.Value,
|
|
|
ReporterId = null,
|
|
|
- CreatedAt = DateTime.Now,
|
|
|
+ CreatedAt = now,
|
|
|
+ // S8-SLA-TIMEOUT-RUNTIME-1:sla_deadline 来自 hit.ExceptionTypeCode 对应 sla_minutes。
|
|
|
+ SlaDeadline = slaDeadline,
|
|
|
IsDeleted = false,
|
|
|
ExceptionTypeCode = hit.ExceptionTypeCode,
|
|
|
ModuleCode = resolvedModule,
|