From 39a68f5c25656c44d023e28b95ada1ac204a37e6 Mon Sep 17 00:00:00 2001
From: elforjani13 <39470382+elforjani13@users.noreply.github.com>
Date: Sun, 20 Mar 2022 16:16:22 +0200
Subject: [PATCH] feat(Sales): add sales.
---
src/components/Vendors/VendorDrawerLink.js | 3 +-
.../Bills/BillForm/BillFormFooterRight.js | 16 +++--
.../Bills/BillForm/BillFormHeaderFields.js | 44 ++++++------
.../Purchases/Bills/BillForm/components.js | 28 ++++++++
.../Purchases/Bills/BillForm/utils.js | 70 ++++++++++++++++++-
.../CreditNoteFormFooterRight.js | 7 +-
.../CreditNoteFormHeaderFields.js | 35 +++++-----
.../CreditNotes/CreditNoteForm/components.js | 29 ++++++++
.../Sales/CreditNotes/CreditNoteForm/utils.js | 47 +++++++++++++
.../EstimateForm/EstimateFormFooterRight.js | 8 ++-
.../EstimateForm/EstimateFormHeaderFields.js | 37 +++++-----
.../Estimates/EstimateForm/components.js | 29 ++++++++
.../Sales/Estimates/EstimateForm/utils.js | 47 +++++++++++++
.../InvoiceForm/InvoiceFormHeaderFields.js | 1 -
.../PaymentReceiveFormFootetLeft.js | 9 ++-
.../PaymentReceiveFormFootetRight.js | 7 +-
.../PaymentReceiveHeaderFields.js | 39 +++++------
.../PaymentReceiveForm/components.js | 32 +++++++--
.../PaymentReceiveForm/utils.js | 47 +++++++++++++
.../ReceiptForm/ReceiptFormFooterRight.js | 16 +++--
.../ReceiptForm/ReceiptFormHeaderFields.js | 40 +++++------
.../Sales/Receipts/ReceiptForm/components.js | 29 ++++++++
.../Sales/Receipts/ReceiptForm/utils.js | 69 ++++++++++++++++++
23 files changed, 559 insertions(+), 130 deletions(-)
create mode 100644 src/containers/Purchases/Bills/BillForm/components.js
create mode 100644 src/containers/Sales/CreditNotes/CreditNoteForm/components.js
create mode 100644 src/containers/Sales/Estimates/EstimateForm/components.js
create mode 100644 src/containers/Sales/Receipts/ReceiptForm/components.js
diff --git a/src/components/Vendors/VendorDrawerLink.js b/src/components/Vendors/VendorDrawerLink.js
index 91b528e6f..9fdabf6df 100644
--- a/src/components/Vendors/VendorDrawerLink.js
+++ b/src/components/Vendors/VendorDrawerLink.js
@@ -13,8 +13,9 @@ function VendorDrawerLinkComponent({
openDrawer,
}) {
// Handle view customer drawer.
- const handleVendorDrawer = () => {
+ const handleVendorDrawer = (event) => {
openDrawer('vendor-details-drawer', { vendorId });
+ event.preventDefault();
};
return {children};
diff --git a/src/containers/Purchases/Bills/BillForm/BillFormFooterRight.js b/src/containers/Purchases/Bills/BillForm/BillFormFooterRight.js
index f5f5b385e..05ae8719f 100644
--- a/src/containers/Purchases/Bills/BillForm/BillFormFooterRight.js
+++ b/src/containers/Purchases/Bills/BillForm/BillFormFooterRight.js
@@ -8,29 +8,37 @@ import {
TotalLineBorderStyle,
TotalLineTextStyle,
} from 'components';
+import { useBillTotals } from './utils';
export function BillFormFooterRight() {
+ const {
+ formattedSubtotal,
+ formattedTotal,
+ formattedDueTotal,
+ formattedPaymentTotal,
+ } = useBillTotals();
+
return (
}
- value={'$5000.00'}
+ value={formattedSubtotal}
borderStyle={TotalLineBorderStyle.None}
/>
}
- value={'$5000.00'}
+ value={formattedTotal}
borderStyle={TotalLineBorderStyle.SingleDark}
textStyle={TotalLineTextStyle.Bold}
/>
}
- value={'$0.00'}
+ value={formattedPaymentTotal}
borderStyle={TotalLineBorderStyle.None}
/>
}
- value={'$5000.00'}
+ value={formattedDueTotal}
textStyle={TotalLineTextStyle.Bold}
/>
diff --git a/src/containers/Purchases/Bills/BillForm/BillFormHeaderFields.js b/src/containers/Purchases/Bills/BillForm/BillFormHeaderFields.js
index 8844d014a..335189720 100644
--- a/src/containers/Purchases/Bills/BillForm/BillFormHeaderFields.js
+++ b/src/containers/Purchases/Bills/BillForm/BillFormHeaderFields.js
@@ -16,13 +16,13 @@ import {
VendorSelectField,
FieldRequiredHint,
Icon,
- ExchangeRateInputGroup,
- If,
+ CustomerDrawerLink,
+ VendorDrawerLink,
} from 'components';
import { vendorsFieldShouldUpdate } from './utils';
import { useBillFormContext } from './BillFormProvider';
-import BillFormCurrencyTag from './BillFormCurrencyTag';
+import { BillExchangeRateInputField } from './components';
import withDialogActions from 'containers/Dialog/withDialogActions';
import {
momentFormatter,
@@ -37,13 +37,7 @@ import {
*/
function BillFormHeader() {
// Bill form context.
- const {
- vendors,
- isForeignVendor,
- baseCurrency,
- selectVendor,
- setSelectVendor,
- } = useBillFormContext();
+ const { vendors } = useBillFormContext();
return (
@@ -57,7 +51,11 @@ function BillFormHeader() {
}
inline={true}
- className={classNames(CLASSES.FILL, 'form-group--vendor')}
+ className={classNames(
+ 'form-group--customer-name',
+ 'form-group--select-list',
+ CLASSES.FILL,
+ )}
labelInfo={
}
intent={inputIntent({ error, touched })}
helperText={
}
@@ -70,26 +68,25 @@ function BillFormHeader() {
onContactSelected={(contact) => {
form.setFieldValue('vendor_id', contact.id);
form.setFieldValue('currency_code', contact?.currency_code);
- setSelectVendor(contact);
}}
popoverFill={true}
allowCreate={true}
/>
-
+ {value && (
+
+ View Vendor Details
+
+ )}
)}
{/* ----------- Exchange rate ----------- */}
-
-
-
+
{/* ------- Bill date ------- */}
@@ -184,3 +181,8 @@ const ControlVendorGroup = styled(ControlGroup)`
align-items: center;
transform: none;
`;
+
+const VendorButtonLink = styled(VendorDrawerLink)`
+ font-size: 11px;
+ margin-top: 6px;
+`;
diff --git a/src/containers/Purchases/Bills/BillForm/components.js b/src/containers/Purchases/Bills/BillForm/components.js
new file mode 100644
index 000000000..842a7e9f0
--- /dev/null
+++ b/src/containers/Purchases/Bills/BillForm/components.js
@@ -0,0 +1,28 @@
+import React from 'react';
+import { useFormikContext } from 'formik';
+import { ExchangeRateInputGroup } from 'components';
+import { useCurrentOrganization } from 'hooks/state';
+import { useBillIsForeignCustomer } from './utils';
+
+/**
+ * bill exchange rate input field.
+ * @returns {JSX.Element}
+ */
+export function BillExchangeRateInputField({ ...props }) {
+ const currentOrganization = useCurrentOrganization();
+ const { values } = useFormikContext();
+
+ const isForeignCustomer = useBillIsForeignCustomer();
+
+ // Can't continue if the customer is not foreign.
+ if (!isForeignCustomer) {
+ return null;
+ }
+ return (
+
+ );
+}
diff --git a/src/containers/Purchases/Bills/BillForm/utils.js b/src/containers/Purchases/Bills/BillForm/utils.js
index 33e856c01..a88ce2a05 100644
--- a/src/containers/Purchases/Bills/BillForm/utils.js
+++ b/src/containers/Purchases/Bills/BillForm/utils.js
@@ -11,12 +11,14 @@ import {
transformToForm,
repeatValue,
orderingLinesIndexes,
+ formattedAmount,
} from 'utils';
import {
updateItemsEntriesTotal,
ensureEntriesHaveEmptyLine,
} from 'containers/Entries/utils';
-import { isLandedCostDisabled } from '../../../Entries/utils';
+import { useCurrentOrganization } from 'hooks/state';
+import { isLandedCostDisabled, getEntriesTotal } from '../../../Entries/utils';
import { useBillFormContext } from './BillFormProvider';
export const MIN_LINES_NUMBER = 1;
@@ -216,3 +218,69 @@ export const useSetPrimaryWarehouseToForm = () => {
}
}, [isWarehousesSuccess, setFieldValue, warehouses]);
};
+
+/**
+ * Retreives the bill totals.
+ */
+export const useBillTotals = () => {
+ const {
+ values: { entries, currency_code: currencyCode },
+ } = useFormikContext();
+
+ // Retrieves the bili entries total.
+ const total = React.useMemo(() => getEntriesTotal(entries), [entries]);
+
+ // 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],
+ );
+ // Retrieves the payment total.
+ const paymentTotal = React.useMemo(() => 0, []);
+
+ // Retireves the formatted payment total.
+ const formattedPaymentTotal = React.useMemo(
+ () => formattedAmount(paymentTotal, currencyCode),
+ [paymentTotal, currencyCode],
+ );
+ // Retrieves the formatted due total.
+ const dueTotal = React.useMemo(
+ () => total - paymentTotal,
+ [total, paymentTotal],
+ );
+ // Retrieves the formatted due total.
+ const formattedDueTotal = React.useMemo(
+ () => formattedAmount(dueTotal, currencyCode),
+ [dueTotal, currencyCode],
+ );
+
+ return {
+ total,
+ paymentTotal,
+ dueTotal,
+ formattedTotal,
+ formattedSubtotal,
+ formattedPaymentTotal,
+ formattedDueTotal,
+ };
+};
+
+/**
+ * Detarmines whether the bill has foreign customer.
+ * @returns {boolean}
+ */
+export const useBillIsForeignCustomer = () => {
+ const { values } = useFormikContext();
+ const currentOrganization = useCurrentOrganization();
+
+ const isForeignCustomer = React.useMemo(
+ () => values.currency_code !== currentOrganization.base_currency,
+ [values.currency_code, currentOrganization.base_currency],
+ );
+ return isForeignCustomer;
+};
diff --git a/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFormFooterRight.js b/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFormFooterRight.js
index 16c702767..941350ba0 100644
--- a/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFormFooterRight.js
+++ b/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFormFooterRight.js
@@ -7,18 +7,21 @@ import {
TotalLineBorderStyle,
TotalLineTextStyle,
} from 'components';
+import { useCreditNoteTotals } from './utils';
export function CreditNoteFormFooterRight() {
+ const { formattedSubtotal, formattedTotal } = useCreditNoteTotals();
+
return (
}
- value={'$5000.00'}
+ value={formattedSubtotal}
borderStyle={TotalLineBorderStyle.None}
/>
}
- value={'$5000.00'}
+ value={formattedTotal}
// borderStyle={TotalLineBorderStyle.SingleDark}
textStyle={TotalLineTextStyle.Bold}
/>
diff --git a/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFormHeaderFields.js b/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFormHeaderFields.js
index ee8a9f086..f06fcce36 100644
--- a/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFormHeaderFields.js
+++ b/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFormHeaderFields.js
@@ -15,9 +15,8 @@ import {
FieldRequiredHint,
InputPrependButton,
Icon,
- If,
FormattedMessage as T,
- ExchangeRateInputGroup,
+ CustomerDrawerLink,
} from 'components';
import {
customerNameFieldShouldUpdate,
@@ -27,7 +26,7 @@ import {
import { useCreditNoteFormContext } from './CreditNoteFormProvider';
import withSettings from 'containers/Settings/withSettings';
import withDialogActions from 'containers/Dialog/withDialogActions';
-import CreditNotetFormCurrencyTag from './CreditNotetFormCurrencyTag';
+import { CreditNoteExchangeRateInputField } from './components';
import {
momentFormatter,
compose,
@@ -49,13 +48,7 @@ function CreditNoteFormHeaderFields({
creditNextNumber,
}) {
// Credit note form context.
- const {
- customers,
- isForeignCustomer,
- baseCurrency,
- selectCustomer,
- setSelectCustomer,
- } = useCreditNoteFormContext();
+ const { customers } = useCreditNoteFormContext();
// Handle credit number changing.
const handleCreditNumberChange = () => {
@@ -108,25 +101,25 @@ function CreditNoteFormHeaderFields({
onContactSelected={(customer) => {
form.setFieldValue('customer_id', customer.id);
form.setFieldValue('currency_code', customer?.currency_code);
- setSelectCustomer(customer);
}}
popoverFill={true}
allowCreate={true}
/>
+ {value && (
+
+ View Customer Details
+
+ )}
)}
{/* ----------- Exchange rate ----------- */}
-
-
-
+
{/* ----------- Credit note date ----------- */}
@@ -222,3 +215,7 @@ const ControlCustomerGroup = styled(ControlGroup)`
align-items: center;
transform: none;
`;
+const CustomerButtonLink = styled(CustomerDrawerLink)`
+ font-size: 11px;
+ margin-top: 6px;
+`;
diff --git a/src/containers/Sales/CreditNotes/CreditNoteForm/components.js b/src/containers/Sales/CreditNotes/CreditNoteForm/components.js
new file mode 100644
index 000000000..466d5a802
--- /dev/null
+++ b/src/containers/Sales/CreditNotes/CreditNoteForm/components.js
@@ -0,0 +1,29 @@
+import React from 'react';
+import { useFormikContext } from 'formik';
+import { ExchangeRateInputGroup } from 'components';
+import { useCurrentOrganization } from 'hooks/state';
+import { useCreditNoteIsForeignCustomer } from './utils';
+
+
+/**
+ * credit exchange rate input field.
+ * @returns {JSX.Element}
+ */
+ export function CreditNoteExchangeRateInputField({ ...props }) {
+ const currentOrganization = useCurrentOrganization();
+ const { values } = useFormikContext();
+
+ const isForeignCustomer = useCreditNoteIsForeignCustomer();
+
+ // Can't continue if the customer is not foreign.
+ if (!isForeignCustomer) {
+ return null;
+ }
+ return (
+
+ );
+}
\ No newline at end of file
diff --git a/src/containers/Sales/CreditNotes/CreditNoteForm/utils.js b/src/containers/Sales/CreditNotes/CreditNoteForm/utils.js
index d8a26fad0..96c2d7add 100644
--- a/src/containers/Sales/CreditNotes/CreditNoteForm/utils.js
+++ b/src/containers/Sales/CreditNotes/CreditNoteForm/utils.js
@@ -8,6 +8,7 @@ import {
transformToForm,
repeatValue,
transactionNumber,
+ formattedAmount,
orderingLinesIndexes,
} from 'utils';
import { useFormikContext } from 'formik';
@@ -17,6 +18,8 @@ import {
updateItemsEntriesTotal,
ensureEntriesHaveEmptyLine,
} from 'containers/Entries/utils';
+import { useCurrentOrganization } from 'hooks/state';
+import { getEntriesTotal } from 'containers/Entries/utils';
export const MIN_LINES_NUMBER = 1;
@@ -168,3 +171,47 @@ export const useSetPrimaryWarehouseToForm = () => {
}
}, [isWarehousesSuccess, setFieldValue, warehouses]);
};
+
+/**
+ * Retreives the credit note totals.
+ */
+export const useCreditNoteTotals = () => {
+ const {
+ values: { entries, currency_code: currencyCode },
+ } = useFormikContext();
+
+ // Retrieves the invoice entries total.
+ const total = React.useMemo(() => getEntriesTotal(entries), [entries]);
+
+ // 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 {
+ total,
+ formattedTotal,
+ formattedSubtotal,
+ };
+};
+
+/**
+ * Detarmines whether the receipt has foreign customer.
+ * @returns {boolean}
+ */
+export const useCreditNoteIsForeignCustomer = () => {
+ const { values } = useFormikContext();
+ const currentOrganization = useCurrentOrganization();
+
+ const isForeignCustomer = React.useMemo(
+ () => values.currency_code !== currentOrganization.base_currency,
+ [values.currency_code, currentOrganization.base_currency],
+ );
+ return isForeignCustomer;
+};
diff --git a/src/containers/Sales/Estimates/EstimateForm/EstimateFormFooterRight.js b/src/containers/Sales/Estimates/EstimateForm/EstimateFormFooterRight.js
index 38b76c3b8..107fb2b66 100644
--- a/src/containers/Sales/Estimates/EstimateForm/EstimateFormFooterRight.js
+++ b/src/containers/Sales/Estimates/EstimateForm/EstimateFormFooterRight.js
@@ -7,18 +7,22 @@ import {
TotalLineBorderStyle,
TotalLineTextStyle,
} from 'components';
+import { useEstimateTotals } from './utils';
export function EstimateFormFooterRight() {
+
+ const { formattedSubtotal, formattedTotal } = useEstimateTotals();
+
return (
}
- value={'$5000.00'}
+ value={formattedSubtotal}
borderStyle={TotalLineBorderStyle.None}
/>
}
- value={'$5000.00'}
+ value={formattedTotal}
// borderStyle={TotalLineBorderStyle.SingleDark}
textStyle={TotalLineTextStyle.Bold}
/>
diff --git a/src/containers/Sales/Estimates/EstimateForm/EstimateFormHeaderFields.js b/src/containers/Sales/Estimates/EstimateForm/EstimateFormHeaderFields.js
index 7a84fc318..34d4db271 100644
--- a/src/containers/Sales/Estimates/EstimateForm/EstimateFormHeaderFields.js
+++ b/src/containers/Sales/Estimates/EstimateForm/EstimateFormHeaderFields.js
@@ -23,16 +23,15 @@ import { CLASSES } from 'common/classes';
import {
CustomerSelectField,
FieldRequiredHint,
- If,
Icon,
InputPrependButton,
- ExchangeRateInputGroup,
+ CustomerDrawerLink,
} from 'components';
import withDialogActions from 'containers/Dialog/withDialogActions';
import withSettings from 'containers/Settings/withSettings';
-import EstimateFormCurrencyTag from './EstimateFormCurrencyTag';
import { useObserveEstimateNoSettings } from './utils';
+import { EstimateExchangeRateInputField } from './components';
import { useEstimateFormContext } from './EstimateFormProvider';
/**
@@ -47,13 +46,7 @@ function EstimateFormHeader({
estimateNumberPrefix,
estimateNextNumber,
}) {
- const {
- customers,
- isForeignCustomer,
- baseCurrency,
- selectCustomer,
- setSelectCustomer,
- } = useEstimateFormContext();
+ const { customers } = useEstimateFormContext();
const handleEstimateNumberBtnClick = () => {
openDialog('estimate-number-form', {});
@@ -100,27 +93,26 @@ function EstimateFormHeader({
onContactSelected={(customer) => {
form.setFieldValue('customer_id', customer.id);
form.setFieldValue('currency_code', customer?.currency_code);
- setSelectCustomer(customer);
}}
popoverFill={true}
intent={inputIntent({ error, touched })}
allowCreate={true}
/>
-
+ {value && (
+
+ View Customer Details
+
+ )}
)}
{/* ----------- Exchange rate ----------- */}
-
-
-
+
{/* ----------- Estimate date ----------- */}
@@ -246,3 +238,8 @@ const ControlCustomerGroup = styled(ControlGroup)`
align-items: center;
transform: none;
`;
+
+const CustomerButtonLink = styled(CustomerDrawerLink)`
+ font-size: 11px;
+ margin-top: 6px;
+`;
diff --git a/src/containers/Sales/Estimates/EstimateForm/components.js b/src/containers/Sales/Estimates/EstimateForm/components.js
new file mode 100644
index 000000000..8a4ada2f6
--- /dev/null
+++ b/src/containers/Sales/Estimates/EstimateForm/components.js
@@ -0,0 +1,29 @@
+import React from 'react';
+import { useFormikContext } from 'formik';
+import { ExchangeRateInputGroup } from 'components';
+import { useCurrentOrganization } from 'hooks/state';
+import { useEstimateIsForeignCustomer } from './utils';
+
+
+/**
+ * Estimate exchange rate input field.
+ * @returns {JSX.Element}
+ */
+ export function EstimateExchangeRateInputField({ ...props }) {
+ const currentOrganization = useCurrentOrganization();
+ const { values } = useFormikContext();
+
+ const isForeignCustomer = useEstimateIsForeignCustomer();
+
+ // Can't continue if the customer is not foreign.
+ if (!isForeignCustomer) {
+ return null;
+ }
+ return (
+
+ );
+}
diff --git a/src/containers/Sales/Estimates/EstimateForm/utils.js b/src/containers/Sales/Estimates/EstimateForm/utils.js
index 7de4acd68..0fb87d970 100644
--- a/src/containers/Sales/Estimates/EstimateForm/utils.js
+++ b/src/containers/Sales/Estimates/EstimateForm/utils.js
@@ -9,12 +9,15 @@ import {
transactionNumber,
repeatValue,
transformToForm,
+ formattedAmount,
} from 'utils';
import { useEstimateFormContext } from './EstimateFormProvider';
import {
updateItemsEntriesTotal,
ensureEntriesHaveEmptyLine,
} from 'containers/Entries/utils';
+import { useCurrentOrganization } from 'hooks/state';
+import { getEntriesTotal } from 'containers/Entries/utils';
export const MIN_LINES_NUMBER = 1;
@@ -187,3 +190,47 @@ export const useSetPrimaryBranchToForm = () => {
}
}, [isBranchesSuccess, setFieldValue, branches]);
};
+
+/**
+ * Retreives the estimate totals.
+ */
+export const useEstimateTotals = () => {
+ const {
+ values: { entries, currency_code: currencyCode },
+ } = useFormikContext();
+
+ // Retrieves the invoice entries total.
+ const total = React.useMemo(() => getEntriesTotal(entries), [entries]);
+
+ // 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 {
+ total,
+ formattedTotal,
+ formattedSubtotal,
+ };
+};
+
+/**
+ * Detarmines whether the estimate has foreign customer.
+ * @returns {boolean}
+ */
+export const useEstimateIsForeignCustomer = () => {
+ const { values } = useFormikContext();
+ const currentOrganization = useCurrentOrganization();
+
+ const isForeignCustomer = React.useMemo(
+ () => values.currency_code !== currentOrganization.base_currency,
+ [values.currency_code, currentOrganization.base_currency],
+ );
+ return isForeignCustomer;
+};
diff --git a/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormHeaderFields.js b/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormHeaderFields.js
index 0019fdce2..ca9c58d5e 100644
--- a/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormHeaderFields.js
+++ b/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormHeaderFields.js
@@ -104,7 +104,6 @@ function InvoiceFormHeaderFields({
popoverFill={true}
allowCreate={true}
/>
- {/* */}
{value && (
diff --git a/src/containers/Sales/PaymentReceives/PaymentReceiveForm/PaymentReceiveFormFootetLeft.js b/src/containers/Sales/PaymentReceives/PaymentReceiveForm/PaymentReceiveFormFootetLeft.js
index 470bcea50..795e628a3 100644
--- a/src/containers/Sales/PaymentReceives/PaymentReceiveForm/PaymentReceiveFormFootetLeft.js
+++ b/src/containers/Sales/PaymentReceives/PaymentReceiveForm/PaymentReceiveFormFootetLeft.js
@@ -6,7 +6,7 @@ export function PaymentReceiveFormFootetLeft() {
return (
{/* --------- Statement--------- */}
- }
hintText={'Will be displayed on the Payment'}
@@ -15,15 +15,13 @@ export function PaymentReceiveFormFootetLeft() {
name={'statement'}
placeholder={'Thanks for your business and have a great day!'}
/>
-
+
);
}
-const StatementFormGroup = styled(FFormGroup)`
+const TermsConditsFormGroup = styled(FFormGroup)`
&.bp3-form-group {
- margin-bottom: 40px;
-
.bp3-label {
font-size: 12px;
margin-bottom: 12px;
@@ -33,3 +31,4 @@ const StatementFormGroup = styled(FFormGroup)`
}
}
`;
+
diff --git a/src/containers/Sales/PaymentReceives/PaymentReceiveForm/PaymentReceiveFormFootetRight.js b/src/containers/Sales/PaymentReceives/PaymentReceiveForm/PaymentReceiveFormFootetRight.js
index d185510dd..3734dc753 100644
--- a/src/containers/Sales/PaymentReceives/PaymentReceiveForm/PaymentReceiveFormFootetRight.js
+++ b/src/containers/Sales/PaymentReceives/PaymentReceiveForm/PaymentReceiveFormFootetRight.js
@@ -7,18 +7,21 @@ import {
TotalLineBorderStyle,
TotalLineTextStyle,
} from 'components';
+import { usePaymentReceiveTotals } from './utils';
export function PaymentReceiveFormFootetRight() {
+ const { formattedSubtotal, formattedTotal } = usePaymentReceiveTotals();
+
return (
}
- value={'$5000.00'}
+ value={formattedSubtotal}
borderStyle={TotalLineBorderStyle.None}
/>
}
- value={'$5000.00'}
+ value={formattedTotal}
// borderStyle={TotalLineBorderStyle.SingleDark}
textStyle={TotalLineTextStyle.Bold}
/>
diff --git a/src/containers/Sales/PaymentReceives/PaymentReceiveForm/PaymentReceiveHeaderFields.js b/src/containers/Sales/PaymentReceives/PaymentReceiveForm/PaymentReceiveHeaderFields.js
index 50200edcd..bb7616c8a 100644
--- a/src/containers/Sales/PaymentReceives/PaymentReceiveForm/PaymentReceiveHeaderFields.js
+++ b/src/containers/Sales/PaymentReceives/PaymentReceiveForm/PaymentReceiveHeaderFields.js
@@ -30,13 +30,13 @@ import {
InputPrependButton,
MoneyInputGroup,
InputPrependText,
- ExchangeRateInputGroup,
+ CustomerDrawerLink,
Hint,
Money,
} from 'components';
import { usePaymentReceiveFormContext } from './PaymentReceiveFormProvider';
import { ACCOUNT_TYPE } from 'common/accountTypes';
-import PaymentReceiveFormCurrencyTag from './PaymentReceiveFormCurrencyTag';
+import { PaymentReceiveExchangeRateInputField } from './components';
import withDialogActions from 'containers/Dialog/withDialogActions';
import withSettings from 'containers/Settings/withSettings';
@@ -49,6 +49,7 @@ import {
customersFieldShouldUpdate,
accountsFieldShouldUpdate,
} from './utils';
+
import { toSafeInteger } from 'lodash';
/**
@@ -67,15 +68,7 @@ function PaymentReceiveHeaderFields({
paymentReceiveNextNumber,
}) {
// Payment receive form context.
- const {
- customers,
- accounts,
- isNewMode,
- isForeignCustomer,
- baseCurrency,
- selectCustomer,
- setSelectCustomer,
- } = usePaymentReceiveFormContext();
+ const { customers, accounts, isNewMode } = usePaymentReceiveFormContext();
// Formik form context.
const {
@@ -154,7 +147,6 @@ function PaymentReceiveHeaderFields({
form.setFieldValue('customer_id', customer.id);
form.setFieldValue('full_amount', '');
form.setFieldValue('currency_code', customer?.currency_code);
- setSelectCustomer(customer);
}}
popoverFill={true}
disabled={!isNewMode}
@@ -164,20 +156,20 @@ function PaymentReceiveHeaderFields({
allowCreate={true}
/>
+ {value && (
+
+ View Customer Details
+
+ )}
)}
{/* ----------- Exchange rate ----------- */}
-
-
-
-
+
{/* ------------- Payment date ------------- */}
{({ form, field: { value }, meta: { error, touched } }) => (
@@ -359,3 +351,8 @@ const ControlCustomerGroup = styled(ControlGroup)`
align-items: center;
transform: none;
`;
+
+const CustomerButtonLink = styled(CustomerDrawerLink)`
+ font-size: 11px;
+ margin-top: 6px;
+`;
diff --git a/src/containers/Sales/PaymentReceives/PaymentReceiveForm/components.js b/src/containers/Sales/PaymentReceives/PaymentReceiveForm/components.js
index 8941d6467..4f17607e6 100644
--- a/src/containers/Sales/PaymentReceives/PaymentReceiveForm/components.js
+++ b/src/containers/Sales/PaymentReceives/PaymentReceiveForm/components.js
@@ -2,9 +2,12 @@ import React from 'react';
import moment from 'moment';
import intl from 'react-intl-universal';
-import { Money } from 'components';
+import { Money, ExchangeRateInputGroup } from 'components';
import { MoneyFieldCell } from 'components/DataTableCells';
import { safeSumBy, formattedAmount } from 'utils';
+import { useFormikContext } from 'formik';
+import { useCurrentOrganization } from 'hooks/state';
+import { useEstimateIsForeignCustomer } from './utils';
/**
* Invoice date cell.
@@ -59,15 +62,13 @@ function MoneyTableCell({ row: { original }, value }) {
}
function DateFooterCell() {
- return intl.get('total')
+ return intl.get('total');
}
/**
* Retrieve payment receive form entries columns.
*/
export const usePaymentReceiveEntriesColumns = () => {
-
-
return React.useMemo(
() => [
{
@@ -127,3 +128,26 @@ export const usePaymentReceiveEntriesColumns = () => {
[],
);
};
+
+/**
+ * payment receive exchange rate input field.
+ * @returns {JSX.Element}
+ */
+export function PaymentReceiveExchangeRateInputField({ ...props }) {
+ const currentOrganization = useCurrentOrganization();
+ const { values } = useFormikContext();
+
+ const isForeignCustomer = useEstimateIsForeignCustomer();
+
+ // Can't continue if the customer is not foreign.
+ if (!isForeignCustomer) {
+ return null;
+ }
+ return (
+
+ );
+}
diff --git a/src/containers/Sales/PaymentReceives/PaymentReceiveForm/utils.js b/src/containers/Sales/PaymentReceives/PaymentReceiveForm/utils.js
index ada3570e8..e21d6cc12 100644
--- a/src/containers/Sales/PaymentReceives/PaymentReceiveForm/utils.js
+++ b/src/containers/Sales/PaymentReceives/PaymentReceiveForm/utils.js
@@ -12,7 +12,10 @@ import {
transformToForm,
safeSumBy,
orderingLinesIndexes,
+ formattedAmount,
} from 'utils';
+import { useCurrentOrganization } from 'hooks/state';
+import { getEntriesTotal } from 'containers/Entries/utils';
// Default payment receive entry.
export const defaultPaymentReceiveEntry = {
@@ -213,3 +216,47 @@ export const transformErrors = (errors, { setFieldError }) => {
});
}
};
+
+/**
+ * Retreives the payment receive totals.
+ */
+export const usePaymentReceiveTotals = () => {
+ const {
+ values: { entries, currency_code: currencyCode },
+ } = useFormikContext();
+
+ // Retrieves the invoice entries total.
+ const total = React.useMemo(() => getEntriesTotal(entries), [entries]);
+
+ // 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 {
+ total,
+ formattedTotal,
+ formattedSubtotal,
+ };
+};
+
+/**
+ * Detarmines whether the payment has foreign customer.
+ * @returns {boolean}
+ */
+export const useEstimateIsForeignCustomer = () => {
+ const { values } = useFormikContext();
+ const currentOrganization = useCurrentOrganization();
+
+ const isForeignCustomer = React.useMemo(
+ () => values.currency_code !== currentOrganization.base_currency,
+ [values.currency_code, currentOrganization.base_currency],
+ );
+ return isForeignCustomer;
+};
diff --git a/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormFooterRight.js b/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormFooterRight.js
index a297162ae..ab050893f 100644
--- a/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormFooterRight.js
+++ b/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormFooterRight.js
@@ -8,29 +8,37 @@ import {
TotalLineBorderStyle,
TotalLineTextStyle,
} from 'components';
+import { useReceiptTotals } from './utils';
export function ReceiptFormFooterRight() {
+ const {
+ formattedSubtotal,
+ formattedTotal,
+ formattedDueTotal,
+ formattedPaymentTotal,
+ } = useReceiptTotals();
+
return (
}
- value={'$5000.00'}
+ value={formattedSubtotal}
borderStyle={TotalLineBorderStyle.None}
/>
}
- value={'$5000.00'}
+ value={formattedTotal}
borderStyle={TotalLineBorderStyle.SingleDark}
textStyle={TotalLineTextStyle.Bold}
/>
}
- value={'$0.00'}
+ value={formattedPaymentTotal}
borderStyle={TotalLineBorderStyle.None}
/>
}
- value={'$5000.00'}
+ value={formattedDueTotal}
textStyle={TotalLineTextStyle.Bold}
/>
diff --git a/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormHeaderFields.js b/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormHeaderFields.js
index 3bf129059..03f812dd1 100644
--- a/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormHeaderFields.js
+++ b/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormHeaderFields.js
@@ -19,7 +19,7 @@ import {
Icon,
If,
InputPrependButton,
- ExchangeRateInputGroup,
+ CustomerDrawerLink,
} from 'components';
import withSettings from 'containers/Settings/withSettings';
import withDialogActions from 'containers/Dialog/withDialogActions';
@@ -31,13 +31,13 @@ import {
handleDateChange,
inputIntent,
} from 'utils';
-import ReceiptFormCurrencyTag from './ReceiptFormCurrencyTag';
import { useReceiptFormContext } from './ReceiptFormProvider';
import {
accountsFieldShouldUpdate,
customersFieldShouldUpdate,
useObserveReceiptNoSettings,
} from './utils';
+import { ReceiptExchangeRateInputField } from './components';
/**
* Receipt form header fields.
@@ -46,22 +46,12 @@ function ReceiptFormHeader({
//#withDialogActions
openDialog,
- // #ownProps
- onReceiptNumberChanged,
-
// #withSettings
receiptAutoIncrement,
receiptNextNumber,
receiptNumberPrefix,
}) {
- const {
- accounts,
- customers,
- isForeignCustomer,
- baseCurrency,
- selectCustomer,
- setSelectCustomer,
- } = useReceiptFormContext();
+ const { accounts, customers } = useReceiptFormContext();
const handleReceiptNumberChange = useCallback(() => {
openDialog('receipt-number-form', {});
@@ -108,26 +98,25 @@ function ReceiptFormHeader({
onContactSelected={(customer) => {
form.setFieldValue('customer_id', customer.id);
form.setFieldValue('currency_code', customer?.currency_code);
- setSelectCustomer(customer);
}}
popoverFill={true}
allowCreate={true}
/>
-
+ {value && (
+
+ View Customer Details
+
+ )}
)}
{/* ----------- Exchange rate ----------- */}
-
-
-
+
{/* ----------- Deposit account ----------- */}
+ );
+}
\ No newline at end of file
diff --git a/src/containers/Sales/Receipts/ReceiptForm/utils.js b/src/containers/Sales/Receipts/ReceiptForm/utils.js
index 64378259c..cc69f4244 100644
--- a/src/containers/Sales/Receipts/ReceiptForm/utils.js
+++ b/src/containers/Sales/Receipts/ReceiptForm/utils.js
@@ -9,12 +9,15 @@ import {
transactionNumber,
repeatValue,
transformToForm,
+ formattedAmount,
} from 'utils';
import { useReceiptFormContext } from './ReceiptFormProvider';
import {
updateItemsEntriesTotal,
ensureEntriesHaveEmptyLine,
} from 'containers/Entries/utils';
+import { useCurrentOrganization } from 'hooks/state';
+import { getEntriesTotal } from 'containers/Entries/utils';
export const MIN_LINES_NUMBER = 1;
@@ -178,3 +181,69 @@ export const useSetPrimaryBranchToForm = () => {
}
}, [isBranchesSuccess, setFieldValue, branches]);
};
+
+/**
+ * Retreives the Receipt totals.
+ */
+export const useReceiptTotals = () => {
+ const {
+ values: { entries, currency_code: currencyCode },
+ } = useFormikContext();
+
+ // Retrieves the invoice entries total.
+ const total = React.useMemo(() => getEntriesTotal(entries), [entries]);
+
+ // 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],
+ );
+ // Retrieves the payment total.
+ const paymentTotal = React.useMemo(() => 0, []);
+
+ // Retireves the formatted payment total.
+ const formattedPaymentTotal = React.useMemo(
+ () => formattedAmount(paymentTotal, currencyCode),
+ [paymentTotal, currencyCode],
+ );
+ // Retrieves the formatted due total.
+ const dueTotal = React.useMemo(
+ () => total - paymentTotal,
+ [total, paymentTotal],
+ );
+ // Retrieves the formatted due total.
+ const formattedDueTotal = React.useMemo(
+ () => formattedAmount(dueTotal, currencyCode),
+ [dueTotal, currencyCode],
+ );
+
+ return {
+ total,
+ paymentTotal,
+ dueTotal,
+ formattedTotal,
+ formattedSubtotal,
+ formattedPaymentTotal,
+ formattedDueTotal,
+ };
+};
+
+/**
+ * Detarmines whether the receipt has foreign customer.
+ * @returns {boolean}
+ */
+export const useReceiptIsForeignCustomer = () => {
+ const { values } = useFormikContext();
+ const currentOrganization = useCurrentOrganization();
+
+ const isForeignCustomer = React.useMemo(
+ () => values.currency_code !== currentOrganization.base_currency,
+ [values.currency_code, currentOrganization.base_currency],
+ );
+ return isForeignCustomer;
+};