Remove Legacy Status from the code (#5982)

This commit is contained in:
Nicolas Dorier
2024-05-15 07:49:53 +09:00
committed by GitHub
parent d96b066658
commit c134602cbd
40 changed files with 218 additions and 309 deletions

View File

@@ -5,7 +5,6 @@ public enum InvoiceExceptionStatus
PaidLate, PaidLate,
PaidPartial, PaidPartial,
Marked, Marked,
Invalid,
PaidOver PaidOver
} }

View File

@@ -349,7 +349,24 @@ namespace BTCPayServer.Data
if (blob["defaultPaymentMethod"] is not (null or { Type : JTokenType.Null })) if (blob["defaultPaymentMethod"] is not (null or { Type : JTokenType.Null }))
blob["defaultPaymentMethod"] = MigrationExtensions.MigratePaymentMethodId(blob["defaultPaymentMethod"].Value<string>()); blob["defaultPaymentMethod"] = MigrationExtensions.MigratePaymentMethodId(blob["defaultPaymentMethod"].Value<string>());
blob.Remove("derivationStrategies"); blob.Remove("derivationStrategies");
Status = Status switch
{
"new" => "New",
"paid" => "Processing",
"complete" or "confirmed" => "Settled",
"expired" => "Expired",
null or "invalid" => "Invalid",
_ => throw new NotSupportedException($"Unknown Status for invoice ({Status})")
};
ExceptionStatus = ExceptionStatus switch
{
"marked" => "Marked",
"paidLate" => "PaidLate",
"paidPartial" => "PaidPartial",
"paidOver" => "PaidOver",
null or "" => "",
_ => throw new NotSupportedException($"Unknown ExceptionStatus for invoice ({ExceptionStatus})")
};
blob["version"] = 3; blob["version"] = 3;
Blob2 = blob.ToString(Formatting.None); Blob2 = blob.ToString(Formatting.None);
} }

View File

@@ -3,14 +3,9 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Security.Cryptography;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using BTCPayServer.Rating; using BTCPayServer.Rating;
using BTCPayServer.Rating.Providers;
using ExchangeSharp;
using NBitcoin;
using Newtonsoft.Json.Linq;
namespace BTCPayServer.Services.Rates namespace BTCPayServer.Services.Rates
{ {

View File

@@ -336,7 +336,7 @@ namespace BTCPayServer.Tests
Assert.Equal("paid", invoice.Status); Assert.Equal("paid", invoice.Status);
checkout = (Models.InvoicingModels.PaymentModel)((JsonResult)controller.GetStatus(invoice.Id) checkout = (Models.InvoicingModels.PaymentModel)((JsonResult)controller.GetStatus(invoice.Id)
.GetAwaiter().GetResult()).Value; .GetAwaiter().GetResult()).Value;
Assert.Equal("paid", checkout.Status); Assert.Equal("Processing", checkout.Status);
}); });
} }
} }

View File

