Skip to content

Commit

Permalink
Return appropriate error message when item for manual fee/fine can't …
Browse files Browse the repository at this point in the history
…be found
  • Loading branch information
artem-blazhko committed Jan 17, 2025
1 parent 14cc4b8 commit 2775e92
Show file tree
Hide file tree
Showing 5 changed files with 178 additions and 28 deletions.
46 changes: 32 additions & 14 deletions src/components/Accounts/ChargeFeeFine/ChargeFeeFine.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ import {
loadServicePoints,
deleteOptionalActionFields,
} from '../accountFunctions';
import { SHARED_OWNER } from '../../../constants';
import {
SHARED_OWNER,
NEW_FEE_FINE_FIELD_NAMES,
} from '../../../constants';

class ChargeFeeFine extends React.Component {
static propTypes = {
Expand Down Expand Up @@ -72,6 +75,7 @@ class ChargeFeeFine extends React.Component {
showConfirmDialog: false,
notify: null,
paymentNotify: null,
itemBarcode: '',
};
this.chargeAction = this.chargeAction.bind(this);
this.payAction = this.payAction.bind(this);
Expand Down Expand Up @@ -232,7 +236,10 @@ class ChargeFeeFine extends React.Component {

onClickSelectItem(barcode) {
if (barcode !== '') {
this.props.mutator.activeRecord.update({ barcode });
this.props.mutator.activeRecord.update({
barcode,
isBarcodeValidated: true,
});
if ((this.props.resources.activeRecord || {}).barcode === barcode) {
this.setState({
lookup: true,
Expand All @@ -241,7 +248,7 @@ class ChargeFeeFine extends React.Component {
}
}

onChangeOwner(ownerId) {
onChangeOwner(ownerId, itemBarcode = '') {
const {
resources,
mutator,
Expand All @@ -253,7 +260,11 @@ class ChargeFeeFine extends React.Component {
mutator.activeRecord.update({ shared });
}
mutator.activeRecord.update({ ownerId });
this.setState({ ownerId });

this.setState({
ownerId,
itemBarcode,
});
}

onChangeItem(item) {
Expand Down Expand Up @@ -396,18 +407,23 @@ class ChargeFeeFine extends React.Component {
}

onSubmitCharge = (data) => {
if (data.pay) {
delete data.pay;
this.type.remaining = data.amount;
const dataToSend = _.cloneDeep(data);

_.unset(dataToSend, NEW_FEE_FINE_FIELD_NAMES.ITEM_BARCODE);
_.unset(dataToSend, NEW_FEE_FINE_FIELD_NAMES.KEY_OF_ITEM_BARCODE);

if (dataToSend.pay) {
delete dataToSend.pay;
this.type.remaining = dataToSend.amount;

return this.chargeAction(data)
.then(() => this.payAction(data))
return this.chargeAction(dataToSend)
.then(() => this.payAction(dataToSend))
.then(() => this.goBack());
} else {
delete data.pay;
delete dataToSend.pay;

return this.chargeAction(data)
.then(() => this.showCalloutMessage(data))
return this.chargeAction(dataToSend)
.then(() => this.showCalloutMessage(dataToSend))
.then(() => this.goBack());
}
}
Expand All @@ -433,6 +449,7 @@ class ChargeFeeFine extends React.Component {
ownerId,
feeFineTypeId,
pay,
itemBarcode,
} = this.state;
this.item = _.get(resources, ['items', 'records', [0]], {});
const feefines = _.get(resources, ['allfeefines', 'records'], []);
Expand Down Expand Up @@ -461,7 +478,7 @@ class ChargeFeeFine extends React.Component {
parseFloat(selected).toFixed(2);
let item;

if (this.item && (loanid || barcode)) {
if (this.item && (loanid || barcode || !resources.activeRecord?.isBarcodeValidated)) {
item = {
id: this.item.id || '',
instance: this.item.title || '',
Expand Down Expand Up @@ -490,7 +507,8 @@ class ChargeFeeFine extends React.Component {
ownerId: initialOwnerId,
notify: !!(selectedFeeFine?.chargeNoticeId || selectedOwner?.defaultChargeNoticeId),
feeFineId: '',
amount: ''
amount: '',
itemBarcode,
};

const initialActionValues = {
Expand Down
18 changes: 15 additions & 3 deletions src/components/Accounts/ChargeFeeFine/ChargeForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ import { effectiveCallNumber } from '@folio/stripes/util';
import UserInfo from './UserInfo';
import FeeFineInfo from './FeeFineInfo';
import ItemInfo from './ItemInfo';
import { SHARED_OWNER } from '../../../constants';
import {
SHARED_OWNER,
NEW_FEE_FINE_FIELD_NAMES,
} from '../../../constants';
import { formatCurrencyAmount } from '../../util';

function showValidationErrors({ feeFineId, ownerId, amount }) {
Expand Down Expand Up @@ -62,6 +65,7 @@ class ChargeForm extends React.Component {
handleSubmit: PropTypes.func.isRequired,
onClickSelectItem: PropTypes.func.isRequired,
onFindShared: PropTypes.func.isRequired,
values: PropTypes.object.isRequired,
pristine: PropTypes.bool,
submitting: PropTypes.bool,
invalid: PropTypes.bool,
Expand Down Expand Up @@ -122,9 +126,17 @@ class ChargeForm extends React.Component {
}

onChangeOwner(ownerId) {
const { form: { change, reset } } = this.props;
const {
form: {
change,
reset,
},
values,
onChangeOwner,
} = this.props;

reset();
this.props.onChangeOwner(ownerId);
onChangeOwner(ownerId, values[NEW_FEE_FINE_FIELD_NAMES.ITEM_BARCODE]);
let showNotify = false;
const owner = this.props.owners.find(o => o.id === ownerId) || {};
if (owner?.defaultChargeNoticeId) {
Expand Down
136 changes: 125 additions & 11 deletions src/components/Accounts/ChargeFeeFine/ItemInfo.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
import React from 'react';
import { Field } from 'react-final-form';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
import { FormattedMessage } from 'react-intl';

import {
Button,
Row,
Col,
TextField,
} from '@folio/stripes/components';

import { NEW_FEE_FINE_FIELD_NAMES } from '../../../constants';

class ItemInfo extends React.Component {
static propTypes = {
resources: PropTypes.shape({
items: PropTypes.shape({
records: PropTypes.arrayOf(PropTypes.object),
}),
}).isRequired,
form: PropTypes.object.isRequired,
onClickSelectItem: PropTypes.func,
item: PropTypes.object,
editable: PropTypes.bool,
Expand All @@ -25,6 +35,29 @@ class ItemInfo extends React.Component {
this.onClickSelectItem = this.onClickSelectItem.bind(this);
this.onChangeSelectItem = this.onChangeSelectItem.bind(this);
this.query = '';
this.state = {
isBarcodeChangedAfterValidation: false,
};
}

componentDidUpdate(prevProps) {
const {
resources: {
items,
},
} = this.props;
const {
resources: {
items: prevItems,
},
} = prevProps;

if (prevItems.records !== items.records && this.state.isBarcodeChangedAfterValidation) {
this.triggerItemBarcodeValidation();
this.setState({
isBarcodeChangedAfterValidation: false,
});
}
}

onClickSelectItem(e) {
Expand All @@ -33,10 +66,61 @@ class ItemInfo extends React.Component {
}

onChangeSelectItem(e) {
if (e) e.preventDefault();
this.query = e.target.value;
const value = e.target.value;
const {
form,
resources,
} = this.props;
const {
isBarcodeChangedAfterValidation,
} = this.state;

if (e) {
e.preventDefault();
}

if (resources.activeRecord?.barcode && resources.activeRecord?.barcode !== value) {

Check failure on line 82 in src/components/Accounts/ChargeFeeFine/ItemInfo.js

View workflow job for this annotation

GitHub Actions / build-npm

'resources.activeRecord' is missing in props validation

Check failure on line 82 in src/components/Accounts/ChargeFeeFine/ItemInfo.js

View workflow job for this annotation

GitHub Actions / build-npm

'resources.activeRecord.barcode' is missing in props validation

Check failure on line 82 in src/components/Accounts/ChargeFeeFine/ItemInfo.js

View workflow job for this annotation

GitHub Actions / build-npm

'resources.activeRecord' is missing in props validation

Check failure on line 82 in src/components/Accounts/ChargeFeeFine/ItemInfo.js

View workflow job for this annotation

GitHub Actions / build-npm

'resources.activeRecord.barcode' is missing in props validation
this.props.mutator.activeRecord.replace({

Check failure on line 83 in src/components/Accounts/ChargeFeeFine/ItemInfo.js

View workflow job for this annotation

GitHub Actions / build-npm

'mutator' is missing in props validation

Check failure on line 83 in src/components/Accounts/ChargeFeeFine/ItemInfo.js

View workflow job for this annotation

GitHub Actions / build-npm

'mutator.activeRecord' is missing in props validation

Check failure on line 83 in src/components/Accounts/ChargeFeeFine/ItemInfo.js

View workflow job for this annotation

GitHub Actions / build-npm

'mutator.activeRecord.replace' is missing in props validation
...resources.activeRecord,

Check failure on line 84 in src/components/Accounts/ChargeFeeFine/ItemInfo.js

View workflow job for this annotation

GitHub Actions / build-npm

'resources.activeRecord' is missing in props validation
isBarcodeValidated: false,
barcode: '',
});
}

if (!isBarcodeChangedAfterValidation) {
this.setState({
isBarcodeChangedAfterValidation: true,
});
}

form.change(NEW_FEE_FINE_FIELD_NAMES.ITEM_BARCODE, value);
this.query = value;
}

triggerItemBarcodeValidation = () => {
const {
form,
values,

Check failure on line 103 in src/components/Accounts/ChargeFeeFine/ItemInfo.js

View workflow job for this annotation

GitHub Actions / build-npm

'values' is missing in props validation
} = this.props;

form.change(NEW_FEE_FINE_FIELD_NAMES.KEY_OF_ITEM_BARCODE, values[NEW_FEE_FINE_FIELD_NAMES.KEY_OF_ITEM_BARCODE] ? 0 : 1);
};

validateBarcode = (barcode) => {
const {
resources: {
items,
activeRecord,

Check failure on line 113 in src/components/Accounts/ChargeFeeFine/ItemInfo.js

View workflow job for this annotation

GitHub Actions / build-npm

'resources.activeRecord' is missing in props validation
},
} = this.props;

if (barcode && barcode === activeRecord.barcode && items.records.length === 0) {
return <FormattedMessage id="ui-users.charge.item.barcode.error" />;
}

return undefined;
};

render() {
const {
item: {
Expand All @@ -46,8 +130,17 @@ class ItemInfo extends React.Component {
instance,
barcode,
id,
}
},
values,
editable,
resources: {
items,
},
} = this.props;
const {
isBarcodeChangedAfterValidation,
} = this.state;
const isEnterButtonDisabled = !editable || items.isPending;

return (
<div>
Expand All @@ -57,20 +150,41 @@ class ItemInfo extends React.Component {
<Row>
<Col xs={8}>
<FormattedMessage id="ui-users.charge.item.placeholder">
{placeholder => (
<TextField
placeholder={placeholder}
disabled={!this.props.editable}
onChange={this.onChangeSelectItem}
/>
)}
{placeholder => {
const key = values[NEW_FEE_FINE_FIELD_NAMES.KEY_OF_ITEM_BARCODE] ?? 0;

return (
<Field
name={NEW_FEE_FINE_FIELD_NAMES.ITEM_BARCODE}
key={key}
validate={this.validateBarcode}
validateFields={[]}
>
{
({input, meta}) => {
const validationError = !isBarcodeChangedAfterValidation && meta.error;

return (
<TextField
{...input}
placeholder={placeholder}
disabled={!editable}
onChange={this.onChangeSelectItem}
error={validationError}
/>
);
}
}
</Field>
);
}}
</FormattedMessage>
</Col>
<Col xs={2}>
<Button
buttonStyle="primary"
onClick={this.onClickSelectItem}
disabled={!this.props.editable}
disabled={isEnterButtonDisabled}
>
<FormattedMessage id="ui-users.charge.item.button" />
</Button>
Expand Down
5 changes: 5 additions & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -401,3 +401,8 @@ export const KEYCLOAK_USER_EXISTANCE = {
nonExist: 'nonExist',
error: 'error',
};

export const NEW_FEE_FINE_FIELD_NAMES = {
ITEM_BARCODE: 'itemBarcode',
KEY_OF_ITEM_BARCODE: 'keyOfItemBarcode',
};
1 change: 1 addition & 0 deletions translations/ui-users/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,7 @@
"charge.item.placeholder": "Scan or enter item barcode",
"charge.item.button": "Enter",
"charge.item.barcode": "Barcode",
"charge.item.barcode.error": "Item with this barcode does not exist",
"charge.item.instance": "Instance",
"charge.item.status": "Item Status",
"charge.item.callNumber": "Effective call number string",
Expand Down

0 comments on commit 2775e92

Please sign in to comment.