diff --git a/src/containers/Accounting/MakeJournal/MakeJournalEntriesHeaderFields.js b/src/containers/Accounting/MakeJournal/MakeJournalEntriesHeaderFields.js
index 448ef9b67..9e5e3a783 100644
--- a/src/containers/Accounting/MakeJournal/MakeJournalEntriesHeaderFields.js
+++ b/src/containers/Accounting/MakeJournal/MakeJournalEntriesHeaderFields.js
@@ -9,7 +9,6 @@ import { FastField, ErrorMessage } from 'formik';
import { DateInput } from '@blueprintjs/datetime';
import { FormattedMessage as T } from 'components';
import classNames from 'classnames';
-import { Features } from 'common';
import { CLASSES } from 'common/classes';
import {
@@ -24,14 +23,12 @@ import {
FieldHint,
FieldRequiredHint,
Icon,
- If,
- FeatureCan,
InputPrependButton,
CurrencySelectList,
- ExchangeRateInputGroup,
} from 'components';
import withSettings from 'containers/Settings/withSettings';
import { useMakeJournalFormContext } from './MakeJournalProvider';
+import { JournalExchangeRateInputField } from './components';
import withDialogActions from 'containers/Dialog/withDialogActions';
import {
currenciesFieldShouldUpdate,
@@ -52,13 +49,7 @@ function MakeJournalEntriesHeader({
journalNextNumber,
journalNumberPrefix,
}) {
- const {
- currencies,
- isForeignJournal,
- baseCurrency,
- selectJournalCurrency,
- setSelactJournalCurrency,
- } = useMakeJournalFormContext();
+ const { currencies } = useMakeJournalFormContext();
// Handle journal number change.
const handleJournalNumberChange = () => {
@@ -195,45 +186,35 @@ function MakeJournalEntriesHeader({
{/*------------ Currency -----------*/}
-
-
- {({ form, field: { value }, meta: { error, touched } }) => (
- }
- className={classNames('form-group--currency', CLASSES.FILL)}
- inline={true}
- >
- {
- form.setFieldValue(
- 'currency_code',
- currencyItem.currency_code,
- );
- form.setFieldValue('exchange_rate', '');
- setSelactJournalCurrency(currencyItem);
- }}
- defaultSelectText={value}
- />
-
- )}
-
-
+
+ {({ form, field: { value }, meta: { error, touched } }) => (
+ }
+ className={classNames('form-group--currency', CLASSES.FILL)}
+ inline={true}
+ >
+ {
+ form.setFieldValue('currency_code', currencyItem.currency_code);
+ form.setFieldValue('exchange_rate', '');
+ }}
+ defaultSelectText={value}
+ />
+
+ )}
+
{/* ----------- Exchange rate ----------- */}
-
-
-
+
);
}
diff --git a/src/containers/Accounting/MakeJournal/MakeJournalFormFooter.js b/src/containers/Accounting/MakeJournal/MakeJournalFormFooter.js
index fd1315e05..26c11aa29 100644
--- a/src/containers/Accounting/MakeJournal/MakeJournalFormFooter.js
+++ b/src/containers/Accounting/MakeJournal/MakeJournalFormFooter.js
@@ -1,44 +1,29 @@
import React from 'react';
-import { FastField } from 'formik';
import classNames from 'classnames';
+import styled from 'styled-components';
+
import { CLASSES } from 'common/classes';
-import { FormGroup, TextArea } from '@blueprintjs/core';
-import { FormattedMessage as T } from 'components';
-import { Postbox, ErrorMessage, Row, Col } from 'components';
-import Dragzone from 'components/Dragzone';
-import { inputIntent } from 'utils';
+import { Row, Col, Paper } from 'components';
+import { MakeJournalFormFooterLeft } from './MakeJournalFormFooterLeft';
+import { MakeJournalFormFooterRight } from './MakeJournalFormFooterRight';
export default function MakeJournalFormFooter() {
return (
-
} defaultOpen={false}>
+
-
- {({ field, meta: { error, touched } }) => (
- }
- className={'form-group--description'}
- intent={inputIntent({ error, touched })}
- helperText={}
- fill={true}
- >
-
-
- )}
-
+
- }
- />
+
-
+
);
}
+const MakeJournalFooterPaper = styled(Paper)`
+ padding: 20px;
+`;
diff --git a/src/containers/Accounting/MakeJournal/MakeJournalFormFooterLeft.js b/src/containers/Accounting/MakeJournal/MakeJournalFormFooterLeft.js
new file mode 100644
index 000000000..607093a9e
--- /dev/null
+++ b/src/containers/Accounting/MakeJournal/MakeJournalFormFooterLeft.js
@@ -0,0 +1,34 @@
+import React from 'react';
+import styled from 'styled-components';
+import { FFormGroup, FEditableText, FormattedMessage as T } from 'components';
+
+export function MakeJournalFormFooterLeft() {
+ return (
+
+ {/* --------- Description --------- */}
+ }
+ name={'description'}
+ >
+
+
+
+ );
+}
+
+const DescriptionFormGroup = styled(FFormGroup)`
+ &.bp3-form-group {
+ .bp3-label {
+ font-size: 12px;
+ margin-bottom: 12px;
+ }
+ .bp3-form-content {
+ margin-left: 10px;
+ }
+ }
+`;
diff --git a/src/containers/Accounting/MakeJournal/MakeJournalFormFooterRight.js b/src/containers/Accounting/MakeJournal/MakeJournalFormFooterRight.js
new file mode 100644
index 000000000..fc18018f4
--- /dev/null
+++ b/src/containers/Accounting/MakeJournal/MakeJournalFormFooterRight.js
@@ -0,0 +1,35 @@
+import React from 'react';
+import styled from 'styled-components';
+import {
+ T,
+ TotalLines,
+ TotalLine,
+ TotalLineBorderStyle,
+ TotalLineTextStyle,
+} from 'components';
+import { useJournalTotals } from './utils';
+
+export function MakeJournalFormFooterRight() {
+ const { formattedSubtotal, formattedTotal } = useJournalTotals();
+
+ return (
+
+ }
+ value={formattedSubtotal}
+ borderStyle={TotalLineBorderStyle.None}
+ />
+ }
+ value={formattedTotal}
+ // borderStyle={TotalLineBorderStyle.SingleDark}
+ textStyle={TotalLineTextStyle.Bold}
+ />
+
+ );
+}
+
+const MakeJouranlTotalLines = styled(TotalLines)`
+ width: 100%;
+ color: #555555;
+`;
diff --git a/src/containers/Accounting/MakeJournal/components.js b/src/containers/Accounting/MakeJournal/components.js
index 4354ef57d..3e8abee9a 100644
--- a/src/containers/Accounting/MakeJournal/components.js
+++ b/src/containers/Accounting/MakeJournal/components.js
@@ -10,6 +10,10 @@ import {
BranchesListFieldCell,
} from 'components/DataTableCells';
import { useFeatureCan } from 'hooks/state';
+import { useFormikContext } from 'formik';
+import { ExchangeRateInputGroup } from 'components';
+import { useCurrentOrganization } from 'hooks/state';
+import { useJournalIsForeign } from './utils';
import { Features } from 'common';
/**
@@ -145,3 +149,26 @@ export const useJournalTableEntriesColumns = () => {
[],
);
};
+
+/**
+ * Journal exchange rate input field.
+ * @returns {JSX.Element}
+ */
+ export function JournalExchangeRateInputField({ ...props }) {
+ const currentOrganization = useCurrentOrganization();
+ const { values } = useFormikContext();
+
+ const isForeignJouranl = useJournalIsForeign();
+
+ // Can't continue if the customer is not foreign.
+ if (!isForeignJouranl) {
+ return null;
+ }
+ return (
+
+ );
+}
diff --git a/src/containers/Accounting/MakeJournal/utils.js b/src/containers/Accounting/MakeJournal/utils.js
index 4fb625f80..7b49d5376 100644
--- a/src/containers/Accounting/MakeJournal/utils.js
+++ b/src/containers/Accounting/MakeJournal/utils.js
@@ -10,11 +10,14 @@ import {
transformToForm,
defaultFastFieldShouldUpdate,
ensureEntriesHasEmptyLine,
+ formattedAmount,
+ safeSumBy,
} from 'utils';
import { AppToaster } from 'components';
import intl from 'react-intl-universal';
import { useFormikContext } from 'formik';
import { useMakeJournalFormContext } from './MakeJournalProvider';
+import { useCurrentOrganization } from 'hooks/state';
const ERROR = {
JOURNAL_NUMBER_ALREADY_EXISTS: 'JOURNAL.NUMBER.ALREADY.EXISTS',
@@ -214,3 +217,48 @@ export const useSetPrimaryBranchToForm = () => {
}
}, [isBranchesSuccess, setFieldValue, branches]);
};
+
+/**
+ * Retreives the Journal totals.
+ */
+export const useJournalTotals = () => {
+ const {
+ values: { entries, currency_code: currencyCode },
+ } = useFormikContext();
+
+ // Retrieves the invoice entries total.
+ const totalCredit = safeSumBy(entries, 'credit');
+ const totalDebit = safeSumBy(entries, 'debit');
+
+ const total = Math.max(totalCredit, totalDebit);
+ // Retrieves the formatted total money.
+ const formattedTotal = React.useMemo(
+ () => formattedAmount(total, currencyCode),
+ [total, currencyCode],
+ );
+ // Retrieves the formatted subtotal.
+ const formattedSubtotal = React.useMemo(
+ () => formattedAmount(total, currencyCode, { money: false }),
+ [total, currencyCode],
+ );
+
+ return {
+ formattedTotal,
+ formattedSubtotal,
+ };
+};
+
+/**
+ * Detarmines whether the expenses has foreign .
+ * @returns {boolean}
+ */
+export const useJournalIsForeign = () => {
+ const { values } = useFormikContext();
+ const currentOrganization = useCurrentOrganization();
+
+ const isForeignJournal = React.useMemo(
+ () => values.currency_code !== currentOrganization.base_currency,
+ [values.currency_code, currentOrganization.base_currency],
+ );
+ return isForeignJournal;
+};
diff --git a/src/containers/Expenses/ExpenseForm/ExpenseFormFooter.js b/src/containers/Expenses/ExpenseForm/ExpenseFormFooter.js
index f60532e33..9f351a0e0 100644
--- a/src/containers/Expenses/ExpenseForm/ExpenseFormFooter.js
+++ b/src/containers/Expenses/ExpenseForm/ExpenseFormFooter.js
@@ -1,41 +1,30 @@
import React from 'react';
-import { FastField } from 'formik';
-import { FormGroup, TextArea } from '@blueprintjs/core';
-import { FormattedMessage as T } from 'components';
import classNames from 'classnames';
-import { inputIntent } from 'utils';
-import { Row, Dragzone, Col, Postbox } from 'components';
+import styled from 'styled-components';
+
import { CLASSES } from 'common/classes';
+import { Row, Col, Paper } from 'components';
+import { ExpenseFormFooterLeft } from './ExpenseFormFooterLeft';
+import { ExpenseFormFooterRight } from './ExpenseFormFooterRight';
export default function ExpenseFormFooter() {
return (
-
} defaultOpen={false}>
+
-
- {({ field, meta: { error, touched } }) => (
- }
- className={'form-group--description'}
- intent={inputIntent({ error, touched })}
- >
-
-
- )}
-
+
- }
- />
+
-
+
);
}
+
+const ExpensesFooterPaper = styled(Paper)`
+ padding: 20px;
+`;
diff --git a/src/containers/Expenses/ExpenseForm/ExpenseFormFooterLeft.js b/src/containers/Expenses/ExpenseForm/ExpenseFormFooterLeft.js
new file mode 100644
index 000000000..224182474
--- /dev/null
+++ b/src/containers/Expenses/ExpenseForm/ExpenseFormFooterLeft.js
@@ -0,0 +1,33 @@
+import React from 'react';
+import styled from 'styled-components';
+import { FFormGroup, FEditableText, FormattedMessage as T } from 'components';
+
+export function ExpenseFormFooterLeft() {
+ return (
+
+ {/* --------- Description --------- */}
+ }
+ name={'description'}
+ >
+
+
+
+ );
+}
+const DescriptionFormGroup = styled(FFormGroup)`
+ &.bp3-form-group {
+ .bp3-label {
+ font-size: 12px;
+ margin-bottom: 12px;
+ }
+ .bp3-form-content {
+ margin-left: 10px;
+ }
+ }
+`;
diff --git a/src/containers/Expenses/ExpenseForm/ExpenseFormFooterRight.js b/src/containers/Expenses/ExpenseForm/ExpenseFormFooterRight.js
new file mode 100644
index 000000000..9b9ed5685
--- /dev/null
+++ b/src/containers/Expenses/ExpenseForm/ExpenseFormFooterRight.js
@@ -0,0 +1,35 @@
+import React from 'react';
+import styled from 'styled-components';
+import {
+ T,
+ TotalLines,
+ TotalLine,
+ TotalLineBorderStyle,
+ TotalLineTextStyle,
+} from 'components';
+import { useExpensesTotals } from './utils';
+
+export function ExpenseFormFooterRight() {
+ const { formattedSubtotal, formattedTotal } = useExpensesTotals();
+
+ return (
+
+ }
+ value={formattedSubtotal}
+ borderStyle={TotalLineBorderStyle.None}
+ />
+ }
+ value={formattedTotal}
+ // borderStyle={TotalLineBorderStyle.SingleDark}
+ textStyle={TotalLineTextStyle.Bold}
+ />
+
+ );
+}
+
+const ExpensesTotalLines = styled(TotalLines)`
+ width: 100%;
+ color: #555555;
+`;
diff --git a/src/containers/Expenses/ExpenseForm/ExpenseFormHeaderFields.js b/src/containers/Expenses/ExpenseForm/ExpenseFormHeaderFields.js
index 432f0ba29..3200af8b7 100644
--- a/src/containers/Expenses/ExpenseForm/ExpenseFormHeaderFields.js
+++ b/src/containers/Expenses/ExpenseForm/ExpenseFormHeaderFields.js
@@ -23,10 +23,9 @@ import {
CustomerSelectField,
AccountsSelectList,
FieldRequiredHint,
- ExchangeRateInputGroup,
Hint,
- If,
} from 'components';
+import { ExpensesExchangeRateInputField } from './components';
import { ACCOUNT_PARENT_TYPE } from 'common/accountTypes';
import { useExpenseFormContext } from './ExpenseFormPageProvider';
@@ -34,15 +33,7 @@ import { useExpenseFormContext } from './ExpenseFormPageProvider';
* Expense form header.
*/
export default function ExpenseFormHeader() {
- const {
- currencies,
- accounts,
- customers,
- isForeignCustomer,
- baseCurrency,
- selectCustomer,
- setSelectCustomer,
- } = useExpenseFormContext();
+ const { currencies, accounts, customers } = useExpenseFormContext();
return (
@@ -118,7 +109,6 @@ export default function ExpenseFormHeader() {
selectedCurrencyCode={value}
onCurrencySelected={(currencyItem) => {
form.setFieldValue('currency_code', currencyItem.currency_code);
- setSelectCustomer(currencyItem);
}}
defaultSelectText={value}
/>
@@ -126,14 +116,11 @@ export default function ExpenseFormHeader() {
)}
-
-
-
+ {/* ----------- Exchange rate ----------- */}
+
{({ form, field, meta: { error, touched } }) => (
diff --git a/src/containers/Expenses/ExpenseForm/components.js b/src/containers/Expenses/ExpenseForm/components.js
index 25ffd9a32..0a87717be 100644
--- a/src/containers/Expenses/ExpenseForm/components.js
+++ b/src/containers/Expenses/ExpenseForm/components.js
@@ -9,7 +9,10 @@ import {
AccountsListFieldCell,
CheckBoxFieldCell,
} from 'components/DataTableCells';
-import { formattedAmount, safeSumBy } from 'utils';
+import { useFormikContext } from 'formik';
+import { ExchangeRateInputGroup } from 'components';
+import { useCurrentOrganization } from 'hooks/state';
+import { useExpensesIsForeign } from './utils';
/**
* Expense category header cell.
@@ -128,3 +131,27 @@ export function useExpenseFormTableColumns({ landedCost }) {
[],
);
}
+;
+
+/**
+ * Expense exchange rate input field.
+ * @returns {JSX.Element}
+ */
+export function ExpensesExchangeRateInputField({ ...props }) {
+ const currentOrganization = useCurrentOrganization();
+ const { values } = useFormikContext();
+
+ const isForeignJouranl = useExpensesIsForeign();
+
+ // Can't continue if the customer is not foreign.
+ if (!isForeignJouranl) {
+ return null;
+ }
+ return (
+
+ );
+}
diff --git a/src/containers/Expenses/ExpenseForm/utils.js b/src/containers/Expenses/ExpenseForm/utils.js
index 0f8dc0c5a..da4b2a5d7 100644
--- a/src/containers/Expenses/ExpenseForm/utils.js
+++ b/src/containers/Expenses/ExpenseForm/utils.js
@@ -5,7 +5,7 @@ import { useFormikContext } from 'formik';
import moment from 'moment';
import intl from 'react-intl-universal';
import * as R from 'ramda';
-import { first } from 'lodash';
+import { first, sumBy } from 'lodash';
import { useExpenseFormContext } from './ExpenseFormPageProvider';
import {
@@ -14,7 +14,9 @@ import {
repeatValue,
ensureEntriesHasEmptyLine,
orderingLinesIndexes,
+ formattedAmount,
} from 'utils';
+import { useCurrentOrganization } from 'hooks/state';
const ERROR = {
EXPENSE_ALREADY_PUBLISHED: 'EXPENSE.ALREADY.PUBLISHED',
@@ -150,3 +152,45 @@ export const useSetPrimaryBranchToForm = () => {
}
}, [isBranchesSuccess, setFieldValue, branches]);
};
+
+/**
+ * Retreives the Journal totals.
+ */
+export const useExpensesTotals = () => {
+ const {
+ values: { categories, currency_code: currencyCode },
+ } = useFormikContext();
+
+ const total = sumBy(categories, 'amount');
+
+ // Retrieves the formatted total money.
+ const formattedTotal = React.useMemo(
+ () => formattedAmount(total, currencyCode),
+ [total, currencyCode],
+ );
+ // Retrieves the formatted subtotal.
+ const formattedSubtotal = React.useMemo(
+ () => formattedAmount(total, currencyCode, { money: false }),
+ [total, currencyCode],
+ );
+
+ return {
+ formattedTotal,
+ formattedSubtotal,
+ };
+};
+
+/**
+ * Detarmines whether the expenses has foreign .
+ * @returns {boolean}
+ */
+export const useExpensesIsForeign = () => {
+ const { values } = useFormikContext();
+ const currentOrganization = useCurrentOrganization();
+
+ const isForeignExpenses = React.useMemo(
+ () => values.currency_code !== currentOrganization.base_currency,
+ [values.currency_code, currentOrganization.base_currency],
+ );
+ return isForeignExpenses;
+};
diff --git a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormFooter.js b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormFooter.js
index 7e0a70ff5..ddf8e3160 100644
--- a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormFooter.js
+++ b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormFooter.js
@@ -1,42 +1,25 @@
import React from 'react';
import classNames from 'classnames';
-import { FormGroup, TextArea } from '@blueprintjs/core';
-import { FormattedMessage as T } from 'components';
-import { FastField, ErrorMessage } from 'formik';
-import { Row, Col, Postbox } from 'components';
+import styled from 'styled-components';
+
import { CLASSES } from 'common/classes';
-import { inputIntent } from 'utils';
+import { Paper, Row, Col } from 'components';
+import { WarehouseTransferFormFooterLeft } from './WarehouseTransferFormFooterLeft';
export default function WarehouseTransferFormFooter() {
return (
-
}
- defaultOpen={false}
- >
+
- {/*------------ reason -----------*/}
-
- {({ field, meta: { error, touched } }) => (
- }
- className={'form-group--reason'}
- intent={inputIntent({ error, touched })}
- helperText={}
- >
-
-
- )}
-
+
-
+
);
}
+
+const WarehousesTransferFooterPaper = styled(Paper)`
+ padding: 20px;
+`;
diff --git a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormFooterLeft.js b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormFooterLeft.js
new file mode 100644
index 000000000..cc181b7f6
--- /dev/null
+++ b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormFooterLeft.js
@@ -0,0 +1,31 @@
+import React from 'react';
+import styled from 'styled-components';
+import { FFormGroup, FEditableText, FormattedMessage as T } from 'components';
+
+export function WarehouseTransferFormFooterLeft() {
+ return (
+
+ {/* --------- Terms and conditions --------- */}
+ } name={'reason'}>
+
+
+
+ );
+}
+
+const TermsConditsFormGroup = styled(FFormGroup)`
+ &.bp3-form-group {
+ .bp3-label {
+ font-size: 12px;
+ margin-bottom: 12px;
+ }
+ .bp3-form-content {
+ margin-left: 10px;
+ }
+ }
+`;
diff --git a/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormFooterRight.js b/src/containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormFooterRight.js
new file mode 100644
index 000000000..e69de29bb