using DS.Module.Core; using DS.WMS.Core.Fee.Entity; using DS.WMS.Core.Flow.Dtos; using DS.WMS.Core.Flow.Entity; using DS.WMS.Core.Op.Entity; using DS.WMS.Core.TaskInteraction.Dtos; using DS.WMS.Core.TaskInteraction.Entity; using DS.WMS.Core.TaskInteraction.Interface; using Masuit.Tools.Systems; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using SqlSugar; namespace DS.WMS.Core.TaskInteraction.Method { /// /// 费用整票审核任务 /// public class FeeBillTaskService : TaskService, IFeeBillTaskService { /// /// 当前用户ID /// public readonly long UserId; readonly ILogger logger; /// /// 初始化 /// /// public FeeBillTaskService(IServiceProvider provider) : base(provider) { logger = provider.GetRequiredService>(); UserId = long.Parse(User.UserId); } /// /// 批量创建 /// /// /// /// public override Task CreateMultipleTaskAsync(TaskCreationRequest request, bool useTransaction = true) { return Task.FromResult(DataResult.Failed("不支持批量提交整票审核任务")); } /// /// 整票审核回调更新 /// /// /// public override async Task UpdateBusinessAsync(FlowCallback callback) { var auditType = callback.AuditType; if (auditType != TaskBaseTypeEnum.BILL_RECV_AUDIT && auditType != TaskBaseTypeEnum.BILL_PAY_AUDIT) return; var biz = await TenantDb.Queryable().Where(x => x.BusinessId == callback.BusinessId && x.BusinessType == callback.BusinessType) .InnerJoin((x, s) => x.BusinessId == s.Id) .Select((x, s) => new BusinessFeeStatus { CustomerNo = s.CustomerNo, Id = x.Id, BusinessId = x.BusinessId, BusinessType = x.BusinessType, BillAuditStatus = x.BillAuditStatus, BillFeeStatusTime = x.BillFeeStatusTime, ProfitMargin = SqlFunc.Subqueryable().Where(f => f.BusinessId == x.BusinessId && f.BusinessType == x.BusinessType && f.FeeType == FeeType.Receivable).Sum(f => f.Amount) - SqlFunc.Subqueryable().Where(f => f.BusinessId == x.BusinessId && f.BusinessType == x.BusinessType && f.FeeType == FeeType.Payable).Sum(f => f.Amount) }).FirstAsync(); if (biz == null) return; DataResult result; DateTime dtNow = DateTime.Now; await TenantDb.Ado.BeginTranAsync(); try { await UpdateTaskStatus(callback, biz); FeeStatus feeStatus = default; if (auditType == TaskBaseTypeEnum.BILL_RECV_AUDIT) { if (callback.FlowStatus == FlowStatusEnum.Approve) { feeStatus = FeeStatus.AuditPassed; biz.BillAuditStatus = BillAuditStatus.PaySubmitted; //生成应付确认任务 result = await CreateTaskAsync(new TaskCreationRequest { BusinessId = callback.BusinessId, BusinessType = callback.BusinessType.GetValueOrDefault(), TaskTypeName = TaskBaseTypeEnum.BILL_PAY_AUDIT.ToString(), TaskTitle = $"【{TaskBaseTypeEnum.BILL_PAY_AUDIT.GetDescription()}】【{callback.BusinessType.GetDescription()}】{biz.CustomerNo}" }, false); if (!result.Succeeded) logger.LogError($"生成【{TaskBaseTypeEnum.BILL_PAY_AUDIT.GetDescription()}】任务失败:" + result.Message); } else if (callback.FlowStatus == FlowStatusEnum.Reject) { feeStatus = FeeStatus.RejectSubmission; biz.BillAuditStatus = BillAuditStatus.RecvRejected; } //更新应收费用状态 await TenantDb.Updateable() .SetColumns(x => x.FeeStatus == feeStatus) .SetColumns(x => x.AuditBy == UserId) .SetColumns(x => x.AuditOperator == User.UserName) .SetColumns(x => x.AuditDate == dtNow) .Where(x => x.BusinessId == biz.BusinessId && x.BusinessType == biz.BusinessType && x.FeeStatus == FeeStatus.AuditSubmitted) .WhereIF(callback.FlowStatus == FlowStatusEnum.Approve, x => x.FeeType == FeeType.Receivable) .ExecuteCommandAsync(); biz.BillFeeStatusTime = dtNow; await TenantDb.Updateable(biz).UpdateColumns(x => new { x.BillAuditStatus, x.BillFeeStatusTime }).ExecuteCommandAsync(); } else if (auditType == TaskBaseTypeEnum.BILL_PAY_AUDIT) { if (callback.FlowStatus == FlowStatusEnum.Approve) { biz.BillAuditStatus = BillAuditStatus.PayPassed; biz.ARFeeStatus = biz.APFeeStatus = BillFeeStatus.AuditPassed; feeStatus = FeeStatus.AuditPassed; } else if (callback.FlowStatus == FlowStatusEnum.Reject) { biz.BillAuditStatus = BillAuditStatus.PayRejected; biz.ARFeeStatus = biz.APFeeStatus = BillFeeStatus.RejectSubmission; feeStatus = FeeStatus.RejectSubmission; } biz.BillFeeStatusTime = dtNow; await TenantDb.Updateable(biz).UpdateColumns(x => new { x.BillAuditStatus, x.BillFeeStatusTime, x.ARFeeStatus, x.APFeeStatus }).ExecuteCommandAsync(); await TenantDb.Updateable() .SetColumns(x => x.FeeStatus == feeStatus) .SetColumns(x => x.AuditBy == UserId) .SetColumns(x => x.AuditOperator == User.UserName) .SetColumns(x => x.AuditDate == dtNow) .Where(x => x.BusinessId == biz.BusinessId && x.BusinessType == biz.BusinessType && x.FeeStatus == FeeStatus.AuditSubmitted) .ExecuteCommandAsync(); } //锁单审核 else if (auditType == TaskBaseTypeEnum.BILL_LOCK_AUDIT && callback.FlowStatus == FlowStatusEnum.Approve) { biz.IsBusinessLocking = true; await SetLockAsync(biz); } await TenantDb.Ado.CommitTranAsync(); } catch (Exception ex) { await TenantDb.Ado.RollbackTranAsync(); await ex.LogAsync(Db); throw; } if (auditType == TaskBaseTypeEnum.BILL_PAY_AUDIT && callback.FlowStatus == FlowStatusEnum.Approve) { if (biz.ProfitMargin > 0) { biz.IsBusinessLocking = true; await SetLockAsync(biz); } else //如果为非正利润则生成锁单任务 { result = await CreateTaskAsync(new TaskCreationRequest { BusinessId = biz.BusinessId, BusinessType = biz.BusinessType, TaskTypeName = TaskBaseTypeEnum.BILL_LOCK_AUDIT.ToString(), TaskTitle = $"【{TaskBaseTypeEnum.BILL_LOCK_AUDIT.GetDescription()}】{biz.CustomerNo}", }); if (!result.Succeeded) logger.LogError($"生成【{TaskBaseTypeEnum.BILL_LOCK_AUDIT.GetDescription()}】任务失败:" + result.Message); } //生成账单任务 } } /// /// 锁单审核 /// /// /// public async Task BillLockAuditAsync(TaskAuditRequest request) { request.TaskTypeName = TaskBaseTypeEnum.BILL_LOCK_AUDIT.ToString(); return await AuditAsync(request); } /// /// 设置锁定 /// /// 业务费用对象 /// public async Task SetLockAsync(BusinessFeeStatus biz) { if (biz.IsFeeLocking.GetValueOrDefault()) { biz.FeeLockingTime = DateTime.Now; biz.FeeLockingUserId = UserId; biz.FeeLockingUserName = User.UserName; } else { biz.FeeUnLockingTime = DateTime.Now; biz.FeeUnLockingUserId = UserId; biz.FeeUnLockingUserName = User.UserName; } await TenantDb.Updateable(biz).UpdateColumns(x => new { x.IsFeeLocking, x.FeeLockingTime, x.FeeLockingUserId, x.FeeLockingUserName, x.FeeUnLockingTime, x.FeeUnLockingUserId, x.FeeUnLockingUserName }).ExecuteCommandAsync(); } /// /// 任务审核 /// /// /// public override async Task AuditAsync(TaskAuditRequest request) { var tasks = await TenantDb.Queryable().Where(x => x.TaskType == request.TaskType && request.Ids.Contains(x.BusinessId)) .WhereIF(request.BusinessType.HasValue, x => x.BusinessType == request.BusinessType.Value).ToListAsync(); if (tasks.Count == 0) return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TaskNotExists)); if (tasks.Count != request.Ids.Length) return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TaskCountNotMatch)); if (tasks.Exists(x => x.TaskStatus == TaskStatusEnum.Complete)) { return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TaskCompleted)); } else if (tasks.Exists(x => x.TaskStatus != TaskStatusEnum.Create && x.TaskStatus != TaskStatusEnum.Pending)) { return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TaskAuditStatusError)); } DataResult result = DataResult.Success; await TenantDb.Ado.BeginTranAsync(); try { var flowIds = tasks.Select(x => x.FlowId.Value); var flowInstances = await Db.Queryable().Where(x => flowIds.Contains(x.Id)).ToListAsync(); foreach (var instance in flowInstances) { result = await FlowService.Value.AuditAsync(new FlowAuditInfo { AuditNote = request.Remark, Status = request.Result, Instance = instance }); if (!result.Succeeded) return result; var req = new TaskUpdateRequest { BusinessId = instance.BusinessId, BusinessType = instance.BusinessType, RejectReason = request.Remark, TaskTypeName = request.TaskType.ToString(), TaskStatus = request.Result == 1 ? TaskStatusEnum.Complete : TaskStatusEnum.Pending, AutoCreateNext = true }; //根据审批结果更新任务状态 await SetTaskStatusAsync(req, false); if (instance.FlowStatus == FlowStatusEnum.Reject) result.Message = MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.TaskRejected)); } await TenantDb.Ado.CommitTranAsync(); return result; } catch (Exception ex) { await TenantDb.Ado.RollbackTranAsync(); await ex.LogAsync(Db); return DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed)); } } /// /// 设置任务状态 /// /// /// /// public override Task SetTaskStatusAsync(TaskUpdateRequest request, bool useTransaction = true) { return base.SetTaskStatusAsync(request, useTransaction); } //更新当前任务状态 private async Task UpdateTaskStatus(FlowCallback callback, BusinessFeeStatus business) { DataResult result = await SetTaskStatusAsync(new TaskUpdateRequest { BusinessId = callback.BusinessId, BusinessType = callback.BusinessType, TaskTypeName = callback.AuditType.ToString()!, TaskStatus = TaskStatusEnum.Complete }, false); if (!result.Succeeded) logger.LogError($"设置【{callback.AuditType.GetDescription()}】任务状态失败:" + result.Message); string remark = "终审完成,审批结果为:" + callback.FlowStatus.GetDescription(); if (callback.FlowStatus == FlowStatusEnum.Reject) { var task = await GetQuery(callback.BusinessId, callback.BusinessType, callback.AuditType.Value).FirstAsync(); var request = new TaskCreationRequest { BusinessId = callback.BusinessId, BusinessType = callback.BusinessType, TaskTypeName = GetRejectedType(callback.AuditType.Value).ToString()!, TaskTitle = $"【{callback.AuditType.GetDescription()}】【{callback.BusinessType.GetDescription()}】{business.CustomerNo}", RecvUserIdList = [task.CreateBy] //通知任务发起人 }; //创建驳回任务以进行通知 await CreateTaskAsync(request, false); //更新任务描述为驳回原因 await SetTaskBaseDescription(callback.BusinessId, request.TaskType, callback.RejectReason!); remark += ";驳回原因:" + callback.RejectReason; } long userId = long.Parse(User.UserId); var users = await FillInUserInfoAsync(userId); //记录日志 await LogService.WriteLogAsync(new BusinessTaskLog { ActionType = ActionType.Audit, AuditStatus = callback.FlowStatus, BusinessId = callback.BusinessId, BusinessType = callback.BusinessType, CreateBy = userId, CreateTime = DateTime.Now, TaskStatus = callback.FlowStatus == FlowStatusEnum.Approve ? TaskStatusEnum.Complete : TaskStatusEnum.Pending, TaskType = callback.AuditType.GetValueOrDefault(), RecvUsers = users.Count > 0 ? users[0].RecvUserName : null, Remark = remark }); } } }