diff --git a/BTCPayServer.Client/Models/InvoiceExceptionStatus.cs b/BTCPayServer.Client/Models/InvoiceExceptionStatus.cs index d111433a0..b4a471e92 100644 --- a/BTCPayServer.Client/Models/InvoiceExceptionStatus.cs +++ b/BTCPayServer.Client/Models/InvoiceExceptionStatus.cs @@ -5,7 +5,6 @@ public enum InvoiceExceptionStatus PaidLate, PaidPartial, Marked, - Invalid, PaidOver } diff --git a/BTCPayServer.Data/Data/InvoiceData.Migration.cs b/BTCPayServer.Data/Data/InvoiceData.Migration.cs index 76f51a5ec..32ada35c3 100644 --- a/BTCPayServer.Data/Data/InvoiceData.Migration.cs +++ b/BTCPayServer.Data/Data/InvoiceData.Migration.cs @@ -349,7 +349,24 @@ namespace BTCPayServer.Data if (blob["defaultPaymentMethod"] is not (null or { Type : JTokenType.Null })) blob["defaultPaymentMethod"] = MigrationExtensions.MigratePaymentMethodId(blob["defaultPaymentMethod"].Value()); 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; Blob2 = blob.ToString(Formatting.None); } diff --git a/BTCPayServer.Rating/Services/RateProviderFactory.cs b/BTCPayServer.Rating/Services/RateProviderFactory.cs index 736e95bc8..6577fa935 100644 --- a/BTCPayServer.Rating/Services/RateProviderFactory.cs +++ b/BTCPayServer.Rating/Services/RateProviderFactory.cs @@ -3,14 +3,9 @@ using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; -using System.Security.Cryptography; using System.Threading; using System.Threading.Tasks; using BTCPayServer.Rating; -using BTCPayServer.Rating.Providers; -using ExchangeSharp; -using NBitcoin; -using Newtonsoft.Json.Linq; namespace BTCPayServer.Services.Rates { diff --git a/BTCPayServer.Tests/AltcoinTests/AltcoinTests.cs b/BTCPayServer.Tests/AltcoinTests/AltcoinTests.cs index cc18d3fb9..c16e3fdd1 100644 --- a/BTCPayServer.Tests/AltcoinTests/AltcoinTests.cs +++ b/BTCPayServer.Tests/AltcoinTests/AltcoinTests.cs @@ -336,7 +336,7 @@ namespace BTCPayServer.Tests Assert.Equal("paid", invoice.Status); checkout = (Models.InvoicingModels.PaymentModel)((JsonResult)controller.GetStatus(invoice.Id) .GetAwaiter().GetResult()).Value; - Assert.Equal("paid", checkout.Status); + Assert.Equal("Processing", checkout.Status); }); } } diff --git a/BTCPayServer.Tests/PayJoinTests.cs b/BTCPayServer.Tests/PayJoinTests.cs index b3ab8f815..137257d28 100644 --- a/BTCPayServer.Tests/PayJoinTests.cs +++ b/BTCPayServer.Tests/PayJoinTests.cs @@ -285,7 +285,7 @@ namespace BTCPayServer.Tests await TestUtils.EventuallyAsync(async () => { var invoice = await invoiceRepository.GetInvoice(invoiceId); - Assert.Equal(InvoiceStatusLegacy.Paid, invoice.Status); + Assert.Equal(InvoiceStatus.Processing, invoice.Status); Assert.Equal(0.023m, invoice.Price); }); } @@ -344,7 +344,7 @@ namespace BTCPayServer.Tests await TestUtils.EventuallyAsync(async () => { var invoice = await s.Server.PayTester.GetService().GetInvoice(invoiceId); - Assert.Equal(InvoiceStatusLegacy.Paid, invoice.Status); + Assert.Equal(InvoiceStatus.Processing, invoice.Status); }); s.SelectStoreContext(receiver.storeId); @@ -396,7 +396,7 @@ namespace BTCPayServer.Tests await TestUtils.EventuallyAsync(async () => { var invoice = await s.Server.PayTester.GetService().GetInvoice(invoiceId); - Assert.Equal(InvoiceStatusLegacy.Paid, invoice.Status); + Assert.Equal(InvoiceStatus.Processing, invoice.Status); }); s.GoToInvoices(receiver.storeId); paymentValueRowColumn = s.Driver.FindElement(By.Id($"invoice_details_{invoiceId}")) @@ -790,7 +790,7 @@ retry: await TestUtils.EventuallyAsync(async () => { var invoice = await tester.PayTester.GetService().GetInvoice(lastInvoiceId); - Assert.Equal(InvoiceStatusLegacy.Paid, invoice.Status); + Assert.Equal(InvoiceStatus.Processing, invoice.Status); Assert.Equal(InvoiceExceptionStatus.None, invoice.ExceptionStatus); var coins = await btcPayWallet.GetUnspentCoins(receiverUser.DerivationScheme); foreach (var coin in coins) @@ -1131,7 +1131,7 @@ retry: await TestUtils.EventuallyAsync(async () => { var invoiceEntity = await tester.PayTester.GetService().GetInvoice(invoice7.Id); - Assert.Equal(InvoiceStatusLegacy.Paid, invoiceEntity.Status); + Assert.Equal(InvoiceStatus.Processing, invoiceEntity.Status); Assert.Contains(invoiceEntity.GetPayments(false), p => p.Accounted && handler.ParsePaymentDetails(p.Details).PayjoinInformation is null); }); @@ -1160,7 +1160,7 @@ retry: await TestUtils.EventuallyAsync(async () => { var invoiceEntity = await tester.PayTester.GetService().GetInvoice(invoice7.Id); - Assert.Equal(InvoiceStatusLegacy.New, invoiceEntity.Status); + Assert.Equal(InvoiceStatus.New, invoiceEntity.Status); Assert.True(invoiceEntity.GetPayments(false).All(p => !p.Accounted)); ourOutpoint = invoiceEntity.GetAllBitcoinPaymentData(handler, false).First().PayjoinInformation.ContributedOutPoints[0]; }); diff --git a/BTCPayServer.Tests/PaymentRequestTests.cs b/BTCPayServer.Tests/PaymentRequestTests.cs index 8975d0381..5c098506e 100644 --- a/BTCPayServer.Tests/PaymentRequestTests.cs +++ b/BTCPayServer.Tests/PaymentRequestTests.cs @@ -208,12 +208,12 @@ namespace BTCPayServer.Tests pair => pair.Key == "Id" && pair.Value.ToString() == invoiceId); var invoice = user.BitPay.GetInvoice(invoiceId, Facade.Merchant); - Assert.Equal(InvoiceState.ToString(InvoiceStatusLegacy.New), invoice.Status); + Assert.Equal("new", invoice.Status); Assert.IsType(await paymentRequestController.CancelUnpaidPendingInvoice(paymentRequestId, false)); invoice = user.BitPay.GetInvoice(invoiceId, Facade.Merchant); - Assert.Equal(InvoiceState.ToString(InvoiceStatusLegacy.Invalid), invoice.Status); + Assert.Equal("invalid", invoice.Status); Assert.IsType(await paymentRequestController.CancelUnpaidPendingInvoice(paymentRequestId, false)); diff --git a/BTCPayServer.Tests/SeleniumTests.cs b/BTCPayServer.Tests/SeleniumTests.cs index 35fa714f2..43f2fc229 100644 --- a/BTCPayServer.Tests/SeleniumTests.cs +++ b/BTCPayServer.Tests/SeleniumTests.cs @@ -2988,7 +2988,7 @@ namespace BTCPayServer.Tests await TestUtils.EventuallyAsync(async () => { 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 paymentMethods = await greenfield.GetInvoicePaymentMethods(s.StoreId, i); @@ -3110,7 +3110,7 @@ namespace BTCPayServer.Tests await TestUtils.EventuallyAsync(async () => { 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().CreateContext(); var payoutsData = await ctx.Payouts.Where(p => p.PullPaymentDataId == pullPaymentId).ToListAsync(); diff --git a/BTCPayServer.Tests/UnitTest1.cs b/BTCPayServer.Tests/UnitTest1.cs index 448036eab..63e650f5a 100644 --- a/BTCPayServer.Tests/UnitTest1.cs +++ b/BTCPayServer.Tests/UnitTest1.cs @@ -409,7 +409,7 @@ namespace BTCPayServer.Tests }, evt => evt.InvoiceId == invoice.Id); 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); //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 () => { 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.False(i.GetPayments(false).First().Accounted); }); diff --git a/BTCPayServer/Components/InvoiceStatus/Default.cshtml b/BTCPayServer/Components/InvoiceStatus/Default.cshtml index 4b34eaf3f..084dd5cba 100644 --- a/BTCPayServer/Components/InvoiceStatus/Default.cshtml +++ b/BTCPayServer/Components/InvoiceStatus/Default.cshtml @@ -6,7 +6,7 @@ @{ 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()); }
diff --git a/BTCPayServer/Controllers/GreenField/GreenfieldInvoiceController.cs b/BTCPayServer/Controllers/GreenField/GreenfieldInvoiceController.cs index be1fc7adb..ca19fbca1 100644 --- a/BTCPayServer/Controllers/GreenField/GreenfieldInvoiceController.cs +++ b/BTCPayServer/Controllers/GreenField/GreenfieldInvoiceController.cs @@ -670,7 +670,7 @@ namespace BTCPayServer.Controllers.Greenfield Type = entity.Type, Id = entity.Id, 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, Currency = entity.Currency, Archived = entity.Archived, diff --git a/BTCPayServer/Controllers/GreenField/GreenfieldLightningNodeApiController.Store.cs b/BTCPayServer/Controllers/GreenField/GreenfieldLightningNodeApiController.Store.cs index d87695df6..57813a8fe 100644 --- a/BTCPayServer/Controllers/GreenField/GreenfieldLightningNodeApiController.Store.cs +++ b/BTCPayServer/Controllers/GreenField/GreenfieldLightningNodeApiController.Store.cs @@ -13,7 +13,6 @@ using BTCPayServer.Payments; using BTCPayServer.Payments.Lightning; using BTCPayServer.Services; using BTCPayServer.Services.Invoices; -using ExchangeSharp; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Mvc; diff --git a/BTCPayServer/Controllers/UIInvoiceController.UI.cs b/BTCPayServer/Controllers/UIInvoiceController.UI.cs index a60dbe666..dffe791df 100644 --- a/BTCPayServer/Controllers/UIInvoiceController.UI.cs +++ b/BTCPayServer/Controllers/UIInvoiceController.UI.cs @@ -150,8 +150,8 @@ namespace BTCPayServer.Controllers HasRefund = invoice.Refunds.Any(), CanRefund = invoiceState.CanRefund(), Refunds = invoice.Refunds, - ShowCheckout = invoice.Status == InvoiceStatusLegacy.New, - ShowReceipt = invoice.Status.ToModernStatus() == InvoiceStatus.Settled && (invoice.ReceiptOptions?.Enabled ?? receipt.Enabled is true), + ShowCheckout = invoice.Status == InvoiceStatus.New, + ShowReceipt = invoice.Status == InvoiceStatus.Settled && (invoice.ReceiptOptions?.Enabled ?? receipt.Enabled is true), Deliveries = (await _InvoiceRepository.GetWebhookDeliveries(invoiceId)) .Select(c => new Models.StoreViewModels.DeliveryViewModel(c)) .ToList() @@ -215,7 +215,7 @@ namespace BTCPayServer.Controllers InvoiceId = i.Id, OrderId = i.Metadata?.OrderId, OrderUrl = i.Metadata?.OrderUrl, - Status = i.Status.ToModernStatus(), + Status = i.Status, Currency = i.Currency, Timestamp = i.InvoiceTime, StoreName = store.StoreName, @@ -223,7 +223,7 @@ namespace BTCPayServer.Controllers ReceiptOptions = receipt }; - if (i.Status.ToModernStatus() != InvoiceStatus.Settled) + if (i.Status != InvoiceStatus.Settled) { return View(vm); } @@ -929,9 +929,7 @@ namespace BTCPayServer.Controllers _ => null }, ReceivedConfirmations = handler is BitcoinLikePaymentHandler bh ? invoice.GetAllBitcoinPaymentData(bh, false).FirstOrDefault()?.ConfirmationCount : null, -#pragma warning disable CS0618 // Type or member is obsolete - Status = invoice.StatusString, -#pragma warning restore CS0618 // Type or member is obsolete + Status = invoice.Status.ToString(), NetworkFee = prompt.PaymentMethodFee, IsMultiCurrency = invoice.GetPayments(false).Select(p => p.PaymentMethodId).Concat(new[] { prompt.PaymentMethodId }).Distinct().Count() > 1, StoreId = store.Id, @@ -1038,7 +1036,7 @@ namespace BTCPayServer.Controllers if (!HttpContext.WebSockets.IsWebSocketRequest) return NotFound(); 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(); var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync(); CompositeDisposable leases = new CompositeDisposable(); @@ -1138,7 +1136,7 @@ namespace BTCPayServer.Controllers model.Invoices.Add(new InvoiceModel { Status = state, - ShowCheckout = invoice.Status == InvoiceStatusLegacy.New, + ShowCheckout = invoice.Status == InvoiceStatus.New, Date = invoice.InvoiceTime, InvoiceId = invoice.Id, OrderId = invoice.Metadata.OrderId ?? string.Empty, @@ -1322,12 +1320,12 @@ namespace BTCPayServer.Controllers if (newState == "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") { 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); diff --git a/BTCPayServer/Controllers/UIInvoiceController.cs b/BTCPayServer/Controllers/UIInvoiceController.cs index be824bfd4..5934fea90 100644 --- a/BTCPayServer/Controllers/UIInvoiceController.cs +++ b/BTCPayServer/Controllers/UIInvoiceController.cs @@ -235,7 +235,7 @@ namespace BTCPayServer.Controllers } var getAppsTaggingStore = _InvoiceRepository.GetAppsTaggingStore(store.Id); - entity.Status = InvoiceStatusLegacy.New; + entity.Status = InvoiceStatus.New; entity.UpdateTotals(); diff --git a/BTCPayServer/Controllers/UILNURLController.cs b/BTCPayServer/Controllers/UILNURLController.cs index 16996fc6d..c931997aa 100644 --- a/BTCPayServer/Controllers/UILNURLController.cs +++ b/BTCPayServer/Controllers/UILNURLController.cs @@ -656,7 +656,7 @@ namespace BTCPayServer if (store is null) return NotFound(); - if (i.Status == InvoiceStatusLegacy.New) + if (i.Status == InvoiceStatus.New) { var pmi = GetLNUrlPaymentMethodId(cryptoCode, store, out var lnurlSupportedPaymentMethod); if (pmi is null) diff --git a/BTCPayServer/Controllers/UIPaymentRequestController.cs b/BTCPayServer/Controllers/UIPaymentRequestController.cs index 5c0844bd0..89551f4b2 100644 --- a/BTCPayServer/Controllers/UIPaymentRequestController.cs +++ b/BTCPayServer/Controllers/UIPaymentRequestController.cs @@ -392,7 +392,7 @@ namespace BTCPayServer.Controllers } 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()) { diff --git a/BTCPayServer/Data/InvoiceDataExtensions.cs b/BTCPayServer/Data/InvoiceDataExtensions.cs index 9a240a72f..50d028ca3 100644 --- a/BTCPayServer/Data/InvoiceDataExtensions.cs +++ b/BTCPayServer/Data/InvoiceDataExtensions.cs @@ -60,7 +60,7 @@ namespace BTCPayServer.Data } public static InvoiceState GetInvoiceState(this InvoiceData invoiceData) { - return new InvoiceState(invoiceData.Status ?? "new", invoiceData.ExceptionStatus); + return new InvoiceState(invoiceData.Status, invoiceData.ExceptionStatus); } } } diff --git a/BTCPayServer/HostedServices/BitpayIPNSender.cs b/BTCPayServer/HostedServices/BitpayIPNSender.cs index 2c9fffec3..aeb4b4811 100644 --- a/BTCPayServer/HostedServices/BitpayIPNSender.cs +++ b/BTCPayServer/HostedServices/BitpayIPNSender.cs @@ -5,6 +5,7 @@ using System.Net.Http; using System.Text; using System.Threading; using System.Threading.Tasks; +using BTCPayServer.Client.Models; using BTCPayServer.Events; using BTCPayServer.Payments; using BTCPayServer.Services; @@ -101,11 +102,11 @@ namespace BTCPayServer.HostedServices // So here, we just override the status expressed by the notification if (invoiceEvent.Name == InvoiceEvent.Confirmed) { - notification.Data.Status = InvoiceState.ToString(InvoiceStatusLegacy.Confirmed); + notification.Data.Status = "confirmed"; } if (invoiceEvent.Name == InvoiceEvent.PaidInFull) { - notification.Data.Status = InvoiceState.ToString(InvoiceStatusLegacy.Paid); + notification.Data.Status = "paid"; } ////////////////// diff --git a/BTCPayServer/HostedServices/InvoiceWatcher.cs b/BTCPayServer/HostedServices/InvoiceWatcher.cs index f9e897812..a92c2cc2d 100644 --- a/BTCPayServer/HostedServices/InvoiceWatcher.cs +++ b/BTCPayServer/HostedServices/InvoiceWatcher.cs @@ -81,10 +81,10 @@ namespace BTCPayServer.HostedServices private void UpdateInvoice(UpdateInvoiceContext context) { var invoice = context.Invoice; - if (invoice.Status == InvoiceStatusLegacy.New && invoice.ExpirationTime <= DateTimeOffset.UtcNow) + if (invoice.Status == InvoiceStatus.New && invoice.ExpirationTime <= DateTimeOffset.UtcNow) { context.MarkDirty(); - invoice.Status = InvoiceStatusLegacy.Expired; + invoice.Status = InvoiceStatus.Expired; var paidPartial = invoice.ExceptionStatus == InvoiceExceptionStatus.PaidPartial; context.Events.Add(new InvoiceEvent(invoice, InvoiceEvent.Expired) { PaidPartial = paidPartial }); if (invoice.ExceptionStatus == InvoiceExceptionStatus.PaidPartial) @@ -92,17 +92,17 @@ namespace BTCPayServer.HostedServices } 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() ? hasPayment : !invoice.IsUnderPaid; if (isPaid) { - if (invoice.Status == InvoiceStatusLegacy.New) + if (invoice.Status == InvoiceStatus.New) { context.Events.Add(new InvoiceEvent(invoice, InvoiceEvent.PaidInFull)); - invoice.Status = InvoiceStatusLegacy.Paid; + invoice.Status = InvoiceStatus.Processing; if (invoice.IsUnsetTopUp()) { invoice.ExceptionStatus = InvoiceExceptionStatus.None; @@ -118,7 +118,7 @@ namespace BTCPayServer.HostedServices } 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; context.Events.Add(new InvoiceEvent(invoice, InvoiceEvent.PaidAfterExpiration)); @@ -134,7 +134,7 @@ namespace BTCPayServer.HostedServices } // 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) { @@ -150,13 +150,13 @@ namespace BTCPayServer.HostedServices if (invoice.IsUnderPaid) { - invoice.Status = InvoiceStatusLegacy.New; + invoice.Status = InvoiceStatus.New; invoice.ExceptionStatus = hasPayment ? InvoiceExceptionStatus.PaidPartial : InvoiceExceptionStatus.None; 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 unconfirmedPaid = unconfPayments.Select(p => p.InvoicePaidAmount.Net).Sum(); @@ -168,12 +168,12 @@ namespace BTCPayServer.HostedServices (minimumDue > 0.0m)) { context.Events.Add(new InvoiceEvent(invoice, InvoiceEvent.FailedToConfirm)); - invoice.Status = InvoiceStatusLegacy.Invalid; + invoice.Status = InvoiceStatus.Invalid; context.MarkDirty(); } 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.Completed)); context.MarkDirty(); @@ -292,8 +292,8 @@ namespace BTCPayServer.HostedServices _eventAggregator.Publish(evt, evt.GetType()); } - if (invoice.Status == InvoiceStatusLegacy.Complete || - ((invoice.Status == InvoiceStatusLegacy.Invalid || invoice.Status == InvoiceStatusLegacy.Expired) && invoice.MonitoringExpiration < DateTimeOffset.UtcNow)) + if (invoice.Status == InvoiceStatus.Settled || + ((invoice.Status == InvoiceStatus.Invalid || invoice.Status == InvoiceStatus.Expired) && invoice.MonitoringExpiration < DateTimeOffset.UtcNow)) { var extendInvoiceMonitoring = await UpdateConfirmationCount(invoice); diff --git a/BTCPayServer/HostedServices/Webhooks/InvoiceWebhookProvider.cs b/BTCPayServer/HostedServices/Webhooks/InvoiceWebhookProvider.cs index 7fdc3ba99..25d87f79b 100644 --- a/BTCPayServer/HostedServices/Webhooks/InvoiceWebhookProvider.cs +++ b/BTCPayServer/HostedServices/Webhooks/InvoiceWebhookProvider.cs @@ -97,8 +97,8 @@ public class InvoiceWebhookProvider : WebhookProvider return new WebhookInvoiceReceivedPaymentEvent(WebhookEventType.InvoiceReceivedPayment, storeId) { AfterExpiration = - invoiceEvent.Invoice.Status.ToModernStatus() == InvoiceStatus.Expired || - invoiceEvent.Invoice.Status.ToModernStatus() == InvoiceStatus.Invalid, + invoiceEvent.Invoice.Status == InvoiceStatus.Expired || + invoiceEvent.Invoice.Status == InvoiceStatus.Invalid, PaymentMethodId = invoiceEvent.Payment.PaymentMethodId.ToString(), Payment = GreenfieldInvoiceController.ToPaymentModel(invoiceEvent.Invoice, invoiceEvent.Payment), StoreId = invoiceEvent.Invoice.StoreId @@ -107,8 +107,8 @@ public class InvoiceWebhookProvider : WebhookProvider return new WebhookInvoiceReceivedPaymentEvent(WebhookEventType.InvoicePaymentSettled, storeId) { AfterExpiration = - invoiceEvent.Invoice.Status.ToModernStatus() == InvoiceStatus.Expired || - invoiceEvent.Invoice.Status.ToModernStatus() == InvoiceStatus.Invalid, + invoiceEvent.Invoice.Status == InvoiceStatus.Expired || + invoiceEvent.Invoice.Status == InvoiceStatus.Invalid, PaymentMethodId = invoiceEvent.Payment.PaymentMethodId.ToString(), Payment = GreenfieldInvoiceController.ToPaymentModel(invoiceEvent.Invoice, invoiceEvent.Payment), StoreId = invoiceEvent.Invoice.StoreId diff --git a/BTCPayServer/Hosting/BTCPayServerServices.cs b/BTCPayServer/Hosting/BTCPayServerServices.cs index 8141867c7..ba3814018 100644 --- a/BTCPayServer/Hosting/BTCPayServerServices.cs +++ b/BTCPayServer/Hosting/BTCPayServerServices.cs @@ -48,7 +48,6 @@ using BTCPayServer.Services.PaymentRequests; using BTCPayServer.Services.Rates; using BTCPayServer.Services.Stores; using BTCPayServer.Services.Wallets; -using ExchangeSharp; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; @@ -71,6 +70,8 @@ using BTCPayServer.Services.WalletFileParsing; using BTCPayServer.Payments.LNURLPay; using System.Collections.Generic; using BTCPayServer.Payouts; +using ExchangeSharp; + @@ -658,7 +659,7 @@ o.GetRequiredService>().ToDictionary(o => o.P { services.AddSingleton(new TransactionLinkProviders.Entry(cryptoCode, provider)); } - public static void AddRateProviderExchangeSharp(this IServiceCollection services, RateSourceInfo rateInfo) where T : ExchangeAPI + public static void AddRateProviderExchangeSharp(this IServiceCollection services, RateSourceInfo rateInfo) where T : ExchangeSharp.ExchangeAPI { services.AddSingleton>(o => { diff --git a/BTCPayServer/Models/PaymentRequestViewModels/ListPaymentRequestsViewModel.cs b/BTCPayServer/Models/PaymentRequestViewModels/ListPaymentRequestsViewModel.cs index c3c6da860..94de30873 100644 --- a/BTCPayServer/Models/PaymentRequestViewModels/ListPaymentRequestsViewModel.cs +++ b/BTCPayServer/Models/PaymentRequestViewModels/ListPaymentRequestsViewModel.cs @@ -149,8 +149,8 @@ namespace BTCPayServer.Models.PaymentRequestViewModels { static HashSet stateAllowedToDisplay = new HashSet { - new InvoiceState(InvoiceStatusLegacy.New, InvoiceExceptionStatus.None), - new InvoiceState(InvoiceStatusLegacy.New, InvoiceExceptionStatus.PaidPartial), + new InvoiceState(InvoiceStatus.New, InvoiceExceptionStatus.None), + new InvoiceState(InvoiceStatus.New, InvoiceExceptionStatus.PaidPartial), }; public InvoiceList() { @@ -187,7 +187,6 @@ namespace BTCPayServer.Models.PaymentRequestViewModels public decimal Amount { get; set; } public string AmountFormatted { get; set; } public InvoiceState State { get; set; } - public InvoiceStatusLegacy Status { get; set; } public string StateFormatted { get; set; } public List Payments { get; set; } diff --git a/BTCPayServer/PaymentRequest/PaymentRequestService.cs b/BTCPayServer/PaymentRequest/PaymentRequestService.cs index 681fd2978..b2f43bd92 100644 --- a/BTCPayServer/PaymentRequest/PaymentRequestService.cs +++ b/BTCPayServer/PaymentRequest/PaymentRequestService.cs @@ -101,7 +101,7 @@ namespace BTCPayServer.PaymentRequest var paymentStats = _invoiceRepository.GetContributionsByPaymentMethodId(blob.Currency, invoices, true); var amountDue = blob.Amount - paymentStats.TotalCurrency; var pendingInvoice = invoices.OrderByDescending(entity => entity.InvoiceTime) - .FirstOrDefault(entity => entity.Status == InvoiceStatusLegacy.New); + .FirstOrDefault(entity => entity.Status == InvoiceStatus.New); return new ViewPaymentRequestViewModel(pr) { @@ -123,8 +123,8 @@ namespace BTCPayServer.PaymentRequest var state = entity.GetInvoiceState(); var payments = ViewPaymentRequestViewModel.PaymentRequestInvoicePayment.GetViewModels(entity, _displayFormatter, _transactionLinkProviders, _handlers); - if (state.Status == InvoiceStatusLegacy.Invalid || - state.Status == InvoiceStatusLegacy.Expired && !payments.Any()) + if (state.Status == InvoiceStatus.Invalid || + state.Status == InvoiceStatus.Expired && !payments.Any()) return null; return new ViewPaymentRequestViewModel.PaymentRequestInvoice diff --git a/BTCPayServer/Payments/Lightning/LightningListener.cs b/BTCPayServer/Payments/Lightning/LightningListener.cs index 0b7fe5c1f..9cdeed766 100644 --- a/BTCPayServer/Payments/Lightning/LightningListener.cs +++ b/BTCPayServer/Payments/Lightning/LightningListener.cs @@ -202,7 +202,7 @@ retry: _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(); if (pm.Calculate().Due > 0m) @@ -213,7 +213,7 @@ retry: })); leases.Add(_Aggregator.SubscribeAsync(async inv => { - if (inv.State.Status == InvoiceStatusLegacy.New && + if (inv.State.Status == InvoiceStatus.New && inv.State.ExceptionStatus == InvoiceExceptionStatus.PaidPartial) { var invoice = await _InvoiceRepository.GetInvoice(inv.InvoiceId); diff --git a/BTCPayServer/Plugins/Crowdfund/CrowdfundPlugin.cs b/BTCPayServer/Plugins/Crowdfund/CrowdfundPlugin.cs index f94652a75..f38159d09 100644 --- a/BTCPayServer/Plugins/Crowdfund/CrowdfundPlugin.cs +++ b/BTCPayServer/Plugins/Crowdfund/CrowdfundPlugin.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using BTCPayServer.Abstractions.Contracts; using BTCPayServer.Abstractions.Models; using BTCPayServer.Abstractions.Services; +using BTCPayServer.Client.Models; using BTCPayServer.Configuration; using BTCPayServer.Data; using BTCPayServer.Models; @@ -113,10 +114,10 @@ namespace BTCPayServer.Plugins.Crowdfund public override async Task GetInfo(AppData appData) { var settings = appData.GetSettings(); - var resetEvery = settings.StartDate.HasValue ? settings.ResetEvery : CrowdfundResetEvery.Never; + var resetEvery = settings.StartDate.HasValue ? settings.ResetEvery : Services.Apps.CrowdfundResetEvery.Never; DateTime? lastResetDate = 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; @@ -126,16 +127,16 @@ namespace BTCPayServer.Plugins.Crowdfund lastResetDate = nextResetDate; switch (resetEvery) { - case CrowdfundResetEvery.Hour: + case Services.Apps.CrowdfundResetEvery.Hour: nextResetDate = lastResetDate.Value.AddHours(settings.ResetEveryAmount); break; - case CrowdfundResetEvery.Day: + case Services.Apps.CrowdfundResetEvery.Day: nextResetDate = lastResetDate.Value.AddDays(settings.ResetEveryAmount); break; - case CrowdfundResetEvery.Month: + case Services.Apps.CrowdfundResetEvery.Month: nextResetDate = lastResetDate.Value.AddMonths(settings.ResetEveryAmount); break; - case CrowdfundResetEvery.Year: + case Services.Apps.CrowdfundResetEvery.Year: nextResetDate = lastResetDate.Value.AddYears(settings.ResetEveryAmount); break; } @@ -206,11 +207,11 @@ namespace BTCPayServer.Plugins.Crowdfund DisqusShortname = settings.DisqusShortname, AnimationsEnabled = settings.AnimationsEnabled, ResetEveryAmount = settings.ResetEveryAmount, - ResetEvery = Enum.GetName(typeof(CrowdfundResetEvery), settings.ResetEvery), + ResetEvery = Enum.GetName(typeof(Services.Apps.CrowdfundResetEvery), settings.ResetEvery), DisplayPerksRanking = settings.DisplayPerksRanking, PerkCount = perkCount, PerkValue = perkValue, - NeverReset = settings.ResetEvery == CrowdfundResetEvery.Never, + NeverReset = settings.ResetEvery == Services.Apps.CrowdfundResetEvery.Never, FormUrl = formUrl, Sounds = settings.Sounds, AnimationColors = settings.AnimationColors, @@ -264,17 +265,17 @@ namespace BTCPayServer.Plugins.Crowdfund 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) { - return !(entity.Status == InvoiceStatusLegacy.Complete || entity.Status == InvoiceStatusLegacy.Confirmed); + return entity.Status != InvoiceStatus.Settled; } private static bool IsComplete(InvoiceEntity entity) { - return entity.Status == InvoiceStatusLegacy.Complete || entity.Status == InvoiceStatusLegacy.Confirmed; + return entity.Status == InvoiceStatus.Settled; } } } diff --git a/BTCPayServer/Plugins/NFC/NFCController.cs b/BTCPayServer/Plugins/NFC/NFCController.cs index 2d91cba37..4c11bdff7 100644 --- a/BTCPayServer/Plugins/NFC/NFCController.cs +++ b/BTCPayServer/Plugins/NFC/NFCController.cs @@ -48,7 +48,7 @@ namespace BTCPayServer.Plugins.NFC public async Task SubmitLNURLWithdrawForInvoice([FromBody] SubmitRequest request) { var invoice = await _invoiceRepository.GetInvoice(request.InvoiceId); - if (invoice?.Status is not InvoiceStatusLegacy.New) + if (invoice?.Status is not InvoiceStatus.New) { return NotFound(); } diff --git a/BTCPayServer/Plugins/PluginBuilderClient.cs b/BTCPayServer/Plugins/PluginBuilderClient.cs index f37ef46be..1858feb51 100644 --- a/BTCPayServer/Plugins/PluginBuilderClient.cs +++ b/BTCPayServer/Plugins/PluginBuilderClient.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Net.Http; using System.Text.RegularExpressions; using System.Threading.Tasks; -using ExchangeSharp; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using static System.Net.WebRequestMethods; diff --git a/BTCPayServer/Plugins/PointOfSale/Controllers/UIPointOfSaleController.cs b/BTCPayServer/Plugins/PointOfSale/Controllers/UIPointOfSaleController.cs index aa4ea7a2a..effb55267 100644 --- a/BTCPayServer/Plugins/PointOfSale/Controllers/UIPointOfSaleController.cs +++ b/BTCPayServer/Plugins/PointOfSale/Controllers/UIPointOfSaleController.cs @@ -539,15 +539,7 @@ namespace BTCPayServer.Plugins.PointOfSale.Controllers return NotFound(); var from = DateTimeOffset.UtcNow - TimeSpan.FromDays(3); - var invoices = await AppService.GetInvoicesForApp(_invoiceRepository, app, from, new[] - { - 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 invoices = await AppService.GetInvoicesForApp(_invoiceRepository, app, from); var recent = invoices .Take(10) .Select(i => new JObject @@ -555,7 +547,7 @@ namespace BTCPayServer.Plugins.PointOfSale.Controllers ["id"] = i.Id, ["date"] = i.InvoiceTime, ["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 }) }); return Json(recent); diff --git a/BTCPayServer/Plugins/Shopify/ShopifyOrderMarkerHostedService.cs b/BTCPayServer/Plugins/Shopify/ShopifyOrderMarkerHostedService.cs index c5849b285..83ea88100 100644 --- a/BTCPayServer/Plugins/Shopify/ShopifyOrderMarkerHostedService.cs +++ b/BTCPayServer/Plugins/Shopify/ShopifyOrderMarkerHostedService.cs @@ -50,15 +50,14 @@ namespace BTCPayServer.Plugins.Shopify var shopifyOrderId = invoice.GetInternalTags(SHOPIFY_ORDER_ID_PREFIX).FirstOrDefault(); 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) { //you have failed us, customer await RegisterTransaction(invoice, shopifyOrderId, false); } - else if (new[] { InvoiceStatusLegacy.Complete, InvoiceStatusLegacy.Confirmed }.Contains( - invoice.Status)) + else if (invoice.Status == InvoiceStatus.Settled) { await RegisterTransaction(invoice, shopifyOrderId, true); } diff --git a/BTCPayServer/Plugins/Shopify/UIShopifyController.cs b/BTCPayServer/Plugins/Shopify/UIShopifyController.cs index 9d5c83764..3e14ba654 100644 --- a/BTCPayServer/Plugins/Shopify/UIShopifyController.cs +++ b/BTCPayServer/Plugins/Shopify/UIShopifyController.cs @@ -119,7 +119,7 @@ namespace BTCPayServer.Plugins.Shopify var firstInvoiceStillPending = matchedExistingInvoices.FirstOrDefault(entity => - entity.GetInvoiceState().Status == InvoiceStatusLegacy.New); + entity.GetInvoiceState().Status == InvoiceStatus.New); if (firstInvoiceStillPending != null) { return Ok(new @@ -131,7 +131,7 @@ namespace BTCPayServer.Plugins.Shopify var firstInvoiceSettled = matchedExistingInvoices.LastOrDefault(entity => - new[] { InvoiceStatusLegacy.Paid, InvoiceStatusLegacy.Complete, InvoiceStatusLegacy.Confirmed } + new[] { InvoiceStatus.Processing, InvoiceStatus.Settled } .Contains( 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 (client != null && order?.FinancialStatus == "pending" && - firstInvoiceSettled.Status != InvoiceStatusLegacy.Paid) + firstInvoiceSettled.Status != InvoiceStatus.Processing) { await new OrderTransactionRegisterLogic(client).Process(orderId, firstInvoiceSettled.Id, firstInvoiceSettled.Currency, diff --git a/BTCPayServer/Services/Apps/AppService.cs b/BTCPayServer/Services/Apps/AppService.cs index fdfb566b5..e1a5f0b55 100644 --- a/BTCPayServer/Services/Apps/AppService.cs +++ b/BTCPayServer/Services/Apps/AppService.cs @@ -7,6 +7,7 @@ using System.IO; using System.Linq; using System.Threading.Tasks; using BTCPayServer.Client; +using BTCPayServer.Client.Models; using BTCPayServer.Data; using BTCPayServer.Models.AppViewModels; using BTCPayServer.Plugins.Crowdfund; @@ -93,9 +94,8 @@ namespace BTCPayServer.Services.Apps var paidInvoices = await GetInvoicesForApp(_InvoiceRepository, appData, null, new[] { - InvoiceState.ToString(InvoiceStatusLegacy.Paid), - InvoiceState.ToString(InvoiceStatusLegacy.Confirmed), - InvoiceState.ToString(InvoiceStatusLegacy.Complete) + InvoiceStatus.Processing.ToString(), + InvoiceStatus.Settled.ToString() }); 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), new[] { - InvoiceState.ToString(InvoiceStatusLegacy.Paid), - InvoiceState.ToString(InvoiceStatusLegacy.Confirmed), - InvoiceState.ToString(InvoiceStatusLegacy.Complete) + InvoiceStatus.Processing.ToString(), + InvoiceStatus.Settled.ToString() }); return await salesType.GetSalesStats(app, paidInvoices, numberOfDays); @@ -185,7 +184,7 @@ namespace BTCPayServer.Services.Apps { 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, Date = e.InvoiceTime.Date }); @@ -220,11 +219,7 @@ namespace BTCPayServer.Services.Apps { StoreId = new[] { appData.StoreDataId }, TextSearch = appData.TagAllInvoices ? null : GetAppSearchTerm(appData), - Status = status ?? new[]{ - InvoiceState.ToString(InvoiceStatusLegacy.New), - InvoiceState.ToString(InvoiceStatusLegacy.Paid), - InvoiceState.ToString(InvoiceStatusLegacy.Confirmed), - InvoiceState.ToString(InvoiceStatusLegacy.Complete)}, + Status = status, StartDate = startDate }); @@ -297,8 +292,8 @@ namespace BTCPayServer.Services.Apps { case PointOfSaleAppType.AppType: var settings = app.GetSettings(); - string posViewStyle = (settings.EnableShoppingCart ? PosViewType.Cart : settings.DefaultView).ToString(); - style = typeof(PosViewType).DisplayName(posViewStyle); + string posViewStyle = (settings.EnableShoppingCart ? Plugins.PointOfSale.PosViewType.Cart : settings.DefaultView).ToString(); + style = typeof(Plugins.PointOfSale.PosViewType).DisplayName(posViewStyle); break; default: diff --git a/BTCPayServer/Services/Fees/MempoolSpaceFeeProvider.cs b/BTCPayServer/Services/Fees/MempoolSpaceFeeProvider.cs index 777002bde..561fd5caf 100644 --- a/BTCPayServer/Services/Fees/MempoolSpaceFeeProvider.cs +++ b/BTCPayServer/Services/Fees/MempoolSpaceFeeProvider.cs @@ -7,8 +7,6 @@ using System.Runtime.InteropServices; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; -using AngleSharp.Dom; -using ExchangeSharp; using Microsoft.Extensions.Caching.Memory; using NBitcoin; using Org.BouncyCastle.Asn1.X509; diff --git a/BTCPayServer/Services/InvoiceActivator.cs b/BTCPayServer/Services/InvoiceActivator.cs index 873f3dcbb..5b5df86e4 100644 --- a/BTCPayServer/Services/InvoiceActivator.cs +++ b/BTCPayServer/Services/InvoiceActivator.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Threading.Tasks; +using BTCPayServer.Client.Models; using BTCPayServer.Data; using BTCPayServer.Events; using BTCPayServer.Logging; @@ -40,7 +41,7 @@ namespace BTCPayServer.Services public async Task ActivateInvoicePaymentMethod(string invoiceId, PaymentMethodId paymentMethodId, bool forceNew = false) { var invoice = await _invoiceRepository.GetInvoice(invoiceId); - if (invoice?.GetInvoiceState().Status is not InvoiceStatusLegacy.New) + if (invoice?.GetInvoiceState().Status is not InvoiceStatus.New) return false; var store = await _storeRepository.FindStore(invoice.StoreId); if (store is null) diff --git a/BTCPayServer/Services/Invoices/InvoiceEntity.cs b/BTCPayServer/Services/Invoices/InvoiceEntity.cs index 08ab64ba4..804769437 100644 --- a/BTCPayServer/Services/Invoices/InvoiceEntity.cs +++ b/BTCPayServer/Services/Invoices/InvoiceEntity.cs @@ -437,13 +437,9 @@ namespace BTCPayServer.Services.Invoices public decimal PaidFee { get; set; } [JsonIgnore] - public InvoiceStatusLegacy Status { get; set; } - [JsonIgnore] - public string StatusString => InvoiceState.ToString(Status); + public InvoiceStatus Status { get; set; } [JsonIgnore] public InvoiceExceptionStatus ExceptionStatus { get; set; } - [JsonIgnore] - public string ExceptionStatusString => InvoiceState.ToString(ExceptionStatus); [Obsolete("Use GetPayments instead")] [JsonIgnore] @@ -541,10 +537,8 @@ namespace BTCPayServer.Services.Invoices CurrentTime = DateTimeOffset.UtcNow, InvoiceTime = InvoiceTime, ExpirationTime = ExpirationTime, -#pragma warning disable CS0618 // Type or member is obsolete - Status = StatusString, - ExceptionStatus = ExceptionStatus == InvoiceExceptionStatus.None ? new JValue(false) : new JValue(ExceptionStatusString), -#pragma warning restore CS0618 // Type or member is obsolete + Status = Status.ToLegacyStatusString(), + ExceptionStatus = ExceptionStatus == InvoiceExceptionStatus.None ? new JValue(false) : new JValue(ExceptionStatus.ToLegacyExceptionStatusString()), Currency = Currency, PaymentSubtotals = new Dictionary(), PaymentTotals = new Dictionary(), @@ -739,160 +733,76 @@ namespace BTCPayServer.Services.Invoices public enum InvoiceStatusLegacy { - New, - Paid, - Expired, - Invalid, - Complete, - Confirmed } public static class InvoiceStatusLegacyExtensions { - public static InvoiceStatus ToModernStatus(this InvoiceStatusLegacy legacy) - { - switch (legacy) + public static string ToLegacyStatusString(this InvoiceStatus status) => + status switch { - case InvoiceStatusLegacy.Complete: - case InvoiceStatusLegacy.Confirmed: - return InvoiceStatus.Settled; - case InvoiceStatusLegacy.Expired: - return InvoiceStatus.Expired; - case InvoiceStatusLegacy.Invalid: - return InvoiceStatus.Invalid; - case InvoiceStatusLegacy.Paid: - return InvoiceStatus.Processing; - case InvoiceStatusLegacy.New: - return InvoiceStatus.New; - default: - throw new NotSupportedException(); - } - } + InvoiceStatus.Settled => "complete", + InvoiceStatus.Expired => "expired", + InvoiceStatus.Invalid => "invalid", + InvoiceStatus.Processing => "paid", + InvoiceStatus.New => "new", + _ => throw new NotSupportedException(status.ToString()) + }; + public static string ToLegacyExceptionStatusString(this InvoiceExceptionStatus status) => + status switch + { + InvoiceExceptionStatus.None => string.Empty, + InvoiceExceptionStatus.PaidLate => "paidLater", + 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 _StringToInvoiceStatus; - static readonly Dictionary _InvoiceStatusToString; - - static readonly Dictionary _StringToExceptionStatus; - static readonly Dictionary _ExceptionStatusToString; - - static InvoiceState() + public InvoiceState(string status, string exceptionStatus): + this(Enum.Parse(status), exceptionStatus switch { "None" or "" or null => InvoiceExceptionStatus.None, _ => Enum.Parse(exceptionStatus) }) { - _StringToInvoiceStatus = new Dictionary(); - _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(); - _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() { - return Status is InvoiceStatusLegacy.New or InvoiceStatusLegacy.Paid or InvoiceStatusLegacy.Expired or InvoiceStatusLegacy.Invalid || - (Status != InvoiceStatusLegacy.Complete && ExceptionStatus == InvoiceExceptionStatus.Marked); + return Status is InvoiceStatus.New or InvoiceStatus.Processing or InvoiceStatus.Expired or InvoiceStatus.Invalid || + (Status != InvoiceStatus.Settled && ExceptionStatus == InvoiceExceptionStatus.Marked); } public bool CanMarkInvalid() { - return Status is InvoiceStatusLegacy.New or InvoiceStatusLegacy.Paid or InvoiceStatusLegacy.Expired || - (Status != InvoiceStatusLegacy.Invalid && ExceptionStatus == InvoiceExceptionStatus.Marked); + return Status is InvoiceStatus.New or InvoiceStatus.Processing or InvoiceStatus.Expired || + (Status != InvoiceStatus.Invalid && ExceptionStatus == InvoiceExceptionStatus.Marked); } public bool CanRefund() { - return Status == InvoiceStatusLegacy.Confirmed || - Status == InvoiceStatusLegacy.Complete || - (Status == InvoiceStatusLegacy.Expired && + return + Status == InvoiceStatus.Settled || + (Status == InvoiceStatus.Expired && (ExceptionStatus == InvoiceExceptionStatus.PaidLate || ExceptionStatus == InvoiceExceptionStatus.PaidOver || ExceptionStatus == InvoiceExceptionStatus.PaidPartial)) || - Status == InvoiceStatusLegacy.Invalid; + Status == InvoiceStatus.Invalid; } public bool IsSettled() { - return Status == InvoiceStatusLegacy.Confirmed || - Status == InvoiceStatusLegacy.Complete || - (Status == InvoiceStatusLegacy.Expired && + return + Status == InvoiceStatus.Settled || + (Status == InvoiceStatus.Expired && 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() { - return Status.ToModernStatus() + ExceptionStatus switch + return Status + ExceptionStatus switch { InvoiceExceptionStatus.PaidOver => " (paid over)", InvoiceExceptionStatus.PaidLate => " (paid late)", InvoiceExceptionStatus.PaidPartial => " (paid partial)", InvoiceExceptionStatus.Marked => " (marked)", - InvoiceExceptionStatus.Invalid => " (invalid)", _ => "" }; } diff --git a/BTCPayServer/Services/Invoices/InvoiceRepository.cs b/BTCPayServer/Services/Invoices/InvoiceRepository.cs index 5c469f1d3..06d7c70e5 100644 --- a/BTCPayServer/Services/Invoices/InvoiceRepository.cs +++ b/BTCPayServer/Services/Invoices/InvoiceRepository.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Globalization; using System.Linq; +using System.Linq.Expressions; using System.Threading; using System.Threading.Tasks; using BTCPayServer.Abstractions.Extensions; @@ -230,9 +231,7 @@ retry: StoreDataId = invoice.StoreId, Id = invoice.Id, OrderId = invoice.Metadata.OrderId, -#pragma warning disable CS0618 // Type or member is obsolete - Status = invoice.StatusString, -#pragma warning restore CS0618 // Type or member is obsolete + Status = invoice.Status.ToString(), ItemCode = invoice.Metadata.ItemCode, Archived = false }; @@ -451,8 +450,8 @@ retry: new { id = invoiceId, - status = InvoiceState.ToString(invoiceState.Status), - exstatus = InvoiceState.ToString(invoiceState.ExceptionStatus) + status = invoiceState.Status.ToString(), + exstatus = invoiceState.ExceptionStatus is InvoiceExceptionStatus.None ? string.Empty : invoiceState.ExceptionStatus.ToString() }); } internal async Task UpdateInvoicePrice(string invoiceId, decimal price) @@ -559,7 +558,6 @@ retry: context.Attach(invoiceData); string eventName; - string legacyStatus; switch (status) { case InvoiceStatus.Settled: @@ -569,7 +567,6 @@ retry: } eventName = InvoiceEvent.MarkedCompleted; - legacyStatus = InvoiceStatusLegacy.Complete.ToString(); break; case InvoiceStatus.Invalid: if (!invoiceData.GetInvoiceState().CanMarkInvalid()) @@ -577,14 +574,13 @@ retry: return false; } eventName = InvoiceEvent.MarkedInvalid; - legacyStatus = InvoiceStatusLegacy.Invalid.ToString(); break; default: return false; } - invoiceData.Status = legacyStatus.ToLowerInvariant(); - invoiceData.ExceptionStatus = InvoiceExceptionStatus.Marked.ToString().ToLowerInvariant(); + invoiceData.Status = status.ToString(); + invoiceData.ExceptionStatus = InvoiceExceptionStatus.Marked.ToString(); try { await context.SaveChangesAsync(); @@ -705,42 +701,50 @@ retry: } 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(); 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(); - // 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()) { - query = query.Where(i => statusSet.Contains(i.Status) || exceptionStatusSet.Contains(i.ExceptionStatus)); + Expression> statusExpression = null; + Expression> 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>(predicate, parameter); + query = query.Where(expression); } if (queryObject.Unusual != null) { 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) @@ -795,27 +799,31 @@ retry: 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) { status = status.ToLowerInvariant(); - switch (status) + return status switch { - case "paidover": - case "over": - case "overpaid": - status = "paidOver"; - break; - case "paidlate": - case "late": - status = "paidLate"; - break; - case "paidpartial": - case "underpaid": - case "partial": - status = "paidPartial"; - break; - } - return status; + "paidover" or "over" or "overpaid" => "PaidOver", + "paidlate" or "late" => "PaidLate", + "paidpartial" or "underpaid" or "partial" => "PaidPartial", + "none" or "" => "", + _ => null + }; } public static T FromBytes(byte[] blob, BTCPayNetworkBase network = null) @@ -846,7 +854,7 @@ retry: contribution.Value = contribution.CurrencyValue; // 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 }; // 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); if (payments.Count == 0 && p.ExceptionStatus == InvoiceExceptionStatus.Marked && - p.Status == InvoiceStatusLegacy.Complete) + p.Status == InvoiceStatus.Settled) return new[] { contribution }; contribution.CurrencyValue = 0m; @@ -862,7 +870,7 @@ retry: // If an invoice has been marked invalid, remove the contribution if (p.ExceptionStatus == InvoiceExceptionStatus.Marked && - p.Status == InvoiceStatusLegacy.Invalid) + p.Status == InvoiceStatus.Invalid) return new[] { contribution }; // Else, we just sum the payments diff --git a/BTCPayServer/Services/Reporting/LegacyInvoiceExportReportProvider.cs b/BTCPayServer/Services/Reporting/LegacyInvoiceExportReportProvider.cs index aa776a6c7..c6b41e417 100644 --- a/BTCPayServer/Services/Reporting/LegacyInvoiceExportReportProvider.cs +++ b/BTCPayServer/Services/Reporting/LegacyInvoiceExportReportProvider.cs @@ -95,8 +95,8 @@ public class LegacyInvoiceExportReportProvider : ReportProvider data.Add(invoiceEntity.Metadata.ItemDesc); data.Add(invoiceEntity.GetInvoiceState().ToString()); #pragma warning disable CS0618 // Type or member is obsolete - data.Add(invoiceEntity.StatusString); - data.Add(invoiceEntity.ExceptionStatusString); + data.Add(invoiceEntity.Status.ToLegacyStatusString()); + data.Add(invoiceEntity.ExceptionStatus.ToLegacyExceptionStatusString()); #pragma warning restore CS0618 // Type or member is obsolete data.Add(invoiceEntity.Metadata.BuyerEmail); data.Add(payment.Accounted); @@ -128,10 +128,8 @@ public class LegacyInvoiceExportReportProvider : ReportProvider data.Add(invoiceEntity.Metadata.ItemCode); data.Add(invoiceEntity.Metadata.ItemDesc); data.Add(invoiceEntity.GetInvoiceState().ToString()); -#pragma warning disable CS0618 // Type or member is obsolete - data.Add(invoiceEntity.StatusString); - data.Add(invoiceEntity.ExceptionStatusString); -#pragma warning restore CS0618 // Type or member is obsolete + data.Add(invoiceEntity.Status.ToLegacyStatusString()); + data.Add(invoiceEntity.ExceptionStatus.ToLegacyExceptionStatusString()); data.Add(invoiceEntity.Metadata.BuyerEmail); data.Add(null); // Accounted } diff --git a/BTCPayServer/Services/Reporting/ProductsReportProvider.cs b/BTCPayServer/Services/Reporting/ProductsReportProvider.cs index 2697773e2..2d49a6c66 100644 --- a/BTCPayServer/Services/Reporting/ProductsReportProvider.cs +++ b/BTCPayServer/Services/Reporting/ProductsReportProvider.cs @@ -42,7 +42,7 @@ public class ProductsReportProvider : ReportProvider var values = queryContext.CreateData(); values.Add(i.InvoiceTime); 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) continue; values.Add(status.ToString()); diff --git a/BTCPayServer/VaultClient.cs b/BTCPayServer/VaultClient.cs index 10a54d98a..54a5b153f 100644 --- a/BTCPayServer/VaultClient.cs +++ b/BTCPayServer/VaultClient.cs @@ -5,7 +5,6 @@ using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; using Amazon.S3.Model.Internal.MarshallTransformations; -using ExchangeSharp; using Newtonsoft.Json.Linq; namespace BTCPayServer diff --git a/BTCPayServer/Views/UIPaymentRequest/ViewPaymentRequest.cshtml b/BTCPayServer/Views/UIPaymentRequest/ViewPaymentRequest.cshtml index deb91f8d1..12c3e99b9 100644 --- a/BTCPayServer/Views/UIPaymentRequest/ViewPaymentRequest.cshtml +++ b/BTCPayServer/Views/UIPaymentRequest/ViewPaymentRequest.cshtml @@ -11,7 +11,7 @@ Layout = null; string StatusClass(InvoiceState state) { - var status = state.Status.ToModernStatus(); + var status = state.Status; switch (status) { case InvoiceStatus.Expired: diff --git a/BTCPayServer/wwwroot/checkout/checkout.js b/BTCPayServer/wwwroot/checkout/checkout.js index 1f13f6921..3cd655f5f 100644 --- a/BTCPayServer/wwwroot/checkout/checkout.js +++ b/BTCPayServer/wwwroot/checkout/checkout.js @@ -1,8 +1,8 @@ // These are the legacy states, see InvoiceEntity -const STATUS_PAYABLE = ['new']; -const STATUS_PAID = ['paid']; -const STATUS_SETTLED = ['complete', 'confirmed']; -const STATUS_INVALID = ['expired', 'invalid']; +const STATUS_PAYABLE = ['New']; +const STATUS_PAID = ['Processing']; +const STATUS_SETTLED = ['Settled']; +const STATUS_INVALID = ['Expired', 'Invalid']; const urlParams = new URLSearchParams(window.location.search); class NDEFReaderWrapper { diff --git a/BTCPayServer/wwwroot/shopify/btcpay-shopify.js b/BTCPayServer/wwwroot/shopify/btcpay-shopify.js index 5a2afb58b..a4f0696a1 100644 --- a/BTCPayServer/wwwroot/shopify/btcpay-shopify.js +++ b/BTCPayServer/wwwroot/shopify/btcpay-shopify.js @@ -101,7 +101,7 @@ window.BTCPayShopifyIntegrationModule = function () { } return; } - if (["complete", "confirmed", "paid"].indexOf(currentInvoiceData.status.toLowerCase()) >= 0) { + if (["settled", "processing"].indexOf(currentInvoiceData.status.toLowerCase()) >= 0) { setOrderAsPaid(); } else if (["invalid", "expired"].indexOf(currentInvoiceData.status.toLowerCase()) >= 0) { fail();