mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-19 22:30:31 +00:00
feat(Sales & Purchases ): add exchange rate input.
This commit is contained in:
@@ -14,7 +14,9 @@ import {
|
||||
FieldRequiredHint,
|
||||
InputPrependButton,
|
||||
Icon,
|
||||
If,
|
||||
FormattedMessage as T,
|
||||
ExchangeRateInputGroup,
|
||||
} from 'components';
|
||||
import {
|
||||
customerNameFieldShouldUpdate,
|
||||
@@ -46,7 +48,8 @@ function CreditNoteFormHeaderFields({
|
||||
creditNextNumber,
|
||||
}) {
|
||||
// Credit note form context.
|
||||
const { customers } = useCreditNoteFormContext();
|
||||
const { customers, isForeignCustomer, baseCurrency, setSelectCustomer } =
|
||||
useCreditNoteFormContext();
|
||||
|
||||
// Handle credit number changing.
|
||||
const handleCreditNumberChange = () => {
|
||||
@@ -97,6 +100,7 @@ function CreditNoteFormHeaderFields({
|
||||
defaultSelectText={<T id={'select_customer_account'} />}
|
||||
onContactSelected={(customer) => {
|
||||
form.setFieldValue('customer_id', customer.id);
|
||||
setSelectCustomer(customer);
|
||||
}}
|
||||
popoverFill={true}
|
||||
allowCreate={true}
|
||||
@@ -104,6 +108,17 @@ function CreditNoteFormHeaderFields({
|
||||
</FormGroup>
|
||||
)}
|
||||
</FastField>
|
||||
|
||||
{/* ----------- Exchange rate ----------- */}
|
||||
<If condition={isForeignCustomer}>
|
||||
<ExchangeRateInputGroup
|
||||
fromCurrency={'USD'}
|
||||
toCurrency={'LYD'}
|
||||
name={'exchange_rate'}
|
||||
formGroupProps={{ label: ' ', inline: true }}
|
||||
/>
|
||||
</If>
|
||||
|
||||
{/* ----------- Credit note date ----------- */}
|
||||
<FastField name={'credit_note_date'}>
|
||||
{({ form, field: { value }, meta: { error, touched } }) => (
|
||||
|
||||
@@ -5,17 +5,27 @@ import '../../../../style/pages/CreditNote/PageForm.scss';
|
||||
|
||||
import CreditNoteForm from './CreditNoteForm';
|
||||
import { CreditNoteFormProvider } from './CreditNoteFormProvider';
|
||||
import withCurrentOrganization from 'containers/Organization/withCurrentOrganization';
|
||||
import { compose } from 'utils';
|
||||
|
||||
/**
|
||||
* Credit note form page.
|
||||
*/
|
||||
export default function CreditNoteFormPage() {
|
||||
function CreditNoteFormPage({
|
||||
// #withCurrentOrganization
|
||||
organization: { base_currency },
|
||||
}) {
|
||||
const { id } = useParams();
|
||||
const idAsInteger = parseInt(id, 10);
|
||||
|
||||
return (
|
||||
<CreditNoteFormProvider creditNoteId={idAsInteger}>
|
||||
<CreditNoteFormProvider
|
||||
creditNoteId={idAsInteger}
|
||||
baseCurrency={base_currency}
|
||||
>
|
||||
<CreditNoteForm />
|
||||
</CreditNoteFormProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(withCurrentOrganization())(CreditNoteFormPage);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { isEmpty, pick } from 'lodash';
|
||||
import { isEmpty, pick, isEqual, isUndefined } from 'lodash';
|
||||
import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
||||
import { transformToEditForm } from './utils';
|
||||
|
||||
@@ -21,7 +21,7 @@ const CreditNoteFormContext = React.createContext();
|
||||
/**
|
||||
* Credit note data provider.
|
||||
*/
|
||||
function CreditNoteFormProvider({ creditNoteId, ...props }) {
|
||||
function CreditNoteFormProvider({ creditNoteId, baseCurrency, ...props }) {
|
||||
const { state } = useLocation();
|
||||
const invoiceId = state?.invoiceId;
|
||||
|
||||
@@ -75,6 +75,8 @@ function CreditNoteFormProvider({ creditNoteId, ...props }) {
|
||||
// Form submit payload.
|
||||
const [submitPayload, setSubmitPayload] = React.useState();
|
||||
|
||||
const [selectCustomer, setSelectCustomer] = React.useState(null);
|
||||
|
||||
// Determines whether the form in new mode.
|
||||
const isNewMode = !creditNoteId;
|
||||
|
||||
@@ -87,6 +89,11 @@ function CreditNoteFormProvider({ creditNoteId, ...props }) {
|
||||
})
|
||||
: [];
|
||||
|
||||
// Determines whether the foreign customer.
|
||||
const isForeignCustomer =
|
||||
!isEqual(selectCustomer?.currency_code, baseCurrency) &&
|
||||
!isUndefined(selectCustomer?.currency_code);
|
||||
|
||||
// Provider payload.
|
||||
const provider = {
|
||||
items,
|
||||
@@ -95,15 +102,19 @@ function CreditNoteFormProvider({ creditNoteId, ...props }) {
|
||||
branches,
|
||||
warehouses,
|
||||
submitPayload,
|
||||
baseCurrency,
|
||||
selectCustomer,
|
||||
setSelectCustomer,
|
||||
isNewMode,
|
||||
newCreditNote,
|
||||
isForeignCustomer,
|
||||
|
||||
isItemsLoading,
|
||||
isCustomersLoading,
|
||||
isFeatureLoading,
|
||||
isBranchesSuccess,
|
||||
isWarehousesSuccess,
|
||||
|
||||
|
||||
createCreditNoteMutate,
|
||||
editCreditNoteMutate,
|
||||
setSubmitPayload,
|
||||
|
||||
@@ -21,8 +21,10 @@ import { CLASSES } from 'common/classes';
|
||||
import {
|
||||
CustomerSelectField,
|
||||
FieldRequiredHint,
|
||||
If,
|
||||
Icon,
|
||||
InputPrependButton,
|
||||
ExchangeRateInputGroup,
|
||||
} from 'components';
|
||||
|
||||
import withDialogActions from 'containers/Dialog/withDialogActions';
|
||||
@@ -43,7 +45,8 @@ function EstimateFormHeader({
|
||||
estimateNumberPrefix,
|
||||
estimateNextNumber,
|
||||
}) {
|
||||
const { customers } = useEstimateFormContext();
|
||||
const { customers, isForeignCustomer, baseCurrency, setSelectCustomer } =
|
||||
useEstimateFormContext();
|
||||
|
||||
const handleEstimateNumberBtnClick = () => {
|
||||
openDialog('estimate-number-form', {});
|
||||
@@ -88,6 +91,7 @@ function EstimateFormHeader({
|
||||
defaultSelectText={<T id={'select_customer_account'} />}
|
||||
onContactSelected={(customer) => {
|
||||
form.setFieldValue('customer_id', customer.id);
|
||||
setSelectCustomer(customer);
|
||||
}}
|
||||
popoverFill={true}
|
||||
intent={inputIntent({ error, touched })}
|
||||
@@ -97,6 +101,16 @@ function EstimateFormHeader({
|
||||
)}
|
||||
</FastField>
|
||||
|
||||
{/* ----------- Exchange rate ----------- */}
|
||||
<If condition={isForeignCustomer}>
|
||||
<ExchangeRateInputGroup
|
||||
fromCurrency={'USD'}
|
||||
toCurrency={'LYD'}
|
||||
name={'exchange_rate'}
|
||||
formGroupProps={{ label: ' ', inline: true }}
|
||||
/>
|
||||
</If>
|
||||
|
||||
{/* ----------- Estimate date ----------- */}
|
||||
<FastField name={'estimate_date'}>
|
||||
{({ form, field: { value }, meta: { error, touched } }) => (
|
||||
|
||||
@@ -1,21 +1,27 @@
|
||||
import React from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
|
||||
import 'style/pages/SaleEstimate/PageForm.scss';
|
||||
|
||||
import EstimateForm from './EstimateForm';
|
||||
import { EstimateFormProvider } from './EstimateFormProvider';
|
||||
import withCurrentOrganization from 'containers/Organization/withCurrentOrganization';
|
||||
import { compose } from 'utils';
|
||||
|
||||
/**
|
||||
* Estimate form page.
|
||||
*/
|
||||
export default function EstimateFormPage() {
|
||||
function EstimateFormPage({
|
||||
// #withCurrentOrganization
|
||||
organization: { base_currency },
|
||||
}) {
|
||||
const { id } = useParams();
|
||||
const idInteger = parseInt(id, 10);
|
||||
|
||||
return (
|
||||
<EstimateFormProvider estimateId={idInteger}>
|
||||
<EstimateFormProvider estimateId={idInteger} baseCurrency={base_currency}>
|
||||
<EstimateForm />
|
||||
</EstimateFormProvider>
|
||||
);
|
||||
}
|
||||
}
|
||||
export default compose(withCurrentOrganization())(EstimateFormPage);
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import React, { createContext, useContext } from 'react';
|
||||
import { isEqual, isUndefined } from 'lodash';
|
||||
|
||||
import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
||||
import {
|
||||
useEstimate,
|
||||
@@ -17,7 +19,7 @@ const EstimateFormContext = createContext();
|
||||
/**
|
||||
* Estimate form provider.
|
||||
*/
|
||||
function EstimateFormProvider({ estimateId, ...props }) {
|
||||
function EstimateFormProvider({ estimateId, baseCurrency, ...props }) {
|
||||
const {
|
||||
data: estimate,
|
||||
isFetching: isEstimateFetching,
|
||||
@@ -60,6 +62,7 @@ function EstimateFormProvider({ estimateId, ...props }) {
|
||||
|
||||
// Form submit payload.
|
||||
const [submitPayload, setSubmitPayload] = React.useState({});
|
||||
const [selectCustomer, setSelectCustomer] = React.useState(null);
|
||||
|
||||
// Create and edit estimate form.
|
||||
const { mutateAsync: createEstimateMutate } = useCreateEstimate();
|
||||
@@ -70,6 +73,11 @@ function EstimateFormProvider({ estimateId, ...props }) {
|
||||
// Determines whether the warehouse and branches are loading.
|
||||
const isFeatureLoading = isWarehouesLoading || isBranchesLoading;
|
||||
|
||||
// Determines whether the foreign customer.
|
||||
const isForeignCustomer =
|
||||
!isEqual(selectCustomer?.currency_code, baseCurrency) &&
|
||||
!isUndefined(selectCustomer?.currency_code);
|
||||
|
||||
// Provider payload.
|
||||
const provider = {
|
||||
estimateId,
|
||||
@@ -89,9 +97,13 @@ function EstimateFormProvider({ estimateId, ...props }) {
|
||||
isFeatureLoading,
|
||||
isBranchesSuccess,
|
||||
isWarehousesSuccess,
|
||||
isForeignCustomer,
|
||||
submitPayload,
|
||||
setSubmitPayload,
|
||||
|
||||
selectCustomer,
|
||||
setSelectCustomer,
|
||||
baseCurrency,
|
||||
|
||||
createEstimateMutate,
|
||||
editEstimateMutate,
|
||||
};
|
||||
|
||||
@@ -3,17 +3,25 @@ import { useParams } from 'react-router-dom';
|
||||
|
||||
import { PaymentReceiveFormProvider } from './PaymentReceiveFormProvider';
|
||||
import PaymentReceiveForm from './PaymentReceiveForm';
|
||||
|
||||
import withCurrentOrganization from 'containers/Organization/withCurrentOrganization';
|
||||
import { compose } from 'utils';
|
||||
/**
|
||||
* Payment receive form page.
|
||||
*/
|
||||
export default function PaymentReceiveFormPage() {
|
||||
function PaymentReceiveFormPage({
|
||||
// #withCurrentOrganization
|
||||
organization: { base_currency },
|
||||
}) {
|
||||
const { id: paymentReceiveId } = useParams();
|
||||
const paymentReceiveIdInt = parseInt(paymentReceiveId, 10);
|
||||
|
||||
return (
|
||||
<PaymentReceiveFormProvider paymentReceiveId={paymentReceiveIdInt}>
|
||||
<PaymentReceiveFormProvider
|
||||
paymentReceiveId={paymentReceiveIdInt}
|
||||
baseCurrency={base_currency}
|
||||
>
|
||||
<PaymentReceiveForm paymentReceiveId={paymentReceiveIdInt} />
|
||||
</PaymentReceiveFormProvider>
|
||||
);
|
||||
}
|
||||
export default compose(withCurrentOrganization())(PaymentReceiveFormPage);
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import React, { createContext, useContext } from 'react';
|
||||
import { isEmpty, pick, isEqual, isUndefined } from 'lodash';
|
||||
|
||||
import { DashboardInsider } from 'components';
|
||||
import {
|
||||
useSettingsPaymentReceives,
|
||||
@@ -16,10 +18,16 @@ const PaymentReceiveFormContext = createContext();
|
||||
/**
|
||||
* Payment receive form provider.
|
||||
*/
|
||||
function PaymentReceiveFormProvider({ paymentReceiveId, ...props }) {
|
||||
function PaymentReceiveFormProvider({
|
||||
paymentReceiveId,
|
||||
baseCurrency,
|
||||
...props
|
||||
}) {
|
||||
// Form state.
|
||||
const [submitPayload, setSubmitPayload] = React.useState({});
|
||||
|
||||
const [selectCustomer, setSelectCustomer] = React.useState(null);
|
||||
|
||||
// Fetches payment recevie details.
|
||||
const {
|
||||
data: {
|
||||
@@ -59,6 +67,11 @@ function PaymentReceiveFormProvider({ paymentReceiveId, ...props }) {
|
||||
const { mutateAsync: editPaymentReceiveMutate } = useEditPaymentReceive();
|
||||
const { mutateAsync: createPaymentReceiveMutate } = useCreatePaymentReceive();
|
||||
|
||||
// Determines whether the foreign customer.
|
||||
const isForeignCustomer =
|
||||
!isEqual(selectCustomer?.currency_code, baseCurrency) &&
|
||||
!isUndefined(selectCustomer?.currency_code);
|
||||
|
||||
// Provider payload.
|
||||
const provider = {
|
||||
paymentReceiveId,
|
||||
@@ -67,6 +80,7 @@ function PaymentReceiveFormProvider({ paymentReceiveId, ...props }) {
|
||||
accounts,
|
||||
customers,
|
||||
branches,
|
||||
baseCurrency,
|
||||
|
||||
isPaymentLoading,
|
||||
isAccountsLoading,
|
||||
@@ -74,10 +88,13 @@ function PaymentReceiveFormProvider({ paymentReceiveId, ...props }) {
|
||||
isCustomersLoading,
|
||||
isFeatureLoading,
|
||||
isBranchesSuccess,
|
||||
isForeignCustomer,
|
||||
isNewMode,
|
||||
|
||||
submitPayload,
|
||||
setSubmitPayload,
|
||||
selectCustomer,
|
||||
setSelectCustomer,
|
||||
|
||||
editPaymentReceiveMutate,
|
||||
createPaymentReceiveMutate,
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
Button,
|
||||
} from '@blueprintjs/core';
|
||||
import { DateInput } from '@blueprintjs/datetime';
|
||||
import { FormattedMessage as T } from 'components';
|
||||
import { FormattedMessage as T, If } from 'components';
|
||||
import { FastField, Field, useFormikContext, ErrorMessage } from 'formik';
|
||||
|
||||
import { useAutofocus } from 'hooks';
|
||||
@@ -29,6 +29,7 @@ import {
|
||||
InputPrependButton,
|
||||
MoneyInputGroup,
|
||||
InputPrependText,
|
||||
ExchangeRateInputGroup,
|
||||
Hint,
|
||||
Money,
|
||||
} from 'components';
|
||||
@@ -64,7 +65,14 @@ function PaymentReceiveHeaderFields({
|
||||
paymentReceiveNextNumber,
|
||||
}) {
|
||||
// Payment receive form context.
|
||||
const { customers, accounts, isNewMode } = usePaymentReceiveFormContext();
|
||||
const {
|
||||
customers,
|
||||
accounts,
|
||||
isNewMode,
|
||||
isForeignCustomer,
|
||||
baseCurrency,
|
||||
setSelectCustomer,
|
||||
} = usePaymentReceiveFormContext();
|
||||
|
||||
// Formik form context.
|
||||
const {
|
||||
@@ -141,6 +149,7 @@ function PaymentReceiveHeaderFields({
|
||||
onContactSelected={(customer) => {
|
||||
form.setFieldValue('customer_id', customer.id);
|
||||
form.setFieldValue('full_amount', '');
|
||||
setSelectCustomer(customer);
|
||||
}}
|
||||
popoverFill={true}
|
||||
disabled={!isNewMode}
|
||||
@@ -153,6 +162,16 @@ function PaymentReceiveHeaderFields({
|
||||
)}
|
||||
</FastField>
|
||||
|
||||
{/* ----------- Exchange rate ----------- */}
|
||||
<If condition={isForeignCustomer}>
|
||||
<ExchangeRateInputGroup
|
||||
fromCurrency={'USD'}
|
||||
toCurrency={'LYD'}
|
||||
name={'exchange_rate'}
|
||||
formGroupProps={{ label: ' ', inline: true }}
|
||||
/>
|
||||
</If>
|
||||
|
||||
{/* ------------- Payment date ------------- */}
|
||||
<FastField name={'payment_date'}>
|
||||
{({ form, field: { value }, meta: { error, touched } }) => (
|
||||
|
||||
@@ -15,7 +15,9 @@ import {
|
||||
CustomerSelectField,
|
||||
FieldRequiredHint,
|
||||
Icon,
|
||||
If,
|
||||
InputPrependButton,
|
||||
ExchangeRateInputGroup,
|
||||
} from 'components';
|
||||
import withSettings from 'containers/Settings/withSettings';
|
||||
import withDialogActions from 'containers/Dialog/withDialogActions';
|
||||
@@ -49,7 +51,8 @@ function ReceiptFormHeader({
|
||||
receiptNextNumber,
|
||||
receiptNumberPrefix,
|
||||
}) {
|
||||
const { accounts, customers } = useReceiptFormContext();
|
||||
const { accounts, customers, isForeignCustomer, setSelectCustomer } =
|
||||
useReceiptFormContext();
|
||||
|
||||
const handleReceiptNumberChange = useCallback(() => {
|
||||
openDialog('receipt-number-form', {});
|
||||
@@ -92,8 +95,9 @@ function ReceiptFormHeader({
|
||||
contacts={customers}
|
||||
selectedContactId={value}
|
||||
defaultSelectText={<T id={'select_customer_account'} />}
|
||||
onContactSelected={(contact) => {
|
||||
form.setFieldValue('customer_id', contact.id);
|
||||
onContactSelected={(customer) => {
|
||||
form.setFieldValue('customer_id', customer.id);
|
||||
setSelectCustomer(customer);
|
||||
}}
|
||||
popoverFill={true}
|
||||
allowCreate={true}
|
||||
@@ -102,6 +106,16 @@ function ReceiptFormHeader({
|
||||
)}
|
||||
</FastField>
|
||||
|
||||
{/* ----------- Exchange rate ----------- */}
|
||||
<If condition={isForeignCustomer}>
|
||||
<ExchangeRateInputGroup
|
||||
fromCurrency={'USD'}
|
||||
toCurrency={'LYD'}
|
||||
name={'exchange_rate'}
|
||||
formGroupProps={{ label: ' ', inline: true }}
|
||||
/>
|
||||
</If>
|
||||
|
||||
{/* ----------- Deposit account ----------- */}
|
||||
<FastField
|
||||
name={'deposit_account_id'}
|
||||
|
||||
@@ -4,18 +4,25 @@ import { useParams } from 'react-router-dom';
|
||||
import 'style/pages/SaleReceipt/PageForm.scss';
|
||||
|
||||
import ReceiptFrom from './ReceiptForm';
|
||||
import withCurrentOrganization from 'containers/Organization/withCurrentOrganization';
|
||||
import { ReceiptFormProvider } from './ReceiptFormProvider';
|
||||
|
||||
import { compose } from 'utils';
|
||||
|
||||
/**
|
||||
* Receipt form page.
|
||||
*/
|
||||
export default function ReceiptFormPage() {
|
||||
function ReceiptFormPage({
|
||||
// #withCurrentOrganization
|
||||
organization: { base_currency },
|
||||
}) {
|
||||
const { id } = useParams();
|
||||
const idInt = parseInt(id, 10);
|
||||
|
||||
return (
|
||||
<ReceiptFormProvider receiptId={idInt}>
|
||||
<ReceiptFormProvider receiptId={idInt} baseCurrency={base_currency}>
|
||||
<ReceiptFrom />
|
||||
</ReceiptFormProvider>
|
||||
);
|
||||
}
|
||||
export default compose(withCurrentOrganization())(ReceiptFormPage);
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import React, { createContext, useState } from 'react';
|
||||
import { isEmpty, pick, isEqual, isUndefined } from 'lodash';
|
||||
|
||||
import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
||||
import {
|
||||
useReceipt,
|
||||
@@ -17,7 +19,7 @@ const ReceiptFormContext = createContext();
|
||||
/**
|
||||
* Receipt form provider.
|
||||
*/
|
||||
function ReceiptFormProvider({ receiptId, ...props }) {
|
||||
function ReceiptFormProvider({ receiptId, baseCurrency, ...props }) {
|
||||
// Fetch sale receipt details.
|
||||
const { data: receipt, isLoading: isReceiptLoading } = useReceipt(receiptId, {
|
||||
enabled: !!receiptId,
|
||||
@@ -84,10 +86,17 @@ function ReceiptFormProvider({ receiptId, ...props }) {
|
||||
|
||||
const [submitPayload, setSubmitPayload] = useState({});
|
||||
|
||||
const [selectCustomer, setSelectCustomer] = React.useState(null);
|
||||
|
||||
const isNewMode = !receiptId;
|
||||
|
||||
const isFeatureLoading = isWarehouesLoading || isBranchesLoading;
|
||||
|
||||
// Determines whether the foreign customer.
|
||||
const isForeignCustomer =
|
||||
!isEqual(selectCustomer?.currency_code, baseCurrency) &&
|
||||
!isUndefined(selectCustomer?.currency_code);
|
||||
|
||||
const provider = {
|
||||
receiptId,
|
||||
receipt,
|
||||
@@ -97,6 +106,9 @@ function ReceiptFormProvider({ receiptId, ...props }) {
|
||||
branches,
|
||||
warehouses,
|
||||
submitPayload,
|
||||
baseCurrency,
|
||||
selectCustomer,
|
||||
setSelectCustomer,
|
||||
|
||||
isNewMode,
|
||||
isReceiptLoading,
|
||||
@@ -109,6 +121,7 @@ function ReceiptFormProvider({ receiptId, ...props }) {
|
||||
isSettingLoading,
|
||||
isBranchesSuccess,
|
||||
isWarehousesSuccess,
|
||||
isForeignCustomer,
|
||||
|
||||
createReceiptMutate,
|
||||
editReceiptMutate,
|
||||
|
||||
Reference in New Issue
Block a user