From d96bd15b3b21ac74a2354b4443c817cf655839bf Mon Sep 17 00:00:00 2001 From: Kukks Date: Fri, 24 Jul 2020 09:40:37 +0200 Subject: [PATCH] add status and refactor --- BTCPayServer.Client/Models/InvoiceData.cs | 4 ++ .../Models/InvoiceExceptionStatus.cs | 12 ++++ BTCPayServer.Client/Models/InvoiceStatus.cs | 12 ++++ .../Models/UpdateInvoiceRequest.cs | 4 +- BTCPayServer.Tests/PayJoinTests.cs | 1 + BTCPayServer.Tests/PaymentRequestTests.cs | 1 + .../GreenField/InvoiceController.cs | 55 ++++++++++++++++++- .../Controllers/InvoiceController.UI.cs | 6 +- BTCPayServer/Controllers/InvoiceController.cs | 2 +- .../Controllers/PaymentRequestController.cs | 8 ++- BTCPayServer/Events/InvoiceEvent.cs | 20 ++++++- .../InvoiceNotificationManager.cs | 1 + BTCPayServer/HostedServices/InvoiceWatcher.cs | 15 ++--- BTCPayServer/Hosting/BTCPayServerServices.cs | 2 +- .../Models/InvoicingModels/InvoicesModel.cs | 1 + .../PaymentRequest/PaymentRequestService.cs | 2 + .../Payments/Bitcoin/NBXplorerListener.cs | 2 +- .../Payments/Lightning/LightningListener.cs | 2 +- .../PayJoin/PayJoinEndpointController.cs | 2 +- .../Monero/Services/MoneroListener.cs | 2 +- BTCPayServer/Services/Apps/AppService.cs | 2 + .../Services/Invoices/InvoiceEntity.cs | 19 +------ .../Services/Invoices/InvoiceRepository.cs | 54 ++++++++++++------ 23 files changed, 167 insertions(+), 62 deletions(-) create mode 100644 BTCPayServer.Client/Models/InvoiceExceptionStatus.cs create mode 100644 BTCPayServer.Client/Models/InvoiceStatus.cs diff --git a/BTCPayServer.Client/Models/InvoiceData.cs b/BTCPayServer.Client/Models/InvoiceData.cs index 8e447fbf6..e2838fb02 100644 --- a/BTCPayServer.Client/Models/InvoiceData.cs +++ b/BTCPayServer.Client/Models/InvoiceData.cs @@ -9,6 +9,10 @@ namespace BTCPayServer.Client.Models public class InvoiceData : CreateInvoiceRequest { public string Id { get; set; } + [JsonConverter(typeof(StringEnumConverter))] + public InvoiceStatus Status { get; set; } + [JsonConverter(typeof(StringEnumConverter))] + public InvoiceExceptionStatus ExceptionStatus { get; set; } public Dictionary PaymentMethodData { get; set; } public class PaymentMethodDataModel diff --git a/BTCPayServer.Client/Models/InvoiceExceptionStatus.cs b/BTCPayServer.Client/Models/InvoiceExceptionStatus.cs new file mode 100644 index 000000000..e526fde3a --- /dev/null +++ b/BTCPayServer.Client/Models/InvoiceExceptionStatus.cs @@ -0,0 +1,12 @@ +namespace BTCPayServer.Client.Models +{ + public enum InvoiceExceptionStatus + { + None, + PaidLate, + PaidPartial, + Marked, + Invalid, + PaidOver + } +} \ No newline at end of file diff --git a/BTCPayServer.Client/Models/InvoiceStatus.cs b/BTCPayServer.Client/Models/InvoiceStatus.cs new file mode 100644 index 000000000..a3d866acd --- /dev/null +++ b/BTCPayServer.Client/Models/InvoiceStatus.cs @@ -0,0 +1,12 @@ +namespace BTCPayServer.Client.Models +{ + public enum InvoiceStatus + { + New, + Paid, + Expired, + Invalid, + Complete, + Confirmed + } +} \ No newline at end of file diff --git a/BTCPayServer.Client/Models/UpdateInvoiceRequest.cs b/BTCPayServer.Client/Models/UpdateInvoiceRequest.cs index dea03c3b1..5b3ebf983 100644 --- a/BTCPayServer.Client/Models/UpdateInvoiceRequest.cs +++ b/BTCPayServer.Client/Models/UpdateInvoiceRequest.cs @@ -2,6 +2,8 @@ namespace BTCPayServer.Client.Models { public class UpdateInvoiceRequest { - public bool Archived { get; set; } + public bool? Archived { get; set; } + public InvoiceStatus? Status { get; set; } + public string Email { get; set; } } } diff --git a/BTCPayServer.Tests/PayJoinTests.cs b/BTCPayServer.Tests/PayJoinTests.cs index 270d8c3e5..41825f703 100644 --- a/BTCPayServer.Tests/PayJoinTests.cs +++ b/BTCPayServer.Tests/PayJoinTests.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Net.Http; using System.Text; using System.Threading.Tasks; +using BTCPayServer.Client.Models; using BTCPayServer.Controllers; using BTCPayServer.Data; using BTCPayServer.Events; diff --git a/BTCPayServer.Tests/PaymentRequestTests.cs b/BTCPayServer.Tests/PaymentRequestTests.cs index 4ef4f0659..df844addd 100644 --- a/BTCPayServer.Tests/PaymentRequestTests.cs +++ b/BTCPayServer.Tests/PaymentRequestTests.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Threading.Tasks; +using BTCPayServer.Client.Models; using BTCPayServer.Controllers; using BTCPayServer.Models.PaymentRequestViewModels; using BTCPayServer.PaymentRequest; diff --git a/BTCPayServer/Controllers/GreenField/InvoiceController.cs b/BTCPayServer/Controllers/GreenField/InvoiceController.cs index 0caf6db2c..ee730829b 100644 --- a/BTCPayServer/Controllers/GreenField/InvoiceController.cs +++ b/BTCPayServer/Controllers/GreenField/InvoiceController.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Threading.Tasks; using BTCPayServer.Client; using BTCPayServer.Client.Models; +using BTCPayServer.Models.InvoicingModels; using BTCPayServer.Payments; using BTCPayServer.Security; using BTCPayServer.Services.Invoices; @@ -154,16 +155,64 @@ namespace BTCPayServer.Controllers.GreenField return NotFound(); } - await _invoiceRepository.ToggleInvoiceArchival(invoiceId, request.Archived, storeId); + var invoice = await _invoiceRepository.GetInvoice(invoiceId, true); + if (invoice.StoreId != store.Id) + { + return NotFound(); + } + + if (request.Archived.HasValue) + { + if (request.Archived.Value && !invoice.Archived) + { + ModelState.AddModelError(nameof(request.Archived), + "You can only archive an invoice via HTTP DELETE."); + } + else if (!request.Archived.Value && invoice.Archived) + { + await _invoiceRepository.ToggleInvoiceArchival(invoiceId, false, storeId); + } + } + + if (request.Status != null) + { + if (!await _invoiceRepository.MarkInvoiceStatus(invoice.Id, request.Status.Value)) + { + ModelState.AddModelError(nameof(request.Status), + "Status can only be marked to invalid or complete within certain conditions."); + } + } + + if (request.Email != null) + { + if (!EmailValidator.IsEmail(request.Email)) + { + request.AddModelError(invoiceRequest => invoiceRequest.Email, "Invalid email address", + this); + } + else if (!string.IsNullOrEmpty(invoice.BuyerInformation.BuyerEmail)) + { + request.AddModelError(invoiceRequest => invoiceRequest.Email, "Email address already set", + this); + } + + await _invoiceRepository.UpdateInvoice(invoice.Id, new UpdateCustomerModel() {Email = request.Email}); + } + + if (!ModelState.IsValid) + return this.CreateValidationError(ModelState); + return await GetInvoice(storeId, invoiceId); } - public InvoiceData ToModel(InvoiceEntity entity) + private InvoiceData ToModel(InvoiceEntity entity) { return new InvoiceData() { Amount = entity.ProductInformation.Price, Id = entity.Id, + Status = entity.Status, + ExceptionStatus = entity.ExceptionStatus, Currency = entity.ProductInformation.Currency, Metadata = new CreateInvoiceRequest.ProductInformation() @@ -244,7 +293,7 @@ namespace BTCPayServer.Controllers.GreenField }; } - public Models.CreateInvoiceRequest FromModel(CreateInvoiceRequest entity) + private Models.CreateInvoiceRequest FromModel(CreateInvoiceRequest entity) { return new Models.CreateInvoiceRequest() { diff --git a/BTCPayServer/Controllers/InvoiceController.UI.cs b/BTCPayServer/Controllers/InvoiceController.UI.cs index df6d6a5db..9fcb90689 100644 --- a/BTCPayServer/Controllers/InvoiceController.UI.cs +++ b/BTCPayServer/Controllers/InvoiceController.UI.cs @@ -778,14 +778,12 @@ namespace BTCPayServer.Controllers } if (newState == "invalid") { - await _InvoiceRepository.UpdatePaidInvoiceToInvalid(invoiceId); - _EventAggregator.Publish(new InvoiceEvent(invoice, 1008, InvoiceEvent.MarkedInvalid)); + await _InvoiceRepository.MarkInvoiceStatus(invoiceId, InvoiceStatus.Invalid); model.StatusString = new InvoiceState("invalid", "marked").ToString(); } else if (newState == "complete") { - await _InvoiceRepository.UpdatePaidInvoiceToComplete(invoiceId); - _EventAggregator.Publish(new InvoiceEvent(invoice, 2008, InvoiceEvent.MarkedCompleted)); + await _InvoiceRepository.MarkInvoiceStatus(invoiceId, InvoiceStatus.Complete); model.StatusString = new InvoiceState("complete", "marked").ToString(); } diff --git a/BTCPayServer/Controllers/InvoiceController.cs b/BTCPayServer/Controllers/InvoiceController.cs index cc52715e4..c8da6d15b 100644 --- a/BTCPayServer/Controllers/InvoiceController.cs +++ b/BTCPayServer/Controllers/InvoiceController.cs @@ -243,7 +243,7 @@ namespace BTCPayServer.Controllers } await _InvoiceRepository.AddInvoiceLogs(entity.Id, logs); }); - _EventAggregator.Publish(new Events.InvoiceEvent(entity, 1001, InvoiceEvent.Created)); + _EventAggregator.Publish(new Events.InvoiceEvent(entity, InvoiceEvent.Created)); return entity; } diff --git a/BTCPayServer/Controllers/PaymentRequestController.cs b/BTCPayServer/Controllers/PaymentRequestController.cs index ebbcd790b..3e198c14d 100644 --- a/BTCPayServer/Controllers/PaymentRequestController.cs +++ b/BTCPayServer/Controllers/PaymentRequestController.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using BTCPayServer.Client.Models; using BTCPayServer.Data; using BTCPayServer.Events; using BTCPayServer.Filters; @@ -19,6 +20,9 @@ using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Routing; +using CreateInvoiceRequest = BTCPayServer.Models.CreateInvoiceRequest; +using PaymentRequestData = BTCPayServer.Data.PaymentRequestData; +using StoreData = BTCPayServer.Data.StoreData; namespace BTCPayServer.Controllers { @@ -303,9 +307,7 @@ namespace BTCPayServer.Controllers foreach (var invoice in invoices) { - await _InvoiceRepository.UpdatePaidInvoiceToInvalid(invoice.Id); - _EventAggregator.Publish(new InvoiceEvent(await _InvoiceRepository.GetInvoice(invoice.Id), 1008, - InvoiceEvent.MarkedInvalid)); + await _InvoiceRepository.MarkInvoiceStatus(invoice.Id, InvoiceStatus.Invalid); } if (redirect) diff --git a/BTCPayServer/Events/InvoiceEvent.cs b/BTCPayServer/Events/InvoiceEvent.cs index b55f7384d..ede5028ca 100644 --- a/BTCPayServer/Events/InvoiceEvent.cs +++ b/BTCPayServer/Events/InvoiceEvent.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using BTCPayServer.Services.Invoices; namespace BTCPayServer.Events @@ -15,11 +16,26 @@ namespace BTCPayServer.Events public const string FailedToConfirm = "invoice_failedToConfirm"; public const string Confirmed = "invoice_confirmed"; public const string Completed = "invoice_completed"; + + public static Dictionary EventCodes = new Dictionary() + { + {Created, 1001}, + {ReceivedPayment, 1002}, + {PaidInFull, 1003}, + {Expired, 1004}, + {Confirmed, 1005}, + {Completed, 1006}, + {MarkedInvalid, 1008}, + {FailedToConfirm, 1013}, + {PaidAfterExpiration, 1009}, + {ExpiredPaidPartial, 2000}, + {MarkedCompleted, 2008}, + }; - public InvoiceEvent(InvoiceEntity invoice, int code, string name) + public InvoiceEvent(InvoiceEntity invoice, string name) { Invoice = invoice; - EventCode = code; + EventCode = EventCodes[name]; Name = name; } diff --git a/BTCPayServer/HostedServices/InvoiceNotificationManager.cs b/BTCPayServer/HostedServices/InvoiceNotificationManager.cs index 83133f511..5502104c6 100644 --- a/BTCPayServer/HostedServices/InvoiceNotificationManager.cs +++ b/BTCPayServer/HostedServices/InvoiceNotificationManager.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; diff --git a/BTCPayServer/HostedServices/InvoiceWatcher.cs b/BTCPayServer/HostedServices/InvoiceWatcher.cs index c3a94114b..af3101f72 100644 --- a/BTCPayServer/HostedServices/InvoiceWatcher.cs +++ b/BTCPayServer/HostedServices/InvoiceWatcher.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Threading; using System.Threading.Channels; using System.Threading.Tasks; +using BTCPayServer.Client.Models; using BTCPayServer.Events; using BTCPayServer.Logging; using BTCPayServer.Services.Invoices; @@ -65,9 +66,9 @@ namespace BTCPayServer.HostedServices await _InvoiceRepository.UnaffectAddress(invoice.Id); invoice.Status = InvoiceStatus.Expired; - context.Events.Add(new InvoiceEvent(invoice, 1004, InvoiceEvent.Expired)); + context.Events.Add(new InvoiceEvent(invoice, InvoiceEvent.Expired)); if (invoice.ExceptionStatus == InvoiceExceptionStatus.PaidPartial) - context.Events.Add(new InvoiceEvent(invoice, 2000, InvoiceEvent.ExpiredPaidPartial)); + context.Events.Add(new InvoiceEvent(invoice, InvoiceEvent.ExpiredPaidPartial)); } var payments = invoice.GetPayments().Where(p => p.Accounted).ToArray(); @@ -81,7 +82,7 @@ namespace BTCPayServer.HostedServices { if (invoice.Status == InvoiceStatus.New) { - context.Events.Add(new InvoiceEvent(invoice, 1003, InvoiceEvent.PaidInFull)); + context.Events.Add(new InvoiceEvent(invoice, InvoiceEvent.PaidInFull)); invoice.Status = InvoiceStatus.Paid; invoice.ExceptionStatus = accounting.Paid > accounting.TotalDue ? InvoiceExceptionStatus.PaidOver : InvoiceExceptionStatus.None; await _InvoiceRepository.UnaffectAddress(invoice.Id); @@ -90,7 +91,7 @@ namespace BTCPayServer.HostedServices else if (invoice.Status == InvoiceStatus.Expired && invoice.ExceptionStatus != InvoiceExceptionStatus.PaidLate) { invoice.ExceptionStatus = InvoiceExceptionStatus.PaidLate; - context.Events.Add(new InvoiceEvent(invoice, 1009, InvoiceEvent.PaidAfterExpiration)); + context.Events.Add(new InvoiceEvent(invoice, InvoiceEvent.PaidAfterExpiration)); context.MarkDirty(); } } @@ -136,7 +137,7 @@ namespace BTCPayServer.HostedServices (confirmedAccounting.Paid < accounting.MinimumTotalDue)) { await _InvoiceRepository.UnaffectAddress(invoice.Id); - context.Events.Add(new InvoiceEvent(invoice, 1013, InvoiceEvent.FailedToConfirm)); + context.Events.Add(new InvoiceEvent(invoice, InvoiceEvent.FailedToConfirm)); invoice.Status = InvoiceStatus.Invalid; context.MarkDirty(); } @@ -144,7 +145,7 @@ namespace BTCPayServer.HostedServices { await _InvoiceRepository.UnaffectAddress(invoice.Id); invoice.Status = InvoiceStatus.Confirmed; - context.Events.Add(new InvoiceEvent(invoice, 1005, InvoiceEvent.Confirmed)); + context.Events.Add(new InvoiceEvent(invoice, InvoiceEvent.Confirmed)); context.MarkDirty(); } } @@ -154,7 +155,7 @@ namespace BTCPayServer.HostedServices var completedAccounting = paymentMethod.Calculate(p => p.GetCryptoPaymentData().PaymentCompleted(p)); if (completedAccounting.Paid >= accounting.MinimumTotalDue) { - context.Events.Add(new InvoiceEvent(invoice, 1006, InvoiceEvent.Completed)); + context.Events.Add(new InvoiceEvent(invoice, InvoiceEvent.Completed)); invoice.Status = InvoiceStatus.Complete; context.MarkDirty(); } diff --git a/BTCPayServer/Hosting/BTCPayServerServices.cs b/BTCPayServer/Hosting/BTCPayServerServices.cs index 04fb29eeb..ebcaa9fe6 100644 --- a/BTCPayServer/Hosting/BTCPayServerServices.cs +++ b/BTCPayServer/Hosting/BTCPayServerServices.cs @@ -96,7 +96,7 @@ namespace BTCPayServer.Hosting var dbpath = Path.Combine(opts.DataDir, "InvoiceDB"); if (!Directory.Exists(dbpath)) Directory.CreateDirectory(dbpath); - return new InvoiceRepository(dbContext, dbpath, o.GetRequiredService()); + return new InvoiceRepository(dbContext, dbpath, o.GetRequiredService(), o.GetService()); }); services.AddSingleton(); services.TryAddSingleton(); diff --git a/BTCPayServer/Models/InvoicingModels/InvoicesModel.cs b/BTCPayServer/Models/InvoicingModels/InvoicesModel.cs index 1e109a706..001ddd973 100644 --- a/BTCPayServer/Models/InvoicingModels/InvoicesModel.cs +++ b/BTCPayServer/Models/InvoicingModels/InvoicesModel.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using BTCPayServer.Client.Models; using BTCPayServer.Services.Invoices; namespace BTCPayServer.Models.InvoicingModels diff --git a/BTCPayServer/PaymentRequest/PaymentRequestService.cs b/BTCPayServer/PaymentRequest/PaymentRequestService.cs index da6f7cbaf..e743fcbae 100644 --- a/BTCPayServer/PaymentRequest/PaymentRequestService.cs +++ b/BTCPayServer/PaymentRequest/PaymentRequestService.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Threading.Tasks; +using BTCPayServer.Client.Models; using BTCPayServer.Data; using BTCPayServer.Models.PaymentRequestViewModels; using BTCPayServer.Payments; @@ -9,6 +10,7 @@ using BTCPayServer.Services.Invoices; using BTCPayServer.Services.PaymentRequests; using BTCPayServer.Services.Rates; using Microsoft.AspNetCore.SignalR; +using PaymentRequestData = BTCPayServer.Data.PaymentRequestData; namespace BTCPayServer.PaymentRequest { diff --git a/BTCPayServer/Payments/Bitcoin/NBXplorerListener.cs b/BTCPayServer/Payments/Bitcoin/NBXplorerListener.cs index 243ab0f55..0f61f54f5 100644 --- a/BTCPayServer/Payments/Bitcoin/NBXplorerListener.cs +++ b/BTCPayServer/Payments/Bitcoin/NBXplorerListener.cs @@ -406,7 +406,7 @@ namespace BTCPayServer.Payments.Bitcoin invoice.SetPaymentMethod(paymentMethod); } wallet.InvalidateCache(strategy); - _Aggregator.Publish(new InvoiceEvent(invoice, 1002, InvoiceEvent.ReceivedPayment) { Payment = payment }); + _Aggregator.Publish(new InvoiceEvent(invoice, InvoiceEvent.ReceivedPayment) { Payment = payment }); return invoice; } public async Task StopAsync(CancellationToken cancellationToken) diff --git a/BTCPayServer/Payments/Lightning/LightningListener.cs b/BTCPayServer/Payments/Lightning/LightningListener.cs index ac09e1650..4c8da4d52 100644 --- a/BTCPayServer/Payments/Lightning/LightningListener.cs +++ b/BTCPayServer/Payments/Lightning/LightningListener.cs @@ -329,7 +329,7 @@ namespace BTCPayServer.Payments.Lightning { var invoice = await invoiceRepository.GetInvoice(invoiceId); if (invoice != null) - _eventAggregator.Publish(new InvoiceEvent(invoice, 1002, InvoiceEvent.ReceivedPayment) { Payment = payment }); + _eventAggregator.Publish(new InvoiceEvent(invoice, InvoiceEvent.ReceivedPayment) { Payment = payment }); } return payment != null; } diff --git a/BTCPayServer/Payments/PayJoin/PayJoinEndpointController.cs b/BTCPayServer/Payments/PayJoin/PayJoinEndpointController.cs index 56666857e..98e57abbf 100644 --- a/BTCPayServer/Payments/PayJoin/PayJoinEndpointController.cs +++ b/BTCPayServer/Payments/PayJoin/PayJoinEndpointController.cs @@ -454,7 +454,7 @@ namespace BTCPayServer.Payments.PayJoin $"The original transaction has already been accounted")); } await _btcPayWalletProvider.GetWallet(network).SaveOffchainTransactionAsync(ctx.OriginalTransaction); - _eventAggregator.Publish(new InvoiceEvent(invoice, 1002, InvoiceEvent.ReceivedPayment) { Payment = payment }); + _eventAggregator.Publish(new InvoiceEvent(invoice,InvoiceEvent.ReceivedPayment) { Payment = payment }); _eventAggregator.Publish(new UpdateTransactionLabel() { WalletId = new WalletId(invoice.StoreId, network.CryptoCode), diff --git a/BTCPayServer/Services/Altcoins/Monero/Services/MoneroListener.cs b/BTCPayServer/Services/Altcoins/Monero/Services/MoneroListener.cs index 95d9e0fb8..ee17ce646 100644 --- a/BTCPayServer/Services/Altcoins/Monero/Services/MoneroListener.cs +++ b/BTCPayServer/Services/Altcoins/Monero/Services/MoneroListener.cs @@ -143,7 +143,7 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services } _eventAggregator.Publish( - new InvoiceEvent(invoice, 1002, InvoiceEvent.ReceivedPayment) { Payment = payment }); + new InvoiceEvent(invoice, InvoiceEvent.ReceivedPayment) { Payment = payment }); } private async Task UpdatePaymentStates(string cryptoCode, InvoiceEntity[] invoices) diff --git a/BTCPayServer/Services/Apps/AppService.cs b/BTCPayServer/Services/Apps/AppService.cs index 2a1f92abd..9ad30f2a4 100644 --- a/BTCPayServer/Services/Apps/AppService.cs +++ b/BTCPayServer/Services/Apps/AppService.cs @@ -4,6 +4,7 @@ using System.Globalization; using System.IO; using System.Linq; using System.Threading.Tasks; +using BTCPayServer.Client.Models; using BTCPayServer.Data; using BTCPayServer.Models.AppViewModels; using BTCPayServer.Payments; @@ -20,6 +21,7 @@ using NUglify.Helpers; using YamlDotNet.RepresentationModel; using YamlDotNet.Serialization; using static BTCPayServer.Models.AppViewModels.ViewCrowdfundViewModel; +using StoreData = BTCPayServer.Data.StoreData; namespace BTCPayServer.Services.Apps { diff --git a/BTCPayServer/Services/Invoices/InvoiceEntity.cs b/BTCPayServer/Services/Invoices/InvoiceEntity.cs index ed7249341..72730ed96 100644 --- a/BTCPayServer/Services/Invoices/InvoiceEntity.cs +++ b/BTCPayServer/Services/Invoices/InvoiceEntity.cs @@ -604,24 +604,7 @@ namespace BTCPayServer.Services.Invoices } } - public enum InvoiceStatus - { - New, - Paid, - Expired, - Invalid, - Complete, - Confirmed - } - public enum InvoiceExceptionStatus - { - None, - PaidLate, - PaidPartial, - Marked, - Invalid, - PaidOver - } + public class InvoiceState { static readonly Dictionary _StringToInvoiceStatus; diff --git a/BTCPayServer/Services/Invoices/InvoiceRepository.cs b/BTCPayServer/Services/Invoices/InvoiceRepository.cs index 0deadd243..c1a2f2f59 100644 --- a/BTCPayServer/Services/Invoices/InvoiceRepository.cs +++ b/BTCPayServer/Services/Invoices/InvoiceRepository.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Threading.Tasks; using BTCPayServer.Client.Models; using BTCPayServer.Data; +using BTCPayServer.Events; using BTCPayServer.Logging; using BTCPayServer.Models.InvoicingModels; using BTCPayServer.Payments; @@ -37,11 +38,12 @@ namespace BTCPayServer.Services.Invoices } private readonly ApplicationDbContextFactory _ContextFactory; + private readonly EventAggregator _eventAggregator; private readonly BTCPayNetworkProvider _Networks; private readonly CustomThreadPool _IndexerThread; public InvoiceRepository(ApplicationDbContextFactory contextFactory, string dbreezePath, - BTCPayNetworkProvider networks) + BTCPayNetworkProvider networks, EventAggregator eventAggregator) { int retryCount = 0; retry: @@ -53,6 +55,7 @@ retry: _IndexerThread = new CustomThreadPool(1, "Invoice Indexer"); _ContextFactory = contextFactory; _Networks = networks; + _eventAggregator = eventAggregator; } public InvoiceEntity CreateNewInvoice() @@ -441,29 +444,44 @@ retry: await context.SaveChangesAsync().ConfigureAwait(false); } } - public async Task UpdatePaidInvoiceToInvalid(string invoiceId) + public async Task MarkInvoiceStatus(string invoiceId, InvoiceStatus status) { using (var context = _ContextFactory.CreateContext()) { var invoiceData = await context.FindAsync(invoiceId).ConfigureAwait(false); - if (invoiceData == null || !invoiceData.GetInvoiceState().CanMarkInvalid()) - return; - invoiceData.Status = "invalid"; - invoiceData.ExceptionStatus = "marked"; - await context.SaveChangesAsync().ConfigureAwait(false); - } - } - public async Task UpdatePaidInvoiceToComplete(string invoiceId) - { - using (var context = _ContextFactory.CreateContext()) - { - var invoiceData = await context.FindAsync(invoiceId).ConfigureAwait(false); - if (invoiceData == null || !invoiceData.GetInvoiceState().CanMarkComplete()) - return; - invoiceData.Status = "complete"; - invoiceData.ExceptionStatus = "marked"; + if (invoiceData == null) + { + return false; + } + + string eventName; + switch (status) + { + case InvoiceStatus.Complete: + if (!invoiceData.GetInvoiceState().CanMarkComplete()) + { + return false; + } + + eventName = InvoiceEvent.MarkedCompleted; + break; + case InvoiceStatus.Invalid: + if (!invoiceData.GetInvoiceState().CanMarkInvalid()) + { + return false; + } + eventName = InvoiceEvent.MarkedInvalid; + break; + default: + return false; + } + invoiceData.Status =status.ToString().ToLowerInvariant(); + invoiceData.ExceptionStatus = InvoiceExceptionStatus.Marked.ToString().ToLowerInvariant(); + _eventAggregator.Publish(new InvoiceEvent(ToEntity(invoiceData), eventName)); await context.SaveChangesAsync().ConfigureAwait(false); } + + return true; } public async Task GetInvoice(string id, bool inludeAddressData = false) {