sunpengfei
2 天以前 e14381ae0ec7a149f99b175140d8ce7c2c7c6b05
FlexJobApi.Core/Jobs/CompleteTaskSettlementT1Job.cs
@@ -1,10 +1,12 @@
using Aop.Api.Domain;
using Azure;
using Furion;
using Furion.DatabaseAccessor;
using Furion.DistributedIDGenerator;
using Furion.FriendlyException;
using Furion.Schedule;
using Microsoft.EntityFrameworkCore;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -23,33 +25,276 @@
            IRepository<TaskInfoUser> repTaskInfoUser,
            IRepository<EnterpriseWallet> repEnterpriseWallet,
            IRepository<EnterpriseWalletTransaction> repEnterpriseWalletTransaction,
            IRepository<UserWallet> repUserWallet,
            IRepository<UserWalletTransaction> repUserWalletTransaction,
            AlipayUtils alipayUtils
        ) : IJob
    {
        private readonly IRepository<TaskInfo> rep = rep;
        private readonly IRepository<TaskInfoUser> repTaskInfoUser = repTaskInfoUser;
        private readonly IRepository<EnterpriseWallet> repEnterpriseWallet = repEnterpriseWallet;
        private readonly IRepository<UserWallet> repUserWallet = repUserWallet;
        private readonly IRepository<UserWalletTransaction> repUserWalletTransaction = repUserWalletTransaction;
        private readonly AlipayUtils alipayUtils = alipayUtils;
        [UnitOfWork(false)]
        public async Task ExecuteAsync(JobExecutingContext context, CancellationToken stoppingToken)
        {
            var now = DateTime.Now;
            var env = App.GetConfig<string>("Environment");
            var q = rep.AsQueryable()
                .Where(it => it.SettlementStatus == EnumTaskSettlementStatus.InProcess);
            var minTime = env == "Local"
                ? now.AddMinutes(-1)
                : env == "Test"
                ? now.AddMinutes(-5)
                : now.AddDays(-1);
            q = q.Where(it => it.SettlementStartTime.HasValue && it.SettlementStartTime < minTime);
            var tasks = await q.ToListAsync();
            var enterpriseIds = tasks.DistinctSelect(it => it.EnterpriseId);
            var taskIds = tasks.DistinctSelect(it => it.Id);
            var taskUsers = await repTaskInfoUser
                .Where(it => taskIds.Contains(it.TaskInfoId) && it.SettlementStatus == EnumTaskSettlementStatus.InProcess)
            if (env != "Local")
            {
                var tasks = await GetTasks();
                var enterpriseIds = tasks.DistinctSelect(it => it.EnterpriseId);
                var taskIds = tasks.DistinctSelect(it => it.Id);
                var taskUsers = await GetTaskUsers(taskIds);
                var userIds = taskUsers.DistinctSelect(it => it.EnterpriseEmployee.UserId.Value);
                var userWallets = await GetUserWallets(userIds);
                var enterpriseWallets = await GetEnterpriseWallets(enterpriseIds);
                if (tasks.IsNotNull())
                {
                    foreach (var task in tasks)
                    {
                        var enterpriseWallet = enterpriseWallets.FirstOrDefault(it => it.EnterpriseId == task.EnterpriseId);
                        task.SettlementStatus = EnumTaskSettlementStatus.Completed;
                        task.SettlementTime = DateTime.Now;
                        await rep.UpdateNowAsync(task);
                        var users = taskUsers.Where(it => it.TaskInfoId == task.Id).ToList();
                        foreach (var user in users)
                        {
                            user.SettlementStatus = EnumTaskSettlementStatus.Completed;
                            user.SettlementTime = DateTime.Now;
                            await repTaskInfoUser.UpdateNowAsync(user);
                            var userWallet = await AddUserWalletTransactionIncome(userWallets, task, user);
                            var withdraw = await AddUserWalletTransactionWithdraw(userWallet, task, user);
                            var transfer = await AddEnterpriseWalletTransactionTransfer(enterpriseWallet, task, user);
                            await UpdateUserWalletTransactionWithdraw(userWallet, withdraw, transfer);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// 更新用户钱包提现记录
        /// </summary>
        /// <param name="wallet"></param>
        /// <param name="withdraw"></param>
        /// <param name="transfer"></param>
        /// <returns></returns>
        private async Task UpdateUserWalletTransactionWithdraw(UserWallet wallet, UserWalletTransaction withdraw, EnterpriseWalletTransaction transfer)
        {
            withdraw.EnterpriseWalletTransactionId = transfer.Id;
            withdraw.TransactionStatus = transfer.TransactionStatus;
            withdraw.TransDate = transfer.TransDate;
            if (withdraw.TransactionStatus == EnumWalletTransactionStatus.Success)
            {
                withdraw.ActualAmount = withdraw.Amount;
            }
            else
            {
                withdraw.ActualAmount = 0;
                var order = new UserWalletTransaction();
                order.WalletId = wallet.Id;
                order.Type = EnumUserWalletTransactionType.Income;
                order.OperatorUserId = withdraw.OperatorUserId;
                order.OperatorTime = withdraw.OperatorTime;
                order.Title = $"收入-提现失败退款";
                order.Amount = withdraw.Amount;
                order.ActualAmount = order.Amount;
                order.Balance = wallet.Balance;
                order.AfterBalance = wallet.Balance + order.Amount;
                order.TransDate = DateTime.Now;
                order.TransactionStatus = EnumWalletTransactionStatus.Success;
                await SetCode(order);
                await repUserWalletTransaction.InsertNowAsync(order);
                wallet.Balance = order.AfterBalance;
                await repUserWallet.UpdateNowAsync(wallet);
            }
        }
        /// <summary>
        /// 添加用户钱包提现记录
        /// </summary>
        /// <param name="wallet"></param>
        /// <param name="task"></param>
        /// <param name="user"></param>
        /// <returns></returns>
        private async Task<UserWalletTransaction> AddUserWalletTransactionWithdraw(UserWallet wallet, TaskInfo task, TaskInfoUser user)
        {
            var order = new UserWalletTransaction();
            order.WalletId = wallet.Id;
            order.Type = EnumUserWalletTransactionType.Withdraw;
            order.OperatorUserId = task.SettlementOperatorUserId;
            order.OperatorTime = task.SettlementStartTime;
            order.Title = $"提现-支付宝提现";
            order.Amount = user.ActualSettlementAmount ?? 0;
            order.Balance = wallet.Balance;
            order.AfterBalance = wallet.Balance - order.Amount;
            order.ReceiveName = user.ReceiveName;
            order.ReceiveAccount = user.ReceiveAccount;
            order.TransDate = DateTime.Now;
            order.TransactionStatus = EnumWalletTransactionStatus.Dealing;
            await SetCode(order);
            await repUserWalletTransaction.InsertNowAsync(order);
            wallet.Balance -= user.ActualSettlementAmount ?? 0;
            await repUserWallet.UpdateNowAsync(wallet);
            return order;
        }
        /// <summary>
        /// 添加用户钱包收入记录
        /// </summary>
        /// <param name="wallets"></param>
        /// <param name="task"></param>
        /// <param name="user"></param>
        /// <returns></returns>
        private async Task<UserWallet> AddUserWalletTransactionIncome(List<UserWallet> wallets, TaskInfo task, TaskInfoUser user)
        {
            var wallet = wallets.FirstOrDefault(it => it.UserId == user.EnterpriseEmployee.UserId);
            if (wallet == null)
            {
                wallet = new UserWallet();
                wallet.UserId = user.EnterpriseEmployee.UserId.Value;
                await repUserWallet.InsertNowAsync(wallet);
            }
            var order = new UserWalletTransaction();
            order.WalletId = wallet.Id;
            order.Type = EnumUserWalletTransactionType.Income;
            order.TaskUserId = user.Id;
            order.EnterpriseName = task.Enterprise.EnterpriseName;
            order.SettlementTime = user.SettlementTime;
            order.SettlementAmount = user.SettlementAmount;
            order.OperatorUserId = task.SettlementOperatorUserId;
            order.OperatorTime = task.SettlementStartTime;
            order.Title = $"收入-{order.EnterpriseName}";
            order.Amount = user.ActualSettlementAmount ?? 0;
            order.ActualAmount = order.Amount;
            order.Balance = wallet.Balance;
            order.AfterBalance = wallet.Balance + order.Amount;
            order.TransDate = DateTime.Now;
            order.TransactionStatus = EnumWalletTransactionStatus.Success;
            await SetCode(order);
            await repUserWalletTransaction.InsertNowAsync(order);
            wallet.Balance = order.AfterBalance;
            await repUserWallet.UpdateNowAsync(wallet);
            return wallet;
        }
        /// <summary>
        /// 添加企业钱包转账记录
        /// </summary>
        /// <param name="wallet"></param>
        /// <param name="task"></param>
        /// <param name="user"></param>
        /// <returns></returns>
        private async Task<EnterpriseWalletTransaction> AddEnterpriseWalletTransactionTransfer(EnterpriseWallet wallet, TaskInfo task, TaskInfoUser user)
        {
            var order = new EnterpriseWalletTransaction();
            order.Type = EnumEnterpriseWalletTransactionType.Transfer;
            order.WalletId = wallet.Id;
            order.TaskUserId = user.Id;
            order.Amount = user.ActualSettlementAmount ?? 0;
            order.Remark = user.SettlementRemark;
            order.ProductCode = "SINGLE_TRANSFER_NO_PWD";
            order.BizScene = "ENTRUST_TRANSFER";
            order.TransactionStatus = EnumWalletTransactionStatus.WaitSubmit;
            order.Balance = wallet.Balance;
            order.AfterBalance = wallet.Balance - order.Amount;
            order.OperatorUserId = task.SettlementOperatorUserId;
            order.OperatorTime = task.SettlementStartTime;
            order.ReceiveUserId = user.EnterpriseEmployee.UserId;
            order.ReceiveName = user.ReceiveName;
            order.ReceiveAccount = user.ReceiveAccount;
            await SetCode(order);
            await repEnterpriseWalletTransaction.InsertNowAsync(order);
            var response = alipayUtils.FundTransUniTransfer(new AlipayFundTransUniTransferModel
            {
                OutBizNo = order.Code,
                TransAmount = order.Amount.ToString(),
                ProductCode = order.ProductCode,
                BizScene = order.BizScene,
                PayeeInfo = new Participant
                {
                    IdentityType = "ALIPAY_LOGON_ID",
                    Identity = order.ReceiveAccount,
                    Name = order.ReceiveName,
                },
                PayerInfo = new Participant
                {
                    IdentityType = "ACCOUNT_BOOK_ID",
                    Identity = wallet.AccountBookId,
                    ExtInfo = new
                    {
                        agreement_no = wallet.AgreementNo,
                    }.ToJson(),
                },
                OrderTitle = order.Remark,
                Remark = order.Remark,
                BusinessParams = new
                {
                    withdraw_timeliness = "T0"
                }.ToJson()
            }, "/api/user/enterpriseWallet/alipayFundTransOrderChangedNotify");
            if (response.IsError)
            {
                order.ErrorCode = response.Code;
                order.FailReason = response.SubMsg ?? response.Msg;
                await repEnterpriseWalletTransaction.UpdateNowAsync(order);
            }
            else
            {
                order.OrderId = response.OrderId;
                order.PayFundOrderId = response.PayFundOrderId;
                order.SettleSerialNo = response.SettleSerialNo;
                order.TransDate = response.TransDate.ToDateTime();
                order.Link = response.Link;
                order.Status = response.Status;
                order.SubStatus = response.SubStatus;
                order.TransactionStatus = response.Status == "SUCCESS"
                    ? EnumWalletTransactionStatus.Success
                    : response.Status == "DEALING"
                    ? EnumWalletTransactionStatus.Dealing
                    : response.Status == "REFUND"
                    ? EnumWalletTransactionStatus.Refund
                    : EnumWalletTransactionStatus.Fail;
                await repEnterpriseWalletTransaction.UpdateNowAsync(order);
            }
            return order;
        }
        /// <summary>
        /// 查询用户钱包
        /// </summary>
        /// <param name="userIds"></param>
        /// <returns></returns>
        private async Task<List<UserWallet>> GetUserWallets(List<Guid> userIds)
        {
            var wallets = await repUserWallet.AsQueryable().AsNoTracking()
                .Where(it => userIds.Contains(it.UserId))
                .ToListAsync();
            return wallets;
        }
        /// <summary>
        /// 查询企业钱包
        /// </summary>
        /// <param name="enterpriseIds"></param>
        /// <returns></returns>
        private async Task<List<EnterpriseWallet>> GetEnterpriseWallets(List<Guid> enterpriseIds)
        {
            var wallets = await repEnterpriseWallet.AsQueryable()
                .Where(it => enterpriseIds.Contains(it.EnterpriseId) && it.Access == EnumEnterpriseWalletAccess.Alipay)
                .ToListAsync();
@@ -65,88 +310,42 @@
                wallet.Balance = response.AvailableAmount.ToDecimal() ?? 0;
                await repEnterpriseWallet.UpdateNowAsync(wallet);
            }
            if (tasks.IsNotNull())
            {
                foreach (var task in tasks)
                {
                    var wallet = wallets.FirstOrDefault(it => it.EnterpriseId == task.EnterpriseId);
                    task.SettlementStatus = EnumTaskSettlementStatus.Completed;
                    task.SettlementTime = DateTime.Now;
                    await rep.UpdateNowAsync(task);
            return wallets;
        }
                    var users = taskUsers.Where(it => it.TaskInfoId == task.Id).ToList();
                    foreach (var user in users)
                    {
                        user.SettlementStatus = EnumTaskSettlementStatus.Completed;
                        user.SettlementTime = DateTime.Now;
                        await repTaskInfoUser.UpdateNowAsync(user);
        /// <summary>
        /// 查询任务用户
        /// </summary>
        /// <param name="taskIds"></param>
        /// <returns></returns>
        private async Task<List<TaskInfoUser>> GetTaskUsers(List<Guid> taskIds)
        {
            var taskUsers = await repTaskInfoUser
                .Include(it => it.EnterpriseEmployee)
                .Where(it =>
                    taskIds.Contains(it.TaskInfoId)
                    && it.SettlementStatus == EnumTaskSettlementStatus.InProcess)
                .ToListAsync();
            return taskUsers;
        }
                        var order = new EnterpriseWalletTransaction();
                        order.Type = EnumEnterpriseWalletTransactionType.Recharge;
                        order.WalletId = wallet.Id;
                        order.Amount = user.ActualSettlementAmount ?? 0;
                        order.Remark = user.SettlementRemark;
                        order.ProductCode = "SINGLE_TRANSFER_NO_PWD";
                        order.BizScene = "ENTRUST_TRANSFER";
                        order.TransactionStatus = EnumEnterpriseWalletTransactionStatus.WaitSubmit;
                        order.Balance = wallet.Balance;
                        await SetCode(order);
                        await repEnterpriseWalletTransaction.InsertNowAsync(order);
                        var response = alipayUtils.FundTransUniTransfer(new AlipayFundTransUniTransferModel
                        {
                            OutBizNo = order.Code,
                            TransAmount = order.Amount.ToString(),
                            ProductCode = order.ProductCode,
                            BizScene = order.BizScene,
                            PayeeInfo = new Participant
                            {
                                IdentityType = "ALIPAY_LOGON_ID",
                                Identity = user.ReceiveAccount,
                                Name = user.ReceiveName,
                            },
                            PayerInfo = new Participant
                            {
                                IdentityType = "ACCOUNT_BOOK_ID",
                                Identity = wallet.AccountBookId,
                                ExtInfo = new
                                {
                                    agreement_no = wallet.AgreementNo,
                                }.ToJson(),
                            },
                            OrderTitle = order.Remark,
                            Remark = order.Remark,
                            BusinessParams = new
                            {
                                withdraw_timeliness = "T0"
                            }.ToJson()
                        }, "/api/user/enterpriseWallet/alipayFundTransOrderChangedNotify");
                        if (response.IsError)
                        {
                            order.ErrorCode = response.Code;
                            order.FailReason = response.SubMsg ?? response.Msg;
                        }
                        else
                        {
                            order.OrderId = response.OrderId;
                            order.PayFundOrderId = response.PayFundOrderId;
                            order.SettleSerialNo = response.SettleSerialNo;
                            order.TransDate = response.TransDate.ToDateTime();
                            order.Link = response.Link;
                            order.Status = response.Status;
                            order.SubStatus = response.SubStatus;
                            order.TransactionStatus = response.Status == "SUCCESS"
                                ? EnumEnterpriseWalletTransactionStatus.Success
                                : response.Status == "DEALING"
                                ? EnumEnterpriseWalletTransactionStatus.Dealing
                                : response.Status == "REFUND"
                                ? EnumEnterpriseWalletTransactionStatus.Refund
                                : EnumEnterpriseWalletTransactionStatus.Fail;
                            await repEnterpriseWalletTransaction.UpdateNowAsync(order);
                        }
                    }
                }
            }
        /// <summary>
        /// 查询任务
        /// </summary>
        /// <param name="env"></param>
        /// <returns></returns>
        private async Task<List<TaskInfo>> GetTasks()
        {
            var now = DateTime.Now;
            var q = rep.AsQueryable()
                .Include(it => it.Enterprise)
                .Where(it => it.SettlementStatus == EnumTaskSettlementStatus.InProcess);
            var minTime = App.GetConfig<string>("Task:SettlementTime") == "T0"
                ? now.AddMinutes(-5)
                : now.AddDays(-1);
            q = q.Where(it => it.SettlementStartTime.HasValue && it.SettlementStartTime < minTime);
            var tasks = await q.ToListAsync();
            return tasks;
        }
        private async Task SetCode(EnterpriseWalletTransaction entity)
@@ -160,5 +359,16 @@
            }
        }
        private async Task SetCode(UserWalletTransaction entity)
        {
            entity.Code = $"{DateTime.Now:yyyyMMddHHmmss}{new Random(IDGen.NextID().GetHashCode()).Next(1000, 9999)}";
            var exist = await repUserWalletTransaction.AsQueryable().AsNoTracking()
                .AnyAsync(it => it.Code == entity.Code);
            if (exist)
            {
                await SetCode(entity);
            }
        }
    }
}