feat: Financial statements enhancement.

This commit is contained in:
Ahmed Bouhuolia
2020-06-17 22:06:33 +02:00
parent 5c43f902e3
commit 3e15cd42c8
75 changed files with 1308 additions and 593 deletions

View File

@@ -121,6 +121,17 @@ function ExpenseDataTable({
[handleEditExpense, handleDeleteExpense, handlePublishExpense],
);
const expenseAccountAccessor = (expense) => {
if (expense.categories.length === 1) {
return expense.categories[0].expense_account.name;
} else if (expense.categories.length > 1) {
const mutliCategories = expense.categories.map(category =>
(<div>- {category.expense_account.name} ${ category.amount }</div>)
);
return <Tooltip content={mutliCategories}>{ '- Multi Categories -' }</Tooltip>;
}
}
const columns = useMemo(
() => [
{
@@ -155,11 +166,10 @@ function ExpenseDataTable({
{
id: 'expense_account_id',
Header: formatMessage({ id: 'expense_account' }),
accessor:'expense_account_id',
accessor: expenseAccountAccessor,
width: 150,
className: 'expense_account',
},
{
id: 'publish',
Header: formatMessage({ id: 'publish' }),

View File

@@ -12,10 +12,11 @@ import { Intent, FormGroup, TextArea } from '@blueprintjs/core';
import { FormattedMessage as T, useIntl } from 'react-intl';
import { pick } from 'lodash';
import { useQuery } from 'react-query';
import { Col, Row } from 'react-grid-system';
import ExpenseFormHeader from './ExpenseFormHeader';
import ExpenseTable from './ExpenseTable';
import ExpenseFooter from './ExpenseFooter';
import ExpenseFloatingFooter from './ExpenseFooter';
import withExpensesActions from 'containers/Expenses/withExpensesActions';
import withExpneseDetail from 'containers/Expenses/withExpenseDetail';
@@ -76,11 +77,11 @@ function ExpenseForm({
useEffect(() => {
if (expenseDetail && expenseDetail.id) {
changePageTitle(formatMessage({ id: 'edit_expense' }));
changePageSubtitle(`No. ${expenseDetail.payment_account_id}`);
// changePageSubtitle(`No. ${expenseDetail.payment_account_id}`);
} else {
changePageTitle(formatMessage({ id: 'new_expense' }));
}
// @todo not functions just states.
// @todo not functions just states.
}, [changePageTitle, changePageSubtitle, expenseDetail, formatMessage]);
const validationSchema = Yup.object().shape({
@@ -137,7 +138,6 @@ function ExpenseForm({
reference_no: '',
currency_code: '',
categories: [
// @todo @mohamed index
defaultCategory,
defaultCategory,
defaultCategory,
@@ -154,7 +154,8 @@ function ExpenseForm({
...pick(expenseDetail, Object.keys(defaultInitialValues)),
categories: expenseDetail.categories.map((category) => ({
...pick(category, Object.keys(defaultCategory)),
})),
}),
),
}
: {
...defaultInitialValues,
@@ -257,7 +258,7 @@ function ExpenseForm({
},
});
console.log(formik.errors);
console.log(formik.values, 'VALUES');
const handleSubmitClick = useCallback(
(payload) => {
@@ -298,29 +299,32 @@ function ExpenseForm({
defaultRow={defaultCategory}
/>
<FormGroup
label={<T id={'description'} />}
className={'form-group--description'}
>
<TextArea
growVertically={true}
large={true}
{...formik.getFieldProps('description')}
/>
</FormGroup>
<div class="expense-form-footer">
<FormGroup
label={<T id={'description'} />}
className={'form-group--description'}
>
<TextArea
growVertically={true}
large={true}
{...formik.getFieldProps('description')}
/>
</FormGroup>
<ExpenseFooter
<Dragzone
initialFiles={initialAttachmentFiles}
onDrop={handleDropFiles}
onDeleteFile={handleDeleteFile}
hint={'Attachments: Maxiumum size: 20MB'}
/>
</div>
<ExpenseFloatingFooter
formik={formik}
onSubmitClick={handleSubmitClick}
onCancelClick={handleCancelClick}
/>
</form>
<Dragzone
initialFiles={initialAttachmentFiles}
onDrop={handleDropFiles}
onDeleteFile={handleDeleteFile}
hint={'Attachments: Maxiumum size: 20MB'}
/>
</div>
);
}

View File

@@ -117,7 +117,7 @@ function ExpenseFormHeader({
return (
<div className={'dashboard__insider--expense-form__header'}>
<Row>
<Col sm={3.5}>
<Col width={300}>
<FormGroup
label={<T id={'beneficiary'} />}
className={classNames('form-group--select-list', Classes.FILL)}
@@ -141,7 +141,8 @@ function ExpenseFormHeader({
/>
</FormGroup>
</Col>
<Col sm={3}>
<Col width={400}>
<FormGroup
label={<T id={'payment_account'} />}
className={classNames(
@@ -177,8 +178,9 @@ function ExpenseFormHeader({
</FormGroup>
</Col>
</Row>
<Row>
<Col sm={3.5}>
<Col width={300}>
<FormGroup
label={<T id={'payment_date'} />}
labelInfo={infoIcon}
@@ -189,17 +191,17 @@ function ExpenseFormHeader({
helperText={
<ErrorMessage name="payment_date" {...{ errors, touched }} />
}
minimal={true}
>
<DateInput
{...momentFormatter('YYYY/MM/DD')}
defaultValue={new Date()}
onChange={handleDateChange}
popoverProps={{ position: Position.BOTTOM }}
popoverProps={{ position: Position.BOTTOM, minimal: true }}
/>
</FormGroup>
</Col>
<Col sm={2}>
<Col width={200}>
<FormGroup
label={<T id={'currency'} />}
className={classNames(
@@ -223,23 +225,25 @@ function ExpenseFormHeader({
onItemSelect={onItemsSelect('currency_code')}
selectedItem={values.currency_code}
selectedItemProp={'currency_code'}
defaultText={<T id={'select_currency_code'} />}
defaultText={<T id={'select_currency'} />}
labelProp={'currency_code'}
/>
</FormGroup>
</Col>
<Col sm={3}>
<Col width={200}>
<FormGroup
label={<T id={'ref_no'} />}
className={'form-group--ref_no'}
className={classNames(
'form-group--ref_no',
Classes.FILL,
)}
intent={
errors.reference_no && touched.reference_no && Intent.DANGER
}
helperText={
<ErrorMessage name="reference_no" {...{ errors, touched }} />
}
minimal={true}
>
<InputGroup
intent={

View File

@@ -1,9 +1,10 @@
import React, { useState, useMemo, useEffect, useCallback } from 'react';
import { Button, Intent } from '@blueprintjs/core';
import { Button, Intent, Position, Tooltip } from '@blueprintjs/core';
import { FormattedMessage as T, useIntl } from 'react-intl';
import DataTable from 'components/DataTable';
import Icon from 'components/Icon';
import { Hint } from 'components';
import { compose, formattedAmount } from 'utils';
import {
AccountsListFieldCell,
@@ -88,14 +89,16 @@ function ExpenseTable({
payload.removeRow(index);
};
return (
<Button
icon={<Icon icon="times-circle" iconSize={14} />}
iconSize={14}
className="ml2"
minimal={true}
intent={Intent.DANGER}
onClick={onClickRemoveRole}
/>
<Tooltip content={<T id={'remove_the_line'} />} position={Position.LEFT}>
<Button
icon={<Icon icon="times-circle" iconSize={14} />}
iconSize={14}
className="ml2"
minimal={true}
intent={Intent.DANGER}
onClick={onClickRemoveRole}
/>
</Tooltip>
);
};
@@ -144,8 +147,7 @@ function ExpenseTable({
disableSortBy: true,
},
{
// @todo Add hint component after the header label.
Header: formatMessage({ id: 'expense_category' }),
Header: (<>{ formatMessage({ id: 'expense_category' }) }<Hint /></>),
id: 'expense_account_id',
accessor: 'expense_account_id',
Cell: TotalExpenseCellRenderer(AccountsListFieldCell),
@@ -161,6 +163,7 @@ function ExpenseTable({
disableSortBy: true,
disableResizing: true,
width: 150,
className: 'amount',
},
{
Header: formatMessage({ id: 'description' }),
@@ -195,7 +198,6 @@ function ExpenseTable({
[rows],
);
return (
<div className={'dashboard__insider--expense-form__table'}>
<DataTable
@@ -235,5 +237,4 @@ export default compose(
withAccounts(({ accounts }) => ({
accounts,
})),
)(ExpenseTable);

View File

@@ -12,6 +12,7 @@ import ExpenseDataTable from 'containers/Expenses/ExpenseDataTable';
import ExpenseActionsBar from 'containers/Expenses/ExpenseActionsBar';
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
import withExpenses from 'containers/Expenses/withExpenses';
import withExpensesActions from 'containers/Expenses/withExpensesActions';
import withViewsActions from 'containers/Views/withViewsActions';
@@ -24,6 +25,9 @@ function ExpensesList({
// #withViewsActions
requestFetchResourceViews,
// #withExpenses
expensesTableQuery,
//#withExpensesActions
requestFetchExpensesTable,
requestDeleteExpense,
@@ -44,8 +48,9 @@ function ExpensesList({
return requestFetchResourceViews('expenses');
});
const fetchExpenses = useQuery('expenses-table', () =>
requestFetchExpensesTable(),
const fetchExpenses = useQuery(
['expenses-table', expensesTableQuery],
() => requestFetchExpensesTable(),
);
useEffect(() => {
@@ -53,7 +58,6 @@ function ExpensesList({
}, [changePageTitle, formatMessage]);
// Handle delete expense click.
const handleDeleteExpense = useCallback(
(expnese) => {
setDeleteExpense(expnese);
@@ -108,8 +112,6 @@ function ExpensesList({
.catch((error) => {
setBulkDelete(false);
});
// @todo
}, [requestDeleteBulkExpenses, bulkDelete, formatMessage, selectedRowsCount]);
// Handle cancel bulk delete alert.
@@ -149,6 +151,7 @@ function ExpensesList({
message: formatMessage({ id: 'the_expense_id_has_been_published' }),
});
});
fetchExpenses.refetch();
},
[requestPublishExpense, formatMessage],
);
@@ -163,7 +166,7 @@ function ExpensesList({
return (
<DashboardInsider
loading={fetchViews.isFetching || fetchExpenses.isFetching}
loading={fetchViews.isFetching}
name={'expenses'}
>
<ExpenseActionsBar
@@ -232,5 +235,6 @@ function ExpensesList({
export default compose(
withDashboardActions,
withExpensesActions,
withExpenses(({ expensesTableQuery }) => ({ expensesTableQuery })),
withViewsActions,
)(ExpensesList);