From e526f861b2a7f46a073273482f10111f06e44f84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Falc=C3=B3n?= Date: Fri, 12 Jun 2026 19:04:43 +0200 Subject: [PATCH] fix(automation-rules): hint amount sign for expenses vs income (#524) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Problem A user reported automation rules not applying. The rule matched a description **and** `Valor es igual a 21,99`, but never fired. Root cause: the matching engine evaluates the **signed** transaction amount (`amount / 100`), and expenses are stored negative. So an expense of `-21,99` is compared as `-21.99 == 21.99` → false. The rule editor showed a plain number input with no hint about the sign convention, so entering a positive `21,99` to match an expense silently builds a rule that can never match. This is a common trap — likely affecting many users with amount-based rules. ## Change Add a small helper note under the numeric `amount`/`Valor` value input: > Usa un valor negativo para gastos (ej. -21,99) y un valor positivo para ingresos. - Renders only for the numeric `amount` field; text conditions are unaffected. - No change to how rules are stored or evaluated — existing rules keep working. - Added the Spanish translation key (`es.json` is CI-enforced). ## Testing - `bun run format` and `eslint` clean on the component. - `LocalizationTest` passes (translation key resolves, no missing keys). ## Follow-up (not in this PR) The hint guides new rules but doesn't retroactively fix rules already saved wrong. A future enhancement could warn when saving a positive-value amount condition, since most finance rules target expenses. --- lang/es.json | 1 + .../automation-rules/rule-builder.tsx | 121 ++++++++++-------- 2 files changed, 70 insertions(+), 52 deletions(-) diff --git a/lang/es.json b/lang/es.json index cfd7b919..9364919a 100644 --- a/lang/es.json +++ b/lang/es.json @@ -1645,6 +1645,7 @@ "Uruguayan Peso": "Peso uruguayo", "Usage Information:": "Información de Uso:", "Use Defaults": "Usar Valores Predeterminados", + "Use a negative value for expenses (e.g. -21.99) and a positive value for income.": "Usa un valor negativo para gastos (ej. -21,99) y un valor positivo para ingresos.", "Use a strong password (minimum 12 characters). This password will encrypt your data.": "Usa una contraseña fuerte (mínimo 12 caracteres). Esta contraseña encriptará tus datos.", "Use a strong password (minimum 12 characters). This\\n password will encrypt your data.": "Usa una contraseña segura (mínimo 12 caracteres). Esta contraseña cifrará tus datos.", "Use a view-only key.": "Usa una clave de solo lectura.", diff --git a/resources/js/components/automation-rules/rule-builder.tsx b/resources/js/components/automation-rules/rule-builder.tsx index 38cf861d..a064cbf5 100644 --- a/resources/js/components/automation-rules/rule-builder.tsx +++ b/resources/js/components/automation-rules/rule-builder.tsx @@ -275,62 +275,79 @@ function ConditionRow({ const inputType = fieldConfig?.type === 'number' ? 'number' : 'text'; + const showAmountHint = showValueInput && inputType === 'number'; + return ( -
- +
+
+ - + - {showValueInput && ( - - onChange({ ...condition, value: e.target.value }) - } - placeholder={__('Value')} - className="w-full sm:flex-1" - step={inputType === 'number' ? 'any' : undefined} - /> + {showValueInput && ( + + onChange({ ...condition, value: e.target.value }) + } + placeholder={__('Value')} + className="w-full sm:flex-1" + step={inputType === 'number' ? 'any' : undefined} + /> + )} + + {!showValueInput && ( +
+ )} + + +
+ + {showAmountHint && ( +

+ {__( + 'Use a negative value for expenses (e.g. -21.99) and a positive value for income.', + )} +

)} - - {!showValueInput &&
} - -
); }