diff --git a/BTCPayServer.Tests/UnitTest1.cs b/BTCPayServer.Tests/UnitTest1.cs index 4fdee81d6..43424e6f3 100644 --- a/BTCPayServer.Tests/UnitTest1.cs +++ b/BTCPayServer.Tests/UnitTest1.cs @@ -598,6 +598,53 @@ namespace BTCPayServer.Tests } } + [Fact] + public void CanListInvoices() + { + using (var tester = ServerTester.Create()) + { + tester.Start(); + var acc = tester.NewAccount(); + acc.GrantAccess(); + acc.RegisterDerivationScheme("BTC"); + // First we try payment with a merchant having only BTC + var invoice = acc.BitPay.CreateInvoice(new Invoice() + { + Price = 500, + Currency = "USD", + PosData = "posData", + OrderId = "orderId", + ItemDesc = "Some description", + FullNotifications = true + }, Facade.Merchant); + + var cashCow = tester.ExplorerNode; + var invoiceAddress = BitcoinAddress.Create(invoice.CryptoInfo[0].Address, cashCow.Network); + var firstPayment = invoice.CryptoInfo[0].TotalDue - Money.Satoshis(10); + cashCow.SendToAddress(invoiceAddress, firstPayment); + Eventually(() => + { + invoice = acc.BitPay.GetInvoice(invoice.Id); + Assert.Equal(firstPayment, invoice.CryptoInfo[0].Paid); + }); + + + AssertSearchInvoice(acc, true, invoice.Id, $"storeid:{acc.StoreId}"); + AssertSearchInvoice(acc, false, invoice.Id, $"storeid:blah"); + AssertSearchInvoice(acc, true, invoice.Id, $"{invoice.Id}"); + AssertSearchInvoice(acc, true, invoice.Id, $"exceptionstatus:paidPartial"); + AssertSearchInvoice(acc, false, invoice.Id, $"exceptionstatus:paidOver"); + AssertSearchInvoice(acc, true, invoice.Id, $"unusual:true"); + AssertSearchInvoice(acc, false, invoice.Id, $"unusual:false"); + } + } + + private void AssertSearchInvoice(TestAccount acc, bool expected, string invoiceId, string filter) + { + var result = (Models.InvoicingModels.InvoicesModel)((ViewResult)acc.GetController().ListInvoices(filter).Result).Model; + Assert.Equal(expected, result.Invoices.Any(i => i.InvoiceId == invoiceId)); + } + [Fact] public void CanRBFPayment() { diff --git a/BTCPayServer/BTCPayServer.csproj b/BTCPayServer/BTCPayServer.csproj index d53ba72bd..bc24091f0 100644 --- a/BTCPayServer/BTCPayServer.csproj +++ b/BTCPayServer/BTCPayServer.csproj @@ -2,7 +2,7 @@ Exe netcoreapp2.0 - 1.0.2.6 + 1.0.2.7 NU1701,CA1816,CA1308,CA1810,CA2208 diff --git a/BTCPayServer/Controllers/InvoiceController.UI.cs b/BTCPayServer/Controllers/InvoiceController.UI.cs index 7601fb0f6..4a23db278 100644 --- a/BTCPayServer/Controllers/InvoiceController.UI.cs +++ b/BTCPayServer/Controllers/InvoiceController.UI.cs @@ -370,6 +370,9 @@ namespace BTCPayServer.Controllers Count = count, Skip = skip, UserId = GetUserId(), + Unusual = !filterString.Filters.ContainsKey("unusual") ? null + : !bool.TryParse(filterString.Filters["unusual"].First(), out var r) ? (bool?)null + : r, Status = filterString.Filters.ContainsKey("status") ? filterString.Filters["status"].ToArray() : null, ExceptionStatus = filterString.Filters.ContainsKey("exceptionstatus") ? filterString.Filters["exceptionstatus"].ToArray() : null, StoreId = filterString.Filters.ContainsKey("storeid") ? filterString.Filters["storeid"].ToArray() : null diff --git a/BTCPayServer/Services/Invoices/InvoiceRepository.cs b/BTCPayServer/Services/Invoices/InvoiceRepository.cs index d3460f311..33253d0ec 100644 --- a/BTCPayServer/Services/Invoices/InvoiceRepository.cs +++ b/BTCPayServer/Services/Invoices/InvoiceRepository.cs @@ -436,6 +436,12 @@ namespace BTCPayServer.Services.Invoices query = query.Where(i => statusSet.Contains(i.Status)); } + if(queryObject.Unusual != null) + { + var unused = queryObject.Unusual.Value; + query = query.Where(i => unused == (i.Status == "invalid" || i.ExceptionStatus != null)); + } + if (queryObject.ExceptionStatus != null && queryObject.ExceptionStatus.Length > 0) { var exceptionStatusSet = queryObject.ExceptionStatus.Select(s => NormalizeExceptionStatus(s)).ToHashSet(); @@ -643,6 +649,8 @@ namespace BTCPayServer.Services.Invoices get; set; } + public bool? Unusual { get; set; } + public string[] Status { get; set; diff --git a/BTCPayServer/Views/Invoice/ListInvoices.cshtml b/BTCPayServer/Views/Invoice/ListInvoices.cshtml index 3f88526b0..b5d3bc11b 100644 --- a/BTCPayServer/Views/Invoice/ListInvoices.cshtml +++ b/BTCPayServer/Views/Invoice/ListInvoices.cshtml @@ -26,6 +26,7 @@
  • storeid:id for filtering a specific store
  • status:(expired|invalid|complete|confirmed|paid|new) for filtering a specific status
  • exceptionstatus:(paidover|paidlate|paidpartial) for filtering a specific exception state
  • +
  • unusual:(true|false) for filtering invoices which might requires merchant attention (those invalid or with an exceptionstatus)
  • If you want two confirmed and complete invoices, duplicate the filter: status:confirmed status:complete.