| | |
| | | using FlexJobApi.Core; |
| | | using Aop.Api.Domain; |
| | | using FlexJobApi.Core; |
| | | using Furion.DatabaseAccessor; |
| | | using Furion.DistributedIDGenerator; |
| | | using Furion.FriendlyException; |
| | |
| | | using System.Linq; |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | | using TaskInfo = FlexJobApi.Core.TaskInfo; |
| | | |
| | | namespace FlexJobApi.FlexJobServer.Application |
| | | { |
| | |
| | | /// 任务命令处理器 |
| | | /// </summary> |
| | | public class TaskInfoCommandHandler( |
| | | IRepository<TaskInfo> rep |
| | | IRepository<TaskInfo> rep, |
| | | IRepository<EnterpriseWallet> repEnterpriseWallet, |
| | | AlipayUtils alipayUtils |
| | | ) : |
| | | IRequestHandler<SaveTaskInfoCommand, Guid>, |
| | | IRequestHandler<SetTaskInfoReleaseStatusCommand, int>, |
| | | IRequestHandler<SetTaskInfoRecommendStatusCommand, int> |
| | | IRequestHandler<SetTaskInfoRecommendStatusCommand, int>, |
| | | IRequestHandler<DeleteTaskInfoCommand, int>, |
| | | IRequestHandler<SureTaskSettlementOrderCommand, Guid>, |
| | | IRequestHandler<RevokeTaskSettlementOrderCommand, Guid>, |
| | | IRequestHandler<SureTaskSettlementCommand, Guid> |
| | | { |
| | | private readonly IRepository<TaskInfo> rep = rep; |
| | | private readonly IRepository<EnterpriseWallet> repEnterpriseWallet = repEnterpriseWallet; |
| | | private readonly AlipayUtils alipayUtils = alipayUtils; |
| | | |
| | | /// <summary> |
| | | /// 保存任务 |
| | |
| | | { |
| | | var logier = JwtUtils.GetCurrentLogier(); |
| | | if (logier.EnterpriseId == null) throw Oops.Oh(EnumErrorCodeType.s400, "当前登录用户必须为企业用户才可以创建任务"); |
| | | return await request.SaveData<TaskInfo, SaveTaskInfoCommand>( |
| | | var entity = await request.SaveData<TaskInfo, SaveTaskInfoCommand>( |
| | | q => |
| | | { |
| | | q = TaskInfoRepository.GetQueryable(rep, false) |
| | |
| | | .ToList(); |
| | | }, |
| | | cancellationToken); |
| | | return entity.Id; |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | public async Task<int> Handle(SetTaskInfoRecommendStatusCommand request, CancellationToken cancellationToken) |
| | | { |
| | | var entities = await TaskInfoRepository.GetQueryable(rep, false) |
| | | .Where(it => request.Ids.Contains(it.Id)) |
| | | .Where(it => request.Ids.Contains(it.Id) && it.RecommendStatus != request.RecommendStatus) |
| | | .ToListAsync(); |
| | | foreach (var entity in entities) |
| | | if (entities.IsNotNull()) |
| | | { |
| | | entity.RecommendStatus = request.RecommendStatus; |
| | | foreach (var entity in entities) |
| | | { |
| | | entity.RecommendStatus = request.RecommendStatus; |
| | | if (entity.RecommendStatus == EnumTaskRecommendStatus.Yes) |
| | | { |
| | | entity.RecommendTime = DateTime.Now; |
| | | } |
| | | } |
| | | await rep.UpdateAsync(entities); |
| | | } |
| | | await rep.UpdateAsync(entities); |
| | | return entities.Count; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 删除任务 |
| | | /// </summary> |
| | | /// <param name="request"></param> |
| | | /// <param name="cancellationToken"></param> |
| | | /// <returns></returns> |
| | | public Task<int> Handle(DeleteTaskInfoCommand request, CancellationToken cancellationToken) |
| | | { |
| | | return request.DeleteData<TaskInfo>( |
| | | q => |
| | | { |
| | | q = TaskInfoRepository.GetQueryable(rep, false); |
| | | if (q.AsNoTracking().Any(it => request.Ids.Contains(it.Id) && it.Status == EnumTaskStatus.Complete)) |
| | | { |
| | | throw Oops.Oh(EnumErrorCodeType.s510, "已安排的任务无法删除"); |
| | | } |
| | | return q; |
| | | }, cancellationToken); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 确认结算单 |
| | | /// </summary> |
| | | /// <param name="request"></param> |
| | | /// <param name="cancellationToken"></param> |
| | | /// <returns></returns> |
| | | public async Task<Guid> Handle(SureTaskSettlementOrderCommand request, CancellationToken cancellationToken) |
| | | { |
| | | var entity = await TaskInfoRepository.GetQueryable(rep, false) |
| | | .Include(it => it.TaskInfoUsers) |
| | | .Where(it => it.Id == request.TaskInfoId) |
| | | .FirstOrDefaultAsync(); |
| | | if (entity == null) throw Oops.Oh(EnumErrorCodeType.s404, "任务"); |
| | | if (entity.SettlementStatus == EnumTaskSettlementStatus.InProcess) throw Oops.Oh(EnumErrorCodeType.s510, "结算中不可修改,请先撤回"); |
| | | if (entity.SettlementStatus == EnumTaskSettlementStatus.Completed) throw Oops.Oh(EnumErrorCodeType.s510, "已结算不可修改"); |
| | | entity.SettlementOrderStatus = EnumTaskSettlementOrderStatus.Completed; |
| | | entity.SettlementOrderUrl = request.SettlementOrderUrl; |
| | | entity.SettlementOrderName = entity.SettlementOrderUrl.Substring(entity.SettlementOrderUrl.LastIndexOf("/") + 1); |
| | | entity.SettlementStatus = EnumTaskSettlementStatus.Wait; |
| | | entity.SettlementUserCount = request.TaskInfoUsers.Count; |
| | | entity.SettlementAmount = request.TaskInfoUsers.Sum(it => it.SettlementAmount ?? 0); |
| | | entity.ActualSettlementAmount = request.TaskInfoUsers.Sum(it => it.ActualSettlementAmount ?? 0); |
| | | foreach (var model in request.TaskInfoUsers) |
| | | { |
| | | var user = entity.TaskInfoUsers.FirstOrDefault(it => it.Id == model.Id); |
| | | if (user == null) throw Oops.Oh(EnumErrorCodeType.s404, $"灵工{model.Name}"); |
| | | if (user.SettlementStatus == EnumTaskSettlementStatus.InProcess) throw Oops.Oh(EnumErrorCodeType.s510, $"{model.Name}结算中不可修改,请先撤回"); |
| | | if (user.SettlementStatus == EnumTaskSettlementStatus.Completed) throw Oops.Oh(EnumErrorCodeType.s510, $"{model.Name}已结算不可修改"); |
| | | if (user.CheckReceiveStatus != EnumTaskCheckReceiveStatus.Completed) throw Oops.Oh(EnumErrorCodeType.s510, $"{model.Name}未验收"); |
| | | if (model.SettlementAmount < 0) throw Oops.Oh(EnumErrorCodeType.s510, $"{model.Name}结算金额不可负数"); |
| | | if (model.ActualSettlementAmount < 0) throw Oops.Oh(EnumErrorCodeType.s510, $"{model.Name}实发金额不可负数"); |
| | | if (model.ActualSettlementAmount > 0 && model.ActualSettlementAmount < (decimal)0.3) throw Oops.Oh(EnumErrorCodeType.s510, $"{model.Name}实发金额不可小于1元"); |
| | | user.Bank = model.Bank; |
| | | user.BankBranch = model.BankBranch; |
| | | user.ReceiveAccount = model.ReceiveAccount; |
| | | user.SettlementAmount = model.SettlementAmount; |
| | | user.ActualSettlementAmount = model.ActualSettlementAmount; |
| | | user.SettlementStatus = EnumTaskSettlementStatus.Wait; |
| | | } |
| | | await rep.UpdateAsync(entity); |
| | | return entity.Id; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 撤回结算 |
| | | /// </summary> |
| | | /// <param name="request"></param> |
| | | /// <param name="cancellationToken"></param> |
| | | /// <returns></returns> |
| | | public async Task<Guid> Handle(RevokeTaskSettlementOrderCommand request, CancellationToken cancellationToken) |
| | | { |
| | | var entity = await TaskInfoRepository.GetQueryable(rep, false) |
| | | .Include(it => it.TaskInfoUsers) |
| | | .Where(it => it.Id == request.TaskInfoId) |
| | | .FirstOrDefaultAsync(); |
| | | if (entity == null) throw Oops.Oh(EnumErrorCodeType.s404, "任务"); |
| | | if (entity.SettlementStatus == EnumTaskSettlementStatus.Wait) throw Oops.Oh(EnumErrorCodeType.s510, "未开始结算,请先上传结算单并确认"); |
| | | if (entity.SettlementStatus == EnumTaskSettlementStatus.Completed) throw Oops.Oh(EnumErrorCodeType.s510, "已结算不可撤回"); |
| | | entity.SettlementStatus = EnumTaskSettlementStatus.Wait; |
| | | foreach (var user in entity.TaskInfoUsers) |
| | | { |
| | | if (user.SettlementStatus == EnumTaskSettlementStatus.InProcess) |
| | | { |
| | | user.SettlementStatus = EnumTaskSettlementStatus.Wait; |
| | | } |
| | | } |
| | | await rep.UpdateAsync(entity); |
| | | return entity.Id; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 确认结算 |
| | | /// </summary> |
| | | /// <param name="request"></param> |
| | | /// <param name="cancellationToken"></param> |
| | | /// <returns></returns> |
| | | public async Task<Guid> Handle(SureTaskSettlementCommand request, CancellationToken cancellationToken) |
| | | { |
| | | var logier = JwtUtils.GetCurrentLogier(); |
| | | var entity = await TaskInfoRepository.GetQueryable(rep, false, logier) |
| | | .Include(it => it.TaskInfoUsers) |
| | | .Where(it => it.Id == request.TaskInfoId) |
| | | .FirstOrDefaultAsync(); |
| | | if (entity == null) throw Oops.Oh(EnumErrorCodeType.s404, "任务"); |
| | | if (entity.SettlementOrderStatus != EnumTaskSettlementOrderStatus.Completed) throw Oops.Oh(EnumErrorCodeType.s510, "请先上传结算单并确认"); |
| | | if (entity.SettlementStatus == null) throw Oops.Oh(EnumErrorCodeType.s510, "未开始结算,请先上传结算单并确认"); |
| | | if (entity.SettlementStatus == EnumTaskSettlementStatus.Completed) throw Oops.Oh(EnumErrorCodeType.s510, "已结算"); |
| | | entity.SettlementStatus = EnumTaskSettlementStatus.InProcess; |
| | | entity.SettlementStartTime = DateTime.Now; |
| | | foreach (var user in entity.TaskInfoUsers) |
| | | { |
| | | if (user.SettlementStatus == EnumTaskSettlementStatus.Wait) |
| | | { |
| | | user.SettlementStatus = EnumTaskSettlementStatus.InProcess; |
| | | } |
| | | } |
| | | var wallet = await repEnterpriseWallet.AsQueryable() |
| | | .Where(it => it.EnterpriseId == entity.EnterpriseId && it.Access == EnumEnterpriseWalletAccess.Alipay) |
| | | .FirstOrDefaultAsync(); |
| | | if (wallet == null) throw Oops.Oh(EnumErrorCodeType.s404, "企业钱包"); |
| | | if (wallet.SignStatus != EnumEnterpriseWalletSignStatus.Normal) throw Oops.Oh(EnumErrorCodeType.s404, "企业钱包未签约"); |
| | | if (wallet.AccountBookStatus != EnumEnterpriseWalletAccountBookStatus.Normal) throw Oops.Oh(EnumErrorCodeType.s404, "企业钱包记账本未开通"); |
| | | var response = alipayUtils.FundAccountbookQuery(new AlipayFundAccountbookQueryModel |
| | | { |
| | | AccountBookId = wallet.AccountBookId, |
| | | SceneCode = "SATF_FUND_BOOK", |
| | | MerchantUserId = wallet.Code, |
| | | }); |
| | | if (response.IsError) throw Oops.Oh(EnumErrorCodeType.s510, response.SubMsg ?? response.Msg); |
| | | wallet.Balance = response.AvailableAmount.ToDecimal() ?? 0; |
| | | await repEnterpriseWallet.UpdateAsync(wallet); |
| | | |
| | | var amount = await TaskInfoRepository.GetQueryable(rep, false, logier) |
| | | .Where(it => |
| | | it.EnterpriseId == entity.EnterpriseId |
| | | && it.Id != request.TaskInfoId |
| | | && it.SettlementStatus == EnumTaskSettlementStatus.InProcess |
| | | && it.ActualSettlementAmount.HasValue) |
| | | .SumAsync(it => it.ActualSettlementAmount!.Value); |
| | | amount += entity.ActualSettlementAmount!.Value; |
| | | if (wallet.Balance < amount) |
| | | throw Oops.Oh(EnumErrorCodeType.s510, "企业钱包余额不足"); |
| | | |
| | | await rep.UpdateAsync(entity); |
| | | return entity.Id; |
| | | } |
| | | |
| | | private async Task BuildCode(TaskInfo entity) |
| | | { |
| | | entity.Code = $"{DateTime.Now:yyyyMMddHHmm}{new Random(IDGen.NextID().GetHashCode()).Next(1000, 9999)}"; |