mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-21 15:20:34 +00:00
feat(customer & vendor): add branch.
This commit is contained in:
@@ -3,32 +3,33 @@ import classNames from 'classnames';
|
|||||||
import { FormGroup, Position, Classes, ControlGroup } from '@blueprintjs/core';
|
import { FormGroup, Position, Classes, ControlGroup } from '@blueprintjs/core';
|
||||||
import { DateInput } from '@blueprintjs/datetime';
|
import { DateInput } from '@blueprintjs/datetime';
|
||||||
import { FastField, ErrorMessage } from 'formik';
|
import { FastField, ErrorMessage } from 'formik';
|
||||||
|
import { FFormGroup } from '../../../components/Forms';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
import { Features } from 'common';
|
||||||
import {
|
import {
|
||||||
MoneyInputGroup,
|
MoneyInputGroup,
|
||||||
InputPrependText,
|
InputPrependText,
|
||||||
CurrencySelectList,
|
CurrencySelectList,
|
||||||
|
BranchSelect,
|
||||||
|
BranchSelectButton,
|
||||||
|
FeatureCan,
|
||||||
Row,
|
Row,
|
||||||
Col,
|
Col,
|
||||||
} from 'components';
|
} from 'components';
|
||||||
import { FormattedMessage as T } from 'components';
|
import { FormattedMessage as T } from 'components';
|
||||||
|
|
||||||
import { useCustomerFormContext } from './CustomerFormProvider';
|
import { useCustomerFormContext } from './CustomerFormProvider';
|
||||||
|
import { useSetPrimaryBranchToForm } from './utils';
|
||||||
import {
|
import { momentFormatter, tansformDateValue, inputIntent } from 'utils';
|
||||||
momentFormatter,
|
|
||||||
tansformDateValue,
|
|
||||||
inputIntent,
|
|
||||||
} from 'utils';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Customer financial panel.
|
* Customer financial panel.
|
||||||
*/
|
*/
|
||||||
export default function CustomerFinancialPanel() {
|
export default function CustomerFinancialPanel() {
|
||||||
const {
|
const { currencies, customerId, branches } = useCustomerFormContext();
|
||||||
currencies,
|
|
||||||
customerId
|
// Sets the primary branch to form.
|
||||||
} = useCustomerFormContext();
|
useSetPrimaryBranchToForm();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={'tab-panel--financial'}>
|
<div className={'tab-panel--financial'}>
|
||||||
@@ -62,12 +63,7 @@ export default function CustomerFinancialPanel() {
|
|||||||
|
|
||||||
{/*------------ Opening balance -----------*/}
|
{/*------------ Opening balance -----------*/}
|
||||||
<FastField name={'opening_balance'}>
|
<FastField name={'opening_balance'}>
|
||||||
{({
|
{({ form, field, field: { value }, meta: { error, touched } }) => (
|
||||||
form,
|
|
||||||
field,
|
|
||||||
field: { value },
|
|
||||||
meta: { error, touched },
|
|
||||||
}) => (
|
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={<T id={'opening_balance'} />}
|
label={<T id={'opening_balance'} />}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
@@ -92,6 +88,23 @@ export default function CustomerFinancialPanel() {
|
|||||||
)}
|
)}
|
||||||
</FastField>
|
</FastField>
|
||||||
|
|
||||||
|
{/*------------ Opening branch -----------*/}
|
||||||
|
<FeatureCan feature={Features.Branches}>
|
||||||
|
<FFormGroup
|
||||||
|
label={<T id={'customer.label.opening_branch'} />}
|
||||||
|
name={'opening_balance_branch_id'}
|
||||||
|
inline={true}
|
||||||
|
className={classNames('form-group--select-list', Classes.FILL)}
|
||||||
|
>
|
||||||
|
<BranchSelect
|
||||||
|
name={'opening_balance_branch_id'}
|
||||||
|
branches={branches}
|
||||||
|
input={BranchSelectButton}
|
||||||
|
popoverProps={{ minimal: true }}
|
||||||
|
/>
|
||||||
|
</FFormGroup>
|
||||||
|
</FeatureCan>
|
||||||
|
|
||||||
{/*------------ Currency -----------*/}
|
{/*------------ Currency -----------*/}
|
||||||
<FastField name={'currency_code'}>
|
<FastField name={'currency_code'}>
|
||||||
{({ form, field: { value }, meta: { error, touched } }) => (
|
{({ form, field: { value }, meta: { error, touched } }) => (
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ const Schema = Yup.object().shape({
|
|||||||
opening_balance: Yup.number().nullable(),
|
opening_balance: Yup.number().nullable(),
|
||||||
currency_code: Yup.string(),
|
currency_code: Yup.string(),
|
||||||
opening_balance_at: Yup.date(),
|
opening_balance_at: Yup.date(),
|
||||||
|
opening_balance_branch_id: Yup.string(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const CreateCustomerForm = Schema;
|
export const CreateCustomerForm = Schema;
|
||||||
|
|||||||
@@ -6,15 +6,21 @@ import {
|
|||||||
useCreateCustomer,
|
useCreateCustomer,
|
||||||
useEditCustomer,
|
useEditCustomer,
|
||||||
useContact,
|
useContact,
|
||||||
|
useBranches,
|
||||||
} from 'hooks/query';
|
} from 'hooks/query';
|
||||||
|
import { Features } from 'common';
|
||||||
|
import { useFeatureCan } from 'hooks/state';
|
||||||
|
|
||||||
const CustomerFormContext = createContext();
|
const CustomerFormContext = createContext();
|
||||||
|
|
||||||
function CustomerFormProvider({ customerId, ...props }) {
|
function CustomerFormProvider({ query, customerId, ...props }) {
|
||||||
const { state } = useLocation();
|
const { state } = useLocation();
|
||||||
|
|
||||||
const contactId = state?.action;
|
const contactId = state?.action;
|
||||||
|
|
||||||
|
// Features guard.
|
||||||
|
const { featureCan } = useFeatureCan();
|
||||||
|
const isBranchFeatureCan = featureCan(Features.Branches);
|
||||||
|
|
||||||
// Handle fetch customer details.
|
// Handle fetch customer details.
|
||||||
const { data: customer, isLoading: isCustomerLoading } = useCustomer(
|
const { data: customer, isLoading: isCustomerLoading } = useCustomer(
|
||||||
customerId,
|
customerId,
|
||||||
@@ -28,6 +34,13 @@ function CustomerFormProvider({ customerId, ...props }) {
|
|||||||
// Handle fetch Currencies data table
|
// Handle fetch Currencies data table
|
||||||
const { data: currencies, isLoading: isCurrenciesLoading } = useCurrencies();
|
const { data: currencies, isLoading: isCurrenciesLoading } = useCurrencies();
|
||||||
|
|
||||||
|
// Fetches the branches list.
|
||||||
|
const {
|
||||||
|
data: branches,
|
||||||
|
isLoading: isBranchesLoading,
|
||||||
|
isSuccess: isBranchesSuccess,
|
||||||
|
} = useBranches(query, { enabled: isBranchFeatureCan });
|
||||||
|
|
||||||
// Form submit payload.
|
// Form submit payload.
|
||||||
const [submitPayload, setSubmitPayload] = useState({});
|
const [submitPayload, setSubmitPayload] = useState({});
|
||||||
|
|
||||||
@@ -38,18 +51,20 @@ function CustomerFormProvider({ customerId, ...props }) {
|
|||||||
const isNewMode = contactId || !customerId;
|
const isNewMode = contactId || !customerId;
|
||||||
|
|
||||||
const isFormLoading =
|
const isFormLoading =
|
||||||
isCustomerLoading || isCurrenciesLoading || isContactLoading;
|
isCustomerLoading || isCurrenciesLoading || isBranchesLoading;
|
||||||
|
|
||||||
const provider = {
|
const provider = {
|
||||||
customerId,
|
customerId,
|
||||||
customer,
|
customer,
|
||||||
currencies,
|
currencies,
|
||||||
|
branches,
|
||||||
contactDuplicate,
|
contactDuplicate,
|
||||||
submitPayload,
|
submitPayload,
|
||||||
isNewMode,
|
isNewMode,
|
||||||
|
|
||||||
isCustomerLoading,
|
isCustomerLoading,
|
||||||
isCurrenciesLoading,
|
isCurrenciesLoading,
|
||||||
|
isBranchesSuccess,
|
||||||
isFormLoading,
|
isFormLoading,
|
||||||
|
|
||||||
setSubmitPayload,
|
setSubmitPayload,
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
|
import React from 'react';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
import { useFormikContext } from 'formik';
|
||||||
|
import { first } from 'lodash';
|
||||||
|
|
||||||
|
import { useCustomerFormContext } from './CustomerFormProvider';
|
||||||
|
|
||||||
export const defaultInitialValues = {
|
export const defaultInitialValues = {
|
||||||
customer_type: 'business',
|
customer_type: 'business',
|
||||||
@@ -35,4 +39,20 @@ export const defaultInitialValues = {
|
|||||||
opening_balance: '',
|
opening_balance: '',
|
||||||
currency_code: '',
|
currency_code: '',
|
||||||
opening_balance_at: moment(new Date()).format('YYYY-MM-DD'),
|
opening_balance_at: moment(new Date()).format('YYYY-MM-DD'),
|
||||||
|
opening_balance_branch_id: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useSetPrimaryBranchToForm = () => {
|
||||||
|
const { setFieldValue } = useFormikContext();
|
||||||
|
const { branches, isBranchesSuccess } = useCustomerFormContext();
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (isBranchesSuccess) {
|
||||||
|
const primaryBranch = branches.find((b) => b.primary) || first(branches);
|
||||||
|
|
||||||
|
if (primaryBranch) {
|
||||||
|
setFieldValue('opening_balance_branch_id', primaryBranch.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [isBranchesSuccess, setFieldValue, branches]);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,17 +1,23 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import moment from 'moment';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { FormGroup, ControlGroup, Position, Classes } from '@blueprintjs/core';
|
import { FormGroup, ControlGroup, Position, Classes } from '@blueprintjs/core';
|
||||||
import { DateInput } from '@blueprintjs/datetime';
|
import { DateInput } from '@blueprintjs/datetime';
|
||||||
import { FastField, ErrorMessage } from 'formik';
|
import { FastField, ErrorMessage } from 'formik';
|
||||||
import moment from 'moment';
|
import { FFormGroup } from '../../../components/Forms';
|
||||||
|
import { Features } from 'common';
|
||||||
import {
|
import {
|
||||||
MoneyInputGroup,
|
MoneyInputGroup,
|
||||||
InputPrependText,
|
InputPrependText,
|
||||||
CurrencySelectList,
|
CurrencySelectList,
|
||||||
|
BranchSelect,
|
||||||
|
BranchSelectButton,
|
||||||
|
FeatureCan,
|
||||||
Row,
|
Row,
|
||||||
Col,
|
Col,
|
||||||
} from 'components';
|
} from 'components';
|
||||||
import { FormattedMessage as T } from 'components';
|
import { FormattedMessage as T } from 'components';
|
||||||
|
import { useSetPrimaryBranchToForm } from './utils';
|
||||||
import { momentFormatter, tansformDateValue, inputIntent } from 'utils';
|
import { momentFormatter, tansformDateValue, inputIntent } from 'utils';
|
||||||
import { useVendorFormContext } from './VendorFormProvider';
|
import { useVendorFormContext } from './VendorFormProvider';
|
||||||
|
|
||||||
@@ -19,7 +25,10 @@ import { useVendorFormContext } from './VendorFormProvider';
|
|||||||
* Vendor Finaniceal Panel Tab.
|
* Vendor Finaniceal Panel Tab.
|
||||||
*/
|
*/
|
||||||
export default function VendorFinanicalPanelTab() {
|
export default function VendorFinanicalPanelTab() {
|
||||||
const { vendorId, currencies } = useVendorFormContext();
|
const { vendorId, currencies, branches } = useVendorFormContext();
|
||||||
|
|
||||||
|
// Sets the primary branch to form.
|
||||||
|
useSetPrimaryBranchToForm();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={'tab-panel--financial'}>
|
<div className={'tab-panel--financial'}>
|
||||||
@@ -80,6 +89,23 @@ export default function VendorFinanicalPanelTab() {
|
|||||||
)}
|
)}
|
||||||
</FastField>
|
</FastField>
|
||||||
|
|
||||||
|
{/*------------ Opening branch -----------*/}
|
||||||
|
<FeatureCan feature={Features.Branches}>
|
||||||
|
<FFormGroup
|
||||||
|
label={<T id={'vendor.label.opening_branch'} />}
|
||||||
|
name={'opening_balance_branch_id'}
|
||||||
|
inline={true}
|
||||||
|
className={classNames('form-group--select-list', Classes.FILL)}
|
||||||
|
>
|
||||||
|
<BranchSelect
|
||||||
|
name={'opening_balance_branch_id'}
|
||||||
|
branches={branches}
|
||||||
|
input={BranchSelectButton}
|
||||||
|
popoverProps={{ minimal: true }}
|
||||||
|
/>
|
||||||
|
</FFormGroup>
|
||||||
|
</FeatureCan>
|
||||||
|
|
||||||
{/*------------ Currency -----------*/}
|
{/*------------ Currency -----------*/}
|
||||||
<FastField name={'currency_code'}>
|
<FastField name={'currency_code'}>
|
||||||
{({ form, field: { value }, meta: { error, touched } }) => (
|
{({ form, field: { value }, meta: { error, touched } }) => (
|
||||||
|
|||||||
@@ -6,10 +6,7 @@ const Schema = Yup.object().shape({
|
|||||||
first_name: Yup.string().trim(),
|
first_name: Yup.string().trim(),
|
||||||
last_name: Yup.string().trim(),
|
last_name: Yup.string().trim(),
|
||||||
company_name: Yup.string().trim(),
|
company_name: Yup.string().trim(),
|
||||||
display_name: Yup.string()
|
display_name: Yup.string().trim().required().label(intl.get('display_name_')),
|
||||||
.trim()
|
|
||||||
.required()
|
|
||||||
.label(intl.get('display_name_')),
|
|
||||||
|
|
||||||
email: Yup.string().email().nullable(),
|
email: Yup.string().email().nullable(),
|
||||||
work_phone: Yup.number(),
|
work_phone: Yup.number(),
|
||||||
@@ -38,6 +35,7 @@ const Schema = Yup.object().shape({
|
|||||||
opening_balance: Yup.number().nullable(),
|
opening_balance: Yup.number().nullable(),
|
||||||
currency_code: Yup.string(),
|
currency_code: Yup.string(),
|
||||||
opening_balance_at: Yup.date(),
|
opening_balance_at: Yup.date(),
|
||||||
|
opening_balance_branch_id: Yup.string(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const CreateVendorFormSchema = Schema;
|
export const CreateVendorFormSchema = Schema;
|
||||||
|
|||||||
@@ -8,18 +8,24 @@ import {
|
|||||||
useCurrencies,
|
useCurrencies,
|
||||||
useCreateVendor,
|
useCreateVendor,
|
||||||
useEditVendor,
|
useEditVendor,
|
||||||
|
useBranches,
|
||||||
} from 'hooks/query';
|
} from 'hooks/query';
|
||||||
|
import { Features } from 'common';
|
||||||
|
import { useFeatureCan } from 'hooks/state';
|
||||||
|
|
||||||
const VendorFormContext = createContext();
|
const VendorFormContext = createContext();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Vendor form provider.
|
* Vendor form provider.
|
||||||
*/
|
*/
|
||||||
function VendorFormProvider({ vendorId, ...props }) {
|
function VendorFormProvider({ query, vendorId, ...props }) {
|
||||||
const { state } = useLocation();
|
const { state } = useLocation();
|
||||||
|
|
||||||
const contactId = state?.action;
|
const contactId = state?.action;
|
||||||
|
|
||||||
|
// Features guard.
|
||||||
|
const { featureCan } = useFeatureCan();
|
||||||
|
const isBranchFeatureCan = featureCan(Features.Branches);
|
||||||
|
|
||||||
// Handle fetch Currencies data table
|
// Handle fetch Currencies data table
|
||||||
const { data: currencies, isLoading: isCurrenciesLoading } = useCurrencies();
|
const { data: currencies, isLoading: isCurrenciesLoading } = useCurrencies();
|
||||||
|
|
||||||
@@ -33,6 +39,14 @@ function VendorFormProvider({ vendorId, ...props }) {
|
|||||||
contactId,
|
contactId,
|
||||||
{ enabled: !!contactId },
|
{ enabled: !!contactId },
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Fetches the branches list.
|
||||||
|
const {
|
||||||
|
data: branches,
|
||||||
|
isLoading: isBranchesLoading,
|
||||||
|
isSuccess: isBranchesSuccess,
|
||||||
|
} = useBranches(query, { enabled: isBranchFeatureCan });
|
||||||
|
|
||||||
// Create and edit vendor mutations.
|
// Create and edit vendor mutations.
|
||||||
const { mutateAsync: createVendorMutate } = useCreateVendor();
|
const { mutateAsync: createVendorMutate } = useCreateVendor();
|
||||||
const { mutateAsync: editVendorMutate } = useEditVendor();
|
const { mutateAsync: editVendorMutate } = useEditVendor();
|
||||||
@@ -44,17 +58,22 @@ function VendorFormProvider({ vendorId, ...props }) {
|
|||||||
const isNewMode = contactId || !vendorId;
|
const isNewMode = contactId || !vendorId;
|
||||||
|
|
||||||
const isFormLoading =
|
const isFormLoading =
|
||||||
isVendorLoading || isContactLoading || isCurrenciesLoading;
|
isVendorLoading ||
|
||||||
|
isContactLoading ||
|
||||||
|
isCurrenciesLoading ||
|
||||||
|
isBranchesLoading;
|
||||||
|
|
||||||
const provider = {
|
const provider = {
|
||||||
vendorId,
|
vendorId,
|
||||||
currencies,
|
currencies,
|
||||||
vendor,
|
vendor,
|
||||||
|
branches,
|
||||||
contactDuplicate: { ...omit(contactDuplicate, ['opening_balance_at']) },
|
contactDuplicate: { ...omit(contactDuplicate, ['opening_balance_at']) },
|
||||||
submitPayload,
|
submitPayload,
|
||||||
|
|
||||||
isNewMode,
|
isNewMode,
|
||||||
isFormLoading,
|
isFormLoading,
|
||||||
|
isBranchesSuccess,
|
||||||
|
|
||||||
createVendorMutate,
|
createVendorMutate,
|
||||||
editVendorMutate,
|
editVendorMutate,
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
|
import React from 'react';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
import { useFormikContext } from 'formik';
|
||||||
|
import { first } from 'lodash';
|
||||||
|
|
||||||
|
import { useVendorFormContext } from './VendorFormProvider';
|
||||||
|
|
||||||
export const defaultInitialValues = {
|
export const defaultInitialValues = {
|
||||||
salutation: '',
|
salutation: '',
|
||||||
@@ -33,4 +38,20 @@ export const defaultInitialValues = {
|
|||||||
opening_balance: '',
|
opening_balance: '',
|
||||||
currency_code: '',
|
currency_code: '',
|
||||||
opening_balance_at: moment(new Date()).format('YYYY-MM-DD'),
|
opening_balance_at: moment(new Date()).format('YYYY-MM-DD'),
|
||||||
|
opening_balance_branch_id: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useSetPrimaryBranchToForm = () => {
|
||||||
|
const { setFieldValue } = useFormikContext();
|
||||||
|
const { branches, isBranchesSuccess } = useVendorFormContext();
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (isBranchesSuccess) {
|
||||||
|
const primaryBranch = branches.find((b) => b.primary) || first(branches);
|
||||||
|
|
||||||
|
if (primaryBranch) {
|
||||||
|
setFieldValue('opening_balance_branch_id', primaryBranch.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [isBranchesSuccess, setFieldValue, branches]);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1895,5 +1895,7 @@
|
|||||||
"vendor_opening_balance.success_message": "The opening balance of the given vendor has been changed successfully.",
|
"vendor_opening_balance.success_message": "The opening balance of the given vendor has been changed successfully.",
|
||||||
"vendor_opening_balance.label": "Edit Vendor Opening Balance",
|
"vendor_opening_balance.label": "Edit Vendor Opening Balance",
|
||||||
"vendor_opening_balance.label.opening_balance": "Opening balance",
|
"vendor_opening_balance.label.opening_balance": "Opening balance",
|
||||||
"vendor_opening_balance.label.opening_balance_at": "Opening balance at"
|
"vendor_opening_balance.label.opening_balance_at": "Opening balance at",
|
||||||
|
"customer.label.opening_branch": "Opening Balance Branch",
|
||||||
|
"vendor.label.opening_branch": "Opening Balance Branch"
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user