Merge pull request #6412 from NicolasDorier/payreqfix

Fix: Payment Requests should show payments of invalid invoices
This commit is contained in:
Nicolas Dorier 2024-12-04 19:18:43 +09:00 committed by GitHub
commit 70f97382a4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 36 additions and 32 deletions

View file

@ -67,16 +67,14 @@ namespace BTCPayServer.PaymentRequest
var invoices = await _paymentRequestRepository.GetInvoicesForPaymentRequest(pr.Id); var invoices = await _paymentRequestRepository.GetInvoicesForPaymentRequest(pr.Id);
var contributions = _invoiceRepository.GetContributionsByPaymentMethodId(blob.Currency, invoices, true); var contributions = _invoiceRepository.GetContributionsByPaymentMethodId(blob.Currency, invoices, true);
if (contributions.Total >= blob.Amount) currentStatus =
{ (PaidEnough: contributions.Total >= blob.Amount,
currentStatus = contributions.TotalSettled >= blob.Amount SettledEnough: contributions.TotalSettled >= blob.Amount) switch
? Client.Models.PaymentRequestData.PaymentRequestStatus.Completed {
: Client.Models.PaymentRequestData.PaymentRequestStatus.Processing; { SettledEnough: true } => Client.Models.PaymentRequestData.PaymentRequestStatus.Completed,
} { PaidEnough: true } => Client.Models.PaymentRequestData.PaymentRequestStatus.Processing,
else _ => Client.Models.PaymentRequestData.PaymentRequestStatus.Pending
{ };
currentStatus = Client.Models.PaymentRequestData.PaymentRequestStatus.Pending;
}
} }
if (currentStatus != pr.Status) if (currentStatus != pr.Status)
@ -100,7 +98,7 @@ namespace BTCPayServer.PaymentRequest
var amountDue = blob.Amount - paymentStats.Total; var amountDue = blob.Amount - paymentStats.Total;
var pendingInvoice = invoices.OrderByDescending(entity => entity.InvoiceTime) var pendingInvoice = invoices.OrderByDescending(entity => entity.InvoiceTime)
.FirstOrDefault(entity => entity.Status == InvoiceStatus.New); .FirstOrDefault(entity => entity.Status == InvoiceStatus.New);
return new ViewPaymentRequestViewModel(pr) return new ViewPaymentRequestViewModel(pr)
{ {
Archived = pr.Archived, Archived = pr.Archived,
@ -121,8 +119,7 @@ namespace BTCPayServer.PaymentRequest
var state = entity.GetInvoiceState(); var state = entity.GetInvoiceState();
var payments = ViewPaymentRequestViewModel.PaymentRequestInvoicePayment.GetViewModels(entity, _displayFormatter, _transactionLinkProviders, _handlers); var payments = ViewPaymentRequestViewModel.PaymentRequestInvoicePayment.GetViewModels(entity, _displayFormatter, _transactionLinkProviders, _handlers);
if (state.Status == InvoiceStatus.Invalid || if (state.Status is InvoiceStatus.Invalid or InvoiceStatus.Expired && payments.Count is 0)
state.Status == InvoiceStatus.Expired && !payments.Any())
return null; return null;
return new ViewPaymentRequestViewModel.PaymentRequestInvoice return new ViewPaymentRequestViewModel.PaymentRequestInvoice

View file

@ -267,9 +267,9 @@ namespace BTCPayServer.Services.Invoices
} }
public const int InternalTagSupport_Version = 1; public const int InternalTagSupport_Version = 1;
public const int GreenfieldInvoices_Version = 2; public const int GreenfieldInvoices_Version = 2;
public const int LeanInvoices_Version = 3; public const int LeanInvoices_Version = 3;
public const int Lastest_Version = 3; public const int Lastest_Version = 3;
public int Version { get; set; } public int Version { get; set; }
[JsonIgnore] [JsonIgnore]
public string Id { get; set; } public string Id { get; set; }
[JsonIgnore] [JsonIgnore]
@ -349,7 +349,7 @@ namespace BTCPayServer.Services.Invoices
ArgumentNullException.ThrowIfNull(pair); ArgumentNullException.ThrowIfNull(pair);
#pragma warning disable CS0618 // Type or member is obsolete #pragma warning disable CS0618 // Type or member is obsolete
if (pair.Right == Currency && Rates.TryGetValue(pair.Left, out var rate)) // Fast lane if (pair.Right == Currency && Rates.TryGetValue(pair.Left, out var rate)) // Fast lane
return rate; return rate;
#pragma warning restore CS0618 // Type or member is obsolete #pragma warning restore CS0618 // Type or member is obsolete
var rule = GetRateRules().GetRuleFor(pair); var rule = GetRateRules().GetRuleFor(pair);
rule.Reevaluate(); rule.Reevaluate();
@ -802,33 +802,40 @@ namespace BTCPayServer.Services.Invoices
} }
public record InvoiceState(InvoiceStatus Status, InvoiceExceptionStatus ExceptionStatus) public record InvoiceState(InvoiceStatus Status, InvoiceExceptionStatus ExceptionStatus)
{ {
public InvoiceState(string status, string exceptionStatus): public InvoiceState(string status, string exceptionStatus) :
this(Enum.Parse<InvoiceStatus>(status), exceptionStatus switch { "None" or "" or null => InvoiceExceptionStatus.None, _ => Enum.Parse<InvoiceExceptionStatus>(exceptionStatus) }) this(Enum.Parse<InvoiceStatus>(status), exceptionStatus switch { "None" or "" or null => InvoiceExceptionStatus.None, _ => Enum.Parse<InvoiceExceptionStatus>(exceptionStatus) })
{ {
} }
public bool CanMarkComplete() public bool CanMarkComplete() => (Status, ExceptionStatus) is
{ {
return Status is InvoiceStatus.New or InvoiceStatus.Processing or InvoiceStatus.Expired or InvoiceStatus.Invalid || Status: InvoiceStatus.New or InvoiceStatus.Processing or InvoiceStatus.Expired or InvoiceStatus.Invalid
(Status != InvoiceStatus.Settled && ExceptionStatus == InvoiceExceptionStatus.Marked);
} }
or
{
Status: not InvoiceStatus.Settled,
ExceptionStatus: InvoiceExceptionStatus.Marked
};
public bool CanMarkInvalid() public bool CanMarkInvalid() => (Status, ExceptionStatus) is
{ {
return Status is InvoiceStatus.New or InvoiceStatus.Processing or InvoiceStatus.Expired || Status: InvoiceStatus.New or InvoiceStatus.Processing or InvoiceStatus.Expired
(Status != InvoiceStatus.Invalid && ExceptionStatus == InvoiceExceptionStatus.Marked);
} }
or
{
Status: not InvoiceStatus.Invalid,
ExceptionStatus: InvoiceExceptionStatus.Marked
};
public bool CanRefund() public bool CanRefund() => (Status, ExceptionStatus) is
{ {
return Status: InvoiceStatus.Settled or InvoiceStatus.Invalid
Status == InvoiceStatus.Settled ||
(Status == InvoiceStatus.Expired &&
(ExceptionStatus == InvoiceExceptionStatus.PaidLate ||
ExceptionStatus == InvoiceExceptionStatus.PaidOver ||
ExceptionStatus == InvoiceExceptionStatus.PaidPartial)) ||
Status == InvoiceStatus.Invalid;
} }
or
{
Status: InvoiceStatus.Expired,
ExceptionStatus: InvoiceExceptionStatus.PaidLate or InvoiceExceptionStatus.PaidOver or InvoiceExceptionStatus.PaidPartial
};
public override string ToString() public override string ToString()
{ {