From 56c5a533e78278d5e984bc3b16d020b688c5edee Mon Sep 17 00:00:00 2001
From: Sebastian Civarolo <scivarolo@gmail.com>
Date: Sat, 3 Aug 2024 13:09:25 -0500
Subject: [PATCH] Fix false positives for duplicate filters error when saving a
 new filter (#2970)

* update conditionExists function to compare filter options

* rename method

* array.some instead of for loop

* release note

* refactor the condition search
---
 packages/loot-core/src/server/filters/app.ts | 62 +++++++++++---------
 upcoming-release-notes/2970.md               |  6 ++
 2 files changed, 41 insertions(+), 27 deletions(-)
 create mode 100644 upcoming-release-notes/2970.md

diff --git a/packages/loot-core/src/server/filters/app.ts b/packages/loot-core/src/server/filters/app.ts
index 4e1c4fd79..c6b4ef69c 100644
--- a/packages/loot-core/src/server/filters/app.ts
+++ b/packages/loot-core/src/server/filters/app.ts
@@ -56,50 +56,58 @@ async function filterNameExists(name, filterId, newItem) {
   return true;
 }
 
-//TODO: Possible to simplify this?
-//use filters and maps
 function conditionExists(item, filters, newItem) {
   const { conditions, conditionsOp } = item;
-  let condCheck = [];
-  let fCondCheck = false;
-  let fCondFound;
+  let fConditionFound = null;
 
-  filters.map(filter => {
+  filters.some(filter => {
     if (
-      !fCondCheck &&
-      //If conditions.length equals 1 then ignore conditionsOp
-      (conditions.length === 1 ? true : filter.conditionsOp === conditionsOp) &&
+      (conditions.length === 1 || filter.conditionsOp === conditionsOp) &&
       !filter.tombstone &&
       filter.conditions.length === conditions.length
     ) {
-      fCondCheck = false;
-      conditions.map((cond, i) => {
-        condCheck[i] =
-          filter.conditions.filter(fcond => {
-            return (
+      const allConditionsMatch = !conditions.some(
+        cond =>
+          !filter.conditions.some(
+            fcond =>
               cond.value === fcond.value &&
               cond.op === fcond.op &&
-              cond.field === fcond.field
-            );
-          }).length > 0;
-        fCondCheck = (i === 0 ? true : fCondCheck) && condCheck[i];
+              cond.field === fcond.field &&
+              filterOptionsMatch(cond.options, fcond.options),
+          ),
+      );
+
+      if (allConditionsMatch) {
+        fConditionFound = filter;
         return true;
-      });
-      fCondFound = fCondCheck && condCheck[conditions.length - 1] && filter;
+      }
     }
-    return true;
+    return false;
   });
 
-  condCheck = [];
-
   if (!newItem) {
-    return fCondFound
-      ? fCondFound.id !== item.id
-        ? fCondFound.name
+    return fConditionFound
+      ? fConditionFound.id !== item.id
+        ? fConditionFound.name
         : false
       : false;
   }
-  return fCondFound ? fCondFound.name : false;
+
+  return fConditionFound ? fConditionFound.name : false;
+}
+
+function filterOptionsMatch(options1, options2) {
+  const opt1 = options1 ?? {};
+  const opt2 = options2 ?? {};
+
+  const keys1 = Object.keys(opt1);
+  const keys2 = Object.keys(opt2);
+
+  if (keys1.length !== keys2.length) {
+    return false;
+  }
+
+  return keys1.every(key => opt1[key] === opt2[key]);
 }
 
 async function createFilter(filter) {
diff --git a/upcoming-release-notes/2970.md b/upcoming-release-notes/2970.md
new file mode 100644
index 000000000..43d444d73
--- /dev/null
+++ b/upcoming-release-notes/2970.md
@@ -0,0 +1,6 @@
+---
+category: Bugfix
+authors: [scivarolo]
+---
+
+Fix false positives for duplicate filters error when saving a new filter.
-- 
GitLab