using Aop.Api.Domain; using FlexJobApi.Core; using Furion.DatabaseAccessor; using Furion.DistributedIDGenerator; using Furion.FriendlyException; using Mapster; using MediatR; using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using TaskInfo = FlexJobApi.Core.TaskInfo; namespace FlexJobApi.FlexJobServer.Application { /// /// 任务命令处理器 /// public class TaskInfoCommandHandler( IRepository rep, IRepository repEnterpriseWallet, AlipayUtils alipayUtils ) : IRequestHandler, IRequestHandler, IRequestHandler, IRequestHandler, IRequestHandler, IRequestHandler, IRequestHandler { private readonly IRepository rep = rep; private readonly IRepository repEnterpriseWallet = repEnterpriseWallet; private readonly AlipayUtils alipayUtils = alipayUtils; /// /// 保存任务 /// /// /// /// /// [UnitOfWork] public async Task Handle(SaveTaskInfoCommand request, CancellationToken cancellationToken) { var logier = JwtUtils.GetCurrentLogier(); if (logier.EnterpriseId == null) throw Oops.Oh(EnumErrorCodeType.s400, "当前登录用户必须为企业用户才可以创建任务"); var entity = await request.SaveData( q => { q = TaskInfoRepository.GetQueryable(rep, false) .Include(it => it.Benefits) .Include(it => it.CredentialLimits); return q; }, null, (entity) => { if (request.Id == null) { entity.EnterpriseId = logier.EnterpriseId.Value; entity.Status = EnumTaskStatus.Wait; entity.ReleaseStatus = EnumTaskReleaseStatus.InProcess; entity.RecommendStatus = EnumTaskRecommendStatus.No; BuildCode(entity).Wait(); } request.Adapt(entity); entity.Benefits = request.Benefits .Select(it => new TaskInfoBenefit { BenefitCode = it }) .ToList(); entity.CredentialLimits = request.CredentialLimits .Select(it => new TaskInfoCredentialLimit { TypeCode = it }) .ToList(); }, cancellationToken); return entity.Id; } /// /// 设置任务发布状态 /// /// /// /// public async Task Handle(SetTaskInfoReleaseStatusCommand request, CancellationToken cancellationToken) { var entities = await TaskInfoRepository.GetQueryable(rep, false) .Where(it => request.Ids.Contains(it.Id)) .ToListAsync(); foreach (var entity in entities) { entity.ReleaseStatus = request.ReleaseStatus; } await rep.UpdateAsync(entities); return entities.Count; } /// /// 设置任务是否推荐 /// /// /// /// public async Task Handle(SetTaskInfoRecommendStatusCommand request, CancellationToken cancellationToken) { var entities = await TaskInfoRepository.GetQueryable(rep, false) .Where(it => request.Ids.Contains(it.Id) && it.RecommendStatus != request.RecommendStatus) .ToListAsync(); if (entities.IsNotNull()) { foreach (var entity in entities) { entity.RecommendStatus = request.RecommendStatus; if (entity.RecommendStatus == EnumTaskRecommendStatus.Yes) { entity.RecommendTime = DateTime.Now; } } await rep.UpdateAsync(entities); } return entities.Count; } /// /// 删除任务 /// /// /// /// public Task Handle(DeleteTaskInfoCommand request, CancellationToken cancellationToken) { return request.DeleteData( 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); } /// /// 确认结算单 /// /// /// /// public async Task 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; } foreach (var user in entity.TaskInfoUsers) { var model = request.TaskInfoUsers.FirstOrDefault(it => it.Id == user.Id); if (model == null) { user.SettlementStatus = null; } } await rep.UpdateAsync(entity); return entity.Id; } /// /// 撤回结算 /// /// /// /// public async Task 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; } /// /// 确认结算 /// /// /// /// public async Task 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)}"; var exist = await rep.AsQueryable().AsNoTracking() .AnyAsync(it => it.EnterpriseId == entity.EnterpriseId && it.Code == entity.Code); if (exist) await BuildCode(entity); } } }