From a98a423f057be913a6652b73121e1ce0c83d6a93 Mon Sep 17 00:00:00 2001
From: Robert Goldmann <deadlocker@gmx.de>
Date: Sun, 29 Aug 2021 21:37:11 +0200
Subject: [PATCH] Fixed #642 - search: added new checkbox to include
 transactions from hidden accounts

---
 .../budgetmaster/search/Search.java           | 17 ++++++++--
 .../TransactionSearchSpecifications.java      | 17 +++++++++-
 .../resources/languages/base_de.properties    |  1 +
 .../resources/languages/base_en.properties    |  1 +
 .../templates/search/searchMacros.ftl         |  8 +++++
 .../integration/selenium/SearchTest.java      |  1 +
 .../TransactionSearchSpecificationsTest.java  | 34 ++++++++++++-------
 7 files changed, 64 insertions(+), 15 deletions(-)

diff --git a/src/main/java/de/deadlocker8/budgetmaster/search/Search.java b/src/main/java/de/deadlocker8/budgetmaster/search/Search.java
index 5b9917100..221494b7e 100644
--- a/src/main/java/de/deadlocker8/budgetmaster/search/Search.java
+++ b/src/main/java/de/deadlocker8/budgetmaster/search/Search.java
@@ -2,13 +2,14 @@ package de.deadlocker8.budgetmaster.search;
 
 public class Search
 {
-	public static final Search DEFAULT = new Search("", true, true, true, true, 0);
+	public static final Search DEFAULT = new Search("", true, true, true, true, false, 0);
 
 	private String searchText;
 	private boolean searchName;
 	private boolean searchDescription;
 	private boolean searchCategory;
 	private boolean searchTags;
+	private boolean includeHiddenAccounts;
 	private int page;
 
 	public Search()
@@ -17,13 +18,14 @@ public class Search
 		this.page = 0;
 	}
 
-	public Search(String searchText, boolean searchName, boolean searchDescription, boolean searchCategory, boolean searchTags, int page)
+	public Search(String searchText, boolean searchName, boolean searchDescription, boolean searchCategory, boolean searchTags, boolean includeHiddenAccounts, int page)
 	{
 		this.searchText = searchText;
 		this.searchName = searchName;
 		this.searchDescription = searchDescription;
 		this.searchCategory = searchCategory;
 		this.searchTags = searchTags;
+		this.includeHiddenAccounts = includeHiddenAccounts;
 		this.page = page;
 	}
 
@@ -77,6 +79,16 @@ public class Search
 		this.searchTags = searchTags;
 	}
 
+	public boolean isIncludeHiddenAccounts()
+	{
+		return includeHiddenAccounts;
+	}
+
+	public void setIncludeHiddenAccounts(boolean includeHiddenAccounts)
+	{
+		this.includeHiddenAccounts = includeHiddenAccounts;
+	}
+
 	public int getPage()
 	{
 		return page;
@@ -100,6 +112,7 @@ public class Search
 				", searchDescription=" + searchDescription +
 				", searchCategory=" + searchCategory +
 				", searchTags=" + searchTags +
+				", includeHiddenAccounts=" + includeHiddenAccounts +
 				", page=" + page +
 				'}';
 	}
diff --git a/src/main/java/de/deadlocker8/budgetmaster/transactions/TransactionSearchSpecifications.java b/src/main/java/de/deadlocker8/budgetmaster/transactions/TransactionSearchSpecifications.java
index ed3afbb43..f2ace4e2e 100644
--- a/src/main/java/de/deadlocker8/budgetmaster/transactions/TransactionSearchSpecifications.java
+++ b/src/main/java/de/deadlocker8/budgetmaster/transactions/TransactionSearchSpecifications.java
@@ -51,10 +51,25 @@ public class TransactionSearchSpecifications
 			Predicate[] predicatesArray = new Predicate[predicates.size()];
 			Predicate predicatesCombined = builder.or(predicates.toArray(predicatesArray));
 
-			Predicate accountStatePredicate = transaction.get(Transaction_.account).get("accountState").in(List.of(AccountState.FULL_ACCESS, AccountState.READ_ONLY));
+			Predicate accountStatePredicate = transaction.get(Transaction_.account).get("accountState").in(getAllowedAccountStates(search));
+			;
 
 			query.orderBy(builder.desc(transaction.get(Transaction_.date)));
 			return builder.and(accountStatePredicate, predicatesCombined);
 		};
 	}
+
+	private static List<AccountState> getAllowedAccountStates(Search search)
+	{
+		List<AccountState> allowedAccountStates = new ArrayList<>();
+		allowedAccountStates.add(AccountState.FULL_ACCESS);
+		allowedAccountStates.add(AccountState.READ_ONLY);
+
+		if(search.isIncludeHiddenAccounts())
+		{
+			allowedAccountStates.add(AccountState.HIDDEN);
+		}
+
+		return allowedAccountStates;
+	}
 }
