🐛 Fix recieve fund save db together to prevent cocurrent db save

This commit is contained in:
2025-11-17 00:49:10 +08:00
parent 713777cd8a
commit 260b3e7bc6

View File

@@ -113,7 +113,8 @@ public class PaymentService(
decimal amount, decimal amount,
string? remarks = null, string? remarks = null,
Shared.Models.TransactionType type = Shared.Models.TransactionType.System, Shared.Models.TransactionType type = Shared.Models.TransactionType.System,
bool silent = false bool silent = false,
bool autoSave = true
) )
{ {
if (payerWalletId == null && payeeWalletId == null) if (payerWalletId == null && payeeWalletId == null)
@@ -163,7 +164,10 @@ public class PaymentService(
} }
db.PaymentTransactions.Add(transaction); db.PaymentTransactions.Add(transaction);
if (autoSave)
{
await db.SaveChangesAsync(); await db.SaveChangesAsync();
}
if (!silent) if (!silent)
await NotifyNewTransaction(transaction, payerWallet, payeeWallet); await NotifyNewTransaction(transaction, payerWallet, payeeWallet);
@@ -171,7 +175,8 @@ public class PaymentService(
return transaction; return transaction;
} }
private async Task NotifyNewTransaction(SnWalletTransaction transaction, SnWallet? payerWallet, SnWallet? payeeWallet) private async Task NotifyNewTransaction(SnWalletTransaction transaction, SnWallet? payerWallet,
SnWallet? payeeWallet)
{ {
if (payerWallet is not null) if (payerWallet is not null)
{ {
@@ -593,8 +598,7 @@ public class PaymentService(
return Math.Max(amountPerSplit, 0.01m); // Minimum 0.01 per claim return Math.Max(amountPerSplit, 0.01m); // Minimum 0.01 per claim
} }
// For closed mode funds: use split type calculation // For closed mode funds: use split type calculation
else
{
var unclaimedRecipients = fund.Recipients.Count(r => !r.IsReceived); var unclaimedRecipients = fund.Recipients.Count(r => !r.IsReceived);
if (unclaimedRecipients == 0) if (unclaimedRecipients == 0)
return 0; return 0;
@@ -606,7 +610,6 @@ public class PaymentService(
_ => throw new ArgumentException("Invalid split type") _ => throw new ArgumentException("Invalid split type")
}; };
} }
}
public async Task<SnWalletTransaction> ReceiveFundAsync(Guid recipientAccountId, Guid fundId) public async Task<SnWalletTransaction> ReceiveFundAsync(Guid recipientAccountId, Guid fundId)
{ {
@@ -682,7 +685,8 @@ public class PaymentService(
amount: recipient.Amount, amount: recipient.Amount,
remarks: $"Received fund portion from {fund.CreatorAccountId}", remarks: $"Received fund portion from {fund.CreatorAccountId}",
type: Shared.Models.TransactionType.System, type: Shared.Models.TransactionType.System,
silent: true silent: true,
autoSave: false
); );
// Mark as received // Mark as received
@@ -692,18 +696,16 @@ public class PaymentService(
// Update fund status // Update fund status
if (fund.IsOpen) if (fund.IsOpen)
{ {
if (fund.RemainingAmount <= 0) fund.Status = fund.RemainingAmount <= 0
fund.Status = Shared.Models.FundStatus.FullyReceived; ? Shared.Models.FundStatus.FullyReceived
else : Shared.Models.FundStatus.PartiallyReceived;
fund.Status = Shared.Models.FundStatus.PartiallyReceived;
} }
else else
{ {
var allReceived = fund.Recipients.All(r => r.IsReceived); var allReceived = fund.Recipients.All(r => r.IsReceived);
if (allReceived) fund.Status = allReceived
fund.Status = Shared.Models.FundStatus.FullyReceived; ? Shared.Models.FundStatus.FullyReceived
else : Shared.Models.FundStatus.PartiallyReceived;
fund.Status = Shared.Models.FundStatus.PartiallyReceived;
} }
await db.SaveChangesAsync(); await db.SaveChangesAsync();
@@ -724,7 +726,8 @@ public class PaymentService(
var expiredFunds = await db.WalletFunds var expiredFunds = await db.WalletFunds
.Include(f => f.Recipients) .Include(f => f.Recipients)
.Where(f => f.Status == Shared.Models.FundStatus.Created || f.Status == Shared.Models.FundStatus.PartiallyReceived) .Where(f => f.Status == Shared.Models.FundStatus.Created ||
f.Status == Shared.Models.FundStatus.PartiallyReceived)
.Where(f => f.ExpiredAt < now) .Where(f => f.ExpiredAt < now)
.ToListAsync(); .ToListAsync();
@@ -775,7 +778,8 @@ public class PaymentService(
return fund; return fund;
} }
public async Task<WalletOverview> GetWalletOverviewAsync(Guid accountId, DateTime? startDate = null, DateTime? endDate = null) public async Task<WalletOverview> GetWalletOverviewAsync(Guid accountId, DateTime? startDate = null,
DateTime? endDate = null)
{ {
var wallet = await wat.GetWalletAsync(accountId); var wallet = await wat.GetWalletAsync(accountId);
if (wallet == null) if (wallet == null)