@@ -285,7 +285,7 @@ namespace BTCPayServer.Tests
await TestUtils.EventuallyAsync(async () => await TestUtils.EventuallyAsync(async () =>
{ {
var invoice = await invoiceRepository.GetInvoice(invoiceId); var invoice = await invoiceRepository.GetInvoice(invoiceId);
Assert.Equal(InvoiceStatusLegacy.Paid, invoice.Status); Assert.Equal(InvoiceStatus.Processing, invoice.Status);
Assert.Equal(0.023m, invoice.Price); Assert.Equal(0.023m, invoice.Price);
}); });
} }
@@ -344,7 +344,7 @@ namespace BTCPayServer.Tests
await TestUtils.EventuallyAsync(async () => await TestUtils.EventuallyAsync(async () =>
{ {
var invoice = await s.Server.PayTester.GetService<InvoiceRepository>().GetInvoice(invoiceId); var invoice = await s.Server.PayTester.GetService<InvoiceRepository>().GetInvoice(invoiceId);
Assert.Equal(InvoiceStatusLegacy.Paid, invoice.Status); Assert.Equal(InvoiceStatus.Processing, invoice.Status);
}); });
s.SelectStoreContext(receiver.storeId); s.SelectStoreContext(receiver.storeId);
@@ -396,7 +396,7 @@ namespace BTCPayServer.Tests
await TestUtils.EventuallyAsync(async () => await TestUtils.EventuallyAsync(async () =>
{ {
var invoice = await s.Server.PayTester.GetService<InvoiceRepository>().GetInvoice(invoiceId); var invoice = await s.Server.PayTester.GetService<InvoiceRepository>().GetInvoice(invoiceId);
Assert.Equal(InvoiceStatusLegacy.Paid, invoice.Status); Assert.Equal(InvoiceStatus.Processing, invoice.Status);
}); });
s.GoToInvoices(receiver.storeId); s.GoToInvoices(receiver.storeId);
paymentValueRowColumn = s.Driver.FindElement(By.Id($"invoice_details_{invoiceId}")) paymentValueRowColumn = s.Driver.FindElement(By.Id($"invoice_details_{invoiceId}"))
@@ -790,7 +790,7 @@ retry:
await TestUtils.EventuallyAsync(async () => await TestUtils.EventuallyAsync(async () =>
{ {
var invoice = await tester.PayTester.GetService<InvoiceRepository>().GetInvoice(lastInvoiceId); var invoice = await tester.PayTester.GetService<InvoiceRepository>().GetInvoice(lastInvoiceId);
Assert.Equal(InvoiceStatusLegacy.Paid, invoice.Status); Assert.Equal(InvoiceStatus.Processing, invoice.Status);
Assert.Equal(InvoiceExceptionStatus.None, invoice.ExceptionStatus); Assert.Equal(InvoiceExceptionStatus.None, invoice.ExceptionStatus);
var coins = await btcPayWallet.GetUnspentCoins(receiverUser.DerivationScheme); var coins = await btcPayWallet.GetUnspentCoins(receiverUser.DerivationScheme);
foreach (var coin in coins) foreach (var coin in coins)
@@ -1131,7 +1131,7 @@ retry:
await TestUtils.EventuallyAsync(async () => await TestUtils.EventuallyAsync(async () =>
{ {
var invoiceEntity = await tester.PayTester.GetService<InvoiceRepository>().GetInvoice(invoice7.Id); var invoiceEntity = await tester.PayTester.GetService<InvoiceRepository>().GetInvoice(invoice7.Id);
Assert.Equal(InvoiceStatusLegacy.Paid, invoiceEntity.Status); Assert.Equal(InvoiceStatus.Processing, invoiceEntity.Status);
Assert.Contains(invoiceEntity.GetPayments(false), p => p.Accounted && Assert.Contains(invoiceEntity.GetPayments(false), p => p.Accounted &&
handler.ParsePaymentDetails(p.Details).PayjoinInformation is null); handler.ParsePaymentDetails(p.Details).PayjoinInformation is null);
}); });
@@ -1160,7 +1160,7 @@ retry:
await TestUtils.EventuallyAsync(async () => await TestUtils.EventuallyAsync(async () =>
{ {
var invoiceEntity = await tester.PayTester.GetService<InvoiceRepository>().GetInvoice(invoice7.Id); var invoiceEntity = await tester.PayTester.GetService<InvoiceRepository>().GetInvoice(invoice7.Id);
Assert.Equal(InvoiceStatusLegacy.New, invoiceEntity.Status); Assert.Equal(InvoiceStatus.New, invoiceEntity.Status);
Assert.True(invoiceEntity.GetPayments(false).All(p => !p.Accounted)); Assert.True(invoiceEntity.GetPayments(false).All(p => !p.Accounted));
ourOutpoint = invoiceEntity.GetAllBitcoinPaymentData(handler, false).First().PayjoinInformation.ContributedOutPoints[0]; ourOutpoint = invoiceEntity.GetAllBitcoinPaymentData(handler, false).First().PayjoinInformation.ContributedOutPoints[0];
}); });

View File

@@ -208,12 +208,12 @@ namespace BTCPayServer.Tests
pair => pair.Key == "Id" && pair.Value.ToString() == invoiceId); pair => pair.Key == "Id" && pair.Value.ToString() == invoiceId);
var invoice = user.BitPay.GetInvoice(invoiceId, Facade.Merchant); var invoice = user.BitPay.GetInvoice(invoiceId, Facade.Merchant);
Assert.Equal(InvoiceState.ToString(InvoiceStatusLegacy.New), invoice.Status); Assert.Equal("new", invoice.Status);
Assert.IsType<OkObjectResult>(await Assert.IsType<OkObjectResult>(await
paymentRequestController.CancelUnpaidPendingInvoice(paymentRequestId, false)); paymentRequestController.CancelUnpaidPendingInvoice(paymentRequestId, false));
invoice = user.BitPay.GetInvoice(invoiceId, Facade.Merchant); invoice = user.BitPay.GetInvoice(invoiceId, Facade.Merchant);
Assert.Equal(InvoiceState.ToString(InvoiceStatusLegacy.Invalid), invoice.Status); Assert.Equal("invalid", invoice.Status);
Assert.IsType<BadRequestObjectResult>(await Assert.IsType<BadRequestObjectResult>(await
paymentRequestController.CancelUnpaidPendingInvoice(paymentRequestId, false)); paymentRequestController.CancelUnpaidPendingInvoice(paymentRequestId, false));

View File

@@ -2988,7 +2988,7 @@ namespace BTCPayServer.Tests
await TestUtils.EventuallyAsync(async () => await TestUtils.EventuallyAsync(async () =>
{ {
var inv = await s.Server.PayTester.InvoiceRepository.GetInvoice(i); var inv = await s.Server.PayTester.InvoiceRepository.GetInvoice(i);
Assert.Equal(InvoiceStatusLegacy.Complete, inv.Status); Assert.Equal(InvoiceStatus.Settled, inv.Status);
}); });
var greenfield = await s.AsTestAccount().CreateClient(); var greenfield = await s.AsTestAccount().CreateClient();
var paymentMethods = await greenfield.GetInvoicePaymentMethods(s.StoreId, i); var paymentMethods = await greenfield.GetInvoicePaymentMethods(s.StoreId, i);
@@ -3110,7 +3110,7 @@ namespace BTCPayServer.Tests
await TestUtils.EventuallyAsync(async () => await TestUtils.EventuallyAsync(async () =>
{ {
var inv = await s.Server.PayTester.InvoiceRepository.GetInvoice(invForPP); var inv = await s.Server.PayTester.InvoiceRepository.GetInvoice(invForPP);
Assert.Equal(InvoiceStatusLegacy.Complete, inv.Status); Assert.Equal(InvoiceStatus.Settled, inv.Status);
await using var ctx = s.Server.PayTester.GetService<ApplicationDbContextFactory>().CreateContext(); await using var ctx = s.Server.PayTester.GetService<ApplicationDbContextFactory>().CreateContext();
var payoutsData = await ctx.Payouts.Where(p => p.PullPaymentDataId == pullPaymentId).ToListAsync(); var payoutsData = await ctx.Payouts.Where(p => p.PullPaymentDataId == pullPaymentId).ToListAsync();

View File

@@ -409,7 +409,7 @@ namespace BTCPayServer.Tests
}, evt => evt.InvoiceId == invoice.Id); }, evt => evt.InvoiceId == invoice.Id);
var fetchedInvoice = await tester.PayTester.InvoiceRepository.GetInvoice(evt.InvoiceId); var fetchedInvoice = await tester.PayTester.InvoiceRepository.GetInvoice(evt.InvoiceId);
Assert.Contains(fetchedInvoice.Status, new[] { InvoiceStatusLegacy.Complete, InvoiceStatusLegacy.Confirmed }); Assert.Equal(fetchedInvoice.Status, InvoiceStatus.Settled);
Assert.Equal(InvoiceExceptionStatus.None, fetchedInvoice.ExceptionStatus); Assert.Equal(InvoiceExceptionStatus.None, fetchedInvoice.ExceptionStatus);
//BTCPay will attempt to cancel previous bolt11 invoices so that there are less weird edge case scenarios //BTCPay will attempt to cancel previous bolt11 invoices so that there are less weird edge case scenarios
@@ -1018,7 +1018,7 @@ namespace BTCPayServer.Tests
await TestUtils.EventuallyAsync(async () => await TestUtils.EventuallyAsync(async () =>
{ {
var i = await tester.PayTester.InvoiceRepository.GetInvoice(invoice2.Id); var i = await tester.PayTester.InvoiceRepository.GetInvoice(invoice2.Id);
Assert.Equal(InvoiceStatusLegacy.New, i.Status); Assert.Equal(InvoiceStatus.New, i.Status);
Assert.Single(i.GetPayments(false)); Assert.Single(i.GetPayments(false));
Assert.False(i.GetPayments(false).First().Accounted); Assert.False(i.GetPayments(false).First().Accounted);
}); });

View File

@@ -6,7 +6,7 @@
@{ @{
var state = Model.State.ToString(); var state = Model.State.ToString();
var badgeClass = Model.State.Status.ToModernStatus().ToString().ToLower(); var badgeClass = Model.State.Status.ToString().ToLower();
var canMark = !string.IsNullOrEmpty(Model.InvoiceId) && (Model.State.CanMarkComplete() || Model.State.CanMarkInvalid()); var canMark = !string.IsNullOrEmpty(Model.InvoiceId) && (Model.State.CanMarkComplete() || Model.State.CanMarkInvalid());
} }
<div class="d-inline-flex align-items-center gap-2"> <div class="d-inline-flex align-items-center gap-2">

View File

@@ -670,7 +670,7 @@ namespace BTCPayServer.Controllers.Greenfield
Type = entity.Type, Type = entity.Type,
Id = entity.Id, Id = entity.Id,
CheckoutLink = request is null ? null : linkGenerator.CheckoutLink(entity.Id, request.Scheme, request.Host, request.PathBase), CheckoutLink = request is null ? null : linkGenerator.CheckoutLink(entity.Id, request.Scheme, request.Host, request.PathBase),
Status = entity.Status.ToModernStatus(), Status = entity.Status,
AdditionalStatus = entity.ExceptionStatus, AdditionalStatus = entity.ExceptionStatus,
Currency = entity.Currency, Currency = entity.Currency,
Archived = entity.Archived, Archived = entity.Archived,

View File

@@ -13,7 +13,6 @@ using BTCPayServer.Payments;
using BTCPayServer.Payments.Lightning; using BTCPayServer.Payments.Lightning;
using BTCPayServer.Services; using BTCPayServer.Services;
using BTCPayServer.Services.Invoices; using BTCPayServer.Services.Invoices;
using ExchangeSharp;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;

View File

@@ -150,8 +150,8 @@ namespace BTCPayServer.Controllers
HasRefund = invoice.Refunds.Any(), HasRefund = invoice.Refunds.Any(),
CanRefund = invoiceState.CanRefund(), CanRefund = invoiceState.CanRefund(),
Refunds = invoice.Refunds, Refunds = invoice.Refunds,
ShowCheckout = invoice.Status == InvoiceStatusLegacy.New, ShowCheckout = invoice.Status == InvoiceStatus.New,
ShowReceipt = invoice.Status.ToModernStatus() == InvoiceStatus.Settled && (invoice.ReceiptOptions?.Enabled ?? receipt.Enabled is true), ShowReceipt = invoice.Status == InvoiceStatus.Settled && (invoice.ReceiptOptions?.Enabled ?? receipt.Enabled is true),
Deliveries = (await _InvoiceRepository.GetWebhookDeliveries(invoiceId)) Deliveries = (await _InvoiceRepository.GetWebhookDeliveries(invoiceId))
.Select(c => new Models.StoreViewModels.DeliveryViewModel(c)) .Select(c => new Models.StoreViewModels.DeliveryViewModel(c))
.ToList() .ToList()
@@ -215,7 +215,7 @@ namespace BTCPayServer.Controllers
InvoiceId = i.Id, InvoiceId = i.Id,
OrderId = i.Metadata?.OrderId, OrderId = i.Metadata?.OrderId,
OrderUrl = i.Metadata?.OrderUrl, OrderUrl = i.Metadata?.OrderUrl,
Status = i.Status.ToModernStatus(), Status = i.Status,
Currency = i.Currency, Currency = i.Currency,
Timestamp = i.InvoiceTime, Timestamp = i.InvoiceTime,
StoreName = store.StoreName, StoreName = store.StoreName,
@@ -223,7 +223,7 @@ namespace BTCPayServer.Controllers
ReceiptOptions = receipt ReceiptOptions = receipt
}; };
if (i.Status.ToModernStatus() != InvoiceStatus.Settled) if (i.Status != InvoiceStatus.Settled)
{ {
return View(vm); return View(vm);
} }
@@ -929,9 +929,7 @@ namespace BTCPayServer.Controllers
_ => null _ => null
}, },
ReceivedConfirmations = handler is BitcoinLikePaymentHandler bh ? invoice.GetAllBitcoinPaymentData(bh, false).FirstOrDefault()?.ConfirmationCount : null, ReceivedConfirmations = handler is BitcoinLikePaymentHandler bh ? invoice.GetAllBitcoinPaymentData(bh, false).FirstOrDefault()?.ConfirmationCount : null,
#pragma warning disable CS0618 // Type or member is obsolete Status = invoice.Status.ToString(),
Status = invoice.StatusString,
#pragma warning restore CS0618 // Type or member is obsolete
NetworkFee = prompt.PaymentMethodFee, NetworkFee = prompt.PaymentMethodFee,
IsMultiCurrency = invoice.GetPayments(false).Select(p => p.PaymentMethodId).Concat(new[] { prompt.PaymentMethodId }).Distinct().Count() > 1, IsMultiCurrency = invoice.GetPayments(false).Select(p => p.PaymentMethodId).Concat(new[] { prompt.PaymentMethodId }).Distinct().Count() > 1,
StoreId = store.Id, StoreId = store.Id,
@@ -1038,7 +1036,7 @@ namespace BTCPayServer.Controllers
if (!HttpContext.WebSockets.IsWebSocketRequest) if (!HttpContext.WebSockets.IsWebSocketRequest)
return NotFound(); return NotFound();
var invoice = await _InvoiceRepository.GetInvoice(invoiceId); var invoice = await _InvoiceRepository.GetInvoice(invoiceId);
if (invoice == null || invoice.Status == InvoiceStatusLegacy.Complete || invoice.Status == InvoiceStatusLegacy.Invalid || invoice.Status == InvoiceStatusLegacy.Expired) if (invoice == null || invoice.Status == InvoiceStatus.Settled || invoice.Status == InvoiceStatus.Invalid || invoice.Status == InvoiceStatus.Expired)
return NotFound(); return NotFound();
var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync(); var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync();
CompositeDisposable leases = new CompositeDisposable(); CompositeDisposable leases = new CompositeDisposable();
@@ -1138,7 +1136,7 @@ namespace BTCPayServer.Controllers
model.Invoices.Add(new InvoiceModel model.Invoices.Add(new InvoiceModel
{ {
Status = state, Status = state,
ShowCheckout = invoice.Status == InvoiceStatusLegacy.New, ShowCheckout = invoice.Status == InvoiceStatus.New,
Date = invoice.InvoiceTime, Date = invoice.InvoiceTime,
InvoiceId = invoice.Id, InvoiceId = invoice.Id,
OrderId = invoice.Metadata.OrderId ?? string.Empty, OrderId = invoice.Metadata.OrderId ?? string.Empty,
@@ -1322,12 +1320,12 @@ namespace BTCPayServer.Controllers
if (newState == "invalid") if (newState == "invalid")
{ {
await _InvoiceRepository.MarkInvoiceStatus(invoiceId, InvoiceStatus.Invalid); await _InvoiceRepository.MarkInvoiceStatus(invoiceId, InvoiceStatus.Invalid);
model.StatusString = new InvoiceState(InvoiceStatusLegacy.Invalid, InvoiceExceptionStatus.Marked).ToString(); model.StatusString = new InvoiceState(InvoiceStatus.Invalid, InvoiceExceptionStatus.Marked).ToString();
} }
else if (newState == "settled") else if (newState == "settled")
{ {
await _InvoiceRepository.MarkInvoiceStatus(invoiceId, InvoiceStatus.Settled); await _InvoiceRepository.MarkInvoiceStatus(invoiceId, InvoiceStatus.Settled);
model.StatusString = new InvoiceState(InvoiceStatusLegacy.Complete, InvoiceExceptionStatus.Marked).ToString(); model.StatusString = new InvoiceState(InvoiceStatus.Settled, InvoiceExceptionStatus.Marked).ToString();
} }
return Json(model); return Json(model);

View File

@@ -235,7 +235,7 @@ namespace BTCPayServer.Controllers
} }
var getAppsTaggingStore = _InvoiceRepository.GetAppsTaggingStore(store.Id); var getAppsTaggingStore = _InvoiceRepository.GetAppsTaggingStore(store.Id);
entity.Status = InvoiceStatusLegacy.New; entity.Status = InvoiceStatus.New;
entity.UpdateTotals(); entity.UpdateTotals();

View File

@@ -656,7 +656,7 @@ namespace BTCPayServer
if (store is null) if (store is null)
return NotFound(); return NotFound();
if (i.Status == InvoiceStatusLegacy.New) if (i.Status == InvoiceStatus.New)
{ {
var pmi = GetLNUrlPaymentMethodId(cryptoCode, store, out var lnurlSupportedPaymentMethod); var pmi = GetLNUrlPaymentMethodId(cryptoCode, store, out var lnurlSupportedPaymentMethod);
if (pmi is null) if (pmi is null)

View File

@@ -392,7 +392,7 @@ namespace BTCPayServer.Controllers
} }
var invoices = result.Invoices.Where(requestInvoice => var invoices = result.Invoices.Where(requestInvoice =>
requestInvoice.State.Status == InvoiceStatusLegacy.New && !requestInvoice.Payments.Any()); requestInvoice.State.Status == InvoiceStatus.New && !requestInvoice.Payments.Any());
if (!invoices.Any()) if (!invoices.Any())
{ {

View File

@@ -60,7 +60,7 @@ namespace BTCPayServer.Data
} }
public static InvoiceState GetInvoiceState(this InvoiceData invoiceData) public static InvoiceState GetInvoiceState(this InvoiceData invoiceData)
{ {
return new InvoiceState(invoiceData.Status ?? "new", invoiceData.ExceptionStatus); return new InvoiceState(invoiceData.Status, invoiceData.ExceptionStatus);
} }
} }
} }

