using Admin.NET.Plugin.AiDOP.Entity.S8; using Admin.NET.Plugin.AiDOP.Infrastructure.S8; namespace Admin.NET.Plugin.AiDOP.Service.S8; public class S8TaskFlowService : ITransient { private readonly SqlSugarRepository _rep; private readonly SqlSugarRepository _timelineRep; public S8TaskFlowService( SqlSugarRepository rep, SqlSugarRepository timelineRep) { _rep = rep; _timelineRep = timelineRep; } public async Task ClaimAsync(long id, long tenantId, long factoryId, long assigneeId, string? remark) { if (assigneeId <= 0) throw new S8BizException("认领需指定处理人 AssigneeId"); var e = await LoadAsync(id, tenantId, factoryId) ?? throw new S8BizException("异常不存在"); if (!S8StatusRules.IsAllowedTransition(e.Status, "ASSIGNED")) throw new S8BizException($"状态 {e.Status} 不可认领"); var fromStatus = e.Status; e.Status = "ASSIGNED"; e.AssigneeId = assigneeId; e.AssignedAt = DateTime.Now; e.UpdatedAt = DateTime.Now; await _rep.AsTenant().UseTranAsync(async () => { await _rep.UpdateAsync(e); await InsertTimelineAsync(e.Id, "CLAIM", "认领", fromStatus, "ASSIGNED", assigneeId, null, remark); }, ex => throw ex); return e; } public async Task TransferAsync(long id, long tenantId, long factoryId, long newAssigneeId, string? remark) { if (newAssigneeId <= 0) throw new S8BizException("转派目标无效"); var e = await LoadAsync(id, tenantId, factoryId) ?? throw new S8BizException("异常不存在"); if (S8StatusRules.IsTerminal(e.Status)) throw new S8BizException("已关闭不可转派"); e.AssigneeId = newAssigneeId; e.UpdatedAt = DateTime.Now; await _rep.AsTenant().UseTranAsync(async () => { await _rep.UpdateAsync(e); await InsertTimelineAsync(e.Id, "TRANSFER", "转派", e.Status, e.Status, newAssigneeId, null, remark); }, ex => throw ex); return e; } public async Task UpgradeAsync(long id, long tenantId, long factoryId, string? remark) { var e = await LoadAsync(id, tenantId, factoryId) ?? throw new S8BizException("异常不存在"); if (!S8StatusRules.IsAllowedTransition(e.Status, "ESCALATED")) throw new S8BizException($"状态 {e.Status} 不可升级"); var from = e.Status; e.Status = "ESCALATED"; e.UpdatedAt = DateTime.Now; await _rep.AsTenant().UseTranAsync(async () => { await _rep.UpdateAsync(e); await InsertTimelineAsync(e.Id, "UPGRADE", "升级", from, "ESCALATED", null, null, remark); }, ex => throw ex); return e; } public async Task RejectAsync(long id, long tenantId, long factoryId, string? remark) { var e = await LoadAsync(id, tenantId, factoryId) ?? throw new S8BizException("异常不存在"); if (!S8StatusRules.IsAllowedTransition(e.Status, "REJECTED")) throw new S8BizException($"状态 {e.Status} 不可驳回"); var from = e.Status; e.Status = "REJECTED"; e.UpdatedAt = DateTime.Now; await _rep.AsTenant().UseTranAsync(async () => { await _rep.UpdateAsync(e); await InsertTimelineAsync(e.Id, "REJECT", "驳回", from, "REJECTED", null, null, remark); }, ex => throw ex); return e; } public async Task CloseAsync(long id, long tenantId, long factoryId, string? remark) { var e = await LoadAsync(id, tenantId, factoryId) ?? throw new S8BizException("异常不存在"); if (!S8StatusRules.IsAllowedTransition(e.Status, "CLOSED")) throw new S8BizException($"状态 {e.Status} 不可关闭"); var from = e.Status; e.Status = "CLOSED"; e.ClosedAt = DateTime.Now; e.UpdatedAt = DateTime.Now; await _rep.AsTenant().UseTranAsync(async () => { await _rep.UpdateAsync(e); await InsertTimelineAsync(e.Id, "CLOSE", "关闭", from, "CLOSED", null, null, remark); }, ex => throw ex); return e; } public async Task CommentAsync(long id, string? remark) { var e = await _rep.GetFirstAsync(x => x.Id == id && !x.IsDeleted) ?? throw new S8BizException("异常不存在"); await InsertTimelineAsync(e.Id, "COMMENT", "补充说明", e.Status, e.Status, null, null, remark); } private Task LoadAsync(long id, long tenantId, long factoryId) => _rep.GetFirstAsync(x => x.Id == id && x.TenantId == tenantId && x.FactoryId == factoryId && !x.IsDeleted); private async Task InsertTimelineAsync(long exceptionId, string code, string label, string? from, string? to, long? operatorId, string? operatorName, string? remark) => await _timelineRep.InsertAsync(new AdoS8ExceptionTimeline { ExceptionId = exceptionId, ActionCode = code, ActionLabel = label, FromStatus = from, ToStatus = to, OperatorId = operatorId, OperatorName = operatorName, ActionRemark = remark, CreatedAt = DateTime.Now }); }