From 8490c3d2ac1468245727c422e5bd2122820e2317 Mon Sep 17 00:00:00 2001
From: Robert Goldmann <deadlocker@gmx.de>
Date: Sun, 3 Mar 2019 18:03:10 +0100
Subject: [PATCH] Fixed #293 - fixed filtering by tags

---
 .../deadlocker8/budgetmaster/tags/Tag_.java   | 13 +++++
 .../TransactionSpecifications.java            | 16 ++++-
 .../transactions/Transaction_.java            |  2 +-
 src/main/resources/static/js/transactions.js  |  1 -
 .../TransactionRepositoryTest.java            | 58 ++++++++++++++++++-
 5 files changed, 82 insertions(+), 8 deletions(-)
 create mode 100644 src/main/java/de/deadlocker8/budgetmaster/tags/Tag_.java

diff --git a/src/main/java/de/deadlocker8/budgetmaster/tags/Tag_.java b/src/main/java/de/deadlocker8/budgetmaster/tags/Tag_.java
new file mode 100644
index 000000000..f93592e78
--- /dev/null
+++ b/src/main/java/de/deadlocker8/budgetmaster/tags/Tag_.java
@@ -0,0 +1,13 @@
+package de.deadlocker8.budgetmaster.tags;
+
+import de.deadlocker8.budgetmaster.transactions.Transaction;
+
+import javax.persistence.metamodel.SingularAttribute;
+import javax.persistence.metamodel.StaticMetamodel;
+
+@StaticMetamodel(Tag.class)
+public class Tag_
+{
+	public static volatile SingularAttribute<Tag, Integer> ID;
+	public static volatile SingularAttribute<Tag, Integer> amount;
+}
diff --git a/src/main/java/de/deadlocker8/budgetmaster/transactions/TransactionSpecifications.java b/src/main/java/de/deadlocker8/budgetmaster/transactions/TransactionSpecifications.java
index 2a3999bb5..44828251b 100644
--- a/src/main/java/de/deadlocker8/budgetmaster/transactions/TransactionSpecifications.java
+++ b/src/main/java/de/deadlocker8/budgetmaster/transactions/TransactionSpecifications.java
@@ -1,11 +1,14 @@
 package de.deadlocker8.budgetmaster.transactions;
 
 import de.deadlocker8.budgetmaster.accounts.Account;
+import de.deadlocker8.budgetmaster.tags.Tag;
+import de.deadlocker8.budgetmaster.tags.Tag_;
 import org.joda.time.DateTime;
 import org.springframework.data.jpa.domain.Specification;
 
-import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.*;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 
 public class TransactionSpecifications
@@ -56,12 +59,19 @@ public class TransactionSpecifications
 
 			if(tagIDs != null)
 			{
-//				predicates.add(builder.and(transaction.get(Transaction_.tags).in(tagIDs)));
+				Join<Transaction, Tag> join = transaction.join(Transaction_.tags);
+				Predicate actorIdPredicate = builder.disjunction();
+				for(Integer tagID : tagIDs)
+				{
+					actorIdPredicate.getExpressions().add(builder.equal(join.get(Tag_.ID), tagID));
+				}
+
+				predicates.add(actorIdPredicate);
 			}
 
 			if(name != null && name.length() > 0)
 			{
-				predicates.add(builder.and(builder.like(builder.lower(transaction.get(Transaction_.name)), "%"+name.toLowerCase()+"%")));
+				predicates.add(builder.and(builder.like(builder.lower(transaction.get(Transaction_.name)), "%" + name.toLowerCase() + "%")));
 			}
 
 			query.orderBy(builder.desc(transaction.get(Transaction_.date)));
diff --git a/src/main/java/de/deadlocker8/budgetmaster/transactions/Transaction_.java b/src/main/java/de/deadlocker8/budgetmaster/transactions/Transaction_.java
index 38498990a..68a4c071a 100644
--- a/src/main/java/de/deadlocker8/budgetmaster/transactions/Transaction_.java
+++ b/src/main/java/de/deadlocker8/budgetmaster/transactions/Transaction_.java
@@ -21,6 +21,6 @@ public class Transaction_
 	public static volatile SingularAttribute<Transaction, Category> category;
 	public static volatile SingularAttribute<Transaction, String> name;
 	public static volatile SingularAttribute<Transaction, String> description;
-	public static volatile ListAttribute<Transaction, List<Tag>> tags;
+	public static volatile ListAttribute<Transaction, Tag> tags;
 	public static volatile SingularAttribute<Transaction, RepeatingOption> repeatingOption;
 }
