merge: estimate work branch to master

This commit is contained in:
Ahmed Bouhuolia
2020-10-26 14:34:54 +02:00
parent 4ed96e5143
commit 40fa6aa71f
25 changed files with 419 additions and 96 deletions

View File

@@ -9,6 +9,8 @@ import AccountFormDialog from 'containers/Dialogs/AccountFormDialog';
// import ExchangeRateDialog from 'containers/Dialogs/ExchangeRateDialog'; // import ExchangeRateDialog from 'containers/Dialogs/ExchangeRateDialog';
import JournalNumberDialog from 'containers/Dialogs/JournalNumberDialog'; import JournalNumberDialog from 'containers/Dialogs/JournalNumberDialog';
import BillNumberDialog from 'containers/Dialogs/BillNumberDialog'; import BillNumberDialog from 'containers/Dialogs/BillNumberDialog';
import PaymentNumberDialog from 'containers/Dialogs/PaymentNumberDialog';
import EstimateNumberDialog from 'containers/Dialogs/EstimateNumberDialog';
export default function DialogsContainer() { export default function DialogsContainer() {
return ( return (
@@ -16,6 +18,8 @@ export default function DialogsContainer() {
<AccountFormDialog dialogName={'account-form'} /> <AccountFormDialog dialogName={'account-form'} />
<JournalNumberDialog dialogName={'journal-number-form'} /> <JournalNumberDialog dialogName={'journal-number-form'} />
<BillNumberDialog dialogName={'bill-number-form'} /> <BillNumberDialog dialogName={'bill-number-form'} />
<PaymentNumberDialog dialogName={'payment-number-form'} />
<EstimateNumberDialog dialogName={'estimate-number-form'} />
</div> </div>
); );
} }

View File

@@ -0,0 +1,70 @@
import React from 'react';
import { DialogContent } from 'components';
import { useQuery, queryCache } from 'react-query';
import ReferenceNumberForm from 'containers/JournalNumber/ReferenceNumberForm';
import withDialogActions from 'containers/Dialog/withDialogActions';
import withSettingsActions from 'containers/Settings/withSettingsActions';
import withSettings from 'containers/Settings/withSettings';
import { compose, optionsMapToArray } from 'utils';
/**
* Estimate number dialog's content.
*/
function EstimateNumberDialogContent({
// #withSettings
nextNumber,
numberPrefix,
// #withSettingsActions
requestFetchOptions,
requestSubmitOptions,
// #withDialogActions
closeDialog,
}) {
const fetchSettings = useQuery(['settings'], () => requestFetchOptions({}));
const handleSubmitForm = (values, { setSubmitting }) => {
const options = optionsMapToArray(values).map((option) => {
return { key: option.key, ...option, group: 'sales_estimates' };
});
requestSubmitOptions({ options })
.then(() => {
setSubmitting(false);
closeDialog('estimate-number-form');
setTimeout(() => {
queryCache.invalidateQueries('settings');
}, 250);
})
.catch(() => {
setSubmitting(false);
});
};
const handleClose = () => {
closeDialog('estimate-number-form');
};
return (
<DialogContent isLoading={fetchSettings.isFetching}>
<ReferenceNumberForm
initialNumber={nextNumber}
initialPrefix={numberPrefix}
onSubmit={handleSubmitForm}
onClose={handleClose}
/>
</DialogContent>
);
}
export default compose(
withDialogActions,
withSettingsActions,
withSettings(({ estimatesSettings }) => ({
nextNumber: estimatesSettings?.next_number,
numberPrefix: estimatesSettings?.number_prefix,
})),
)(EstimateNumberDialogContent);

View File

@@ -0,0 +1,28 @@
import React, { lazy } from 'react';
import { FormattedMessage as T } from 'react-intl';
import { Dialog, DialogSuspense } from 'components';
import withDialogRedux from 'components/DialogReduxConnect';
import { compose } from 'utils';
const EstimateNumberDialogContent = lazy(() =>
import('./EstimateNumberDialogContent'),
);
function EstimateNumberDialog({ dialogName, paylaod = { id: null }, isOpen }) {
return (
<Dialog
name={dialogName}
title={<T id={'Estimate_number_settings'} />}
autoFocus={true}
canEscapeKeyClose={true}
isOpen={isOpen}
className={'dialog--journal-number-settings'}
>
<DialogSuspense>
<EstimateNumberDialogContent EstimateNumberId={paylaod.id} />
</DialogSuspense>
</Dialog>
);
}
export default compose(withDialogRedux())(EstimateNumberDialog);

View File

@@ -0,0 +1,78 @@
import React from 'react';
import { DialogContent } from 'components';
import { useQuery, queryCache } from 'react-query';
import ReferenceNumberForm from 'containers/JournalNumber/ReferenceNumberForm';
import withDialogActions from 'containers/Dialog/withDialogActions';
import withSettingsActions from 'containers/Settings/withSettingsActions';
import withSettings from 'containers/Settings/withSettings';
import withPaymentMadeActions from 'containers/Purchases/PaymentMades/withPaymentMadeActions';
import { compose, optionsMapToArray } from 'utils';
/**
* payment number dialog's content.
*/
function PaymentNumberDialogContent({
// #withSettings
nextNumber,
numberPrefix,
// #withSettingsActions
requestFetchOptions,
requestSubmitOptions,
// #withDialogActions
closeDialog,
// #withPaymentMadeActions
setPaymentNumberChange,
}) {
const fetchSettings = useQuery(['settings'], () => requestFetchOptions({}));
const handleSubmitForm = (values, { setSubmitting }) => {
const options = optionsMapToArray(values).map((option) => {
return { key: option.key, ...option, group: 'bill_payments' };
});
requestSubmitOptions({ options })
.then(() => {
setSubmitting(false);
closeDialog('payment-number-form');
setPaymentNumberChange(true);
setTimeout(() => {
queryCache.invalidateQueries('settings');
}, 250);
})
.catch(() => {
setSubmitting(false);
});
};
const handleClose = () => {
closeDialog('payment-number-form');
};
return (
<DialogContent
isLoading={fetchSettings.isFetching}
>
<ReferenceNumberForm
initialNumber={nextNumber}
initialPrefix={numberPrefix}
onSubmit={handleSubmitForm}
onClose={handleClose}
/>
</DialogContent>
);
}
export default compose(
withDialogActions,
withSettingsActions,
withSettings(({ billPaymentSettings }) => ({
nextNumber: billPaymentSettings?.next_number,
numberPrefix: billPaymentSettings?.number_prefix,
})),
withPaymentMadeActions,
)(PaymentNumberDialogContent);

View File

@@ -0,0 +1,28 @@
import React, { lazy } from 'react';
import { FormattedMessage as T } from 'react-intl';
import { Dialog, DialogSuspense } from 'components';
import withDialogRedux from 'components/DialogReduxConnect';
import { compose } from 'utils';
const PaymentNumbereDialogConetnet = lazy(() =>
import('./PaymentNumberDialogContent'),
);
function PaymentNumberDialog({ dialogName, payload = { id: null }, isOpen }) {
return (
<Dialog
name={dialogName}
name={dialogName}
title={<T id={'payment_number_settings'} />}
autoFocus={true}
canEscapeKeyClose={true}
isOpen={isOpen}
>
<DialogSuspense>
<PaymentNumbereDialogConetnet paymentNumberId={payload.id} />
</DialogSuspense>
</Dialog>
);
}
export default compose(withDialogRedux())(PaymentNumberDialog);

View File

@@ -207,7 +207,7 @@ function BillForm({
}, [bill]); }, [bill]);
const formik = useFormik({ const formik = useFormik({
enableReinitialize: true, // enableReinitialize: true,
validationSchema, validationSchema,
initialValues: { initialValues: {
...initialValues, ...initialValues,

View File

@@ -10,6 +10,7 @@ import withAccountsActions from 'containers/Accounts/withAccountsActions';
import withItemsActions from 'containers/Items/withItemsActions'; import withItemsActions from 'containers/Items/withItemsActions';
import withPaymentMadeActions from './withPaymentMadeActions'; import withPaymentMadeActions from './withPaymentMadeActions';
import withBillActions from '../Bill/withBillActions'; import withBillActions from '../Bill/withBillActions';
import withSettingsActions from 'containers/Settings/withSettingsActions';
import { compose } from 'utils'; import { compose } from 'utils';
@@ -27,6 +28,9 @@ function PaymentMade({
requestFetchPaymentMade, requestFetchPaymentMade,
//#withBillActions //#withBillActions
// #withSettingsActions
requestFetchOptions,
}) { }) {
const history = useHistory(); const history = useHistory();
const { id } = useParams(); const { id } = useParams();
@@ -51,6 +55,8 @@ function PaymentMade({
{ enabled: !!id }, { enabled: !!id },
); );
const fetchSettings = useQuery(['settings'], () => requestFetchOptions({}));
const handleFormSubmit = useCallback( const handleFormSubmit = useCallback(
(payload) => { (payload) => {
payload.redirect && history.push('/payment-mades'); payload.redirect && history.push('/payment-mades');
@@ -90,4 +96,5 @@ export default compose(
withAccountsActions, withAccountsActions,
withBillActions, withBillActions,
withPaymentMadeActions, withPaymentMadeActions,
withSettingsActions
)(PaymentMade); )(PaymentMade);

View File

@@ -64,19 +64,7 @@ function PaymentMadeDataTable({
} }
}, [paymentMadeLoading, setInitialMount]); }, [paymentMadeLoading, setInitialMount]);
// useEffect(() => {
// if (customViewId) {
// changeCurrentView(customViewId);
// setTopbarEditView(customViewId);
// }
// changePageSubtitle(customViewId && viewMeta ? viewMeta.name : '');
// }, [
// customViewId,
// changeCurrentView,
// changePageSubtitle,
// setTopbarEditView,
// viewMeta,
// ]);
const handleEditPaymentMade = useCallback( const handleEditPaymentMade = useCallback(
(paymentMade) => () => { (paymentMade) => () => {
@@ -95,9 +83,13 @@ function PaymentMadeDataTable({
const actionMenuList = useCallback( const actionMenuList = useCallback(
(paymentMade) => ( (paymentMade) => (
<Menu> <Menu>
<MenuItem text={formatMessage({ id: 'view_details' })} /> <MenuItem
icon={<Icon icon="reader-18" />}
text={formatMessage({ id: 'view_details' })}
/>
<MenuDivider /> <MenuDivider />
<MenuItem <MenuItem
icon={<Icon icon="pen-18" />}
text={formatMessage({ id: 'edit_payment_made' })} text={formatMessage({ id: 'edit_payment_made' })}
onClick={handleEditPaymentMade(paymentMade)} onClick={handleEditPaymentMade(paymentMade)}
/> />

View File

@@ -28,6 +28,7 @@ import Dragzone from 'components/Dragzone';
import useMedia from 'hooks/useMedia'; import useMedia from 'hooks/useMedia';
import { compose, repeatValue } from 'utils'; import { compose, repeatValue } from 'utils';
import withSettings from 'containers/Settings/withSettings';
const MIN_LINES_NUMBER = 5; const MIN_LINES_NUMBER = 5;
@@ -35,10 +36,18 @@ function PaymentMadeForm({
//#withMedia //#withMedia
requestSubmitMedia, requestSubmitMedia,
requestDeleteMedia, requestDeleteMedia,
//#withPaymentMadesActions
//#withPaymentMadesActions
requestSubmitPaymentMade, requestSubmitPaymentMade,
requestEditPaymentMade, requestEditPaymentMade,
setPaymentNumberChange,
// #withPaymentMade
nextPaymentNumberChanged,
// #withSettings
paymentNextNumber,
paymentNumberPrefix,
//#withDashboard //#withDashboard
changePageTitle, changePageTitle,
@@ -92,7 +101,7 @@ function PaymentMadeForm({
payment_account_id: Yup.number() payment_account_id: Yup.number()
.required() .required()
.label(formatMessage({ id: 'payment_account_' })), .label(formatMessage({ id: 'payment_account_' })),
payment_number: Yup.number() payment_number: Yup.string()
.required() .required()
.label(formatMessage({ id: 'payment_no_' })), .label(formatMessage({ id: 'payment_no_' })),
reference: Yup.string().min(1).max(255).nullable(), reference: Yup.string().min(1).max(255).nullable(),
@@ -133,13 +142,17 @@ function PaymentMadeForm({
[], [],
); );
const paymentNumber = paymentNumberPrefix
? `${paymentNumberPrefix}-${paymentNextNumber}`
: paymentNextNumber;
const defaultInitialValues = useMemo( const defaultInitialValues = useMemo(
() => ({ () => ({
vendor_id: '', vendor_id: '',
payment_account_id: '', payment_account_id: '',
payment_date: moment(new Date()).format('YYYY-MM-DD'), payment_date: moment(new Date()).format('YYYY-MM-DD'),
reference: '', reference: '',
payment_number: '', payment_number: paymentNumber,
// receive_amount: '', // receive_amount: '',
description: '', description: '',
entries: [...repeatValue(defaultPaymentMade, MIN_LINES_NUMBER)], entries: [...repeatValue(defaultPaymentMade, MIN_LINES_NUMBER)],
@@ -188,7 +201,6 @@ function PaymentMadeForm({
}, [paymentMade]); }, [paymentMade]);
const formik = useFormik({ const formik = useFormik({
enableReinitialize: true,
validationSchema, validationSchema,
initialValues: { initialValues: {
...initialValues, ...initialValues,
@@ -282,7 +294,11 @@ function PaymentMadeForm({
orderingIndex([...repeatValue(defaultPaymentMade, MIN_LINES_NUMBER)]), orderingIndex([...repeatValue(defaultPaymentMade, MIN_LINES_NUMBER)]),
); );
}; };
console.log(formik.errors, 'ERROR');
useEffect(() => {
formik.setFieldValue('payment_number', paymentNumber);
setPaymentNumberChange(false);
}, [nextPaymentNumberChanged, paymentNumber]);
return ( return (
<div className={'payment_made_form'}> <div className={'payment_made_form'}>
@@ -291,7 +307,7 @@ function PaymentMadeForm({
<PaymentMadeItemsTable <PaymentMadeItemsTable
formik={formik} formik={formik}
entries={formik.values.entries} entries={formik.values.entries}
// vendor_id={formik.values.vendor_id} vendor_id={formik.values.vendor_id}
onClickAddNewRow={handleClickAddNewRow} onClickAddNewRow={handleClickAddNewRow}
onClickClearAllLines={handleClearAllLines} onClickClearAllLines={handleClearAllLines}
/> />
@@ -317,4 +333,11 @@ export default compose(
withDashboardActions, withDashboardActions,
withMediaActions, withMediaActions,
withPaymentMadeDetail(), withPaymentMadeDetail(),
withPaymentMade(({ nextPaymentNumberChanged }) => ({
nextPaymentNumberChanged,
})),
withSettings(({ billPaymentSettings }) => ({
paymentNextNumber: billPaymentSettings?.next_number,
paymentNumberPrefix: billPaymentSettings?.number_prefix,
})),
)(PaymentMadeForm); )(PaymentMadeForm);

View File

@@ -20,18 +20,24 @@ import {
ListSelect, ListSelect,
ErrorMessage, ErrorMessage,
FieldRequiredHint, FieldRequiredHint,
Icon,
InputPrependButton,
} from 'components'; } from 'components';
import withVender from 'containers/Vendors/withVendors'; import withVender from 'containers/Vendors/withVendors';
import withAccounts from 'containers/Accounts/withAccounts'; import withAccounts from 'containers/Accounts/withAccounts';
import withDialogActions from 'containers/Dialog/withDialogActions';
function PaymentMadeFormHeader({ function PaymentMadeFormHeader({
formik: { errors, touched, setFieldValue, getFieldProps, values }, formik: { errors, touched, setFieldValue, getFieldProps, values },
//#withVender //#withVender
vendorsCurrentPage, vendorsCurrentPage,
vendorItems,
//#withAccouts //#withAccouts
accountsList, accountsList,
// #withDialogActions
openDialog,
}) { }) {
const handleDateChange = useCallback( const handleDateChange = useCallback(
(date_filed) => (date) => { (date_filed) => (date) => {
@@ -79,10 +85,14 @@ function PaymentMadeFormHeader({
[accountsList], [accountsList],
); );
const handlePaymentNumberChange = useCallback(() => {
openDialog('payment-number-form', {});
}, [openDialog]);
return ( return (
<div> <div>
<div> <div>
{/* Vend name */} {/* Vendor name */}
<FormGroup <FormGroup
label={<T id={'vendor_name'} />} label={<T id={'vendor_name'} />}
inline={true} inline={true}
@@ -94,7 +104,7 @@ function PaymentMadeFormHeader({
} }
> >
<ListSelect <ListSelect
items={vendorsCurrentPage} items={vendorItems}
noResults={<MenuItem disabled={true} text="No results." />} noResults={<MenuItem disabled={true} text="No results." />}
itemRenderer={handleVenderRenderer} itemRenderer={handleVenderRenderer}
itemPredicate={handleFilterVender} itemPredicate={handleFilterVender}
@@ -144,6 +154,20 @@ function PaymentMadeFormHeader({
errors.payment_number && touched.payment_number && Intent.DANGER errors.payment_number && touched.payment_number && Intent.DANGER
} }
minimal={true} minimal={true}
rightElement={
<InputPrependButton
buttonProps={{
onClick: handlePaymentNumberChange,
icon: <Icon icon={'settings-18'} />,
}}
tooltip={true}
tooltipProps={{
content: 'Setting your auto-generated payment number',
position: Position.BOTTOM_LEFT,
}}
/>
}
minimal={true}
{...getFieldProps('payment_number')} {...getFieldProps('payment_number')}
/> />
</FormGroup> </FormGroup>
@@ -199,10 +223,12 @@ function PaymentMadeFormHeader({
} }
export default compose( export default compose(
withVender(({ vendorsCurrentPage }) => ({ withVender(({ vendorsCurrentPage, vendorItems }) => ({
vendorsCurrentPage, vendorsCurrentPage,
vendorItems,
})), })),
withAccounts(({ accountsList }) => ({ withAccounts(({ accountsList }) => ({
accountsList, accountsList,
})), })),
withDialogActions,
)(PaymentMadeFormHeader); )(PaymentMadeFormHeader);

View File

@@ -7,7 +7,6 @@ import {
getPaymentMadeTableQuery, getPaymentMadeTableQuery,
} from 'store/PaymentMades/paymentMade.selector'; } from 'store/PaymentMades/paymentMade.selector';
export default (mapState) => { export default (mapState) => {
const getPyamentMadesItems = getPaymentMadeCurrentPageFactory(); const getPyamentMadesItems = getPaymentMadeCurrentPageFactory();
const getPyamentMadesPaginationMeta = getPaymentMadePaginationMetaFactory(); const getPyamentMadesPaginationMeta = getPaymentMadePaginationMetaFactory();
@@ -18,8 +17,14 @@ export default (mapState) => {
paymentMadeViews: getResourceViews(state, props, 'bill_payments'), paymentMadeViews: getResourceViews(state, props, 'bill_payments'),
paymentMadeItems: state.paymentMades.items, paymentMadeItems: state.paymentMades.items,
paymentMadeTableQuery: query, paymentMadeTableQuery: query,
paymentMadePageination: getPyamentMadesPaginationMeta(state, props, query), paymentMadePageination: getPyamentMadesPaginationMeta(
state,
props,
query,
),
paymentMadesLoading: state.paymentMades.loading, paymentMadesLoading: state.paymentMades.loading,
nextPaymentNumberChanged:
state.paymentMades.nextPaymentNumberChanged,
}; };
return mapState ? mapState(mapped, state, props) : mapped; return mapState ? mapState(mapped, state, props) : mapped;
}; };

View File

@@ -27,5 +27,10 @@ const mapDispatchToProps = (dispatch) => ({
type: t.PAYMENT_MADE_TABLE_QUERIES_ADD, type: t.PAYMENT_MADE_TABLE_QUERIES_ADD,
queries, queries,
}), }),
setPaymentNumberChange: (isChanged) =>
dispatch({
type: t.PAYMENT_MADES_NUMBER_CHANGED,
payload: { isChanged },
}),
}); });
export default connect(null, mapDispatchToProps); export default connect(null, mapDispatchToProps);

View File

@@ -21,6 +21,7 @@ import withEstimateActions from './withEstimateActions';
import withEstimateDetail from './withEstimateDetail'; import withEstimateDetail from './withEstimateDetail';
import withDashboardActions from 'containers/Dashboard/withDashboardActions'; import withDashboardActions from 'containers/Dashboard/withDashboardActions';
import withMediaActions from 'containers/Media/withMediaActions'; import withMediaActions from 'containers/Media/withMediaActions';
import withSettings from 'containers/Settings/withSettings';
import AppToaster from 'components/AppToaster'; import AppToaster from 'components/AppToaster';
import Dragzone from 'components/Dragzone'; import Dragzone from 'components/Dragzone';
@@ -43,6 +44,10 @@ const EstimateForm = ({
changePageTitle, changePageTitle,
changePageSubtitle, changePageSubtitle,
// #withSettings
estimateNextNumber,
estimateNumberPrefix,
//#withEstimateDetail //#withEstimateDetail
estimate, estimate,
@@ -92,7 +97,7 @@ const EstimateForm = ({
expiration_date: Yup.date() expiration_date: Yup.date()
.required() .required()
.label(formatMessage({ id: 'expiration_date_' })), .label(formatMessage({ id: 'expiration_date_' })),
estimate_number: Yup.number() estimate_number: Yup.string()
.required() .required()
.nullable() .nullable()
.label(formatMessage({ id: 'estimate_number_' })), .label(formatMessage({ id: 'estimate_number_' })),
@@ -110,18 +115,6 @@ const EstimateForm = ({
entries: Yup.array().of( entries: Yup.array().of(
Yup.object().shape({ Yup.object().shape({
quantity: Yup.number().nullable(), quantity: Yup.number().nullable(),
//Cyclic dependency
rate: Yup.number().nullable(),
// .when(['item_id'], {
// is: (item_id) => item_id,
// then: Yup.number().required(),
// }),
// rate: Yup.number().test((value) => {
// const { item_id } = this.parent;
// if (!item_id) return value != null;
// return false;
// }),
item_id: Yup.number() item_id: Yup.number()
.nullable() .nullable()
.when(['quantity', 'rate'], { .when(['quantity', 'rate'], {
@@ -152,13 +145,16 @@ const EstimateForm = ({
}), }),
[], [],
); );
const estimateNumber = estimateNumberPrefix
? `${estimateNumberPrefix}-${estimateNextNumber}`
: estimateNextNumber;
const defaultInitialValues = useMemo( const defaultInitialValues = useMemo(
() => ({ () => ({
customer_id: '', customer_id: '',
estimate_date: moment(new Date()).format('YYYY-MM-DD'), estimate_date: moment(new Date()).format('YYYY-MM-DD'),
expiration_date: moment(new Date()).format('YYYY-MM-DD'), expiration_date: moment(new Date()).format('YYYY-MM-DD'),
estimate_number: '', estimate_number: estimateNumber,
reference: '', reference: '',
note: '', note: '',
terms_conditions: '', terms_conditions: '',
@@ -208,7 +204,6 @@ const EstimateForm = ({
}, [estimate]); }, [estimate]);
const formik = useFormik({ const formik = useFormik({
enableReinitialize: true,
validationSchema, validationSchema,
initialValues: { initialValues: {
...initialValues, ...initialValues,
@@ -226,9 +221,12 @@ const EstimateForm = ({
if (estimate && estimate.id) { if (estimate && estimate.id) {
requestEditEstimate(estimate.id, requestForm).then((response) => { requestEditEstimate(estimate.id, requestForm).then((response) => {
AppToaster.show({ AppToaster.show({
message: formatMessage({ message: formatMessage(
id: 'the_estimate_has_been_successfully_edited', {
}), id: 'the_estimate_has_been_successfully_edited',
},
{ number: values.estimate_number },
),
intent: Intent.SUCCESS, intent: Intent.SUCCESS,
}); });
setSubmitting(false); setSubmitting(false);
@@ -255,7 +253,11 @@ const EstimateForm = ({
} }
}, },
}); });
console.log(formik.errors ,'ERROR');
useEffect(() => {
formik.setFieldValue('estimate_number', estimateNumber);
}, [estimateNumber]);
const handleSubmitClick = useCallback( const handleSubmitClick = useCallback(
(payload) => { (payload) => {
setPayload(payload); setPayload(payload);
@@ -353,7 +355,11 @@ const EstimateForm = ({
export default compose( export default compose(
withEstimateActions, withEstimateActions,
withEstimateDetail(),
withDashboardActions, withDashboardActions,
withMediaActions, withMediaActions,
withEstimateDetail(), withSettings(({ estimatesSettings }) => ({
estimateNextNumber: estimatesSettings?.next_number,
estimateNumberPrefix: estimatesSettings?.number_prefix,
})),
)(EstimateForm); )(EstimateForm);

View File

@@ -13,15 +13,24 @@ import { Row, Col } from 'react-grid-system';
import moment from 'moment'; import moment from 'moment';
import { momentFormatter, compose, tansformDateValue } from 'utils'; import { momentFormatter, compose, tansformDateValue } from 'utils';
import classNames from 'classnames'; import classNames from 'classnames';
import { ListSelect, ErrorMessage, FieldRequiredHint, Hint } from 'components'; import {
ListSelect,
ErrorMessage,
FieldRequiredHint,
Icon,
InputPrependButton,
} from 'components';
import withCustomers from 'containers/Customers/withCustomers'; import withCustomers from 'containers/Customers/withCustomers';
import withDialogActions from 'containers/Dialog/withDialogActions';
function EstimateFormHeader({ function EstimateFormHeader({
formik: { errors, touched, setFieldValue, getFieldProps, values }, formik: { errors, touched, setFieldValue, getFieldProps, values },
//#withCustomers //#withCustomers
customers, customers,
// #withDialogActions
openDialog,
}) { }) {
const handleDateChange = useCallback( const handleDateChange = useCallback(
(date_filed) => (date) => { (date_filed) => (date) => {
@@ -67,6 +76,10 @@ function EstimateFormHeader({
[setFieldValue], [setFieldValue],
); );
const handleEstimateNumberChange = useCallback(() => {
openDialog('estimate-number-form', {});
}, [openDialog]);
return ( return (
<div className={'page-form page-form--estimate'}> <div className={'page-form page-form--estimate'}>
<div className={'page-form__primary-section'}> <div className={'page-form__primary-section'}>
@@ -171,6 +184,19 @@ function EstimateFormHeader({
errors.estimate_number && touched.estimate_number && Intent.DANGER errors.estimate_number && touched.estimate_number && Intent.DANGER
} }
minimal={true} minimal={true}
rightElement={
<InputPrependButton
buttonProps={{
onClick: handleEstimateNumberChange,
icon: <Icon icon={'settings-18'} />,
}}
tooltip={true}
tooltipProps={{
content: 'Setting your auto-generated estimate number',
position: Position.BOTTOM_LEFT,
}}
/>
}
{...getFieldProps('estimate_number')} {...getFieldProps('estimate_number')}
/> />
</FormGroup> </FormGroup>
@@ -196,4 +222,5 @@ export default compose(
withCustomers(({ customers }) => ({ withCustomers(({ customers }) => ({
customers, customers,
})), })),
withDialogActions,
)(EstimateFormHeader); )(EstimateFormHeader);

View File

@@ -42,15 +42,15 @@ function EstimateList({
const [deleteEstimate, setDeleteEstimate] = useState(false); const [deleteEstimate, setDeleteEstimate] = useState(false);
const [selectedRows, setSelectedRows] = useState([]); const [selectedRows, setSelectedRows] = useState([]);
const fetchResourceViews = useQuery( // const fetchResourceViews = useQuery(
['resource-views', 'sales_estimates'], // ['resource-views', 'sales_estimates'],
(key, resourceName) => requestFetchResourceViews(resourceName), // (key, resourceName) => requestFetchResourceViews(resourceName),
); // );
const fetchResourceFields = useQuery( // const fetchResourceFields = useQuery(
['resource-fields', 'sales_estimates'], // ['resource-fields', 'sales_estimates'],
(key, resourceName) => requestFetchResourceFields(resourceName), // (key, resourceName) => requestFetchResourceFields(resourceName),
); // );
const fetchEstimate = useQuery(['estimates-table', estimateTableQuery], () => const fetchEstimate = useQuery(['estimates-table', estimateTableQuery], () =>
requestFetchEstimatesTable(), requestFetchEstimatesTable(),
@@ -86,16 +86,6 @@ function EstimateList({
}); });
}, [deleteEstimate, requestDeleteEstimate, formatMessage]); }, [deleteEstimate, requestDeleteEstimate, formatMessage]);
// // Handle filter change to re-fetch data-table.
// const handleFilterChanged = useCallback(
// (filterConditions) => {
// addEstimatesTableQueries({
// filter_roles: filterConditions || '',
// });
// },
// [fetchEstimate],
// );
// Handle filter change to re-fetch data-table. // Handle filter change to re-fetch data-table.
const handleFilterChanged = useCallback(() => {}, [fetchEstimate]); const handleFilterChanged = useCallback(() => {}, [fetchEstimate]);
@@ -136,7 +126,7 @@ function EstimateList({
); );
return ( return (
<DashboardInsider <DashboardInsider
loading={fetchResourceViews.isFetching || fetchResourceFields.isFetching} // loading={fetchResourceViews.isFetching || fetchResourceFields.isFetching}
name={'sales_estimates'} name={'sales_estimates'}
> >
<EstimateActionsBar <EstimateActionsBar

View File

@@ -8,13 +8,22 @@ import DashboardInsider from 'components/Dashboard/DashboardInsider';
import withCustomersActions from 'containers/Customers/withCustomersActions'; import withCustomersActions from 'containers/Customers/withCustomersActions';
import withItemsActions from 'containers/Items/withItemsActions'; import withItemsActions from 'containers/Items/withItemsActions';
import withEstimateActions from './withEstimateActions'; import withEstimateActions from './withEstimateActions';
import withSettingsActions from 'containers/Settings/withSettingsActions';
import { compose } from 'utils'; import { compose } from 'utils';
function Estimates({ function Estimates({
// #withCustomersActions
requestFetchCustomers, requestFetchCustomers,
// #withItemsActions
requestFetchItems, requestFetchItems,
// #withEstimateActions
requsetFetchEstimate, requsetFetchEstimate,
// #withSettingsActions
requestFetchOptions,
}) { }) {
const history = useHistory(); const history = useHistory();
const { id } = useParams(); const { id } = useParams();
@@ -44,6 +53,8 @@ function Estimates({
history.goBack(); history.goBack();
}, [history]); }, [history]);
const fetchSettings = useQuery(['settings'], () => requestFetchOptions({}));
return ( return (
<DashboardInsider <DashboardInsider
loading={ loading={
@@ -66,4 +77,5 @@ export default compose(
withEstimateActions, withEstimateActions,
withCustomersActions, withCustomersActions,
withItemsActions, withItemsActions,
withSettingsActions,
)(Estimates); )(Estimates);

View File

@@ -94,9 +94,13 @@ function EstimatesDataTable({
const actionMenuList = useCallback( const actionMenuList = useCallback(
(estimate) => ( (estimate) => (
<Menu> <Menu>
<MenuItem text={formatMessage({ id: 'view_details' })} /> <MenuItem
icon={<Icon icon="reader-18" />}
text={formatMessage({ id: 'view_details' })}
/>
<MenuDivider /> <MenuDivider />
<MenuItem <MenuItem
icon={<Icon icon="pen-18" />}
text={formatMessage({ id: 'edit_estimate' })} text={formatMessage({ id: 'edit_estimate' })}
onClick={handleEditEstimate(estimate)} onClick={handleEditEstimate(estimate)}
/> />

View File

@@ -6,6 +6,8 @@ export default (mapState) => {
organizationSettings: state.settings.data.organization, organizationSettings: state.settings.data.organization,
manualJournalsSettings: state.settings.data.manual_journals, manualJournalsSettings: state.settings.data.manual_journals,
billsettings: state.settings.data.bills, billsettings: state.settings.data.bills,
billPaymentSettings: state.settings.data.bill_payments,
estimatesSettings: state.settings.data.sales_estimates,
}; };
return mapState ? mapState(mapped, state, props) : mapped; return mapState ? mapState(mapped, state, props) : mapped;
}; };

View File

@@ -776,6 +776,8 @@ export default {
bigger_or_equals: 'Bigger or equals', bigger_or_equals: 'Bigger or equals',
prefix: 'Prefix', prefix: 'Prefix',
next_number: 'Next Number', next_number: 'Next Number',
journal_number_settings: 'Journal number settings', journal_number_settings: 'Journal number Settings',
bill_number_settings: 'Bill number settings', bill_number_settings: 'Bill number Settings',
payment_number_settings: 'Payment number Settings',
Estimate_number_settings: 'Estimate Number Settings',
}; };

View File

@@ -80,9 +80,8 @@ const reducer = createReducer(initialState, {
[t.BILLS_PAGINATION_SET]: (state, action) => { [t.BILLS_PAGINATION_SET]: (state, action) => {
const { pagination, customViewId } = action.payload; const { pagination, customViewId } = action.payload;
const mapped = { const mapped = {
pageSize: parseInt(pagination.pageSize, 10), pageSize: parseInt(pagination.page_size, 10),
page: parseInt(pagination.page, 10), page: parseInt(pagination.page, 10),
total: parseInt(pagination.total, 10), total: parseInt(pagination.total, 10),
}; };

View File

@@ -6,17 +6,12 @@ export const submitEstimate = ({ form }) => {
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
ApiService.post('sales/estimates', form) ApiService.post('sales/estimates', form)
.then((response) => { .then((response) => {
dispatch({
type: t.SET_DASHBOARD_REQUEST_COMPLETED,
});
resolve(response); resolve(response);
}) })
.catch((error) => { .catch((error) => {
const { response } = error; const { response } = error;
const { data } = response; const { data } = response;
dispatch({
type: t.SET_DASHBOARD_REQUEST_COMPLETED,
});
reject(data?.errors); reject(data?.errors);
}); });
}); });
@@ -95,21 +90,21 @@ export const fetchEstimatesTable = ({ query = {} }) => {
dispatch({ dispatch({
type: t.ESTIMATES_PAGE_SET, type: t.ESTIMATES_PAGE_SET,
payload: { payload: {
sales_estimates: response.data.sales_estimates.results, sales_estimates: response.data.sales_estimates,
pagination: response.data.sales_estimates.pagination, pagination: response.data.pagination,
customViewId: response.data.customViewId || -1, customViewId: response.data.customViewId || -1,
}, },
}); });
dispatch({ dispatch({
type: t.ESTIMATES_ITEMS_SET, type: t.ESTIMATES_ITEMS_SET,
payload: { payload: {
sales_estimates: response.data.sales_estimates.results, sales_estimates: response.data.sales_estimates,
}, },
}); });
dispatch({ dispatch({
type: t.ESTIMATES_PAGINATION_SET, type: t.ESTIMATES_PAGINATION_SET,
payload: { payload: {
pagination: response.data.sales_estimates.pagination, pagination: response.data.pagination,
customViewId: response.data.customViewId || -1, customViewId: response.data.customViewId || -1,
}, },
}); });

View File

@@ -65,21 +65,21 @@ export const fetchPaymentMadesTable = ({ query = {} }) => {
dispatch({ dispatch({
type: t.PAYMENT_MADES_PAGE_SET, type: t.PAYMENT_MADES_PAGE_SET,
payload: { payload: {
bill_payments: response.data.bill_payments.results, bill_payments: response.data.bill_payments,
pagination: response.data.bill_payments.pagination, pagination: response.data.pagination,
customViewId: response.data.customViewId || -1, customViewId: response.data.customViewId || -1,
}, },
}); });
dispatch({ dispatch({
type: t.PAYMENT_MADES_ITEMS_SET, type: t.PAYMENT_MADES_ITEMS_SET,
payload: { payload: {
bill_payments: response.data.bill_payments.results, bill_payments: response.data.bill_payments,
}, },
}); });
dispatch({ dispatch({
type: t.PAYMENT_MADES_PAGINATION_SET, type: t.PAYMENT_MADES_PAGINATION_SET,
payload: { payload: {
pagination: response.data.bill_payments.pagination, pagination: response.data.pagination,
customViewId: response.data.customViewId || -1, customViewId: response.data.customViewId || -1,
}, },
}); });
@@ -102,14 +102,6 @@ export const fetchPaymentMade = ({ id }) => {
new Promise((resovle, reject) => { new Promise((resovle, reject) => {
ApiService.get(`purchases/bill_payments/${id}`, {}) ApiService.get(`purchases/bill_payments/${id}`, {})
.then((response) => { .then((response) => {
// dispatch({
// type: t.RELOAD_INVOICES,
// payload: {
// sales_invoices: response.data.paymentReceive.entries.map(
// (e) => e.invoice,
// ),
// },
// });
dispatch({ dispatch({
type: t.PAYMENT_MADE_SET, type: t.PAYMENT_MADE_SET,
payload: { payload: {

View File

@@ -12,6 +12,7 @@ const initialState = {
page_size: 5, page_size: 5,
page: 1, page: 1,
}, },
nextPaymentNumberChanged: false,
}; };
const defaultPaymentMade = { const defaultPaymentMade = {
@@ -84,5 +85,11 @@ const reducer = createReducer(initialState, {
}, },
}; };
}, },
[t.PAYMENT_MADES_NUMBER_CHANGED]:(state,action)=>{
const { isChanged } = action.payload;
state.nextPaymentNumberChanged = isChanged
}
}); });
export default createTableQueryReducers('bill_payments', reducer); export default createTableQueryReducers('bill_payments', reducer);

View File

@@ -8,4 +8,5 @@ export default {
PAYMENT_MADES_PAGE_SET: 'PAYMENT_MADES_PAGE_SET', PAYMENT_MADES_PAGE_SET: 'PAYMENT_MADES_PAGE_SET',
PAYMENT_MADES_ITEMS_SET: 'PAYMENT_MADES_ITEMS_SET', PAYMENT_MADES_ITEMS_SET: 'PAYMENT_MADES_ITEMS_SET',
PAYMENT_MADES_PAGINATION_SET: 'PAYMENT_MADES_PAGINATION_SET', PAYMENT_MADES_PAGINATION_SET: 'PAYMENT_MADES_PAGINATION_SET',
PAYMENT_MADES_NUMBER_CHANGED:'PAYMENT_MADES_NUMBER_CHANGED'
}; };

View File

@@ -63,4 +63,24 @@ export default {
type: "string", type: "string",
}, },
], ],
bill_payments: [
{
key: "next_number",
type: "number",
},
{
key: "number_prefix",
type: "string",
},
],
sales_estimates: [
{
key: "next_number",
type: "number",
},
{
key: "number_prefix",
type: "string",
},
],
}; };