diff --git a/src/main/resources/languages/base_de.properties b/src/main/resources/languages/base_de.properties
index 42dd1aaac..bfe443661 100644
--- a/src/main/resources/languages/base_de.properties
+++ b/src/main/resources/languages/base_de.properties
@@ -336,6 +336,7 @@ search.in.name=Name
 search.in.description=Beschreibung
 search.in.category=Kategorie
 search.in.tags=Tags
+search.include.hidden.accounts=Versteckte Konten
 
 template.checkbox.include.category=Kategorie übernehmen
 template.checkbox.include.account=Konto übernehmen
diff --git a/src/main/resources/languages/base_en.properties b/src/main/resources/languages/base_en.properties
index 97c8db5b9..cf7c86c5c 100644
--- a/src/main/resources/languages/base_en.properties
+++ b/src/main/resources/languages/base_en.properties
@@ -337,6 +337,7 @@ search.in.name=Name
 search.in.description=Description
 search.in.category=Category
 search.in.tags=Tags
+search.include.hidden.accounts=Hidden accounts
 
 template.checkbox.include.category=Include category
 template.checkbox.include.account=Include account
diff --git a/src/main/resources/templates/search/searchMacros.ftl b/src/main/resources/templates/search/searchMacros.ftl
index 863786171..3c011ca27 100644
--- a/src/main/resources/templates/search/searchMacros.ftl
+++ b/src/main/resources/templates/search/searchMacros.ftl
@@ -55,6 +55,14 @@
                 </label>
             </div>
         </div>
+        <div class="col s8 offset-s2 m4 offset-m2 l3 offset-l3">
+            <div class="search-checkbox-container">
+                <label>
+                    <input type="checkbox" name="includeHiddenAccounts" <#if search.isIncludeHiddenAccounts()>checked="checked"</#if>>
+                    <span class="text-default">${locale.getString('search.include.hidden.accounts')}</span>
+                </label>
+            </div>
+        </div>
     </div>
 </#macro>
 
diff --git a/src/test/java/de/deadlocker8/budgetmaster/integration/selenium/SearchTest.java b/src/test/java/de/deadlocker8/budgetmaster/integration/selenium/SearchTest.java
index 17eb2e051..a4d6e2944 100644
--- a/src/test/java/de/deadlocker8/budgetmaster/integration/selenium/SearchTest.java
+++ b/src/test/java/de/deadlocker8/budgetmaster/integration/selenium/SearchTest.java
@@ -132,6 +132,7 @@ class SearchTest extends SeleniumTestBase
 		assertThat(driver.findElement(By.cssSelector(".main-card #searchForm input[name=\"searchDescription\"]")).isSelected()).isFalse();
 		assertThat(driver.findElement(By.cssSelector(".main-card #searchForm input[name=\"searchCategory\"]")).isSelected()).isTrue();
 		assertThat(driver.findElement(By.cssSelector(".main-card #searchForm input[name=\"searchTags\"]")).isSelected()).isTrue();
+		assertThat(driver.findElement(By.cssSelector(".main-card #searchForm input[name=\"includeHiddenAccounts\"]")).isSelected()).isFalse();
 
 		// results
 		List<WebElement> results = driver.findElements(By.cssSelector(".search-container .card-panel"));