diff --git a/src/main/resources/static/js/transactions.js b/src/main/resources/static/js/transactions.js
index 6a4803f43..4b7b89f09 100644
--- a/src/main/resources/static/js/transactions.js
+++ b/src/main/resources/static/js/transactions.js
@@ -142,7 +142,6 @@ $( document ).ready(function() {
 
     // prevent form submit on enter (otherwise tag functionality will be hard to use)
     $(document).on("keypress", 'form', function (e) {
-
         var code = e.keyCode || e.which;
         if((code === 13) &&  e.target.nodeName!=='TEXTAREA') {
             e.preventDefault();
diff --git a/src/test/java/de/deadlocker8/budgetmaster/TransactionRepositoryTest.java b/src/test/java/de/deadlocker8/budgetmaster/TransactionRepositoryTest.java
index 0c702d24e..9769bb21a 100644
--- a/src/test/java/de/deadlocker8/budgetmaster/TransactionRepositoryTest.java
+++ b/src/test/java/de/deadlocker8/budgetmaster/TransactionRepositoryTest.java
@@ -54,6 +54,8 @@ public class TransactionRepositoryTest
 	@Autowired
 	private TagRepository tagRepository;
 	private Tag tag1;
+	private Tag tag2;
+	private Tag tagUnused;
 
 	@Autowired
 	private RepeatingOptionRepository repeatingOptionRepository;
@@ -72,6 +74,8 @@ public class TransactionRepositoryTest
 		category2 = categoryRepository.save(new Category("Category2", "#ff0000", CategoryType.CUSTOM));
 
 		tag1 = tagRepository.save(new Tag("MyAwesomeTag"));
+		tag2 = tagRepository.save(new Tag("TagMaster_2"));
+		tagUnused = tagRepository.save(new Tag("Unused"));
 
 		transaction1 = new Transaction();
 		transaction1.setName("Test");
@@ -79,6 +83,9 @@ public class TransactionRepositoryTest
 		transaction1.setDate(new DateTime(2018, 10, 3, 12, 0, 0, 0));
 		transaction1.setCategory(category1);
 		transaction1.setAccount(account);
+		ArrayList<Tag> tags = new ArrayList<>();
+		tags.add(tag1);
+		transaction1.setTags(tags);
 		transaction1 = transactionRepository.save(transaction1);
 
 		transaction2 = new Transaction();
@@ -105,9 +112,9 @@ public class TransactionRepositoryTest
 		repeatingTransaction.setDescription("");
 		repeatingTransaction.setAccount(account);
 		repeatingTransaction.setRepeatingOption(repeatingOption);
-		ArrayList<Tag> tags = new ArrayList<>();
-		tags.add(tag1);
-		repeatingTransaction.setTags(tags);
+		ArrayList<Tag> tags2 = new ArrayList<>();
+		tags2.add(tag2);
+		repeatingTransaction.setTags(tags2);
 		repeatingTransaction = transactionRepository.save(repeatingTransaction);
 	}
 
@@ -225,6 +232,50 @@ public class TransactionRepositoryTest
 		assertTrue(results.contains(repeatingTransaction));
 	}
 
+	@Test
+	public void getByTags()
+	{
+		List<Integer> tagIDs = new ArrayList<>();
+		tagIDs.add(tag1.getID());
+
+		Specification spec = TransactionSpecifications.withDynamicQuery(startDate, DateTime.now(), account, true, true, null, null, tagIDs, null);
+
+		List<Transaction> results = transactionRepository.findAll(spec);
+		assertTrue(results.contains(transaction1));
+		assertFalse(results.contains(transaction2));
+		assertFalse(results.contains(repeatingTransaction));
+	}
+
+	@Test
+	public void getByMultipleTags()
+	{
+		List<Integer> tagIDs = new ArrayList<>();
+		tagIDs.add(tag1.getID());
+		tagIDs.add(tag2.getID());
+
+		Specification spec = TransactionSpecifications.withDynamicQuery(startDate, DateTime.now(), account, true, true, null, null, tagIDs, null);
+
+		List<Transaction> results = transactionRepository.findAll(spec);
+		assertTrue(results.contains(transaction1));
+		assertFalse(results.contains(transaction2));
+		assertTrue(results.contains(repeatingTransaction));
+	}
+
+
+	@Test
+	public void getByUnusedTags()
+	{
+		List<Integer> tagIDs = new ArrayList<>();
+		tagIDs.add(tagUnused.getID());
+
+		Specification spec = TransactionSpecifications.withDynamicQuery(startDate, DateTime.now(), account, true, true, null, null, tagIDs, null);
+
+		List<Transaction> results = transactionRepository.findAll(spec);
+		assertFalse(results.contains(transaction1));
+		assertFalse(results.contains(transaction2));
+		assertFalse(results.contains(repeatingTransaction));
+	}
+
 	@Test
 	public void getRepeatingExpenditureByCategoryAndTagsAndName()
 	{
@@ -233,6 +284,7 @@ public class TransactionRepositoryTest
 
 		List<Integer> tagIDs = new ArrayList<>();
 		tagIDs.add(tag1.getID());
+		tagIDs.add(tag2.getID());
 
 		Specification spec = TransactionSpecifications.withDynamicQuery(startDate, DateTime.now(), account, false, true, true, categoryIDs, tagIDs, "Repeating");
 
-- 
GitLab