From 2cb577b912bee24f598653e68f95c39c85637d02 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Wed, 1 Jul 2026 13:31:12 +0530 Subject: [PATCH] fix(banking): use custom renderer for translated strings and parser for rules (backport #56643) (#56647) fix(banking): use custom renderer for translated strings and parser for rules (#56643) fix(banking): use custom renderer for translated strings and parser for formula evaluation (cherry picked from commit 8447f551e7b0ee9f611cf42533e33141105b0af2) Co-authored-by: Nikhil Kothari --- banking/package.json | 1 + .../BankClearanceSummary.tsx | 12 ++--- .../BankEntryModalContent.tsx | 32 ++----------- .../BankReconciliationStatement.tsx | 12 ++--- .../BankTransactionList.tsx | 12 ++--- .../IncorrectlyClearedEntries.tsx | 18 +++---- .../BankReconciliation/Rules/RuleForm.tsx | 4 +- banking/src/lib/amountFormula.ts | 26 ++++++++++ banking/yarn.lock | 5 ++ .../bank_transaction_rule.py | 47 +++++++++++++++++++ .../test_bank_transaction_rule.py | 42 +++++++++++++++++ 11 files changed, 154 insertions(+), 57 deletions(-) create mode 100644 banking/src/lib/amountFormula.ts diff --git a/banking/package.json b/banking/package.json index 439e4376789..a957fb01bf6 100644 --- a/banking/package.json +++ b/banking/package.json @@ -42,6 +42,7 @@ "react-router": "^8.1.0", "rehype-raw": "^7.0.0", "remark-gfm": "^4.0.1", + "safe-expr-eval": "^1.0.4", "sonner": "^2.0.7", "tailwind-merge": "^3.5.0", "tailwindcss": "^4.3.0", diff --git a/banking/src/components/features/BankReconciliation/BankClearanceSummary.tsx b/banking/src/components/features/BankReconciliation/BankClearanceSummary.tsx index dd248d31092..c26b9e9fb22 100644 --- a/banking/src/components/features/BankReconciliation/BankClearanceSummary.tsx +++ b/banking/src/components/features/BankReconciliation/BankClearanceSummary.tsx @@ -2,7 +2,6 @@ import { useAtomValue } from "jotai" import { MissingFiltersBanner } from "./MissingFiltersBanner" import { bankRecDateAtom, SelectedBank, selectedBankAccountAtom } from "./bankRecAtoms" import { useCurrentCompany } from "@/hooks/useCurrentCompany" -import { Paragraph } from "@/components/ui/typography" import type { ColumnDef } from "@tanstack/react-table" import { useCallback, useMemo, useState } from "react" import { useFrappeGetCall, useFrappePostCall, useSWRConfig } from "frappe-react-sdk" @@ -26,6 +25,7 @@ import { Form } from "@/components/ui/form" import { useForm } from "react-hook-form" import { DateField } from "@/components/ui/form-elements" import { Empty, EmptyMedia, EmptyHeader, EmptyTitle, EmptyDescription } from "@/components/ui/empty" +import MarkdownRenderer from "@/components/ui/markdown" const BankClearanceSummary = () => { const bankAccount = useAtomValue(selectedBankAccountAtom) @@ -203,14 +203,14 @@ const BankClearanceSummaryView = () => { [accountCurrency, bankAccount, companyID, mutate, onCopy], ) + const content = _("Below is a list of all accounting entries posted against the bank account {0} between {1} and {2}.", [`${bankAccount?.account}`, `${formattedFromDate}`, `${formattedToDate}`]) + return
- - ${bankAccount?.account}`, `${formattedFromDate}`, `${formattedToDate}`]) - }} /> - + + +
{error && } diff --git a/banking/src/components/features/BankReconciliation/BankEntryModalContent.tsx b/banking/src/components/features/BankReconciliation/BankEntryModalContent.tsx index 17ef3314a1f..4e5ddb425e2 100644 --- a/banking/src/components/features/BankReconciliation/BankEntryModalContent.tsx +++ b/banking/src/components/features/BankReconciliation/BankEntryModalContent.tsx @@ -18,6 +18,7 @@ import { useMultiFileUploadProgress } from "@/hooks/useMultiFileUploadProgress" import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table" import { Checkbox } from "@/components/ui/checkbox" import { ArrowDownRight, ArrowUpRight, Plus, Trash2 } from "lucide-react" +import { evaluateAmountFormula } from "@/lib/amountFormula" import { flt, formatCurrency } from "@/lib/numbers" import { cn } from "@/lib/utils" import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip" @@ -215,38 +216,13 @@ const BankEntryForm = ({ selectedTransaction }: { selectedTransaction: Unreconci }) } else { - /** - * The debit and credit amounts can also be expressions - like "transaction_amount * 0.5" - * So we need to compute the value of the expression - * We can use the eval function to do this. But we need to expose certain variables to the expression. - * One of them is transaction_amount which is the unallocated amount of the selected transaction - * @param expression - The expression to compute - * @returns The computed value - */ - const computeExpression = (expression: string) => { - - const script = ` - const transaction_amount = ${selectedTransaction.unallocated_amount ?? 0} - ${expression}; - ` - - let value = 0; - - try { - value = window.eval(script); - } catch (error: unknown) { - console.error(error); - value = 0; - } - - return value; - } + const transactionAmount = selectedTransaction.unallocated_amount ?? 0 if (!acc?.debit && !acc?.credit) { hasTotallyEmptyRowEarlier = true; } - const computedDebit = acc?.debit ? flt(computeExpression(acc.debit), 2) : 0 - const computedCredit = acc?.credit ? flt(computeExpression(acc.credit), 2) : 0 + const computedDebit = acc?.debit ? flt(evaluateAmountFormula(acc.debit, transactionAmount), 2) : 0 + const computedCredit = acc?.credit ? flt(evaluateAmountFormula(acc.credit, transactionAmount), 2) : 0 totalDebits = flt(totalDebits + computedDebit, 2) totalCredits = flt(totalCredits + computedCredit, 2) diff --git a/banking/src/components/features/BankReconciliation/BankReconciliationStatement.tsx b/banking/src/components/features/BankReconciliation/BankReconciliationStatement.tsx index 7b505efadc3..0815bc8a65e 100644 --- a/banking/src/components/features/BankReconciliation/BankReconciliationStatement.tsx +++ b/banking/src/components/features/BankReconciliation/BankReconciliationStatement.tsx @@ -2,7 +2,6 @@ import { useAtomValue } from "jotai" import { MissingFiltersBanner } from "./MissingFiltersBanner" import { bankRecDateAtom, selectedBankAccountAtom } from "./bankRecAtoms" import { useCurrentCompany } from "@/hooks/useCurrentCompany" -import { Paragraph } from "@/components/ui/typography" import { useCallback, useMemo } from "react" import type { ColumnDef } from "@tanstack/react-table" import { useFrappeGetCall } from "frappe-react-sdk" @@ -19,6 +18,7 @@ import _ from "@/lib/translate" import { toast } from "sonner" import { useCopyToClipboard } from "usehooks-ts" import { Empty, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle } from "@/components/ui/empty" +import MarkdownRenderer from "@/components/ui/markdown" const BankReconciliationStatement = () => { const bankAccount = useAtomValue(selectedBankAccountAtom) @@ -189,14 +189,14 @@ const BankReconciliationStatementView = () => { return data.message.result.filter((row: BankClearanceSummaryEntry) => Boolean(row.payment_entry)) }, [data]) + const content = _("Below is a list of all entries posted against the bank account {0} which have not been cleared till {1}.", [`${bankAccount?.account}`, `${formatDate(dates.toDate)}`]) + return
- - ${bankAccount?.account}`, `${formatDate(dates.toDate)}`]) - }} /> - + + +
{error && } diff --git a/banking/src/components/features/BankReconciliation/BankTransactionList.tsx b/banking/src/components/features/BankReconciliation/BankTransactionList.tsx index 17f231a0833..1513e567a4b 100644 --- a/banking/src/components/features/BankReconciliation/BankTransactionList.tsx +++ b/banking/src/components/features/BankReconciliation/BankTransactionList.tsx @@ -1,7 +1,6 @@ import { useAtomValue, useSetAtom } from "jotai" import { MissingFiltersBanner } from "./MissingFiltersBanner" import { bankRecDateAtom, bankRecUnreconcileModalAtom, selectedBankAccountAtom } from "./bankRecAtoms" -import { Paragraph } from "@/components/ui/typography" import { formatDate } from "@/lib/date" import { ListView, type ListViewColumnMeta } from "@/components/ui/list-view" import { formatCurrency, getCurrencyFormatInfo } from "@/lib/numbers" @@ -23,6 +22,7 @@ import { useCallback, useMemo, useState } from "react" import { Link } from "react-router" import { Empty, EmptyTitle, EmptyHeader, EmptyMedia, EmptyDescription, EmptyContent } from "@/components/ui/empty" import { InputGroup, InputGroupAddon } from "@/components/ui/input-group" +import MarkdownRenderer from "@/components/ui/markdown" const BankTransactions = () => { const selectedBank = useAtomValue(selectedBankAccountAtom) @@ -243,14 +243,14 @@ const BankTransactionListView = () => { }, [data, search, amountFilter, typeFilter, status]) + const content = _("Below is a list of all bank transactions imported in the system for the bank account {0} between {1} and {2}.", [`${bankAccount?.account_name}`, `${formattedFromDate}`, `${formattedToDate}`]) + return
- - ${bankAccount?.account_name}`, `${formattedFromDate}`, `${formattedToDate}`]) - }} /> - + + +