From 5c45bc53e2c18e45130c21048df4af4896455c6d Mon Sep 17 00:00:00 2001 From: sunpengfei <i@angelzzz.com> Date: 星期五, 12 九月 2025 15:58:48 +0800 Subject: [PATCH] feat:开发 --- FlexJobApi.Core/Jobs/CompleteTaskSettlementT1Job.cs | 404 ++++++++++++++++++++++++++++++++++++++++++++------------- 1 files changed, 310 insertions(+), 94 deletions(-) diff --git a/FlexJobApi.Core/Jobs/CompleteTaskSettlementT1Job.cs b/FlexJobApi.Core/Jobs/CompleteTaskSettlementT1Job.cs index 52742c1..01e4698 100644 --- a/FlexJobApi.Core/Jobs/CompleteTaskSettlementT1Job.cs +++ b/FlexJobApi.Core/Jobs/CompleteTaskSettlementT1Job.cs @@ -1,10 +1,12 @@ 锘縰sing 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,278 @@ 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.ErrorCode = transfer.ErrorCode; + withdraw.FailReason = transfer.FailReason; + 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(); @@ -60,93 +307,51 @@ AccountBookId = wallet.AccountBookId, SceneCode = "SATF_FUND_BOOK", MerchantUserId = wallet.Code, + ExtInfo = new + { + agreement_no = wallet.AgreementNo + }.ToJson() }); if (response.IsError) throw Oops.Oh(EnumErrorCodeType.s510, response.SubMsg ?? response.Msg); 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 +365,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); + } + } + } } -- Gitblit v1.9.1