mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-18 14:34:23 +01:00
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:
@@ -1746,6 +1746,15 @@ namespace BTCPayServer.Tests
|
|||||||
return decimal.Parse(match.Groups[1].Value.Trim(), CultureInfo.InvariantCulture);
|
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();
|
using var tester = CreateServerTester();
|
||||||
await tester.StartAsync();
|
await tester.StartAsync();
|
||||||
var user = tester.NewAccount();
|
var user = tester.NewAccount();
|
||||||
@@ -1764,14 +1773,11 @@ namespace BTCPayServer.Tests
|
|||||||
}, Facade.Merchant);
|
}, Facade.Merchant);
|
||||||
|
|
||||||
var networkFee = new FeeRate(invoice.MinerFees["BTC"].SatoshiPerBytes).GetFee(100);
|
var networkFee = new FeeRate(invoice.MinerFees["BTC"].SatoshiPerBytes).GetFee(100);
|
||||||
var jsonResult = user.GetController<UIInvoiceController>().Export("json").GetAwaiter().GetResult();
|
var result = await GetExport(user);
|
||||||
var result = Assert.IsType<ContentResult>(jsonResult);
|
Assert.Single(result);
|
||||||
Assert.Equal("application/json", result.ContentType);
|
|
||||||
Assert.Single(JArray.Parse(result.Content));
|
|
||||||
|
|
||||||
var cashCow = tester.ExplorerNode;
|
var cashCow = tester.ExplorerNode;
|
||||||
var invoiceAddress = BitcoinAddress.Create(invoice.CryptoInfo[0].Address, cashCow.Network);
|
var invoiceAddress = BitcoinAddress.Create(invoice.CryptoInfo[0].Address, cashCow.Network);
|
||||||
//
|
|
||||||
var firstPayment = invoice.CryptoInfo[0].TotalDue - 3 * networkFee;
|
var firstPayment = invoice.CryptoInfo[0].TotalDue - 3 * networkFee;
|
||||||
cashCow.SendToAddress(invoiceAddress, firstPayment);
|
cashCow.SendToAddress(invoiceAddress, firstPayment);
|
||||||
Thread.Sleep(1000); // prevent race conditions, ordering payments
|
Thread.Sleep(1000); // prevent race conditions, ordering payments
|
||||||
@@ -1785,14 +1791,9 @@ namespace BTCPayServer.Tests
|
|||||||
cashCow.SendToAddress(invoiceAddress, 4 * networkFee);
|
cashCow.SendToAddress(invoiceAddress, 4 * networkFee);
|
||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
|
|
||||||
TestUtils.Eventually(() =>
|
await TestUtils.EventuallyAsync(async () =>
|
||||||
{
|
{
|
||||||
var jsonResultPaid =
|
var parsedJson = await GetExport(user);
|
||||||
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);
|
|
||||||
Assert.Equal(3, parsedJson.Length);
|
Assert.Equal(3, parsedJson.Length);
|
||||||
|
|
||||||
var invoiceDueAfterFirstPayment = (3 * networkFee).ToDecimal(MoneyUnit.BTC) * invoice.Rate;
|
var invoiceDueAfterFirstPayment = (3 * networkFee).ToDecimal(MoneyUnit.BTC) * invoice.Rate;
|
||||||
@@ -1809,6 +1810,32 @@ namespace BTCPayServer.Tests
|
|||||||
var pay3str = parsedJson[2].ToString();
|
var pay3str = parsedJson[2].ToString();
|
||||||
Assert.Contains("\"InvoiceDue\": 0", pay3str);
|
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)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
|
|||||||
@@ -1011,12 +1011,23 @@ namespace BTCPayServer.Controllers
|
|||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie, Policy = Policies.CanViewInvoices)]
|
[Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie, Policy = Policies.CanViewInvoices)]
|
||||||
[BitpayAPIConstraint(false)]
|
[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 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 invoiceQuery = GetInvoiceQuery(searchTerm, timezoneOffset);
|
||||||
invoiceQuery.StoreId = new[] { GetCurrentStore().Id };
|
invoiceQuery.StoreId = storeIds.ToArray();
|
||||||
invoiceQuery.Skip = 0;
|
invoiceQuery.Skip = 0;
|
||||||
invoiceQuery.Take = int.MaxValue;
|
invoiceQuery.Take = int.MaxValue;
|
||||||
var invoices = await _InvoiceRepository.GetInvoices(invoiceQuery);
|
var invoices = await _InvoiceRepository.GetInvoices(invoiceQuery);
|
||||||
|
|||||||
@@ -267,8 +267,8 @@
|
|||||||
Export
|
Export
|
||||||
</button>
|
</button>
|
||||||
<div class="dropdown-menu" aria-labelledby="ExportDropdownToggle">
|
<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="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-searchTerm="@Model.SearchTerm" class="dropdown-item export-link" target="_blank">JSON</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>
|
</div>
|
||||||
<a href="https://docs.btcpayserver.org/Accounting/" target="_blank" rel="noreferrer noopener">
|
<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>
|
<span class="fa fa-question-circle-o text-secondary" title="More information..."></span>
|
||||||
|
|||||||
Reference in New Issue
Block a user