|
|
@@ -75,6 +75,8 @@ public class S8ManualReportService : ITransient
|
|
|
private readonly SqlSugarRepository<AdoS0LineMaster> _lineRep;
|
|
|
private readonly SqlSugarRepository<AdoS8ExceptionType> _typeRep;
|
|
|
private readonly SqlSugarRepository<AdoS0EmployeeMaster> _empRep;
|
|
|
+ // S8-AUTO-WATCH-DEPT-RESOLVE-1(P2):自动建单部门 resolver 需读取 watch_rule.params_json 里的默认部门字段。
|
|
|
+ private readonly SqlSugarRepository<AdoS8WatchRule> _ruleRep;
|
|
|
private readonly UserManager _userManager;
|
|
|
private readonly FlowEngineService _flowEngine;
|
|
|
private readonly ILogger<S8ManualReportService> _logger;
|
|
|
@@ -88,6 +90,7 @@ public class S8ManualReportService : ITransient
|
|
|
SqlSugarRepository<AdoS0LineMaster> lineRep,
|
|
|
SqlSugarRepository<AdoS8ExceptionType> typeRep,
|
|
|
SqlSugarRepository<AdoS0EmployeeMaster> empRep,
|
|
|
+ SqlSugarRepository<AdoS8WatchRule> ruleRep,
|
|
|
UserManager userManager,
|
|
|
FlowEngineService flowEngine,
|
|
|
ILogger<S8ManualReportService> logger)
|
|
|
@@ -100,16 +103,31 @@ public class S8ManualReportService : ITransient
|
|
|
_lineRep = lineRep;
|
|
|
_typeRep = typeRep;
|
|
|
_empRep = empRep;
|
|
|
+ _ruleRep = ruleRep;
|
|
|
_userManager = userManager;
|
|
|
_flowEngine = flowEngine;
|
|
|
_logger = logger;
|
|
|
}
|
|
|
|
|
|
- // S8-AUTO-WATCH-DEPT-ZERO-AUDIT-1(P0-B-4):自动建单将写入 dept=0 时打 warning,行为不变。
|
|
|
- // 触发:raw 部门字段为 null 或 <=0。两条自动建单路径(CreateFromWatchAsync / CreateFromHitAsync)
|
|
|
- // 当前都用 `?? 0` 兜底;本助手只观测、不阻断、不替换值。部门派生器属 P2,不在本批。
|
|
|
- private void WarnIfAutoWatchZeroDept(
|
|
|
+ // S8-AUTO-WATCH-DEPT-RESOLVE-1(P2):自动建单部门解析顺序 hit → watch_rule.params_json default → 未归属。
|
|
|
+ // 单字段独立解析(occurrence / responsible 各自走优先级)。任一字段最终为 null → 调用方按"throw 让 scheduler 跳过"处理。
|
|
|
+ // 不允许写 0 作为最终值;不硬编码 1=质量部 / 2=生产部;不猜测业务对象部门派生(待后续增强)。
|
|
|
+ // 协议常量:未归属部门 codename = D-UNASSIGNED;按 factory_ref_id 唯一存在;本批不创建该基线,缺失时 resolver 返回 null。
|
|
|
+ private const string UnassignedDepartmentCode = "D-UNASSIGNED";
|
|
|
+
|
|
|
+ private sealed class AutoWatchDeptResolution
|
|
|
+ {
|
|
|
+ public long? OccurrenceDeptId { get; set; }
|
|
|
+ public long? ResponsibleDeptId { get; set; }
|
|
|
+ public string OccurrenceSource { get; set; } = "failed";
|
|
|
+ public string ResponsibleSource { get; set; } = "failed";
|
|
|
+ }
|
|
|
+
|
|
|
+ private async Task<AutoWatchDeptResolution> ResolveAutoWatchDepartmentsAsync(
|
|
|
string path,
|
|
|
+ long factoryId,
|
|
|
+ long? hitOccurrenceDeptId,
|
|
|
+ long? hitResponsibleDeptId,
|
|
|
long? ruleId,
|
|
|
string? ruleCode,
|
|
|
string? moduleCode,
|
|
|
@@ -118,21 +136,111 @@ public class S8ManualReportService : ITransient
|
|
|
string? sourceObjectType,
|
|
|
string? sourceObjectId,
|
|
|
string? relatedObjectCode,
|
|
|
- string? dedupKey,
|
|
|
- long? rawOccurrenceDeptId,
|
|
|
- long? rawResponsibleDeptId,
|
|
|
- long finalOccurrenceDeptId,
|
|
|
- long finalResponsibleDeptId,
|
|
|
- long tenantId,
|
|
|
- long factoryId,
|
|
|
- string? exceptionCode)
|
|
|
+ string? dedupKey)
|
|
|
+ {
|
|
|
+ var result = new AutoWatchDeptResolution();
|
|
|
+
|
|
|
+ // 1) hit dept 优先
|
|
|
+ var occOk = await ValidateDeptForFactoryAsync(hitOccurrenceDeptId, factoryId);
|
|
|
+ var respOk = await ValidateDeptForFactoryAsync(hitResponsibleDeptId, factoryId);
|
|
|
+ if (occOk) { result.OccurrenceDeptId = hitOccurrenceDeptId; result.OccurrenceSource = "hit"; }
|
|
|
+ if (respOk) { result.ResponsibleDeptId = hitResponsibleDeptId; result.ResponsibleSource = "hit"; }
|
|
|
+
|
|
|
+ // 2) watch_rule.params_json 默认部门
|
|
|
+ if ((!occOk || !respOk) && ruleId.HasValue && ruleId.Value > 0)
|
|
|
+ {
|
|
|
+ var paramsJson = await _ruleRep.AsQueryable()
|
|
|
+ .Where(x => x.Id == ruleId.Value)
|
|
|
+ .Select(x => x.ParamsJson)
|
|
|
+ .FirstAsync();
|
|
|
+ var (paramsOcc, paramsResp) = ParseParamsDefaultDepts(paramsJson);
|
|
|
+ if (!occOk && paramsOcc.HasValue)
|
|
|
+ {
|
|
|
+ if (await ValidateDeptForFactoryAsync(paramsOcc, factoryId))
|
|
|
+ {
|
|
|
+ result.OccurrenceDeptId = paramsOcc;
|
|
|
+ result.OccurrenceSource = "watch_rule_params";
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ _logger.LogWarning(
|
|
|
+ "s8_auto_watch_default_dept_invalid path={Path} ruleId={RuleId} ruleCode={RuleCode} field=defaultOccurrenceDeptId value={Value} factoryId={FactoryId}",
|
|
|
+ path, ruleId, ruleCode, paramsOcc, factoryId);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!respOk && paramsResp.HasValue)
|
|
|
+ {
|
|
|
+ if (await ValidateDeptForFactoryAsync(paramsResp, factoryId))
|
|
|
+ {
|
|
|
+ result.ResponsibleDeptId = paramsResp;
|
|
|
+ result.ResponsibleSource = "watch_rule_params";
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ _logger.LogWarning(
|
|
|
+ "s8_auto_watch_default_dept_invalid path={Path} ruleId={RuleId} ruleCode={RuleCode} field=defaultResponsibleDeptId value={Value} factoryId={FactoryId}",
|
|
|
+ path, ruleId, ruleCode, paramsResp, factoryId);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3) 未归属部门 fallback
|
|
|
+ long? unassignedId = null;
|
|
|
+ if (result.OccurrenceDeptId == null || result.ResponsibleDeptId == null)
|
|
|
+ {
|
|
|
+ unassignedId = await _deptRep.AsQueryable().ClearFilter()
|
|
|
+ .Where(x => x.Department == UnassignedDepartmentCode && x.FactoryRefId == factoryId && x.IsActive)
|
|
|
+ .Select(x => (long?)x.Id)
|
|
|
+ .FirstAsync();
|
|
|
+ if (result.OccurrenceDeptId == null && unassignedId.HasValue)
|
|
|
+ {
|
|
|
+ result.OccurrenceDeptId = unassignedId;
|
|
|
+ result.OccurrenceSource = "unassigned";
|
|
|
+ _logger.LogWarning(
|
|
|
+ "s8_auto_watch_dept_unassigned_fallback path={Path} ruleId={RuleId} ruleCode={RuleCode} field=occurrence factoryId={FactoryId} unassignedDeptId={UnassignedId} sourceObjectType={SourceObjectType} sourceObjectId={SourceObjectId} relatedObjectCode={RelatedObjectCode} dedupKey={DedupKey}",
|
|
|
+ path, ruleId, ruleCode, factoryId, unassignedId, sourceObjectType, sourceObjectId, relatedObjectCode, dedupKey);
|
|
|
+ }
|
|
|
+ if (result.ResponsibleDeptId == null && unassignedId.HasValue)
|
|
|
+ {
|
|
|
+ result.ResponsibleDeptId = unassignedId;
|
|
|
+ result.ResponsibleSource = "unassigned";
|
|
|
+ _logger.LogWarning(
|
|
|
+ "s8_auto_watch_dept_unassigned_fallback path={Path} ruleId={RuleId} ruleCode={RuleCode} field=responsible factoryId={FactoryId} unassignedDeptId={UnassignedId} sourceObjectType={SourceObjectType} sourceObjectId={SourceObjectId} relatedObjectCode={RelatedObjectCode} dedupKey={DedupKey}",
|
|
|
+ path, ruleId, ruleCode, factoryId, unassignedId, sourceObjectType, sourceObjectId, relatedObjectCode, dedupKey);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ private async Task<bool> ValidateDeptForFactoryAsync(long? deptId, long factoryId)
|
|
|
+ {
|
|
|
+ if (!deptId.HasValue || deptId.Value <= 0 || factoryId <= 0) return false;
|
|
|
+ return await _deptRep.AsQueryable().ClearFilter()
|
|
|
+ .Where(x => x.Id == deptId.Value && x.FactoryRefId == factoryId && x.IsActive)
|
|
|
+ .AnyAsync();
|
|
|
+ }
|
|
|
+
|
|
|
+ private static (long? Occurrence, long? Responsible) ParseParamsDefaultDepts(string? paramsJson)
|
|
|
+ {
|
|
|
+ if (string.IsNullOrWhiteSpace(paramsJson)) return (null, null);
|
|
|
+ try
|
|
|
+ {
|
|
|
+ using var doc = System.Text.Json.JsonDocument.Parse(paramsJson);
|
|
|
+ long? occ = ReadJsonLong(doc.RootElement, "defaultOccurrenceDeptId");
|
|
|
+ long? resp = ReadJsonLong(doc.RootElement, "defaultResponsibleDeptId");
|
|
|
+ return (occ, resp);
|
|
|
+ }
|
|
|
+ catch (System.Text.Json.JsonException) { return (null, null); }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static long? ReadJsonLong(System.Text.Json.JsonElement root, string property)
|
|
|
{
|
|
|
- var occMissing = !rawOccurrenceDeptId.HasValue || rawOccurrenceDeptId.Value <= 0;
|
|
|
- var respMissing = !rawResponsibleDeptId.HasValue || rawResponsibleDeptId.Value <= 0;
|
|
|
- if (!occMissing && !respMissing) return;
|
|
|
- _logger.LogWarning(
|
|
|
- "s8_auto_watch_zero_dept_detected path={Path} ruleId={RuleId} ruleCode={RuleCode} moduleCode={ModuleCode} sceneCode={SceneCode} exceptionTypeCode={ExceptionTypeCode} sourceObjectType={SourceObjectType} sourceObjectId={SourceObjectId} relatedObjectCode={RelatedObjectCode} dedupKey={DedupKey} rawOccurrenceDeptId={RawOccDept} rawResponsibleDeptId={RawRespDept} finalOccurrenceDeptId={FinalOccDept} finalResponsibleDeptId={FinalRespDept} tenantId={TenantId} factoryId={FactoryId} exceptionCode={ExceptionCode}",
|
|
|
- path, ruleId, ruleCode, moduleCode, sceneCode, exceptionTypeCode, sourceObjectType, sourceObjectId, relatedObjectCode, dedupKey, rawOccurrenceDeptId, rawResponsibleDeptId, finalOccurrenceDeptId, finalResponsibleDeptId, tenantId, factoryId, exceptionCode);
|
|
|
+ if (root.ValueKind != System.Text.Json.JsonValueKind.Object) return null;
|
|
|
+ if (!root.TryGetProperty(property, out var el)) return null;
|
|
|
+ if (el.ValueKind == System.Text.Json.JsonValueKind.Number && el.TryGetInt64(out var v)) return v;
|
|
|
+ if (el.ValueKind == System.Text.Json.JsonValueKind.String && long.TryParse(el.GetString(), out var sv)) return sv;
|
|
|
+ return null;
|
|
|
}
|
|
|
|
|
|
// S8-REPORTER-IDSPACE-FIX-1(P0-B-1):把当前登录 SysUser.Id 反查 EmployeeMaster.RecID。
|
|
|
@@ -421,11 +529,37 @@ public class S8ManualReportService : ITransient
|
|
|
"auto_watch_module_code_unresolved sceneCode={SceneCode} exceptionTypeCode={TypeCode} ruleId={RuleId}",
|
|
|
S8SceneCode.S2, "EQUIP_FAULT", hit.SourceRuleId);
|
|
|
}
|
|
|
+ // S8-AUTO-WATCH-DEPT-RESOLVE-1(P2):部门解析顺序 hit → params → unassigned;resolver 失败 → throw。
|
|
|
+ const long fixedTenantId = 1;
|
|
|
+ const long fixedFactoryId = 1;
|
|
|
+ var deptResolution = await ResolveAutoWatchDepartmentsAsync(
|
|
|
+ path: nameof(CreateFromWatchAsync),
|
|
|
+ factoryId: fixedFactoryId,
|
|
|
+ hitOccurrenceDeptId: hit.OccurrenceDeptId,
|
|
|
+ hitResponsibleDeptId: hit.ResponsibleDeptId,
|
|
|
+ ruleId: hit.SourceRuleId,
|
|
|
+ ruleCode: hit.SourceRuleCode,
|
|
|
+ moduleCode: resolvedModule,
|
|
|
+ sceneCode: S8SceneCode.S2,
|
|
|
+ exceptionTypeCode: "EQUIP_FAULT",
|
|
|
+ sourceObjectType: null,
|
|
|
+ sourceObjectId: null,
|
|
|
+ relatedObjectCode: hit.RelatedObjectCode,
|
|
|
+ dedupKey: null);
|
|
|
+ if (!deptResolution.OccurrenceDeptId.HasValue || !deptResolution.ResponsibleDeptId.HasValue)
|
|
|
+ {
|
|
|
+ _logger.LogWarning(
|
|
|
+ "s8_auto_watch_dept_resolve_failed path={Path} ruleId={RuleId} ruleCode={RuleCode} factoryId={FactoryId} occSource={OccSource} respSource={RespSource} relatedObjectCode={RelatedObjectCode}",
|
|
|
+ nameof(CreateFromWatchAsync), hit.SourceRuleId, hit.SourceRuleCode, fixedFactoryId,
|
|
|
+ deptResolution.OccurrenceSource, deptResolution.ResponsibleSource, hit.RelatedObjectCode);
|
|
|
+ throw new S8BizException($"自动建单部门解析失败:缺少未归属部门基线(factory_ref_id={fixedFactoryId}, codename={UnassignedDepartmentCode})");
|
|
|
+ }
|
|
|
+
|
|
|
var entity = new AdoS8Exception
|
|
|
{
|
|
|
// 租户/工厂:与 S8WatchSchedulerService.RunOnceAsync 当前固定上下文一致。
|
|
|
- TenantId = 1,
|
|
|
- FactoryId = 1,
|
|
|
+ TenantId = fixedTenantId,
|
|
|
+ FactoryId = fixedFactoryId,
|
|
|
ExceptionCode = code,
|
|
|
Title = title,
|
|
|
Description = null,
|
|
|
@@ -436,10 +570,9 @@ public class S8ManualReportService : ITransient
|
|
|
Severity = S8SeverityCode.Normalize(hit.Severity),
|
|
|
PriorityScore = 0,
|
|
|
PriorityLevel = "P3",
|
|
|
- // 首版兜底口径:Hit 未提供部门时置 0 仅为保证“能建成标准异常单并进入主链”,
|
|
|
- // 不是最终业务部门语义;后续需由上游查询结果提供,或在专项任务中补口径。
|
|
|
- OccurrenceDeptId = hit.OccurrenceDeptId ?? 0,
|
|
|
- ResponsibleDeptId = hit.ResponsibleDeptId ?? 0,
|
|
|
+ // S8-AUTO-WATCH-DEPT-RESOLVE-1:经 resolver 严格校验后写入;不再使用 ?? 0 兜底。
|
|
|
+ OccurrenceDeptId = deptResolution.OccurrenceDeptId.Value,
|
|
|
+ ResponsibleDeptId = deptResolution.ResponsibleDeptId.Value,
|
|
|
ReporterId = null,
|
|
|
CreatedAt = DateTime.Now,
|
|
|
IsDeleted = false,
|
|
|
@@ -456,25 +589,10 @@ public class S8ManualReportService : ITransient
|
|
|
RelatedObjectCode = hit.RelatedObjectCode
|
|
|
};
|
|
|
|
|
|
- // S8-AUTO-WATCH-DEPT-ZERO-AUDIT-1(P0-B-4):raw dept 缺失时打 warning,行为不变。
|
|
|
- WarnIfAutoWatchZeroDept(
|
|
|
- path: nameof(CreateFromWatchAsync),
|
|
|
- ruleId: hit.SourceRuleId,
|
|
|
- ruleCode: null,
|
|
|
- moduleCode: resolvedModule,
|
|
|
- sceneCode: S8SceneCode.S2,
|
|
|
- exceptionTypeCode: "EQUIP_FAULT",
|
|
|
- sourceObjectType: null,
|
|
|
- sourceObjectId: null,
|
|
|
- relatedObjectCode: hit.RelatedObjectCode,
|
|
|
- dedupKey: null,
|
|
|
- rawOccurrenceDeptId: hit.OccurrenceDeptId,
|
|
|
- rawResponsibleDeptId: hit.ResponsibleDeptId,
|
|
|
- finalOccurrenceDeptId: entity.OccurrenceDeptId,
|
|
|
- finalResponsibleDeptId: entity.ResponsibleDeptId,
|
|
|
- tenantId: entity.TenantId,
|
|
|
- factoryId: entity.FactoryId,
|
|
|
- exceptionCode: entity.ExceptionCode);
|
|
|
+ _logger.LogInformation(
|
|
|
+ "s8_auto_watch_dept_resolved path={Path} ruleId={RuleId} ruleCode={RuleCode} factoryId={FactoryId} occDeptId={OccDeptId} occSource={OccSource} respDeptId={RespDeptId} respSource={RespSource}",
|
|
|
+ nameof(CreateFromWatchAsync), hit.SourceRuleId, hit.SourceRuleCode, fixedFactoryId,
|
|
|
+ entity.OccurrenceDeptId, deptResolution.OccurrenceSource, entity.ResponsibleDeptId, deptResolution.ResponsibleSource);
|
|
|
|
|
|
await _rep.AsTenant().UseTranAsync(async () =>
|
|
|
{
|
|
|
@@ -525,12 +643,38 @@ public class S8ManualReportService : ITransient
|
|
|
hit.SceneCode, hit.ModuleCode, hit.ExceptionTypeCode, hit.SourceRuleCode);
|
|
|
}
|
|
|
|
|
|
+ // S8-AUTO-WATCH-DEPT-RESOLVE-1(P2):部门解析顺序 hit → params → unassigned;resolver 失败 → throw。
|
|
|
+ const long fixedTenantId = 1;
|
|
|
+ const long fixedFactoryId = 1;
|
|
|
+ var deptResolution = await ResolveAutoWatchDepartmentsAsync(
|
|
|
+ path: nameof(CreateFromHitAsync),
|
|
|
+ factoryId: fixedFactoryId,
|
|
|
+ hitOccurrenceDeptId: hit.OccurrenceDeptId,
|
|
|
+ hitResponsibleDeptId: hit.ResponsibleDeptId,
|
|
|
+ ruleId: hit.SourceRuleId,
|
|
|
+ ruleCode: hit.SourceRuleCode,
|
|
|
+ moduleCode: resolvedModule,
|
|
|
+ sceneCode: effectiveScene,
|
|
|
+ exceptionTypeCode: hit.ExceptionTypeCode,
|
|
|
+ sourceObjectType: hit.SourceObjectType,
|
|
|
+ sourceObjectId: hit.SourceObjectId,
|
|
|
+ relatedObjectCode: hit.RelatedObjectCode,
|
|
|
+ dedupKey: hit.DedupKey);
|
|
|
+ if (!deptResolution.OccurrenceDeptId.HasValue || !deptResolution.ResponsibleDeptId.HasValue)
|
|
|
+ {
|
|
|
+ _logger.LogWarning(
|
|
|
+ "s8_auto_watch_dept_resolve_failed path={Path} ruleId={RuleId} ruleCode={RuleCode} factoryId={FactoryId} occSource={OccSource} respSource={RespSource} sourceObjectType={SourceObjectType} sourceObjectId={SourceObjectId} dedupKey={DedupKey}",
|
|
|
+ nameof(CreateFromHitAsync), hit.SourceRuleId, hit.SourceRuleCode, fixedFactoryId,
|
|
|
+ deptResolution.OccurrenceSource, deptResolution.ResponsibleSource, hit.SourceObjectType, hit.SourceObjectId, hit.DedupKey);
|
|
|
+ throw new S8BizException($"自动建单部门解析失败:缺少未归属部门基线(factory_ref_id={fixedFactoryId}, codename={UnassignedDepartmentCode})");
|
|
|
+ }
|
|
|
+
|
|
|
var code = $"EX-{DateTime.Now:yyyyMMdd}-{Guid.NewGuid().ToString("N")[..8].ToUpperInvariant()}";
|
|
|
var entity = new AdoS8Exception
|
|
|
{
|
|
|
// 与 CreateFromWatchAsync 当前固定上下文一致;R2 不变更租户/工厂上下文语义。
|
|
|
- TenantId = 1,
|
|
|
- FactoryId = 1,
|
|
|
+ TenantId = fixedTenantId,
|
|
|
+ FactoryId = fixedFactoryId,
|
|
|
ExceptionCode = code,
|
|
|
Title = string.IsNullOrWhiteSpace(hit.Title)
|
|
|
? $"[自动] {hit.SourceObjectType} {hit.SourceObjectId}"
|
|
|
@@ -542,8 +686,9 @@ public class S8ManualReportService : ITransient
|
|
|
Severity = S8SeverityCode.Normalize(hit.Severity),
|
|
|
PriorityScore = 0,
|
|
|
PriorityLevel = "P3",
|
|
|
- OccurrenceDeptId = hit.OccurrenceDeptId ?? 0,
|
|
|
- ResponsibleDeptId = hit.ResponsibleDeptId ?? 0,
|
|
|
+ // S8-AUTO-WATCH-DEPT-RESOLVE-1:经 resolver 严格校验后写入;不再使用 ?? 0 兜底。
|
|
|
+ OccurrenceDeptId = deptResolution.OccurrenceDeptId.Value,
|
|
|
+ ResponsibleDeptId = deptResolution.ResponsibleDeptId.Value,
|
|
|
ReporterId = null,
|
|
|
CreatedAt = DateTime.Now,
|
|
|
IsDeleted = false,
|
|
|
@@ -565,25 +710,10 @@ public class S8ManualReportService : ITransient
|
|
|
SourceObjectId = hit.SourceObjectId
|
|
|
};
|
|
|
|
|
|
- // S8-AUTO-WATCH-DEPT-ZERO-AUDIT-1(P0-B-4):raw dept 缺失时打 warning,行为不变。
|
|
|
- WarnIfAutoWatchZeroDept(
|
|
|
- path: nameof(CreateFromHitAsync),
|
|
|
- ruleId: hit.SourceRuleId,
|
|
|
- ruleCode: hit.SourceRuleCode,
|
|
|
- moduleCode: resolvedModule,
|
|
|
- sceneCode: effectiveScene,
|
|
|
- exceptionTypeCode: hit.ExceptionTypeCode,
|
|
|
- sourceObjectType: hit.SourceObjectType,
|
|
|
- sourceObjectId: hit.SourceObjectId,
|
|
|
- relatedObjectCode: hit.RelatedObjectCode,
|
|
|
- dedupKey: hit.DedupKey,
|
|
|
- rawOccurrenceDeptId: hit.OccurrenceDeptId,
|
|
|
- rawResponsibleDeptId: hit.ResponsibleDeptId,
|
|
|
- finalOccurrenceDeptId: entity.OccurrenceDeptId,
|
|
|
- finalResponsibleDeptId: entity.ResponsibleDeptId,
|
|
|
- tenantId: entity.TenantId,
|
|
|
- factoryId: entity.FactoryId,
|
|
|
- exceptionCode: entity.ExceptionCode);
|
|
|
+ _logger.LogInformation(
|
|
|
+ "s8_auto_watch_dept_resolved path={Path} ruleId={RuleId} ruleCode={RuleCode} factoryId={FactoryId} occDeptId={OccDeptId} occSource={OccSource} respDeptId={RespDeptId} respSource={RespSource} sourceObjectType={SourceObjectType} sourceObjectId={SourceObjectId} dedupKey={DedupKey}",
|
|
|
+ nameof(CreateFromHitAsync), hit.SourceRuleId, hit.SourceRuleCode, fixedFactoryId,
|
|
|
+ entity.OccurrenceDeptId, deptResolution.OccurrenceSource, entity.ResponsibleDeptId, deptResolution.ResponsibleSource, hit.SourceObjectType, hit.SourceObjectId, hit.DedupKey);
|
|
|
|
|
|
await _rep.AsTenant().UseTranAsync(async () =>
|
|
|
{
|