fix: journal number increment.

This commit is contained in:
Ahmed Bouhuolia
2020-11-07 14:28:25 +02:00
parent cc1de9c897
commit acd74fd044
14 changed files with 146 additions and 72 deletions

View File

@@ -3,10 +3,10 @@ import { Intent, Button } from '@blueprintjs/core';
import { FormattedMessage as T } from 'react-intl'; import { FormattedMessage as T } from 'react-intl';
export default function MakeJournalEntriesFooter({ export default function MakeJournalEntriesFooter({
formik: { isSubmitting }, isSubmitting,
onSubmitClick, onSubmitClick,
onCancelClick, onCancelClick,
manualJournal, manualJournalId,
}) { }) {
return ( return (
<div> <div>
@@ -19,11 +19,7 @@ export default function MakeJournalEntriesFooter({
onSubmitClick({ publish: true, redirect: true }); onSubmitClick({ publish: true, redirect: true });
}} }}
> >
{manualJournal && manualJournal.id ? ( {manualJournalId ? <T id={'edit'} /> : <T id={'save'} />}
<T id={'edit'} />
) : (
<T id={'save'} />
)}
</Button> </Button>
<Button <Button

View File

@@ -52,6 +52,7 @@ function MakeJournalEntriesForm({
// #withJournalsActions // #withJournalsActions
requestMakeJournalEntries, requestMakeJournalEntries,
requestEditManualJournal, requestEditManualJournal,
setJournalNumberChanged,
// #withDashboard // #withDashboard
changePageTitle, changePageTitle,
@@ -62,10 +63,9 @@ function MakeJournalEntriesForm({
journalNumberPrefix, journalNumberPrefix,
// #withManualJournals // #withManualJournals
nextJournalNumberChanged, journalNumberChanged,
setJournalNumberChanged,
// #ownProps
manualJournalId, manualJournalId,
manualJournal, manualJournal,
onFormSubmit, onFormSubmit,
@@ -161,8 +161,9 @@ function MakeJournalEntriesForm({
[], [],
); );
const journalNumber = (journalNumberPrefix) ? const journalNumber = journalNumberPrefix
`${journalNumberPrefix}-${journalNextNumber}` : journalNextNumber; ? `${journalNumberPrefix}-${journalNextNumber}`
: journalNextNumber;
const defaultInitialValues = useMemo( const defaultInitialValues = useMemo(
() => ({ () => ({
@@ -269,12 +270,20 @@ function MakeJournalEntriesForm({
} }
}; };
const formik = useFormik({ const {
values,
errors,
setFieldError,
setFieldValue,
handleSubmit,
getFieldProps,
touched,
isSubmitting
} = useFormik({
validationSchema, validationSchema,
initialValues: { initialValues,
...initialValues, onSubmit: (values, { setErrors, setSubmitting, resetForm }) => {
}, setSubmitting(true);
onSubmit: async (values, { setErrors, setSubmitting, resetForm }) => {
const entries = values.entries.filter( const entries = values.entries.filter(
(entry) => entry.debit || entry.credit, (entry) => entry.debit || entry.credit,
); );
@@ -369,17 +378,24 @@ function MakeJournalEntriesForm({
}); });
useEffect(() => { useEffect(() => {
formik.setFieldValue('journal_number', journalNumber); if (journalNumberChanged) {
setJournalNumberChanged(false); setFieldValue('journal_number', journalNumber);
}, [nextJournalNumberChanged, journalNumber]); setJournalNumberChanged(false);
}
}, [journalNumberChanged, setJournalNumberChanged, journalNumber, setFieldValue]);
// Change page subtitle.
useEffect(() => {
changePageSubtitle(`No. ${journalNumber}`);
}, [changePageSubtitle, journalNumber]);
const handleSubmitClick = useCallback( const handleSubmitClick = useCallback(
(payload) => { (payload) => {
setPayload(payload); setPayload(payload);
// formik.resetForm(); // formik.resetForm();
formik.handleSubmit(); handleSubmit();
}, },
[setPayload, formik], [setPayload, handleSubmit],
); );
const handleCancelClick = useCallback( const handleCancelClick = useCallback(
@@ -401,38 +417,53 @@ function MakeJournalEntriesForm({
); );
// Handle click on add a new line/row. // Handle click on add a new line/row.
const handleClickAddNewRow = () => { const handleClickAddNewRow = useCallback(() => {
formik.setFieldValue( setFieldValue(
'entries', 'entries',
reorderingEntriesIndex([...formik.values.entries, defaultEntry]), reorderingEntriesIndex([...values.entries, defaultEntry]),
); );
}; }, [values.entries, defaultEntry, setFieldValue]);
// Handle click `Clear all lines` button. // Handle click `Clear all lines` button.
const handleClickClearLines = () => { const handleClickClearLines = useCallback(() => {
formik.setFieldValue( setFieldValue(
'entries', 'entries',
reorderingEntriesIndex([...repeatValue(defaultEntry, 4)]), reorderingEntriesIndex([...repeatValue(defaultEntry, 4)]),
); );
}; }, [defaultEntry, setFieldValue]);
// Handle journal number field change.
const handleJournalNumberChanged = useCallback(
(journalNumber) => {
changePageSubtitle(`No. ${journalNumber}`);
},
[changePageSubtitle],
);
return ( return (
<div class="make-journal-entries"> <div class="make-journal-entries">
<form onSubmit={formik.handleSubmit}> <form onSubmit={handleSubmit}>
<MakeJournalEntriesHeader formik={formik} /> <MakeJournalEntriesHeader
errors={errors}
touched={touched}
values={values}
setFieldValue={setFieldValue}
getFieldProps={getFieldProps}
onJournalNumberChanged={handleJournalNumberChanged}
/>
<MakeJournalEntriesTable <MakeJournalEntriesTable
values={formik.values.entries} values={values.entries}
formik={formik} errors={errors}
setFieldValue={setFieldValue}
defaultRow={defaultEntry} defaultRow={defaultEntry}
onClickClearAllLines={handleClickClearLines} onClickClearAllLines={handleClickClearLines}
onClickAddNewRow={handleClickAddNewRow} onClickAddNewRow={handleClickAddNewRow}
/> />
<MakeJournalEntriesFooter <MakeJournalEntriesFooter
formik={formik} isSubmitting={isSubmitting}
onSubmitClick={handleSubmitClick} onSubmitClick={handleSubmitClick}
onCancelClick={handleCancelClick} onCancelClick={handleCancelClick}
manualJournal={manualJournal} manualJournal={manualJournalId}
/> />
</form> </form>
@@ -449,15 +480,15 @@ function MakeJournalEntriesForm({
export default compose( export default compose(
withJournalsActions, withJournalsActions,
withManualJournalDetail, withManualJournalDetail,
withManualJournals(({ nextJournalNumberChanged }) => ({ withManualJournals(({ journalNumberChanged }) => ({
nextJournalNumberChanged, journalNumberChanged,
})), })),
withAccountsActions, withAccountsActions,
withDashboardActions, withDashboardActions,
withMediaActions, withMediaActions,
withSettings(({ manualJournalsSettings }) => ({ withSettings(({ manualJournalsSettings }) => ({
journalNextNumber: manualJournalsSettings.nextNumber, journalNextNumber: manualJournalsSettings.nextNumber,
journalNumberPrefix: manualJournalsSettings.numberPrefix journalNumberPrefix: manualJournalsSettings.numberPrefix,
})), })),
withManualJournalsActions, withManualJournalsActions,
)(MakeJournalEntriesForm); )(MakeJournalEntriesForm);

View File

@@ -11,7 +11,7 @@ import { FormattedMessage as T } from 'react-intl';
import { Row, Col } from 'react-grid-system'; import { Row, Col } from 'react-grid-system';
import moment from 'moment'; import moment from 'moment';
import classNames from 'classnames'; import classNames from 'classnames';
import { momentFormatter, tansformDateValue } from 'utils'; import { momentFormatter, tansformDateValue, saveInvoke } from 'utils';
import { import {
CurrenciesSelectList, CurrenciesSelectList,
ErrorMessage, ErrorMessage,
@@ -27,7 +27,14 @@ import withDialogActions from 'containers/Dialog/withDialogActions';
import { compose } from 'utils'; import { compose } from 'utils';
function MakeJournalEntriesHeader({ function MakeJournalEntriesHeader({
formik: { errors, touched, values, setFieldValue, getFieldProps }, errors,
touched,
values,
setFieldValue,
getFieldProps,
// #ownProps
onJournalNumberChanged,
// #withDialog // #withDialog
openDialog, openDialog,
@@ -43,6 +50,11 @@ function MakeJournalEntriesHeader({
openDialog('journal-number-form', {}); openDialog('journal-number-form', {});
}, [openDialog]); }, [openDialog]);
// Handle journal number field blur event.
const handleJournalNumberChanged = (event) => {
saveInvoke(onJournalNumberChanged, event.currentTarget.value);
};
return ( return (
<div class="make-journal-entries__header"> <div class="make-journal-entries__header">
<Row> <Row>
@@ -82,6 +94,7 @@ function MakeJournalEntriesHeader({
}} }}
/>} />}
{...getFieldProps('journal_number')} {...getFieldProps('journal_number')}
onBlur={handleJournalNumberChanged}
/> />
</FormGroup> </FormGroup>
</Col> </Col>

View File

@@ -36,7 +36,10 @@ function MakeJournalEntriesPage({
requestFetchCustomers(), requestFetchCustomers(),
); );
const fetchSettings = useQuery(['settings'], () => requestFetchOptions({})); const fetchSettings = useQuery(
['settings'],
() => requestFetchOptions({}),
);
const fetchJournal = useQuery( const fetchJournal = useQuery(
['manual-journal', id], ['manual-journal', id],

View File

@@ -103,7 +103,7 @@ function MakeJournalEntriesTable({
onClickClearAllLines, onClickClearAllLines,
defaultRow, defaultRow,
values, values,
formik: { errors, setFieldValue }, errors, setFieldValue,
}) { }) {
const [rows, setRows] = useState([]); const [rows, setRows] = useState([]);
const { formatMessage } = useIntl(); const { formatMessage } = useIntl();

View File

@@ -20,7 +20,7 @@ export default (mapState) => {
manualJournalsPagination: getManualJournalsPagination(state, props, query), manualJournalsPagination: getManualJournalsPagination(state, props, query),
manualJournalsLoading: state.manualJournals.loading, manualJournalsLoading: state.manualJournals.loading,
nextJournalNumberChanged: state.manualJournals.nextJournalNumberChanged, journalNumberChanged: state.manualJournals.journalNumberChanged,
}; };
return mapState ? mapState(mapped, state, props) : mapped; return mapState ? mapState(mapped, state, props) : mapped;
}; };

View File

@@ -1,13 +1,14 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { getCustomersItems } from 'store/customers/customers.selectors'; import { getCustomersItems, getCustomersListFactory } from 'store/customers/customers.selectors';
import { getResourceViews } from 'store/customViews/customViews.selectors'; import { getResourceViews } from 'store/customViews/customViews.selectors';
export default (mapState) => { export default (mapState) => {
const mapStateToProps = (state, props) => { const getCustomersList = getCustomersListFactory();
const mapStateToProps = (state, props) => {
const mapped = { const mapped = {
customersViews: getResourceViews(state, props, 'customers'), customersViews: getResourceViews(state, props, 'customers'),
customersItems: Object.values(state.customers.items), customersItems: getCustomersList(state, props),
customers: getCustomersItems(state, state.customers.currentViewId), customers: getCustomersItems(state, state.customers.currentViewId),
customersLoading: state.customers.loading, customersLoading: state.customers.loading,
customerErrors: state.customers.errors, customerErrors: state.customers.errors,

View File

@@ -1,4 +1,4 @@
import React from 'react'; import React, { useState, useCallback, useEffect } from 'react';
import { DialogContent } from 'components'; import { DialogContent } from 'components';
import { useQuery, queryCache } from 'react-query'; import { useQuery, queryCache } from 'react-query';
@@ -29,29 +29,40 @@ function JournalNumberDialogContent({
// #withManualJournalsActions // #withManualJournalsActions
setJournalNumberChanged, setJournalNumberChanged,
}) { }) {
const fetchSettings = useQuery(['settings'], () => requestFetchOptions({})); const [isChanged, setIsChanged] = useState(false);
const fetchSettings = useQuery(
['settings', { group: 'manual_journal' }],
() => requestFetchOptions({}),
{
onSuccess: () => {
if (isChanged) {
setJournalNumberChanged(true);
setIsChanged(false);
}
}
}
);
const handleSubmitForm = (values, { setSubmitting }) => { const handleSubmitForm = (values, { setSubmitting }) => {
const options = optionsMapToArray(values).map((option) => { const options = optionsMapToArray(values).map((option) => ({
return { key: option.key, ...option, group: 'manual_journals' }; key: option.key, ...option, group: 'manual_journals',
}); }));
requestSubmitOptions({ options }).then(() => { requestSubmitOptions({ options }).then(() => {
setSubmitting(false); setSubmitting(false);
closeDialog('journal-number-form'); setIsChanged(true);
setJournalNumberChanged(true);
setTimeout(() => { queryCache.invalidateQueries('settings');
queryCache.invalidateQueries('settings'); closeDialog('journal-number-form');
}, 250);
}).catch(() => { }).catch(() => {
setSubmitting(false); setSubmitting(false);
}); });
}; };
const handleClose = () => { const handleClose = useCallback(() => {
closeDialog('journal-number-form'); closeDialog('journal-number-form');
}; }, [closeDialog]);
return ( return (
<DialogContent isLoading={fetchSettings.isFetching}> <DialogContent isLoading={fetchSettings.isFetching}>
@@ -62,15 +73,15 @@ function JournalNumberDialogContent({
onClose={handleClose} onClose={handleClose}
/> />
</DialogContent> </DialogContent>
) );
} }
export default compose( export default compose(
withDialogActions, withDialogActions,
withSettingsActions, withSettingsActions,
withSettings(({ manualJournalsSettings }) => ({ withSettings(({ manualJournalsSettings }) => ({
nextNumber: manualJournalsSettings?.next_number, nextNumber: manualJournalsSettings?.nextNumber,
numberPrefix: manualJournalsSettings?.number_prefix, numberPrefix: manualJournalsSettings?.numberPrefix,
})), })),
withManualJournalsActions, withManualJournalsActions,
)(JournalNumberDialogContent); )(JournalNumberDialogContent);

View File

@@ -17,3 +17,10 @@ export const getCustomersItems = createSelector(
: []; : [];
}, },
); );
export const getCustomersListFactory = () => createSelector(
customersItemsSelector,
(customersItems) => {
return Object.values(customersItems);
}
);

View File

@@ -0,0 +1,7 @@
export const journalNumberReducers = (type) => ({
[type]: (state, action) => {
const { isChanged } = action.payload;
state.journalNumberChanged = isChanged;
},
});

View File

@@ -2,6 +2,7 @@ import t from 'store/types';
import { createReducer } from '@reduxjs/toolkit'; import { createReducer } from '@reduxjs/toolkit';
import { createTableQueryReducers } from 'store/queryReducers'; import { createTableQueryReducers } from 'store/queryReducers';
import { omit } from 'lodash'; import { omit } from 'lodash';
import { journalNumberReducers } from 'store/journalNumber.reducer';
const initialState = { const initialState = {
items: {}, items: {},
@@ -15,7 +16,7 @@ const initialState = {
paginationMeta: { paginationMeta: {
total: 0, total: 0,
}, },
nextJournalNumberChanged: false, journalNumberChanged: false,
}; };
const defaultJournal = { const defaultJournal = {
@@ -117,10 +118,7 @@ const reducer = createReducer(initialState, {
}; };
}, },
[t.MANUAL_JOURNAL_NUMBER_CHANGED]: (state, action) => { ...journalNumberReducers(t.MANUAL_JOURNAL_NUMBER_CHANGED),
const { isChanged } = action.payload;
state.nextJournalNumberChanged = isChanged;
}
}); });
export default createTableQueryReducers('manual_journals', reducer); export default createTableQueryReducers('manual_journals', reducer);

View File

@@ -274,3 +274,7 @@ export const transformToObject = (arr, key) => {
export const itemsStartWith = (items, char) => { export const itemsStartWith = (items, char) => {
return items.filter((item) => item.indexOf(char) === 0); return items.filter((item) => item.indexOf(char) === 0);
}; };
export const saveInvoke = (func, ...rest) => {
return func && func(...rest);
}

View File

@@ -249,7 +249,11 @@ export default class ItemsController extends BaseController {
filter.filterRoles = JSON.parse(filter.stringifiedFilterRoles); filter.filterRoles = JSON.parse(filter.stringifiedFilterRoles);
} }
try { try {
const { items, pagination, filterMeta } = await this.itemsService.itemsList(tenantId, filter); const {
items,
pagination,
filterMeta
} = await this.itemsService.itemsList(tenantId, filter);
return res.status(200).send({ return res.status(200).send({
items, items,

View File

@@ -338,7 +338,6 @@ export default class BillsController extends BaseController {
}); });
} }
} }
console.log(error.errorType);
next(error); next(error);
} }
} }