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

View file

@ -267,9 +267,9 @@ namespace BTCPayServer.Services.Invoices
}
public const int InternalTagSupport_Version = 1;
public const int GreenfieldInvoices_Version = 2;
public const int LeanInvoices_Version = 3;
public const int Lastest_Version = 3;
public int Version { get; set; }
public const int LeanInvoices_Version = 3;
public const int Lastest_Version = 3;
public int Version { get; set; }
[JsonIgnore]
public string Id { get; set; }
[JsonIgnore]
@ -349,7 +349,7 @@ namespace BTCPayServer.Services.Invoices
ArgumentNullException.ThrowIfNull(pair);
#pragma warning disable CS0618 // Type or member is obsolete
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
var rule = GetRateRules().GetRuleFor(pair);
rule.Reevaluate();
@ -802,33 +802,40 @@ namespace BTCPayServer.Services.Invoices
}
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) })
{
}
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.Settled && ExceptionStatus == InvoiceExceptionStatus.Marked);
Status: InvoiceStatus.New or InvoiceStatus.Processing or InvoiceStatus.Expired or InvoiceStatus.Invalid
}
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.Invalid && ExceptionStatus == InvoiceExceptionStatus.Marked);
Status: InvoiceStatus.New or InvoiceStatus.Processing or InvoiceStatus.Expired
}
or
{
Status: not InvoiceStatus.Invalid,
ExceptionStatus: InvoiceExceptionStatus.Marked
};
public bool CanRefund()
public bool CanRefund() => (Status, ExceptionStatus) is
{
return
Status == InvoiceStatus.Settled ||
(Status == InvoiceStatus.Expired &&
(ExceptionStatus == InvoiceExceptionStatus.PaidLate ||
ExceptionStatus == InvoiceExceptionStatus.PaidOver ||
ExceptionStatus == InvoiceExceptionStatus.PaidPartial)) ||
Status == InvoiceStatus.Invalid;
Status: InvoiceStatus.Settled or InvoiceStatus.Invalid
}
or
{
Status: InvoiceStatus.Expired,
ExceptionStatus: InvoiceExceptionStatus.PaidLate or InvoiceExceptionStatus.PaidOver or InvoiceExceptionStatus.PaidPartial
};
public override string ToString()
{