From 285404b0f7161ceca8621e61026682bbbb3f71aa Mon Sep 17 00:00:00 2001 From: sunpengfei <i@angelzzz.com> Date: 星期三, 10 九月 2025 14:23:31 +0800 Subject: [PATCH] feat:开发 --- FlexJobApi.Core/Jobs/CompleteTaskSettlementT1Job.cs | 389 ++++++++++++++++++++++++++++++++++++++++++------------ 1 files changed, 300 insertions(+), 89 deletions(-) diff --git a/FlexJobApi.Core/Jobs/CompleteTaskSettlementT1Job.cs b/FlexJobApi.Core/Jobs/CompleteTaskSettlementT1Job.cs index 032363c..79ebd00 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,12 +25,16 @@ 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)] @@ -37,39 +43,19 @@ var env = App.GetConfig<string>("Environment"); if (env != "Local") { - var now = DateTime.Now; - var q = rep.AsQueryable() - .Where(it => it.SettlementStatus == EnumTaskSettlementStatus.InProcess); - var minTime = env == "Test" - ? now.AddMinutes(-5) - : now.AddDays(-1); - q = q.Where(it => it.SettlementStartTime.HasValue && it.SettlementStartTime < minTime); - var tasks = await q.ToListAsync(); + var tasks = await GetTasks(); 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) - .ToListAsync(); - var wallets = await repEnterpriseWallet.AsQueryable() - .Where(it => enterpriseIds.Contains(it.EnterpriseId) && it.Access == EnumEnterpriseWalletAccess.Alipay) - .ToListAsync(); - foreach (var wallet in wallets) - { - 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.UpdateNowAsync(wallet); - } + 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 wallet = wallets.FirstOrDefault(it => it.EnterpriseId == task.EnterpriseId); + var enterpriseWallet = enterpriseWallets.FirstOrDefault(it => it.EnterpriseId == task.EnterpriseId); + task.SettlementStatus = EnumTaskSettlementStatus.Completed; task.SettlementTime = DateTime.Now; await rep.UpdateNowAsync(task); @@ -81,75 +67,289 @@ user.SettlementTime = DateTime.Now; await repTaskInfoUser.UpdateNowAsync(user); - 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 userWallet = await AddUserWalletTransactionIncome(userWallets, task, user); - 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); - } + 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(); + foreach (var wallet in wallets) + { + 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.UpdateNowAsync(wallet); + } + return wallets; + } + + /// <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; + } + + /// <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) { entity.Code = $"{DateTime.Now:yyyyMMddHHmmss}{new Random(IDGen.NextID().GetHashCode()).Next(1000, 9999)}"; @@ -161,5 +361,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