Merge branch 'feature/manual-journals' of https://github.com/abouolia/Ratteb

This commit is contained in:
Ahmed Bouhuolia
2020-04-09 01:30:18 +02:00
27 changed files with 869 additions and 103 deletions

View File

@@ -7,6 +7,8 @@ import { FormattedList } from 'react-intl';
export default function MakeJournalEntriesFooter({
formik,
onSubmitClick,
onCancelClick,
}) {
return (
<div>
@@ -14,28 +16,38 @@ export default function MakeJournalEntriesFooter({
<Button
disabled={formik.isSubmitting}
intent={Intent.PRIMARY}
type="submit">
name={'save'}
onClick={() => {
onSubmitClick({ publish: true, redirect: true });
}}>
Save
</Button>
<Button
disabled={formik.isSubmitting}
intent={Intent.PRIMARY}
type="submit"
className={'ml1'}>
className={'ml1'}
name={'save_and_new'}
onClick={() => {
onSubmitClick({ publish: true, redirect: false });
}}>
Save & New
</Button>
<Button
disabled={formik.isSubmitting}
type="submit"
className={'button-secondary ml1'}>
className={'button-secondary ml1'}
onClick={() => {
onSubmitClick({ publish: false, redirect: false });
}}>
Save as Draft
</Button>
<Button
type="submit"
className={'button-secondary ml1'}>
className={'button-secondary ml1'}
onClick={() => {
onCancelClick && onCancelClick();
}}>
Cancel
</Button>
</div>

View File

@@ -1,6 +1,4 @@
import React, {useMemo, useEffect} from 'react';
import React, {useMemo, useState, useEffect, useCallback} from 'react';
import * as Yup from 'yup';
import MakeJournalEntriesHeader from './MakeJournalEntriesHeader';
import MakeJournalEntriesFooter from './MakeJournalEntriesFooter';
@@ -10,10 +8,9 @@ import MakeJournalEntriesConnect from 'connectors/MakeJournalEntries.connect';
import AccountsConnect from 'connectors/Accounts.connector';
import DashboardConnect from 'connectors/Dashboard.connector';
import {compose} from 'utils';
import useAsync from 'hooks/async';
import moment from 'moment';
import AppToaster from 'components/AppToaster';
import {pick, omit} from 'lodash';
import {pick} from 'lodash';
function MakeJournalEntriesForm({
requestMakeJournalEntries,
@@ -21,6 +18,8 @@ function MakeJournalEntriesForm({
changePageTitle,
changePageSubtitle,
editJournal,
onFormSubmit,
onCancelForm,
}) {
useEffect(() => {
if (editJournal && editJournal.id) {
@@ -49,6 +48,12 @@ function MakeJournalEntriesForm({
)
});
const saveInvokeSubmit = useCallback((payload) => {
onFormSubmit && onFormSubmit(payload)
}, [onFormSubmit]);
const [payload, setPayload] = useState({});
const defaultEntry = useMemo(() => ({
account_id: null,
credit: 0,
@@ -83,11 +88,11 @@ function MakeJournalEntriesForm({
}
},
onSubmit: (values, actions) => {
const form = values.entries.filter((entry) => (
const entries = values.entries.filter((entry) => (
(entry.credit || entry.debit)
));
const getTotal = (type = 'credit') => {
return form.reduce((total, item) => {
return entries.reduce((total, item) => {
return item[type] ? item[type] + total : total;
}, 0);
}
@@ -101,24 +106,27 @@ function MakeJournalEntriesForm({
actions.setSubmitting(false);
return;
}
const form = { ...values, status: payload.publish, entries };
if (editJournal && editJournal.id) {
requestEditManualJournal(editJournal.id, { ...values, entries: form })
requestEditManualJournal(editJournal.id, form)
.then((response) => {
AppToaster.show({
message: 'manual_journal_has_been_edited',
});
actions.setSubmitting(false);
saveInvokeSubmit({ action: 'update', ...payload });
}).catch((error) => {
actions.setSubmitting(false);
});
} else {
requestMakeJournalEntries({ ...values, entries: form })
requestMakeJournalEntries(form)
.then((response) => {
AppToaster.show({
message: 'manual_journal_has_been_submit',
});
actions.setSubmitting(false);
saveInvokeSubmit({ action: 'new', ...payload });
}).catch((error) => {
actions.setSubmitting(false);
});
@@ -126,12 +134,24 @@ function MakeJournalEntriesForm({
},
});
const handleSubmitClick = useCallback((payload) => {
setPayload(payload);
formik.handleSubmit();
}, [setPayload, formik]);
const handleCancelClick = useCallback((payload) => {
onCancelForm && onCancelForm(payload);
}, [onCancelForm]);
return (
<div class="make-journal-entries">
<form onSubmit={formik.handleSubmit}>
<MakeJournalEntriesHeader formik={formik} />
<MakeJournalEntriesTable formik={formik} defaultRow={defaultEntry} />
<MakeJournalEntriesFooter formik={formik} />
<MakeJournalEntriesFooter
formik={formik}
onSubmitClick={handleSubmitClick}
onCancelClick={handleCancelClick} />
</form>
</div>
);

View File

@@ -1,13 +1,11 @@
import React, {useMemo, useCallback} from 'react';
import * as Yup from 'yup';
import {
InputGroup,
FormGroup,
Intent,
Position,
} from '@blueprintjs/core';
import {DatePicker, DateInput} from '@blueprintjs/datetime';
import {Formik, useFormik} from "formik";
import {DateInput} from '@blueprintjs/datetime';
import {useIntl} from 'react-intl';
import {Row, Col} from 'react-grid-system';
import moment from 'moment';

View File

@@ -1,5 +1,5 @@
import React, {useMemo} from 'react';
import { useParams } from 'react-router-dom';
import React, {useMemo, useCallback} from 'react';
import { useParams, useHistory } from 'react-router-dom';
import { useAsync } from 'react-use';
import MakeJournalEntriesForm from './MakeJournalEntriesForm';
import LoadingIndicator from 'components/LoadingIndicator';
@@ -13,6 +13,7 @@ function MakeJournalEntriesPage({
getManualJournal,
fetchAccounts,
}) {
const history = useHistory();
const { id } = useParams();
const fetchJournal = useAsync(() => {
@@ -25,9 +26,21 @@ function MakeJournalEntriesPage({
getManualJournal(id) || null,
[getManualJournal, id]);
const handleFormSubmit = useCallback((payload) => {
payload.redirect &&
history.push('/dashboard/accounting/manual-journals');
}, [history]);
const handleCancel = useCallback(() => {
history.push('/dashboard/accounting/manual-journals');
}, [history]);
return (
<LoadingIndicator loading={fetchJournal.loading} mount={false}>
<MakeJournalEntriesForm editJournal={editJournal} />
<MakeJournalEntriesForm
onFormSubmit={handleFormSubmit}
editJournal={editJournal}
onCancelForm={handleCancel} />
</LoadingIndicator>
);
}

View File

@@ -0,0 +1,126 @@
import React, { useEffect, useState, useCallback } from 'react';
import { Route, Switch, useHistory } from 'react-router-dom';
import useAsync from 'hooks/async';
import { Alert, Intent } from '@blueprintjs/core';
import AppToaster from 'components/AppToaster';
import DashboardPageContent from 'components/Dashboard/DashboardPageContent';
import DashboardInsider from 'components/Dashboard/DashboardInsider';
import ManualJournalsViewTabs from 'components/JournalEntry/ManualJournalsViewTabs';
import ManualJournalsDataTable from 'components/JournalEntry/ManualJournalsDataTable';
import DashboardActionsBar from 'components/JournalEntry/ManualJournalActionsBar';
import ManualJournalsConnect from 'connectors/ManualJournals.connect';
import DashboardConnect from 'connectors/Dashboard.connector';
import CustomViewConnect from 'connectors/CustomView.connector';
import ResourceConnect from 'connectors/Resource.connector';
import { compose } from 'utils';
function ManualJournalsTable({
changePageTitle,
fetchResourceViews,
fetchManualJournalsTable,
requestDeleteManualJournal,
requestPublishManualJournal,
}) {
const history = useHistory();
const [deleteManualJournal, setDeleteManualJournal] = useState(false);
const fetchHook = useAsync(async () => {
await Promise.all([
fetchResourceViews('manual_journals'),
]);
});
const fetchManualJournalsHook = useAsync(async () => {
return fetchManualJournalsTable();
}, false);
useEffect(() => {
changePageTitle('Manual Journals');
}, []);
const handleCancelManualJournalDelete = () => {
setDeleteManualJournal(false);
};
const handleConfirmManualJournalDelete = useCallback(() => {
requestDeleteManualJournal(deleteManualJournal.id).then(() => {
setDeleteManualJournal(false);
AppToaster.show({ message: 'the_manual_Journal_has_been_deleted' });
});
}, [deleteManualJournal, requestDeleteManualJournal]);
const handleEditJournal = useCallback((journal) => {
history.push(`/dashboard/accounting/manual-journals/${journal.id}/edit`);
}, [history]);
const handleDeleteJournal = useCallback((journal) => {
setDeleteManualJournal(journal);
}, []);
const handleFilterChanged = useCallback(() => {
fetchManualJournalsHook.execute();
}, []);
const handleViewChanged = useCallback(() => {
fetchManualJournalsHook.execute();
}, []);
const handleFetchData = useCallback(() => {
fetchManualJournalsHook.execute();
}, []);
const handlePublishJournal = useCallback((journal) => {
requestPublishManualJournal(journal.id).then(() => {
AppToaster.show({ message: 'the_manual_journal_id_has_been_published' });
})
}, [requestPublishManualJournal]);
return (
<DashboardInsider loading={fetchHook.pending} name={'manual-journals'}>
<DashboardActionsBar
onFilterChanged={handleFilterChanged} />
<DashboardPageContent>
<Switch>
<Route
exact={true}
path={[
'/dashboard/accounting/manual-journals/:custom_view_id/custom_view',
'/dashboard/accounting/manual-journals',
]}>
<ManualJournalsViewTabs
onViewChanged={handleViewChanged} />
</Route>
</Switch>
<ManualJournalsDataTable
onDeleteJournal={handleDeleteJournal}
onFetchData={handleFetchData}
onEditJournal={handleEditJournal}
onPublishJournal={handlePublishJournal} />
<Alert
cancelButtonText='Cancel'
confirmButtonText='Move to Trash'
icon='trash'
intent={Intent.DANGER}
isOpen={deleteManualJournal}
onCancel={handleCancelManualJournalDelete}
onConfirm={handleConfirmManualJournalDelete}
>
<p>
Are you sure you want to move <b>filename</b> to Trash? You will be
able to restore it later, but it will become private to you.
</p>
</Alert>
</DashboardPageContent>
</DashboardInsider>
);
}
export default compose(
ManualJournalsConnect,
CustomViewConnect,
ResourceConnect,
DashboardConnect
)(ManualJournalsTable);