Invoice filter must work with duplicated filter

This commit is contained in:
nicolas.dorier
2018-04-26 11:01:59 +09:00
parent 8745c3f8c6
commit 16f1791a9a
7 changed files with 47 additions and 17 deletions

View File

@@ -598,8 +598,18 @@ namespace BTCPayServer.Tests
var search = new SearchString(filter); var search = new SearchString(filter);
Assert.Equal("storeid:abc status:abed blabhbalh", search.ToString()); Assert.Equal("storeid:abc status:abed blabhbalh", search.ToString());
Assert.Equal("blabhbalh", search.TextSearch); Assert.Equal("blabhbalh", search.TextSearch);
Assert.Equal("abc", search.Filters["storeid"]); Assert.Single(search.Filters["storeid"]);
Assert.Equal("abed", search.Filters["status"]); Assert.Single(search.Filters["status"]);
Assert.Equal("abc", search.Filters["storeid"].First());
Assert.Equal("abed", search.Filters["status"].First());
filter = "status:abed status:abed2";
search = new SearchString(filter);
Assert.Equal("status:abed status:abed2", search.ToString());
Assert.Throws<KeyNotFoundException>(() => search.Filters["test"]);
Assert.Equal(2, search.Filters["status"].Count);
Assert.Equal("abed", search.Filters["status"].First());
Assert.Equal("abed2", search.Filters["status"].Skip(1).First());
} }
[Fact] [Fact]
@@ -1054,13 +1064,13 @@ namespace BTCPayServer.Tests
{ {
var textSearchResult = tester.PayTester.InvoiceRepository.GetInvoices(new InvoiceQuery() var textSearchResult = tester.PayTester.InvoiceRepository.GetInvoices(new InvoiceQuery()
{ {
StoreId = user.StoreId, StoreId = new[] { user.StoreId },
TextSearch = invoice.OrderId TextSearch = invoice.OrderId
}).GetAwaiter().GetResult(); }).GetAwaiter().GetResult();
Assert.Single(textSearchResult); Assert.Single(textSearchResult);
textSearchResult = tester.PayTester.InvoiceRepository.GetInvoices(new InvoiceQuery() textSearchResult = tester.PayTester.InvoiceRepository.GetInvoices(new InvoiceQuery()
{ {
StoreId = user.StoreId, StoreId = new[] { user.StoreId },
TextSearch = invoice.Id TextSearch = invoice.Id
}).GetAwaiter().GetResult(); }).GetAwaiter().GetResult();

View File

@@ -87,8 +87,8 @@ namespace BTCPayServer.Controllers
StartDate = dateStart, StartDate = dateStart,
OrderId = orderId, OrderId = orderId,
ItemCode = itemCode, ItemCode = itemCode,
Status = status, Status = status == null ? null : new[] { status },
StoreId = store.Id StoreId = new[] { store.Id }
}; };

View File

@@ -366,8 +366,8 @@ namespace BTCPayServer.Controllers
Count = count, Count = count,
Skip = skip, Skip = skip,
UserId = GetUserId(), UserId = GetUserId(),
Status = filterString.Filters.TryGet("status"), Status = filterString.Filters.ContainsKey("status") ? filterString.Filters["status"].ToArray() : null,
StoreId = filterString.Filters.TryGet("storeid") StoreId = filterString.Filters.ContainsKey("storeid") ? filterString.Filters["storeid"].ToArray() : null
})) }))
{ {
model.SearchTerm = searchTerm; model.SearchTerm = searchTerm;

View File

@@ -1111,4 +1111,17 @@ namespace BTCPayServer
#endregion #endregion
} }
} }
public static class MultiValueDictionaryExtensions
{
public static MultiValueDictionary<TKey, TValue> ToMultiValueDictionary<TInput, TKey, TValue>(this IEnumerable<TInput> collection, Func<TInput, TKey> keySelector, Func<TInput, TValue> valueSelector)
{
var dictionary = new MultiValueDictionary<TKey, TValue>();
foreach(var item in collection)
{
dictionary.Add(keySelector(item), valueSelector(item));
}
return dictionary;
}
}
} }

View File

@@ -21,7 +21,7 @@ namespace BTCPayServer
.Select(t => t.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries)) .Select(t => t.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries))
.Where(kv => kv.Length == 2) .Where(kv => kv.Length == 2)
.Select(kv => new KeyValuePair<string, string>(kv[0].ToLowerInvariant(), kv[1])) .Select(kv => new KeyValuePair<string, string>(kv[0].ToLowerInvariant(), kv[1]))
.ToDictionary(o => o.Key, o => o.Value); .ToMultiValueDictionary(o => o.Key, o => o.Value);
foreach(var filter in splitted) foreach(var filter in splitted)
{ {
@@ -39,7 +39,7 @@ namespace BTCPayServer
private set; private set;
} }
public Dictionary<string, string> Filters { get; private set; } public MultiValueDictionary<string, string> Filters { get; private set; }
public override string ToString() public override string ToString()
{ {

View File

@@ -399,9 +399,10 @@ namespace BTCPayServer.Services.Invoices
query = query.Where(i => i.Id == queryObject.InvoiceId); query = query.Where(i => i.Id == queryObject.InvoiceId);
} }
if (!string.IsNullOrEmpty(queryObject.StoreId)) if (queryObject.StoreId != null && queryObject.StoreId.Length > 0)
{ {
query = query.Where(i => i.StoreDataId == queryObject.StoreId); var stores = queryObject.StoreId.ToHashSet();
query = query.Where(i => stores.Contains(i.StoreDataId));
} }
if (queryObject.UserId != null) if (queryObject.UserId != null)
@@ -429,8 +430,11 @@ namespace BTCPayServer.Services.Invoices
if (queryObject.OrderId != null) if (queryObject.OrderId != null)
query = query.Where(i => i.OrderId == queryObject.OrderId); query = query.Where(i => i.OrderId == queryObject.OrderId);
if (queryObject.Status != null) if (queryObject.Status != null && queryObject.Status.Length > 0)
query = query.Where(i => i.Status == queryObject.Status); {
var statusSet = queryObject.Status.ToHashSet();
query = query.Where(i => statusSet.Contains(i.Status));
}
query = query.OrderByDescending(q => q.Created); query = query.OrderByDescending(q => q.Created);
@@ -568,7 +572,7 @@ namespace BTCPayServer.Services.Invoices
public class InvoiceQuery public class InvoiceQuery
{ {
public string StoreId public string[] StoreId
{ {
get; set; get; set;
} }
@@ -610,7 +614,7 @@ namespace BTCPayServer.Services.Invoices
get; set; get; set;
} }
public string Status public string[] Status
{ {
get; set; get; set;
} }

View File

@@ -26,6 +26,9 @@
<li><b>storeid:id</b> for filtering a specific store</li> <li><b>storeid:id</b> for filtering a specific store</li>
<li><b>status:(expired|invalid|complete|confirmed|paid|new)</b> for filtering a specific status</li> <li><b>status:(expired|invalid|complete|confirmed|paid|new)</b> for filtering a specific status</li>
</ul> </ul>
<p>
If you want two confirmed and complete invoices, duplicate the filter: `status:confirmed status:complete`.
</p>
</div> </div>
<div class="form-group"> <div class="form-group">
<form asp-action="SearchInvoice" method="post"> <form asp-action="SearchInvoice" method="post">