diff --git a/client/src/containers/Accounts/utils.js b/client/src/containers/Accounts/utils.js index 8411ee3ba..38f8cdeea 100644 --- a/client/src/containers/Accounts/utils.js +++ b/client/src/containers/Accounts/utils.js @@ -4,10 +4,10 @@ import { If } from 'components'; export const accountNameAccessor = (account) => { return ( - - { account.name } + {account.name} + + {account.description} - { account.description } ); -} \ No newline at end of file +}; diff --git a/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/DecrementAdjustmentFields.js b/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/DecrementAdjustmentFields.js index 4e1820f83..ecf61e359 100644 --- a/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/DecrementAdjustmentFields.js +++ b/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/DecrementAdjustmentFields.js @@ -1,16 +1,17 @@ -import React, { useRef } from 'react'; -import { FastField, ErrorMessage, useFormikContext } from 'formik'; -import { FormGroup, InputGroup, Intent } from '@blueprintjs/core'; +import React from 'react'; +import { Field, ErrorMessage, FastField } from 'formik'; +import { FormGroup, InputGroup } from '@blueprintjs/core'; import { inputIntent } from 'utils'; -import { Row, Col, If, FieldRequiredHint } from 'components'; +import { Row, Col, MoneyInputGroup } from 'components'; import { FormattedMessage as T } from 'react-intl'; -import { decrementCalc, dec } from './utils'; +import { decrementQuantity } from './utils'; +import { toSafeNumber } from 'utils'; function DecrementAdjustmentFields() { return ( - + {/*------------ Quantity on hand -----------*/} - + {({ field, meta: { error, touched } }) => ( + + + + + {/*------------ Decrement -----------*/} - - + + {({ form: { values, setFieldValue }, field, @@ -37,19 +43,34 @@ function DecrementAdjustmentFields() { helperText={} fill={true} > - { - setFieldValue('new_quantity', decrementCalc(values, event)); + { + setFieldValue('quantity', value); + }} + onBlurValue={(value) => { + setFieldValue( + 'new_quantity', + decrementQuantity( + toSafeNumber(value), + toSafeNumber(values.quantity_on_hand), + ), + ); }} /> )} - + + + + + = {/*------------ New quantity -----------*/} - - + + {({ form: { values, setFieldValue }, field, @@ -60,15 +81,26 @@ function DecrementAdjustmentFields() { intent={inputIntent({ error, touched })} helperText={} > - { - setFieldValue('quantity', decrementCalc(values, event)); + { + setFieldValue('new_quantity', value); + }} + onBlurValue={(value) => { + setFieldValue( + 'quantity', + decrementQuantity( + toSafeNumber(value), + toSafeNumber(values.quantity_on_hand), + ), + ); }} /> )} - + ); diff --git a/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/IncrementAdjustmentFields.js b/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/IncrementAdjustmentFields.js index 286bea519..b352c9155 100644 --- a/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/IncrementAdjustmentFields.js +++ b/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/IncrementAdjustmentFields.js @@ -1,16 +1,16 @@ import React from 'react'; -import { FastField, ErrorMessage, useFormikContext } from 'formik'; -import { FormGroup, InputGroup, Intent } from '@blueprintjs/core'; -import { Row, Col, FieldRequiredHint } from 'components'; -import { inputIntent } from 'utils'; +import { Field, FastField, ErrorMessage } from 'formik'; +import { FormGroup, InputGroup } from '@blueprintjs/core'; +import { Row, Col, MoneyInputGroup } from 'components'; +import { inputIntent, toSafeNumber } from 'utils'; import { FormattedMessage as T } from 'react-intl'; -import { decrementCalc, incrementCalc } from './utils'; +import { decrementQuantity, incrementQuantity } from './utils'; function IncrementAdjustmentFields() { return ( {/*------------ Quantity on hand -----------*/} - + {({ field, meta: { error, touched } }) => ( + + {/*------------ Sign -----------*/} + + + + + {/*------------ Increment -----------*/} - - + + {({ form: { values, setFieldValue }, field, @@ -37,33 +43,60 @@ function IncrementAdjustmentFields() { helperText={} fill={true} > - { - setFieldValue('new_quantity', incrementCalc(values, event)); + { + setFieldValue('quantity', value); + }} + onBlurValue={(value) => { + setFieldValue( + 'new_quantity', + incrementQuantity( + toSafeNumber(value), + toSafeNumber(values.quantity_on_hand), + ), + ); + }} + /> + + )} + + + + {/*------------ Cost -----------*/} + + + {({ + form: { setFieldValue }, + field: { value }, + meta: { error, touched }, + }) => ( + } + intent={inputIntent({ error, touched })} + helperText={} + > + { + setFieldValue('cost', value); }} /> )} - {/*------------ Cost -----------*/} - - - {({ field, meta: { error, touched } }) => ( - } - intent={inputIntent({ error, touched })} - helperText={} - > - - - )} - + + {/*------------ Sign -----------*/} + + = + {/*------------ New quantity -----------*/} - - + + {({ form: { values, setFieldValue }, field, @@ -74,15 +107,26 @@ function IncrementAdjustmentFields() { intent={inputIntent({ error, touched })} helperText={} > - { - setFieldValue('quantity', decrementCalc(values, event)); + { + setFieldValue('new_quantity', value); + }} + onBlurValue={(value) => { + setFieldValue( + 'quantity', + decrementQuantity( + toSafeNumber(value), + toSafeNumber(values.quantity_on_hand), + ), + ); }} /> )} - + ); diff --git a/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/InventoryAdjustmentForm.schema.js b/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/InventoryAdjustmentForm.schema.js index 25fe6c687..41a1af3a1 100644 --- a/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/InventoryAdjustmentForm.schema.js +++ b/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/InventoryAdjustmentForm.schema.js @@ -11,19 +11,19 @@ const Schema = Yup.object().shape({ item_id: Yup.number().required(), reason: Yup.string() .required() + .min(3) + .max(DATATYPES_LENGTH.TEXT) .label(formatMessage({ id: 'reason' })), quantity_on_hand: Yup.number() - .min(0) .required() .label(formatMessage({ id: 'qty' })), - quantity: Yup.number().integer().max(Yup.ref('quantity_on_hand')).required(), + quantity: Yup.number().integer().min(1).required(), cost: Yup.number().when(['type'], { - is: (type) => type, - then: Yup.number(), + is: (type) => type === 'increment', + then: Yup.number().required(), }), reference_no: Yup.string(), - new_quantity: Yup.number().min(Yup.ref('quantity')).required(), - description: Yup.string().min(3).max(DATATYPES_LENGTH.TEXT).nullable().trim(), + new_quantity: Yup.number().required(), publish: Yup.boolean(), }); diff --git a/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/InventoryAdjustmentFormDialogContent.js b/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/InventoryAdjustmentFormDialogContent.js index c66401cfb..c2017709d 100644 --- a/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/InventoryAdjustmentFormDialogContent.js +++ b/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/InventoryAdjustmentFormDialogContent.js @@ -1,17 +1,26 @@ -import React, { useState, useCallback, useMemo } from 'react'; +import React, { useState, useCallback } from 'react'; import { Intent } from '@blueprintjs/core'; import { Formik, Form } from 'formik'; -import { FormattedMessage as T, useIntl } from 'react-intl'; +import { useIntl } from 'react-intl'; import { useQuery, queryCache } from 'react-query'; import moment from 'moment'; -import { omit } from 'lodash'; +import { omit, get } from 'lodash'; + +import 'style/pages/Items/ItemAdjustmentDialog.scss'; import { AppToaster, DialogContent } from 'components'; + import { CreateInventoryAdjustmentFormSchema } from './InventoryAdjustmentForm.schema'; + import InventoryAdjustmentFormDialogFields from './InventoryAdjustmentFormDialogFields'; import InventoryAdjustmentFloatingActions from './InventoryAdjustmentFloatingActions'; + import withDialogActions from 'containers/Dialog/withDialogActions'; import withInventoryAdjustmentActions from 'containers/Items/withInventoryAdjustmentActions'; +import withAccountsActions from 'containers/Accounts/withAccountsActions'; +import withItem from 'containers/Items/withItem'; +import withItemsActions from 'containers/Items/withItemsActions'; + import { compose } from 'utils'; const defaultInitialValues = { @@ -24,7 +33,6 @@ const defaultInitialValues = { quantity: '', reference_no: '', quantity_on_hand: '', - description: '', publish: '', }; @@ -41,8 +49,14 @@ function InventoryAdjustmentFormDialogContent({ // #withInventoryAdjustmentActions requestSubmitInventoryAdjustment, + // #withItemsActions + requestFetchItem, + + // #withItem + item, + // #ownProp - itemDetail, + itemId, dialogName, }) { const { formatMessage } = useIntl(); @@ -51,13 +65,16 @@ function InventoryAdjustmentFormDialogContent({ // Fetches accounts list. const fetchAccount = useQuery('accounts-list', () => requestFetchAccounts()); - const initialValues = useMemo( - () => ({ - ...defaultInitialValues, - ...itemDetail, - }), - [], - ); + // Fetches the item details. + const fetchItem = useQuery(['item', itemId], + (key, id) => requestFetchItem(id)); + + // Initial form values. + const initialValues = { + ...defaultInitialValues, + item_id: itemId, + quantity_on_hand: get(item, 'quantity_on_hand', 0), + }; // Handles the form submit. const handleFormSubmit = (values, { setSubmitting, setErrors }) => { @@ -65,7 +82,6 @@ function InventoryAdjustmentFormDialogContent({ ...omit(values, ['quantity_on_hand', 'new_quantity', 'action']), publish: submitPayload.publish, }; - const onSuccess = ({ response }) => { closeDialog(dialogName); queryCache.invalidateQueries('accounts-list'); @@ -88,7 +104,7 @@ function InventoryAdjustmentFormDialogContent({ const handleCloseClick = useCallback(() => { closeDialog(dialogName); }, [closeDialog, dialogName]); - + const handleSubmitClick = useCallback( (event, payload) => { setSubmitPayload({ ...payload }); @@ -97,7 +113,7 @@ function InventoryAdjustmentFormDialogContent({ ); return ( - + ({ + item: item + })), + withItemsActions, )(InventoryAdjustmentFormDialogContent); diff --git a/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/InventoryAdjustmentFormDialogFields.js b/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/InventoryAdjustmentFormDialogFields.js index c950dc918..9623384bb 100644 --- a/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/InventoryAdjustmentFormDialogFields.js +++ b/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/InventoryAdjustmentFormDialogFields.js @@ -1,5 +1,5 @@ import React from 'react'; -import { FastField, ErrorMessage, useFormikContext } from 'formik'; +import { FastField, ErrorMessage, Field, useFormikContext } from 'formik'; import { Classes, FormGroup, @@ -10,21 +10,22 @@ import { import classNames from 'classnames'; import { FormattedMessage as T, useIntl } from 'react-intl'; import { DateInput } from '@blueprintjs/datetime'; -import { ListSelect, Choose, If, FieldRequiredHint } from 'components'; +import { compose } from 'redux'; +import { ListSelect, FieldRequiredHint, Col, Row } from 'components'; import { inputIntent, momentFormatter, tansformDateValue, handleDateChange, + toSafeNumber } from 'utils'; import { CLASSES } from 'common/classes'; import adjustmentType from 'common/adjustmentType'; -import IncrementAdjustmentFields from './IncrementAdjustmentFields'; -import DecrementAdjustmentFields from './DecrementAdjustmentFields'; + import AccountsSuggestField from 'components/AccountsSuggestField'; import withAccounts from 'containers/Accounts/withAccounts'; -import { compose } from 'redux'; -import { decrementCalc, incrementCalc, dec } from './utils'; +import { diffQuantity } from './utils'; +import InventoryAdjustmentQuantityFields from './InventoryAdjustmentQuantityFields'; /** * Inventory adjustment form dialogs fields. @@ -38,83 +39,71 @@ function InventoryAdjustmentFormDialogFields({ return (
- {/*------------ Date -----------*/} - - {({ form, field: { value }, meta: { error, touched } }) => ( - } - labelInfo={} - intent={inputIntent({ error, touched })} - helperText={} - minimal={true} - className={classNames(CLASSES.FILL)} - > - { - form.setFieldValue('date', formattedDate); - })} - value={tansformDateValue(value)} - popoverProps={{ - position: Position.BOTTOM, - minimal: true, - }} - /> - - )} - + + + {/*------------ Date -----------*/} + + {({ form, field: { value }, meta: { error, touched } }) => ( + } + labelInfo={} + intent={inputIntent({ error, touched })} + helperText={} + minimal={true} + className={classNames(CLASSES.FILL, 'form-group--date')} + > + { + form.setFieldValue('date', formattedDate); + })} + value={tansformDateValue(value)} + popoverProps={{ + position: Position.BOTTOM, + minimal: true, + }} + /> + + )} + + - {/*------------ Adjustment type -----------*/} - - {({ form, field: { value }, meta: { error, touched } }) => ( - } - labelInfo={} - helperText={} - intent={inputIntent({ error, touched })} - className={classNames(CLASSES.FILL)} - > - { - form.setFieldValue('type', type.value); - type?.value == 'increment' - ? form.setFieldValue('new_quantity', incrementCalc(values)) - : form.setFieldValue( - 'new_quantity', - values.quantity_on_hand - values.quantity, + + {/*------------ Adjustment type -----------*/} + + {({ form: { values, setFieldValue }, field: { value }, meta: { error, touched } }) => ( + } + labelInfo={} + helperText={} + intent={inputIntent({ error, touched })} + className={classNames(CLASSES.FILL, 'form-group--type')} + > + { + const result = diffQuantity( + toSafeNumber(values.quantity), + toSafeNumber(values.quantity_on_hand), + type.value ); - }} - filterable={false} - selectedItem={value} - selectedItemProp={'value'} - textProp={'name'} - popoverProps={{ minimal: true }} - /> - - )} - - - - - - - - - - {/*------------ Reason -----------*/} - - {({ form, field, meta: { error, touched } }) => ( - } - labelInfo={} - intent={inputIntent({ error, touched })} - helperText={} - > - - - )} - + setFieldValue('type', type.value); + setFieldValue('new_quantity', result); + }} + filterable={false} + selectedItem={value} + selectedItemProp={'value'} + textProp={'name'} + popoverProps={{ minimal: true }} + /> + + )} + + + + + + {/*------------ Adjustment account -----------*/} {({ form, field, meta: { error, touched } }) => ( @@ -123,6 +112,7 @@ function InventoryAdjustmentFormDialogFields({ labelInfo={} intent={inputIntent({ error, touched })} helperText={} + className={'form-group--adjustment-account'} > )} + {/*------------ Reference -----------*/} {({ form, field, meta: { error, touched } }) => ( } - className={classNames(CLASSES.FILL)} intent={inputIntent({ error, touched })} helperText={} + className={'form-group--reference-no'} > )} + {/*------------ description -----------*/} - + {({ field, meta: { error, touched } }) => ( } - className={'form-group--description'} + label={} + className={'form-group--adjustment-reasons'} intent={inputIntent({ error, touched })} - helperText={} + helperText={} >