diff --git a/client/src/common/numberFormatsOptions.js b/client/src/common/numberFormatsOptions.js new file mode 100644 index 000000000..d39845288 --- /dev/null +++ b/client/src/common/numberFormatsOptions.js @@ -0,0 +1,18 @@ +export const moneyFormat = [ + { id: 'total', text: 'Total rows' }, + { id: 'always', text: 'Always' }, + { id: 'none', text: 'None' }, +]; + +export const negativeFormat = [ + { id: 'parentheses', text: 'Parentheses ($1000)' }, + { id: 'mines', text: 'Minus -$1000' }, +]; + +export const decimalPlaces = [ + { text: '1 Decimals', label: '$0.1', id: 1 }, + { text: '2 Decimals', label: '$0.01', id: 2 }, + { text: '3 Decimals', label: '$0.001', id: 3 }, + { text: '4 Decimals', label: '$0.0001', id: 4 }, + { text: '5 Decimals', label: '$0.00001', id: 5 }, +]; diff --git a/client/src/components/AccountsTypesSelect.js b/client/src/components/AccountsTypesSelect.js index 1803f49f6..69782bab7 100644 --- a/client/src/components/AccountsTypesSelect.js +++ b/client/src/components/AccountsTypesSelect.js @@ -39,7 +39,7 @@ export default function AccountsTypesSelect({ items={items} selectedItemProp={'id'} selectedItem={selectedTypeId} - labelProp={'label'} + textProp={'label'} defaultText={defaultSelectText} onItemSelect={handleItemSelected} itemPredicate={filterAccountTypeItems} diff --git a/client/src/components/CategoriesSelectList.js b/client/src/components/CategoriesSelectList.js index 541c2d813..52bf07a14 100644 --- a/client/src/components/CategoriesSelectList.js +++ b/client/src/components/CategoriesSelectList.js @@ -44,7 +44,7 @@ export default function CategoriesSelectList({ items={categoriesList} selectedItemProp={'id'} selectedItem={selecetedCategoryId} - labelProp={'name'} + textProp={'name'} defaultText={defaultSelectText} onItemSelect={handleItemCategorySelected} itemPredicate={filterItemCategory} diff --git a/client/src/components/DisplayNameList.js b/client/src/components/DisplayNameList.js index eb0cb28b3..cb09cb4ac 100644 --- a/client/src/components/DisplayNameList.js +++ b/client/src/components/DisplayNameList.js @@ -34,7 +34,7 @@ export default function DisplayNameList({ ); diff --git a/client/src/components/ListSelect.js b/client/src/components/ListSelect.js index c0aedf686..ebbfb5479 100644 --- a/client/src/components/ListSelect.js +++ b/client/src/components/ListSelect.js @@ -10,6 +10,7 @@ export default function ListSelect({ defaultText, noResultsText = , isLoading = false, + textProp, labelProp, selectedItem, @@ -52,8 +53,9 @@ export default function ListSelect({ const itemRenderer = (item, { handleClick, modifiers, query }) => { return ( ); @@ -77,7 +79,7 @@ export default function ListSelect({ )} > + + {/*------------ Money formats -----------*/} + + {({ form, field: { value }, meta: { error, touched } }) => ( + } + helperText={} + intent={inputIntent({ error, touched })} + className={classNames(CLASSES.FILL)} + > + { + form.setFieldValue('format_money', format.name); + }} + filterable={false} + selectedItem={value} + selectedItemProp={'id'} + textProp={'text'} + popoverProps={{ minimal: true, captureDismiss: true }} + /> + + )} + + {/*------------ Negative formats -----------*/} + + {({ form, field: { value }, meta: { error, touched } }) => ( + } + helperText={} + intent={inputIntent({ error, touched })} + className={classNames(CLASSES.FILL)} + > + { + form.setFieldValue('negative_format', format.name); + }} + filterable={false} + selectedItem={value} + selectedItemProp={'id'} + textProp={'text'} + popoverProps={{ minimal: true, captureDismiss: true }} + /> + + )} + + + {/*------------ Decimal places -----------*/} + + {({ form, field: { value }, meta: { error, touched } }) => ( + } + helperText={} + intent={inputIntent({ error, touched })} + className={classNames(CLASSES.FILL)} + > + { + form.setFieldValue('precision', format.key); + }} + filterable={false} + selectedItem={value} + selectedItemProp={'id'} + labelProp={'label'} + textProp={'text'} + popoverProps={{ minimal: true, captureDismiss: true }} + /> + + )} + + + {/*------------ show zero -----------*/} + + {({ field }) => ( + + } + name={'show_zero'} + {...field} + /> + + )} + + {/*------------ show negative in red-----------*/} + + {({ field }) => ( + + } + name={'show_in_red'} + {...field} + /> + + )} + + {/*------------ Divide on 1000 -----------*/} + + {({ field }) => ( + + } + name={'divide_on_1000'} + {...field} + /> + + )} + + + + + + + + + + + + + ); +} diff --git a/client/src/components/NumberFormats/NumberFormats.schema.js b/client/src/components/NumberFormats/NumberFormats.schema.js new file mode 100644 index 000000000..4b67fa97b --- /dev/null +++ b/client/src/components/NumberFormats/NumberFormats.schema.js @@ -0,0 +1,15 @@ +import * as Yup from 'yup'; +import { DATATYPES_LENGTH } from 'common/dataTypes'; +import { defaultTo } from 'lodash'; + + +const Schema = Yup.object().shape({ + format_money: Yup.string(), + show_zero: Yup.boolean(), + show_in_red: Yup.boolean(), + divide_on_1000: Yup.boolean(), + negative_format: Yup.string(), + precision: Yup.string(), +}); + +export const CreateNumberFormateSchema = Schema; diff --git a/client/src/components/NumberFormats/index.js b/client/src/components/NumberFormats/index.js new file mode 100644 index 000000000..1d1a5a87a --- /dev/null +++ b/client/src/components/NumberFormats/index.js @@ -0,0 +1,42 @@ +import React, { useState, useCallback, useMemo } from 'react'; +import { Classes } from '@blueprintjs/core'; +import { Formik } from 'formik'; +import classNames from 'classnames'; +import NumberFormatFields from './NumberFormatFields'; + +import { compose } from 'utils'; + +/** + * Number format form popover content. + */ +function NumberFormats() { + const initialValues = useMemo( + () => ({ + format_money: '', + show_zero: '', + show_in_red: '', + divide_on_1000: '', + negative_format: '', + precision: '', + }), + [], + ); + // Handle cancel button click. + const handleCancelClick = useCallback(() => {}, []); + + // Handle form submit. + const handleFormSubmit = (values, { setSubmitting }) => { + setSubmitting(true); + const form = { ...values }; + }; + + return ( + + + + + + ); +} + +export default NumberFormats; diff --git a/client/src/components/PaymentReceiveListField.js b/client/src/components/PaymentReceiveListField.js index 4c9f828ba..6b6b3a34d 100644 --- a/client/src/components/PaymentReceiveListField.js +++ b/client/src/components/PaymentReceiveListField.js @@ -29,7 +29,7 @@ function PaymentReceiveListField({ onItemSelect={onInvoiceSelect} selectedItem={`${selectedInvoiceId}`} selectedItemProp={'id'} - labelProp={'name'} + textProp={'name'} defaultText={defaultSelectText} /> ); diff --git a/client/src/components/SalutationList.js b/client/src/components/SalutationList.js index 9b7e1d660..96b881589 100644 --- a/client/src/components/SalutationList.js +++ b/client/src/components/SalutationList.js @@ -13,7 +13,7 @@ export default function SalutationList({ {/*------------ Quantity on hand -----------*/} - + {({ field, meta: { error, touched } }) => ( } intent={inputIntent({ error, touched })} - helperText={} + helperText={} > @@ -24,15 +25,24 @@ function DecrementAdjustmentFields() { {/*------------ Decrement -----------*/} - - {({ field, meta: { error, touched } }) => ( + + {({ + form: { values, setFieldValue }, + field, + meta: { error, touched }, + }) => ( } intent={inputIntent({ error, touched })} - helperText={} + helperText={} fill={true} > - + { + setFieldValue('new_quantity', decrementCalc(values, event)); + }} + /> )} @@ -40,13 +50,22 @@ function DecrementAdjustmentFields() { {/*------------ New quantity -----------*/} - {({ field, meta: { error, touched } }) => ( + {({ + form: { values, setFieldValue }, + field, + meta: { error, touched }, + }) => ( } intent={inputIntent({ error, touched })} helperText={} > - + { + setFieldValue('quantity', decrementCalc(values, event)); + }} + /> )} diff --git a/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/IncrementAdjustmentFields.js b/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/IncrementAdjustmentFields.js index 4a667e94d..286bea519 100644 --- a/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/IncrementAdjustmentFields.js +++ b/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/IncrementAdjustmentFields.js @@ -1,21 +1,22 @@ import React from 'react'; -import { FastField, ErrorMessage } from 'formik'; +import { FastField, ErrorMessage, useFormikContext } from 'formik'; import { FormGroup, InputGroup, Intent } from '@blueprintjs/core'; import { Row, Col, FieldRequiredHint } from 'components'; import { inputIntent } from 'utils'; import { FormattedMessage as T } from 'react-intl'; +import { decrementCalc, incrementCalc } from './utils'; function IncrementAdjustmentFields() { return ( {/*------------ Quantity on hand -----------*/} - + {({ field, meta: { error, touched } }) => ( } intent={inputIntent({ error, touched })} - helperText={} + helperText={} > @@ -24,15 +25,24 @@ function IncrementAdjustmentFields() { {/*------------ Increment -----------*/} - - {({ field, meta: { error, touched } }) => ( + + {({ + form: { values, setFieldValue }, + field, + meta: { error, touched }, + }) => ( } intent={inputIntent({ error, touched })} - helperText={} + helperText={} fill={true} > - + { + setFieldValue('new_quantity', incrementCalc(values, event)); + }} + /> )} @@ -54,13 +64,22 @@ function IncrementAdjustmentFields() { {/*------------ New quantity -----------*/} - {({ field, meta: { error, touched } }) => ( + {({ + form: { values, setFieldValue }, + field, + meta: { error, touched }, + }) => ( } intent={inputIntent({ error, touched })} helperText={} > - + { + setFieldValue('quantity', decrementCalc(values, event)); + }} + /> )} diff --git a/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/InventoryAdjustmentFloatingActions.js b/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/InventoryAdjustmentFloatingActions.js new file mode 100644 index 000000000..1665e8adf --- /dev/null +++ b/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/InventoryAdjustmentFloatingActions.js @@ -0,0 +1,51 @@ +import React from 'react'; +import { Intent, Button, Classes } from '@blueprintjs/core'; +import { useFormikContext } from 'formik'; +import { FormattedMessage as T } from 'react-intl'; +import { saveInvoke } from 'utils'; + +export default function InventoryAdjustmentFloatingActions({ + onCloseClick, + onSubmitClick, +}) { + const { isSubmitting } = useFormikContext(); + + const handleSubmitDraftBtnClick = (event) => { + saveInvoke(onSubmitClick, event, { + publish: false, + }); + }; + const handleSubmitMakeAdjustmentBtnClick = (event) => { + saveInvoke(onSubmitClick, event, { + publish: true, + }); + }; + + return ( + + + + + + + + {} + + + {} + + + + ); +} diff --git a/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/InventoryAdjustmentForm.schema.js b/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/InventoryAdjustmentForm.schema.js index 7b0048f2d..25fe6c687 100644 --- a/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/InventoryAdjustmentForm.schema.js +++ b/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/InventoryAdjustmentForm.schema.js @@ -6,22 +6,25 @@ const Schema = Yup.object().shape({ date: Yup.date() .required() .label(formatMessage({ id: 'date' })), - type: Yup.number().required(), - adjustment_account_id: Yup.number().required(), + type: Yup.string().required(), + adjustment_account_id: Yup.string().required(), + item_id: Yup.number().required(), reason: Yup.string() .required() .label(formatMessage({ id: 'reason' })), - quantity: Yup.number().when(['type'], { - is: (type) => type, - then: Yup.number().required(), - }), + quantity_on_hand: Yup.number() + .min(0) + .required() + .label(formatMessage({ id: 'qty' })), + quantity: Yup.number().integer().max(Yup.ref('quantity_on_hand')).required(), cost: Yup.number().when(['type'], { is: (type) => type, - then: Yup.number().required(), + then: Yup.number(), }), reference_no: Yup.string(), - new_quantity: Yup.number(), + new_quantity: Yup.number().min(Yup.ref('quantity')).required(), description: Yup.string().min(3).max(DATATYPES_LENGTH.TEXT).nullable().trim(), + publish: Yup.boolean(), }); export const CreateInventoryAdjustmentFormSchema = Schema; diff --git a/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/InventoryAdjustmentFormDialogContent.js b/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/InventoryAdjustmentFormDialogContent.js index 4887fbc00..c66401cfb 100644 --- a/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/InventoryAdjustmentFormDialogContent.js +++ b/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/InventoryAdjustmentFormDialogContent.js @@ -1,33 +1,31 @@ -import React, { useCallback, useMemo } from 'react'; +import React, { useState, useCallback, useMemo } from 'react'; import { Intent } from '@blueprintjs/core'; -import { Formik } from 'formik'; +import { Formik, Form } from 'formik'; import { FormattedMessage as T, useIntl } from 'react-intl'; import { useQuery, queryCache } from 'react-query'; import moment from 'moment'; import { omit } from 'lodash'; -import { - AppToaster, - DialogContent, - Row, - Col, - ListSelect, - IF, -} from 'components'; +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 { compose } from 'utils'; const defaultInitialValues = { date: moment(new Date()).format('YYYY-MM-DD'), type: 'decrement', adjustment_account_id: '', + item_id: '', reason: '', + cost: '', + quantity: '', reference_no: '', + quantity_on_hand: '', description: '', + publish: '', }; /** @@ -40,31 +38,38 @@ function InventoryAdjustmentFormDialogContent({ // #withAccountsActions requestFetchAccounts, + // #withInventoryAdjustmentActions + requestSubmitInventoryAdjustment, + // #ownProp + itemDetail, dialogName, - action, }) { const { formatMessage } = useIntl(); + const [submitPayload, setSubmitPayload] = useState({}); // Fetches accounts list. - const fetchAccountsList = useQuery('accounts-list', () => - requestFetchAccounts(), - ); + const fetchAccount = useQuery('accounts-list', () => requestFetchAccounts()); const initialValues = useMemo( () => ({ ...defaultInitialValues, + ...itemDetail, }), [], ); // Handles the form submit. const handleFormSubmit = (values, { setSubmitting, setErrors }) => { - const form = { ...values }; + const form = { + ...omit(values, ['quantity_on_hand', 'new_quantity', 'action']), + publish: submitPayload.publish, + }; const onSuccess = ({ response }) => { closeDialog(dialogName); queryCache.invalidateQueries('accounts-list'); + queryCache.invalidateQueries('items-table'); AppToaster.show({ message: formatMessage({ @@ -76,14 +81,21 @@ function InventoryAdjustmentFormDialogContent({ const onError = (error) => { setSubmitting(false); }; - //requestInventoryAdjustment + requestSubmitInventoryAdjustment({ form }).then(onSuccess).catch(onError); }; // Handles dialog close. - const handleClose = useCallback(() => { + const handleCloseClick = useCallback(() => { closeDialog(dialogName); }, [closeDialog, dialogName]); + const handleSubmitClick = useCallback( + (event, payload) => { + setSubmitPayload({ ...payload }); + }, + [setSubmitPayload], + ); + return ( - + + + + ); } -export default compose(withDialogActions)(InventoryAdjustmentFormDialogContent); +export default compose( + withInventoryAdjustmentActions, + withDialogActions, +)(InventoryAdjustmentFormDialogContent); diff --git a/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/InventoryAdjustmentFormDialogFields.js b/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/InventoryAdjustmentFormDialogFields.js index fca2d3b27..c950dc918 100644 --- a/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/InventoryAdjustmentFormDialogFields.js +++ b/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/InventoryAdjustmentFormDialogFields.js @@ -1,22 +1,14 @@ import React from 'react'; +import { FastField, ErrorMessage, useFormikContext } from 'formik'; import { - Form, - FastField, - ErrorMessage, - useFormikContext, - useField, -} from 'formik'; -import { - Button, Classes, FormGroup, InputGroup, - Intent, TextArea, Position, } from '@blueprintjs/core'; import classNames from 'classnames'; -import { FormattedMessage as T } from 'react-intl'; +import { FormattedMessage as T, useIntl } from 'react-intl'; import { DateInput } from '@blueprintjs/datetime'; import { ListSelect, Choose, If, FieldRequiredHint } from 'components'; import { @@ -30,166 +22,149 @@ 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'; /** * Inventory adjustment form dialogs fields. */ function InventoryAdjustmentFormDialogFields({ - // #ownProps - onClose, - //# withAccount accountsList, }) { - const { values, isSubmitting } = useFormikContext(); + const { values } = useFormikContext(); + const { formatMessage } = useIntl(); 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, - }} - /> - - )} - - - {/*------------ Adjustment type -----------*/} - - {({ form, field: { value }, meta: { error, touched } }) => ( - } - labelInfo={} - helperText={} - intent={inputIntent({ error, touched })} - className={classNames(CLASSES.FILL)} - > - { - console.log(type.value, 'EE'); - form.setFieldValue('type', type.value); - }} - selectedItem={value} - selectedItemProp={'value'} - labelProp={'name'} - popoverProps={{ minimal: true }} - /> - - )} - - - - - - - - - - - {/*------------ Reason -----------*/} - - {({ form, field, meta: { error, touched } }) => ( - } - labelInfo={} - intent={inputIntent({ error, touched })} - helperText={} - > - - - )} - - {/*------------ Adjustment account -----------*/} - - {({ form, field, meta: { error, touched } }) => ( - } - labelInfo={} - intent={inputIntent({ error, touched })} - helperText={} - > - - form.setFieldValue('adjustment_account_id', item) - } - /> - - )} - - {/*------------ Reference -----------*/} - - {({ form, field, meta: { error, touched } }) => ( - } - className={classNames(CLASSES.FILL)} - intent={inputIntent({ error, touched })} - helperText={} - > - - - )} - - {/*------------ description -----------*/} - - {({ field, meta: { error, touched } }) => ( - } - className={'form-group--description'} - intent={inputIntent({ error, touched })} - helperText={} - > - - - )} - - - - - - - - - + {/*------------ 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, + }} + /> + + )} + + + {/*------------ 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, + ); + }} + filterable={false} + selectedItem={value} + selectedItemProp={'value'} + textProp={'name'} + popoverProps={{ minimal: true }} + /> + + )} + + + + + + + + + + {/*------------ Reason -----------*/} + + {({ form, field, meta: { error, touched } }) => ( + } + labelInfo={} + intent={inputIntent({ error, touched })} + helperText={} + > + + + )} + + {/*------------ Adjustment account -----------*/} + + {({ form, field, meta: { error, touched } }) => ( + } + labelInfo={} + intent={inputIntent({ error, touched })} + helperText={} + > + + form.setFieldValue('adjustment_account_id', item.id) + } + inputProps={{ + placeholder: formatMessage({ + id: 'select_adjustment_account', + }), + }} + /> + + )} + + {/*------------ Reference -----------*/} + + {({ form, field, meta: { error, touched } }) => ( + } + className={classNames(CLASSES.FILL)} + intent={inputIntent({ error, touched })} + helperText={} + > + + + )} + + {/*------------ description -----------*/} + + {({ field, meta: { error, touched } }) => ( + } + className={'form-group--description'} + intent={inputIntent({ error, touched })} + helperText={} + > + + + )} + + ); } diff --git a/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/index.js b/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/index.js index 604bad6d1..e32d749ee 100644 --- a/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/index.js +++ b/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/index.js @@ -27,7 +27,7 @@ function InventoryAdjustmentFormDialog({ diff --git a/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/utils.js b/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/utils.js new file mode 100644 index 000000000..5585d3707 --- /dev/null +++ b/client/src/containers/Dialogs/InventoryAdjustmentFormDialog/utils.js @@ -0,0 +1,11 @@ +export const decrementCalc = ({ quantity_on_hand, type }, e) => { + if (type == 'decrement') { + return parseInt(quantity_on_hand, 10) - parseInt(e.currentTarget.value, 10); + } else { + return e.currentTarget.value - quantity_on_hand; + } +}; + +export const incrementCalc = ({ quantity_on_hand, quantity }, e) => { + return parseInt(quantity_on_hand, 10) + parseInt(quantity, 10); +}; diff --git a/client/src/containers/FinancialStatements/BalanceSheet/BalanceSheetActionsBar.js b/client/src/containers/FinancialStatements/BalanceSheet/BalanceSheetActionsBar.js index c03943d8d..ea21c3849 100644 --- a/client/src/containers/FinancialStatements/BalanceSheet/BalanceSheetActionsBar.js +++ b/client/src/containers/FinancialStatements/BalanceSheet/BalanceSheetActionsBar.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState } from 'react'; import { NavbarGroup, Button, @@ -13,6 +13,7 @@ import classNames from 'classnames'; import Icon from 'components/Icon'; import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar'; +import NumberFormats from 'components/NumberFormats'; import { compose } from 'utils'; import withBalanceSheetDetail from './withBalanceSheetDetail'; @@ -72,6 +73,18 @@ function BalanceSheetActionsBar({ icon={} /> + } + minimal={true} + interactionKind={PopoverInteractionKind.CLICK} + position={Position.BOTTOM_LEFT} + > + } + icon={} + /> + diff --git a/client/src/containers/FinancialStatements/FinancialAccountsFilter.js b/client/src/containers/FinancialStatements/FinancialAccountsFilter.js index 4f6e89585..233865ad0 100644 --- a/client/src/containers/FinancialStatements/FinancialAccountsFilter.js +++ b/client/src/containers/FinancialStatements/FinancialAccountsFilter.js @@ -54,7 +54,7 @@ export default function FinancialAccountsFilter({ ...restProps }) { filterable={false} selectedItem={value} selectedItemProp={'key'} - labelProp={'name'} + textProp={'name'} onItemSelect={(item) => { setFieldValue('accountsFilter', item.key); }} diff --git a/client/src/containers/FinancialStatements/SelectDisplayColumnsBy.js b/client/src/containers/FinancialStatements/SelectDisplayColumnsBy.js index 7c2f1446e..09346a795 100644 --- a/client/src/containers/FinancialStatements/SelectDisplayColumnsBy.js +++ b/client/src/containers/FinancialStatements/SelectDisplayColumnsBy.js @@ -27,7 +27,7 @@ export default function SelectsListColumnsBy(props) { filterable={false} selectedItem={value} selectedItemProp={'key'} - labelProp={'name'} + textProp={'name'} onItemSelect={(item) => { form.setFieldValue('displayColumnsType', item.key); }} diff --git a/client/src/containers/Items/InventoryAdjustmentDataTable.js b/client/src/containers/Items/InventoryAdjustmentDataTable.js index 7c0abedc4..9b898592d 100644 --- a/client/src/containers/Items/InventoryAdjustmentDataTable.js +++ b/client/src/containers/Items/InventoryAdjustmentDataTable.js @@ -7,38 +7,42 @@ import { MenuItem, MenuDivider, Position, + Tag, } from '@blueprintjs/core'; import { FormattedMessage as T, useIntl } from 'react-intl'; import moment from 'moment'; import classNames from 'classnames'; -import { - DataTable, - If, - Money, - Choose, - Icon, - LoadingIndicator, -} from 'components'; +import { DataTable, Icon, LoadingIndicator } from 'components'; import { CLASSES } from 'common/classes'; import { useIsValuePassed } from 'hooks'; import withDialogActions from 'containers/Dialog/withDialogActions'; -// withInventoryAdjustments -// withInventoryAdjustmentsActions +import withInventoryAdjustments from './withInventoryAdjustments'; +import withInventoryAdjustmentActions from './withInventoryAdjustmentActions'; import { compose, saveInvoke } from 'utils'; import { withRouter } from 'react-router-dom'; function InventoryAdjustmentDataTable({ + // withInventoryAdjustments + inventoryAdjustmentItems, + inventoryAdjustmentCurrentPage, + inventoryAdjustmentLoading, + inventoryAdjustmentsPagination, + + // withInventoryAdjustmentsActions + addInventoryAdjustmentTableQueries, + // #ownProps onDeleteInventoryAdjustment, onSelectedRowsChange, }) { const { formatMessage } = useIntl(); + const isLoadedBefore = useIsValuePassed(inventoryAdjustmentLoading, false); const handleDeleteInventoryAdjustment = useCallback( - (_inventory) => { - saveInvoke(onDeleteInventoryAdjustment, _inventory); + (_adjustment) => () => { + saveInvoke(onDeleteInventoryAdjustment, _adjustment); }, [onDeleteInventoryAdjustment], ); @@ -53,9 +57,9 @@ function InventoryAdjustmentDataTable({ } intent={Intent.DANGER} onClick={handleDeleteInventoryAdjustment(adjustment)} + icon={} /> ), @@ -79,41 +83,53 @@ function InventoryAdjustmentDataTable({ { id: 'type', Header: formatMessage({ id: 'type' }), - accessor: 'type', + accessor: (row) => + row.type ? ( + + {formatMessage({ id: row.type })} + + ) : ( + '' + ), className: 'type', width: 100, }, { id: 'reason', Header: formatMessage({ id: 'reason' }), - // accessor: (r) => ( - // - // - // ), + accessor: 'reason', className: 'reason', width: 115, }, { - id: 'reference', - Header: formatMessage({ id: 'reference' }), - accessor: (row) => `#${row.reference}`, - className: 'reference', + id: 'reference_no', + Header: formatMessage({ id: 'reference_no' }), + accessor: 'reference_no', + className: 'reference_no', width: 100, }, { - id: 'status', + id: 'publish', Header: formatMessage({ id: 'status' }), - accessor: 'status', + accessor: (r) => { + return r.is_published ? ( + + + + ) : ( + + + + ); + }, width: 95, - className: 'status', + className: 'publish', }, { id: 'description', Header: formatMessage({ id: 'description' }), + accessor: 'description', disableSorting: true, width: 85, className: 'description', @@ -144,6 +160,23 @@ function InventoryAdjustmentDataTable({ [actionMenuList, formatMessage], ); + const handleDataTableFetchData = useCallback( + ({ pageSize, pageIndex, sortBy }) => { + addInventoryAdjustmentTableQueries({ + ...(sortBy.length > 0 + ? { + column_sort_by: sortBy[0].id, + sort_order: sortBy[0].desc ? 'desc' : 'asc', + } + : {}), + page_size: pageSize, + page: pageIndex + 1, + }); + }, + [addInventoryAdjustmentTableQueries], + ); + + const handleSelectedRowsChange = useCallback( (selectedRows) => { saveInvoke( @@ -160,11 +193,23 @@ function InventoryAdjustmentDataTable({ return ( - - + + ); @@ -173,4 +218,18 @@ function InventoryAdjustmentDataTable({ export default compose( withRouter, withDialogActions, + withInventoryAdjustmentActions, + withInventoryAdjustments( + ({ + inventoryAdjustmentLoading, + inventoryAdjustmentItems, + inventoryAdjustmentCurrentPage, + inventoryAdjustmentsPagination, + }) => ({ + inventoryAdjustmentLoading, + inventoryAdjustmentItems, + inventoryAdjustmentCurrentPage, + inventoryAdjustmentsPagination, + }), + ), )(InventoryAdjustmentDataTable); diff --git a/client/src/containers/Items/InventoryAdjustmentList.js b/client/src/containers/Items/InventoryAdjustmentList.js index 03bc43b6b..b6f35eecb 100644 --- a/client/src/containers/Items/InventoryAdjustmentList.js +++ b/client/src/containers/Items/InventoryAdjustmentList.js @@ -3,13 +3,15 @@ import { useQuery } from 'react-query'; import { Alert, Intent } from '@blueprintjs/core'; import { FormattedMessage as T, useIntl } from 'react-intl'; +import AppToaster from 'components/AppToaster'; import DashboardPageContent from 'components/Dashboard/DashboardPageContent'; import DashboardInsider from 'components/Dashboard/DashboardInsider'; import InventoryAdjustmentDataTable from './InventoryAdjustmentDataTable'; - +import withInventoryAdjustmentActions from './withInventoryAdjustmentActions'; +import withInventoryAdjustments from './withInventoryAdjustments'; import withDashboardActions from 'containers/Dashboard/withDashboardActions'; -//withInventoryAdjustmentsActions + import { compose } from 'utils'; import { Route, Switch } from 'react-router-dom'; @@ -19,7 +21,13 @@ import { Route, Switch } from 'react-router-dom'; function InventoryAdjustmentList({ // #withDashboardActions changePageTitle, + + // #withInventoryAdjustments + inventoryAdjustmentTableQuery, + // #withInventoryAdjustmentsActions + requestFetchInventoryAdjustmentTable, + requestDeleteInventoryAdjustment, }) { const { formatMessage } = useIntl(); const [selectedRows, setSelectedRows] = useState([]); @@ -32,8 +40,8 @@ function InventoryAdjustmentList({ }, [changePageTitle, formatMessage]); const fetchInventoryAdjustments = useQuery( - ['inventory-adjustment-list'], - () => {}, + ['inventory-adjustment-list' ,inventoryAdjustmentTableQuery], + (key, query) => requestFetchInventoryAdjustmentTable({ ...query }), ); // Handle selected rows change. @@ -55,7 +63,25 @@ function InventoryAdjustmentList({ setDeleteInventoryAdjustment(false); }, [setDeleteInventoryAdjustment]); - const handleConfirmInventoryAdjustmentDelete = useCallback(() => {}, []); + const handleConfirmInventoryAdjustmentDelete = useCallback(() => { + requestDeleteInventoryAdjustment(deleteInventoryAdjustment.id) + .then(() => { + setDeleteInventoryAdjustment(false); + AppToaster.show({ + message: formatMessage({ + id: 'the_adjustment_has_been_successfully_deleted', + }), + intent: Intent.SUCCESS, + }); + }) + .catch((errors) => { + setDeleteInventoryAdjustment(false); + }); + }, [ + deleteInventoryAdjustment, + requestDeleteInventoryAdjustment, + formatMessage, + ]); // Calculates the data table selected rows count. const selectedRowsCount = useMemo(() => Object.values(selectedRows).length, [ @@ -63,7 +89,7 @@ function InventoryAdjustmentList({ ]); return ( - + @@ -73,9 +99,32 @@ function InventoryAdjustmentList({ /> + } + confirmButtonText={} + icon={'trash'} + intent={Intent.DANGER} + isOpen={deleteInventoryAdjustment} + onCancel={handleCancelInventoryAdjustmentDelete} + onConfirm={handleConfirmInventoryAdjustmentDelete} + > + + + + ); } -export default compose(withDashboardActions)(InventoryAdjustmentList); +export default compose( + withDashboardActions, + withInventoryAdjustmentActions, + withInventoryAdjustments(({ inventoryAdjustmentTableQuery }) => ({ + inventoryAdjustmentTableQuery, + })), +)(InventoryAdjustmentList); diff --git a/client/src/containers/Items/ItemForm.js b/client/src/containers/Items/ItemForm.js index f3bd8b9cf..d19efc0af 100644 --- a/client/src/containers/Items/ItemForm.js +++ b/client/src/containers/Items/ItemForm.js @@ -45,9 +45,6 @@ const defaultInitialValues = { category_id: '', sellable: 1, purchasable: true, - opening_quantity: '', - opening_cost: '', - opening_date: moment(new Date()).format('YYYY-MM-DD'), }; /** diff --git a/client/src/containers/Items/ItemForm.schema.js b/client/src/containers/Items/ItemForm.schema.js index 963b12f12..8eade519d 100644 --- a/client/src/containers/Items/ItemForm.schema.js +++ b/client/src/containers/Items/ItemForm.schema.js @@ -61,26 +61,6 @@ const Schema = Yup.object().shape({ stock: Yup.string() || Yup.boolean(), sellable: Yup.boolean().required(), purchasable: Yup.boolean().required(), - opening_cost: Yup.number().when(['opening_quantity'], { - is: (value) => value, - then: Yup.number() - .min(0) - .required() - .label(formatMessage({ id: 'opening_cost_' })), - otherwise: Yup.number().nullable(), - }), - opening_quantity: Yup.number() - .integer() - .min(1) - .nullable() - .label(formatMessage({ id: 'opening_quantity_' })), - opening_date: Yup.date().when(['opening_quantity', 'opening_cost'], { - is: (quantity, cost) => !isBlank(quantity) && !isBlank(cost), - then: Yup.date() - .required() - .label(formatMessage({ id: 'opening_date_' })), - otherwise: Yup.date().nullable(), - }), }); export const transformItemFormData = (item, defaultValue) => { diff --git a/client/src/containers/Items/ItemFormInventorySection.js b/client/src/containers/Items/ItemFormInventorySection.js index f595635cc..efb2762fe 100644 --- a/client/src/containers/Items/ItemFormInventorySection.js +++ b/client/src/containers/Items/ItemFormInventorySection.js @@ -65,77 +65,6 @@ function ItemFormInventorySection({ accountsList, baseCurrency }) { )} - - {/*------------- Opening quantity ------------- */} - - {({ field, meta: { touched, error } }) => ( - } - labelInfo={} - className={'form-group--opening_quantity'} - intent={inputIntent({ error, touched })} - helperText={} - inline={true} - > - - - )} - - - {/*------------- Opening date ------------- */} - - {({ form, field: { value }, meta: { touched, error } }) => ( - } - labelInfo={} - className={classNames( - 'form-group--select-list', - 'form-group--opening_date', - CLASSES.FILL, - )} - intent={inputIntent({ error, touched })} - helperText={} - inline={true} - > - { - form.setFieldValue('opening_date', value); - })} - helperText={} - popoverProps={{ position: Position.BOTTOM, minimal: true }} - /> - - )} - - - - {/*------------- Opening cost ------------- */} - - - {({ form, field: { value }, meta: { touched, error } }) => ( - } - labelInfo={} - className={'form-group--opening_cost'} - intent={inputIntent({ error, touched })} - helperText={} - inline={true} - > - - - { - form.setFieldValue('opening_cost', unformattedValue); - }} - /> - - - )} - diff --git a/client/src/containers/Items/ItemsDataTable.js b/client/src/containers/Items/ItemsDataTable.js index 3c7bde719..f0dcfbbbf 100644 --- a/client/src/containers/Items/ItemsDataTable.js +++ b/client/src/containers/Items/ItemsDataTable.js @@ -75,6 +75,17 @@ function ItemsDataTable({ [addItemsTableQueries], ); + const handleMakeAdjustment = useCallback( + (item) => () => { + openDialog('inventory-adjustment-form', { + action: 'make_adjustment', + item_id: item.id, + quantity_on_hand: item.quantity_on_hand, + }); + }, + [openDialog], + ); + const handleEditItem = useCallback( (item) => () => { onEditItem && onEditItem(item); @@ -89,10 +100,6 @@ function ItemsDataTable({ [onDeleteItem], ); - const handleMakeAdjustment = useCallback(() => { - openDialog('inventory-adjustment-form', {}); - }, [openDialog]); - const actionMenuList = useCallback( (item) => ( @@ -120,11 +127,11 @@ function ItemsDataTable({ onClick={() => onActivateItem(item)} /> - + { + if ( + errors.find((error) => error.type === 'ITEM_HAS_ASSOCIATED_TRANSACTINS') + ) { + AppToaster.show({ + message: formatMessage({ + id: 'the_item_has_associated_transactions', + }), + intent: Intent.DANGER, + }); + } + + if ( + errors.find( + (error) => error.type === 'ITEM_HAS_ASSOCIATED_INVENTORY_ADJUSTMENT', + ) + ) { + AppToaster.show({ + message: formatMessage({ + id: + 'you_could_not_delete_item_that_has_associated_inventory_adjustments_transacions', + }), + intent: Intent.DANGER, + }); + } + }; + // handle confirm delete item. const handleConfirmDeleteItem = useCallback(() => { requestDeleteItem(deleteItem.id) @@ -112,19 +139,8 @@ function ItemsList({ setDeleteItem(false); }) .catch(({ errors }) => { - if ( - errors.find( - (error) => error.type === 'ITEM_HAS_ASSOCIATED_TRANSACTINS', - ) - ) { - AppToaster.show({ - message: formatMessage({ - id: 'the_item_has_associated_transactions', - }), - intent: Intent.DANGER, - }); - } setDeleteItem(false); + handleDeleteErrors(errors); }); }, [requestDeleteItem, deleteItem, formatMessage]); diff --git a/client/src/containers/Items/withInventoryAdjustmentActions.js b/client/src/containers/Items/withInventoryAdjustmentActions.js index 3cadd6fed..f596e2b0f 100644 --- a/client/src/containers/Items/withInventoryAdjustmentActions.js +++ b/client/src/containers/Items/withInventoryAdjustmentActions.js @@ -7,7 +7,7 @@ import { import t from 'store/types'; const mapDispatchToProps = (dispatch) => ({ - requestSubmitInventoryAdjustment: (form) => + requestSubmitInventoryAdjustment: ({ form }) => dispatch(submitInventoryAdjustment({ form })), requestFetchInventoryAdjustmentTable: (query = {}) => dispatch(fetchInventoryAdjustmentsTable({ query: { ...query } })), diff --git a/client/src/containers/Items/withInventoryAdjustments.js b/client/src/containers/Items/withInventoryAdjustments.js index 87fbdd40c..c35b646a0 100644 --- a/client/src/containers/Items/withInventoryAdjustments.js +++ b/client/src/containers/Items/withInventoryAdjustments.js @@ -1,4 +1,34 @@ import { connect } from 'react-redux'; +import { + getInvoiceTableQueryFactory, + getInventoryAdjustmentCurrentPageFactory, + getInventoryAdjustmentPaginationMetaFactory, +} from 'store/inventoryAdjustments/inventoryAdjustment.selector'; +export default (mapState) => { + const getInventoryAdjustmentItems = getInventoryAdjustmentCurrentPageFactory(); + const getInventoryAdjustmentTableQuery = getInvoiceTableQueryFactory(); + const getInventoryAdjustmentsPaginationMeta = getInventoryAdjustmentPaginationMetaFactory(); + const mapStateToProps = (state, props) => { + const query = getInventoryAdjustmentTableQuery(state, props); + const mapped = { + inventoryAdjustmentCurrentPage: getInventoryAdjustmentItems( + state, + props, + query, + ), + inventoryAdjustmentItems: Object.values(state.inventoryAdjustments.items), + inventoryAdjustmentTableQuery: query, + inventoryAdjustmentsPagination: getInventoryAdjustmentsPaginationMeta( + state, + props, + query, + ), + inventoryAdjustmentLoading: state.inventoryAdjustments.loading, + }; + return mapState ? mapState(mapped, state, props) : mapped; + }; + return connect(mapStateToProps); +}; diff --git a/client/src/containers/Preferences/General/GeneralForm.js b/client/src/containers/Preferences/General/GeneralForm.js index ef1239cbd..46a711c8a 100644 --- a/client/src/containers/Preferences/General/GeneralForm.js +++ b/client/src/containers/Preferences/General/GeneralForm.js @@ -105,7 +105,7 @@ export default function PreferencesGeneralForm({}) { selectedItem={value} selectedItemProp={'value'} defaultText={} - labelProp={'name'} + textProp={'name'} popoverProps={{ minimal: true }} /> @@ -130,7 +130,7 @@ export default function PreferencesGeneralForm({}) { selectedItem={value} selectedItemProp={'code'} defaultText={} - labelProp={'label'} + textProp={'label'} popoverProps={{ minimal: true }} /> @@ -150,7 +150,7 @@ export default function PreferencesGeneralForm({}) { } selectedItem={value} onItemSelect={(item) => {}} @@ -173,7 +173,7 @@ export default function PreferencesGeneralForm({}) { } selectedItem={value} onItemSelect={(item) => {}} @@ -227,7 +227,7 @@ export default function PreferencesGeneralForm({}) { selectedItem={value} selectedItemProp={'value'} defaultText={} - labelProp={'name'} + textProp={'name'} popoverProps={{ minimal: true }} /> diff --git a/client/src/containers/Setup/SetupOrganizationForm.js b/client/src/containers/Setup/SetupOrganizationForm.js index fc7d5f3f6..5a9795278 100644 --- a/client/src/containers/Setup/SetupOrganizationForm.js +++ b/client/src/containers/Setup/SetupOrganizationForm.js @@ -324,7 +324,7 @@ function SetupOrganizationForm({ selectedItem={values.base_currency} selectedItemProp={'value'} defaultText={} - labelProp={'name'} + textProp={'name'} /> @@ -354,7 +354,7 @@ function SetupOrganizationForm({ selectedItem={values.language} selectedItemProp={'value'} defaultText={} - labelProp={'name'} + textProp={'name'} /> @@ -383,7 +383,7 @@ function SetupOrganizationForm({ selectedItem={values.fiscal_year} selectedItemProp={'value'} defaultText={} - labelProp={'name'} + textProp={'name'} /> diff --git a/client/src/lang/en/index.js b/client/src/lang/en/index.js index b3ef465a3..fd5942b91 100644 --- a/client/src/lang/en/index.js +++ b/client/src/lang/en/index.js @@ -950,9 +950,24 @@ export default { cost: 'Cost', qty_on_hand: 'Qty on hand', adjustment_account: 'Adjustment account', - inventory_adjustment_list:'Inventory Adjustment List', - delete_adjustment:'Delete Adjustment', + inventory_adjustment_list: 'Inventory Adjustment List', + delete_adjustment: 'Delete Adjustment', the_make_adjustment_has_been_successfully_created: 'The make adjustment has been successfully created.', + the_adjustment_has_been_successfully_deleted: + 'The adjustment has been successfully deleted.', + once_delete_this_inventory_a_adjustment_you_will_able_to_restore_it: `Once you delete this inventory a adjustment, you won\'t be able to restore it later. Are you sure you want to delete this invoice?`, + select_adjustment_account: 'Select Adjustment account', + qty: 'Quantity on hand', + money_format: 'Money format', + show_zero: 'Show zero', + show_negative_in_red: 'Show negative in red', + divide_on_1000: 'Divide on 1000', + negative_format: 'Negative format', + decimal_places: 'Decimal places', + run: 'Run', + you_could_not_delete_item_that_has_associated_inventory_adjustments_transacions: + 'You could not delete item that has associated inventory adjustments transactions', + format: 'Format', current: 'Current', }; diff --git a/client/src/store/inventoryAdjustments/inventoryAdjustment.actions.js b/client/src/store/inventoryAdjustments/inventoryAdjustment.actions.js index e82db2779..89fd1f50a 100644 --- a/client/src/store/inventoryAdjustments/inventoryAdjustment.actions.js +++ b/client/src/store/inventoryAdjustments/inventoryAdjustment.actions.js @@ -4,10 +4,11 @@ import t from 'store/types'; export const submitInventoryAdjustment = ({ form }) => { return (dispatch) => new Promise((resolve, reject) => { - ApiService.post('inventory_adjustments', form).then((response) => { - resolve(response); - }), - caches((error) => { + ApiService.post('inventory_adjustments/quick', form) + .then((response) => { + resolve(response); + }) + .catch((error) => { const { response } = error; const { data } = response; @@ -51,7 +52,7 @@ export const fetchInventoryAdjustmentsTable = ({ query } = {}) => { dispatch({ type: t.INVENTORY_ADJUSTMENTS_PAGE_SET, payload: { - inventory_adjustments: response.data, + inventory_adjustments: response.data.inventoy_adjustments, pagination: response.data.pagination, customViewId: response.data?.filter_meta?.view?.custom_view_id || -1, @@ -60,7 +61,7 @@ export const fetchInventoryAdjustmentsTable = ({ query } = {}) => { dispatch({ type: t.INVENTORY_ADJUSTMENT_ITEMS_SET, payload: { - inventory_adjustment: response.data, + inventory_adjustment: response.data.inventoy_adjustments, }, }); dispatch({ diff --git a/client/src/store/inventoryAdjustments/inventoryAdjustment.reducer.js b/client/src/store/inventoryAdjustments/inventoryAdjustment.reducer.js index 8b84c1084..6ebdc0b71 100644 --- a/client/src/store/inventoryAdjustments/inventoryAdjustment.reducer.js +++ b/client/src/store/inventoryAdjustments/inventoryAdjustment.reducer.js @@ -14,9 +14,6 @@ const initialState = { page_size: 12, page: 1, }, - paginationMeta: { - total: 0, - }, }; export default createReducer(initialState, { @@ -37,7 +34,6 @@ export default createReducer(initialState, { const viewId = customViewId || -1; const view = state.views[viewId] || {}; - state.views[viewId] = { ...view, pages: { @@ -49,7 +45,6 @@ export default createReducer(initialState, { }; }, - //useless [t.INVENTORY_ADJUSTMENT_ITEMS_SET]: (state, action) => { const { inventory_adjustment } = action.payload; const _inventory_adjustment = {}; diff --git a/client/src/store/inventoryAdjustments/inventoryAdjustment.selector.js b/client/src/store/inventoryAdjustments/inventoryAdjustment.selector.js index 3f45271a8..1625e57f3 100644 --- a/client/src/store/inventoryAdjustments/inventoryAdjustment.selector.js +++ b/client/src/store/inventoryAdjustments/inventoryAdjustment.selector.js @@ -5,3 +5,55 @@ import { defaultPaginationMeta, } from 'store/selectors'; +const inventoryAdjustmentTableQuery = (state) => + state.inventoryAdjustments.tableQuery; + +const inventoryAdjustmentsPaginationSelector = (state, props) => { + const viewId = state.inventoryAdjustments.currentViewId; + return state.inventoryAdjustments.views?.[viewId]; +}; + +const inventoryAdjustmentItemsSelector = (state) => + state.inventoryAdjustments.items; + +const inventoryAdjustmentCurrentPageSelector = (state, props) => { + const currentViewId = state.inventoryAdjustments.currentViewId; + const currentView = state.inventoryAdjustments.views?.[currentViewId]; + const currentPageId = currentView?.paginationMeta?.page; + + return currentView?.pages?.[currentPageId]; +}; + +const getinventoryAdjustmentCurrentViewIdSelector = (state) => + state.inventoryAdjustments.currentViewId; + +export const getInvoiceTableQueryFactory = () => + createSelector( + paginationLocationQuery, + inventoryAdjustmentTableQuery, + (locationQuery, tableQuery) => { + return { + ...locationQuery, + ...tableQuery, + }; + }, + ); + +export const getInventoryAdjustmentCurrentPageFactory = () => + createSelector( + inventoryAdjustmentCurrentPageSelector, + inventoryAdjustmentItemsSelector, + (currentPage, items) => { + return typeof currentPage === 'object' + ? pickItemsFromIds(items, currentPage.ids) || [] + : []; + }, + ); + +export const getInventoryAdjustmentPaginationMetaFactory = () => + createSelector(inventoryAdjustmentsPaginationSelector, (Page) => { + return { + ...defaultPaginationMeta(), + ...(Page?.paginationMeta || {}), + }; + }); diff --git a/client/src/store/inventoryAdjustments/inventoryAdjustment.type.js b/client/src/store/inventoryAdjustments/inventoryAdjustment.type.js index 20837993e..677e6ed22 100644 --- a/client/src/store/inventoryAdjustments/inventoryAdjustment.type.js +++ b/client/src/store/inventoryAdjustments/inventoryAdjustment.type.js @@ -8,7 +8,7 @@ export default { INVENTORY_ADJUSTMENTS_TABLE_QUERIES_ADD: - 'INVENTORY_ADJUSTMENTS_TABLE_QUERIES_ADD', + 'INVENTORY_ADJUSTMENTS/TABLE_QUERIES_ADD', INVENTORY_ADJUSTMENTS_SET_CURRENT_VIEW: 'INVENTORY_ADJUSTMENTS_SET_CURRENT_VIEW', }; diff --git a/client/src/style/App.scss b/client/src/style/App.scss index bda8db957..9f8ce8864 100644 --- a/client/src/style/App.scss +++ b/client/src/style/App.scss @@ -30,6 +30,8 @@ @import 'pages/view-form'; @import 'pages/register-organizaton'; +@import 'pages/number-format.scss'; + // Views @import 'views/filter-dropdown'; diff --git a/client/src/style/pages/number-format.scss b/client/src/style/pages/number-format.scss new file mode 100644 index 000000000..dce18cf3f --- /dev/null +++ b/client/src/style/pages/number-format.scss @@ -0,0 +1,24 @@ +.number-format { + width: 400px; + padding: 12px; + // width: 300px; + // padding: 10px; + &__content { + .bp3-form-group { + margin-bottom: 5px; + // margin-bottom: 0px; + .bp3-form-content { + .bp3-label { + margin-bottom: 3px; + } + .bp3-control { + margin: 5px 0px 0px; + } + } + } + } + &__footer { + display: flex; + justify-content: flex-end; + } +}
+ +