diff --git a/src/test/java/de/deadlocker8/budgetmaster/unit/TransactionSearchSpecificationsTest.java b/src/test/java/de/deadlocker8/budgetmaster/unit/TransactionSearchSpecificationsTest.java
index 04045e2bb..ba11b5e4e 100644
--- a/src/test/java/de/deadlocker8/budgetmaster/unit/TransactionSearchSpecificationsTest.java
+++ b/src/test/java/de/deadlocker8/budgetmaster/unit/TransactionSearchSpecificationsTest.java
@@ -139,7 +139,7 @@ class TransactionSearchSpecificationsTest
 	@Test
 	void getMatches_OnlyName()
 	{
-		Search search = new Search("Test", true, false, false, false, 0);
+		Search search = new Search("Test", true, false, false, false, false, 0);
 		Specification spec = TransactionSearchSpecifications.withDynamicQuery(search);
 
 		List<Transaction> results = transactionRepository.findAll(spec);
@@ -150,7 +150,7 @@ class TransactionSearchSpecificationsTest
 	@Test
 	void getMatches_PartialName()
 	{
-		Search search = new Search("es", true, false, false, false, 0);
+		Search search = new Search("es", true, false, false, false, false, 0);
 		Specification spec = TransactionSearchSpecifications.withDynamicQuery(search);
 
 		List<Transaction> results = transactionRepository.findAll(spec);
@@ -161,7 +161,7 @@ class TransactionSearchSpecificationsTest
 	@Test
 	void getMatches_IgnoreCase()
 	{
-		Search search = new Search("tEST", true, true, true, true, 0);
+		Search search = new Search("tEST", true, true, true, true, false, 0);
 		Specification spec = TransactionSearchSpecifications.withDynamicQuery(search);
 
 		List<Transaction> results = transactionRepository.findAll(spec);
@@ -172,7 +172,7 @@ class TransactionSearchSpecificationsTest
 	@Test
 	void getMatches_OnlyDescription()
 	{
-		Search search = new Search("What", true, true, true, true, 0);
+		Search search = new Search("What", true, true, true, true, false, 0);
 		Specification spec = TransactionSearchSpecifications.withDynamicQuery(search);
 
 		List<Transaction> results = transactionRepository.findAll(spec);
@@ -183,7 +183,7 @@ class TransactionSearchSpecificationsTest
 	@Test
 	void getMatches_OnlyCategory()
 	{
-		Search search = new Search(category2.getName(), false, false, true, false, 0);
+		Search search = new Search(category2.getName(), false, false, true, false, false, 0);
 		Specification spec = TransactionSearchSpecifications.withDynamicQuery(search);
 
 		List<Transaction> results = transactionRepository.findAll(spec);
@@ -195,7 +195,7 @@ class TransactionSearchSpecificationsTest
 	@Test
 	void getMatches_Order()
 	{
-		Search search = new Search("", true, true, true, true, 0);
+		Search search = new Search("", true, true, true, true, false, 0);
 		Specification spec = TransactionSearchSpecifications.withDynamicQuery(search);
 
 		List<Transaction> results = transactionRepository.findAll(spec);
@@ -209,7 +209,7 @@ class TransactionSearchSpecificationsTest
 	@Test
 	void getMatches_Mixed()
 	{
-		Search search = new Search("e", true, true, true, true, 0);
+		Search search = new Search("e", true, true, true, true, false, 0);
 		Specification spec = TransactionSearchSpecifications.withDynamicQuery(search);
 
 		List<Transaction> results = transactionRepository.findAll(spec);
@@ -222,7 +222,7 @@ class TransactionSearchSpecificationsTest
 	@Test
 	void getMatches_NoMatches()
 	{
-		Search search = new Search("asuzgdzasuiduzasds", true, true, true, true, 0);
+		Search search = new Search("asuzgdzasuiduzasds", true, true, true, true, false, 0);
 		Specification spec = TransactionSearchSpecifications.withDynamicQuery(search);
 
 		List<Transaction> results = transactionRepository.findAll(spec);
@@ -232,7 +232,7 @@ class TransactionSearchSpecificationsTest
 	@Test
 	void getMatches_SearchNothing()
 	{
-		Search search = new Search("egal", false, false, false, false, 0);
+		Search search = new Search("egal", false, false, false, false, false, 0);
 		Specification spec = TransactionSearchSpecifications.withDynamicQuery(search);
 
 		List<Transaction> results = transactionRepository.findAll(spec);
@@ -242,7 +242,7 @@ class TransactionSearchSpecificationsTest
 	@Test
 	void getMatches_SearchTagsEquals()
 	{
-		Search search = new Search("MyAwesomeTag", false, false, false, true, 0);
+		Search search = new Search("MyAwesomeTag", false, false, false, true, false, 0);
 		Specification spec = TransactionSearchSpecifications.withDynamicQuery(search);
 
 		List<Transaction> results = transactionRepository.findAll(spec);
@@ -253,7 +253,7 @@ class TransactionSearchSpecificationsTest
 	@Test
 	void getMatches_SearchTagsLike()
 	{
-		Search search = new Search("Awesome", false, false, false, true, 0);
+		Search search = new Search("Awesome", false, false, false, true, false, 0);
 		Specification spec = TransactionSearchSpecifications.withDynamicQuery(search);
 
 		List<Transaction> results = transactionRepository.findAll(spec);
@@ -264,10 +264,20 @@ class TransactionSearchSpecificationsTest
 	@Test
 	void getMatches_IgnoreTransactionsFromHiddenAccounts()
 	{
-		Search search = new Search("hidden", true, false, false, false, 0);
+		Search search = new Search("hidden", true, false, false, false, false, 0);
 		Specification spec = TransactionSearchSpecifications.withDynamicQuery(search);
 
 		List<Transaction> results = transactionRepository.findAll(spec);
 		assertThat(results).isEmpty();
 	}
+
+	@Test
+	void getMatches_IncludeTransactionsFromHiddenAccounts()
+	{
+		Search search = new Search("hidden", true, false, false, false, true, 0);
+		Specification spec = TransactionSearchSpecifications.withDynamicQuery(search);
+
+		List<Transaction> results = transactionRepository.findAll(spec);
+		assertThat(results).containsExactly(transactionFromHiddenAccount);
+	}
 }
\ No newline at end of file
-- 
GitLab