View File

@@ -5,6 +5,7 @@ using System.Net.Http;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using BTCPayServer.Client.Models;
using BTCPayServer.Events; using BTCPayServer.Events;
using BTCPayServer.Payments; using BTCPayServer.Payments;
using BTCPayServer.Services; using BTCPayServer.Services;
@@ -101,11 +102,11 @@ namespace BTCPayServer.HostedServices
// So here, we just override the status expressed by the notification // So here, we just override the status expressed by the notification
if (invoiceEvent.Name == InvoiceEvent.Confirmed) if (invoiceEvent.Name == InvoiceEvent.Confirmed)
{ {
notification.Data.Status = InvoiceState.ToString(InvoiceStatusLegacy.Confirmed); notification.Data.Status = "confirmed";
} }
if (invoiceEvent.Name == InvoiceEvent.PaidInFull) if (invoiceEvent.Name == InvoiceEvent.PaidInFull)
{ {
notification.Data.Status = InvoiceState.ToString(InvoiceStatusLegacy.Paid); notification.Data.Status = "paid";
} }
////////////////// //////////////////

View File

@@ -81,10 +81,10 @@ namespace BTCPayServer.HostedServices
private void UpdateInvoice(UpdateInvoiceContext context) private void UpdateInvoice(UpdateInvoiceContext context)
{ {
var invoice = context.Invoice; var invoice = context.Invoice;
if (invoice.Status == InvoiceStatusLegacy.New && invoice.ExpirationTime <= DateTimeOffset.UtcNow) if (invoice.Status == InvoiceStatus.New && invoice.ExpirationTime <= DateTimeOffset.UtcNow)
{ {
context.MarkDirty(); context.MarkDirty();
invoice.Status = InvoiceStatusLegacy.Expired; invoice.Status = InvoiceStatus.Expired;
var paidPartial = invoice.ExceptionStatus == InvoiceExceptionStatus.PaidPartial; var paidPartial = invoice.ExceptionStatus == InvoiceExceptionStatus.PaidPartial;
context.Events.Add(new InvoiceEvent(invoice, InvoiceEvent.Expired) { PaidPartial = paidPartial }); context.Events.Add(new InvoiceEvent(invoice, InvoiceEvent.Expired) { PaidPartial = paidPartial });
if (invoice.ExceptionStatus == InvoiceExceptionStatus.PaidPartial) if (invoice.ExceptionStatus == InvoiceExceptionStatus.PaidPartial)
@@ -92,17 +92,17 @@ namespace BTCPayServer.HostedServices
} }
var hasPayment = invoice.GetPayments(true).Any(); var hasPayment = invoice.GetPayments(true).Any();
if (invoice.Status == InvoiceStatusLegacy.New || invoice.Status == InvoiceStatusLegacy.Expired) if (invoice.Status == InvoiceStatus.New || invoice.Status == InvoiceStatus.Expired)
{ {
var isPaid = invoice.IsUnsetTopUp() ? var isPaid = invoice.IsUnsetTopUp() ?
hasPayment : hasPayment :
!invoice.IsUnderPaid; !invoice.IsUnderPaid;
if (isPaid) if (isPaid)
{ {
if (invoice.Status == InvoiceStatusLegacy.New) if (invoice.Status == InvoiceStatus.New)
{ {
context.Events.Add(new InvoiceEvent(invoice, InvoiceEvent.PaidInFull)); context.Events.Add(new InvoiceEvent(invoice, InvoiceEvent.PaidInFull));
invoice.Status = InvoiceStatusLegacy.Paid; invoice.Status = InvoiceStatus.Processing;
if (invoice.IsUnsetTopUp()) if (invoice.IsUnsetTopUp())
{ {
invoice.ExceptionStatus = InvoiceExceptionStatus.None; invoice.ExceptionStatus = InvoiceExceptionStatus.None;
@@ -118,7 +118,7 @@ namespace BTCPayServer.HostedServices
} }
context.MarkDirty(); context.MarkDirty();
} }
else if (invoice.Status == InvoiceStatusLegacy.Expired && invoice.ExceptionStatus != InvoiceExceptionStatus.PaidLate) else if (invoice.Status == InvoiceStatus.Expired && invoice.ExceptionStatus != InvoiceExceptionStatus.PaidLate)
{ {
invoice.ExceptionStatus = InvoiceExceptionStatus.PaidLate; invoice.ExceptionStatus = InvoiceExceptionStatus.PaidLate;
context.Events.Add(new InvoiceEvent(invoice, InvoiceEvent.PaidAfterExpiration)); context.Events.Add(new InvoiceEvent(invoice, InvoiceEvent.PaidAfterExpiration));
@@ -134,7 +134,7 @@ namespace BTCPayServer.HostedServices
} }
// Just make sure RBF did not cancelled a payment // Just make sure RBF did not cancelled a payment
if (invoice.Status == InvoiceStatusLegacy.Paid) if (invoice.Status == InvoiceStatus.Processing)
{ {
if (!invoice.IsUnderPaid && !invoice.IsOverPaid && invoice.ExceptionStatus == InvoiceExceptionStatus.PaidOver) if (!invoice.IsUnderPaid && !invoice.IsOverPaid && invoice.ExceptionStatus == InvoiceExceptionStatus.PaidOver)
{ {
@@ -150,13 +150,13 @@ namespace BTCPayServer.HostedServices
if (invoice.IsUnderPaid) if (invoice.IsUnderPaid)
{ {
invoice.Status = InvoiceStatusLegacy.New; invoice.Status = InvoiceStatus.New;
invoice.ExceptionStatus = hasPayment ? InvoiceExceptionStatus.PaidPartial : InvoiceExceptionStatus.None; invoice.ExceptionStatus = hasPayment ? InvoiceExceptionStatus.PaidPartial : InvoiceExceptionStatus.None;
context.MarkDirty(); context.MarkDirty();
} }
} }
if (invoice.Status == InvoiceStatusLegacy.Paid) if (invoice.Status == InvoiceStatus.Processing)
{ {
var unconfPayments = invoice.GetPayments(false).Where(p => p.Status is PaymentStatus.Processing).ToList(); var unconfPayments = invoice.GetPayments(false).Where(p => p.Status is PaymentStatus.Processing).ToList();
var unconfirmedPaid = unconfPayments.Select(p => p.InvoicePaidAmount.Net).Sum(); var unconfirmedPaid = unconfPayments.Select(p => p.InvoicePaidAmount.Net).Sum();
@@ -168,12 +168,12 @@ namespace BTCPayServer.HostedServices
(minimumDue > 0.0m)) (minimumDue > 0.0m))
{ {
context.Events.Add(new InvoiceEvent(invoice, InvoiceEvent.FailedToConfirm)); context.Events.Add(new InvoiceEvent(invoice, InvoiceEvent.FailedToConfirm));
invoice.Status = InvoiceStatusLegacy.Invalid; invoice.Status = InvoiceStatus.Invalid;
context.MarkDirty(); context.MarkDirty();
} }
else if (minimumDue <= 0.0m) else if (minimumDue <= 0.0m)
{ {
invoice.Status = InvoiceStatusLegacy.Complete; invoice.Status = InvoiceStatus.Settled;
context.Events.Add(new InvoiceEvent(invoice, InvoiceEvent.Confirmed)); context.Events.Add(new InvoiceEvent(invoice, InvoiceEvent.Confirmed));
context.Events.Add(new InvoiceEvent(invoice, InvoiceEvent.Completed)); context.Events.Add(new InvoiceEvent(invoice, InvoiceEvent.Completed));
context.MarkDirty(); context.MarkDirty();
@@ -292,8 +292,8 @@ namespace BTCPayServer.HostedServices
_eventAggregator.Publish(evt, evt.GetType()); _eventAggregator.Publish(evt, evt.GetType());
} }
if (invoice.Status == InvoiceStatusLegacy.Complete || if (invoice.Status == InvoiceStatus.Settled ||
((invoice.Status == InvoiceStatusLegacy.Invalid || invoice.Status == InvoiceStatusLegacy.Expired) && invoice.MonitoringExpiration < DateTimeOffset.UtcNow)) ((invoice.Status == InvoiceStatus.Invalid || invoice.Status == InvoiceStatus.Expired) && invoice.MonitoringExpiration < DateTimeOffset.UtcNow))
{ {
var extendInvoiceMonitoring = await UpdateConfirmationCount(invoice); var extendInvoiceMonitoring = await UpdateConfirmationCount(invoice);

View File

@@ -97,8 +97,8 @@ public class InvoiceWebhookProvider : WebhookProvider<InvoiceEvent>
return new WebhookInvoiceReceivedPaymentEvent(WebhookEventType.InvoiceReceivedPayment, storeId) return new WebhookInvoiceReceivedPaymentEvent(WebhookEventType.InvoiceReceivedPayment, storeId)
{ {
AfterExpiration = AfterExpiration =
invoiceEvent.Invoice.Status.ToModernStatus() == InvoiceStatus.Expired || invoiceEvent.Invoice.Status == InvoiceStatus.Expired ||
invoiceEvent.Invoice.Status.ToModernStatus() == InvoiceStatus.Invalid, invoiceEvent.Invoice.Status == InvoiceStatus.Invalid,
PaymentMethodId = invoiceEvent.Payment.PaymentMethodId.ToString(), PaymentMethodId = invoiceEvent.Payment.PaymentMethodId.ToString(),
Payment = GreenfieldInvoiceController.ToPaymentModel(invoiceEvent.Invoice, invoiceEvent.Payment), Payment = GreenfieldInvoiceController.ToPaymentModel(invoiceEvent.Invoice, invoiceEvent.Payment),
StoreId = invoiceEvent.Invoice.StoreId StoreId = invoiceEvent.Invoice.StoreId
@@ -107,8 +107,8 @@ public class InvoiceWebhookProvider : WebhookProvider<InvoiceEvent>
return new WebhookInvoiceReceivedPaymentEvent(WebhookEventType.InvoicePaymentSettled, storeId) return new WebhookInvoiceReceivedPaymentEvent(WebhookEventType.InvoicePaymentSettled, storeId)
{ {
AfterExpiration = AfterExpiration =
invoiceEvent.Invoice.Status.ToModernStatus() == InvoiceStatus.Expired || invoiceEvent.Invoice.Status == InvoiceStatus.Expired ||
invoiceEvent.Invoice.Status.ToModernStatus() == InvoiceStatus.Invalid, invoiceEvent.Invoice.Status == InvoiceStatus.Invalid,
PaymentMethodId = invoiceEvent.Payment.PaymentMethodId.ToString(), PaymentMethodId = invoiceEvent.Payment.PaymentMethodId.ToString(),
Payment = GreenfieldInvoiceController.ToPaymentModel(invoiceEvent.Invoice, invoiceEvent.Payment), Payment = GreenfieldInvoiceController.ToPaymentModel(invoiceEvent.Invoice, invoiceEvent.Payment),
StoreId = invoiceEvent.Invoice.StoreId StoreId = invoiceEvent.Invoice.StoreId

View File

@@ -48,7 +48,6 @@ using BTCPayServer.Services.PaymentRequests;
using BTCPayServer.Services.Rates; using BTCPayServer.Services.Rates;
using BTCPayServer.Services.Stores; using BTCPayServer.Services.Stores;
using BTCPayServer.Services.Wallets; using BTCPayServer.Services.Wallets;
using ExchangeSharp;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
@@ -71,6 +70,8 @@ using BTCPayServer.Services.WalletFileParsing;
using BTCPayServer.Payments.LNURLPay; using BTCPayServer.Payments.LNURLPay;
using System.Collections.Generic; using System.Collections.Generic;
using BTCPayServer.Payouts; using BTCPayServer.Payouts;
using ExchangeSharp;
@@ -658,7 +659,7 @@ o.GetRequiredService<IEnumerable<IPaymentLinkExtension>>().ToDictionary(o => o.P
{ {
services.AddSingleton<TransactionLinkProviders.Entry>(new TransactionLinkProviders.Entry(cryptoCode, provider)); services.AddSingleton<TransactionLinkProviders.Entry>(new TransactionLinkProviders.Entry(cryptoCode, provider));
} }
public static void AddRateProviderExchangeSharp<T>(this IServiceCollection services, RateSourceInfo rateInfo) where T : ExchangeAPI public static void AddRateProviderExchangeSharp<T>(this IServiceCollection services, RateSourceInfo rateInfo) where T : ExchangeSharp.ExchangeAPI
{ {
services.AddSingleton<IRateProvider, ExchangeSharpRateProvider<T>>(o => services.AddSingleton<IRateProvider, ExchangeSharpRateProvider<T>>(o =>
{ {

View File

@@ -149,8 +149,8 @@ namespace BTCPayServer.Models.PaymentRequestViewModels
{ {
static HashSet<InvoiceState> stateAllowedToDisplay = new HashSet<InvoiceState> static HashSet<InvoiceState> stateAllowedToDisplay = new HashSet<InvoiceState>
{ {
new InvoiceState(InvoiceStatusLegacy.New, InvoiceExceptionStatus.None), new InvoiceState(InvoiceStatus.New, InvoiceExceptionStatus.None),
new InvoiceState(InvoiceStatusLegacy.New, InvoiceExceptionStatus.PaidPartial), new InvoiceState(InvoiceStatus.New, InvoiceExceptionStatus.PaidPartial),
}; };
public InvoiceList() public InvoiceList()
{ {
@@ -187,7 +187,6 @@ namespace BTCPayServer.Models.PaymentRequestViewModels
public decimal Amount { get; set; } public decimal Amount { get; set; }
public string AmountFormatted { get; set; } public string AmountFormatted { get; set; }
public InvoiceState State { get; set; } public InvoiceState State { get; set; }
public InvoiceStatusLegacy Status { get; set; }
public string StateFormatted { get; set; } public string StateFormatted { get; set; }
public List<PaymentRequestInvoicePayment> Payments { get; set; } public List<PaymentRequestInvoicePayment> Payments { get; set; }

View File

@@ -101,7 +101,7 @@ namespace BTCPayServer.PaymentRequest
var paymentStats = _invoiceRepository.GetContributionsByPaymentMethodId(blob.Currency, invoices, true); var paymentStats = _invoiceRepository.GetContributionsByPaymentMethodId(blob.Currency, invoices, true);
var amountDue = blob.Amount - paymentStats.TotalCurrency; var amountDue = blob.Amount - paymentStats.TotalCurrency;
var pendingInvoice = invoices.OrderByDescending(entity => entity.InvoiceTime) var pendingInvoice = invoices.OrderByDescending(entity => entity.InvoiceTime)
.FirstOrDefault(entity => entity.Status == InvoiceStatusLegacy.New); .FirstOrDefault(entity => entity.Status == InvoiceStatus.New);
return new ViewPaymentRequestViewModel(pr) return new ViewPaymentRequestViewModel(pr)
{ {
@@ -123,8 +123,8 @@ 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 == InvoiceStatusLegacy.Invalid || if (state.Status == InvoiceStatus.Invalid ||
state.Status == InvoiceStatusLegacy.Expired && !payments.Any()) state.Status == InvoiceStatus.Expired && !payments.Any())
return null; return null;
return new ViewPaymentRequestViewModel.PaymentRequestInvoice return new ViewPaymentRequestViewModel.PaymentRequestInvoice

View File

@@ -202,7 +202,7 @@ retry:
_CheckInvoices.Writer.TryWrite(inv.Invoice.Id); _CheckInvoices.Writer.TryWrite(inv.Invoice.Id);
} }
if (inv.Name == InvoiceEvent.ReceivedPayment && inv.Invoice.Status == InvoiceStatusLegacy.New && inv.Invoice.ExceptionStatus == InvoiceExceptionStatus.PaidPartial) if (inv.Name == InvoiceEvent.ReceivedPayment && inv.Invoice.Status == InvoiceStatus.New && inv.Invoice.ExceptionStatus == InvoiceExceptionStatus.PaidPartial)
{ {
var pm = inv.Invoice.GetPaymentPrompts().First(); var pm = inv.Invoice.GetPaymentPrompts().First();
if (pm.Calculate().Due > 0m) if (pm.Calculate().Due > 0m)
@@ -213,7 +213,7 @@ retry:
})); }));
leases.Add(_Aggregator.SubscribeAsync<Events.InvoiceDataChangedEvent>(async inv => leases.Add(_Aggregator.SubscribeAsync<Events.InvoiceDataChangedEvent>(async inv =>
{ {
if (inv.State.Status == InvoiceStatusLegacy.New && if (inv.State.Status == InvoiceStatus.New &&
inv.State.ExceptionStatus == InvoiceExceptionStatus.PaidPartial) inv.State.ExceptionStatus == InvoiceExceptionStatus.PaidPartial)
{ {
var invoice = await _InvoiceRepository.GetInvoice(inv.InvoiceId); var invoice = await _InvoiceRepository.GetInvoice(inv.InvoiceId);

View File

@@ -6,6 +6,7 @@ using System.Threading.Tasks;
using BTCPayServer.Abstractions.Contracts; using BTCPayServer.Abstractions.Contracts;
using BTCPayServer.Abstractions.Models; using BTCPayServer.Abstractions.Models;
using BTCPayServer.Abstractions.Services; using BTCPayServer.Abstractions.Services;
using BTCPayServer.Client.Models;
using BTCPayServer.Configuration; using BTCPayServer.Configuration;
using BTCPayServer.Data; using BTCPayServer.Data;
using BTCPayServer.Models; using BTCPayServer.Models;
@@ -113,10 +114,10 @@ namespace BTCPayServer.Plugins.Crowdfund
public override async Task<object?> GetInfo(AppData appData) public override async Task<object?> GetInfo(AppData appData)
{ {
var settings = appData.GetSettings<CrowdfundSettings>(); var settings = appData.GetSettings<CrowdfundSettings>();
var resetEvery = settings.StartDate.HasValue ? settings.ResetEvery : CrowdfundResetEvery.Never; var resetEvery = settings.StartDate.HasValue ? settings.ResetEvery : Services.Apps.CrowdfundResetEvery.Never;
DateTime? lastResetDate = null; DateTime? lastResetDate = null;
DateTime? nextResetDate = null; DateTime? nextResetDate = null;
if (resetEvery != CrowdfundResetEvery.Never && settings.StartDate is not null) if (resetEvery != Services.Apps.CrowdfundResetEvery.Never && settings.StartDate is not null)
{ {
lastResetDate = settings.StartDate.Value; lastResetDate = settings.StartDate.Value;
@@ -126,16 +127,16 @@ namespace BTCPayServer.Plugins.Crowdfund
lastResetDate = nextResetDate; lastResetDate = nextResetDate;
switch (resetEvery) switch (resetEvery)
{ {
case CrowdfundResetEvery.Hour: case Services.Apps.CrowdfundResetEvery.Hour:
nextResetDate = lastResetDate.Value.AddHours(settings.ResetEveryAmount); nextResetDate = lastResetDate.Value.AddHours(settings.ResetEveryAmount);
break; break;
case CrowdfundResetEvery.Day: case Services.Apps.CrowdfundResetEvery.Day:
nextResetDate = lastResetDate.Value.AddDays(settings.ResetEveryAmount); nextResetDate = lastResetDate.Value.AddDays(settings.ResetEveryAmount);
break; break;
case CrowdfundResetEvery.Month: case Services.Apps.CrowdfundResetEvery.Month:
nextResetDate = lastResetDate.Value.AddMonths(settings.ResetEveryAmount); nextResetDate = lastResetDate.Value.AddMonths(settings.ResetEveryAmount);
break; break;
case CrowdfundResetEvery.Year: case Services.Apps.CrowdfundResetEvery.Year:
nextResetDate = lastResetDate.Value.AddYears(settings.ResetEveryAmount); nextResetDate = lastResetDate.Value.AddYears(settings.ResetEveryAmount);
break; break;
} }
@@ -206,11 +207,11 @@ namespace BTCPayServer.Plugins.Crowdfund
DisqusShortname = settings.DisqusShortname, DisqusShortname = settings.DisqusShortname,
AnimationsEnabled = settings.AnimationsEnabled, AnimationsEnabled = settings.AnimationsEnabled,
ResetEveryAmount = settings.ResetEveryAmount, ResetEveryAmount = settings.ResetEveryAmount,
ResetEvery = Enum.GetName(typeof(CrowdfundResetEvery), settings.ResetEvery), ResetEvery = Enum.GetName(typeof(Services.Apps.CrowdfundResetEvery), settings.ResetEvery),
DisplayPerksRanking = settings.DisplayPerksRanking, DisplayPerksRanking = settings.DisplayPerksRanking,
PerkCount = perkCount, PerkCount = perkCount,
PerkValue = perkValue, PerkValue = perkValue,
NeverReset = settings.ResetEvery == CrowdfundResetEvery.Never, NeverReset = settings.ResetEvery == Services.Apps.CrowdfundResetEvery.Never,
FormUrl = formUrl, FormUrl = formUrl,
Sounds = settings.Sounds, Sounds = settings.Sounds,
AnimationColors = settings.AnimationColors, AnimationColors = settings.AnimationColors,
@@ -264,17 +265,17 @@ namespace BTCPayServer.Plugins.Crowdfund
private static bool IsPaid(InvoiceEntity entity) private static bool IsPaid(InvoiceEntity entity)
{ {
return entity.Status == InvoiceStatusLegacy.Complete || entity.Status == InvoiceStatusLegacy.Confirmed || entity.Status == InvoiceStatusLegacy.Paid; return entity.Status == InvoiceStatus.Settled || entity.Status == InvoiceStatus.Processing;
} }
private static bool IsPending(InvoiceEntity entity) private static bool IsPending(InvoiceEntity entity)
{ {
return !(entity.Status == InvoiceStatusLegacy.Complete || entity.Status == InvoiceStatusLegacy.Confirmed); return entity.Status != InvoiceStatus.Settled;
} }
private static bool IsComplete(InvoiceEntity entity) private static bool IsComplete(InvoiceEntity entity)
{ {
return entity.Status == InvoiceStatusLegacy.Complete || entity.Status == InvoiceStatusLegacy.Confirmed; return entity.Status == InvoiceStatus.Settled;
} }
} }
} }

View File

@@ -48,7 +48,7 @@ namespace BTCPayServer.Plugins.NFC
public async Task<IActionResult> SubmitLNURLWithdrawForInvoice([FromBody] SubmitRequest request) public async Task<IActionResult> SubmitLNURLWithdrawForInvoice([FromBody] SubmitRequest request)
{ {
var invoice = await _invoiceRepository.GetInvoice(request.InvoiceId); var invoice = await _invoiceRepository.GetInvoice(request.InvoiceId);
if (invoice?.Status is not InvoiceStatusLegacy.New) if (invoice?.Status is not InvoiceStatus.New)
{ {
return NotFound(); return NotFound();
} }

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Net.Http; using System.Net.Http;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using ExchangeSharp;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using static System.Net.WebRequestMethods; using static System.Net.WebRequestMethods;

View File

@@ -539,15 +539,7 @@ namespace BTCPayServer.Plugins.PointOfSale.Controllers
return NotFound(); return NotFound();
var from = DateTimeOffset.UtcNow - TimeSpan.FromDays(3); var from = DateTimeOffset.UtcNow - TimeSpan.FromDays(3);
var invoices = await AppService.GetInvoicesForApp(_invoiceRepository, app, from, new[] var invoices = await AppService.GetInvoicesForApp(_invoiceRepository, app, from);
{
InvoiceState.ToString(InvoiceStatusLegacy.New),
InvoiceState.ToString(InvoiceStatusLegacy.Paid),
InvoiceState.ToString(InvoiceStatusLegacy.Confirmed),
InvoiceState.ToString(InvoiceStatusLegacy.Complete),
InvoiceState.ToString(InvoiceStatusLegacy.Expired),
InvoiceState.ToString(InvoiceStatusLegacy.Invalid)
});
var recent = invoices var recent = invoices
.Take(10) .Take(10)
.Select(i => new JObject .Select(i => new JObject
@@ -555,7 +547,7 @@ namespace BTCPayServer.Plugins.PointOfSale.Controllers
["id"] = i.Id, ["id"] = i.Id,
["date"] = i.InvoiceTime, ["date"] = i.InvoiceTime,
["price"] = _displayFormatter.Currency(i.Price, i.Currency, DisplayFormatter.CurrencyFormat.Symbol), ["price"] = _displayFormatter.Currency(i.Price, i.Currency, DisplayFormatter.CurrencyFormat.Symbol),
["status"] = i.GetInvoiceState().Status.ToModernStatus().ToString(), ["status"] = i.GetInvoiceState().Status.ToString(),
["url"] = Url.Action(nameof(UIInvoiceController.Invoice), "UIInvoice", new { invoiceId = i.Id }) ["url"] = Url.Action(nameof(UIInvoiceController.Invoice), "UIInvoice", new { invoiceId = i.Id })
}); });
return Json(recent); return Json(recent);

View File

@@ -50,15 +50,14 @@ namespace BTCPayServer.Plugins.Shopify
var shopifyOrderId = invoice.GetInternalTags(SHOPIFY_ORDER_ID_PREFIX).FirstOrDefault(); var shopifyOrderId = invoice.GetInternalTags(SHOPIFY_ORDER_ID_PREFIX).FirstOrDefault();
if (shopifyOrderId != null) if (shopifyOrderId != null)
{ {
if (new[] { InvoiceStatusLegacy.Invalid, InvoiceStatusLegacy.Expired }.Contains(invoice.GetInvoiceState() if (new[] { InvoiceStatus.Invalid, InvoiceStatus.Expired }.Contains(invoice.GetInvoiceState()
.Status) && invoice.ExceptionStatus != InvoiceExceptionStatus.None) .Status) && invoice.ExceptionStatus != InvoiceExceptionStatus.None)
{ {
//you have failed us, customer //you have failed us, customer
await RegisterTransaction(invoice, shopifyOrderId, false); await RegisterTransaction(invoice, shopifyOrderId, false);
} }
else if (new[] { InvoiceStatusLegacy.Complete, InvoiceStatusLegacy.Confirmed }.Contains( else if (invoice.Status == InvoiceStatus.Settled)
invoice.Status))
{ {
await RegisterTransaction(invoice, shopifyOrderId, true); await RegisterTransaction(invoice, shopifyOrderId, true);
} }

View File

@@ -119,7 +119,7 @@ namespace BTCPayServer.Plugins.Shopify
var firstInvoiceStillPending = var firstInvoiceStillPending =
matchedExistingInvoices.FirstOrDefault(entity => matchedExistingInvoices.FirstOrDefault(entity =>
entity.GetInvoiceState().Status == InvoiceStatusLegacy.New); entity.GetInvoiceState().Status == InvoiceStatus.New);
if (firstInvoiceStillPending != null) if (firstInvoiceStillPending != null)
{ {
return Ok(new return Ok(new
@@ -131,7 +131,7 @@ namespace BTCPayServer.Plugins.Shopify
var firstInvoiceSettled = var firstInvoiceSettled =
matchedExistingInvoices.LastOrDefault(entity => matchedExistingInvoices.LastOrDefault(entity =>
new[] { InvoiceStatusLegacy.Paid, InvoiceStatusLegacy.Complete, InvoiceStatusLegacy.Confirmed } new[] { InvoiceStatus.Processing, InvoiceStatus.Settled }
.Contains( .Contains(
entity.GetInvoiceState().Status)); entity.GetInvoiceState().Status));
@@ -153,7 +153,7 @@ namespace BTCPayServer.Plugins.Shopify
{ {
//if BTCPay was shut down before the tx managed to get registered on shopify, this will fix it on the next UI load in shopify //if BTCPay was shut down before the tx managed to get registered on shopify, this will fix it on the next UI load in shopify
if (client != null && order?.FinancialStatus == "pending" && if (client != null && order?.FinancialStatus == "pending" &&
firstInvoiceSettled.Status != InvoiceStatusLegacy.Paid) firstInvoiceSettled.Status != InvoiceStatus.Processing)
{ {
await new OrderTransactionRegisterLogic(client).Process(orderId, firstInvoiceSettled.Id, await new OrderTransactionRegisterLogic(client).Process(orderId, firstInvoiceSettled.Id,
firstInvoiceSettled.Currency, firstInvoiceSettled.Currency,

View File

@@ -7,6 +7,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using BTCPayServer.Client; using BTCPayServer.Client;
using BTCPayServer.Client.Models;
using BTCPayServer.Data; using BTCPayServer.Data;
using BTCPayServer.Models.AppViewModels; using BTCPayServer.Models.AppViewModels;
using BTCPayServer.Plugins.Crowdfund; using BTCPayServer.Plugins.Crowdfund;
@@ -93,9 +94,8 @@ namespace BTCPayServer.Services.Apps
var paidInvoices = await GetInvoicesForApp(_InvoiceRepository, appData, var paidInvoices = await GetInvoicesForApp(_InvoiceRepository, appData,
null, new[] null, new[]
{ {
InvoiceState.ToString(InvoiceStatusLegacy.Paid), InvoiceStatus.Processing.ToString(),
InvoiceState.ToString(InvoiceStatusLegacy.Confirmed), InvoiceStatus.Settled.ToString()
InvoiceState.ToString(InvoiceStatusLegacy.Complete)
}); });
return await salesType.GetItemStats(appData, paidInvoices); return await salesType.GetItemStats(appData, paidInvoices);
} }
@@ -141,9 +141,8 @@ namespace BTCPayServer.Services.Apps
var paidInvoices = await GetInvoicesForApp(_InvoiceRepository, app, DateTimeOffset.UtcNow - TimeSpan.FromDays(numberOfDays), var paidInvoices = await GetInvoicesForApp(_InvoiceRepository, app, DateTimeOffset.UtcNow - TimeSpan.FromDays(numberOfDays),
new[] new[]
{ {
InvoiceState.ToString(InvoiceStatusLegacy.Paid), InvoiceStatus.Processing.ToString(),
InvoiceState.ToString(InvoiceStatusLegacy.Confirmed), InvoiceStatus.Settled.ToString()
InvoiceState.ToString(InvoiceStatusLegacy.Complete)
}); });
return await salesType.GetSalesStats(app, paidInvoices, numberOfDays); return await salesType.GetSalesStats(app, paidInvoices, numberOfDays);
@@ -185,7 +184,7 @@ namespace BTCPayServer.Services.Apps
{ {
res.Add(new InvoiceStatsItem res.Add(new InvoiceStatsItem
{ {
ItemCode = e.Metadata.ItemCode ?? typeof(PosViewType).DisplayName(PosViewType.Light.ToString()), ItemCode = e.Metadata.ItemCode ?? typeof(Plugins.PointOfSale.PosViewType).DisplayName(Plugins.PointOfSale.PosViewType.Light.ToString()),
FiatPrice = e.PaidAmount.Net, FiatPrice = e.PaidAmount.Net,
Date = e.InvoiceTime.Date Date = e.InvoiceTime.Date
}); });
@@ -220,11 +219,7 @@ namespace BTCPayServer.Services.Apps
{ {
StoreId = new[] { appData.StoreDataId }, StoreId = new[] { appData.StoreDataId },
TextSearch = appData.TagAllInvoices ? null : GetAppSearchTerm(appData), TextSearch = appData.TagAllInvoices ? null : GetAppSearchTerm(appData),
Status = status ?? new[]{ Status = status,
InvoiceState.ToString(InvoiceStatusLegacy.New),
InvoiceState.ToString(InvoiceStatusLegacy.Paid),
InvoiceState.ToString(InvoiceStatusLegacy.Confirmed),
InvoiceState.ToString(InvoiceStatusLegacy.Complete)},
StartDate = startDate StartDate = startDate
}); });
@@ -297,8 +292,8 @@ namespace BTCPayServer.Services.Apps
{ {
case PointOfSaleAppType.AppType: case PointOfSaleAppType.AppType:
var settings = app.GetSettings<PointOfSaleSettings>(); var settings = app.GetSettings<PointOfSaleSettings>();
string posViewStyle = (settings.EnableShoppingCart ? PosViewType.Cart : settings.DefaultView).ToString(); string posViewStyle = (settings.EnableShoppingCart ? Plugins.PointOfSale.PosViewType.Cart : settings.DefaultView).ToString();
style = typeof(PosViewType).DisplayName(posViewStyle); style = typeof(Plugins.PointOfSale.PosViewType).DisplayName(posViewStyle);
break; break;
default: default:

View File

@@ -7,8 +7,6 @@ using System.Runtime.InteropServices;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using AngleSharp.Dom;
using ExchangeSharp;
using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Caching.Memory;
using NBitcoin; using NBitcoin;
using Org.BouncyCastle.Asn1.X509; using Org.BouncyCastle.Asn1.X509;

View File

@@ -1,6 +1,7 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using BTCPayServer.Client.Models;
using BTCPayServer.Data; using BTCPayServer.Data;
using BTCPayServer.Events; using BTCPayServer.Events;
using BTCPayServer.Logging; using BTCPayServer.Logging;
@@ -40,7 +41,7 @@ namespace BTCPayServer.Services
public async Task<bool> ActivateInvoicePaymentMethod(string invoiceId, PaymentMethodId paymentMethodId, bool forceNew = false) public async Task<bool> ActivateInvoicePaymentMethod(string invoiceId, PaymentMethodId paymentMethodId, bool forceNew = false)
{ {
var invoice = await _invoiceRepository.GetInvoice(invoiceId); var invoice = await _invoiceRepository.GetInvoice(invoiceId);
if (invoice?.GetInvoiceState().Status is not InvoiceStatusLegacy.New) if (invoice?.GetInvoiceState().Status is not InvoiceStatus.New)
return false; return false;
var store = await _storeRepository.FindStore(invoice.StoreId); var store = await _storeRepository.FindStore(invoice.StoreId);
if (store is null) if (store is null)

View File

@@ -437,13 +437,9 @@ namespace BTCPayServer.Services.Invoices
public decimal PaidFee { get; set; } public decimal PaidFee { get; set; }
[JsonIgnore] [JsonIgnore]
public InvoiceStatusLegacy Status { get; set; } public InvoiceStatus Status { get; set; }
[JsonIgnore]
public string StatusString => InvoiceState.ToString(Status);
[JsonIgnore] [JsonIgnore]
public InvoiceExceptionStatus ExceptionStatus { get; set; } public InvoiceExceptionStatus ExceptionStatus { get; set; }
[JsonIgnore]
public string ExceptionStatusString => InvoiceState.ToString(ExceptionStatus);
[Obsolete("Use GetPayments instead")] [Obsolete("Use GetPayments instead")]
[JsonIgnore] [JsonIgnore]
@@ -541,10 +537,8 @@ namespace BTCPayServer.Services.Invoices
CurrentTime = DateTimeOffset.UtcNow, CurrentTime = DateTimeOffset.UtcNow,
InvoiceTime = InvoiceTime, InvoiceTime = InvoiceTime,
ExpirationTime = ExpirationTime, ExpirationTime = ExpirationTime,
#pragma warning disable CS0618 // Type or member is obsolete Status = Status.ToLegacyStatusString(),
Status = StatusString, ExceptionStatus = ExceptionStatus == InvoiceExceptionStatus.None ? new JValue(false) : new JValue(ExceptionStatus.ToLegacyExceptionStatusString()),
ExceptionStatus = ExceptionStatus == InvoiceExceptionStatus.None ? new JValue(false) : new JValue(ExceptionStatusString),
#pragma warning restore CS0618 // Type or member is obsolete
Currency = Currency, Currency = Currency,
PaymentSubtotals = new Dictionary<string, decimal>(), PaymentSubtotals = new Dictionary<string, decimal>(),
PaymentTotals = new Dictionary<string, decimal>(), PaymentTotals = new Dictionary<string, decimal>(),
@@ -739,160 +733,76 @@ namespace BTCPayServer.Services.Invoices
public enum InvoiceStatusLegacy public enum InvoiceStatusLegacy
{ {
New,
Paid,
Expired,
Invalid,
Complete,
Confirmed
} }
public static class InvoiceStatusLegacyExtensions public static class InvoiceStatusLegacyExtensions
{ {
public static InvoiceStatus ToModernStatus(this InvoiceStatusLegacy legacy) public static string ToLegacyStatusString(this InvoiceStatus status) =>
{ status switch
switch (legacy)
{ {
case InvoiceStatusLegacy.Complete: InvoiceStatus.Settled => "complete",
case InvoiceStatusLegacy.Confirmed: InvoiceStatus.Expired => "expired",
return InvoiceStatus.Settled; InvoiceStatus.Invalid => "invalid",
case InvoiceStatusLegacy.Expired: InvoiceStatus.Processing => "paid",
return InvoiceStatus.Expired; InvoiceStatus.New => "new",
case InvoiceStatusLegacy.Invalid: _ => throw new NotSupportedException(status.ToString())
return InvoiceStatus.Invalid; };
case InvoiceStatusLegacy.Paid: public static string ToLegacyExceptionStatusString(this InvoiceExceptionStatus status) =>
return InvoiceStatus.Processing; status switch
case InvoiceStatusLegacy.New: {
return InvoiceStatus.New; InvoiceExceptionStatus.None => string.Empty,
default: InvoiceExceptionStatus.PaidLate => "paidLater",
throw new NotSupportedException(); InvoiceExceptionStatus.PaidPartial => "paidPartial",
} InvoiceExceptionStatus.PaidOver => "paidOver",
} InvoiceExceptionStatus.Marked => "marked",
_ => throw new NotSupportedException(status.ToString())
};
} }
public class InvoiceState public record InvoiceState(InvoiceStatus Status, InvoiceExceptionStatus ExceptionStatus)
{ {
static readonly Dictionary<string, InvoiceStatusLegacy> _StringToInvoiceStatus; public InvoiceState(string status, string exceptionStatus):
static readonly Dictionary<InvoiceStatusLegacy, string> _InvoiceStatusToString; this(Enum.Parse<InvoiceStatus>(status), exceptionStatus switch { "None" or "" or null => InvoiceExceptionStatus.None, _ => Enum.Parse<InvoiceExceptionStatus>(exceptionStatus) })
static readonly Dictionary<string, InvoiceExceptionStatus> _StringToExceptionStatus;
static readonly Dictionary<InvoiceExceptionStatus, string> _ExceptionStatusToString;
static InvoiceState()
{ {
_StringToInvoiceStatus = new Dictionary<string, InvoiceStatusLegacy>();
_StringToInvoiceStatus.Add("paid", InvoiceStatusLegacy.Paid);
_StringToInvoiceStatus.Add("expired", InvoiceStatusLegacy.Expired);
_StringToInvoiceStatus.Add("invalid", InvoiceStatusLegacy.Invalid);
_StringToInvoiceStatus.Add("complete", InvoiceStatusLegacy.Complete);
_StringToInvoiceStatus.Add("new", InvoiceStatusLegacy.New);
_StringToInvoiceStatus.Add("confirmed", InvoiceStatusLegacy.Confirmed);
_InvoiceStatusToString = _StringToInvoiceStatus.ToDictionary(kv => kv.Value, kv => kv.Key);
_StringToExceptionStatus = new Dictionary<string, InvoiceExceptionStatus>();
_StringToExceptionStatus.Add(string.Empty, InvoiceExceptionStatus.None);
_StringToExceptionStatus.Add("paidPartial", InvoiceExceptionStatus.PaidPartial);
_StringToExceptionStatus.Add("paidLate", InvoiceExceptionStatus.PaidLate);
_StringToExceptionStatus.Add("paidOver", InvoiceExceptionStatus.PaidOver);
_StringToExceptionStatus.Add("marked", InvoiceExceptionStatus.Marked);
_ExceptionStatusToString = _StringToExceptionStatus.ToDictionary(kv => kv.Value, kv => kv.Key);
_StringToExceptionStatus.Add("false", InvoiceExceptionStatus.None);
}
public InvoiceState(string status, string exceptionStatus)
{
Status = _StringToInvoiceStatus[status];
ExceptionStatus = _StringToExceptionStatus[exceptionStatus ?? string.Empty];
}
public InvoiceState(InvoiceStatusLegacy status, InvoiceExceptionStatus exceptionStatus)
{
Status = status;
ExceptionStatus = exceptionStatus;
}
public InvoiceStatusLegacy Status { get; }
public InvoiceExceptionStatus ExceptionStatus { get; }
public static string ToString(InvoiceStatusLegacy status)
{
return _InvoiceStatusToString[status];
}
public static string ToString(InvoiceExceptionStatus exceptionStatus)
{
return _ExceptionStatusToString[exceptionStatus];
} }
public bool CanMarkComplete() public bool CanMarkComplete()
{ {
return Status is InvoiceStatusLegacy.New or InvoiceStatusLegacy.Paid or InvoiceStatusLegacy.Expired or InvoiceStatusLegacy.Invalid || return Status is InvoiceStatus.New or InvoiceStatus.Processing or InvoiceStatus.Expired or InvoiceStatus.Invalid ||
(Status != InvoiceStatusLegacy.Complete && ExceptionStatus == InvoiceExceptionStatus.Marked); (Status != InvoiceStatus.Settled && ExceptionStatus == InvoiceExceptionStatus.Marked);
} }
public bool CanMarkInvalid() public bool CanMarkInvalid()
{ {
return Status is InvoiceStatusLegacy.New or InvoiceStatusLegacy.Paid or InvoiceStatusLegacy.Expired || return Status is InvoiceStatus.New or InvoiceStatus.Processing or InvoiceStatus.Expired ||
(Status != InvoiceStatusLegacy.Invalid && ExceptionStatus == InvoiceExceptionStatus.Marked); (Status != InvoiceStatus.Invalid && ExceptionStatus == InvoiceExceptionStatus.Marked);
} }
public bool CanRefund() public bool CanRefund()
{ {
return Status == InvoiceStatusLegacy.Confirmed || return
Status == InvoiceStatusLegacy.Complete || Status == InvoiceStatus.Settled ||
(Status == InvoiceStatusLegacy.Expired && (Status == InvoiceStatus.Expired &&
(ExceptionStatus == InvoiceExceptionStatus.PaidLate || (ExceptionStatus == InvoiceExceptionStatus.PaidLate ||
ExceptionStatus == InvoiceExceptionStatus.PaidOver || ExceptionStatus == InvoiceExceptionStatus.PaidOver ||
ExceptionStatus == InvoiceExceptionStatus.PaidPartial)) || ExceptionStatus == InvoiceExceptionStatus.PaidPartial)) ||
Status == InvoiceStatusLegacy.Invalid; Status == InvoiceStatus.Invalid;
} }
public bool IsSettled() public bool IsSettled()
{ {
return Status == InvoiceStatusLegacy.Confirmed || return
Status == InvoiceStatusLegacy.Complete || Status == InvoiceStatus.Settled ||
(Status == InvoiceStatusLegacy.Expired && (Status == InvoiceStatus.Expired &&
ExceptionStatus is InvoiceExceptionStatus.PaidLate or InvoiceExceptionStatus.PaidOver); ExceptionStatus is InvoiceExceptionStatus.PaidLate or InvoiceExceptionStatus.PaidOver);
} }
public override int GetHashCode()
{
return HashCode.Combine(Status, ExceptionStatus);
}
public static bool operator ==(InvoiceState a, InvoiceState b)
{
if (a is null && b is null)
return true;
if (a is null)
return false;
return a.Equals(b);
}
public static bool operator !=(InvoiceState a, InvoiceState b)
{
return !(a == b);
}
public bool Equals(InvoiceState o)
{
if (o is null)
return false;
return o.Status == Status && o.ExceptionStatus == ExceptionStatus;
}
public override bool Equals(object obj)
{
if (obj is InvoiceState o)
{
return this.Equals(o);
}
return false;
}
public override string ToString() public override string ToString()
{ {
return Status.ToModernStatus() + ExceptionStatus switch return Status + ExceptionStatus switch
{ {
InvoiceExceptionStatus.PaidOver => " (paid over)", InvoiceExceptionStatus.PaidOver => " (paid over)",
InvoiceExceptionStatus.PaidLate => " (paid late)", InvoiceExceptionStatus.PaidLate => " (paid late)",
InvoiceExceptionStatus.PaidPartial => " (paid partial)", InvoiceExceptionStatus.PaidPartial => " (paid partial)",
InvoiceExceptionStatus.Marked => " (marked)", InvoiceExceptionStatus.Marked => " (marked)",
InvoiceExceptionStatus.Invalid => " (invalid)",
_ => "" _ => ""
}; };
} }

View File

@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Linq.Expressions;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using BTCPayServer.Abstractions.Extensions; using BTCPayServer.Abstractions.Extensions;
@@ -230,9 +231,7 @@ retry:
StoreDataId = invoice.StoreId, StoreDataId = invoice.StoreId,
Id = invoice.Id, Id = invoice.Id,
OrderId = invoice.Metadata.OrderId, OrderId = invoice.Metadata.OrderId,
#pragma warning disable CS0618 // Type or member is obsolete Status = invoice.Status.ToString(),
Status = invoice.StatusString,
#pragma warning restore CS0618 // Type or member is obsolete
ItemCode = invoice.Metadata.ItemCode, ItemCode = invoice.Metadata.ItemCode,
Archived = false Archived = false
}; };
@@ -451,8 +450,8 @@ retry:
new new
{ {
id = invoiceId, id = invoiceId,
status = InvoiceState.ToString(invoiceState.Status), status = invoiceState.Status.ToString(),
exstatus = InvoiceState.ToString(invoiceState.ExceptionStatus) exstatus = invoiceState.ExceptionStatus is InvoiceExceptionStatus.None ? string.Empty : invoiceState.ExceptionStatus.ToString()
}); });
} }
internal async Task UpdateInvoicePrice(string invoiceId, decimal price) internal async Task UpdateInvoicePrice(string invoiceId, decimal price)
@@ -559,7 +558,6 @@ retry:
context.Attach(invoiceData); context.Attach(invoiceData);
string eventName; string eventName;
string legacyStatus;
switch (status) switch (status)
{ {
case InvoiceStatus.Settled: case InvoiceStatus.Settled:
@@ -569,7 +567,6 @@ retry:
} }
eventName = InvoiceEvent.MarkedCompleted; eventName = InvoiceEvent.MarkedCompleted;
legacyStatus = InvoiceStatusLegacy.Complete.ToString();
break; break;
case InvoiceStatus.Invalid: case InvoiceStatus.Invalid:
if (!invoiceData.GetInvoiceState().CanMarkInvalid()) if (!invoiceData.GetInvoiceState().CanMarkInvalid())
@@ -577,14 +574,13 @@ retry:
return false; return false;
} }
eventName = InvoiceEvent.MarkedInvalid; eventName = InvoiceEvent.MarkedInvalid;
legacyStatus = InvoiceStatusLegacy.Invalid.ToString();
break; break;
default: default:
return false; return false;
} }
invoiceData.Status = legacyStatus.ToLowerInvariant(); invoiceData.Status = status.ToString();
invoiceData.ExceptionStatus = InvoiceExceptionStatus.Marked.ToString().ToLowerInvariant(); invoiceData.ExceptionStatus = InvoiceExceptionStatus.Marked.ToString();
try try
{ {
await context.SaveChangesAsync(); await context.SaveChangesAsync();
@@ -705,42 +701,50 @@ retry:
} }
var statusSet = queryObject.Status is { Length: > 0 } var statusSet = queryObject.Status is { Length: > 0 }
? queryObject.Status.Select(s => s.ToLowerInvariant()).ToHashSet() ? queryObject.Status.Select(NormalizeStatus).Where(n => n is not null).ToHashSet()
: new HashSet<string>(); : new HashSet<string>();
var exceptionStatusSet = queryObject.ExceptionStatus is { Length: > 0 } var exceptionStatusSet = queryObject.ExceptionStatus is { Length: > 0 }
? queryObject.ExceptionStatus.Select(NormalizeExceptionStatus).ToHashSet() ? queryObject.ExceptionStatus.Select(NormalizeExceptionStatus).Where(n => n is not null).ToHashSet()
: new HashSet<string>(); : new HashSet<string>();
// We make sure here that the old filters still work
if (statusSet.Contains("paid"))
statusSet.Add("processing");
if (statusSet.Contains("processing"))
statusSet.Add("paid");
if (statusSet.Contains("confirmed"))
{
statusSet.Add("complete");
statusSet.Add("settled");
}
if (statusSet.Contains("settled"))
{
statusSet.Add("complete");
statusSet.Add("confirmed");
}
if (statusSet.Contains("complete"))
{
statusSet.Add("settled");
statusSet.Add("confirmed");
}
if (statusSet.Any() || exceptionStatusSet.Any()) if (statusSet.Any() || exceptionStatusSet.Any())
{ {
query = query.Where(i => statusSet.Contains(i.Status) || exceptionStatusSet.Contains(i.ExceptionStatus)); Expression<Func<InvoiceData, bool>> statusExpression = null;
Expression<Func<InvoiceData, bool>> exceptionStatusExpression = null;
if (statusSet.Count is 1)
{
var status = statusSet.First();
statusExpression = i => i.Status == status;
}
else if (statusSet.Count is > 1)
{
statusExpression = i => statusSet.Contains(i.Status);
}
if (exceptionStatusSet.Count is 1)
{
var exceptionStatus = exceptionStatusSet.First();
exceptionStatusExpression = i => i.ExceptionStatus == exceptionStatus;
}
else if (exceptionStatusSet.Count is > 1)
{
exceptionStatusExpression = i => exceptionStatusSet.Contains(i.ExceptionStatus);
}
(Expression predicate, ParameterExpression parameter) = (statusExpression, exceptionStatusExpression) switch
{
({ } a, { } b) => ((Expression)Expression.Or(a.Body, b.Body), a.Parameters[0]),
({ } a, null) => (a.Body, a.Parameters[0]),
(null, { } b) => (b.Body, b.Parameters[0]),
_ => throw new NotSupportedException()
};
var expression = Expression.Lambda<Func<InvoiceData, bool>>(predicate, parameter);
query = query.Where(expression);
} }
if (queryObject.Unusual != null) if (queryObject.Unusual != null)
{ {
var unusual = queryObject.Unusual.Value; var unusual = queryObject.Unusual.Value;
query = query.Where(i => unusual == (i.Status == "invalid" || !string.IsNullOrEmpty(i.ExceptionStatus))); query = query.Where(i => unusual == (i.Status == "Invalid" || !string.IsNullOrEmpty(i.ExceptionStatus)));
} }
if (queryObject.OrderByDesc) if (queryObject.OrderByDesc)
@@ -795,27 +799,31 @@ retry:
return await GetInvoiceQuery(context, queryObject).CountAsync(); return await GetInvoiceQuery(context, queryObject).CountAsync();
} }
private string NormalizeStatus(string status)
{
status = status.ToLowerInvariant();
return status switch
{
"new" => "New",
"paid" or "processing" => "Processing",
"complete" or "confirmed" => "Settled",
"expired" => "Expired",
"invalid" => "Invalid",
_ => null
};
}
private string NormalizeExceptionStatus(string status) private string NormalizeExceptionStatus(string status)
{ {
status = status.ToLowerInvariant(); status = status.ToLowerInvariant();
switch (status) return status switch
{ {
case "paidover": "paidover" or "over" or "overpaid" => "PaidOver",
case "over": "paidlate" or "late" => "PaidLate",
case "overpaid": "paidpartial" or "underpaid" or "partial" => "PaidPartial",
status = "paidOver"; "none" or "" => "",
break; _ => null
case "paidlate": };
case "late":
status = "paidLate";
break;
case "paidpartial":
case "underpaid":
case "partial":
status = "paidPartial";
break;
}
return status;
} }
public static T FromBytes<T>(byte[] blob, BTCPayNetworkBase network = null) public static T FromBytes<T>(byte[] blob, BTCPayNetworkBase network = null)
@@ -846,7 +854,7 @@ retry:
contribution.Value = contribution.CurrencyValue; contribution.Value = contribution.CurrencyValue;
// For hardcap, we count newly created invoices as part of the contributions // For hardcap, we count newly created invoices as part of the contributions
if (!softcap && p.Status == InvoiceStatusLegacy.New) if (!softcap && p.Status == InvoiceStatus.New)
return new[] { contribution }; return new[] { contribution };
// If the user get a donation via other mean, he can register an invoice manually for such amount // If the user get a donation via other mean, he can register an invoice manually for such amount
@@ -854,7 +862,7 @@ retry:
var payments = p.GetPayments(true); var payments = p.GetPayments(true);
if (payments.Count == 0 && if (payments.Count == 0 &&
p.ExceptionStatus == InvoiceExceptionStatus.Marked && p.ExceptionStatus == InvoiceExceptionStatus.Marked &&
p.Status == InvoiceStatusLegacy.Complete) p.Status == InvoiceStatus.Settled)
return new[] { contribution }; return new[] { contribution };
contribution.CurrencyValue = 0m; contribution.CurrencyValue = 0m;
@@ -862,7 +870,7 @@ retry:
// If an invoice has been marked invalid, remove the contribution // If an invoice has been marked invalid, remove the contribution
if (p.ExceptionStatus == InvoiceExceptionStatus.Marked && if (p.ExceptionStatus == InvoiceExceptionStatus.Marked &&
p.Status == InvoiceStatusLegacy.Invalid) p.Status == InvoiceStatus.Invalid)
return new[] { contribution }; return new[] { contribution };
// Else, we just sum the payments // Else, we just sum the payments

View File

@@ -95,8 +95,8 @@ public class LegacyInvoiceExportReportProvider : ReportProvider
data.Add(invoiceEntity.Metadata.ItemDesc); data.Add(invoiceEntity.Metadata.ItemDesc);
data.Add(invoiceEntity.GetInvoiceState().ToString()); data.Add(invoiceEntity.GetInvoiceState().ToString());
#pragma warning disable CS0618 // Type or member is obsolete #pragma warning disable CS0618 // Type or member is obsolete
data.Add(invoiceEntity.StatusString); data.Add(invoiceEntity.Status.ToLegacyStatusString());
data.Add(invoiceEntity.ExceptionStatusString); data.Add(invoiceEntity.ExceptionStatus.ToLegacyExceptionStatusString());
#pragma warning restore CS0618 // Type or member is obsolete #pragma warning restore CS0618 // Type or member is obsolete
data.Add(invoiceEntity.Metadata.BuyerEmail); data.Add(invoiceEntity.Metadata.BuyerEmail);
data.Add(payment.Accounted); data.Add(payment.Accounted);
@@ -128,10 +128,8 @@ public class LegacyInvoiceExportReportProvider : ReportProvider
data.Add(invoiceEntity.Metadata.ItemCode); data.Add(invoiceEntity.Metadata.ItemCode);
data.Add(invoiceEntity.Metadata.ItemDesc); data.Add(invoiceEntity.Metadata.ItemDesc);
data.Add(invoiceEntity.GetInvoiceState().ToString()); data.Add(invoiceEntity.GetInvoiceState().ToString());
#pragma warning disable CS0618 // Type or member is obsolete data.Add(invoiceEntity.Status.ToLegacyStatusString());
data.Add(invoiceEntity.StatusString); data.Add(invoiceEntity.ExceptionStatus.ToLegacyExceptionStatusString());
data.Add(invoiceEntity.ExceptionStatusString);
#pragma warning restore CS0618 // Type or member is obsolete
data.Add(invoiceEntity.Metadata.BuyerEmail); data.Add(invoiceEntity.Metadata.BuyerEmail);
data.Add(null); // Accounted data.Add(null); // Accounted
} }

View File

@@ -42,7 +42,7 @@ public class ProductsReportProvider : ReportProvider
var values = queryContext.CreateData(); var values = queryContext.CreateData();
values.Add(i.InvoiceTime); values.Add(i.InvoiceTime);
values.Add(i.Id); values.Add(i.Id);
var status = i.Status.ToModernStatus(); var status = i.Status;
if (status == Client.Models.InvoiceStatus.Expired && i.ExceptionStatus == Client.Models.InvoiceExceptionStatus.None) if (status == Client.Models.InvoiceStatus.Expired && i.ExceptionStatus == Client.Models.InvoiceExceptionStatus.None)
continue; continue;
values.Add(status.ToString()); values.Add(status.ToString());

View File

@@ -5,7 +5,6 @@ using System.Runtime.CompilerServices;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Amazon.S3.Model.Internal.MarshallTransformations; using Amazon.S3.Model.Internal.MarshallTransformations;
using ExchangeSharp;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
namespace BTCPayServer namespace BTCPayServer

View File

@@ -11,7 +11,7 @@
Layout = null; Layout = null;
string StatusClass(InvoiceState state) string StatusClass(InvoiceState state)
{ {
var status = state.Status.ToModernStatus(); var status = state.Status;
switch (status) switch (status)
{ {
case InvoiceStatus.Expired: case InvoiceStatus.Expired:

View File

@@ -1,8 +1,8 @@
// These are the legacy states, see InvoiceEntity // These are the legacy states, see InvoiceEntity
const STATUS_PAYABLE = ['new']; const STATUS_PAYABLE = ['New'];
const STATUS_PAID = ['paid']; const STATUS_PAID = ['Processing'];
const STATUS_SETTLED = ['complete', 'confirmed']; const STATUS_SETTLED = ['Settled'];
const STATUS_INVALID = ['expired', 'invalid']; const STATUS_INVALID = ['Expired', 'Invalid'];
const urlParams = new URLSearchParams(window.location.search); const urlParams = new URLSearchParams(window.location.search);
class NDEFReaderWrapper { class NDEFReaderWrapper {

View File

@@ -101,7 +101,7 @@ window.BTCPayShopifyIntegrationModule = function () {
} }
return; return;
} }
if (["complete", "confirmed", "paid"].indexOf(currentInvoiceData.status.toLowerCase()) >= 0) { if (["settled", "processing"].indexOf(currentInvoiceData.status.toLowerCase()) >= 0) {
setOrderAsPaid(); setOrderAsPaid();
} else if (["invalid", "expired"].indexOf(currentInvoiceData.status.toLowerCase()) >= 0) { } else if (["invalid", "expired"].indexOf(currentInvoiceData.status.toLowerCase()) >= 0) {
fail(); fail();