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
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
40 changed files with 218 additions and 309 deletions

View File

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

View File

@ -349,7 +349,24 @@ namespace BTCPayServer.Data
if (blob["defaultPaymentMethod"] is not (null or { Type : JTokenType.Null }))
blob["defaultPaymentMethod"] = MigrationExtensions.MigratePaymentMethodId(blob["defaultPaymentMethod"].Value<string>());
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);
}

View File

@ -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
{

View File

@ -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);
});
}
}

View File

@ -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<InvoiceRepository>().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<InvoiceRepository>().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<InvoiceRepository>().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<InvoiceRepository>().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<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));
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);
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
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<BadRequestObjectResult>(await
paymentRequestController.CancelUnpaidPendingInvoice(paymentRequestId, false));

View File

@ -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<ApplicationDbContextFactory>().CreateContext();
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);
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);
});

View File

@ -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());
}
<div class="d-inline-flex align-items-center gap-2">

View File

@ -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,

View File

@ -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;

View File

@ -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);

View File

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

View File

@ -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)

View File

@ -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())
{

View File

@ -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);
}
}
}

View File

@ -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";
}
//////////////////

View File

@ -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);

View File

@ -97,8 +97,8 @@ public class InvoiceWebhookProvider : WebhookProvider<InvoiceEvent>
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<InvoiceEvent>
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

View File

@ -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<IEnumerable<IPaymentLinkExtension>>().ToDictionary(o => o.P
{
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 =>
{

View File

@ -149,8 +149,8 @@ namespace BTCPayServer.Models.PaymentRequestViewModels
{
static HashSet<InvoiceState> stateAllowedToDisplay = new HashSet<InvoiceState>
{
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<PaymentRequestInvoicePayment> Payments { get; set; }

View File

@ -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

View File

@ -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<Events.InvoiceDataChangedEvent>(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);

View File

@ -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<object?> GetInfo(AppData appData)
{
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? 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;
}
}
}

View File

@ -48,7 +48,7 @@ namespace BTCPayServer.Plugins.NFC
public async Task<IActionResult> 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();
}

View File

@ -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;

View File

@ -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);

View File

@ -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);
}

View File

@ -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,

View File

@ -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<PointOfSaleSettings>();
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:

View File

@ -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;

View File

@ -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<bool> 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)

View File

@ -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<string, decimal>(),
PaymentTotals = new Dictionary<string, decimal>(),
@ -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<string, InvoiceStatusLegacy> _StringToInvoiceStatus;
static readonly Dictionary<InvoiceStatusLegacy, string> _InvoiceStatusToString;
static readonly Dictionary<string, InvoiceExceptionStatus> _StringToExceptionStatus;
static readonly Dictionary<InvoiceExceptionStatus, string> _ExceptionStatusToString;
static InvoiceState()
public InvoiceState(string status, string exceptionStatus):
this(Enum.Parse<InvoiceStatus>(status), exceptionStatus switch { "None" or "" or null => InvoiceExceptionStatus.None, _ => Enum.Parse<InvoiceExceptionStatus>(exceptionStatus) })
{
_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()
{
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)",
_ => ""
};
}

View File

@ -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<string>();
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>();
// 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<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)
{
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<T>(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

View File

@ -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
}

View File

@ -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());

View File

@ -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

View File

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

View File

@ -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 {

View File

@ -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();