mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-19 06:10:31 +00:00
feat: Financial statements enhancement.
This commit is contained in:
51
client/src/components/ContactsListField.js
Normal file
51
client/src/components/ContactsListField.js
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import React, { useCallback, useState } from 'react';
|
||||||
|
import {
|
||||||
|
MenuItem,
|
||||||
|
Button,
|
||||||
|
} from '@blueprintjs/core';
|
||||||
|
import ListSelect from 'components/ListSelect';
|
||||||
|
import { FormattedMessage as T } from 'react-intl';
|
||||||
|
|
||||||
|
export default function ContactsListField({
|
||||||
|
contacts,
|
||||||
|
onContactSelected,
|
||||||
|
error,
|
||||||
|
initialContact,
|
||||||
|
defautlSelectText = (<T id={'select_contact'} />)
|
||||||
|
}) {
|
||||||
|
const [selectedContact, setSelectedContact] = useState(
|
||||||
|
initialContact || null
|
||||||
|
);
|
||||||
|
|
||||||
|
const contactTypeLabel = (contactType) => {
|
||||||
|
switch(contactType) {
|
||||||
|
case 'customer':
|
||||||
|
return 'Customer';
|
||||||
|
case 'vendor':
|
||||||
|
return 'Vendor';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// Contact item of select accounts field.
|
||||||
|
const contactItem = useCallback((item, { handleClick, modifiers, query }) => (
|
||||||
|
<MenuItem text={item.display_name} label={contactTypeLabel(item.contact_type)} key={item.id} onClick={handleClick} />
|
||||||
|
), []);
|
||||||
|
|
||||||
|
const onContactSelect = useCallback((contact) => {
|
||||||
|
setSelectedContact(contact.id);
|
||||||
|
onContactSelected && onContactSelected(contact.id);
|
||||||
|
}, [setSelectedContact, onContactSelected]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ListSelect
|
||||||
|
items={contacts}
|
||||||
|
noResults={<MenuItem disabled={true} text='No results.' />}
|
||||||
|
itemRenderer={contactItem}
|
||||||
|
popoverProps={{ minimal: true }}
|
||||||
|
filterable={true}
|
||||||
|
onItemSelect={onContactSelect}
|
||||||
|
labelProp={'display_name'}
|
||||||
|
selectedItem={selectedContact}
|
||||||
|
selectedItemProp={'id'}
|
||||||
|
defaultText={defautlSelectText} />
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -7,6 +7,8 @@ import {
|
|||||||
NavbarDivider,
|
NavbarDivider,
|
||||||
Button,
|
Button,
|
||||||
Classes,
|
Classes,
|
||||||
|
Tooltip,
|
||||||
|
Position,
|
||||||
} from '@blueprintjs/core';
|
} from '@blueprintjs/core';
|
||||||
import { FormattedMessage as T } from 'react-intl';
|
import { FormattedMessage as T } from 'react-intl';
|
||||||
|
|
||||||
@@ -56,25 +58,27 @@ function DashboardTopbar({
|
|||||||
<div class='dashboard__topbar'>
|
<div class='dashboard__topbar'>
|
||||||
<div class='dashboard__topbar-left'>
|
<div class='dashboard__topbar-left'>
|
||||||
<div class='dashboard__topbar-sidebar-toggle'>
|
<div class='dashboard__topbar-sidebar-toggle'>
|
||||||
<Button minimal={true} onClick={handleSidebarToggleBtn}>
|
<Tooltip content={<T id={'close_sidebar'} />} position={Position.RIGHT}>
|
||||||
<svg
|
<Button minimal={true} onClick={handleSidebarToggleBtn}>
|
||||||
xmlns='http://www.w3.org/2000/svg'
|
<svg
|
||||||
width='20'
|
xmlns='http://www.w3.org/2000/svg'
|
||||||
height='20'
|
width='20'
|
||||||
viewBox='0 0 20 20'
|
height='20'
|
||||||
role='img'
|
viewBox='0 0 20 20'
|
||||||
focusable='false'
|
role='img'
|
||||||
>
|
focusable='false'
|
||||||
<title><T id={'menu'}/></title>
|
>
|
||||||
<path
|
<title><T id={'menu'}/></title>
|
||||||
stroke='currentColor'
|
<path
|
||||||
stroke-linecap='round'
|
stroke='currentColor'
|
||||||
stroke-miterlimit='5'
|
stroke-linecap='round'
|
||||||
stroke-width='2'
|
stroke-miterlimit='5'
|
||||||
d='M4 7h15M4 12h15M4 17h15'
|
stroke-width='2'
|
||||||
></path>
|
d='M4 7h15M4 12h15M4 17h15'
|
||||||
</svg>
|
></path>
|
||||||
</Button>
|
</svg>
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class='dashboard__title'>
|
<div class='dashboard__title'>
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import React, { useCallback, useMemo } from 'react';
|
||||||
|
import { FormGroup, Classes } from "@blueprintjs/core";
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import ContactsListField from 'components/ContactsListField';
|
||||||
|
|
||||||
|
export default function ContactsListCellRenderer({
|
||||||
|
column: { id, value },
|
||||||
|
row: { index, original },
|
||||||
|
cell: { value: initialValue },
|
||||||
|
payload: { contacts, updateData, errors }
|
||||||
|
}) {
|
||||||
|
const handleContactSelected = useCallback((contactId) => {
|
||||||
|
updateData(index, id, contactId)
|
||||||
|
}, [updateData, index, id]);
|
||||||
|
|
||||||
|
const initialContact = useMemo(() => {
|
||||||
|
return contacts.find(c => c.id === initialValue);
|
||||||
|
}, [contacts, initialValue]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormGroup
|
||||||
|
className={classNames(
|
||||||
|
'form-group--select-list',
|
||||||
|
'form-group--contacts-list',
|
||||||
|
Classes.FILL,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<ContactsListField
|
||||||
|
contacts={contacts}
|
||||||
|
onContactSelected={handleContactSelected}
|
||||||
|
initialContact={initialContact}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
import AccountsListFieldCell from './AccountsListFieldCell';
|
import AccountsListFieldCell from './AccountsListFieldCell';
|
||||||
import MoneyFieldCell from './MoneyFieldCell';
|
import MoneyFieldCell from './MoneyFieldCell';
|
||||||
import InputGroupCell from './InputGroupCell';
|
import InputGroupCell from './InputGroupCell';
|
||||||
|
import ContactsListFieldCell from './ContactsListFieldCell';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
AccountsListFieldCell,
|
AccountsListFieldCell,
|
||||||
MoneyFieldCell,
|
MoneyFieldCell,
|
||||||
InputGroupCell,
|
InputGroupCell,
|
||||||
|
ContactsListFieldCell,
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,8 @@ import Icon from './Icon';
|
|||||||
|
|
||||||
export default function FieldHint({ hint }) {
|
export default function FieldHint({ hint }) {
|
||||||
return (
|
return (
|
||||||
<Icon icon="info-circle" iconSize={12} />
|
<span class="hint">
|
||||||
|
<Icon icon="info-circle" iconSize={12} />
|
||||||
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
7
client/src/components/MenuItemLabel.js
Normal file
7
client/src/components/MenuItemLabel.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export default function MenuItemLabel({
|
||||||
|
text
|
||||||
|
}) {
|
||||||
|
return (<span class="bp3-menu-item-label">{ text }</span>);
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import { useHistory, useLocation } from 'react-router-dom';
|
|||||||
import sidebarMenuList from 'config/sidebarMenu';
|
import sidebarMenuList from 'config/sidebarMenu';
|
||||||
import Icon from 'components/Icon';
|
import Icon from 'components/Icon';
|
||||||
import MenuItem from 'components/MenuItem';
|
import MenuItem from 'components/MenuItem';
|
||||||
|
import { MenuItemLabel } from 'components';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
export default function SidebarMenu() {
|
export default function SidebarMenu() {
|
||||||
@@ -29,6 +30,8 @@ export default function SidebarMenu() {
|
|||||||
<div class="bp3-menu-spacer"></div>
|
<div class="bp3-menu-spacer"></div>
|
||||||
) : item.divider ? (
|
) : item.divider ? (
|
||||||
<MenuDivider key={index} title={item.title} />
|
<MenuDivider key={index} title={item.title} />
|
||||||
|
) : item.label ? (
|
||||||
|
<MenuItemLabel key={index} text={item.text} />
|
||||||
) : (
|
) : (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
key={index}
|
key={index}
|
||||||
|
|||||||
@@ -2,16 +2,20 @@ import If from './Utils/If';
|
|||||||
import Money from './Money';
|
import Money from './Money';
|
||||||
import Icon from './Icon';
|
import Icon from './Icon';
|
||||||
import Choose from './Utils/Choose';
|
import Choose from './Utils/Choose';
|
||||||
// import For from './Utils/For';
|
import For from './Utils/For';
|
||||||
import ListSelect from './ListSelect';
|
import ListSelect from './ListSelect';
|
||||||
import FinancialStatement from './FinancialStatement';
|
import FinancialStatement from './FinancialStatement';
|
||||||
import DynamicFilterValueField from './DynamicFilter/DynamicFilterValueField';
|
import DynamicFilterValueField from './DynamicFilter/DynamicFilterValueField';
|
||||||
import ErrorMessage from './ErrorMessage';
|
import ErrorMessage from './ErrorMessage';
|
||||||
import MODIFIER from './modifiers';
|
import MODIFIER from './modifiers';
|
||||||
import FieldHint from './FieldHint';
|
import FieldHint from './FieldHint';
|
||||||
|
import MenuItemLabel from './MenuItemLabel';
|
||||||
|
|
||||||
|
const Hint = FieldHint;
|
||||||
|
|
||||||
export {
|
export {
|
||||||
If,
|
If,
|
||||||
|
For,
|
||||||
Money,
|
Money,
|
||||||
Icon,
|
Icon,
|
||||||
ListSelect,
|
ListSelect,
|
||||||
@@ -21,5 +25,7 @@ export {
|
|||||||
MODIFIER,
|
MODIFIER,
|
||||||
ErrorMessage,
|
ErrorMessage,
|
||||||
FieldHint,
|
FieldHint,
|
||||||
|
Hint,
|
||||||
|
MenuItemLabel,
|
||||||
// For,
|
// For,
|
||||||
};
|
};
|
||||||
45
client/src/config/financialReportsMenu.js
Normal file
45
client/src/config/financialReportsMenu.js
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { FormattedMessage as T } from 'react-intl';
|
||||||
|
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
sectionTitle: 'Financial Accounting',
|
||||||
|
reports: [
|
||||||
|
{
|
||||||
|
title: 'Balance Sheet Report',
|
||||||
|
desc: 'Shows the average age of unresolved issues for a project or filter. This helps you see whether your backlog is being kept up to date.',
|
||||||
|
link: '/financial-reports/balance-sheet',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Trial Balance Sheet',
|
||||||
|
desc: 'Shows the average age of unresolved issues for a project or filter. This helps you see whether your backlog is being kept up to date.',
|
||||||
|
link: '/financial-reports/trial-balance-sheet',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Journal Report',
|
||||||
|
desc: 'Shows the average age of unresolved issues for a project or filter. This helps you see whether your backlog is being kept up to date.',
|
||||||
|
link: '/financial-reports/journal-sheet',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Profit/Loss Report',
|
||||||
|
desc: 'Shows the average age of unresolved issues for a project or filter. This helps you see whether your backlog is being kept up to date.',
|
||||||
|
link: '/financial-reports/profit-loss-sheet',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'General Ledger Report',
|
||||||
|
desc: 'Shows the average age of unresolved issues for a project or filter. This helps you see whether your backlog is being kept up to date.',
|
||||||
|
link: '/financial-reports/general-ledger',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Receivable Aging Summary',
|
||||||
|
desc: 'Shows the average age of unresolved issues for a project or filter. This helps you see whether your backlog is being kept up to date.',
|
||||||
|
link: '/financial-reports/receivable-aging-summary',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Payable Aging Summary',
|
||||||
|
desc: 'Shows the average age of unresolved issues for a project or filter. This helps you see whether your backlog is being kept up to date.',
|
||||||
|
link: '/financial-reports/payable-aging-summary',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
];
|
||||||
@@ -6,8 +6,6 @@ export default [
|
|||||||
divider: true,
|
divider: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'homepage',
|
|
||||||
iconSize: 20,
|
|
||||||
text: <T id={'homepage'} />,
|
text: <T id={'homepage'} />,
|
||||||
disabled: false,
|
disabled: false,
|
||||||
href: '/homepage',
|
href: '/homepage',
|
||||||
@@ -15,9 +13,12 @@ export default [
|
|||||||
{
|
{
|
||||||
divider: true,
|
divider: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
text: 'Sales & inventory',
|
||||||
|
label: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
icon: 'homepage',
|
|
||||||
iconSize: 20,
|
|
||||||
text: <T id={'items'} />,
|
text: <T id={'items'} />,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
@@ -35,11 +36,41 @@ export default [
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
spacer: true,
|
text: <T id={'sales'} />,
|
||||||
|
children: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: <T id={'purchases'} />,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
icon: 'cut',
|
||||||
|
text: 'cut',
|
||||||
|
label: '⌘C',
|
||||||
|
disabled: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: <T id={'contacts'} />,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
text: <T id={'customers'} />,
|
||||||
|
// href: '/',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: <T id={'new_customers'} />,
|
||||||
|
href: '/customers/new',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
divider: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Financial accounting',
|
||||||
|
label: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'balance-scale',
|
|
||||||
iconSize: 20,
|
|
||||||
text: <T id={'financial'} />,
|
text: <T id={'financial'} />,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
@@ -61,92 +92,60 @@ export default [
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'university',
|
|
||||||
iconSize: 20,
|
|
||||||
text: <T id={'banking'} />,
|
text: <T id={'banking'} />,
|
||||||
children: [],
|
children: [],
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
icon: 'shopping-cart',
|
|
||||||
iconSize: 20,
|
|
||||||
text: <T id={'sales'} />,
|
|
||||||
children: [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: 'balance-scale',
|
|
||||||
iconSize: 20,
|
|
||||||
text: <T id={'purchases'} />,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
icon: 'cut',
|
|
||||||
text: 'cut',
|
|
||||||
label: '⌘C',
|
|
||||||
disabled: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: 'analytics',
|
|
||||||
iconSize: 18,
|
|
||||||
text: <T id={'financial_reports'} />,
|
text: <T id={'financial_reports'} />,
|
||||||
children: [
|
children: [
|
||||||
|
{
|
||||||
|
text: <T id={'all_reports'} />,
|
||||||
|
href: '/financial-reports',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
divider: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
text: <T id={'balance_sheet'} />,
|
text: <T id={'balance_sheet'} />,
|
||||||
href: '/balance-sheet',
|
href: '/financial-reports/balance-sheet',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: <T id={'trial_balance_sheet'} />,
|
text: <T id={'trial_balance_sheet'} />,
|
||||||
href: '/trial-balance-sheet',
|
href: '/financial-reports/trial-balance-sheet',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: <T id={'journal'} />,
|
text: <T id={'journal'} />,
|
||||||
href: '/journal-sheet',
|
href: '/financial-reports/journal-sheet',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: <T id={'general_ledger'} />,
|
text: <T id={'general_ledger'} />,
|
||||||
href: '/general-ledger',
|
href: '/financial-reports/general-ledger',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: <T id={'profit_loss_sheet'} />,
|
text: <T id={'profit_loss_sheet'} />,
|
||||||
href: '/profit-loss-sheet',
|
href: '/financial-reports/profit-loss-sheet',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: 'Receivable Aging Summary',
|
text: 'Receivable Aging Summary',
|
||||||
href: '/receivable-aging-summary'
|
href: '/financial-reports/receivable-aging-summary'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: 'Payable Aging Summary',
|
text: 'Payable Aging Summary',
|
||||||
href: '/payable-aging-summary'
|
href: '/financial-reports/payable-aging-summary'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: <T id={'expenses'} />,
|
text: <T id={'expenses'} />,
|
||||||
icon: 'receipt',
|
|
||||||
iconSize: 18,
|
|
||||||
children: [
|
children: [
|
||||||
{
|
|
||||||
text: <T id={'expenses'}/>,
|
|
||||||
href: '/expenses/new',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
text: <T id={'expenses_list'}/>,
|
text: <T id={'expenses_list'}/>,
|
||||||
href: '/expenses-list',
|
href: '/expenses-list',
|
||||||
},
|
},
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: <T id={'customers'} />,
|
|
||||||
icon: 'receipt',
|
|
||||||
iconSize: 18,
|
|
||||||
children: [
|
|
||||||
{
|
{
|
||||||
text: <T id={'customers'} />,
|
text: <T id={'new_expense'}/>,
|
||||||
// href: '/',
|
href: '/expenses/new',
|
||||||
},
|
|
||||||
{
|
|
||||||
text: <T id={'new_customers'} />,
|
|
||||||
href: '/customers/new',
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ function MakeJournalEntriesForm({
|
|||||||
is: (credit, debit) => credit || debit,
|
is: (credit, debit) => credit || debit,
|
||||||
then: Yup.number().required(),
|
then: Yup.number().required(),
|
||||||
}),
|
}),
|
||||||
|
contact_id: Yup.number().nullable(),
|
||||||
note: Yup.string().nullable(),
|
note: Yup.string().nullable(),
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
@@ -114,6 +115,7 @@ function MakeJournalEntriesForm({
|
|||||||
const defaultEntry = useMemo(
|
const defaultEntry = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
account_id: null,
|
account_id: null,
|
||||||
|
contact_id: null,
|
||||||
credit: 0,
|
credit: 0,
|
||||||
debit: 0,
|
debit: 0,
|
||||||
note: '',
|
note: '',
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export default function MakeJournalEntriesHeader({
|
|||||||
return (
|
return (
|
||||||
<div class="make-journal-entries__header">
|
<div class="make-journal-entries__header">
|
||||||
<Row>
|
<Row>
|
||||||
<Col sm={3}>
|
<Col width={260}>
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={<T id={'journal_number'}/>}
|
label={<T id={'journal_number'}/>}
|
||||||
labelInfo={infoIcon}
|
labelInfo={infoIcon}
|
||||||
@@ -46,7 +46,7 @@ export default function MakeJournalEntriesHeader({
|
|||||||
</FormGroup>
|
</FormGroup>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
<Col sm={2}>
|
<Col width={220}>
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={<T id={'date'}/>}
|
label={<T id={'date'}/>}
|
||||||
intent={(errors.date && touched.date) && Intent.DANGER}
|
intent={(errors.date && touched.date) && Intent.DANGER}
|
||||||
@@ -61,7 +61,7 @@ export default function MakeJournalEntriesHeader({
|
|||||||
</FormGroup>
|
</FormGroup>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
<Col sm={4}>
|
<Col width={400}>
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={<T id={'description'}/>}
|
label={<T id={'description'}/>}
|
||||||
className={'form-group--description'}
|
className={'form-group--description'}
|
||||||
@@ -78,7 +78,7 @@ export default function MakeJournalEntriesHeader({
|
|||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
<Row>
|
<Row>
|
||||||
<Col sm={3}>
|
<Col width={260}>
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={<T id={'reference'}/>}
|
label={<T id={'reference'}/>}
|
||||||
labelInfo={infoIcon}
|
labelInfo={infoIcon}
|
||||||
@@ -94,7 +94,7 @@ export default function MakeJournalEntriesHeader({
|
|||||||
</FormGroup>
|
</FormGroup>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
<Col sm={4}>
|
<Col width={220}>
|
||||||
<CurrenciesSelectList />
|
<CurrenciesSelectList />
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import React, { useCallback } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import { useParams, useHistory } from 'react-router-dom';
|
import { useParams, useHistory } from 'react-router-dom';
|
||||||
import { useQuery } from 'react-query';
|
import { useQuery } from 'react-query';
|
||||||
|
|
||||||
import MakeJournalEntriesForm from './MakeJournalEntriesForm';
|
import MakeJournalEntriesForm from './MakeJournalEntriesForm';
|
||||||
import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
||||||
|
|
||||||
|
import withCustomersActions from 'containers/Customers/withCustomersActions';
|
||||||
import withAccountsActions from 'containers/Accounts/withAccountsActions';
|
import withAccountsActions from 'containers/Accounts/withAccountsActions';
|
||||||
import withManualJournalsActions from 'containers/Accounting/withManualJournalsActions';
|
import withManualJournalsActions from 'containers/Accounting/withManualJournalsActions';
|
||||||
|
|
||||||
@@ -11,8 +13,14 @@ import {compose} from 'utils';
|
|||||||
|
|
||||||
|
|
||||||
function MakeJournalEntriesPage({
|
function MakeJournalEntriesPage({
|
||||||
requestFetchManualJournal,
|
// #withCustomersActions
|
||||||
|
requestFetchCustomers,
|
||||||
|
|
||||||
|
// #withAccountsActions
|
||||||
requestFetchAccounts,
|
requestFetchAccounts,
|
||||||
|
|
||||||
|
// #withManualJournalActions
|
||||||
|
requestFetchManualJournal,
|
||||||
}) {
|
}) {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
@@ -20,6 +28,9 @@ function MakeJournalEntriesPage({
|
|||||||
const fetchAccounts = useQuery('accounts-list',
|
const fetchAccounts = useQuery('accounts-list',
|
||||||
(key) => requestFetchAccounts());
|
(key) => requestFetchAccounts());
|
||||||
|
|
||||||
|
const fetchCustomers = useQuery('customers-list',
|
||||||
|
(key) => requestFetchCustomers());
|
||||||
|
|
||||||
const fetchJournal = useQuery(
|
const fetchJournal = useQuery(
|
||||||
id && ['manual-journal', id],
|
id && ['manual-journal', id],
|
||||||
(key, journalId) => requestFetchManualJournal(journalId));
|
(key, journalId) => requestFetchManualJournal(journalId));
|
||||||
@@ -35,7 +46,11 @@ function MakeJournalEntriesPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardInsider
|
<DashboardInsider
|
||||||
loading={fetchJournal.isFetching || fetchAccounts.isFetching}
|
loading={
|
||||||
|
fetchJournal.isFetching ||
|
||||||
|
fetchAccounts.isFetching ||
|
||||||
|
fetchCustomers.isFetching
|
||||||
|
}
|
||||||
name={'make-journal-page'}>
|
name={'make-journal-page'}>
|
||||||
<MakeJournalEntriesForm
|
<MakeJournalEntriesForm
|
||||||
onFormSubmit={handleFormSubmit}
|
onFormSubmit={handleFormSubmit}
|
||||||
@@ -47,5 +62,6 @@ function MakeJournalEntriesPage({
|
|||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
withAccountsActions,
|
withAccountsActions,
|
||||||
|
withCustomersActions,
|
||||||
withManualJournalsActions,
|
withManualJournalsActions,
|
||||||
)(MakeJournalEntriesPage);
|
)(MakeJournalEntriesPage);
|
||||||
@@ -1,17 +1,20 @@
|
|||||||
import React, { useState, useMemo, useEffect, useCallback } from 'react';
|
import React, { useState, useMemo, useEffect, useCallback } from 'react';
|
||||||
import { Button, Intent } from '@blueprintjs/core';
|
import { Button, Intent } from '@blueprintjs/core';
|
||||||
import { FormattedMessage as T, useIntl } from 'react-intl';
|
import { FormattedMessage as T, useIntl } from 'react-intl';
|
||||||
|
import { omit } from 'lodash';
|
||||||
|
|
||||||
import DataTable from 'components/DataTable';
|
import DataTable from 'components/DataTable';
|
||||||
import Icon from 'components/Icon';
|
import Icon from 'components/Icon';
|
||||||
|
import { Hint } from 'components';
|
||||||
import { compose, formattedAmount } from 'utils';
|
import { compose, formattedAmount } from 'utils';
|
||||||
import {
|
import {
|
||||||
AccountsListFieldCell,
|
AccountsListFieldCell,
|
||||||
MoneyFieldCell,
|
MoneyFieldCell,
|
||||||
InputGroupCell,
|
InputGroupCell,
|
||||||
|
ContactsListFieldCell,
|
||||||
} from 'components/DataTableCells';
|
} from 'components/DataTableCells';
|
||||||
import { omit } from 'lodash';
|
|
||||||
import withAccounts from 'containers/Accounts/withAccounts';
|
import withAccounts from 'containers/Accounts/withAccounts';
|
||||||
|
import withCustomers from 'containers/Customers/withCustomers';
|
||||||
|
|
||||||
// Actions cell renderer.
|
// Actions cell renderer.
|
||||||
const ActionsCellRenderer = ({
|
const ActionsCellRenderer = ({
|
||||||
@@ -73,6 +76,9 @@ const NoteCellRenderer = (chainedComponent) => (props) => {
|
|||||||
* Make journal entries table component.
|
* Make journal entries table component.
|
||||||
*/
|
*/
|
||||||
function MakeJournalEntriesTable({
|
function MakeJournalEntriesTable({
|
||||||
|
// #withCustomers
|
||||||
|
customers,
|
||||||
|
|
||||||
// #withAccounts
|
// #withAccounts
|
||||||
accounts,
|
accounts,
|
||||||
|
|
||||||
@@ -142,6 +148,7 @@ function MakeJournalEntriesTable({
|
|||||||
width: 40,
|
width: 40,
|
||||||
disableResizing: true,
|
disableResizing: true,
|
||||||
disableSortBy: true,
|
disableSortBy: true,
|
||||||
|
sticky: 'left',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: formatMessage({ id: 'account' }),
|
Header: formatMessage({ id: 'account' }),
|
||||||
@@ -171,6 +178,16 @@ function MakeJournalEntriesTable({
|
|||||||
disableResizing: true,
|
disableResizing: true,
|
||||||
width: 150,
|
width: 150,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Header: (<><T id={'contact'} /><Hint /></>),
|
||||||
|
id: 'contact_id',
|
||||||
|
accessor: 'contact_id',
|
||||||
|
Cell: NoteCellRenderer(ContactsListFieldCell),
|
||||||
|
className: 'contact',
|
||||||
|
disableResizing: true,
|
||||||
|
disableSortBy: true,
|
||||||
|
width: 180,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Header: formatMessage({ id: 'note' }),
|
Header: formatMessage({ id: 'note' }),
|
||||||
accessor: 'note',
|
accessor: 'note',
|
||||||
@@ -216,6 +233,11 @@ function MakeJournalEntriesTable({
|
|||||||
errors: errors.entries || [],
|
errors: errors.entries || [],
|
||||||
updateData: handleUpdateData,
|
updateData: handleUpdateData,
|
||||||
removeRow: handleRemoveRow,
|
removeRow: handleRemoveRow,
|
||||||
|
contacts: [
|
||||||
|
...customers.map((customer) => ({
|
||||||
|
...customer, contact_type: 'customer',
|
||||||
|
})),
|
||||||
|
],
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -244,4 +266,7 @@ export default compose(
|
|||||||
withAccounts(({ accounts }) => ({
|
withAccounts(({ accounts }) => ({
|
||||||
accounts,
|
accounts,
|
||||||
})),
|
})),
|
||||||
|
withCustomers(({ customersItems }) => ({
|
||||||
|
customers: customersItems,
|
||||||
|
})),
|
||||||
)(MakeJournalEntriesTable);
|
)(MakeJournalEntriesTable);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ export default (mapState) => {
|
|||||||
|
|
||||||
const mapped = {
|
const mapped = {
|
||||||
customersViews: getResourceViews(state, 'customers'),
|
customersViews: getResourceViews(state, 'customers'),
|
||||||
|
customersItems: Object.values(state.customers.items),
|
||||||
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,
|
||||||
|
|||||||
@@ -121,6 +121,17 @@ function ExpenseDataTable({
|
|||||||
[handleEditExpense, handleDeleteExpense, handlePublishExpense],
|
[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(
|
const columns = useMemo(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
@@ -155,11 +166,10 @@ function ExpenseDataTable({
|
|||||||
{
|
{
|
||||||
id: 'expense_account_id',
|
id: 'expense_account_id',
|
||||||
Header: formatMessage({ id: 'expense_account' }),
|
Header: formatMessage({ id: 'expense_account' }),
|
||||||
accessor:'expense_account_id',
|
accessor: expenseAccountAccessor,
|
||||||
width: 150,
|
width: 150,
|
||||||
className: 'expense_account',
|
className: 'expense_account',
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
id: 'publish',
|
id: 'publish',
|
||||||
Header: formatMessage({ id: 'publish' }),
|
Header: formatMessage({ id: 'publish' }),
|
||||||
|
|||||||
@@ -12,10 +12,11 @@ import { Intent, FormGroup, TextArea } from '@blueprintjs/core';
|
|||||||
import { FormattedMessage as T, useIntl } from 'react-intl';
|
import { FormattedMessage as T, useIntl } from 'react-intl';
|
||||||
import { pick } from 'lodash';
|
import { pick } from 'lodash';
|
||||||
import { useQuery } from 'react-query';
|
import { useQuery } from 'react-query';
|
||||||
|
import { Col, Row } from 'react-grid-system';
|
||||||
|
|
||||||
import ExpenseFormHeader from './ExpenseFormHeader';
|
import ExpenseFormHeader from './ExpenseFormHeader';
|
||||||
import ExpenseTable from './ExpenseTable';
|
import ExpenseTable from './ExpenseTable';
|
||||||
import ExpenseFooter from './ExpenseFooter';
|
import ExpenseFloatingFooter from './ExpenseFooter';
|
||||||
|
|
||||||
import withExpensesActions from 'containers/Expenses/withExpensesActions';
|
import withExpensesActions from 'containers/Expenses/withExpensesActions';
|
||||||
import withExpneseDetail from 'containers/Expenses/withExpenseDetail';
|
import withExpneseDetail from 'containers/Expenses/withExpenseDetail';
|
||||||
@@ -76,11 +77,11 @@ function ExpenseForm({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (expenseDetail && expenseDetail.id) {
|
if (expenseDetail && expenseDetail.id) {
|
||||||
changePageTitle(formatMessage({ id: 'edit_expense' }));
|
changePageTitle(formatMessage({ id: 'edit_expense' }));
|
||||||
changePageSubtitle(`No. ${expenseDetail.payment_account_id}`);
|
// changePageSubtitle(`No. ${expenseDetail.payment_account_id}`);
|
||||||
} else {
|
} else {
|
||||||
changePageTitle(formatMessage({ id: 'new_expense' }));
|
changePageTitle(formatMessage({ id: 'new_expense' }));
|
||||||
}
|
}
|
||||||
// @todo not functions just states.
|
// @todo not functions just states.
|
||||||
}, [changePageTitle, changePageSubtitle, expenseDetail, formatMessage]);
|
}, [changePageTitle, changePageSubtitle, expenseDetail, formatMessage]);
|
||||||
|
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
@@ -137,7 +138,6 @@ function ExpenseForm({
|
|||||||
reference_no: '',
|
reference_no: '',
|
||||||
currency_code: '',
|
currency_code: '',
|
||||||
categories: [
|
categories: [
|
||||||
// @todo @mohamed index
|
|
||||||
defaultCategory,
|
defaultCategory,
|
||||||
defaultCategory,
|
defaultCategory,
|
||||||
defaultCategory,
|
defaultCategory,
|
||||||
@@ -154,7 +154,8 @@ function ExpenseForm({
|
|||||||
...pick(expenseDetail, Object.keys(defaultInitialValues)),
|
...pick(expenseDetail, Object.keys(defaultInitialValues)),
|
||||||
categories: expenseDetail.categories.map((category) => ({
|
categories: expenseDetail.categories.map((category) => ({
|
||||||
...pick(category, Object.keys(defaultCategory)),
|
...pick(category, Object.keys(defaultCategory)),
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
...defaultInitialValues,
|
...defaultInitialValues,
|
||||||
@@ -257,7 +258,7 @@ function ExpenseForm({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(formik.errors);
|
console.log(formik.values, 'VALUES');
|
||||||
|
|
||||||
const handleSubmitClick = useCallback(
|
const handleSubmitClick = useCallback(
|
||||||
(payload) => {
|
(payload) => {
|
||||||
@@ -298,29 +299,32 @@ function ExpenseForm({
|
|||||||
defaultRow={defaultCategory}
|
defaultRow={defaultCategory}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<FormGroup
|
<div class="expense-form-footer">
|
||||||
label={<T id={'description'} />}
|
<FormGroup
|
||||||
className={'form-group--description'}
|
label={<T id={'description'} />}
|
||||||
>
|
className={'form-group--description'}
|
||||||
<TextArea
|
>
|
||||||
growVertically={true}
|
<TextArea
|
||||||
large={true}
|
growVertically={true}
|
||||||
{...formik.getFieldProps('description')}
|
large={true}
|
||||||
/>
|
{...formik.getFieldProps('description')}
|
||||||
</FormGroup>
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
|
||||||
<ExpenseFooter
|
<Dragzone
|
||||||
|
initialFiles={initialAttachmentFiles}
|
||||||
|
onDrop={handleDropFiles}
|
||||||
|
onDeleteFile={handleDeleteFile}
|
||||||
|
hint={'Attachments: Maxiumum size: 20MB'}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ExpenseFloatingFooter
|
||||||
formik={formik}
|
formik={formik}
|
||||||
onSubmitClick={handleSubmitClick}
|
onSubmitClick={handleSubmitClick}
|
||||||
onCancelClick={handleCancelClick}
|
onCancelClick={handleCancelClick}
|
||||||
/>
|
/>
|
||||||
</form>
|
</form>
|
||||||
<Dragzone
|
|
||||||
initialFiles={initialAttachmentFiles}
|
|
||||||
onDrop={handleDropFiles}
|
|
||||||
onDeleteFile={handleDeleteFile}
|
|
||||||
hint={'Attachments: Maxiumum size: 20MB'}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ function ExpenseFormHeader({
|
|||||||
return (
|
return (
|
||||||
<div className={'dashboard__insider--expense-form__header'}>
|
<div className={'dashboard__insider--expense-form__header'}>
|
||||||
<Row>
|
<Row>
|
||||||
<Col sm={3.5}>
|
<Col width={300}>
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={<T id={'beneficiary'} />}
|
label={<T id={'beneficiary'} />}
|
||||||
className={classNames('form-group--select-list', Classes.FILL)}
|
className={classNames('form-group--select-list', Classes.FILL)}
|
||||||
@@ -141,7 +141,8 @@ function ExpenseFormHeader({
|
|||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</Col>
|
</Col>
|
||||||
<Col sm={3}>
|
|
||||||
|
<Col width={400}>
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={<T id={'payment_account'} />}
|
label={<T id={'payment_account'} />}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
@@ -177,8 +178,9 @@ function ExpenseFormHeader({
|
|||||||
</FormGroup>
|
</FormGroup>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
<Row>
|
<Row>
|
||||||
<Col sm={3.5}>
|
<Col width={300}>
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={<T id={'payment_date'} />}
|
label={<T id={'payment_date'} />}
|
||||||
labelInfo={infoIcon}
|
labelInfo={infoIcon}
|
||||||
@@ -189,17 +191,17 @@ function ExpenseFormHeader({
|
|||||||
helperText={
|
helperText={
|
||||||
<ErrorMessage name="payment_date" {...{ errors, touched }} />
|
<ErrorMessage name="payment_date" {...{ errors, touched }} />
|
||||||
}
|
}
|
||||||
minimal={true}
|
|
||||||
>
|
>
|
||||||
<DateInput
|
<DateInput
|
||||||
{...momentFormatter('YYYY/MM/DD')}
|
{...momentFormatter('YYYY/MM/DD')}
|
||||||
defaultValue={new Date()}
|
defaultValue={new Date()}
|
||||||
onChange={handleDateChange}
|
onChange={handleDateChange}
|
||||||
popoverProps={{ position: Position.BOTTOM }}
|
popoverProps={{ position: Position.BOTTOM, minimal: true }}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</Col>
|
</Col>
|
||||||
<Col sm={2}>
|
|
||||||
|
<Col width={200}>
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={<T id={'currency'} />}
|
label={<T id={'currency'} />}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
@@ -223,23 +225,25 @@ function ExpenseFormHeader({
|
|||||||
onItemSelect={onItemsSelect('currency_code')}
|
onItemSelect={onItemsSelect('currency_code')}
|
||||||
selectedItem={values.currency_code}
|
selectedItem={values.currency_code}
|
||||||
selectedItemProp={'currency_code'}
|
selectedItemProp={'currency_code'}
|
||||||
defaultText={<T id={'select_currency_code'} />}
|
defaultText={<T id={'select_currency'} />}
|
||||||
labelProp={'currency_code'}
|
labelProp={'currency_code'}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
<Col sm={3}>
|
<Col width={200}>
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={<T id={'ref_no'} />}
|
label={<T id={'ref_no'} />}
|
||||||
className={'form-group--ref_no'}
|
className={classNames(
|
||||||
|
'form-group--ref_no',
|
||||||
|
Classes.FILL,
|
||||||
|
)}
|
||||||
intent={
|
intent={
|
||||||
errors.reference_no && touched.reference_no && Intent.DANGER
|
errors.reference_no && touched.reference_no && Intent.DANGER
|
||||||
}
|
}
|
||||||
helperText={
|
helperText={
|
||||||
<ErrorMessage name="reference_no" {...{ errors, touched }} />
|
<ErrorMessage name="reference_no" {...{ errors, touched }} />
|
||||||
}
|
}
|
||||||
minimal={true}
|
|
||||||
>
|
>
|
||||||
<InputGroup
|
<InputGroup
|
||||||
intent={
|
intent={
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import React, { useState, useMemo, useEffect, useCallback } from 'react';
|
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 { FormattedMessage as T, useIntl } from 'react-intl';
|
||||||
|
|
||||||
import DataTable from 'components/DataTable';
|
import DataTable from 'components/DataTable';
|
||||||
import Icon from 'components/Icon';
|
import Icon from 'components/Icon';
|
||||||
|
import { Hint } from 'components';
|
||||||
import { compose, formattedAmount } from 'utils';
|
import { compose, formattedAmount } from 'utils';
|
||||||
import {
|
import {
|
||||||
AccountsListFieldCell,
|
AccountsListFieldCell,
|
||||||
@@ -88,14 +89,16 @@ function ExpenseTable({
|
|||||||
payload.removeRow(index);
|
payload.removeRow(index);
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<Button
|
<Tooltip content={<T id={'remove_the_line'} />} position={Position.LEFT}>
|
||||||
icon={<Icon icon="times-circle" iconSize={14} />}
|
<Button
|
||||||
iconSize={14}
|
icon={<Icon icon="times-circle" iconSize={14} />}
|
||||||
className="ml2"
|
iconSize={14}
|
||||||
minimal={true}
|
className="ml2"
|
||||||
intent={Intent.DANGER}
|
minimal={true}
|
||||||
onClick={onClickRemoveRole}
|
intent={Intent.DANGER}
|
||||||
/>
|
onClick={onClickRemoveRole}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -144,8 +147,7 @@ function ExpenseTable({
|
|||||||
disableSortBy: true,
|
disableSortBy: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// @todo Add hint component after the header label.
|
Header: (<>{ formatMessage({ id: 'expense_category' }) }<Hint /></>),
|
||||||
Header: formatMessage({ id: 'expense_category' }),
|
|
||||||
id: 'expense_account_id',
|
id: 'expense_account_id',
|
||||||
accessor: 'expense_account_id',
|
accessor: 'expense_account_id',
|
||||||
Cell: TotalExpenseCellRenderer(AccountsListFieldCell),
|
Cell: TotalExpenseCellRenderer(AccountsListFieldCell),
|
||||||
@@ -161,6 +163,7 @@ function ExpenseTable({
|
|||||||
disableSortBy: true,
|
disableSortBy: true,
|
||||||
disableResizing: true,
|
disableResizing: true,
|
||||||
width: 150,
|
width: 150,
|
||||||
|
className: 'amount',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: formatMessage({ id: 'description' }),
|
Header: formatMessage({ id: 'description' }),
|
||||||
@@ -195,7 +198,6 @@ function ExpenseTable({
|
|||||||
[rows],
|
[rows],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={'dashboard__insider--expense-form__table'}>
|
<div className={'dashboard__insider--expense-form__table'}>
|
||||||
<DataTable
|
<DataTable
|
||||||
@@ -235,5 +237,4 @@ export default compose(
|
|||||||
withAccounts(({ accounts }) => ({
|
withAccounts(({ accounts }) => ({
|
||||||
accounts,
|
accounts,
|
||||||
})),
|
})),
|
||||||
|
|
||||||
)(ExpenseTable);
|
)(ExpenseTable);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import ExpenseDataTable from 'containers/Expenses/ExpenseDataTable';
|
|||||||
import ExpenseActionsBar from 'containers/Expenses/ExpenseActionsBar';
|
import ExpenseActionsBar from 'containers/Expenses/ExpenseActionsBar';
|
||||||
|
|
||||||
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||||
|
import withExpenses from 'containers/Expenses/withExpenses';
|
||||||
import withExpensesActions from 'containers/Expenses/withExpensesActions';
|
import withExpensesActions from 'containers/Expenses/withExpensesActions';
|
||||||
import withViewsActions from 'containers/Views/withViewsActions';
|
import withViewsActions from 'containers/Views/withViewsActions';
|
||||||
|
|
||||||
@@ -24,6 +25,9 @@ function ExpensesList({
|
|||||||
// #withViewsActions
|
// #withViewsActions
|
||||||
requestFetchResourceViews,
|
requestFetchResourceViews,
|
||||||
|
|
||||||
|
// #withExpenses
|
||||||
|
expensesTableQuery,
|
||||||
|
|
||||||
//#withExpensesActions
|
//#withExpensesActions
|
||||||
requestFetchExpensesTable,
|
requestFetchExpensesTable,
|
||||||
requestDeleteExpense,
|
requestDeleteExpense,
|
||||||
@@ -44,8 +48,9 @@ function ExpensesList({
|
|||||||
return requestFetchResourceViews('expenses');
|
return requestFetchResourceViews('expenses');
|
||||||
});
|
});
|
||||||
|
|
||||||
const fetchExpenses = useQuery('expenses-table', () =>
|
const fetchExpenses = useQuery(
|
||||||
requestFetchExpensesTable(),
|
['expenses-table', expensesTableQuery],
|
||||||
|
() => requestFetchExpensesTable(),
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -53,7 +58,6 @@ function ExpensesList({
|
|||||||
}, [changePageTitle, formatMessage]);
|
}, [changePageTitle, formatMessage]);
|
||||||
|
|
||||||
// Handle delete expense click.
|
// Handle delete expense click.
|
||||||
|
|
||||||
const handleDeleteExpense = useCallback(
|
const handleDeleteExpense = useCallback(
|
||||||
(expnese) => {
|
(expnese) => {
|
||||||
setDeleteExpense(expnese);
|
setDeleteExpense(expnese);
|
||||||
@@ -108,8 +112,6 @@ function ExpensesList({
|
|||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
setBulkDelete(false);
|
setBulkDelete(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
// @todo
|
|
||||||
}, [requestDeleteBulkExpenses, bulkDelete, formatMessage, selectedRowsCount]);
|
}, [requestDeleteBulkExpenses, bulkDelete, formatMessage, selectedRowsCount]);
|
||||||
|
|
||||||
// Handle cancel bulk delete alert.
|
// Handle cancel bulk delete alert.
|
||||||
@@ -149,6 +151,7 @@ function ExpensesList({
|
|||||||
message: formatMessage({ id: 'the_expense_id_has_been_published' }),
|
message: formatMessage({ id: 'the_expense_id_has_been_published' }),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
fetchExpenses.refetch();
|
||||||
},
|
},
|
||||||
[requestPublishExpense, formatMessage],
|
[requestPublishExpense, formatMessage],
|
||||||
);
|
);
|
||||||
@@ -163,7 +166,7 @@ function ExpensesList({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardInsider
|
<DashboardInsider
|
||||||
loading={fetchViews.isFetching || fetchExpenses.isFetching}
|
loading={fetchViews.isFetching}
|
||||||
name={'expenses'}
|
name={'expenses'}
|
||||||
>
|
>
|
||||||
<ExpenseActionsBar
|
<ExpenseActionsBar
|
||||||
@@ -232,5 +235,6 @@ function ExpensesList({
|
|||||||
export default compose(
|
export default compose(
|
||||||
withDashboardActions,
|
withDashboardActions,
|
||||||
withExpensesActions,
|
withExpensesActions,
|
||||||
|
withExpenses(({ expensesTableQuery }) => ({ expensesTableQuery })),
|
||||||
withViewsActions,
|
withViewsActions,
|
||||||
)(ExpensesList);
|
)(ExpensesList);
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ function BalanceSheet({
|
|||||||
fetchBalanceSheet,
|
fetchBalanceSheet,
|
||||||
|
|
||||||
// #withBalanceSheetDetail
|
// #withBalanceSheetDetail
|
||||||
balanceSheetLoading,
|
|
||||||
balanceSheetFilter,
|
balanceSheetFilter,
|
||||||
|
|
||||||
// #withPreferences
|
// #withPreferences
|
||||||
@@ -41,6 +40,7 @@ function BalanceSheet({
|
|||||||
display_columns_by: '',
|
display_columns_by: '',
|
||||||
none_zero: false,
|
none_zero: false,
|
||||||
});
|
});
|
||||||
|
const [refresh, setRefresh] = useState(true);
|
||||||
|
|
||||||
const fetchHook = useQuery(
|
const fetchHook = useQuery(
|
||||||
['balance-sheet', filter],
|
['balance-sheet', filter],
|
||||||
@@ -50,7 +50,7 @@ function BalanceSheet({
|
|||||||
|
|
||||||
// Handle fetch the data of balance sheet.
|
// Handle fetch the data of balance sheet.
|
||||||
const handleFetchData = useCallback(() => {
|
const handleFetchData = useCallback(() => {
|
||||||
fetchHook.refetch({ force: true });
|
setRefresh(true);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -66,11 +66,18 @@ function BalanceSheet({
|
|||||||
to_date: moment(filter.to_date).format('YYYY-MM-DD'),
|
to_date: moment(filter.to_date).format('YYYY-MM-DD'),
|
||||||
};
|
};
|
||||||
setFilter({ ..._filter });
|
setFilter({ ..._filter });
|
||||||
fetchHook.refetch({ force: true });
|
setRefresh(true);
|
||||||
},
|
},
|
||||||
[setFilter],
|
[setFilter],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (refresh) {
|
||||||
|
fetchHook.refetch({ force: true });
|
||||||
|
setRefresh(false);
|
||||||
|
}
|
||||||
|
}, [refresh]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardInsider>
|
<DashboardInsider>
|
||||||
<BalanceSheetActionsBar />
|
<BalanceSheetActionsBar />
|
||||||
@@ -86,7 +93,6 @@ function BalanceSheet({
|
|||||||
<div class="financial-statement__body">
|
<div class="financial-statement__body">
|
||||||
<BalanceSheetTable
|
<BalanceSheetTable
|
||||||
companyName={organizationSettings.name}
|
companyName={organizationSettings.name}
|
||||||
loading={balanceSheetLoading}
|
|
||||||
balanceSheetQuery={filter}
|
balanceSheetQuery={filter}
|
||||||
onFetchData={handleFetchData}
|
onFetchData={handleFetchData}
|
||||||
/>
|
/>
|
||||||
@@ -100,8 +106,7 @@ function BalanceSheet({
|
|||||||
export default compose(
|
export default compose(
|
||||||
withDashboardActions,
|
withDashboardActions,
|
||||||
withBalanceSheetActions,
|
withBalanceSheetActions,
|
||||||
withBalanceSheetDetail(({ balanceSheetLoading, balanceSheetFilter }) => ({
|
withBalanceSheetDetail(({ balanceSheetFilter }) => ({
|
||||||
balanceSheetLoading,
|
|
||||||
balanceSheetFilter,
|
balanceSheetFilter,
|
||||||
})),
|
})),
|
||||||
withSettings,
|
withSettings,
|
||||||
|
|||||||
@@ -22,8 +22,12 @@ import withBalanceSheetActions from './withBalanceSheetActions';
|
|||||||
|
|
||||||
|
|
||||||
function BalanceSheetActionsBar({
|
function BalanceSheetActionsBar({
|
||||||
|
// #withBalanceSheetDetail
|
||||||
balanceSheetFilter,
|
balanceSheetFilter,
|
||||||
|
|
||||||
|
// #withBalanceSheetActions
|
||||||
toggleBalanceSheetFilter,
|
toggleBalanceSheetFilter,
|
||||||
|
refreshBalanceSheet
|
||||||
}) {
|
}) {
|
||||||
const filterDropdown = FilterDropdown({
|
const filterDropdown = FilterDropdown({
|
||||||
fields: [],
|
fields: [],
|
||||||
@@ -34,6 +38,10 @@ function BalanceSheetActionsBar({
|
|||||||
toggleBalanceSheetFilter();
|
toggleBalanceSheetFilter();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleRecalcReport = () => {
|
||||||
|
refreshBalanceSheet(true);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardActionsBar>
|
<DashboardActionsBar>
|
||||||
<NavbarGroup>
|
<NavbarGroup>
|
||||||
@@ -44,6 +52,16 @@ function BalanceSheetActionsBar({
|
|||||||
/>
|
/>
|
||||||
<NavbarDivider />
|
<NavbarDivider />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
className={classNames(
|
||||||
|
Classes.MINIMAL,
|
||||||
|
'button--gray-highlight',
|
||||||
|
)}
|
||||||
|
text={<T id={'recalc_report'} />}
|
||||||
|
onClick={handleRecalcReport}
|
||||||
|
icon={<Icon icon="refresh-16" iconSize={16} />}
|
||||||
|
/>
|
||||||
|
|
||||||
<If condition={balanceSheetFilter}>
|
<If condition={balanceSheetFilter}>
|
||||||
<Button
|
<Button
|
||||||
className={Classes.MINIMAL}
|
className={Classes.MINIMAL}
|
||||||
@@ -61,7 +79,6 @@ function BalanceSheetActionsBar({
|
|||||||
icon={<Icon icon="arrow-to-bottom" />}
|
icon={<Icon icon="arrow-to-bottom" />}
|
||||||
/>
|
/>
|
||||||
</If>
|
</If>
|
||||||
<NavbarDivider />
|
|
||||||
|
|
||||||
<Popover
|
<Popover
|
||||||
content={filterDropdown}
|
content={filterDropdown}
|
||||||
@@ -75,6 +92,8 @@ function BalanceSheetActionsBar({
|
|||||||
/>
|
/>
|
||||||
</Popover>
|
</Popover>
|
||||||
|
|
||||||
|
<NavbarDivider />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
className={Classes.MINIMAL}
|
className={Classes.MINIMAL}
|
||||||
icon={<Icon icon='print-16' iconSize={16} />}
|
icon={<Icon icon='print-16' iconSize={16} />}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { useMemo, useCallback } from 'react';
|
import React, { useMemo, useCallback, useEffect } from 'react';
|
||||||
import FinancialStatementHeader from 'containers/FinancialStatements/FinancialStatementHeader';
|
import FinancialStatementHeader from 'containers/FinancialStatements/FinancialStatementHeader';
|
||||||
import { Row, Col } from 'react-grid-system';
|
import { Row, Col, Visible } from 'react-grid-system';
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
FormGroup,
|
FormGroup,
|
||||||
@@ -17,11 +17,19 @@ import FinancialStatementDateRange from 'containers/FinancialStatements/Financia
|
|||||||
import SelectDisplayColumnsBy from '../SelectDisplayColumnsBy';
|
import SelectDisplayColumnsBy from '../SelectDisplayColumnsBy';
|
||||||
import RadiosAccountingBasis from '../RadiosAccountingBasis';
|
import RadiosAccountingBasis from '../RadiosAccountingBasis';
|
||||||
|
|
||||||
|
import withBalanceSheet from './withBalanceSheetDetail';
|
||||||
|
import withBalanceSheetActions from './withBalanceSheetActions';
|
||||||
|
|
||||||
export default function BalanceSheetHeader({
|
import { compose } from 'utils';
|
||||||
|
|
||||||
|
function BalanceSheetHeader({
|
||||||
onSubmitFilter,
|
onSubmitFilter,
|
||||||
pageFilter,
|
pageFilter,
|
||||||
show
|
show,
|
||||||
|
refresh,
|
||||||
|
|
||||||
|
// #withBalanceSheetActions
|
||||||
|
refreshBalanceSheet
|
||||||
}) {
|
}) {
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
|
|
||||||
@@ -49,11 +57,6 @@ export default function BalanceSheetHeader({
|
|||||||
formik.setFieldValue('display_columns_by', item.by);
|
formik.setFieldValue('display_columns_by', item.by);
|
||||||
}, [formik]);
|
}, [formik]);
|
||||||
|
|
||||||
// Handle submit filter submit button.
|
|
||||||
const handleSubmitClick = useCallback(() => {
|
|
||||||
formik.submitForm();
|
|
||||||
}, [formik]);
|
|
||||||
|
|
||||||
const filterAccountsOptions = useMemo(() => [
|
const filterAccountsOptions = useMemo(() => [
|
||||||
{ key: '', name: formatMessage({ id: 'accounts_with_zero_balance' }) },
|
{ key: '', name: formatMessage({ id: 'accounts_with_zero_balance' }) },
|
||||||
{ key: 'all-trans', name: formatMessage({ id: 'all_transactions' }) },
|
{ key: 'all-trans', name: formatMessage({ id: 'all_transactions' }) },
|
||||||
@@ -63,24 +66,31 @@ export default function BalanceSheetHeader({
|
|||||||
return (<MenuItem text={item.name} key={item.id} onClick={handleClick} />);
|
return (<MenuItem text={item.name} key={item.id} onClick={handleClick} />);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const infoIcon = useMemo(() =>
|
|
||||||
(<Icon icon="info-circle" iconSize={12} />), []);
|
|
||||||
|
|
||||||
const handleAccountingBasisChange = useCallback((value) => {
|
const handleAccountingBasisChange = useCallback((value) => {
|
||||||
formik.setFieldValue('basis', value);
|
formik.setFieldValue('basis', value);
|
||||||
}, [formik]);
|
}, [formik]);
|
||||||
|
|
||||||
|
// Handle submit filter submit button.
|
||||||
|
useEffect(() => {
|
||||||
|
if (refresh) {
|
||||||
|
formik.submitForm();
|
||||||
|
refreshBalanceSheet(false);
|
||||||
|
}
|
||||||
|
}, [refresh]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FinancialStatementHeader show={show}>
|
<FinancialStatementHeader show={show}>
|
||||||
<FinancialStatementDateRange formik={formik} />
|
|
||||||
|
|
||||||
<Row>
|
<Row>
|
||||||
<Col sm={3}>
|
<FinancialStatementDateRange formik={formik} />
|
||||||
|
|
||||||
|
<Visible xl><Col width={'100%'} /></Visible>
|
||||||
|
|
||||||
|
<Col width={260} offset={10}>
|
||||||
<SelectDisplayColumnsBy
|
<SelectDisplayColumnsBy
|
||||||
onItemSelect={onItemSelectDisplayColumns} />
|
onItemSelect={onItemSelectDisplayColumns} />
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
<Col sm={3}>
|
<Col width={260}>
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={<T id={'filter_accounts'} />}
|
label={<T id={'filter_accounts'} />}
|
||||||
className="form-group--select-list bp3-fill"
|
className="form-group--select-list bp3-fill"
|
||||||
@@ -95,22 +105,19 @@ export default function BalanceSheetHeader({
|
|||||||
</FormGroup>
|
</FormGroup>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
<Col sm={3}>
|
<Col width={260}>
|
||||||
<RadiosAccountingBasis
|
<RadiosAccountingBasis
|
||||||
selectedValue={formik.values.basis}
|
selectedValue={formik.values.basis}
|
||||||
onChange={handleAccountingBasisChange} />
|
onChange={handleAccountingBasisChange} />
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
<Col sm={3}>
|
|
||||||
<Button
|
|
||||||
type="submit"
|
|
||||||
onClick={handleSubmitClick}
|
|
||||||
disabled={formik.isSubmitting}
|
|
||||||
className={'button--submit-filter mt2'}>
|
|
||||||
<T id={'calculate_report'} />
|
|
||||||
</Button>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
</Row>
|
||||||
</FinancialStatementHeader>
|
</FinancialStatementHeader>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default compose(
|
||||||
|
withBalanceSheet(({ balanceSheetRefresh }) => ({
|
||||||
|
refresh: balanceSheetRefresh,
|
||||||
|
})),
|
||||||
|
withBalanceSheetActions,
|
||||||
|
)(BalanceSheetHeader);
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useMemo, useCallback } from 'react';
|
import React, { useMemo, useEffect, useState, useCallback } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
|
|
||||||
@@ -20,23 +20,26 @@ function BalanceSheetTable({
|
|||||||
balanceSheetAccounts,
|
balanceSheetAccounts,
|
||||||
balanceSheetColumns,
|
balanceSheetColumns,
|
||||||
balanceSheetQuery,
|
balanceSheetQuery,
|
||||||
|
balanceSheetLoading,
|
||||||
|
|
||||||
// #ownProps
|
// #ownProps
|
||||||
onFetchData,
|
onFetchData,
|
||||||
loading,
|
|
||||||
}) {
|
}) {
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
|
|
||||||
const columns = useMemo(
|
const columns = useMemo(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
Header: formatMessage({ id: 'account_name' }),
|
Header: formatMessage({ id: 'account_name' }),
|
||||||
accessor: 'name',
|
accessor: 'name',
|
||||||
className: 'account_name',
|
className: 'account_name',
|
||||||
|
width: 100,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: formatMessage({ id: 'code' }),
|
Header: formatMessage({ id: 'account_code' }),
|
||||||
accessor: 'code',
|
accessor: 'code',
|
||||||
className: 'code',
|
className: 'code',
|
||||||
|
width: 80,
|
||||||
},
|
},
|
||||||
...(balanceSheetQuery.display_columns_type === 'total'
|
...(balanceSheetQuery.display_columns_type === 'total'
|
||||||
? [
|
? [
|
||||||
@@ -55,7 +58,8 @@ function BalanceSheetTable({
|
|||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
},
|
},
|
||||||
className: 'credit',
|
className: 'total',
|
||||||
|
width: 80,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
: []),
|
: []),
|
||||||
@@ -70,7 +74,7 @@ function BalanceSheetTable({
|
|||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
},
|
},
|
||||||
width: 100,
|
width: 80,
|
||||||
}))
|
}))
|
||||||
: []),
|
: []),
|
||||||
],
|
],
|
||||||
@@ -89,18 +93,20 @@ function BalanceSheetTable({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<FinancialSheet
|
<FinancialSheet
|
||||||
|
name="balance-sheet"
|
||||||
companyName={organizationSettings.name}
|
companyName={organizationSettings.name}
|
||||||
sheetType={formatMessage({ id: 'balance_sheet' })}
|
sheetType={formatMessage({ id: 'balance_sheet' })}
|
||||||
fromDate={balanceSheetQuery.from_date}
|
fromDate={balanceSheetQuery.from_date}
|
||||||
toDate={balanceSheetQuery.to_date}
|
toDate={balanceSheetQuery.to_date}
|
||||||
basis={balanceSheetQuery.basis}
|
basis={balanceSheetQuery.basis}
|
||||||
loading={loading}
|
loading={balanceSheetLoading}
|
||||||
>
|
>
|
||||||
<DataTable
|
<DataTable
|
||||||
className="bigcapital-datatable--financial-report"
|
className="bigcapital-datatable--financial-report"
|
||||||
columns={columns}
|
columns={columns}
|
||||||
data={balanceSheetAccounts}
|
data={balanceSheetAccounts}
|
||||||
onFetchData={handleFetchData}
|
onFetchData={handleFetchData}
|
||||||
|
noInitialFetch={true}
|
||||||
expanded={expandedRows}
|
expanded={expandedRows}
|
||||||
expandSubRows={true}
|
expandSubRows={true}
|
||||||
sticky={true}
|
sticky={true}
|
||||||
@@ -124,10 +130,16 @@ const withBalanceSheetTable = connect(mapStateToProps);
|
|||||||
export default compose(
|
export default compose(
|
||||||
withBalanceSheetTable,
|
withBalanceSheetTable,
|
||||||
withBalanceSheetDetail(
|
withBalanceSheetDetail(
|
||||||
({ balanceSheetAccounts, balanceSheetColumns, balanceSheetQuery }) => ({
|
({
|
||||||
balanceSheetAccounts,
|
balanceSheetAccounts,
|
||||||
balanceSheetColumns,
|
balanceSheetColumns,
|
||||||
balanceSheetQuery,
|
balanceSheetQuery,
|
||||||
|
balanceSheetLoading,
|
||||||
|
}) => ({
|
||||||
|
balanceSheetAccounts,
|
||||||
|
balanceSheetColumns,
|
||||||
|
balanceSheetQuery,
|
||||||
|
balanceSheetLoading,
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
withSettings,
|
withSettings,
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
import {connect} from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import {
|
import {
|
||||||
fetchBalanceSheet,
|
fetchBalanceSheet,
|
||||||
|
balanceSheetRefresh,
|
||||||
} from 'store/financialStatement/financialStatements.actions';
|
} from 'store/financialStatement/financialStatements.actions';
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
fetchBalanceSheet: (query = {}) => dispatch(fetchBalanceSheet({ query })),
|
fetchBalanceSheet: (query = {}) => dispatch(fetchBalanceSheet({ query })),
|
||||||
toggleBalanceSheetFilter: () => dispatch({ type: 'BALANCE_SHEET_FILTER_TOGGLE' }),
|
toggleBalanceSheetFilter: () =>
|
||||||
|
dispatch({ type: 'BALANCE_SHEET_FILTER_TOGGLE' }),
|
||||||
|
refreshBalanceSheet: (refresh) => dispatch(balanceSheetRefresh(refresh)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(null, mapDispatchToProps);
|
export default connect(null, mapDispatchToProps);
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ export default (mapState) => {
|
|||||||
balanceSheetQuery: getFinancialSheetQuery(state.financialStatements.balanceSheet.sheets, balanceSheetIndex),
|
balanceSheetQuery: getFinancialSheetQuery(state.financialStatements.balanceSheet.sheets, balanceSheetIndex),
|
||||||
balanceSheetLoading: state.financialStatements.balanceSheet.loading,
|
balanceSheetLoading: state.financialStatements.balanceSheet.loading,
|
||||||
balanceSheetFilter: state.financialStatements.balanceSheet.filter,
|
balanceSheetFilter: state.financialStatements.balanceSheet.filter,
|
||||||
|
balanceSheetRefresh: state.financialStatements.balanceSheet.refresh,
|
||||||
};
|
};
|
||||||
return mapState ? mapState(mapped, state, props) : mapped;
|
return mapState ? mapState(mapped, state, props) : mapped;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
import React, { useEffect } from 'react';
|
||||||
|
import { useIntl } from 'react-intl';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
import { For } from 'components';
|
||||||
|
|
||||||
|
import financialReportMenus from 'config/financialReportsMenu';
|
||||||
|
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||||
|
|
||||||
|
import { compose } from 'utils';
|
||||||
|
|
||||||
|
|
||||||
|
function FinancialReportsItem({
|
||||||
|
title,
|
||||||
|
desc,
|
||||||
|
link
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div class="financial-reports__item">
|
||||||
|
<Link class="title" to={link}>{ title }</Link>
|
||||||
|
<p class="desc">{ desc }</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function FinancialReportsSection({
|
||||||
|
sectionTitle,
|
||||||
|
reports
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div class="financial-reports__section">
|
||||||
|
<div class="section-title">{ sectionTitle }</div>
|
||||||
|
|
||||||
|
<div class="financial-reports__list">
|
||||||
|
<For render={FinancialReportsItem} of={reports} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function FinancialReports({
|
||||||
|
// #withDashboardActions
|
||||||
|
changePageTitle,
|
||||||
|
}) {
|
||||||
|
const { formatMessage } = useIntl();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
changePageTitle(formatMessage({ id: 'all_financial_reports' }));
|
||||||
|
}, [changePageTitle, formatMessage]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div class="financial-reports">
|
||||||
|
<For render={FinancialReportsSection} of={financialReportMenus} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default compose(
|
||||||
|
withDashboardActions
|
||||||
|
)(FinancialReports);
|
||||||
@@ -1,96 +1,98 @@
|
|||||||
import React, {useState, useCallback, useMemo} from 'react';
|
import React, { useState, useCallback, useMemo } from 'react';
|
||||||
import {Row, Col} from 'react-grid-system';
|
import { Row, Col } from 'react-grid-system';
|
||||||
import {momentFormatter} from 'utils';
|
import { momentFormatter } from 'utils';
|
||||||
import {DateInput} from '@blueprintjs/datetime';
|
import { DateInput } from '@blueprintjs/datetime';
|
||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
import {
|
import { HTMLSelect, FormGroup, Intent, Position } from '@blueprintjs/core';
|
||||||
HTMLSelect,
|
|
||||||
FormGroup,
|
|
||||||
Intent,
|
|
||||||
Position,
|
|
||||||
} from '@blueprintjs/core';
|
|
||||||
import Icon from 'components/Icon';
|
import Icon from 'components/Icon';
|
||||||
import { FieldHint } from 'components';
|
import { FieldHint } from 'components';
|
||||||
import {
|
import { parseDateRangeQuery } from 'utils';
|
||||||
parseDateRangeQuery
|
|
||||||
} from 'utils';
|
|
||||||
|
|
||||||
export default function FinancialStatementDateRange({
|
export default function FinancialStatementDateRange({ formik }) {
|
||||||
formik,
|
|
||||||
}) {
|
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const [reportDateRange, setReportDateRange] = useState('this_year');
|
const [reportDateRange, setReportDateRange] = useState('this_year');
|
||||||
|
|
||||||
const dateRangeOptions = useMemo(() => [
|
const dateRangeOptions = useMemo(
|
||||||
{value: 'today', label: 'Today', },
|
() => [
|
||||||
{value: 'this_week', label: 'This Week'},
|
{ value: 'today', label: 'Today' },
|
||||||
{value: 'this_month', label: 'This Month'},
|
{ value: 'this_week', label: 'This Week' },
|
||||||
{value: 'this_quarter', label: 'This Quarter'},
|
{ value: 'this_month', label: 'This Month' },
|
||||||
{value: 'this_year', label: 'This Year'},
|
{ value: 'this_quarter', label: 'This Quarter' },
|
||||||
{value: 'custom', label: 'Custom Range'},
|
{ value: 'this_year', label: 'This Year' },
|
||||||
], []);
|
{ value: 'custom', label: 'Custom Range' },
|
||||||
|
],
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
const handleDateChange = useCallback((name) => (date) => {
|
const handleDateChange = useCallback(
|
||||||
setReportDateRange('custom');
|
(name) => (date) => {
|
||||||
formik.setFieldValue(name, date);
|
setReportDateRange('custom');
|
||||||
}, [setReportDateRange, formik]);
|
formik.setFieldValue(name, date);
|
||||||
|
},
|
||||||
|
[setReportDateRange, formik],
|
||||||
|
);
|
||||||
|
|
||||||
// Handles date range field change.
|
// Handles date range field change.
|
||||||
const handleDateRangeChange = useCallback((e) => {
|
const handleDateRangeChange = useCallback(
|
||||||
const value = e.target.value;
|
(e) => {
|
||||||
if (value !== 'custom') {
|
const value = e.target.value;
|
||||||
const dateRange = parseDateRangeQuery(value);
|
if (value !== 'custom') {
|
||||||
if (dateRange) {
|
const dateRange = parseDateRangeQuery(value);
|
||||||
formik.setFieldValue('from_date', dateRange.from_date);
|
if (dateRange) {
|
||||||
formik.setFieldValue('to_date', dateRange.to_date);
|
formik.setFieldValue('from_date', dateRange.from_date);
|
||||||
|
formik.setFieldValue('to_date', dateRange.to_date);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
setReportDateRange(value);
|
||||||
setReportDateRange(value);
|
},
|
||||||
}, [formik]);
|
[formik],
|
||||||
|
);
|
||||||
|
|
||||||
const infoIcon = useMemo(() => (<Icon icon="info-circle" iconSize={12} />), []);
|
const infoIcon = useMemo(() => <Icon icon="info-circle" iconSize={12} />, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Row>
|
<>
|
||||||
<Col sm={3}>
|
<Col width={260}>
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={intl.formatMessage({'id': 'report_date_range'})}
|
label={intl.formatMessage({ id: 'report_date_range' })}
|
||||||
labelInfo={infoIcon}
|
labelInfo={infoIcon}
|
||||||
minimal={true}
|
minimal={true}
|
||||||
fill={true}>
|
fill={true}
|
||||||
|
>
|
||||||
<HTMLSelect
|
<HTMLSelect
|
||||||
fill={true}
|
fill={true}
|
||||||
options={dateRangeOptions}
|
options={dateRangeOptions}
|
||||||
value={reportDateRange}
|
value={reportDateRange}
|
||||||
onChange={handleDateRangeChange} />
|
onChange={handleDateRangeChange}
|
||||||
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
<Col sm={3}>
|
<Col width={260}>
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={intl.formatMessage({'id': 'from_date'})}
|
label={intl.formatMessage({ id: 'from_date' })}
|
||||||
labelInfo={infoIcon}
|
labelInfo={infoIcon}
|
||||||
fill={true}
|
fill={true}
|
||||||
intent={formik.errors.from_date && Intent.DANGER}>
|
intent={formik.errors.from_date && Intent.DANGER}
|
||||||
|
>
|
||||||
<DateInput
|
<DateInput
|
||||||
{...momentFormatter('YYYY/MM/DD')}
|
{...momentFormatter('YYYY/MM/DD')}
|
||||||
value={formik.values.from_date}
|
value={formik.values.from_date}
|
||||||
onChange={handleDateChange('from_date')}
|
onChange={handleDateChange('from_date')}
|
||||||
popoverProps={{ position: Position.BOTTOM }}
|
popoverProps={{ position: Position.BOTTOM }}
|
||||||
minimal={true}
|
minimal={true}
|
||||||
fill={true} />
|
fill={true}
|
||||||
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
<Col sm={3}>
|
<Col width={260}>
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={intl.formatMessage({'id': 'to_date'})}
|
label={intl.formatMessage({ id: 'to_date' })}
|
||||||
labelInfo={<FieldHint />}
|
labelInfo={<FieldHint />}
|
||||||
fill={true}
|
fill={true}
|
||||||
intent={formik.errors.to_date && Intent.DANGER}>
|
intent={formik.errors.to_date && Intent.DANGER}
|
||||||
|
>
|
||||||
<DateInput
|
<DateInput
|
||||||
{...momentFormatter('YYYY/MM/DD')}
|
{...momentFormatter('YYYY/MM/DD')}
|
||||||
value={formik.values.to_date}
|
value={formik.values.to_date}
|
||||||
@@ -98,9 +100,10 @@ export default function FinancialStatementDateRange({
|
|||||||
popoverProps={{ position: Position.BOTTOM }}
|
popoverProps={{ position: Position.BOTTOM }}
|
||||||
fill={true}
|
fill={true}
|
||||||
minimal={true}
|
minimal={true}
|
||||||
intent={formik.errors.to_date && Intent.DANGER} />
|
intent={formik.errors.to_date && Intent.DANGER}
|
||||||
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ function GeneralLedgerActionsBar({
|
|||||||
|
|
||||||
// #withGeneralLedgerActions
|
// #withGeneralLedgerActions
|
||||||
toggleGeneralLedgerSheetFilter,
|
toggleGeneralLedgerSheetFilter,
|
||||||
|
refreshGeneralLedgerSheet
|
||||||
}) {
|
}) {
|
||||||
const filterDropdown = FilterDropdown({
|
const filterDropdown = FilterDropdown({
|
||||||
fields: [],
|
fields: [],
|
||||||
@@ -41,6 +42,10 @@ function GeneralLedgerActionsBar({
|
|||||||
toggleGeneralLedgerSheetFilter();
|
toggleGeneralLedgerSheetFilter();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleRecalcReport = () => {
|
||||||
|
refreshGeneralLedgerSheet(true);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardActionsBar>
|
<DashboardActionsBar>
|
||||||
<NavbarGroup>
|
<NavbarGroup>
|
||||||
@@ -52,6 +57,16 @@ function GeneralLedgerActionsBar({
|
|||||||
|
|
||||||
<NavbarDivider />
|
<NavbarDivider />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
className={classNames(
|
||||||
|
Classes.MINIMAL,
|
||||||
|
'button--gray-highlight',
|
||||||
|
)}
|
||||||
|
text={'Re-calc Report'}
|
||||||
|
onClick={handleRecalcReport}
|
||||||
|
icon={<Icon icon="refresh-16" iconSize={16} />}
|
||||||
|
/>
|
||||||
|
|
||||||
<If condition={generalLedgerSheetFilter}>
|
<If condition={generalLedgerSheetFilter}>
|
||||||
<Button
|
<Button
|
||||||
className={Classes.MINIMAL}
|
className={Classes.MINIMAL}
|
||||||
@@ -69,7 +84,6 @@ function GeneralLedgerActionsBar({
|
|||||||
onClick={handleFilterClick}
|
onClick={handleFilterClick}
|
||||||
/>
|
/>
|
||||||
</If>
|
</If>
|
||||||
<NavbarDivider />
|
|
||||||
|
|
||||||
<Popover
|
<Popover
|
||||||
content={filterDropdown}
|
content={filterDropdown}
|
||||||
@@ -82,6 +96,8 @@ function GeneralLedgerActionsBar({
|
|||||||
icon={<Icon icon="filter-16" iconSize={16} /> } />
|
icon={<Icon icon="filter-16" iconSize={16} /> } />
|
||||||
</Popover>
|
</Popover>
|
||||||
|
|
||||||
|
<NavbarDivider />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
className={Classes.MINIMAL}
|
className={Classes.MINIMAL}
|
||||||
icon={<Icon icon='print-16' iconSize={16} />}
|
icon={<Icon icon='print-16' iconSize={16} />}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { useCallback } from 'react';
|
import React, { useEffect, useCallback } from 'react';
|
||||||
import { Button, FormGroup, Classes } from '@blueprintjs/core';
|
import { Button, FormGroup, Classes } from '@blueprintjs/core';
|
||||||
import { Row, Col } from 'react-grid-system';
|
import { Row, Col, Visible } from 'react-grid-system';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
import { useFormik } from 'formik';
|
import { useFormik } from 'formik';
|
||||||
@@ -13,9 +13,12 @@ import withAccounts from 'containers/Accounts/withAccounts';
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import FinancialStatementDateRange from 'containers/FinancialStatements/FinancialStatementDateRange';
|
import FinancialStatementDateRange from 'containers/FinancialStatements/FinancialStatementDateRange';
|
||||||
import RadiosAccountingBasis from '../RadiosAccountingBasis';
|
import RadiosAccountingBasis from '../RadiosAccountingBasis';
|
||||||
import { compose } from 'utils';
|
|
||||||
|
|
||||||
import withGeneralLedger from './withGeneralLedger';
|
import withGeneralLedger from './withGeneralLedger';
|
||||||
|
import withGeneralLedgerActions from './withGeneralLedgerActions';
|
||||||
|
|
||||||
|
import { compose } from 'utils';
|
||||||
|
|
||||||
|
|
||||||
function GeneralLedgerHeader({
|
function GeneralLedgerHeader({
|
||||||
onSubmitFilter,
|
onSubmitFilter,
|
||||||
@@ -24,8 +27,12 @@ function GeneralLedgerHeader({
|
|||||||
// #withAccounts
|
// #withAccounts
|
||||||
accounts,
|
accounts,
|
||||||
|
|
||||||
|
// #withGeneralLedgerActions
|
||||||
|
refreshGeneralLedgerSheet,
|
||||||
|
|
||||||
// #withGeneralLedger
|
// #withGeneralLedger
|
||||||
generalLedgerSheetFilter,
|
generalLedgerSheetFilter,
|
||||||
|
generalLedgerSheetRefresh
|
||||||
}) {
|
}) {
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
enableReinitialize: true,
|
enableReinitialize: true,
|
||||||
@@ -44,13 +51,8 @@ function GeneralLedgerHeader({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// handle submit filter submit button.
|
|
||||||
const handleSubmitClick = useCallback(() => {
|
|
||||||
formik.submitForm();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const onAccountSelected = useCallback((selectedAccounts) => {
|
const onAccountSelected = useCallback((selectedAccounts) => {
|
||||||
console.log(selectedAccounts);
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleAccountingBasisChange = useCallback(
|
const handleAccountingBasisChange = useCallback(
|
||||||
@@ -59,13 +61,23 @@ function GeneralLedgerHeader({
|
|||||||
},
|
},
|
||||||
[formik],
|
[formik],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// handle submit filter submit button.
|
||||||
|
useEffect(() => {
|
||||||
|
if (generalLedgerSheetRefresh) {
|
||||||
|
formik.submitForm();
|
||||||
|
refreshGeneralLedgerSheet(false);
|
||||||
|
}
|
||||||
|
}, [formik, generalLedgerSheetRefresh])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FinancialStatementHeader show={generalLedgerSheetFilter}>
|
<FinancialStatementHeader show={generalLedgerSheetFilter}>
|
||||||
<FinancialStatementDateRange formik={formik} />
|
|
||||||
|
|
||||||
<Row>
|
<Row>
|
||||||
<Col sm={3}>
|
<FinancialStatementDateRange formik={formik} />
|
||||||
|
|
||||||
|
<Visible xl><Col width={'100%'} /></Visible>
|
||||||
|
|
||||||
|
<Col width={260}>
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={<T id={'specific_accounts'} />}
|
label={<T id={'specific_accounts'} />}
|
||||||
className={classNames('form-group--select-list', Classes.FILL)}
|
className={classNames('form-group--select-list', Classes.FILL)}
|
||||||
@@ -77,23 +89,13 @@ function GeneralLedgerHeader({
|
|||||||
</FormGroup>
|
</FormGroup>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
<Col sm={3}>
|
<Col width={260}>
|
||||||
<RadiosAccountingBasis
|
<RadiosAccountingBasis
|
||||||
onChange={handleAccountingBasisChange}
|
onChange={handleAccountingBasisChange}
|
||||||
selectedValue={formik.values.basis}
|
selectedValue={formik.values.basis}
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
<Col sm={3}>
|
|
||||||
<Button
|
|
||||||
type="submit"
|
|
||||||
onClick={handleSubmitClick}
|
|
||||||
disabled={formik.isSubmitting}
|
|
||||||
className={'button--submit-filter mt2'}
|
|
||||||
>
|
|
||||||
<T id={'calculate_report'} />
|
|
||||||
</Button>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
</Row>
|
||||||
</FinancialStatementHeader>
|
</FinancialStatementHeader>
|
||||||
);
|
);
|
||||||
@@ -103,7 +105,9 @@ export default compose(
|
|||||||
withAccounts(({ accounts }) => ({
|
withAccounts(({ accounts }) => ({
|
||||||
accounts,
|
accounts,
|
||||||
})),
|
})),
|
||||||
withGeneralLedger(({ generalLedgerSheetFilter }) => ({
|
withGeneralLedger(({ generalLedgerSheetFilter, generalLedgerSheetRefresh }) => ({
|
||||||
generalLedgerSheetFilter,
|
generalLedgerSheetFilter,
|
||||||
|
generalLedgerSheetRefresh,
|
||||||
})),
|
})),
|
||||||
|
withGeneralLedgerActions,
|
||||||
)(GeneralLedgerHeader);
|
)(GeneralLedgerHeader);
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
import {connect} from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import {
|
import {
|
||||||
getFinancialSheet,
|
getFinancialSheet,
|
||||||
getFinancialSheetQuery,
|
getFinancialSheetQuery,
|
||||||
getFinancialSheetTableRows,
|
getFinancialSheetTableRows,
|
||||||
} from 'store/financialStatement/financialStatements.selectors';
|
} from 'store/financialStatement/financialStatements.selectors';
|
||||||
|
|
||||||
|
|
||||||
export default (mapState) => {
|
export default (mapState) => {
|
||||||
const mapStateToProps = (state, props) => {
|
const mapStateToProps = (state, props) => {
|
||||||
const { generalLedgerIndex } = props;
|
const { generalLedgerIndex } = props;
|
||||||
@@ -23,8 +22,11 @@ export default (mapState) => {
|
|||||||
state.financialStatements.generalLedger.sheets,
|
state.financialStatements.generalLedger.sheets,
|
||||||
generalLedgerIndex,
|
generalLedgerIndex,
|
||||||
),
|
),
|
||||||
generalLedgerSheetLoading: state.financialStatements.generalLedger.loading,
|
generalLedgerSheetLoading:
|
||||||
|
state.financialStatements.generalLedger.loading,
|
||||||
generalLedgerSheetFilter: state.financialStatements.generalLedger.filter,
|
generalLedgerSheetFilter: state.financialStatements.generalLedger.filter,
|
||||||
|
generalLedgerSheetRefresh:
|
||||||
|
state.financialStatements.generalLedger.refresh,
|
||||||
};
|
};
|
||||||
return mapState ? mapState(mapped, state, props) : mapped;
|
return mapState ? mapState(mapped, state, props) : mapped;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
import {connect} from 'react-redux';
|
import {connect} from 'react-redux';
|
||||||
import {
|
import {
|
||||||
fetchGeneralLedger,
|
fetchGeneralLedger,
|
||||||
|
refreshGeneralLedgerSheet,
|
||||||
} from 'store/financialStatement/financialStatements.actions';
|
} from 'store/financialStatement/financialStatements.actions';
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
fetchGeneralLedger: (query = {}) => dispatch(fetchGeneralLedger({ query })),
|
fetchGeneralLedger: (query = {}) => dispatch(fetchGeneralLedger({ query })),
|
||||||
toggleGeneralLedgerSheetFilter: () => dispatch({ type: 'GENERAL_LEDGER_FILTER_TOGGLE' }),
|
toggleGeneralLedgerSheetFilter: () => dispatch({ type: 'GENERAL_LEDGER_FILTER_TOGGLE' }),
|
||||||
|
refreshGeneralLedgerSheet: (refresh) => dispatch(refreshGeneralLedgerSheet(refresh)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(null, mapDispatchToProps);
|
export default connect(null, mapDispatchToProps);
|
||||||
@@ -27,6 +27,7 @@ function JournalActionsBar({
|
|||||||
|
|
||||||
// #withJournalActions
|
// #withJournalActions
|
||||||
toggleJournalSheetFilter,
|
toggleJournalSheetFilter,
|
||||||
|
refreshJournalSheet,
|
||||||
}) {
|
}) {
|
||||||
const filterDropdown = FilterDropdown({
|
const filterDropdown = FilterDropdown({
|
||||||
fields: [],
|
fields: [],
|
||||||
@@ -37,6 +38,10 @@ function JournalActionsBar({
|
|||||||
toggleJournalSheetFilter();
|
toggleJournalSheetFilter();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleRecalcReport = () => {
|
||||||
|
refreshJournalSheet(true);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardActionsBar>
|
<DashboardActionsBar>
|
||||||
<NavbarGroup>
|
<NavbarGroup>
|
||||||
@@ -47,6 +52,13 @@ function JournalActionsBar({
|
|||||||
/>
|
/>
|
||||||
<NavbarDivider />
|
<NavbarDivider />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
className={classNames(Classes.MINIMAL, 'button--gray-highlight')}
|
||||||
|
text={'Re-calc Report'}
|
||||||
|
onClick={handleRecalcReport}
|
||||||
|
icon={<Icon icon="refresh-16" iconSize={16} />}
|
||||||
|
/>
|
||||||
|
|
||||||
<If condition={journalSheetFilter}>
|
<If condition={journalSheetFilter}>
|
||||||
<Button
|
<Button
|
||||||
className={Classes.MINIMAL}
|
className={Classes.MINIMAL}
|
||||||
@@ -64,7 +76,6 @@ function JournalActionsBar({
|
|||||||
onClick={handleFilterToggleClick}
|
onClick={handleFilterToggleClick}
|
||||||
/>
|
/>
|
||||||
</If>
|
</If>
|
||||||
<NavbarDivider />
|
|
||||||
|
|
||||||
<Popover
|
<Popover
|
||||||
content={filterDropdown}
|
content={filterDropdown}
|
||||||
@@ -78,9 +89,11 @@ function JournalActionsBar({
|
|||||||
/>
|
/>
|
||||||
</Popover>
|
</Popover>
|
||||||
|
|
||||||
|
<NavbarDivider />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
className={Classes.MINIMAL}
|
className={Classes.MINIMAL}
|
||||||
icon={<Icon icon='print-16' iconSize={16} />}
|
icon={<Icon icon="print-16" iconSize={16} />}
|
||||||
text={<T id={'print'} />}
|
text={<T id={'print'} />}
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
import React, { useCallback } from 'react';
|
import React, { useCallback, useEffect } from 'react';
|
||||||
import { Row, Col } from 'react-grid-system';
|
import { Row, Col } from 'react-grid-system';
|
||||||
import {
|
import { Button } from '@blueprintjs/core';
|
||||||
Button,
|
|
||||||
} from '@blueprintjs/core';
|
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { useFormik } from 'formik';
|
import { useFormik } from 'formik';
|
||||||
import { FormattedMessage as T } from 'react-intl';
|
import { FormattedMessage as T } from 'react-intl';
|
||||||
@@ -12,24 +10,30 @@ import FinancialStatementDateRange from 'containers/FinancialStatements/Financia
|
|||||||
import FinancialStatementHeader from 'containers/FinancialStatements/FinancialStatementHeader';
|
import FinancialStatementHeader from 'containers/FinancialStatements/FinancialStatementHeader';
|
||||||
|
|
||||||
import withJournal from './withJournal';
|
import withJournal from './withJournal';
|
||||||
|
import withJournalActions from './withJournalActions';
|
||||||
|
|
||||||
import { compose } from 'utils';
|
import { compose } from 'utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Journal sheet header.
|
* Journal sheet header.
|
||||||
*/
|
*/
|
||||||
function JournalHeader({
|
function JournalHeader({
|
||||||
pageFilter,
|
pageFilter,
|
||||||
onSubmitFilter,
|
onSubmitFilter,
|
||||||
|
|
||||||
|
// #withJournalActions
|
||||||
|
refreshJournalSheet,
|
||||||
|
|
||||||
// #withJournal
|
// #withJournal
|
||||||
journalSheetFilter,
|
journalSheetFilter,
|
||||||
|
journalSheetRefresh,
|
||||||
}) {
|
}) {
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
enableReinitialize: true,
|
enableReinitialize: true,
|
||||||
initialValues: {
|
initialValues: {
|
||||||
...pageFilter,
|
...pageFilter,
|
||||||
from_date: moment(pageFilter.from_date).toDate(),
|
from_date: moment(pageFilter.from_date).toDate(),
|
||||||
to_date: moment(pageFilter.to_date).toDate()
|
to_date: moment(pageFilter.to_date).toDate(),
|
||||||
},
|
},
|
||||||
validationSchema: Yup.object().shape({
|
validationSchema: Yup.object().shape({
|
||||||
from_date: Yup.date().required(),
|
from_date: Yup.date().required(),
|
||||||
@@ -41,29 +45,29 @@ function JournalHeader({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleSubmitClick = useCallback(() => {
|
useEffect(() => {
|
||||||
formik.submitForm();
|
if (journalSheetRefresh) {
|
||||||
}, [formik]);
|
formik.submitForm();
|
||||||
|
refreshJournalSheet(false);
|
||||||
|
}
|
||||||
|
}, [formik, journalSheetRefresh]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FinancialStatementHeader show={journalSheetFilter}>
|
<FinancialStatementHeader show={journalSheetFilter}>
|
||||||
<FinancialStatementDateRange formik={formik} />
|
|
||||||
|
|
||||||
<Row>
|
<Row>
|
||||||
<Col sm={3}>
|
<FinancialStatementDateRange formik={formik} />
|
||||||
<Button
|
|
||||||
type="submit"
|
|
||||||
onClick={handleSubmitClick}
|
|
||||||
className={'button--submit-filter'}>
|
|
||||||
<T id={'run_report'} />
|
|
||||||
</Button>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
</FinancialStatementHeader>
|
</FinancialStatementHeader>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
withJournal(({ journalSheetFilter }) => ({ journalSheetFilter })),
|
withJournal(({
|
||||||
)(JournalHeader);
|
journalSheetFilter,
|
||||||
|
journalSheetRefresh
|
||||||
|
}) => ({
|
||||||
|
journalSheetFilter,
|
||||||
|
journalSheetRefresh,
|
||||||
|
})),
|
||||||
|
withJournalActions,
|
||||||
|
)(JournalHeader);
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ export default (mapState) => {
|
|||||||
),
|
),
|
||||||
journalSheetLoading: state.financialStatements.journal.loading,
|
journalSheetLoading: state.financialStatements.journal.loading,
|
||||||
journalSheetFilter: state.financialStatements.journal.filter,
|
journalSheetFilter: state.financialStatements.journal.filter,
|
||||||
|
journalSheetRefresh: state.financialStatements.journal.refresh,
|
||||||
};
|
};
|
||||||
return mapState ? mapState(mapped, state, props) : mapped;
|
return mapState ? mapState(mapped, state, props) : mapped;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
import {connect} from 'react-redux';
|
import {connect} from 'react-redux';
|
||||||
import {
|
import {
|
||||||
fetchJournalSheet
|
fetchJournalSheet,
|
||||||
|
refreshJournalSheet,
|
||||||
} from 'store/financialStatement/financialStatements.actions';
|
} from 'store/financialStatement/financialStatements.actions';
|
||||||
|
|
||||||
export const mapDispatchToProps = (dispatch) => ({
|
export const mapDispatchToProps = (dispatch) => ({
|
||||||
requestFetchJournalSheet: (query) => dispatch(fetchJournalSheet({ query })),
|
requestFetchJournalSheet: (query) => dispatch(fetchJournalSheet({ query })),
|
||||||
toggleJournalSheetFilter: () => dispatch({ type: 'JOURNAL_FILTER_TOGGLE' }),
|
toggleJournalSheetFilter: () => dispatch({ type: 'JOURNAL_FILTER_TOGGLE' }),
|
||||||
|
refreshJournalSheet: (refresh) => dispatch(refreshJournalSheet(refresh)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(null, mapDispatchToProps);
|
export default connect(null, mapDispatchToProps);
|
||||||
@@ -19,11 +19,16 @@ function ProfitLossActionsBar({
|
|||||||
|
|
||||||
// #withProfitLossActions
|
// #withProfitLossActions
|
||||||
toggleProfitLossSheetFilter,
|
toggleProfitLossSheetFilter,
|
||||||
|
refreshProfitLossSheet,
|
||||||
}) {
|
}) {
|
||||||
const handleFilterClick = () => {
|
const handleFilterClick = () => {
|
||||||
toggleProfitLossSheetFilter();
|
toggleProfitLossSheetFilter();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleRecalcReport = () => {
|
||||||
|
refreshProfitLossSheet(true);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardActionsBar>
|
<DashboardActionsBar>
|
||||||
<NavbarGroup>
|
<NavbarGroup>
|
||||||
@@ -34,6 +39,16 @@ function ProfitLossActionsBar({
|
|||||||
/>
|
/>
|
||||||
<NavbarDivider />
|
<NavbarDivider />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
className={classNames(
|
||||||
|
Classes.MINIMAL,
|
||||||
|
'button--gray-highlight',
|
||||||
|
)}
|
||||||
|
text={'Re-calc Report'}
|
||||||
|
onClick={handleRecalcReport}
|
||||||
|
icon={<Icon icon="refresh-16" iconSize={16} />}
|
||||||
|
/>
|
||||||
|
|
||||||
<If condition={profitLossSheetFilter}>
|
<If condition={profitLossSheetFilter}>
|
||||||
<Button
|
<Button
|
||||||
className={Classes.MINIMAL}
|
className={Classes.MINIMAL}
|
||||||
|
|||||||
@@ -24,9 +24,6 @@ function ProfitLossSheet({
|
|||||||
// #withProfitLossActions
|
// #withProfitLossActions
|
||||||
fetchProfitLossSheet,
|
fetchProfitLossSheet,
|
||||||
|
|
||||||
// #withProfitLoss
|
|
||||||
profitLossSheetLoading,
|
|
||||||
|
|
||||||
// #withPreferences
|
// #withPreferences
|
||||||
organizationSettings,
|
organizationSettings,
|
||||||
}) {
|
}) {
|
||||||
@@ -35,6 +32,7 @@ function ProfitLossSheet({
|
|||||||
from_date: moment().startOf('year').format('YYYY-MM-DD'),
|
from_date: moment().startOf('year').format('YYYY-MM-DD'),
|
||||||
to_date: moment().endOf('year').format('YYYY-MM-DD'),
|
to_date: moment().endOf('year').format('YYYY-MM-DD'),
|
||||||
});
|
});
|
||||||
|
const [refresh, setRefresh] = useState(true);
|
||||||
|
|
||||||
// Change page title of the dashboard.
|
// Change page title of the dashboard.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -54,14 +52,21 @@ function ProfitLossSheet({
|
|||||||
to_date: moment(filter.to_date).format('YYYY-MM-DD'),
|
to_date: moment(filter.to_date).format('YYYY-MM-DD'),
|
||||||
};
|
};
|
||||||
setFilter(_filter);
|
setFilter(_filter);
|
||||||
fetchHook.refetch({ force: true });
|
setRefresh(true);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Handle fetch data of profit/loss sheet table.
|
// Handle fetch data of profit/loss sheet table.
|
||||||
const handleFetchData = useCallback(() => {
|
const handleFetchData = useCallback(() => {
|
||||||
fetchHook.refetch({ force: true });
|
setRefresh(true);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (refresh) {
|
||||||
|
fetchHook.refetch({ force: true });
|
||||||
|
setRefresh(false);
|
||||||
|
}
|
||||||
|
}, [refresh, fetchHook]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardInsider>
|
<DashboardInsider>
|
||||||
<ProfitLossActionsBar />
|
<ProfitLossActionsBar />
|
||||||
@@ -76,8 +81,7 @@ function ProfitLossSheet({
|
|||||||
<ProfitLossSheetTable
|
<ProfitLossSheetTable
|
||||||
companyName={organizationSettings.name}
|
companyName={organizationSettings.name}
|
||||||
profitLossQuery={filter}
|
profitLossQuery={filter}
|
||||||
onFetchData={handleFetchData}
|
onFetchData={handleFetchData} />
|
||||||
loading={profitLossSheetLoading} />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</DashboardPageContent>
|
</DashboardPageContent>
|
||||||
@@ -88,8 +92,5 @@ function ProfitLossSheet({
|
|||||||
export default compose(
|
export default compose(
|
||||||
withDashboardActions,
|
withDashboardActions,
|
||||||
withProfitLossActions,
|
withProfitLossActions,
|
||||||
withProfitLoss(({ profitLossSheetLoading }) => ({
|
|
||||||
profitLossSheetLoading,
|
|
||||||
})),
|
|
||||||
withSettings,
|
withSettings,
|
||||||
)(ProfitLossSheet);
|
)(ProfitLossSheet);
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { useCallback } from 'react';
|
import React, { useCallback, useEffect } from 'react';
|
||||||
import { Row, Col } from 'react-grid-system';
|
import { Row, Col, Visible } from 'react-grid-system';
|
||||||
import { Button } from '@blueprintjs/core';
|
import { Button } from '@blueprintjs/core';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { useFormik } from 'formik';
|
import { useFormik } from 'formik';
|
||||||
@@ -11,6 +11,7 @@ import SelectsListColumnsBy from '../SelectDisplayColumnsBy';
|
|||||||
import RadiosAccountingBasis from '../RadiosAccountingBasis';
|
import RadiosAccountingBasis from '../RadiosAccountingBasis';
|
||||||
|
|
||||||
import withProfitLoss from './withProfitLoss';
|
import withProfitLoss from './withProfitLoss';
|
||||||
|
import withProfitLossActions from './withProfitLossActions';
|
||||||
|
|
||||||
import { compose } from 'utils';
|
import { compose } from 'utils';
|
||||||
|
|
||||||
@@ -21,6 +22,10 @@ function ProfitLossHeader({
|
|||||||
|
|
||||||
// #withProfitLoss
|
// #withProfitLoss
|
||||||
profitLossSheetFilter,
|
profitLossSheetFilter,
|
||||||
|
profitLossSheetRefresh,
|
||||||
|
|
||||||
|
// #withProfitLossActions
|
||||||
|
refreshProfitLossSheet,
|
||||||
}) {
|
}) {
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
@@ -54,10 +59,6 @@ function ProfitLossHeader({
|
|||||||
[formik],
|
[formik],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleSubmitClick = useCallback(() => {
|
|
||||||
formik.submitForm();
|
|
||||||
}, [formik]);
|
|
||||||
|
|
||||||
const handleAccountingBasisChange = useCallback(
|
const handleAccountingBasisChange = useCallback(
|
||||||
(value) => {
|
(value) => {
|
||||||
formik.setFieldValue('basis', value);
|
formik.setFieldValue('basis', value);
|
||||||
@@ -65,36 +66,41 @@ function ProfitLossHeader({
|
|||||||
[formik],
|
[formik],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (profitLossSheetRefresh) {
|
||||||
|
formik.submitForm();
|
||||||
|
refreshProfitLossSheet(false);
|
||||||
|
}
|
||||||
|
}, [profitLossSheetRefresh]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FinancialStatementHeader show={profitLossSheetFilter}>
|
<FinancialStatementHeader show={profitLossSheetFilter}>
|
||||||
<FinancialStatementDateRange formik={formik} />
|
|
||||||
|
|
||||||
<Row>
|
<Row>
|
||||||
<Col sm={3}>
|
<FinancialStatementDateRange formik={formik} />
|
||||||
|
<Visible xl><Col width={'100%'} /></Visible>
|
||||||
|
|
||||||
|
<Col width={260}>
|
||||||
<SelectsListColumnsBy onItemSelect={handleItemSelectDisplayColumns} />
|
<SelectsListColumnsBy onItemSelect={handleItemSelectDisplayColumns} />
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
<Col sm={3}>
|
<Col width={260}>
|
||||||
<RadiosAccountingBasis
|
<RadiosAccountingBasis
|
||||||
selectedValue={formik.values.basis}
|
selectedValue={formik.values.basis}
|
||||||
onChange={handleAccountingBasisChange}
|
onChange={handleAccountingBasisChange}
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
<Col sm={3}>
|
|
||||||
<Button
|
|
||||||
type="submit"
|
|
||||||
onClick={handleSubmitClick}
|
|
||||||
className={'button--submit-filter mt2'}
|
|
||||||
>
|
|
||||||
<T id={'run_report'} />
|
|
||||||
</Button>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
</Row>
|
||||||
</FinancialStatementHeader>
|
</FinancialStatementHeader>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
withProfitLoss(({ profitLossSheetFilter }) => ({ profitLossSheetFilter })),
|
withProfitLoss(({
|
||||||
|
profitLossSheetFilter,
|
||||||
|
profitLossSheetRefresh,
|
||||||
|
}) => ({
|
||||||
|
profitLossSheetFilter,
|
||||||
|
profitLossSheetRefresh,
|
||||||
|
})),
|
||||||
|
withProfitLossActions,
|
||||||
)(ProfitLossHeader);
|
)(ProfitLossHeader);
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ function ProfitLossSheetTable({
|
|||||||
profitLossTableRows,
|
profitLossTableRows,
|
||||||
profitLossQuery,
|
profitLossQuery,
|
||||||
profitLossColumns,
|
profitLossColumns,
|
||||||
|
profitLossSheetLoading,
|
||||||
|
|
||||||
// #ownProps
|
// #ownProps
|
||||||
loading,
|
|
||||||
onFetchData,
|
onFetchData,
|
||||||
companyName,
|
companyName,
|
||||||
}) {
|
}) {
|
||||||
@@ -31,7 +31,7 @@ function ProfitLossSheetTable({
|
|||||||
className: 'name',
|
className: 'name',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: formatMessage({ id: 'acc_code' }),
|
Header: formatMessage({ id: 'account_code' }),
|
||||||
accessor: 'code',
|
accessor: 'code',
|
||||||
className: 'account_code',
|
className: 'account_code',
|
||||||
},
|
},
|
||||||
@@ -102,7 +102,7 @@ function ProfitLossSheetTable({
|
|||||||
fromDate={profitLossQuery.from_date}
|
fromDate={profitLossQuery.from_date}
|
||||||
toDate={profitLossQuery.to_date}
|
toDate={profitLossQuery.to_date}
|
||||||
name="profit-loss-sheet"
|
name="profit-loss-sheet"
|
||||||
loading={loading}
|
loading={profitLossSheetLoading}
|
||||||
basis={profitLossQuery.basis}
|
basis={profitLossQuery.basis}
|
||||||
>
|
>
|
||||||
<DataTable
|
<DataTable
|
||||||
@@ -110,6 +110,7 @@ function ProfitLossSheetTable({
|
|||||||
columns={columns}
|
columns={columns}
|
||||||
data={profitLossTableRows}
|
data={profitLossTableRows}
|
||||||
onFetchData={handleFetchData}
|
onFetchData={handleFetchData}
|
||||||
|
noInitialFetch={true}
|
||||||
expanded={expandedRows}
|
expanded={expandedRows}
|
||||||
rowClassNames={rowClassNames}
|
rowClassNames={rowClassNames}
|
||||||
expandable={true}
|
expandable={true}
|
||||||
@@ -132,10 +133,11 @@ const withProfitLossTable = connect(mapStateToProps);
|
|||||||
export default compose(
|
export default compose(
|
||||||
withProfitLossTable,
|
withProfitLossTable,
|
||||||
withProfitLossDetail(
|
withProfitLossDetail(
|
||||||
({ profitLossQuery, profitLossColumns, profitLossTableRows }) => ({
|
({ profitLossQuery, profitLossColumns, profitLossTableRows, profitLossSheetLoading }) => ({
|
||||||
profitLossColumns,
|
profitLossColumns,
|
||||||
profitLossQuery,
|
profitLossQuery,
|
||||||
profitLossTableRows,
|
profitLossTableRows,
|
||||||
|
profitLossSheetLoading,
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
)(ProfitLossSheetTable);
|
)(ProfitLossSheetTable);
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ export default (mapState) => {
|
|||||||
|
|
||||||
profitLossSheetLoading: state.financialStatements.profitLoss.loading,
|
profitLossSheetLoading: state.financialStatements.profitLoss.loading,
|
||||||
profitLossSheetFilter: state.financialStatements.profitLoss.filter,
|
profitLossSheetFilter: state.financialStatements.profitLoss.filter,
|
||||||
|
profitLossSheetRefresh: state.financialStatements.profitLoss.refresh,
|
||||||
};
|
};
|
||||||
return mapState ? mapState(mapped, state, props) : mapped;
|
return mapState ? mapState(mapped, state, props) : mapped;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
import {connect} from 'react-redux';
|
import {connect} from 'react-redux';
|
||||||
import {
|
import {
|
||||||
fetchProfitLossSheet,
|
fetchProfitLossSheet,
|
||||||
|
profitLossRefresh,
|
||||||
} from 'store/financialStatement/financialStatements.actions';
|
} from 'store/financialStatement/financialStatements.actions';
|
||||||
|
|
||||||
export const mapDispatchToProps = (dispatch) => ({
|
export const mapDispatchToProps = (dispatch) => ({
|
||||||
fetchProfitLossSheet: (query = {}) => dispatch(fetchProfitLossSheet({ query })),
|
fetchProfitLossSheet: (query = {}) => dispatch(fetchProfitLossSheet({ query })),
|
||||||
toggleProfitLossSheetFilter: () => dispatch({ type: 'PROFIT_LOSS_FILTER_TOGGLE' }),
|
toggleProfitLossSheetFilter: () => dispatch({ type: 'PROFIT_LOSS_FILTER_TOGGLE' }),
|
||||||
|
refreshProfitLossSheet: (refresh) => dispatch(profitLossRefresh(refresh)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(null, mapDispatchToProps);
|
export default connect(null, mapDispatchToProps);
|
||||||
@@ -25,23 +25,25 @@ function ReceivableAgingSummarySheet({
|
|||||||
}) {
|
}) {
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
const [query, setQuery] = useState({
|
const [query, setQuery] = useState({
|
||||||
as_date: moment().format('YYYY-MM-DD'),
|
as_date: moment().endOf('day').format('YYYY-MM-DD'),
|
||||||
aging_before_days: 30,
|
aging_before_days: 30,
|
||||||
aging_periods: 3,
|
aging_periods: 3,
|
||||||
});
|
});
|
||||||
|
const [refresh, setRefresh] = useState(true);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
changePageTitle(formatMessage({ id: 'receivable_aging_summary' }));
|
changePageTitle(formatMessage({ id: 'receivable_aging_summary' }));
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const fetchSheet = useQuery(['receivable-aging-summary', query],
|
const fetchSheet = useQuery(
|
||||||
|
['receivable-aging-summary', query],
|
||||||
(key, q) => requestReceivableAgingSummary(q),
|
(key, q) => requestReceivableAgingSummary(q),
|
||||||
{ manual: true });
|
{ manual: true });
|
||||||
|
|
||||||
// Handle fetch the data of receivable aging summary sheet.
|
// Handle fetch the data of receivable aging summary sheet.
|
||||||
const handleFetchData = useCallback(() => {
|
const handleFetchData = useCallback((...args) => {
|
||||||
fetchSheet.refetch({ force: true });
|
setRefresh(true);
|
||||||
}, [fetchSheet]);
|
}, []);
|
||||||
|
|
||||||
const handleFilterSubmit = useCallback((filter) => {
|
const handleFilterSubmit = useCallback((filter) => {
|
||||||
const _filter = {
|
const _filter = {
|
||||||
@@ -49,8 +51,15 @@ function ReceivableAgingSummarySheet({
|
|||||||
as_date: moment(filter.as_date).format('YYYY-MM-DD'),
|
as_date: moment(filter.as_date).format('YYYY-MM-DD'),
|
||||||
};
|
};
|
||||||
setQuery(_filter);
|
setQuery(_filter);
|
||||||
fetchSheet.refetch({ force: true });
|
setRefresh(true);
|
||||||
}, [fetchSheet]);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (refresh) {
|
||||||
|
fetchSheet.refetch({ force: true });
|
||||||
|
setRefresh(false);
|
||||||
|
}
|
||||||
|
}, [fetchSheet, refresh]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardInsider>
|
<DashboardInsider>
|
||||||
@@ -59,6 +68,7 @@ function ReceivableAgingSummarySheet({
|
|||||||
<DashboardPageContent>
|
<DashboardPageContent>
|
||||||
<FinancialStatement>
|
<FinancialStatement>
|
||||||
<ReceivableAgingSummaryHeader
|
<ReceivableAgingSummaryHeader
|
||||||
|
pageFilter={query}
|
||||||
onSubmitFilter={handleFilterSubmit} />
|
onSubmitFilter={handleFilterSubmit} />
|
||||||
|
|
||||||
<div class="financial-statement__body">
|
<div class="financial-statement__body">
|
||||||
|
|||||||
@@ -23,8 +23,12 @@ import { compose } from 'utils';
|
|||||||
|
|
||||||
|
|
||||||
function ReceivableAgingSummaryActionsBar({
|
function ReceivableAgingSummaryActionsBar({
|
||||||
toggleFilterReceivableAgingSummary,
|
// #withReceivableAging
|
||||||
receivableAgingFilter,
|
receivableAgingFilter,
|
||||||
|
|
||||||
|
// #withReceivableAgingActions
|
||||||
|
toggleFilterReceivableAgingSummary,
|
||||||
|
refreshReceivableAgingSummary,
|
||||||
}) {
|
}) {
|
||||||
const filterDropdown = FilterDropdown({
|
const filterDropdown = FilterDropdown({
|
||||||
fields: [],
|
fields: [],
|
||||||
@@ -35,6 +39,10 @@ function ReceivableAgingSummaryActionsBar({
|
|||||||
toggleFilterReceivableAgingSummary();
|
toggleFilterReceivableAgingSummary();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleRecalcReport = () => {
|
||||||
|
refreshReceivableAgingSummary(true);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardActionsBar>
|
<DashboardActionsBar>
|
||||||
<NavbarGroup>
|
<NavbarGroup>
|
||||||
@@ -45,6 +53,16 @@ function ReceivableAgingSummaryActionsBar({
|
|||||||
/>
|
/>
|
||||||
<NavbarDivider />
|
<NavbarDivider />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
className={classNames(
|
||||||
|
Classes.MINIMAL,
|
||||||
|
'button--gray-highlight',
|
||||||
|
)}
|
||||||
|
text={<T id={'recalc_report'} />}
|
||||||
|
icon={<Icon icon="refresh-16" iconSize={16} />}
|
||||||
|
onClick={handleRecalcReport}
|
||||||
|
/>
|
||||||
|
|
||||||
<If condition={receivableAgingFilter}>
|
<If condition={receivableAgingFilter}>
|
||||||
<Button
|
<Button
|
||||||
className={Classes.MINIMAL}
|
className={Classes.MINIMAL}
|
||||||
@@ -62,7 +80,6 @@ function ReceivableAgingSummaryActionsBar({
|
|||||||
icon={<Icon icon="arrow-to-bottom" />}
|
icon={<Icon icon="arrow-to-bottom" />}
|
||||||
/>
|
/>
|
||||||
</If>
|
</If>
|
||||||
<NavbarDivider />
|
|
||||||
|
|
||||||
<Popover
|
<Popover
|
||||||
content={filterDropdown}
|
content={filterDropdown}
|
||||||
@@ -76,6 +93,8 @@ function ReceivableAgingSummaryActionsBar({
|
|||||||
/>
|
/>
|
||||||
</Popover>
|
</Popover>
|
||||||
|
|
||||||
|
<NavbarDivider />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
className={Classes.MINIMAL}
|
className={Classes.MINIMAL}
|
||||||
icon={<Icon icon='print-16' iconSize={16} />}
|
icon={<Icon icon='print-16' iconSize={16} />}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { useCallback } from 'react';
|
import React, { useCallback, useEffect } from 'react';
|
||||||
import { useIntl, FormattedMessage as T, } from 'react-intl';
|
import { useIntl, FormattedMessage as T } from 'react-intl';
|
||||||
import { useFormik } from "formik";
|
import { useFormik } from 'formik';
|
||||||
import { Row, Col } from 'react-grid-system';
|
import { Row, Col } from 'react-grid-system';
|
||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
import {
|
import {
|
||||||
@@ -11,22 +11,27 @@ import {
|
|||||||
Button,
|
Button,
|
||||||
} from '@blueprintjs/core';
|
} from '@blueprintjs/core';
|
||||||
import { DateInput } from '@blueprintjs/datetime';
|
import { DateInput } from '@blueprintjs/datetime';
|
||||||
|
import moment from 'moment';
|
||||||
import FinancialStatementHeader from 'containers/FinancialStatements/FinancialStatementHeader';
|
import FinancialStatementHeader from 'containers/FinancialStatements/FinancialStatementHeader';
|
||||||
import {
|
import { ErrorMessage, FieldHint, FieldRequiredHint } from 'components';
|
||||||
ErrorMessage,
|
import { momentFormatter } from 'utils';
|
||||||
FieldHint,
|
|
||||||
FieldRequiredHint,
|
|
||||||
} from 'components';
|
|
||||||
import {
|
|
||||||
momentFormatter,
|
|
||||||
} from 'utils';
|
|
||||||
|
|
||||||
import withReceivableAging from './withReceivableAgingSummary';
|
import withReceivableAging from './withReceivableAgingSummary';
|
||||||
|
import withReceivableAgingActions from './withReceivableAgingSummaryActions';
|
||||||
|
|
||||||
import { compose } from 'utils';
|
import { compose } from 'utils';
|
||||||
|
|
||||||
|
|
||||||
function ReceivableAgingSummaryHeader({
|
function ReceivableAgingSummaryHeader({
|
||||||
onSubmitFilter,
|
pageFilter,
|
||||||
|
onSubmitFilter,
|
||||||
receivableAgingFilter,
|
receivableAgingFilter,
|
||||||
|
|
||||||
|
// #withReceivableAgingSummary
|
||||||
|
receivableAgingRefresh,
|
||||||
|
|
||||||
|
// #withReceivableAgingSummaryActions
|
||||||
|
refreshReceivableAgingSummary
|
||||||
}) {
|
}) {
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
|
|
||||||
@@ -37,61 +42,75 @@ function ReceivableAgingSummaryHeader({
|
|||||||
setFieldValue,
|
setFieldValue,
|
||||||
getFieldProps,
|
getFieldProps,
|
||||||
submitForm,
|
submitForm,
|
||||||
isSubmitting
|
isSubmitting,
|
||||||
} = useFormik({
|
} = useFormik({
|
||||||
enableReinitialize: true,
|
enableReinitialize: true,
|
||||||
initialValues: {
|
initialValues: {
|
||||||
// as_date: new Date(),
|
as_date: moment(pageFilter.as_date).toDate(),
|
||||||
aging_before_days: 30,
|
aging_before_days: 30,
|
||||||
aging_periods: 3,
|
aging_periods: 3,
|
||||||
},
|
},
|
||||||
validationSchema: Yup.object().shape({
|
validationSchema: Yup.object().shape({
|
||||||
as_date: Yup.date().required().label('As date'),
|
as_date: Yup.date().required().label('as_date'),
|
||||||
aging_before_days: Yup.number().required().integer().positive().label('aging_before_days'),
|
aging_before_days: Yup.number()
|
||||||
aging_periods: Yup.number().required().integer().positive().label('aging_periods'),
|
.required()
|
||||||
|
.integer()
|
||||||
|
.positive()
|
||||||
|
.label('aging_before_days'),
|
||||||
|
aging_periods: Yup.number()
|
||||||
|
.required()
|
||||||
|
.integer()
|
||||||
|
.positive()
|
||||||
|
.label('aging_periods'),
|
||||||
}),
|
}),
|
||||||
onSubmit: (values, { setSubmitting }) => {
|
onSubmit: (values, { setSubmitting }) => {
|
||||||
onSubmitFilter(values);
|
onSubmitFilter(values);
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleDateChange = useCallback((name) => (date) => {
|
const handleDateChange = useCallback(
|
||||||
setFieldValue(name, date);
|
(name) => (date) => {
|
||||||
}, []);
|
setFieldValue(name, date);
|
||||||
|
},
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
// Handle submit filter submit button.
|
// Handle submit filter submit button.
|
||||||
const handleSubmitClick = useCallback(() => {
|
useEffect(() => {
|
||||||
submitForm();
|
if (receivableAgingRefresh) {
|
||||||
}, [submitForm]);
|
submitForm();
|
||||||
|
refreshReceivableAgingSummary(false);
|
||||||
|
}
|
||||||
|
}, [submitForm, receivableAgingRefresh]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FinancialStatementHeader show={receivableAgingFilter}>
|
<FinancialStatementHeader show={receivableAgingFilter}>
|
||||||
<Row>
|
<Row>
|
||||||
<Col sm={3}>
|
<Col width={260}>
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={formatMessage({'id': 'as_date'})}
|
label={formatMessage({ id: 'as_date' })}
|
||||||
labelInfo={<FieldHint />}
|
labelInfo={<FieldHint />}
|
||||||
fill={true}
|
fill={true}
|
||||||
intent={errors.as_date && Intent.DANGER}>
|
intent={errors.as_date && Intent.DANGER}
|
||||||
|
>
|
||||||
<DateInput
|
<DateInput
|
||||||
{...momentFormatter('YYYY/MM/DD')}
|
{...momentFormatter('YYYY/MM/DD')}
|
||||||
// value={values.as_date}
|
value={values.as_date}
|
||||||
onChange={handleDateChange('as_date')}
|
onChange={handleDateChange('as_date')}
|
||||||
popoverProps={{ position: Position.BOTTOM, minimal: true }}
|
popoverProps={{ position: Position.BOTTOM, minimal: true }}
|
||||||
minimal={true}
|
minimal={true}
|
||||||
fill={true} />
|
fill={true}
|
||||||
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
<Col sm={3}>
|
<Col width={260}>
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={<T id={'aging_before_days'} />}
|
label={<T id={'aging_before_days'} />}
|
||||||
labelInfo={<FieldHint />}
|
labelInfo={<FieldHint />}
|
||||||
className={'form-group--aging-before-days'}
|
className={'form-group--aging-before-days'}
|
||||||
intent={errors.aging_before_days && Intent.DANGER}
|
intent={errors.aging_before_days && Intent.DANGER}
|
||||||
helperText={<ErrorMessage name="aging_before_days" {...{ errors, touched }} />}
|
|
||||||
>
|
>
|
||||||
<InputGroup
|
<InputGroup
|
||||||
medium={true}
|
medium={true}
|
||||||
@@ -101,13 +120,12 @@ function ReceivableAgingSummaryHeader({
|
|||||||
</FormGroup>
|
</FormGroup>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
<Col sm={3}>
|
<Col width={260}>
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={<T id={'aging_periods'} />}
|
label={<T id={'aging_periods'} />}
|
||||||
labelInfo={<FieldHint />}
|
labelInfo={<FieldHint />}
|
||||||
className={'form-group--aging-periods'}
|
className={'form-group--aging-periods'}
|
||||||
intent={errors.aging_before_days && Intent.DANGER}
|
intent={errors.aging_before_days && Intent.DANGER}
|
||||||
helperText={<ErrorMessage name="aging_periods" {...{ errors, touched }} />}
|
|
||||||
>
|
>
|
||||||
<InputGroup
|
<InputGroup
|
||||||
medium={true}
|
medium={true}
|
||||||
@@ -117,24 +135,14 @@ function ReceivableAgingSummaryHeader({
|
|||||||
</FormGroup>
|
</FormGroup>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
<Row>
|
|
||||||
<Col sm={3}>
|
|
||||||
<Button
|
|
||||||
type="submit"
|
|
||||||
onClick={handleSubmitClick}
|
|
||||||
disabled={isSubmitting}
|
|
||||||
className={'button--submit-filter'}>
|
|
||||||
<T id={'calculate_report'} />
|
|
||||||
</Button>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</FinancialStatementHeader>
|
</FinancialStatementHeader>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
withReceivableAging(({ receivableAgingSummaryFilter }) => ({
|
withReceivableAgingActions,
|
||||||
|
withReceivableAging(({ receivableAgingSummaryFilter, receivableAgingSummaryRefresh }) => ({
|
||||||
receivableAgingFilter: receivableAgingSummaryFilter,
|
receivableAgingFilter: receivableAgingSummaryFilter,
|
||||||
|
receivableAgingRefresh: receivableAgingSummaryRefresh
|
||||||
})),
|
})),
|
||||||
)(ReceivableAgingSummaryHeader);
|
)(ReceivableAgingSummaryHeader);
|
||||||
|
|||||||
@@ -15,19 +15,18 @@ function ReceivableAgingSummaryTable({
|
|||||||
organizationSettings,
|
organizationSettings,
|
||||||
|
|
||||||
// #withReceivableAgingSummary
|
// #withReceivableAgingSummary
|
||||||
receviableAgingRows = [],
|
receivableAgingRows,
|
||||||
receivableAgingLoading,
|
receivableAgingLoading,
|
||||||
receivableAgingColumns,
|
receivableAgingColumns,
|
||||||
|
|
||||||
// #ownProps
|
// #ownProps
|
||||||
receivableAgingSummaryQuery,
|
|
||||||
onFetchData,
|
onFetchData,
|
||||||
}) {
|
}) {
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
|
|
||||||
const agingColumns = useMemo(() => {
|
const agingColumns = useMemo(() => {
|
||||||
return receivableAgingColumns.map((agingColumn) => {
|
return receivableAgingColumns.map((agingColumn) => {
|
||||||
return `${agingColumn.before_days} - ${agingColumn.to_days || '<'}`;
|
return `${agingColumn.before_days} - ${agingColumn.to_days || 'And Over'}`;
|
||||||
});
|
});
|
||||||
}, [receivableAgingColumns]);
|
}, [receivableAgingColumns]);
|
||||||
|
|
||||||
@@ -36,25 +35,38 @@ function ReceivableAgingSummaryTable({
|
|||||||
Header: (<T id={'customer_name'} />),
|
Header: (<T id={'customer_name'} />),
|
||||||
accessor: 'customer_name',
|
accessor: 'customer_name',
|
||||||
className: 'customer_name',
|
className: 'customer_name',
|
||||||
|
sticky: 'left',
|
||||||
},
|
},
|
||||||
...agingColumns.map((agingColumn, index) => ({
|
...agingColumns.map((agingColumn, index) => ({
|
||||||
Header: agingColumn,
|
Header: agingColumn,
|
||||||
id: `asd-${index}`,
|
accessor: (row) => {
|
||||||
|
const amount = row[`aging-${index}`];
|
||||||
|
if (row.rowType === 'total') {
|
||||||
|
return <Money amount={amount} currency={'USD'} />
|
||||||
|
}
|
||||||
|
return amount > 0 ? amount : '';
|
||||||
|
},
|
||||||
})),
|
})),
|
||||||
{
|
{
|
||||||
Header: (<T id={'total'} />),
|
Header: (<T id={'total'} />),
|
||||||
accessor: 'total',
|
id: 'total',
|
||||||
|
accessor: (row) => {
|
||||||
|
return <Money amount={row.total} currency={'USD'} />;
|
||||||
|
},
|
||||||
className: 'total',
|
className: 'total',
|
||||||
},
|
},
|
||||||
]), [agingColumns]);
|
]), [agingColumns]);
|
||||||
|
|
||||||
|
const rowClassNames = (row) => [`row-type--${row.original.rowType}`];
|
||||||
|
|
||||||
const handleFetchData = useCallback((...args) => {
|
const handleFetchData = useCallback((...args) => {
|
||||||
onFetchData && onFetchData(...args);
|
onFetchData && onFetchData(...args);
|
||||||
}, [onFetchData]);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FinancialSheet
|
<FinancialSheet
|
||||||
companyName={organizationSettings.name}
|
companyName={organizationSettings.name}
|
||||||
|
name={'receivable-aging-summary'}
|
||||||
sheetType={formatMessage({ id: 'receivable_aging_summary' })}
|
sheetType={formatMessage({ id: 'receivable_aging_summary' })}
|
||||||
asDate={new Date()}
|
asDate={new Date()}
|
||||||
loading={receivableAgingLoading}>
|
loading={receivableAgingLoading}>
|
||||||
@@ -62,8 +74,10 @@ function ReceivableAgingSummaryTable({
|
|||||||
<DataTable
|
<DataTable
|
||||||
className="bigcapital-datatable--financial-report"
|
className="bigcapital-datatable--financial-report"
|
||||||
columns={columns}
|
columns={columns}
|
||||||
data={receviableAgingRows}
|
data={receivableAgingRows}
|
||||||
|
rowClassNames={rowClassNames}
|
||||||
onFetchData={handleFetchData}
|
onFetchData={handleFetchData}
|
||||||
|
noInitialFetch={true}
|
||||||
sticky={true}
|
sticky={true}
|
||||||
/>
|
/>
|
||||||
</FinancialSheet>
|
</FinancialSheet>
|
||||||
@@ -75,8 +89,11 @@ export default compose(
|
|||||||
withReceivableAgingSummaryTable,
|
withReceivableAgingSummaryTable,
|
||||||
withReceivableAgingSummary(({
|
withReceivableAgingSummary(({
|
||||||
receivableAgingSummaryLoading,
|
receivableAgingSummaryLoading,
|
||||||
receivableAgingSummaryColumns }) => ({
|
receivableAgingSummaryColumns,
|
||||||
|
receivableAgingSummaryRows,
|
||||||
|
}) => ({
|
||||||
receivableAgingLoading: receivableAgingSummaryLoading,
|
receivableAgingLoading: receivableAgingSummaryLoading,
|
||||||
receivableAgingColumns: receivableAgingSummaryColumns
|
receivableAgingColumns: receivableAgingSummaryColumns,
|
||||||
|
receivableAgingRows: receivableAgingSummaryRows,
|
||||||
})),
|
})),
|
||||||
)(ReceivableAgingSummaryTable);
|
)(ReceivableAgingSummaryTable);
|
||||||
@@ -2,6 +2,7 @@ import { connect } from 'react-redux';
|
|||||||
import {
|
import {
|
||||||
getFinancialSheet,
|
getFinancialSheet,
|
||||||
getFinancialSheetColumns,
|
getFinancialSheetColumns,
|
||||||
|
getFinancialSheetTableRows,
|
||||||
} from 'store/financialStatement/financialStatements.selectors';
|
} from 'store/financialStatement/financialStatements.selectors';
|
||||||
|
|
||||||
export default (mapState) => {
|
export default (mapState) => {
|
||||||
@@ -17,10 +18,16 @@ export default (mapState) => {
|
|||||||
state.financialStatements.receivableAgingSummary.sheets,
|
state.financialStatements.receivableAgingSummary.sheets,
|
||||||
receivableAgingSummaryIndex,
|
receivableAgingSummaryIndex,
|
||||||
),
|
),
|
||||||
|
receivableAgingSummaryRows: getFinancialSheetTableRows(
|
||||||
|
state.financialStatements.receivableAgingSummary.sheets,
|
||||||
|
receivableAgingSummaryIndex,
|
||||||
|
),
|
||||||
receivableAgingSummaryLoading:
|
receivableAgingSummaryLoading:
|
||||||
state.financialStatements.receivableAgingSummary.loading,
|
state.financialStatements.receivableAgingSummary.loading,
|
||||||
receivableAgingSummaryFilter:
|
receivableAgingSummaryFilter:
|
||||||
state.financialStatements.receivableAgingSummary.filter,
|
state.financialStatements.receivableAgingSummary.filter,
|
||||||
|
receivableAgingSummaryRefresh:
|
||||||
|
state.financialStatements.receivableAgingSummary.refresh,
|
||||||
};
|
};
|
||||||
return mapState ? mapState(mapped, state, props) : mapped;
|
return mapState ? mapState(mapped, state, props) : mapped;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,12 +1,18 @@
|
|||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { fetchReceivableAgingSummary } from 'store/financialStatement/financialStatements.actions';
|
import {
|
||||||
|
fetchReceivableAgingSummary,
|
||||||
|
receivableAgingSummaryRefresh,
|
||||||
|
} from 'store/financialStatement/financialStatements.actions';
|
||||||
|
|
||||||
const mapActionsToProps = (dispatch) => ({
|
const mapActionsToProps = (dispatch) => ({
|
||||||
requestReceivableAgingSummary: (query) =>
|
requestReceivableAgingSummary: (query) =>
|
||||||
dispatch(fetchReceivableAgingSummary({ query })),
|
dispatch(fetchReceivableAgingSummary({ query })),
|
||||||
toggleFilterReceivableAgingSummary: () => dispatch({
|
toggleFilterReceivableAgingSummary: () =>
|
||||||
type: 'RECEIVABLE_AGING_SUMMARY_FILTER_TOGGLE',
|
dispatch({
|
||||||
}),
|
type: 'RECEIVABLE_AGING_SUMMARY_FILTER_TOGGLE',
|
||||||
|
}),
|
||||||
|
refreshReceivableAgingSummary: (refresh) =>
|
||||||
|
dispatch(receivableAgingSummaryRefresh(refresh)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(null, mapActionsToProps);
|
export default connect(null, mapActionsToProps);
|
||||||
|
|||||||
@@ -20,12 +20,17 @@ function TrialBalanceActionsBar({
|
|||||||
|
|
||||||
// #withTrialBalanceActions
|
// #withTrialBalanceActions
|
||||||
toggleTrialBalanceFilter,
|
toggleTrialBalanceFilter,
|
||||||
|
refreshTrialBalance,
|
||||||
}) {
|
}) {
|
||||||
|
|
||||||
const handleFilterToggleClick = () => {
|
const handleFilterToggleClick = () => {
|
||||||
toggleTrialBalanceFilter();
|
toggleTrialBalanceFilter();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleRecalcReport = () => {
|
||||||
|
refreshTrialBalance(true);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardActionsBar>
|
<DashboardActionsBar>
|
||||||
<NavbarGroup>
|
<NavbarGroup>
|
||||||
@@ -36,6 +41,16 @@ function TrialBalanceActionsBar({
|
|||||||
/>
|
/>
|
||||||
<NavbarDivider />
|
<NavbarDivider />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
className={classNames(
|
||||||
|
Classes.MINIMAL,
|
||||||
|
'button--gray-highlight',
|
||||||
|
)}
|
||||||
|
text={'Re-calc Report'}
|
||||||
|
onClick={handleRecalcReport}
|
||||||
|
icon={<Icon icon="refresh-16" iconSize={16} />}
|
||||||
|
/>
|
||||||
|
|
||||||
<If condition={trialBalanceSheetFilter}>
|
<If condition={trialBalanceSheetFilter}>
|
||||||
<Button
|
<Button
|
||||||
className={Classes.MINIMAL}
|
className={Classes.MINIMAL}
|
||||||
|
|||||||
@@ -13,10 +13,8 @@ import { compose } from 'utils';
|
|||||||
import DashboardPageContent from 'components/Dashboard/DashboardPageContent';
|
import DashboardPageContent from 'components/Dashboard/DashboardPageContent';
|
||||||
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||||
import withTrialBalanceActions from './withTrialBalanceActions';
|
import withTrialBalanceActions from './withTrialBalanceActions';
|
||||||
import withTrialBalance from './withTrialBalance';
|
|
||||||
import withSettings from 'containers/Settings/withSettings';
|
import withSettings from 'containers/Settings/withSettings';
|
||||||
|
|
||||||
|
|
||||||
function TrialBalanceSheet({
|
function TrialBalanceSheet({
|
||||||
// #withDashboardActions
|
// #withDashboardActions
|
||||||
changePageTitle,
|
changePageTitle,
|
||||||
@@ -24,9 +22,6 @@ function TrialBalanceSheet({
|
|||||||
// #withTrialBalanceActions
|
// #withTrialBalanceActions
|
||||||
fetchTrialBalanceSheet,
|
fetchTrialBalanceSheet,
|
||||||
|
|
||||||
// #withTrialBalance
|
|
||||||
trialBalanceSheetLoading,
|
|
||||||
|
|
||||||
// #withPreferences
|
// #withPreferences
|
||||||
organizationSettings,
|
organizationSettings,
|
||||||
}) {
|
}) {
|
||||||
@@ -36,6 +31,7 @@ function TrialBalanceSheet({
|
|||||||
basis: 'accural',
|
basis: 'accural',
|
||||||
none_zero: false,
|
none_zero: false,
|
||||||
});
|
});
|
||||||
|
const [refresh, setRefresh] = useState(true);
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
|
|
||||||
const fetchHook = useQuery(
|
const fetchHook = useQuery(
|
||||||
@@ -46,7 +42,7 @@ function TrialBalanceSheet({
|
|||||||
|
|
||||||
// handle fetch data of trial balance table.
|
// handle fetch data of trial balance table.
|
||||||
const handleFetchData = useCallback(() => {
|
const handleFetchData = useCallback(() => {
|
||||||
fetchHook.refetch({ force: true });
|
setRefresh(true);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Change page title of the dashboard.
|
// Change page title of the dashboard.
|
||||||
@@ -62,11 +58,18 @@ function TrialBalanceSheet({
|
|||||||
to_date: moment(filter.to_date).format('YYYY-MM-DD'),
|
to_date: moment(filter.to_date).format('YYYY-MM-DD'),
|
||||||
};
|
};
|
||||||
setFilter(parsedFilter);
|
setFilter(parsedFilter);
|
||||||
fetchHook.refetch({ force: true });
|
setRefresh(true);
|
||||||
},
|
},
|
||||||
[fetchHook],
|
[fetchHook],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (refresh) {
|
||||||
|
fetchHook.refetch({ force: true });
|
||||||
|
setRefresh(false);
|
||||||
|
}
|
||||||
|
}, [refresh, fetchHook.refetch]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardInsider>
|
<DashboardInsider>
|
||||||
<TrialBalanceActionsBar />
|
<TrialBalanceActionsBar />
|
||||||
@@ -83,7 +86,6 @@ function TrialBalanceSheet({
|
|||||||
companyName={organizationSettings.name}
|
companyName={organizationSettings.name}
|
||||||
trialBalanceQuery={filter}
|
trialBalanceQuery={filter}
|
||||||
onFetchData={handleFetchData}
|
onFetchData={handleFetchData}
|
||||||
loading={trialBalanceSheetLoading}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -95,8 +97,5 @@ function TrialBalanceSheet({
|
|||||||
export default compose(
|
export default compose(
|
||||||
withDashboardActions,
|
withDashboardActions,
|
||||||
withTrialBalanceActions,
|
withTrialBalanceActions,
|
||||||
withTrialBalance(({ trialBalanceSheetLoading }) => ({
|
|
||||||
trialBalanceSheetLoading,
|
|
||||||
})),
|
|
||||||
withSettings,
|
withSettings,
|
||||||
)(TrialBalanceSheet);
|
)(TrialBalanceSheet);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useCallback } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { Row, Col } from 'react-grid-system';
|
import { Row, Col } from 'react-grid-system';
|
||||||
@@ -9,6 +9,7 @@ import { Button } from "@blueprintjs/core";
|
|||||||
import FinancialStatementHeader from 'containers/FinancialStatements/FinancialStatementHeader';
|
import FinancialStatementHeader from 'containers/FinancialStatements/FinancialStatementHeader';
|
||||||
import FinancialStatementDateRange from 'containers/FinancialStatements/FinancialStatementDateRange';
|
import FinancialStatementDateRange from 'containers/FinancialStatements/FinancialStatementDateRange';
|
||||||
import withTrialBalance from './withTrialBalance';
|
import withTrialBalance from './withTrialBalance';
|
||||||
|
import withTrialBalanceActions from './withTrialBalanceActions';
|
||||||
|
|
||||||
import { compose } from 'utils';
|
import { compose } from 'utils';
|
||||||
|
|
||||||
@@ -19,6 +20,10 @@ function TrialBalanceSheetHeader({
|
|||||||
|
|
||||||
// #withTrialBalance
|
// #withTrialBalance
|
||||||
trialBalanceSheetFilter,
|
trialBalanceSheetFilter,
|
||||||
|
trialBalanceSheetRefresh,
|
||||||
|
|
||||||
|
// #withTrialBalanceActions
|
||||||
|
refreshTrialBalance,
|
||||||
}) {
|
}) {
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
@@ -38,29 +43,29 @@ function TrialBalanceSheetHeader({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleSubmitClick = useCallback(() => {
|
useEffect(() => {
|
||||||
formik.submitForm();
|
if (trialBalanceSheetRefresh) {
|
||||||
}, [formik]);
|
formik.submitForm();
|
||||||
|
refreshTrialBalance(false);
|
||||||
|
}
|
||||||
|
}, [formik, trialBalanceSheetRefresh]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FinancialStatementHeader show={trialBalanceSheetFilter}>
|
<FinancialStatementHeader show={trialBalanceSheetFilter}>
|
||||||
<FinancialStatementDateRange formik={formik} />
|
|
||||||
|
|
||||||
<Row>
|
<Row>
|
||||||
<Col sm={3}>
|
<FinancialStatementDateRange formik={formik} />
|
||||||
<Button
|
|
||||||
type="submit"
|
|
||||||
onClick={handleSubmitClick}
|
|
||||||
disabled={formik.isSubmitting}
|
|
||||||
className={'button--submit-filter'}>
|
|
||||||
<T id={'run_report'} />
|
|
||||||
</Button>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
</Row>
|
||||||
</FinancialStatementHeader>
|
</FinancialStatementHeader>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
withTrialBalance(({ trialBalanceSheetFilter }) => ({ trialBalanceSheetFilter })),
|
withTrialBalance(({
|
||||||
|
trialBalanceSheetFilter,
|
||||||
|
trialBalanceSheetRefresh,
|
||||||
|
}) => ({
|
||||||
|
trialBalanceSheetFilter,
|
||||||
|
trialBalanceSheetRefresh
|
||||||
|
})),
|
||||||
|
withTrialBalanceActions,
|
||||||
)(TrialBalanceSheetHeader);
|
)(TrialBalanceSheetHeader);
|
||||||
@@ -14,13 +14,13 @@ import { compose } from 'utils';
|
|||||||
function TrialBalanceSheetTable({
|
function TrialBalanceSheetTable({
|
||||||
// #withTrialBalanceDetail
|
// #withTrialBalanceDetail
|
||||||
trialBalanceAccounts,
|
trialBalanceAccounts,
|
||||||
|
trialBalanceSheetLoading,
|
||||||
|
|
||||||
// #withTrialBalanceTable
|
// #withTrialBalanceTable
|
||||||
trialBalanceIndex,
|
trialBalanceIndex,
|
||||||
trialBalanceQuery,
|
trialBalanceQuery,
|
||||||
|
|
||||||
onFetchData,
|
onFetchData,
|
||||||
loading,
|
|
||||||
companyName,
|
companyName,
|
||||||
}) {
|
}) {
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
@@ -31,30 +31,41 @@ function TrialBalanceSheetTable({
|
|||||||
Header: formatMessage({ id: 'account_name' }),
|
Header: formatMessage({ id: 'account_name' }),
|
||||||
accessor: 'name',
|
accessor: 'name',
|
||||||
className: 'name',
|
className: 'name',
|
||||||
|
minWidth: 150,
|
||||||
|
maxWidth: 150,
|
||||||
|
width: 150,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: formatMessage({ id: 'code' }),
|
Header: formatMessage({ id: 'code' }),
|
||||||
accessor: 'code',
|
accessor: 'code',
|
||||||
className: 'code',
|
className: 'code',
|
||||||
width: 120,
|
minWidth: 80,
|
||||||
|
maxWidth: 80,
|
||||||
|
width: 80,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: formatMessage({ id: 'credit' }),
|
Header: formatMessage({ id: 'credit' }),
|
||||||
accessor: (r) => <Money amount={r.credit} currency="USD" />,
|
accessor: (r) => <Money amount={r.credit} currency="USD" />,
|
||||||
className: 'credit',
|
className: 'credit',
|
||||||
width: 120,
|
minWidth: 95,
|
||||||
|
maxWidth: 95,
|
||||||
|
width: 95,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: formatMessage({ id: 'debit' }),
|
Header: formatMessage({ id: 'debit' }),
|
||||||
accessor: (r) => <Money amount={r.debit} currency="USD" />,
|
accessor: (r) => <Money amount={r.debit} currency="USD" />,
|
||||||
className: 'debit',
|
className: 'debit',
|
||||||
width: 120,
|
minWidth: 95,
|
||||||
|
maxWidth: 95,
|
||||||
|
width: 95,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: formatMessage({ id: 'balance' }),
|
Header: formatMessage({ id: 'balance' }),
|
||||||
accessor: (r) => <Money amount={r.balance} currency="USD" />,
|
accessor: (r) => <Money amount={r.balance} currency="USD" />,
|
||||||
className: 'balance',
|
className: 'balance',
|
||||||
width: 120,
|
minWidth: 95,
|
||||||
|
maxWidth: 95,
|
||||||
|
width: 95,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[formatMessage],
|
[formatMessage],
|
||||||
@@ -71,7 +82,7 @@ function TrialBalanceSheetTable({
|
|||||||
fromDate={trialBalanceQuery.from_date}
|
fromDate={trialBalanceQuery.from_date}
|
||||||
toDate={trialBalanceQuery.to_date}
|
toDate={trialBalanceQuery.to_date}
|
||||||
name="trial-balance"
|
name="trial-balance"
|
||||||
loading={loading}
|
loading={trialBalanceSheetLoading}
|
||||||
>
|
>
|
||||||
<DataTable
|
<DataTable
|
||||||
className="bigcapital-datatable--financial-report"
|
className="bigcapital-datatable--financial-report"
|
||||||
@@ -100,7 +111,11 @@ const withTrialBalanceTable = connect(mapStateToProps);
|
|||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
withTrialBalanceTable,
|
withTrialBalanceTable,
|
||||||
withTrialBalance(({ trialBalanceAccounts }) => ({
|
withTrialBalance(({
|
||||||
trialBalanceAccounts,
|
trialBalanceAccounts,
|
||||||
|
trialBalanceSheetLoading,
|
||||||
|
}) => ({
|
||||||
|
trialBalanceAccounts,
|
||||||
|
trialBalanceSheetLoading
|
||||||
})),
|
})),
|
||||||
)(TrialBalanceSheetTable);
|
)(TrialBalanceSheetTable);
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ export default (mapState) => {
|
|||||||
),
|
),
|
||||||
trialBalanceSheetLoading: state.financialStatements.trialBalance.loading,
|
trialBalanceSheetLoading: state.financialStatements.trialBalance.loading,
|
||||||
trialBalanceSheetFilter: state.financialStatements.trialBalance.filter,
|
trialBalanceSheetFilter: state.financialStatements.trialBalance.filter,
|
||||||
|
trialBalanceSheetRefresh: state.financialStatements.trialBalance.refresh,
|
||||||
};
|
};
|
||||||
return mapState ? mapState(mapped, state, props) : mapped;
|
return mapState ? mapState(mapped, state, props) : mapped;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
import {connect} from 'react-redux';
|
import {connect} from 'react-redux';
|
||||||
import {
|
import {
|
||||||
fetchTrialBalanceSheet
|
fetchTrialBalanceSheet,
|
||||||
|
trialBalanceRefresh,
|
||||||
} from 'store/financialStatement/financialStatements.actions';
|
} from 'store/financialStatement/financialStatements.actions';
|
||||||
|
|
||||||
export const mapDispatchToProps = (dispatch) => ({
|
export const mapDispatchToProps = (dispatch) => ({
|
||||||
fetchTrialBalanceSheet: (query = {}) => dispatch(fetchTrialBalanceSheet({ query })),
|
fetchTrialBalanceSheet: (query = {}) => dispatch(fetchTrialBalanceSheet({ query })),
|
||||||
toggleTrialBalanceFilter: () => dispatch({ type: 'TRIAL_BALANCE_FILTER_TOGGLE' }),
|
toggleTrialBalanceFilter: () => dispatch({ type: 'TRIAL_BALANCE_FILTER_TOGGLE' }),
|
||||||
|
refreshTrialBalance: (refresh) => dispatch(trialBalanceRefresh(refresh)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(null, mapDispatchToProps);
|
export default connect(null, mapDispatchToProps);
|
||||||
@@ -260,6 +260,7 @@ export default {
|
|||||||
sales: 'Sales',
|
sales: 'Sales',
|
||||||
purchases: 'Purchases',
|
purchases: 'Purchases',
|
||||||
financial_reports: 'Financial Reports',
|
financial_reports: 'Financial Reports',
|
||||||
|
all_financial_reports: 'All Financial Reports',
|
||||||
balance_sheet: 'Balance Sheet',
|
balance_sheet: 'Balance Sheet',
|
||||||
trial_balance_sheet: 'Trial Balance Sheet',
|
trial_balance_sheet: 'Trial Balance Sheet',
|
||||||
journal: 'Journal',
|
journal: 'Journal',
|
||||||
@@ -347,7 +348,7 @@ export default {
|
|||||||
select_language: 'Select Language',
|
select_language: 'Select Language',
|
||||||
select_date_format: 'Select Date Format',
|
select_date_format: 'Select Date Format',
|
||||||
select_time_zone: 'Select Time Zone',
|
select_time_zone: 'Select Time Zone',
|
||||||
select_currency_code: 'Select Currency Code',
|
select_currency: 'Select Currency',
|
||||||
select_parent_category: 'Select Parent Category',
|
select_parent_category: 'Select Parent Category',
|
||||||
the_options_has_been_successfully_created:
|
the_options_has_been_successfully_created:
|
||||||
'The options has been successfully created',
|
'The options has been successfully created',
|
||||||
@@ -422,7 +423,7 @@ export default {
|
|||||||
payment_account_: 'Payment account',
|
payment_account_: 'Payment account',
|
||||||
expense_category: 'Expense Category',
|
expense_category: 'Expense Category',
|
||||||
total_currency: 'Total ({currency})',
|
total_currency: 'Total ({currency})',
|
||||||
amount_currency: 'Amount({currency})',
|
amount_currency: 'Amount ({currency})',
|
||||||
publish_expense: 'Publish Expense',
|
publish_expense: 'Publish Expense',
|
||||||
edit_expense: 'Edit Expense',
|
edit_expense: 'Edit Expense',
|
||||||
delete_expense: 'Delete Expense',
|
delete_expense: 'Delete Expense',
|
||||||
@@ -459,4 +460,12 @@ export default {
|
|||||||
display_name:'Display Name',
|
display_name:'Display Name',
|
||||||
the_customer_has_been_successfully_created:
|
the_customer_has_been_successfully_created:
|
||||||
'The customer has been successfully created.',
|
'The customer has been successfully created.',
|
||||||
|
select_contact: 'Select contact',
|
||||||
|
contact: 'Contact',
|
||||||
|
contacts: 'Contacts',
|
||||||
|
close_sidebar: 'Close sidebar.',
|
||||||
|
recalc_report: 'Re-calc Report',
|
||||||
|
remove_the_line: 'Remove the line',
|
||||||
|
no_results: 'No results',
|
||||||
|
all_reports: 'All Reports',
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ export default [
|
|||||||
|
|
||||||
// Financial Reports.
|
// Financial Reports.
|
||||||
{
|
{
|
||||||
path: `/general-ledger`,
|
path: `/financial-reports/general-ledger`,
|
||||||
component: LazyLoader({
|
component: LazyLoader({
|
||||||
loader: () =>
|
loader: () =>
|
||||||
import('containers/FinancialStatements/GeneralLedger/GeneralLedger'),
|
import('containers/FinancialStatements/GeneralLedger/GeneralLedger'),
|
||||||
@@ -100,7 +100,7 @@ export default [
|
|||||||
breadcrumb: 'General Ledger',
|
breadcrumb: 'General Ledger',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: `/balance-sheet`,
|
path: `/financial-reports/balance-sheet`,
|
||||||
component: LazyLoader({
|
component: LazyLoader({
|
||||||
loader: () =>
|
loader: () =>
|
||||||
import('containers/FinancialStatements/BalanceSheet/BalanceSheet'),
|
import('containers/FinancialStatements/BalanceSheet/BalanceSheet'),
|
||||||
@@ -108,42 +108,49 @@ export default [
|
|||||||
breadcrumb: 'Balance Sheet',
|
breadcrumb: 'Balance Sheet',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: `/trial-balance-sheet`,
|
path: `/financial-reports/trial-balance-sheet`,
|
||||||
component: LazyLoader({
|
component: LazyLoader({
|
||||||
loader: () =>
|
loader: () =>
|
||||||
import(
|
import(
|
||||||
'containers/FinancialStatements/TrialBalanceSheet/TrialBalanceSheet'
|
'containers/FinancialStatements/TrialBalanceSheet/TrialBalanceSheet'
|
||||||
),
|
),
|
||||||
breadcrumb: 'Trial Balance Sheet',
|
|
||||||
}),
|
}),
|
||||||
|
breadcrumb: 'Trial Balance Sheet',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: `/profit-loss-sheet`,
|
path: `/financial-reports/profit-loss-sheet`,
|
||||||
component: LazyLoader({
|
component: LazyLoader({
|
||||||
loader: () =>
|
loader: () =>
|
||||||
import(
|
import(
|
||||||
'containers/FinancialStatements/ProfitLossSheet/ProfitLossSheet'
|
'containers/FinancialStatements/ProfitLossSheet/ProfitLossSheet'
|
||||||
),
|
),
|
||||||
breadcrumb: 'Profit Loss Sheet',
|
|
||||||
}),
|
}),
|
||||||
|
breadcrumb: 'Profit Loss Sheet',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/receivable-aging-summary',
|
path: '/financial-reports/receivable-aging-summary',
|
||||||
component: LazyLoader({
|
component: LazyLoader({
|
||||||
loader: () =>
|
loader: () =>
|
||||||
import(
|
import(
|
||||||
'containers/FinancialStatements/ReceivableAgingSummary/ReceivableAgingSummary'
|
'containers/FinancialStatements/ReceivableAgingSummary/ReceivableAgingSummary'
|
||||||
),
|
),
|
||||||
breadcrumb: 'Receivable Aging Summary',
|
|
||||||
}),
|
}),
|
||||||
|
breadcrumb: 'Receivable Aging Summary',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: `/journal-sheet`,
|
path: `/financial-reports/journal-sheet`,
|
||||||
component: LazyLoader({
|
component: LazyLoader({
|
||||||
loader: () => import('containers/FinancialStatements/Journal/Journal'),
|
loader: () => import('containers/FinancialStatements/Journal/Journal'),
|
||||||
}),
|
}),
|
||||||
breadcrumb: 'Journal Sheet',
|
breadcrumb: 'Journal Sheet',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/financial-reports',
|
||||||
|
component: LazyLoader({
|
||||||
|
loader: () => import('containers/FinancialStatements/FinancialReports'),
|
||||||
|
}),
|
||||||
|
breadcrumb: 'Financial Reports',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: `/ExchangeRates`,
|
path: `/ExchangeRates`,
|
||||||
component: LazyLoader({
|
component: LazyLoader({
|
||||||
@@ -158,7 +165,6 @@ export default [
|
|||||||
loader: () => import('containers/Expenses/Expenses'),
|
loader: () => import('containers/Expenses/Expenses'),
|
||||||
}),
|
}),
|
||||||
breadcrumb: 'Expenses',
|
breadcrumb: 'Expenses',
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: `/expenses/:id/edit`,
|
path: `/expenses/:id/edit`,
|
||||||
|
|||||||
@@ -5,12 +5,6 @@ export default {
|
|||||||
],
|
],
|
||||||
viewBox: '0 0 640 512',
|
viewBox: '0 0 640 512',
|
||||||
},
|
},
|
||||||
homepage: {
|
|
||||||
path: [
|
|
||||||
'M4,7.5H7.5V4H4V7.5ZM9.25,18h3.5V14.5H9.25V18ZM4,18H7.5V14.5H4V18Zm0-5.25H7.5V9.25H4v3.5Zm5.25,0h3.5V9.25H9.25v3.5ZM14.5,4V7.5H18V4ZM9.25,7.5h3.5V4H9.25V7.5Zm5.25,5.25H18V9.25H14.5v3.5Zm0,5.25H18V14.5H14.5V18Z',
|
|
||||||
],
|
|
||||||
viewBox: '0 0 20 20',
|
|
||||||
},
|
|
||||||
university: {
|
university: {
|
||||||
path: [
|
path: [
|
||||||
'M472 440h-8v-56c0-13.255-10.745-24-24-24h-16V208h-48v152h-48V208h-48v152h-48V208h-48v152h-48V208H88v152H72c-13.255 0-24 10.745-24 24v56h-8c-13.255 0-24 10.745-24 24v16a8 8 0 0 0 8 8h464a8 8 0 0 0 8-8v-16c0-13.255-10.745-24-24-24zm-56 0H96v-32h320v32zm72.267-322.942L271.179 26.463a48.004 48.004 0 0 0-30.358 0L23.733 117.058A11.999 11.999 0 0 0 16 128.274V156c0 6.627 5.373 12 12 12h20v12c0 6.627 5.373 12 12 12h392c6.627 0 12-5.373 12-12v-12h20c6.627 0 12-5.373 12-12v-27.726c0-4.982-3.077-9.445-7.733-11.216zM64 144l192-72 192 72H64z',
|
'M472 440h-8v-56c0-13.255-10.745-24-24-24h-16V208h-48v152h-48V208h-48v152h-48V208h-48v152h-48V208H88v152H72c-13.255 0-24 10.745-24 24v56h-8c-13.255 0-24 10.745-24 24v16a8 8 0 0 0 8 8h464a8 8 0 0 0 8-8v-16c0-13.255-10.745-24-24-24zm-56 0H96v-32h320v32zm72.267-322.942L271.179 26.463a48.004 48.004 0 0 0-30.358 0L23.733 117.058A11.999 11.999 0 0 0 16 128.274V156c0 6.627 5.373 12 12 12h20v12c0 6.627 5.373 12 12 12h392c6.627 0 12-5.373 12-12v-12h20c6.627 0 12-5.373 12-12v-27.726c0-4.982-3.077-9.445-7.733-11.216zM64 144l192-72 192 72H64z',
|
||||||
@@ -263,4 +257,10 @@ export default {
|
|||||||
],
|
],
|
||||||
viewBox: '0 0 16 16',
|
viewBox: '0 0 16 16',
|
||||||
},
|
},
|
||||||
|
'refresh-16': {
|
||||||
|
path: [
|
||||||
|
'M13.645,2.35A8.0014,8.0014,0,1,0,15.725,10h-2.08a5.9972,5.9972,0,1,1-5.65-8,5.9149,5.9149,0,0,1,4.22,1.78L8.995,7h7V0Z',
|
||||||
|
],
|
||||||
|
viewBox: '0 0 16 16',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -89,5 +89,5 @@ const reducer = createReducer(initialState, {
|
|||||||
export default createTableQueryReducers('expenses', reducer);
|
export default createTableQueryReducers('expenses', reducer);
|
||||||
|
|
||||||
export const getExpenseById = (state, id) => {
|
export const getExpenseById = (state, id) => {
|
||||||
return state.expenses.items[id] || {};
|
return state.expenses.items[id];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,13 @@
|
|||||||
import ApiService from "services/ApiService";
|
import ApiService from "services/ApiService";
|
||||||
import t from 'store/types';
|
import t from 'store/types';
|
||||||
|
|
||||||
|
export const balanceSheetRefresh = (refresh) => {
|
||||||
|
return dispatch => dispatch({
|
||||||
|
type: 'BALANCE_SHEET_REFRESH',
|
||||||
|
payload: { refresh },
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
export const fetchGeneralLedger = ({ query }) => {
|
export const fetchGeneralLedger = ({ query }) => {
|
||||||
return (dispatch) => new Promise((resolve, reject) => {
|
return (dispatch) => new Promise((resolve, reject) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
@@ -21,6 +28,13 @@ export const fetchGeneralLedger = ({ query }) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const refreshGeneralLedgerSheet = (refresh) => {
|
||||||
|
return (dispatch) => dispatch({
|
||||||
|
type: t.GENERAL_LEDGER_REFRESH,
|
||||||
|
payload: { refresh },
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
export const fetchBalanceSheet = ({ query }) => {
|
export const fetchBalanceSheet = ({ query }) => {
|
||||||
return (dispatch) => new Promise((resolve, reject) => {
|
return (dispatch) => new Promise((resolve, reject) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
@@ -65,6 +79,13 @@ export const fetchTrialBalanceSheet = ({ query }) => {
|
|||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const trialBalanceRefresh = (refresh) => {
|
||||||
|
return (dispatch) => dispatch({
|
||||||
|
type: t.TRIAL_BALANCE_REFRESH,
|
||||||
|
payload: { refresh },
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
export const fetchProfitLossSheet = ({ query }) => {
|
export const fetchProfitLossSheet = ({ query }) => {
|
||||||
return (dispatch) => new Promise((resolve, reject) => {
|
return (dispatch) => new Promise((resolve, reject) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
@@ -87,6 +108,13 @@ export const fetchProfitLossSheet = ({ query }) => {
|
|||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const profitLossRefresh = (refresh) => {
|
||||||
|
return dispatch => dispatch({
|
||||||
|
type: t.PROFIT_LOSS_REFRESH,
|
||||||
|
payload: { refresh },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export const fetchJournalSheet = ({ query }) => {
|
export const fetchJournalSheet = ({ query }) => {
|
||||||
return (dispatch) => new Promise((resolve, reject) => {
|
return (dispatch) => new Promise((resolve, reject) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
@@ -108,6 +136,13 @@ export const fetchJournalSheet = ({ query }) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const refreshJournalSheet = (refresh) => {
|
||||||
|
return dispatch => dispatch({
|
||||||
|
type: t.JOURNAL_SHEET_REFRESH,
|
||||||
|
payload: { refresh },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export const fetchReceivableAgingSummary = ({ query }) => {
|
export const fetchReceivableAgingSummary = ({ query }) => {
|
||||||
return (dispatch) => new Promise((resolve, reject) => {
|
return (dispatch) => new Promise((resolve, reject) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
@@ -139,4 +174,11 @@ export const fetchReceivableAgingSummary = ({ query }) => {
|
|||||||
reject(error);
|
reject(error);
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export const receivableAgingSummaryRefresh = (refresh) => {
|
||||||
|
return (dispatch) => dispatch({
|
||||||
|
type: t.RECEIVABLE_AGING_SUMMARY_REFRESH,
|
||||||
|
payload: { refresh },
|
||||||
|
});
|
||||||
}
|
}
|
||||||
@@ -8,28 +8,32 @@ import { omit } from 'lodash';
|
|||||||
const initialState = {
|
const initialState = {
|
||||||
balanceSheet: {
|
balanceSheet: {
|
||||||
sheets: [],
|
sheets: [],
|
||||||
loading: false,
|
loading: true,
|
||||||
filter: true,
|
filter: true,
|
||||||
|
refresh: false,
|
||||||
},
|
},
|
||||||
trialBalance: {
|
trialBalance: {
|
||||||
sheets: [],
|
sheets: [],
|
||||||
loading: false,
|
loading: true,
|
||||||
filter: true,
|
filter: true,
|
||||||
|
refresh: false,
|
||||||
},
|
},
|
||||||
generalLedger: {
|
generalLedger: {
|
||||||
sheets: [],
|
sheets: [],
|
||||||
loading: false,
|
loading: false,
|
||||||
filter: true,
|
filter: true,
|
||||||
|
refresh: false,
|
||||||
},
|
},
|
||||||
journal: {
|
journal: {
|
||||||
sheets: [],
|
sheets: [],
|
||||||
loading: false,
|
loading: false,
|
||||||
tableRows: [],
|
tableRows: [],
|
||||||
filter: true,
|
filter: true,
|
||||||
|
refresh: true,
|
||||||
},
|
},
|
||||||
profitLoss: {
|
profitLoss: {
|
||||||
sheets: [],
|
sheets: [],
|
||||||
loading: false,
|
loading: true,
|
||||||
tableRows: [],
|
tableRows: [],
|
||||||
filter: true,
|
filter: true,
|
||||||
},
|
},
|
||||||
@@ -38,6 +42,7 @@ const initialState = {
|
|||||||
loading: false,
|
loading: false,
|
||||||
tableRows: [],
|
tableRows: [],
|
||||||
filter: true,
|
filter: true,
|
||||||
|
refresh: false,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -88,6 +93,36 @@ const mapJournalTableRows = (journal) => {
|
|||||||
}, []);
|
}, []);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const mapContactAgingSummary = sheet => {
|
||||||
|
const rows = [];
|
||||||
|
|
||||||
|
const mapAging = (agingPeriods) => {
|
||||||
|
return agingPeriods.reduce((acc, aging, index) => {
|
||||||
|
acc[`aging-${index}`] = aging.formatted_total;
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
}
|
||||||
|
sheet.customers.forEach((customer) => {
|
||||||
|
const agingRow = mapAging(customer.aging);
|
||||||
|
|
||||||
|
rows.push({
|
||||||
|
rowType: 'customer',
|
||||||
|
customer_name: customer.customer_name,
|
||||||
|
...agingRow,
|
||||||
|
total: customer.total,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
rows.push({
|
||||||
|
rowType: 'total',
|
||||||
|
customer_name: 'Total',
|
||||||
|
...mapAging(sheet.total),
|
||||||
|
total: 0,
|
||||||
|
});
|
||||||
|
return rows;
|
||||||
|
};
|
||||||
|
|
||||||
const mapProfitLossToTableRows = (profitLoss) => {
|
const mapProfitLossToTableRows = (profitLoss) => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
@@ -152,6 +187,12 @@ export default createReducer(initialState, {
|
|||||||
[t.BALANCE_SHEET_LOADING]: (state, action) => {
|
[t.BALANCE_SHEET_LOADING]: (state, action) => {
|
||||||
state.balanceSheet.loading = !!action.loading;
|
state.balanceSheet.loading = !!action.loading;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
[t.BALANCE_SHEET_REFRESH]: (state, action) => {
|
||||||
|
const { refresh } = action.payload;
|
||||||
|
state.balanceSheet.refresh = refresh;
|
||||||
|
},
|
||||||
|
|
||||||
...financialStatementFilterToggle('BALANCE_SHEET', 'balanceSheet'),
|
...financialStatementFilterToggle('BALANCE_SHEET', 'balanceSheet'),
|
||||||
|
|
||||||
[t.TRAIL_BALANCE_STATEMENT_SET]: (state, action) => {
|
[t.TRAIL_BALANCE_STATEMENT_SET]: (state, action) => {
|
||||||
@@ -173,6 +214,12 @@ export default createReducer(initialState, {
|
|||||||
[t.TRIAL_BALANCE_SHEET_LOADING]: (state, action) => {
|
[t.TRIAL_BALANCE_SHEET_LOADING]: (state, action) => {
|
||||||
state.trialBalance.loading = !!action.loading;
|
state.trialBalance.loading = !!action.loading;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
[t.TRIAL_BALANCE_REFRESH]: (state, action) => {
|
||||||
|
const { refresh } = action.payload;
|
||||||
|
state.trialBalance.refresh = refresh;
|
||||||
|
},
|
||||||
|
|
||||||
...financialStatementFilterToggle('TRIAL_BALANCE', 'trialBalance'),
|
...financialStatementFilterToggle('TRIAL_BALANCE', 'trialBalance'),
|
||||||
|
|
||||||
[t.JOURNAL_SHEET_SET]: (state, action) => {
|
[t.JOURNAL_SHEET_SET]: (state, action) => {
|
||||||
@@ -196,6 +243,10 @@ export default createReducer(initialState, {
|
|||||||
[t.JOURNAL_SHEET_LOADING]: (state, action) => {
|
[t.JOURNAL_SHEET_LOADING]: (state, action) => {
|
||||||
state.journal.loading = !!action.loading;
|
state.journal.loading = !!action.loading;
|
||||||
},
|
},
|
||||||
|
[t.JOURNAL_SHEET_REFRESH]: (state, action) => {
|
||||||
|
const { refresh } = action.payload;
|
||||||
|
state.journal.refresh = !!refresh;
|
||||||
|
},
|
||||||
...financialStatementFilterToggle('JOURNAL', 'journal'),
|
...financialStatementFilterToggle('JOURNAL', 'journal'),
|
||||||
|
|
||||||
[t.GENERAL_LEDGER_STATEMENT_SET]: (state, action) => {
|
[t.GENERAL_LEDGER_STATEMENT_SET]: (state, action) => {
|
||||||
@@ -219,6 +270,10 @@ export default createReducer(initialState, {
|
|||||||
[t.GENERAL_LEDGER_SHEET_LOADING]: (state, action) => {
|
[t.GENERAL_LEDGER_SHEET_LOADING]: (state, action) => {
|
||||||
state.generalLedger.loading = !!action.loading;
|
state.generalLedger.loading = !!action.loading;
|
||||||
},
|
},
|
||||||
|
[t.GENERAL_LEDGER_REFRESH]: (state, action) => {
|
||||||
|
const { refresh } = action.payload;
|
||||||
|
state.generalLedger.refresh = !!refresh;
|
||||||
|
},
|
||||||
...financialStatementFilterToggle('GENERAL_LEDGER', 'generalLedger'),
|
...financialStatementFilterToggle('GENERAL_LEDGER', 'generalLedger'),
|
||||||
|
|
||||||
[t.PROFIT_LOSS_SHEET_SET]: (state, action) => {
|
[t.PROFIT_LOSS_SHEET_SET]: (state, action) => {
|
||||||
@@ -243,6 +298,12 @@ export default createReducer(initialState, {
|
|||||||
[t.PROFIT_LOSS_SHEET_LOADING]: (state, action) => {
|
[t.PROFIT_LOSS_SHEET_LOADING]: (state, action) => {
|
||||||
state.profitLoss.loading = !!action.loading;
|
state.profitLoss.loading = !!action.loading;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
[t.PROFIT_LOSS_REFRESH]: (state, action) => {
|
||||||
|
const { refresh } = action.payload;
|
||||||
|
state.profitLoss.refresh = !!refresh;
|
||||||
|
},
|
||||||
|
|
||||||
...financialStatementFilterToggle('PROFIT_LOSS', 'profitLoss'),
|
...financialStatementFilterToggle('PROFIT_LOSS', 'profitLoss'),
|
||||||
|
|
||||||
[t.RECEIVABLE_AGING_SUMMARY_LOADING]: (state, action) => {
|
[t.RECEIVABLE_AGING_SUMMARY_LOADING]: (state, action) => {
|
||||||
@@ -258,7 +319,7 @@ export default createReducer(initialState, {
|
|||||||
query,
|
query,
|
||||||
columns,
|
columns,
|
||||||
aging,
|
aging,
|
||||||
tableRows: aging
|
tableRows: mapContactAgingSummary(aging)
|
||||||
};
|
};
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
state.receivableAgingSummary[index] = receivableSheet;
|
state.receivableAgingSummary[index] = receivableSheet;
|
||||||
@@ -266,5 +327,9 @@ export default createReducer(initialState, {
|
|||||||
state.receivableAgingSummary.sheets.push(receivableSheet);
|
state.receivableAgingSummary.sheets.push(receivableSheet);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
[t.RECEIVABLE_AGING_SUMMARY_REFRESH]: (state, action) => {
|
||||||
|
const { refresh } = action.payload;
|
||||||
|
state.receivableAgingSummary.refresh = !!refresh;
|
||||||
|
},
|
||||||
...financialStatementFilterToggle('RECEIVABLE_AGING_SUMMARY', 'receivableAgingSummary'),
|
...financialStatementFilterToggle('RECEIVABLE_AGING_SUMMARY', 'receivableAgingSummary'),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,19 +3,26 @@
|
|||||||
export default {
|
export default {
|
||||||
GENERAL_LEDGER_STATEMENT_SET: 'GENERAL_LEDGER_STATEMENT_SET',
|
GENERAL_LEDGER_STATEMENT_SET: 'GENERAL_LEDGER_STATEMENT_SET',
|
||||||
GENERAL_LEDGER_SHEET_LOADING: 'GENERAL_LEDGER_SHEET_LOADING',
|
GENERAL_LEDGER_SHEET_LOADING: 'GENERAL_LEDGER_SHEET_LOADING',
|
||||||
|
GENERAL_LEDGER_REFRESH: 'GENERAL_LEDGER_REFRESH',
|
||||||
|
|
||||||
BALANCE_SHEET_STATEMENT_SET: 'BALANCE_SHEET_STATEMENT_SET',
|
BALANCE_SHEET_STATEMENT_SET: 'BALANCE_SHEET_STATEMENT_SET',
|
||||||
BALANCE_SHEET_LOADING: 'BALANCE_SHEET_LOADING',
|
BALANCE_SHEET_LOADING: 'BALANCE_SHEET_LOADING',
|
||||||
|
BALANCE_SHEET_REFRESH: 'BALANCE_SHEET_REFRESH',
|
||||||
|
|
||||||
TRAIL_BALANCE_STATEMENT_SET: 'TRAIL_BALANCE_STATEMENT_SET',
|
TRAIL_BALANCE_STATEMENT_SET: 'TRAIL_BALANCE_STATEMENT_SET',
|
||||||
TRIAL_BALANCE_SHEET_LOADING: 'TRIAL_BALANCE_SHEET_LOADING',
|
TRIAL_BALANCE_SHEET_LOADING: 'TRIAL_BALANCE_SHEET_LOADING',
|
||||||
|
TRIAL_BALANCE_REFRESH: 'TRIAL_BALANCE_REFRESH',
|
||||||
|
|
||||||
JOURNAL_SHEET_SET: 'JOURNAL_SHEET_SET',
|
JOURNAL_SHEET_SET: 'JOURNAL_SHEET_SET',
|
||||||
JOURNAL_SHEET_LOADING: 'JOURNAL_SHEET_LOADING',
|
JOURNAL_SHEET_LOADING: 'JOURNAL_SHEET_LOADING',
|
||||||
|
JOURNAL_SHEET_REFRESH: 'JOURNAL_SHEET_REFRESH',
|
||||||
|
|
||||||
PROFIT_LOSS_SHEET_SET: 'PROFIT_LOSS_SHEET_SET',
|
PROFIT_LOSS_SHEET_SET: 'PROFIT_LOSS_SHEET_SET',
|
||||||
PROFIT_LOSS_SHEET_LOADING: 'PROFIT_LOSS_SHEET_LOADING',
|
PROFIT_LOSS_SHEET_LOADING: 'PROFIT_LOSS_SHEET_LOADING',
|
||||||
|
PROFIT_LOSS_REFRESH: 'PROFIT_LOSS_REFRESH',
|
||||||
|
|
||||||
RECEIVABLE_AGING_SUMMARY_LOADING: 'RECEIVABLE_AGING_SUMMARY_LOADING',
|
RECEIVABLE_AGING_SUMMARY_LOADING: 'RECEIVABLE_AGING_SUMMARY_LOADING',
|
||||||
RECEIVABLE_AGING_SUMMARY_SET: 'RECEIVABLE_AGING_SUMMARY_SET',
|
RECEIVABLE_AGING_SUMMARY_SET: 'RECEIVABLE_AGING_SUMMARY_SET',
|
||||||
|
RECEIVABLE_AGING_REFRECH: 'RECEIVABLE_AGING_REFRECH',
|
||||||
|
RECEIVABLE_AGING_SUMMARY_REFRESH: 'RECEIVABLE_AGING_SUMMARY_REFRESH',
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,11 @@ $pt-popover-box-shadow: 0 0 0 1px rgba(16, 22, 26, 0.02),
|
|||||||
@import '@blueprintjs/core/src/common/_variables.scss';
|
@import '@blueprintjs/core/src/common/_variables.scss';
|
||||||
// @import "@blueprintjs/core/src/common/colors.scss";
|
// @import "@blueprintjs/core/src/common/colors.scss";
|
||||||
|
|
||||||
|
$blue1: #0069ff;
|
||||||
|
$blue2: #0052ff;
|
||||||
|
$blue3: rgb(0, 82, 204);
|
||||||
|
$pt-link-color: $blue3;
|
||||||
|
$pt-intent-primary: $blue1;
|
||||||
$menu-item-color-hover: $light-gray4;
|
$menu-item-color-hover: $light-gray4;
|
||||||
$menu-item-color-active: $light-gray3;
|
$menu-item-color-active: $light-gray3;
|
||||||
|
|
||||||
@@ -118,3 +123,13 @@ body.authentication {
|
|||||||
.bp3-datepicker-caption .bp3-html-select::after{
|
.bp3-datepicker-caption .bp3-html-select::after{
|
||||||
margin-right: 6px;
|
margin-right: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.hint{
|
||||||
|
color: #a1b2c5;
|
||||||
|
margin-left: 6px;
|
||||||
|
|
||||||
|
.bp3-icon{
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -254,10 +254,16 @@
|
|||||||
border-top: 1px solid #666;
|
border-top: 1px solid #666;
|
||||||
border-bottom: 1px solid #666;
|
border-bottom: 1px solid #666;
|
||||||
|
|
||||||
padding: 10px 0.4rem;
|
padding: 8px 0.4rem;
|
||||||
color: #222;
|
color: #222;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tbody{
|
||||||
|
.tr .td{
|
||||||
|
border-bottom: 1px dotted #BBB;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
$form-check-input-checked-color: #fff;
|
$form-check-input-checked-color: #fff;
|
||||||
|
$form-check-input-checked-bg-color: $blue1;
|
||||||
$form-check-input-checked-bg-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 16 16' enable-background='new 0 0 16 16' xml:space='preserve'><g id='small_tick_1_'><g><path fill='#{$form-check-input-checked-color}' fill-rule='evenodd' clip-rule='evenodd' d='M12,5c-0.28,0-0.53,0.11-0.71,0.29L7,9.59L4.71,7.29C4.53,7.11,4.28,7,4,7C3.45,7,3,7.45,3,8c0,0.28,0.11,0.53,0.29,0.71l3,3C6.47,11.89,6.72,12,7,12s0.53-0.11,0.71-0.29l5-5C12.89,6.53,13,6.28,13,6C13,5.45,12.55,5,12,5z'/></g></g></svg>") !default;
|
$form-check-input-checked-bg-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 16 16' enable-background='new 0 0 16 16' xml:space='preserve'><g id='small_tick_1_'><g><path fill='#{$form-check-input-checked-color}' fill-rule='evenodd' clip-rule='evenodd' d='M12,5c-0.28,0-0.53,0.11-0.71,0.29L7,9.59L4.71,7.29C4.53,7.11,4.28,7,4,7C3.45,7,3,7.45,3,8c0,0.28,0.11,0.53,0.29,0.71l3,3C6.47,11.89,6.72,12,7,12s0.53-0.11,0.71-0.29l5-5C12.89,6.53,13,6.28,13,6C13,5.45,12.55,5,12,5z'/></g></g></svg>") !default;
|
||||||
$form-check-input-indeterminate-bg-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 16 16' enable-background='new 0 0 16 16' xml:space='preserve'><g id='small_tick_1_'><g><path fill='#{$form-check-input-checked-color}' fill-rule='evenodd' clip-rule='evenodd' d='M11,7H5C4.45,7,4,7.45,4,8c0,0.55,0.45,1,1,1h6c0.55,0,1-0.45,1-1C12,7.45,11.55,7,11,7z'/></g></g></svg>") !default;
|
$form-check-input-indeterminate-bg-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 16 16' enable-background='new 0 0 16 16' xml:space='preserve'><g id='small_tick_1_'><g><path fill='#{$form-check-input-checked-color}' fill-rule='evenodd' clip-rule='evenodd' d='M11,7H5C4.45,7,4,7.45,4,8c0,0.55,0.45,1,1,1h6c0.55,0,1-0.45,1-1C12,7.45,11.55,7,11,7z'/></g></g></svg>") !default;
|
||||||
|
|
||||||
@@ -9,7 +10,7 @@ $form-check-input-indeterminate-bg-image: url("data:image/svg+xml,<svg xmlns='ht
|
|||||||
left: 220px;
|
left: 220px;
|
||||||
right: 0;
|
right: 0;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
padding: 14px 16px;
|
padding: 14px 18px;
|
||||||
border-top: 1px solid #ececec;
|
border-top: 1px solid #ececec;
|
||||||
|
|
||||||
.has-mini-sidebar &{
|
.has-mini-sidebar &{
|
||||||
@@ -48,7 +49,7 @@ $form-check-input-indeterminate-bg-image: url("data:image/svg+xml,<svg xmlns='ht
|
|||||||
|
|
||||||
&.#{$ns}-intent-danger{
|
&.#{$ns}-intent-danger{
|
||||||
select{
|
select{
|
||||||
box-shadow: 0 0 0 0 rgba(219, 55, 55, 0),
|
box-shadow: 0 0 0 0 rgba(228, 226, 226, 0),
|
||||||
0 0 0 0 rgba(2, 2, 2, 0),
|
0 0 0 0 rgba(2, 2, 2, 0),
|
||||||
inset 0 0 0 1px #db3737,
|
inset 0 0 0 1px #db3737,
|
||||||
inset 0 0 0 1px rgba(16, 22, 26, 0.15),
|
inset 0 0 0 1px rgba(16, 22, 26, 0.15),
|
||||||
@@ -285,13 +286,13 @@ $form-check-input-indeterminate-bg-image: url("data:image/svg+xml,<svg xmlns='ht
|
|||||||
}
|
}
|
||||||
input:checked ~ .#{$ns}-control-indicator {
|
input:checked ~ .#{$ns}-control-indicator {
|
||||||
background-image: escape-svg($form-check-input-checked-bg-image);
|
background-image: escape-svg($form-check-input-checked-bg-image);
|
||||||
border-color: #137cbd;
|
border-color: $form-check-input-checked-bg-color;
|
||||||
background-color: #137cbd;
|
background-color: $form-check-input-checked-bg-color;
|
||||||
}
|
}
|
||||||
input:indeterminate ~ .#{$ns}-control-indicator {
|
input:indeterminate ~ .#{$ns}-control-indicator {
|
||||||
background-image: escape-svg($form-check-input-indeterminate-bg-image);
|
background-image: escape-svg($form-check-input-indeterminate-bg-image);
|
||||||
border-color: #137cbd;
|
border-color: $form-check-input-checked-bg-color;
|
||||||
background-color: #137cbd;
|
background-color: $form-check-input-checked-bg-color;
|
||||||
box-shadow: 0 0 0 0 transparent;
|
box-shadow: 0 0 0 0 transparent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -314,8 +315,6 @@ $form-check-input-indeterminate-bg-image: url("data:image/svg+xml,<svg xmlns='ht
|
|||||||
Styleguide radio
|
Styleguide radio
|
||||||
*/
|
*/
|
||||||
&.#{$ns}-radio {
|
&.#{$ns}-radio {
|
||||||
|
|
||||||
|
|
||||||
.#{$ns}-control-indicator{
|
.#{$ns}-control-indicator{
|
||||||
border: 2px solid #cecece;
|
border: 2px solid #cecece;
|
||||||
|
|
||||||
@@ -326,10 +325,10 @@ $form-check-input-indeterminate-bg-image: url("data:image/svg+xml,<svg xmlns='ht
|
|||||||
}
|
}
|
||||||
|
|
||||||
input:checked ~ .#{$ns}-control-indicator{
|
input:checked ~ .#{$ns}-control-indicator{
|
||||||
border-color: #137cbd;
|
border-color: $form-check-input-checked-bg-color;
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
background-image: radial-gradient(#137cbd 40%, transparent 40%);
|
background-image: radial-gradient($form-check-input-checked-bg-color 40%, transparent 40%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,8 +68,8 @@
|
|||||||
background-size: contain;
|
background-size: contain;
|
||||||
background-color: #EED1F2;
|
background-color: #EED1F2;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
height: 30px;
|
height: 35px;
|
||||||
width: 30px;
|
width: 35px;
|
||||||
|
|
||||||
.user-text {
|
.user-text {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
@@ -156,6 +156,19 @@
|
|||||||
background: rgba(219, 55, 55, 0.1);
|
background: rgba(219, 55, 55, 0.1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.button--blue-highlight{
|
||||||
|
background-color: #ebfaff;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus{
|
||||||
|
background-color: darken(#ebfaff, 2.5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.button--gray-highlight{
|
||||||
|
background-color: rgba(127, 189, 255, 0.1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.button--table-views{
|
.button--table-views{
|
||||||
|
|||||||
@@ -9,70 +9,49 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
.bp3-form-group {
|
.bp3-form-group {
|
||||||
.bp3-label {
|
.bp3-label {
|
||||||
margin-bottom: 15px;
|
|
||||||
margin-right: 15px;
|
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
color: #444;
|
color: #444;
|
||||||
}
|
}
|
||||||
.bp3-form-content {
|
.bp3-form-content {
|
||||||
.bp3-button:not([class*='bp3-intent-']):not(.bp3-minimal) {
|
.bp3-button:not([class*='bp3-intent-']):not(.bp3-minimal) {
|
||||||
min-width: 300px;
|
|
||||||
min-height: 32px;
|
|
||||||
background: #fff;
|
|
||||||
box-shadow: 0 0 0 transparent;
|
|
||||||
border: 1px solid #ced4da;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.bp3-input-group {
|
.bp3-input-group {
|
||||||
display: block;
|
|
||||||
position: relative;
|
|
||||||
width: 300px;
|
|
||||||
}
|
}
|
||||||
&.form-group--ref_no {
|
&.form-group--ref_no {
|
||||||
.bp3-input-group .bp3-input {
|
.bp3-input-group .bp3-input {
|
||||||
position: relative;
|
|
||||||
width: 180px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-group--payment_account {
|
.form-group--payment_account {
|
||||||
.bp3-form-group {
|
.bp3-form-group {
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
margin: 0 0 15px;
|
|
||||||
}
|
}
|
||||||
.bp3-form-content {
|
.bp3-form-content {
|
||||||
.bp3-button:not([class*='bp3-intent-']):not(.bp3-minimal) {
|
.bp3-button:not([class*='bp3-intent-']):not(.bp3-minimal) {
|
||||||
min-width: 380px;
|
|
||||||
min-height: 32px;
|
|
||||||
background: #fff;
|
|
||||||
box-shadow: 0 0 0 transparent;
|
|
||||||
border: 1px solid #ced4da;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-group--currency {
|
.form-group--currency {
|
||||||
.bp3-form-group {
|
.bp3-form-group {
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
margin: 0 0 15px;
|
|
||||||
}
|
}
|
||||||
.bp3-form-content {
|
.bp3-form-content {
|
||||||
.bp3-button:not([class*='bp3-intent-']):not(.bp3-minimal) {
|
.bp3-button:not([class*='bp3-intent-']):not(.bp3-minimal) {
|
||||||
min-width: 180px;
|
|
||||||
min-height: 32px;
|
|
||||||
background: #fff;
|
|
||||||
box-shadow: 0 0 0 transparent;
|
|
||||||
border: 1px solid #ced4da;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__table {
|
&__table {
|
||||||
padding: 15px 25px 0;
|
padding: 15px 15px 0;
|
||||||
|
|
||||||
.bp3-form-group {
|
.bp3-form-group {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
@@ -160,19 +139,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.row--total {
|
&.row--total {
|
||||||
.account.td,
|
|
||||||
.debit.td,
|
.td.amount{
|
||||||
.credit.td {
|
font-weight: bold;
|
||||||
> span {
|
|
||||||
padding-top: 6px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.debit.td,
|
|
||||||
.credit.td {
|
|
||||||
> span {
|
|
||||||
font-weight: 600;
|
|
||||||
color: #444;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -212,17 +181,17 @@
|
|||||||
.dropzone {
|
.dropzone {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
height: 75px;
|
height: 75px;
|
||||||
|
}
|
||||||
|
|
||||||
margin-right: 20px;
|
.expense-form-footer{
|
||||||
|
display: flex;
|
||||||
|
padding: 30px 25px 0;
|
||||||
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-group--description {
|
.form-group--description {
|
||||||
padding: 25px 27px 20px;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
.bp3-label {
|
.bp3-label {
|
||||||
margin-bottom: 15px;
|
|
||||||
margin-right: 15px;
|
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
color: #444;
|
color: #444;
|
||||||
@@ -230,10 +199,32 @@
|
|||||||
.bp3-form-content {
|
.bp3-form-content {
|
||||||
// width: 280px;
|
// width: 280px;
|
||||||
textarea {
|
textarea {
|
||||||
width: 300px;
|
width: 450px;
|
||||||
height: 75px;
|
min-height: 75px;
|
||||||
margin-right: 20px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.dashboard__insider--expenses{
|
||||||
|
|
||||||
|
.bigcapital-datatable{
|
||||||
|
|
||||||
|
.tbody{
|
||||||
|
.total_amount{
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description{
|
||||||
|
.bp3-icon{
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
.bp3-tooltip-indicator{
|
||||||
|
cursor: initial;
|
||||||
|
border-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -52,7 +52,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.financial-sheet{
|
.financial-sheet{
|
||||||
border: 1px solid #EEE;
|
border: 2px solid #F1F1F1;
|
||||||
|
border-radius: 10px;
|
||||||
min-width: 640px;
|
min-width: 640px;
|
||||||
width: auto;
|
width: auto;
|
||||||
padding: 30px 20px;
|
padding: 30px 20px;
|
||||||
@@ -64,22 +65,22 @@
|
|||||||
|
|
||||||
&__title{
|
&__title{
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-weight: 300;
|
font-weight: 400;
|
||||||
font-size: 22px;
|
font-size: 22px;
|
||||||
color: #333;
|
color: #464646;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
&__sheet-type{
|
&__sheet-type{
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 15px;
|
font-size: 16px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
color: #666;
|
color: #666;
|
||||||
margin-top: 6px;
|
margin-top: 6px;
|
||||||
}
|
}
|
||||||
&__date{
|
&__date{
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #888;
|
color: #666;
|
||||||
margin-top: 6px;
|
margin-top: 6px;
|
||||||
}
|
}
|
||||||
&__table{
|
&__table{
|
||||||
@@ -93,11 +94,6 @@
|
|||||||
background: #fff;
|
background: #fff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.tbody{
|
|
||||||
.code.td{
|
|
||||||
color: #777;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.tr.no-results{
|
.tr.no-results{
|
||||||
.td{
|
.td{
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -130,23 +126,32 @@
|
|||||||
}
|
}
|
||||||
&--trial-balance{
|
&--trial-balance{
|
||||||
min-width: 720px;
|
min-width: 720px;
|
||||||
|
|
||||||
|
.financial-sheet__table{
|
||||||
|
.tbody{
|
||||||
|
.balance.td{
|
||||||
|
border-bottom-color: #000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&--general-ledger{
|
&--general-ledger{
|
||||||
.table .tbody{
|
.financial-sheet__table{
|
||||||
|
.tbody{
|
||||||
.tr.row-type{
|
.tr.row-type{
|
||||||
|
|
||||||
&--opening_balance,
|
&--opening_balance,
|
||||||
&--closing_balance{
|
&--closing_balance{
|
||||||
background-color: #fbfbfb;
|
background-color: #fbfbfb;
|
||||||
}
|
}
|
||||||
|
|
||||||
&--closing_balance .td{
|
&--closing_balance .td{
|
||||||
border-bottom-color: #666;
|
border-bottom-color: #666;
|
||||||
}
|
}
|
||||||
|
|
||||||
&--account_name .td.name{
|
&--account_name .td.name{
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -188,6 +193,9 @@
|
|||||||
.account_code.td{
|
.account_code.td{
|
||||||
color: #666;
|
color: #666;
|
||||||
}
|
}
|
||||||
|
.total.td {
|
||||||
|
border-bottom-color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
.row--income_total,
|
.row--income_total,
|
||||||
.row--expense_total,
|
.row--expense_total,
|
||||||
@@ -201,4 +209,70 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&--balance-sheet{
|
||||||
|
.financial-sheet__table{
|
||||||
|
.tbody{
|
||||||
|
|
||||||
|
.total.td{
|
||||||
|
border-bottom-color: #000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--receivable-aging-summary{
|
||||||
|
|
||||||
|
.financial-sheet__table{
|
||||||
|
.tbody{
|
||||||
|
.row-type--total{
|
||||||
|
font-weight: 600;
|
||||||
|
|
||||||
|
.td{
|
||||||
|
background-color: #fafbff;
|
||||||
|
border-bottom-color: #666;
|
||||||
|
border-bottom-style: dotted;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.financial-reports{
|
||||||
|
padding: 20px 25px;
|
||||||
|
|
||||||
|
.section-title{
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 1.6rem;
|
||||||
|
font-size: 20px;
|
||||||
|
color: rgb(31, 50, 85);
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__list{
|
||||||
|
display: flex;
|
||||||
|
flex-flow: wrap;
|
||||||
|
margin-left: -28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__item{
|
||||||
|
width: 270px;
|
||||||
|
margin-bottom: 40px;
|
||||||
|
margin-left: 28px;
|
||||||
|
border-top: 2px solid #DDD;
|
||||||
|
padding-top: 16px;
|
||||||
|
|
||||||
|
.title{
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.desc{
|
||||||
|
color: rgb(31, 50, 85);
|
||||||
|
line-height: 1.55;
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -48,7 +48,7 @@
|
|||||||
background-color: #F2F5FA;
|
background-color: #F2F5FA;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: #333;
|
color: #1e1c3e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,8 @@ $sidebar-popover-submenu-bg: rgb(1, 20, 62);
|
|||||||
padding: 16px 12px;
|
padding: 16px 12px;
|
||||||
|
|
||||||
&-logo{
|
&-logo{
|
||||||
margin-top: 2px;
|
position: relative;
|
||||||
|
top: 2px;
|
||||||
|
|
||||||
svg{
|
svg{
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
@@ -59,7 +60,7 @@ $sidebar-popover-submenu-bg: rgb(1, 20, 62);
|
|||||||
.#{$ns}-menu-item {
|
.#{$ns}-menu-item {
|
||||||
color: $sidebar-menu-item-color;
|
color: $sidebar-menu-item-color;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
padding: 10px 16px;
|
padding: 9px 16px;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
|
||||||
@@ -81,7 +82,14 @@ $sidebar-popover-submenu-bg: rgb(1, 20, 62);
|
|||||||
> .#{$ns}-icon-caret-right {
|
> .#{$ns}-icon-caret-right {
|
||||||
margin-right: -4px;
|
margin-right: -4px;
|
||||||
margin-top: 3px;
|
margin-top: 3px;
|
||||||
color: #42547b;
|
color: #354569;
|
||||||
|
}
|
||||||
|
&-label{
|
||||||
|
display: block;
|
||||||
|
color: rgba(255, 255, 255, 0.45);
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 4px 16px;
|
||||||
|
margin-top: 6px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,7 +127,7 @@ $sidebar-popover-submenu-bg: rgb(1, 20, 62);
|
|||||||
color: $sidebar-menu-item-color;
|
color: $sidebar-menu-item-color;
|
||||||
}
|
}
|
||||||
.#{$ns}-menu-divider {
|
.#{$ns}-menu-divider {
|
||||||
border-top-color: #152a55;
|
border-top-color: rgba(255, 255, 255, 0.1);
|
||||||
color: #6b708c;
|
color: #6b708c;
|
||||||
margin: 4px 0;
|
margin: 4px 0;
|
||||||
}
|
}
|
||||||
@@ -134,39 +142,22 @@ $sidebar-popover-submenu-bg: rgb(1, 20, 62);
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
width: 50px;
|
width: 50px;
|
||||||
|
|
||||||
|
|
||||||
// Hide text of bigcapital logo.
|
// Hide text of bigcapital logo.
|
||||||
.sidebar__head-logo{
|
.sidebar__head-logo{
|
||||||
|
|
||||||
.bp3-icon-bigcapital{
|
.bp3-icon-bigcapital{
|
||||||
|
path{
|
||||||
|
transition: opacity 0.3s ease-in-out;
|
||||||
|
}
|
||||||
path:not(.path-1):not(.path-2) {
|
path:not(.path-1):not(.path-2) {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hide text of menu items and right caret icon.
|
|
||||||
.bp3-collapse,
|
|
||||||
.bp3-icon-caret-right,
|
|
||||||
.bp3-menu-item .bp3-text-overflow-ellipsis{
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar__menu{
|
.sidebar__menu{
|
||||||
|
transition: opacity 0.3s ease-in-out;
|
||||||
.bp3-menu{
|
opacity: 0;
|
||||||
> li:not(.bp3-submenu):not(.bp3-menu-divider):not(.has-icon){
|
|
||||||
|
|
||||||
.bp3-menu-item{
|
|
||||||
&:before{
|
|
||||||
content: "";
|
|
||||||
height: 18px;
|
|
||||||
width: 18px;
|
|
||||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' data-icon='ellipsis-h' width='18' height='18' fill='%235c7080' viewBox='0 0 512 512'%3E%3Cdesc%3Eellipsis-h%3C/desc%3E%3Cpath d='M304 256c0 26.5-21.5 48-48 48s-48-21.5-48-48 21.5-48 48-48 48 21.5 48 48zm120-48c-26.5 0-48 21.5-48 48s21.5 48 48 48 48-21.5 48-48-21.5-48-48-48zm-336 0c-26.5 0-48 21.5-48 48s21.5 48 48 48 48-21.5 48-48-21.5-48-48-48z' class='path-1' fill-rule='evenodd'%3E%3C/path%3E%3C/svg%3E");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar__scroll-wrapper{
|
.sidebar__scroll-wrapper{
|
||||||
@@ -185,17 +176,8 @@ $sidebar-popover-submenu-bg: rgb(1, 20, 62);
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.sidebar__menu{
|
||||||
.bp3-collapse,
|
opacity: 1;
|
||||||
.bp3-icon-caret-right,
|
|
||||||
.bp3-menu-item .bp3-text-overflow-ellipsis{
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
.sidebar__menu .bp3-menu > li:not(.bp3-submenu):not(.bp3-menu-divider) .bp3-menu-item{
|
|
||||||
|
|
||||||
&:before{
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -336,7 +336,7 @@ export default {
|
|||||||
}
|
}
|
||||||
const expenses = await Expense.query().onBuild((builder) => {
|
const expenses = await Expense.query().onBuild((builder) => {
|
||||||
builder.withGraphFetched('paymentAccount');
|
builder.withGraphFetched('paymentAccount');
|
||||||
builder.withGraphFetched('categories');
|
builder.withGraphFetched('categories.expenseAccount');
|
||||||
builder.withGraphFetched('user');
|
builder.withGraphFetched('user');
|
||||||
dynamicFilter.buildQuery()(builder);
|
dynamicFilter.buildQuery()(builder);
|
||||||
}).pagination(filter.page - 1, filter.page_size);;
|
}).pagination(filter.page - 1, filter.page_size);;
|
||||||
|
|||||||
@@ -106,11 +106,12 @@ export default class ReceivableAgingSummary extends AgingReport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const storedCustomers = await Customer.query().onBuild((builder) => {
|
const storedCustomers = await Customer.query().onBuild((builder) => {
|
||||||
if (filter.customer_ids) {
|
if (filter.customer_ids.length > 0) {
|
||||||
builder.modify('filterCustomerIds', filter.customer_ids);
|
builder.modify('filterCustomerIds', filter.customer_ids);
|
||||||
}
|
}
|
||||||
return builder;
|
return builder;
|
||||||
});
|
});
|
||||||
|
|
||||||
const accountsReceivableType = await AccountType.query()
|
const accountsReceivableType = await AccountType.query()
|
||||||
.where('key', 'accounts_receivable')
|
.where('key', 'accounts_receivable')
|
||||||
.first();
|
.first();
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export default class Account extends mixin(TenantModel, [CachableModel]) {
|
|||||||
/**
|
/**
|
||||||
* Timestamps columns.
|
* Timestamps columns.
|
||||||
*/
|
*/
|
||||||
static get timestamps() {
|
get timestamps() {
|
||||||
return ['createdAt', 'updatedAt'];
|
return ['createdAt', 'updatedAt'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export default class AccountTransaction extends mixin(TenantModel, [CachableMode
|
|||||||
/**
|
/**
|
||||||
* Timestamps columns.
|
* Timestamps columns.
|
||||||
*/
|
*/
|
||||||
static get timestamps() {
|
get timestamps() {
|
||||||
return ['createdAt'];
|
return ['createdAt'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export default class Customer extends TenantModel {
|
|||||||
/**
|
/**
|
||||||
* Model timestamps.
|
* Model timestamps.
|
||||||
*/
|
*/
|
||||||
static get timestamps() {
|
get timestamps() {
|
||||||
return ['createdAt', 'updatedAt'];
|
return ['createdAt', 'updatedAt'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import moment from 'moment';
|
|||||||
export default (Model) => {
|
export default (Model) => {
|
||||||
return class DateSession extends Model {
|
return class DateSession extends Model {
|
||||||
|
|
||||||
static get timestamps() {
|
get timestamps() {
|
||||||
return ['createdAt', 'updatedAt'];
|
return ['createdAt', 'updatedAt'];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -11,8 +11,8 @@ export default (Model) => {
|
|||||||
const maybePromise = super.$beforeUpdate(opt, context);
|
const maybePromise = super.$beforeUpdate(opt, context);
|
||||||
|
|
||||||
return Promise.resolve(maybePromise).then(() => {
|
return Promise.resolve(maybePromise).then(() => {
|
||||||
if (DateSession.timestamps[1]) {
|
if (this.timestamps[1]) {
|
||||||
this[DateSession.timestamps[1]] = moment().format('YYYY/MM/DD HH:mm:ss');
|
this[this.timestamps[1]] = moment().format('YYYY/MM/DD HH:mm:ss');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -21,8 +21,8 @@ export default (Model) => {
|
|||||||
const maybePromise = super.$beforeInsert(context);
|
const maybePromise = super.$beforeInsert(context);
|
||||||
|
|
||||||
return Promise.resolve(maybePromise).then(() => {
|
return Promise.resolve(maybePromise).then(() => {
|
||||||
if (DateSession.timestamps[0]) {
|
if (this.timestamps[0]) {
|
||||||
this[DateSession.timestamps[0]] = moment().format('YYYY/MM/DD HH:mm:ss');
|
this[this.timestamps[0]] = moment().format('YYYY/MM/DD HH:mm:ss');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user