From 2950e5ede4248154d0f974f054dff0ae161c313e Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Sun, 11 Jun 2023 19:29:26 +0200 Subject: [PATCH 1/5] fix(webapp): customer/vendor opening balnace with exchange rate --- .../CustomerForm/CustomerFinancialPanel.tsx | 203 +++++++++++------- .../Customers/CustomerForm/CustomersTabs.tsx | 5 - .../Customers/CustomerForm/utils.tsx | 27 ++- .../VendorForm/VendorFinanicalPanelTab.tsx | 185 +++++++++------- .../Vendors/VendorForm/VendorsTabs.tsx | 12 +- .../containers/Vendors/VendorForm/utils.tsx | 27 ++- packages/webapp/src/lang/en/index.json | 2 +- 7 files changed, 291 insertions(+), 170 deletions(-) diff --git a/packages/webapp/src/containers/Customers/CustomerForm/CustomerFinancialPanel.tsx b/packages/webapp/src/containers/Customers/CustomerForm/CustomerFinancialPanel.tsx index b41312c81..47225a6a7 100644 --- a/packages/webapp/src/containers/Customers/CustomerForm/CustomerFinancialPanel.tsx +++ b/packages/webapp/src/containers/Customers/CustomerForm/CustomerFinancialPanel.tsx @@ -1,15 +1,12 @@ // @ts-nocheck import React from 'react'; -import moment from 'moment'; import classNames from 'classnames'; import { FormGroup, Position, Classes, ControlGroup } from '@blueprintjs/core'; -import { DateInput } from '@blueprintjs/datetime'; -import { FastField, ErrorMessage } from 'formik'; +import { FastField, ErrorMessage, useFormikContext } from 'formik'; import { Features } from '@/constants'; import { FFormGroup, FormattedMessage as T, - MoneyInputGroup, InputPrependText, CurrencySelectList, BranchSelect, @@ -17,10 +14,17 @@ import { FeatureCan, Row, Col, + FMoneyInputGroup, + ExchangeRateInputGroup, + FDateInput, } from '@/components'; import { useCustomerFormContext } from './CustomerFormProvider'; -import { useSetPrimaryBranchToForm } from './utils'; -import { momentFormatter, tansformDateValue, inputIntent } from '@/utils'; +import { + openingBalanceFieldShouldUpdate, + useIsCustomerForeignCurrency, + useSetPrimaryBranchToForm, +} from './utils'; +import { useCurrentOrganization } from '@/hooks/state'; /** * Customer financial panel. @@ -35,76 +39,6 @@ export default function CustomerFinancialPanel() {
- {/*------------ Opening balance at -----------*/} - - {({ form, field: { value }, meta: { error, touched } }) => ( - } - className={classNames('form-group--select-list', Classes.FILL)} - intent={inputIntent({ error, touched })} - inline={true} - helperText={} - > - { - form.setFieldValue( - 'opening_balance_at', - moment(date).format('YYYY-MM-DD'), - ); - }} - value={tansformDateValue(value)} - popoverProps={{ position: Position.BOTTOM, minimal: true }} - disabled={customerId} - /> - - )} - - - {/*------------ Opening balance -----------*/} - - {({ form, field, field: { value }, meta: { error, touched } }) => ( - } - className={classNames( - 'form-group--opening-balance', - Classes.FILL, - )} - intent={inputIntent({ error, touched })} - inline={true} - > - - - { - form.setFieldValue('opening_balance', balance); - }} - /> - - - )} - - - {/*------------ Opening branch -----------*/} - - } - name={'opening_balance_branch_id'} - inline={true} - className={classNames('form-group--select-list', Classes.FILL)} - > - - - - {/*------------ Currency -----------*/} {({ form, field: { value }, meta: { error, touched } }) => ( @@ -123,12 +57,129 @@ export default function CustomerFinancialPanel() { onCurrencySelected={(currency) => { form.setFieldValue('currency_code', currency.currency_code); }} + disabled={customerId} /> )} + + {/*------------ Opening balance -----------*/} + + + {/*------ Opening Balance Exchange Rate -----*/} + + + {/*------------ Opening balance at -----------*/} + + + {/*------------ Opening branch -----------*/} + + } + name={'opening_balance_branch_id'} + inline={true} + className={classNames('form-group--select-list', Classes.FILL)} + > + + +
); } + +/** + * Customer opening balance at date field. + * @returns {JSX.Element} + */ +function CustomerOpeningBalanceAtField() { + const { customerId } = useCustomerFormContext(); + + // Cannot continue if the customer id is defined. + if (customerId) return null; + + return ( + } + inline={true} + helperText={} + > + date.toLocaleDateString()} + parseDate={(str) => new Date(str)} + fill={true} + /> + + ); +} + +/** + * Customer opening balance field. + * @returns {JSX.Element} + */ +function CustomerOpeningBalanceField() { + const { customerId } = useCustomerFormContext(); + const { values } = useFormikContext(); + + // Cannot continue if the customer id is defined. + if (customerId) return null; + + return ( + } + name={'opening_balance'} + inline={true} + shouldUpdate={openingBalanceFieldShouldUpdate} + shouldUpdateDeps={{ currencyCode: values.currency_code }} + > + + + + + + ); +} + +/** + * Customer opening balance exchange rate field if the customer has foreign + * currency. + * @returns {JSX.Element} + */ +function CustomerOpeningBalanceExchangeRateField() { + const { values } = useFormikContext(); + const { customerId } = useCustomerFormContext(); + const currentOrganization = useCurrentOrganization(); + + const isForeignJouranl = useIsCustomerForeignCurrency(); + + // Can't continue if the customer is not foreign. + if (!isForeignJouranl || customerId) { + return null; + } + return ( + + + + ); +} diff --git a/packages/webapp/src/containers/Customers/CustomerForm/CustomersTabs.tsx b/packages/webapp/src/containers/Customers/CustomerForm/CustomersTabs.tsx index 72881e983..02ecd39ac 100644 --- a/packages/webapp/src/containers/Customers/CustomerForm/CustomersTabs.tsx +++ b/packages/webapp/src/containers/Customers/CustomerForm/CustomersTabs.tsx @@ -32,11 +32,6 @@ export default function CustomersTabs() { title={intl.get('notes')} panel={} /> - } - /> ); diff --git a/packages/webapp/src/containers/Customers/CustomerForm/utils.tsx b/packages/webapp/src/containers/Customers/CustomerForm/utils.tsx index f230c1fd6..a6d17c45c 100644 --- a/packages/webapp/src/containers/Customers/CustomerForm/utils.tsx +++ b/packages/webapp/src/containers/Customers/CustomerForm/utils.tsx @@ -5,6 +5,7 @@ import { useFormikContext } from 'formik'; import { first } from 'lodash'; import { useCustomerFormContext } from './CustomerFormProvider'; +import { useCurrentOrganization } from '@/hooks/state'; export const defaultInitialValues = { customer_type: 'business', @@ -37,9 +38,11 @@ export const defaultInitialValues = { shipping_address_postcode: '', shipping_address_phone: '', - opening_balance: '', currency_code: '', + + opening_balance: '', opening_balance_at: moment(new Date()).format('YYYY-MM-DD'), + opening_balance_exchange_rate: '', opening_balance_branch_id: '', }; @@ -57,3 +60,25 @@ export const useSetPrimaryBranchToForm = () => { } }, [isBranchesSuccess, setFieldValue, branches]); }; + +/** + * Detarmines whether the current customer has foreign currency. + * @returns {boolean} + */ +export const useIsCustomerForeignCurrency = () => { + const currentOrganization = useCurrentOrganization(); + const { values } = useFormikContext(); + + return currentOrganization.base_currency !== values.currency_code; +}; + +/** + * Detarmines the exchange opening balance field when should update. + */ +export const openingBalanceFieldShouldUpdate = (newProps, oldProps) => { + return ( + newProps.shouldUpdateDeps.currencyCode !== + oldProps.shouldUpdateDeps.currencyCode || + defaultFastFieldShouldUpdate(newProps, oldProps) + ); +}; diff --git a/packages/webapp/src/containers/Vendors/VendorForm/VendorFinanicalPanelTab.tsx b/packages/webapp/src/containers/Vendors/VendorForm/VendorFinanicalPanelTab.tsx index ada9e1930..03f21f959 100644 --- a/packages/webapp/src/containers/Vendors/VendorForm/VendorFinanicalPanelTab.tsx +++ b/packages/webapp/src/containers/Vendors/VendorForm/VendorFinanicalPanelTab.tsx @@ -1,14 +1,11 @@ // @ts-nocheck import React from 'react'; -import moment from 'moment'; import classNames from 'classnames'; import { FormGroup, ControlGroup, Position, Classes } from '@blueprintjs/core'; -import { DateInput } from '@blueprintjs/datetime'; -import { FastField, ErrorMessage } from 'formik'; +import { FastField, ErrorMessage, useFormikContext } from 'formik'; import { Features } from '@/constants'; import { FFormGroup, - MoneyInputGroup, InputPrependText, CurrencySelectList, BranchSelect, @@ -17,16 +14,19 @@ import { Row, Col, FormattedMessage as T, + FMoneyInputGroup, + ExchangeRateInputGroup, + FDateInput, } from '@/components'; -import { useSetPrimaryBranchToForm } from './utils'; -import { momentFormatter, tansformDateValue, inputIntent } from '@/utils'; +import { useIsVendorForeignCurrency, useSetPrimaryBranchToForm } from './utils'; import { useVendorFormContext } from './VendorFormProvider'; +import { useCurrentOrganization } from '@/hooks/state'; /** * Vendor Finaniceal Panel Tab. */ export default function VendorFinanicalPanelTab() { - const { vendorId, currencies, branches } = useVendorFormContext(); + const { currencies, branches } = useVendorFormContext(); // Sets the primary branch to form. useSetPrimaryBranchToForm(); @@ -35,78 +35,6 @@ export default function VendorFinanicalPanelTab() {
- {/*------------ Opening balance at -----------*/} - - {({ form, field: { value }, meta: { error, touched } }) => ( - } - className={classNames('form-group--select-list', Classes.FILL)} - intent={inputIntent({ error, touched })} - inline={true} - helperText={} - > - { - form.setFieldValue( - 'opening_balance_at', - moment(date).format('YYYY-MM-DD'), - ); - }} - value={tansformDateValue(value)} - popoverProps={{ position: Position.BOTTOM, minimal: true }} - disabled={vendorId} - /> - - )} - - {/*------------ Opening balance -----------*/} - - {({ form, field, field: { value }, meta: { error, touched } }) => ( - } - className={classNames( - 'form-group--opening-balance', - Classes.FILL, - )} - intent={inputIntent({ error, touched })} - inline={true} - > - - - { - form.setFieldValue('opening_balance', balance); - }} - disabled={vendorId} - /> - - - )} - - - {/*------------ Opening branch -----------*/} - - } - name={'opening_balance_branch_id'} - inline={true} - className={classNames('form-group--select-list', Classes.FILL)} - > - - - - {/*------------ Currency -----------*/} {({ form, field: { value }, meta: { error, touched } }) => ( @@ -129,8 +57,107 @@ export default function VendorFinanicalPanelTab() { )} + + {/*------------ Opening balance -----------*/} + + + + {/*------------ Opening balance at -----------*/} + + + {/*------------ Opening branch -----------*/} + + } + name={'opening_balance_branch_id'} + inline={true} + className={classNames('form-group--select-list', Classes.FILL)} + > + + +
); } + +function VendorOpeningBalanceField() { + const { vendorId } = useVendorFormContext(); + const { values } = useFormikContext(); + + // Cannot continue if the vendor id is defined. + if (vendorId) return null; + + return ( + } + inline={true} + > + + + + + + ); +} + +function VendorOpeningBalanceAtField() { + const { vendorId } = useVendorFormContext(); + + // Cannot continue if the vendor id is defined. + if (vendorId) return null; + + return ( + } + inline={true} + helperText={} + > + date.toLocaleDateString()} + parseDate={(str) => new Date(str)} + fill={true} + /> + + ); +} + +function VendorOpeningBalanceExchangeRateField() { + const { values } = useFormikContext(); + const { vendorId } = useVendorFormContext(); + const isForeignVendor = useIsVendorForeignCurrency(); + const currentOrganization = useCurrentOrganization(); + + // Cannot continue if the current vendor does not have foreign currency. + if (!isForeignVendor || vendorId) { + return null; + } + + return ( + + + + ); +} diff --git a/packages/webapp/src/containers/Vendors/VendorForm/VendorsTabs.tsx b/packages/webapp/src/containers/Vendors/VendorForm/VendorsTabs.tsx index 750d7b6b6..a49ef1a8a 100644 --- a/packages/webapp/src/containers/Vendors/VendorForm/VendorsTabs.tsx +++ b/packages/webapp/src/containers/Vendors/VendorForm/VendorsTabs.tsx @@ -10,6 +10,7 @@ import VendorAttahmentTab from './VendorAttahmentTab'; import CustomerAddressTabs from '@/containers/Customers/CustomerForm/CustomerAddressTabs'; import CustomerNotePanel from '@/containers/Customers/CustomerForm/CustomerNotePanel'; +import styled from 'styled-components'; /** * Vendor form tabs. @@ -18,7 +19,7 @@ export default function VendorTabs() { return (
- } /> - } - /> - +
); } + +const VendorTabsRoot = styled(Tabs)``; \ No newline at end of file diff --git a/packages/webapp/src/containers/Vendors/VendorForm/utils.tsx b/packages/webapp/src/containers/Vendors/VendorForm/utils.tsx index 72ffdb9bc..5be562763 100644 --- a/packages/webapp/src/containers/Vendors/VendorForm/utils.tsx +++ b/packages/webapp/src/containers/Vendors/VendorForm/utils.tsx @@ -5,6 +5,7 @@ import { useFormikContext } from 'formik'; import { first } from 'lodash'; import { useVendorFormContext } from './VendorFormProvider'; +import { useCurrentOrganization } from '@/hooks/state'; export const defaultInitialValues = { salutation: '', @@ -36,10 +37,12 @@ export const defaultInitialValues = { shipping_address_postcode: '', shipping_address_phone: '', - opening_balance: '', currency_code: '', + + opening_balance: '', opening_balance_at: moment(new Date()).format('YYYY-MM-DD'), opening_balance_branch_id: '', + opening_balance_exchange_rate: '' }; export const useSetPrimaryBranchToForm = () => { @@ -56,3 +59,25 @@ export const useSetPrimaryBranchToForm = () => { } }, [isBranchesSuccess, setFieldValue, branches]); }; + +/** + * Detarmines whether the current vendor has foreign currency. + * @returns {boolean} + */ +export const useIsVendorForeignCurrency = () => { + const currentOrganization = useCurrentOrganization(); + const { values } = useFormikContext(); + + return currentOrganization.base_currency !== values.currency_code; +}; + +/** + * Detarmines the exchange opening balance field when should update. + */ +export const openingBalanceFieldShouldUpdate = (newProps, oldProps) => { + return ( + newProps.shouldUpdateDeps.currencyCode !== + oldProps.shouldUpdateDeps.currencyCode || + defaultFastFieldShouldUpdate(newProps, oldProps) + ); +}; diff --git a/packages/webapp/src/lang/en/index.json b/packages/webapp/src/lang/en/index.json index d9b5f02a8..35867a51b 100644 --- a/packages/webapp/src/lang/en/index.json +++ b/packages/webapp/src/lang/en/index.json @@ -658,7 +658,7 @@ "opening_balance_at": "Opening balance at", "opening_balance": "Opening balance", "balance_currency": "Balance currency", - "financial_details": "Financial details", + "financial_details": "Financial", "are_you_sure_you_want_to_clear_this_transaction": "Are you sure you want to clear this transaction?", "clearing_the_table_lines_will_delete_all_credits": "Clearing the table lines will delete all credits and payment were applied, Is this okay?", "changing_full_amount_will_change_all_credits_and_payment": " Changing full amount will change all credits and payment were applied, Is this okay?", From 93d540fbd28fb7395ad072326e7a449e90708662 Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Sun, 11 Jun 2023 19:53:15 +0200 Subject: [PATCH 2/5] fix(webapp): style tweaks on customer/vendor tabs --- packages/webapp/src/style/pages/Customers/Form.scss | 7 ------- 1 file changed, 7 deletions(-) diff --git a/packages/webapp/src/style/pages/Customers/Form.scss b/packages/webapp/src/style/pages/Customers/Form.scss index 6a90e84ed..3d9e1389f 100644 --- a/packages/webapp/src/style/pages/Customers/Form.scss +++ b/packages/webapp/src/style/pages/Customers/Form.scss @@ -142,15 +142,8 @@ > *:not(:last-child) { margin-right: 25px; } - &.bp3-large > .bp3-tab { font-size: 15px; - color: #555; - - &[aria-selected='true'], - &:not([aria-disabled='true']):hover { - color: $pt-link-color; - } } } } From 6a72594fafa86b869317c882461814f26efd27b5 Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Sun, 11 Jun 2023 20:09:51 +0200 Subject: [PATCH 3/5] fix(webapp): update condition of customer opening balance --- .../CustomerForm/CustomerFinancialPanel.tsx | 1 + .../VendorForm/VendorFinanicalPanelTab.tsx | 22 +++++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/packages/webapp/src/containers/Customers/CustomerForm/CustomerFinancialPanel.tsx b/packages/webapp/src/containers/Customers/CustomerForm/CustomerFinancialPanel.tsx index 47225a6a7..8de4eb45c 100644 --- a/packages/webapp/src/containers/Customers/CustomerForm/CustomerFinancialPanel.tsx +++ b/packages/webapp/src/containers/Customers/CustomerForm/CustomerFinancialPanel.tsx @@ -141,6 +141,7 @@ function CustomerOpeningBalanceField() { inline={true} shouldUpdate={openingBalanceFieldShouldUpdate} shouldUpdateDeps={{ currencyCode: values.currency_code }} + fastField={true} > diff --git a/packages/webapp/src/containers/Vendors/VendorForm/VendorFinanicalPanelTab.tsx b/packages/webapp/src/containers/Vendors/VendorForm/VendorFinanicalPanelTab.tsx index 03f21f959..def50c6a7 100644 --- a/packages/webapp/src/containers/Vendors/VendorForm/VendorFinanicalPanelTab.tsx +++ b/packages/webapp/src/containers/Vendors/VendorForm/VendorFinanicalPanelTab.tsx @@ -18,7 +18,11 @@ import { ExchangeRateInputGroup, FDateInput, } from '@/components'; -import { useIsVendorForeignCurrency, useSetPrimaryBranchToForm } from './utils'; +import { + openingBalanceFieldShouldUpdate, + useIsVendorForeignCurrency, + useSetPrimaryBranchToForm, +} from './utils'; import { useVendorFormContext } from './VendorFormProvider'; import { useCurrentOrganization } from '@/hooks/state'; @@ -87,6 +91,10 @@ export default function VendorFinanicalPanelTab() { ); } +/** + * Vendor opening balance field. + * @returns {JSX.Element} + */ function VendorOpeningBalanceField() { const { vendorId } = useVendorFormContext(); const { values } = useFormikContext(); @@ -99,6 +107,9 @@ function VendorOpeningBalanceField() { name={'opening_balance'} label={} inline={true} + shouldUpdate={openingBalanceFieldShouldUpdate} + shouldUpdateDeps={{ currencyCode: values.currency_code }} + FastField={true} > @@ -111,6 +122,10 @@ function VendorOpeningBalanceField() { ); } +/** + * Vendor opening balance at date field. + * @returns {JSX.Element} + */ function VendorOpeningBalanceAtField() { const { vendorId } = useVendorFormContext(); @@ -136,6 +151,10 @@ function VendorOpeningBalanceAtField() { ); } +/** + * Vendor opening balance exchange rate field if the vendor has foreign currency. + * @returns {JSX.Element} + */ function VendorOpeningBalanceExchangeRateField() { const { values } = useFormikContext(); const { vendorId } = useVendorFormContext(); @@ -146,7 +165,6 @@ function VendorOpeningBalanceExchangeRateField() { if (!isForeignVendor || vendorId) { return null; } - return ( Date: Sun, 11 Jun 2023 20:11:30 +0200 Subject: [PATCH 4/5] fix(webapp): vendor form fastField of opening balance field --- .../containers/Vendors/VendorForm/VendorFinanicalPanelTab.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webapp/src/containers/Vendors/VendorForm/VendorFinanicalPanelTab.tsx b/packages/webapp/src/containers/Vendors/VendorForm/VendorFinanicalPanelTab.tsx index def50c6a7..511ba5cc2 100644 --- a/packages/webapp/src/containers/Vendors/VendorForm/VendorFinanicalPanelTab.tsx +++ b/packages/webapp/src/containers/Vendors/VendorForm/VendorFinanicalPanelTab.tsx @@ -109,7 +109,7 @@ function VendorOpeningBalanceField() { inline={true} shouldUpdate={openingBalanceFieldShouldUpdate} shouldUpdateDeps={{ currencyCode: values.currency_code }} - FastField={true} + fastField={true} > From 3ebeb29dc0a2916bf1af4e47d9da039754bcf2c4 Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Sun, 11 Jun 2023 20:12:26 +0200 Subject: [PATCH 5/5] chore(webapp): vendor tabs --- .../src/containers/Vendors/VendorForm/VendorsTabs.tsx | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/packages/webapp/src/containers/Vendors/VendorForm/VendorsTabs.tsx b/packages/webapp/src/containers/Vendors/VendorForm/VendorsTabs.tsx index a49ef1a8a..7870c4000 100644 --- a/packages/webapp/src/containers/Vendors/VendorForm/VendorsTabs.tsx +++ b/packages/webapp/src/containers/Vendors/VendorForm/VendorsTabs.tsx @@ -6,20 +6,17 @@ import { Tabs, Tab } from '@blueprintjs/core'; import { CLASSES } from '@/constants/classes'; import VendorFinanicalPanelTab from './VendorFinanicalPanelTab'; -import VendorAttahmentTab from './VendorAttahmentTab'; import CustomerAddressTabs from '@/containers/Customers/CustomerForm/CustomerAddressTabs'; import CustomerNotePanel from '@/containers/Customers/CustomerForm/CustomerNotePanel'; -import styled from 'styled-components'; /** * Vendor form tabs. */ export default function VendorTabs() { - return (
- } + panel={} /> } /> - +
); } - -const VendorTabsRoot = styled(Tabs)``; \ No newline at end of file