Apply store ids and search term to invoice export (#4516)

This makes the export work like the list in the UI. Exports what one sees.

Fixes #4514.
This commit is contained in:
d11n
2023-01-11 05:36:03 +01:00
committed by GitHub
parent bb733c5811
commit bb0e96a163
3 changed files with 54 additions and 16 deletions

View File

@@ -1746,6 +1746,15 @@ namespace BTCPayServer.Tests
return decimal.Parse(match.Groups[1].Value.Trim(), CultureInfo.InvariantCulture);
}
async Task<object[]> GetExport(TestAccount account, string storeId = null)
{
var content = await account.GetController<UIInvoiceController>(false)
.Export("json", storeId);
var result = Assert.IsType<ContentResult>(content);
Assert.Equal("application/json", result.ContentType);
return JsonConvert.DeserializeObject<object[]>(result.Content ?? "[]");
}
using var tester = CreateServerTester();
await tester.StartAsync();
var user = tester.NewAccount();
@@ -1764,14 +1773,11 @@ namespace BTCPayServer.Tests
}, Facade.Merchant);
var networkFee = new FeeRate(invoice.MinerFees["BTC"].SatoshiPerBytes).GetFee(100);
var jsonResult = user.GetController<UIInvoiceController>().Export("json").GetAwaiter().GetResult();
var result = Assert.IsType<ContentResult>(jsonResult);
Assert.Equal("application/json", result.ContentType);
Assert.Single(JArray.Parse(result.Content));
var result = await GetExport(user);
Assert.Single(result);
var cashCow = tester.ExplorerNode;
var invoiceAddress = BitcoinAddress.Create(invoice.CryptoInfo[0].Address, cashCow.Network);
//
var firstPayment = invoice.CryptoInfo[0].TotalDue - 3 * networkFee;
cashCow.SendToAddress(invoiceAddress, firstPayment);
Thread.Sleep(1000); // prevent race conditions, ordering payments
@@ -1785,14 +1791,9 @@ namespace BTCPayServer.Tests
cashCow.SendToAddress(invoiceAddress, 4 * networkFee);
Thread.Sleep(1000);
TestUtils.Eventually(() =>
await TestUtils.EventuallyAsync(async () =>
{
var jsonResultPaid =
user.GetController<UIInvoiceController>().Export("json").GetAwaiter().GetResult();
var paidresult = Assert.IsType<ContentResult>(jsonResultPaid);
Assert.Equal("application/json", paidresult.ContentType);
var parsedJson = JsonConvert.DeserializeObject<object[]>(paidresult.Content);
var parsedJson = await GetExport(user);
Assert.Equal(3, parsedJson.Length);
var invoiceDueAfterFirstPayment = (3 * networkFee).ToDecimal(MoneyUnit.BTC) * invoice.Rate;
@@ -1809,6 +1810,32 @@ namespace BTCPayServer.Tests
var pay3str = parsedJson[2].ToString();
Assert.Contains("\"InvoiceDue\": 0", pay3str);
});
// create an invoice for a new store and check responses with and without store id
var otherUser = tester.NewAccount();
await otherUser.GrantAccessAsync();
otherUser.RegisterDerivationScheme("BTC");
await otherUser.SetNetworkFeeMode(NetworkFeeMode.Always);
var newInvoice = await otherUser.BitPay.CreateInvoiceAsync(
new Invoice
{
Price = 21,
Currency = "USD",
PosData = "posData",
OrderId = "orderId",
ItemDesc = "Some \", description",
FullNotifications = true
}, Facade.Merchant);
await otherUser.PayInvoice(newInvoice.Id);
Assert.Single(await GetExport(otherUser));
Assert.Single(await GetExport(otherUser, otherUser.StoreId));
Assert.Equal(3, (await GetExport(user, user.StoreId)).Length);
Assert.Equal(3, (await GetExport(user)).Length);
await otherUser.AddOwner(user.UserId);
Assert.Equal(4, (await GetExport(user)).Length);
Assert.Single(await GetExport(user, otherUser.StoreId));
}
[Fact(Timeout = LongRunningTestTimeout)]

View File

@@ -1011,12 +1011,23 @@ namespace BTCPayServer.Controllers
[HttpGet]
[Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie, Policy = Policies.CanViewInvoices)]
[BitpayAPIConstraint(false)]
public async Task<IActionResult> Export(string format, string? searchTerm = null, int timezoneOffset = 0)
public async Task<IActionResult> Export(string format, string? storeId = null, string? searchTerm = null, int timezoneOffset = 0)
{
var model = new InvoiceExport(_CurrencyNameTable);
var fs = new SearchString(searchTerm);
var storeIds = new HashSet<string>();
if (fs.GetFilterArray("storeid") is string[] l)
{
foreach (var i in l)
storeIds.Add(i);
}
if (storeId is not null)
{
storeIds.Add(storeId);
}
InvoiceQuery invoiceQuery = GetInvoiceQuery(searchTerm, timezoneOffset);
invoiceQuery.StoreId = new[] { GetCurrentStore().Id };
invoiceQuery.StoreId = storeIds.ToArray();
invoiceQuery.Skip = 0;
invoiceQuery.Take = int.MaxValue;
var invoices = await _InvoiceRepository.GetInvoices(invoiceQuery);

View File

@@ -267,8 +267,8 @@
Export
</button>
<div class="dropdown-menu" aria-labelledby="ExportDropdownToggle">
<a asp-action="Export" asp-route-timezoneoffset="0" asp-route-format="csv" asp-route-searchTerm="@Model.SearchTerm" class="dropdown-item export-link" target="_blank">CSV</a>
<a asp-action="Export" asp-route-timezoneoffset="0" asp-route-format="json" asp-route-searchTerm="@Model.SearchTerm" class="dropdown-item export-link" target="_blank">JSON</a>
<a asp-action="Export" asp-route-timezoneoffset="0" asp-route-format="csv" asp-route-storeId="@Model.StoreId" asp-route-searchTerm="@Model.SearchTerm" class="dropdown-item export-link" target="_blank">CSV</a>
<a asp-action="Export" asp-route-timezoneoffset="0" asp-route-format="json" asp-route-storeId="@Model.StoreId" asp-route-searchTerm="@Model.SearchTerm" class="dropdown-item export-link" target="_blank">JSON</a>
</div>
<a href="https://docs.btcpayserver.org/Accounting/" target="_blank" rel="noreferrer noopener">
<span class="fa fa-question-circle-o text-secondary" title="More information..."></span>