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 |  400 +++++++++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 306 insertions(+), 94 deletions(-)

diff --git a/FlexJobApi.Core/Jobs/CompleteTaskSettlementT1Job.cs b/FlexJobApi.Core/Jobs/CompleteTaskSettlementT1Job.cs
index 52742c1..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,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();
@@ -65,88 +312,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 +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