Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UIU-2026 format currency values as currencies, not numbers #2611

Merged
merged 7 commits into from
Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* Refactor CSS away from `color()` function. Refs UIU-3013.
* Add `reminderFee` to loan action map. Fixes UIU-3014.
* Create new permission 'Users: Can view profile pictures'. Refs UIU-3018.
* Format currency values as currencies, not numbers. Refs UIU-2026.

## [10.0.4](https://github.com/folio-org/ui-users/tree/v10.0.4) (2023-11-10)
[Full Changelog](https://github.com/folio-org/ui-users/compare/v10.0.3...v10.0.4)
Expand Down
26 changes: 15 additions & 11 deletions src/components/Accounts/Actions/ActionModal.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import _ from 'lodash';
import React from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import { FormattedMessage, injectIntl } from 'react-intl';
import { Field } from 'react-final-form';
import setFieldData from 'final-form-set-field-data';

import { stripesConnect } from "@folio/stripes/core";
import stripesFinalForm from '@folio/stripes/final-form';
import {
Row,
Expand All @@ -28,6 +29,7 @@ import {
} from '../../../constants';

import css from './PayWaive.css';
import { localizeCurrencyAmount } from "../../util/localizeCurrencyAmount";

class ActionModal extends React.Component {
static propTypes = {
Expand Down Expand Up @@ -93,21 +95,22 @@ class ActionModal extends React.Component {
feeFineActions = [],
action,
form: { getState },
intl: { formatMessage },
intl,
stripes,
} = this.props;

const { values: { amount } } = getState();
const selected = calculateSelectedAmount(accounts, this.isRefundAction(action), feeFineActions);
const type = parseFloat(amount) < parseFloat(selected)
? formatMessage({ id: `ui-users.accounts.${action}.summary.partially` })
: formatMessage({ id: `ui-users.accounts.${action}.summary.fully` });
? intl.formatMessage({ id: `ui-users.accounts.${action}.summary.partially` })
: intl.formatMessage({ id: `ui-users.accounts.${action}.summary.fully` });

return (
<FormattedMessage
id="ui-users.accounts.summary"
values={{
count: accounts.length,
amount,
amount: localizeCurrencyAmount(amount || 0, stripes.currency, intl),
type,
}}
/>
Expand Down Expand Up @@ -325,7 +328,8 @@ class ActionModal extends React.Component {
owedAmount,
commentRequired,
form: { getState },
intl: { formatMessage },
intl,
stripes,
data,
handleSubmit,
label,
Expand Down Expand Up @@ -379,7 +383,7 @@ class ActionModal extends React.Component {
:
</Col>
<Col xs={4}>
{totalPaidAmount}
{localizeCurrencyAmount(totalPaidAmount, stripes.currency, intl)}
</Col>
</Row>
) : (
Expand All @@ -399,7 +403,7 @@ class ActionModal extends React.Component {
:
</Col>
<Col xs={4}>
{selected}
{localizeCurrencyAmount(selected, stripes.currency, intl)}
</Col>
</Row>
<Row end="xs">
Expand Down Expand Up @@ -431,7 +435,7 @@ class ActionModal extends React.Component {
:
</Col>
<Col xs={4}>
{ accountRemainingAmount || <NoValue /> }
{accountRemainingAmount ? localizeCurrencyAmount(accountRemainingAmount, stripes.currency, intl) : <NoValue />}
</Col>
</Row>
{ this.isRefundAction(action) && (
Expand Down Expand Up @@ -464,7 +468,7 @@ class ActionModal extends React.Component {
name="ownerId"
component={Select}
dataOptions={ownerOptions}
placeholder={formatMessage({ id: 'ui-users.accounts.payment.owner.placeholder' })}
placeholder={intl.formatMessage({ id: 'ui-users.accounts.payment.owner.placeholder' })}
onChange={this.onChangeOwner}
defaultValue={ownerId}
/>
Expand Down Expand Up @@ -563,4 +567,4 @@ export default stripesFinalForm({
navigationCheck: true,
subscription: { values: true },
mutators: { setFieldData },
})(ActionModal);
})(injectIntl(stripesConnect(ActionModal)));
14 changes: 10 additions & 4 deletions src/components/Accounts/Actions/CancellationModal.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import React from 'react';
import PropTypes from 'prop-types';
import { isEmpty } from 'lodash';
import { FormattedMessage } from 'react-intl';
import { FormattedMessage, injectIntl } from 'react-intl';
import { Field } from 'react-final-form';
import setFieldData from 'final-form-set-field-data';

import { stripesConnect } from "@folio/stripes/core";
import stripesFinalForm from '@folio/stripes/final-form';
import {
Modal,
Expand All @@ -16,6 +17,7 @@ import {
} from '@folio/stripes/components';

import css from './modal.css';
import { localizeCurrencyAmount } from "../../util/localizeCurrencyAmount";

class CancellationModal extends React.Component {
static propTypes = {
Expand All @@ -29,6 +31,8 @@ class CancellationModal extends React.Component {
handleSubmit: PropTypes.func.isRequired,
owners: PropTypes.arrayOf(PropTypes.object),
feefines: PropTypes.arrayOf(PropTypes.object),
intl: PropTypes.object.isRequired,
stripes: PropTypes.object.isRequired,
};

onCloseModal = () => {
Expand All @@ -46,7 +50,7 @@ class CancellationModal extends React.Component {
};

render() {
const defaultAmount = '0.00';
const defaultAmount = 0;
const defaultFeeFineType = 'fee/fine type';
const {
account,
Expand All @@ -60,6 +64,8 @@ class CancellationModal extends React.Component {
pristine,
submitting,
handleSubmit,
intl,
stripes,
form: { getState },
} = this.props;

Expand Down Expand Up @@ -95,7 +101,7 @@ class CancellationModal extends React.Component {
<FormattedMessage
id="ui-users.accounts.cancellation.feeFinewillBeCancelled"
values={{
amount: parseFloat(amount).toFixed(2),
amount: localizeCurrencyAmount(amount, stripes.currency, intl),
feeFineType
}}
/>
Expand Down Expand Up @@ -179,4 +185,4 @@ class CancellationModal extends React.Component {
export default stripesFinalForm({
subscription: { values: true },
mutators: { setFieldData }
})(CancellationModal);
})(injectIntl(stripesConnect(CancellationModal)));
22 changes: 12 additions & 10 deletions src/components/Accounts/Actions/FeeFineActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@ import {
SHARED_OWNER,
} from '../../../constants';
import {
formatCurrencyAmount,
getFullName,
isRefundAllowed,
} from '../../util';
import {
calculateSelectedAmount,
loadServicePoints,
} from '../accountFunctions';
import { localizeCurrencyAmount } from "../../util/localizeCurrencyAmount";

class Actions extends React.Component {
static manifest = Object.freeze({
Expand Down Expand Up @@ -244,17 +246,16 @@ class Actions extends React.Component {
}

showCalloutMessage({ amount }) {
const { user } = this.props;
const { user, stripes, intl } = this.props;
const paymentStatus = this.paymentStatus;
const formattedAmount = parseFloat(amount).toFixed(2);
const fullName = getFullName(user);

const message = (
<FormattedMessage
id="ui-users.accounts.actions.cancellation.success"
values={{
count: 1,
amount: formattedAmount,
amount: localizeCurrencyAmount(amount, stripes.currency, intl),
action: paymentStatus.toLowerCase(),
user: fullName
}}
Expand Down Expand Up @@ -303,8 +304,8 @@ class Actions extends React.Component {
accountId: id,
dateAction: moment().format(),
userId: this.props.user.id,
amountAction: parseFloat(amount || 0).toFixed(2),
balance: parseFloat(balance || 0).toFixed(2),
amountAction: formatCurrencyAmount(amount),
balance: formatCurrencyAmount(balance),
transactionInformation: transaction || '',
comments: comment,
notify,
Expand All @@ -318,7 +319,7 @@ class Actions extends React.Component {
const newAccount = {
status: { name: status },
paymentStatus: { name: paymentStatus },
remaining: parseFloat(remaining || 0).toFixed(2),
remaining: formatCurrencyAmount(remaining),
};

return this.props.mutator.accounts.PUT(Object.assign(account, newAccount));
Expand Down Expand Up @@ -614,8 +615,9 @@ class Actions extends React.Component {
stripes,
resources,
match: { params },
intl: { formatMessage },
intl,
} = this.props;
const { formatMessage } = intl;
const {
accounts,
showConfirmDialog,
Expand Down Expand Up @@ -753,15 +755,15 @@ class Actions extends React.Component {
form={m.form ? m.form : `${m.action}-modal`}
onClose={this.onCloseActionModal}
servicePointsIds={servicePointsIds}
balance={parseFloat(this.props.balance).toFixed(2)}
balance={localizeCurrencyAmount(this.props.balance, stripes.currency, intl)}
accounts={(m.accounts) ? m.accounts : ((m.item) ? this.props.accounts : accounts)}
onSubmit={(values) => { this.showConfirmDialog(values); }}
owners={owners}
feefines={feefines}
feeFineActions={feeFineActions}
okapi={this.props.okapi}
totalPaidAmount={parseFloat(this.props.totalPaidAmount).toFixed(2)}
owedAmount={parseFloat(this.props.owedAmount).toFixed(2)}
totalPaidAmount={localizeCurrencyAmount(this.props.totalPaidAmount, stripes.currency, intl)}
owedAmount={localizeCurrencyAmount(this.props.owedAmount, stripes.currency, intl)}
/>
);
}
Expand Down
7 changes: 4 additions & 3 deletions src/components/Accounts/Actions/FeeFineActions.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import '../../../../test/jest/__mock__';

import FeeFineActions from './FeeFineActions';
import CommentModal from './CommentModal';
import {formatCurrencyAmount} from "../../util";

jest.mock('./CancellationModal', () => jest.fn(() => null));
jest.mock('./CommentModal', () => jest.fn(() => null));
Expand Down Expand Up @@ -167,8 +168,8 @@ describe('FeeFineActions', () => {
createdAt: mockedCurServicePoint.id,
accountId: mockedAccount.id,
userId: mockedUser.id,
amountAction: parseFloat(0).toFixed(2),
balance: parseFloat(mockedAccount.remaining).toFixed(2),
amountAction: formatCurrencyAmount(0),
balance: formatCurrencyAmount(mockedAccount.remaining),
transactionInformation: '',
comments: `${labelIds.tagStaff} : ${mockedComment}`,
})));
Expand All @@ -178,7 +179,7 @@ describe('FeeFineActions', () => {
paymentStatus: {
name: mockedAccount.paymentStatus.name,
},
remaining: parseFloat(mockedAccount.remaining).toFixed(2),
remaining: formatCurrencyAmount(mockedAccount.remaining),
status: {
name: mockedAccount.status.name,
},
Expand Down
7 changes: 5 additions & 2 deletions src/components/Accounts/Actions/WarningModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
injectIntl,
} from 'react-intl';

import { stripesConnect } from "@folio/stripes/core";
import {
Button,
Col,
Expand All @@ -25,6 +26,7 @@ import {
} from '../../util';

import css from './modal.css';
import { localizeCurrencyAmount } from "../../util/localizeCurrencyAmount";

class WarningModal extends React.Component {
static propTypes = {
Expand Down Expand Up @@ -127,6 +129,7 @@ class WarningModal extends React.Component {
};

getAccountsFormatter() {
const { intl, stripes } = this.props;
const { checkedAccounts } = this.state;
return {
' ': a => (
Expand All @@ -138,7 +141,7 @@ class WarningModal extends React.Component {
),
'Alert details': this.getAlertDetailsFormatter,
'Fee/Fine type': a => a.feeFineType || '',
'Remaining': a => parseFloat(a.remaining).toFixed(2) || '0.00',
'Remaining': a => localizeCurrencyAmount(a.remaining, stripes.currency, intl),
'Payment Status': a => (a.paymentStatus || {}).name || '-',
'Item': a => a.title || '',
};
Expand Down Expand Up @@ -290,4 +293,4 @@ class WarningModal extends React.Component {
}
}

export default injectIntl(WarningModal);
export default injectIntl(stripesConnect(WarningModal));
12 changes: 6 additions & 6 deletions src/components/Accounts/ChargeFeeFine/ChargeFeeFine.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { effectiveCallNumber } from '@folio/stripes/util';
import ChargeForm from './ChargeForm';
import ItemLookup from './ItemLookup';
import ActionModal from '../Actions/ActionModal';
import { getFullName } from '../../util';
import { formatCurrencyAmount, getFullName } from '../../util';
import {
loadServicePoints,
deleteOptionalActionFields,
Expand Down Expand Up @@ -194,8 +194,8 @@ class ChargeFeeFine extends React.Component {
accountId: id,
dateAction,
userId: user.id,
amountAction: parseFloat(amount || 0).toFixed(2),
balance: parseFloat(balance || 0).toFixed(2),
amountAction: formatCurrencyAmount(amount),
balance: formatCurrencyAmount(balance),
transactionInformation: transaction || '',
comments: comment,
notify,
Expand Down Expand Up @@ -274,7 +274,7 @@ class ChargeFeeFine extends React.Component {
const {
intl: { formatNumber },
} = this.props;
const amount = parseFloat(a.amount).toFixed(2);
const amount = formatCurrencyAmount(a.amount);
const paymentName = (a.paymentStatus.name).toLowerCase();
const fullName = getFullName(this.props.user);
const { feeFineType } = a;
Expand Down Expand Up @@ -337,7 +337,7 @@ class ChargeFeeFine extends React.Component {
comment = `${comment} \n ${tagPatron} : ${values.patronInfo}`;
}

this.type.remaining = parseFloat(this.type.amount - values.amount).toFixed(2);
this.type.remaining = formatCurrencyAmount(this.type.amount - values.amount);
let paymentStatus = _.capitalize(formatMessage({ id: 'ui-users.accounts.actions.warning.paymentAction' }));

if (this.type.remaining === '0.00') {
Expand Down Expand Up @@ -382,7 +382,7 @@ class ChargeFeeFine extends React.Component {
const { intl: { formatMessage } } = this.props;
const values = this.state.values || {};
const type = this.type || {};
const amount = parseFloat(values.amount || 0).toFixed(2);
const amount = formatCurrencyAmount(values.amount);
let paymentStatus = formatMessage({ id: 'ui-users.accounts.actions.warning.paymentAction' });
paymentStatus = `${(parseFloat(values.amount) !== parseFloat(type.amount)
? formatMessage({ id: 'ui-users.accounts.status.partially' })
Expand Down
3 changes: 2 additions & 1 deletion src/components/Accounts/ChargeFeeFine/ChargeForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import UserInfo from './UserInfo';
import FeeFineInfo from './FeeFineInfo';
import ItemInfo from './ItemInfo';
import { SHARED_OWNER } from '../../../constants';
import {formatCurrencyAmount} from "../../util";

function showValidationErrors({ feeFineId, ownerId, amount }) {
const errors = {};
Expand Down Expand Up @@ -109,7 +110,7 @@ class ChargeForm extends React.Component {
const feefine = feefines.find(f => f.id === feeFineId) || {};
const owner = this.props.owners.find(o => o.id === feefine.ownerId) || {};

const defaultAmount = parseFloat(feefine.defaultAmount || 0).toFixed(2);
const defaultAmount = formatCurrencyAmount(feefine.defaultAmount);
let showNotify = false;
if (feefine?.chargeNoticeId || owner?.defaultChargeNoticeId) {
showNotify = true;
Expand Down
Loading
Loading