From e5a3ef3e22db2df89e2ecc9d9d8f707fac41d4ec Mon Sep 17 00:00:00 2001 From: Kukks Date: Thu, 7 May 2020 12:50:07 +0200 Subject: [PATCH] Archive Invoice --- BTCPayServer.Data/Data/InvoiceData.cs | 4 ++- .../20200507092343_AddArchivedToInvoice.cs | 30 +++++++++++++++++++ .../ApplicationDbContextModelSnapshot.cs | 3 ++ .../Controllers/InvoiceController.UI.cs | 30 +++++++++++++++++-- .../InvoicingModels/InvoiceDetailsModel.cs | 1 + .../Services/Invoices/InvoiceEntity.cs | 1 + .../Services/Invoices/InvoiceRepository.cs | 21 ++++++++++++- BTCPayServer/Views/Invoice/Invoice.cshtml | 16 +++++++++- .../Views/Invoice/ListInvoices.cshtml | 8 ++++- 9 files changed, 107 insertions(+), 7 deletions(-) create mode 100644 BTCPayServer.Data/Migrations/20200507092343_AddArchivedToInvoice.cs diff --git a/BTCPayServer.Data/Data/InvoiceData.cs b/BTCPayServer.Data/Data/InvoiceData.cs index 22484a81e..89104185a 100644 --- a/BTCPayServer.Data/Data/InvoiceData.cs +++ b/BTCPayServer.Data/Data/InvoiceData.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -79,6 +79,8 @@ namespace BTCPayServer.Data { get; set; } + + public bool Archived { get; set; } public List PendingInvoices { get; set; } } } diff --git a/BTCPayServer.Data/Migrations/20200507092343_AddArchivedToInvoice.cs b/BTCPayServer.Data/Migrations/20200507092343_AddArchivedToInvoice.cs new file mode 100644 index 000000000..6d863c7e8 --- /dev/null +++ b/BTCPayServer.Data/Migrations/20200507092343_AddArchivedToInvoice.cs @@ -0,0 +1,30 @@ +using BTCPayServer.Data; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace BTCPayServer.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20200507092343_AddArchivedToInvoice")] + public class AddArchivedToInvoice : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Archived", + table: "Invoices", + nullable: false, + defaultValue: false); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + if (this.SupportDropColumn(migrationBuilder.ActiveProvider)) + { + migrationBuilder.DropColumn( + name: "Archived", + table: "Invoices"); + } + } + } +} diff --git a/BTCPayServer.Data/Migrations/ApplicationDbContextModelSnapshot.cs b/BTCPayServer.Data/Migrations/ApplicationDbContextModelSnapshot.cs index 5548d7f66..0483409a0 100644 --- a/BTCPayServer.Data/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/BTCPayServer.Data/Migrations/ApplicationDbContextModelSnapshot.cs @@ -190,6 +190,9 @@ namespace BTCPayServer.Migrations b.Property("Id") .HasColumnType("TEXT"); + b.Property("Archived") + .HasColumnType("INTEGER"); + b.Property("Blob") .HasColumnType("BLOB"); diff --git a/BTCPayServer/Controllers/InvoiceController.UI.cs b/BTCPayServer/Controllers/InvoiceController.UI.cs index 3f14666f0..c767707ed 100644 --- a/BTCPayServer/Controllers/InvoiceController.UI.cs +++ b/BTCPayServer/Controllers/InvoiceController.UI.cs @@ -41,7 +41,8 @@ namespace BTCPayServer.Controllers InvoiceId = new[] {invoiceId}, UserId = GetUserId(), IncludeAddresses = true, - IncludeEvents = true + IncludeEvents = true, + IncludeArchived = true, })).FirstOrDefault(); if (invoice == null) return NotFound(); @@ -71,7 +72,8 @@ namespace BTCPayServer.Controllers ProductInformation = invoice.ProductInformation, StatusException = invoice.ExceptionStatus, Events = invoice.Events, - PosData = PosDataParser.ParsePosData(invoice.PosData) + PosData = PosDataParser.ParsePosData(invoice.PosData), + Archived = invoice.Archived }; model.Addresses = invoice.HistoricalAddresses.Select(h => @@ -91,6 +93,7 @@ namespace BTCPayServer.Controllers private InvoiceDetailsModel InvoicePopulatePayments(InvoiceEntity invoice) { var model = new InvoiceDetailsModel(); + model.Archived = invoice.Archived; model.Payments = invoice.GetPayments(); foreach (var data in invoice.GetPaymentMethods()) { @@ -111,6 +114,26 @@ namespace BTCPayServer.Controllers return model; } + [HttpPost("invoices/{invoiceId}/archive")] + [Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie)] + [BitpayAPIConstraint(false)] + public async Task ToggleArchive(string invoiceId) + { + var invoice = (await _InvoiceRepository.GetInvoices(new InvoiceQuery() + { + InvoiceId = new[] {invoiceId}, UserId = GetUserId(), IncludeAddresses = true, IncludeEvents = true, IncludeArchived = true, + })).FirstOrDefault(); + if (invoice == null) + return NotFound(); + await _InvoiceRepository.ToggleInvoiceArchival(invoiceId, !invoice.Archived); + TempData.SetStatusMessageModel(new StatusMessageModel() + { + Severity = StatusMessageModel.StatusSeverity.Success, + Message = invoice.Archived ? "The invoice has been unarchived and will appear in the invoice list by default again." : "The invoice has been archived and will no longer appear in the invoice list by default." + }); + return RedirectToAction(nameof(invoice), new {invoiceId}); + } + [HttpGet] [Route("i/{invoiceId}")] [Route("i/{invoiceId}/{paymentMethodId}")] @@ -437,7 +460,7 @@ namespace BTCPayServer.Controllers AmountCurrency = _CurrencyNameTable.DisplayFormatCurrency(invoice.ProductInformation.Price, invoice.ProductInformation.Currency), CanMarkInvalid = state.CanMarkInvalid(), CanMarkComplete = state.CanMarkComplete(), - Details = InvoicePopulatePayments(invoice) + Details = InvoicePopulatePayments(invoice), }); } model.Total = await counting; @@ -452,6 +475,7 @@ namespace BTCPayServer.Controllers TextSearch = fs.TextSearch, UserId = GetUserId(), Unusual = fs.GetFilterBool("unusual"), + IncludeArchived = fs.GetFilterBool("includearchived") ?? false, Status = fs.GetFilterArray("status"), ExceptionStatus = fs.GetFilterArray("exceptionstatus"), StoreId = fs.GetFilterArray("storeid"), diff --git a/BTCPayServer/Models/InvoicingModels/InvoiceDetailsModel.cs b/BTCPayServer/Models/InvoicingModels/InvoiceDetailsModel.cs index 0ed6402f4..2d9ca5d88 100644 --- a/BTCPayServer/Models/InvoicingModels/InvoiceDetailsModel.cs +++ b/BTCPayServer/Models/InvoicingModels/InvoiceDetailsModel.cs @@ -127,5 +127,6 @@ namespace BTCPayServer.Models.InvoicingModels public string NotificationEmail { get; internal set; } public Dictionary PosData { get; set; } public List Payments { get; set; } + public bool Archived { get; set; } } } diff --git a/BTCPayServer/Services/Invoices/InvoiceEntity.cs b/BTCPayServer/Services/Invoices/InvoiceEntity.cs index 70c8d8d76..98c459fad 100644 --- a/BTCPayServer/Services/Invoices/InvoiceEntity.cs +++ b/BTCPayServer/Services/Invoices/InvoiceEntity.cs @@ -371,6 +371,7 @@ namespace BTCPayServer.Services.Invoices public bool ExtendedNotifications { get; set; } public List Events { get; internal set; } public double PaymentTolerance { get; set; } + public bool Archived { get; set; } public bool IsExpired() { diff --git a/BTCPayServer/Services/Invoices/InvoiceRepository.cs b/BTCPayServer/Services/Invoices/InvoiceRepository.cs index 7f26ff6ca..7953862bb 100644 --- a/BTCPayServer/Services/Invoices/InvoiceRepository.cs +++ b/BTCPayServer/Services/Invoices/InvoiceRepository.cs @@ -158,7 +158,8 @@ retry: Status = invoice.StatusString, #pragma warning restore CS0618 // Type or member is obsolete ItemCode = invoice.ProductInformation.ItemCode, - CustomerEmail = invoice.RefundMail + CustomerEmail = invoice.RefundMail, + Archived = false }); foreach (var paymentMethod in invoice.GetPaymentMethods()) @@ -396,6 +397,17 @@ retry: } } + public async Task ToggleInvoiceArchival(string invoiceId, bool archived) + { + using (var context = _ContextFactory.CreateContext()) + { + var invoiceData = await context.FindAsync(invoiceId).ConfigureAwait(false); + if (invoiceData == null || invoiceData.Archived == archived ) + return; + invoiceData.Archived = archived; + await context.SaveChangesAsync().ConfigureAwait(false); + } + } public async Task UpdatePaidInvoiceToInvalid(string invoiceId) { using (var context = _ContextFactory.CreateContext()) @@ -499,6 +511,7 @@ retry: { entity.BuyerInformation.BuyerEmail = entity.RefundMail; } + entity.Archived = invoice.Archived; return entity; } @@ -513,6 +526,11 @@ retry: { IQueryable query = context.Invoices; + if (!queryObject.IncludeArchived) + { + query = query.Where(i => !i.Archived); + } + if (queryObject.InvoiceId != null && queryObject.InvoiceId.Length > 0) { var statusSet = queryObject.InvoiceId.ToHashSet().ToArray(); @@ -838,5 +856,6 @@ retry: public bool IncludeAddresses { get; set; } public bool IncludeEvents { get; set; } + public bool IncludeArchived { get; set; } = true; } } diff --git a/BTCPayServer/Views/Invoice/Invoice.cshtml b/BTCPayServer/Views/Invoice/Invoice.cshtml index 9c796fad2..42db91fe1 100644 --- a/BTCPayServer/Views/Invoice/Invoice.cshtml +++ b/BTCPayServer/Views/Invoice/Invoice.cshtml @@ -28,7 +28,21 @@
-

@ViewData["Title"]

+
+

@ViewData["Title"]

+
+ +
+

diff --git a/BTCPayServer/Views/Invoice/ListInvoices.cshtml b/BTCPayServer/Views/Invoice/ListInvoices.cshtml index 270ea1691..52fda7db4 100644 --- a/BTCPayServer/Views/Invoice/ListInvoices.cshtml +++ b/BTCPayServer/Views/Invoice/ListInvoices.cshtml @@ -88,6 +88,7 @@ Paid Partial Invoices Paid Over Invoices Unusual Invoices + Archived Invoices Last 24 hours Last 3 days @@ -220,7 +221,11 @@ } @invoice.InvoiceId - + + @if(invoice.Details.Archived) + { + archived + } @if (invoice.CanMarkStatus) {
@@ -364,6 +369,7 @@ $("a.last24").each(function () { this.href = this.href.replace("last24", getDateStringWithOffset(24)); }); $("a.last72").each(function () { this.href = this.href.replace("last72", getDateStringWithOffset(72)); }); $("a.last168").each(function () { this.href = this.href.replace("last168", getDateStringWithOffset(168)); }); + }); function getDateStringWithOffset(hoursDiff) {