You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

379 lines
17 KiB
C#

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
{
/// <summary>
/// 费用整票审核任务
/// </summary>
public class FeeBillTaskService : TaskService, IFeeBillTaskService
{
/// <summary>
/// 当前用户ID
/// </summary>
public readonly long UserId;
readonly ILogger<FeeBillTaskService> logger;
/// <summary>
/// 初始化
/// </summary>
/// <param name="provider"></param>
public FeeBillTaskService(IServiceProvider provider) : base(provider)
{
logger = provider.GetRequiredService<ILogger<FeeBillTaskService>>();
UserId = long.Parse(User.UserId);
}
/// <summary>
/// 批量创建
/// </summary>
/// <param name="request"></param>
/// <param name="useTransaction"></param>
/// <returns></returns>
public override Task<DataResult> CreateMultipleTaskAsync(TaskCreationRequest request, bool useTransaction = true)
{
return Task.FromResult(DataResult.Failed("不支持批量提交整票审核任务"));
}
/// <summary>
/// 整票审核回调更新
/// </summary>
/// <param name="callback"></param>
/// <returns></returns>
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<BusinessFeeStatus>().Where(x => x.BusinessId == callback.BusinessId && x.BusinessType == callback.BusinessType)
.InnerJoin<SeaExport>((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<FeeRecord>().Where(f => f.BusinessId == x.BusinessId && f.BusinessType == x.BusinessType && f.FeeType == FeeType.Receivable).Sum(f => f.Amount * SqlFunc.IsNull(f.ExchangeRate.Value, 1))
- SqlFunc.Subqueryable<FeeRecord>().Where(f => f.BusinessId == x.BusinessId && f.BusinessType == x.BusinessType && f.FeeType == FeeType.Payable).Sum(f => f.Amount * SqlFunc.IsNull(f.ExchangeRate.Value, 1))
}).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<FeeRecord>()
.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<FeeRecord>()
.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.IsFeeLocking = 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);
}
var req = new TaskCreationRequest
{
BusinessId = biz.BusinessId,
BusinessType = biz.BusinessType,
TaskTypeName = TaskBaseTypeEnum.BILL_SENDING.ToString(),
TaskTitle = $"【{TaskBaseTypeEnum.BILL_SENDING.GetDescription()}】{biz.CustomerNo}",
Jobs = []
};
req.Jobs.Add(new TaskJob
{
TypeName = typeof(FeeBillTaskJob).FullName!,
NextTriggerTime = dtNow.AddMinutes(60)
});
//生成账单任务
result = await CreateTaskAsync(req);
if (!result.Succeeded)
logger.LogError($"生成【{TaskBaseTypeEnum.BILL_SENDING.GetDescription()}】任务失败:" + result.Message);
}
}
/// <summary>
/// 设置锁定
/// </summary>
/// <param name="biz">业务费用对象</param>
/// <returns></returns>
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();
}
/// <summary>
/// 任务审核
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public override async Task<DataResult> AuditAsync(TaskAuditRequest request)
{
var tasks = await TenantDb.Queryable<BusinessTask>().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<FlowInstance>().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));
}
}
/// <summary>
/// 设置任务状态
/// </summary>
/// <param name="request"></param>
/// <param name="useTransaction"></param>
/// <returns></returns>
public override Task<DataResult> 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}",
TaskDescription = "审核备注:" + callback.RejectReason,
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
});
}
}
}