From d7dbb87a8f6cf28e471cbbf8bad6a5685996c47f Mon Sep 17 00:00:00 2001 From: Lucky Goyal <74194341+LuckyGoyal039@users.noreply.github.com> Date: Mon, 8 Dec 2025 22:20:50 +0530 Subject: [PATCH] use micros converters in FormCurrencyFieldInput (#16330) Fixes: #15887 The currency fields were expecting values in micros (multiplied by 10^6), but this requirement was not indicated anywhere in the workflow UI. Users had to manually add a code node to multiply amounts by 10^6 before using the new currency value. This change integrates the micros conversion logic directly into FormCurrencyFieldInput by using convertCurrencyAmountToCurrencyMicros and convertCurrencyMicrosToCurrencyAmount utilities. This allows users to input human-readable decimal amounts (e.g., 3.21 for $3.21) in the form, which are automatically converted to micros internally for storage and processing. This eliminates the need for users to add separate code nodes for conversion and improves the user experience by making the expected input format clear. --- .../components/FormCurrencyFieldInput.tsx | 36 ++++++++++++++++--- .../FormCurrencyFieldInput.stories.tsx | 4 +-- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/packages/twenty-front/src/modules/object-record/record-field/ui/form-types/components/FormCurrencyFieldInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/ui/form-types/components/FormCurrencyFieldInput.tsx index c664184c10..12c619f47a 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/ui/form-types/components/FormCurrencyFieldInput.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/ui/form-types/components/FormCurrencyFieldInput.tsx @@ -9,6 +9,34 @@ import { InputLabel } from '@/ui/input/components/InputLabel'; import { useMemo } from 'react'; import { type CurrencyCode } from 'twenty-shared/constants'; import { IconCircleOff } from 'twenty-ui/display'; +import { + convertCurrencyAmountToCurrencyMicros, + convertCurrencyMicrosToCurrencyAmount, +} from '~/utils/convertCurrencyToCurrencyMicros'; + +const formatMicrosToDisplayAmount = ( + amountMicros: string | number | null | undefined, +): string | number => { + if (amountMicros == null) { + return ''; + } + if (Number.isFinite(+amountMicros)) { + return convertCurrencyMicrosToCurrencyAmount(+amountMicros); + } + return amountMicros; +}; + +const parseDisplayAmountToMicros = ( + displayAmount: string | number | null, +): number | null => { + if (displayAmount == null) { + return null; + } + if (Number.isFinite(+displayAmount)) { + return convertCurrencyAmountToCurrencyMicros(Number(displayAmount)); + } + return null; +}; type FormCurrencyFieldInputProps = { label?: string; @@ -41,7 +69,7 @@ export const FormCurrencyFieldInput = ({ ) => { onChange({ currencyCode: defaultValue?.currencyCode ?? null, - amountMicros: newAmountMicros ?? null, + amountMicros: parseDisplayAmountToMicros(newAmountMicros), }); }; @@ -65,11 +93,11 @@ export const FormCurrencyFieldInput = ({ readonly={readonly} /> diff --git a/packages/twenty-front/src/modules/object-record/record-field/ui/form-types/components/__stories__/FormCurrencyFieldInput.stories.tsx b/packages/twenty-front/src/modules/object-record/record-field/ui/form-types/components/__stories__/FormCurrencyFieldInput.stories.tsx index 89dcbed214..fab08b77d8 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/ui/form-types/components/__stories__/FormCurrencyFieldInput.stories.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/ui/form-types/components/__stories__/FormCurrencyFieldInput.stories.tsx @@ -32,7 +32,7 @@ export const Default: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); await canvas.findByText('Currency Code'); - await canvas.findByText('Amount Micros'); + await canvas.findByText('Amount'); }, }; @@ -81,7 +81,7 @@ export const Disabled: Story = { const currency = await canvas.findByText(/USD/); expect(currency).toBeVisible(); - const amountInput = await canvas.findByDisplayValue('44000000'); + const amountInput = await canvas.findByDisplayValue('44'); expect(amountInput).toBeVisible(); expect(amountInput).toBeDisabled();