From 3ab6c4da2a6dce1de44bd732c17b14fbe7a0fa5c Mon Sep 17 00:00:00 2001 From: elforjani3 Date: Sun, 8 Nov 2020 17:30:11 +0200 Subject: [PATCH 1/2] Fix : Estimate-Number-Dialog --- .../EstimateNumberDialogContent.js | 6 +++ .../containers/Sales/Estimate/EstimateForm.js | 45 ++++++++++++++++--- .../Sales/Estimate/EstimateFormHeader.js | 15 ++++++- .../Sales/Estimate/withEstimateActions.js | 5 +++ .../Sales/Estimate/withEstimates.js | 5 ++- .../src/store/Estimate/estimates.reducer.js | 5 +++ client/src/store/Estimate/estimates.types.js | 4 +- 7 files changed, 73 insertions(+), 12 deletions(-) diff --git a/client/src/containers/Dialogs/EstimateNumberDialog/EstimateNumberDialogContent.js b/client/src/containers/Dialogs/EstimateNumberDialog/EstimateNumberDialogContent.js index b62bafe2c..ca2feede4 100644 --- a/client/src/containers/Dialogs/EstimateNumberDialog/EstimateNumberDialogContent.js +++ b/client/src/containers/Dialogs/EstimateNumberDialog/EstimateNumberDialogContent.js @@ -5,6 +5,7 @@ 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 withEstimateActions from 'containers/Sales/Estimate/withEstimateActions'; import withSettings from 'containers/Settings/withSettings'; import { compose, optionsMapToArray } from 'utils'; @@ -23,6 +24,9 @@ function EstimateNumberDialogContent({ // #withDialogActions closeDialog, + + // #withEstimateActions + setEstimateNumberChanged, }) { const fetchSettings = useQuery(['settings'], () => requestFetchOptions({})); @@ -37,6 +41,7 @@ function EstimateNumberDialogContent({ setTimeout(() => { queryCache.invalidateQueries('settings'); + setEstimateNumberChanged(true); }, 250); }) .catch(() => { @@ -67,4 +72,5 @@ export default compose( nextNumber: estimatesSettings?.next_number, numberPrefix: estimatesSettings?.number_prefix, })), + withEstimateActions, )(EstimateNumberDialogContent); diff --git a/client/src/containers/Sales/Estimate/EstimateForm.js b/client/src/containers/Sales/Estimate/EstimateForm.js index 78f065584..c696bf93b 100644 --- a/client/src/containers/Sales/Estimate/EstimateForm.js +++ b/client/src/containers/Sales/Estimate/EstimateForm.js @@ -20,6 +20,7 @@ import EstimateFloatingActions from './EstimateFloatingActions'; import withEstimateActions from './withEstimateActions'; import withEstimateDetail from './withEstimateDetail'; +import withEstimates from './withEstimates'; import withDashboardActions from 'containers/Dashboard/withDashboardActions'; import withMediaActions from 'containers/Media/withMediaActions'; import withSettings from 'containers/Settings/withSettings'; @@ -41,7 +42,7 @@ const EstimateForm = ({ //#WithEstimateActions requestSubmitEstimate, requestEditEstimate, - + setEstimateNumberChanged, //#withDashboard changePageTitle, changePageSubtitle, @@ -53,6 +54,9 @@ const EstimateForm = ({ //#withEstimateDetail estimate, + // #withEstimates + estimateNumberChanged, + //#own Props estimateId, onFormSubmit, @@ -81,10 +85,16 @@ const EstimateForm = ({ savedMediaIds.current = []; }; + const estimateNumber = estimateNumberPrefix + ? `${estimateNumberPrefix}-${estimateNextNumber}` + : estimateNextNumber; + useEffect(() => { if (estimate && estimate.id) { changePageTitle(formatMessage({ id: 'edit_estimate' })); + changePageSubtitle(`No. ${estimate.estimate_number}`); } else { + changePageSubtitle(`No. ${estimateNumber}`); changePageTitle(formatMessage({ id: 'new_estimate' })); } }, [changePageTitle, estimate, formatMessage]); @@ -153,9 +163,6 @@ const EstimateForm = ({ }), [], ); - const estimateNumber = estimateNumberPrefix - ? `${estimateNumberPrefix}-${estimateNextNumber}` - : estimateNextNumber; const defaultInitialValues = useMemo( () => ({ @@ -290,9 +297,20 @@ const EstimateForm = ({ } }, }); + useEffect(() => { - formik.setFieldValue('estimate_number', estimateNumber); - }, [estimateNumber]); + if (estimateNumberChanged) { + formik.setFieldValue('estimate_number', estimateNumber); + changePageSubtitle(`No. ${estimateNumber}`); + setEstimateNumberChanged(false); + } + }, [ + estimateNumber, + estimateNumberChanged, + setEstimateNumberChanged, + formik.setFieldValue, + changePageSubtitle, + ]); const handleSubmitClick = useCallback( (payload) => { @@ -336,10 +354,20 @@ const EstimateForm = ({ ); }; + const handleEstimateNumberChange = useCallback( + (estimateNumber) => { + changePageSubtitle(`No. ${estimateNumber}`); + }, + [changePageSubtitle], + ); + return (
- + ({ + estimateNumberChanged, + })), )(EstimateForm); diff --git a/client/src/containers/Sales/Estimate/EstimateFormHeader.js b/client/src/containers/Sales/Estimate/EstimateFormHeader.js index 1cbfdc8d4..eb5b6d40f 100644 --- a/client/src/containers/Sales/Estimate/EstimateFormHeader.js +++ b/client/src/containers/Sales/Estimate/EstimateFormHeader.js @@ -10,7 +10,7 @@ import { import { DateInput } from '@blueprintjs/datetime'; import { FormattedMessage as T } from 'react-intl'; import moment from 'moment'; -import { momentFormatter, compose, tansformDateValue } from 'utils'; +import { momentFormatter, compose, tansformDateValue, saveInvoke } from 'utils'; import classNames from 'classnames'; import { CLASSES } from 'common/classes'; import { @@ -33,6 +33,8 @@ function EstimateFormHeader({ customers, // #withDialogActions openDialog, + // #ownProps + onEstimateNumberChanged, }) { const handleDateChange = useCallback( (date_filed) => (date) => { @@ -67,9 +69,14 @@ function EstimateFormHeader({ openDialog('estimate-number-form', {}); }, [openDialog]); + const handleEstimateNumberChanged = (event) => { + saveInvoke(onEstimateNumberChanged, event.currentTarget.value); + }; + return (
+ {/* ----------- Customer name ----------- */} } inline={true} @@ -94,6 +101,7 @@ function EstimateFormHeader({ + {/* ----------- Estimate date ----------- */} } inline={true} @@ -119,6 +127,7 @@ function EstimateFormHeader({ + {/* ----------- Expiration date ----------- */} } inline={true} @@ -146,7 +155,7 @@ function EstimateFormHeader({ - {/*- Estimate -*/} + {/* ----------- Estimate number ----------- */} } inline={true} @@ -178,9 +187,11 @@ function EstimateFormHeader({ /> } {...getFieldProps('estimate_number')} + onBlur={handleEstimateNumberChanged} /> + {/* ----------- Reference ----------- */} } inline={true} diff --git a/client/src/containers/Sales/Estimate/withEstimateActions.js b/client/src/containers/Sales/Estimate/withEstimateActions.js index 4f9e43ce5..411437256 100644 --- a/client/src/containers/Sales/Estimate/withEstimateActions.js +++ b/client/src/containers/Sales/Estimate/withEstimateActions.js @@ -27,6 +27,11 @@ const mapDipatchToProps = (dispatch) => ({ type: t.ESTIMATES_TABLE_QUERIES_ADD, queries, }), + setEstimateNumberChanged: (isChanged) => + dispatch({ + type: t.ESTIMATE_NUMBER_CHANGED, + payload: { isChanged }, + }), }); export default connect(null, mapDipatchToProps); diff --git a/client/src/containers/Sales/Estimate/withEstimates.js b/client/src/containers/Sales/Estimate/withEstimates.js index b208206fa..a27aa83d3 100644 --- a/client/src/containers/Sales/Estimate/withEstimates.js +++ b/client/src/containers/Sales/Estimate/withEstimates.js @@ -13,14 +13,17 @@ export default (mapState) => { const mapStateToProps = (state, props) => { const query = getEstimatesTableQuery(state, props); - + const mapped = { estimatesCurrentPage: getEstimatesItems(state, props, query), estimateViews: getResourceViews(state, props, 'sales_estimates'), estimateItems: state.salesEstimates.items, estimateTableQuery: query, + estimatesPageination: getEstimatesPaginationMeta(state, props, query), estimatesLoading: state.salesEstimates.loading, + + estimateNumberChanged: state.salesEstimates.estimateNumberChanged, }; return mapState ? mapState(mapped, state, props) : mapped; }; diff --git a/client/src/store/Estimate/estimates.reducer.js b/client/src/store/Estimate/estimates.reducer.js index 55b6604f3..8171b5739 100644 --- a/client/src/store/Estimate/estimates.reducer.js +++ b/client/src/store/Estimate/estimates.reducer.js @@ -1,5 +1,6 @@ import { createReducer } from '@reduxjs/toolkit'; import { createTableQueryReducers } from 'store/queryReducers'; +import { journalNumberChangedReducer } from 'store/journalNumber.reducer'; import t from 'store/types'; @@ -12,6 +13,8 @@ const initialState = { page: 1, }, currentViewId: -1, + + estimateNumberChanged: false, }; const defaultEstimate = { @@ -98,6 +101,8 @@ const reducer = createReducer(initialState, { }, }; }, + + ...journalNumberChangedReducer(t.ESTIMATE_NUMBER_CHANGED), }); export default createTableQueryReducers('sales_estimates', reducer); diff --git a/client/src/store/Estimate/estimates.types.js b/client/src/store/Estimate/estimates.types.js index 5eb1bb7a1..357b9c955 100644 --- a/client/src/store/Estimate/estimates.types.js +++ b/client/src/store/Estimate/estimates.types.js @@ -8,6 +8,6 @@ export default { ESTIMATES_TABLE_LOADING: 'ESTIMATES_TABLE_LOADING', ESTIMATES_PAGINATION_SET: 'ESTIMATES_PAGINATION_SET', ESTIMATES_PAGE_SET: 'ESTIMATES_PAGE_SET', - ESTIMATES_ITEMS_SET:'ESTIMATES_ITEMS_SET', - + ESTIMATES_ITEMS_SET: 'ESTIMATES_ITEMS_SET', + ESTIMATE_NUMBER_CHANGED: 'ESTIMATE_NUMBER_CHANGED', }; From 6c8ff2084741efb1ce52bbaf065647fd2d1778cb Mon Sep 17 00:00:00 2001 From: elforjani3 Date: Sun, 8 Nov 2020 21:19:54 +0200 Subject: [PATCH 2/2] Fix : Auto-Increment Dialog --- .../EstimateNumberDialogContent.js | 12 ++-- .../InvoiceNumberDialogContent.js | 21 ++++--- .../Dialogs/InvoiceNumberDialog/index.js | 2 +- .../ReceiptNumberDialogContent.js | 18 ++++-- .../containers/Sales/Estimate/EstimateForm.js | 11 +++- .../Sales/Estimate/withEstimates.js | 2 +- .../containers/Sales/Invoice/InvoiceForm.js | 61 ++++++++++++++----- .../Sales/Invoice/InvoiceFormHeader.js | 22 +++---- .../Sales/Invoice/withInvoiceActions.js | 5 ++ .../containers/Sales/Invoice/withInvoices.js | 9 ++- .../containers/Sales/Receipt/ReceiptForm.js | 56 ++++++++++++++--- .../Sales/Receipt/ReceiptFormHeader.js | 30 +++++---- .../Sales/Receipt/withReceiptActions.js | 6 +- .../containers/Sales/Receipt/withReceipts.js | 5 +- .../src/store/Estimate/estimates.reducer.js | 3 +- client/src/store/Invoice/invoices.reducer.js | 5 +- client/src/store/Invoice/invoices.types.js | 4 +- client/src/store/receipt/receipt.reducer.js | 4 +- client/src/store/receipt/receipt.type.js | 1 + 19 files changed, 194 insertions(+), 83 deletions(-) diff --git a/client/src/containers/Dialogs/EstimateNumberDialog/EstimateNumberDialogContent.js b/client/src/containers/Dialogs/EstimateNumberDialog/EstimateNumberDialogContent.js index ca2feede4..fda4a8d68 100644 --- a/client/src/containers/Dialogs/EstimateNumberDialog/EstimateNumberDialogContent.js +++ b/client/src/containers/Dialogs/EstimateNumberDialog/EstimateNumberDialogContent.js @@ -1,12 +1,12 @@ -import React from 'react'; +import React, { useCallback } 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 withSettings from 'containers/Settings/withSettings'; import withSettingsActions from 'containers/Settings/withSettingsActions'; import withEstimateActions from 'containers/Sales/Estimate/withEstimateActions'; -import withSettings from 'containers/Settings/withSettings'; import { compose, optionsMapToArray } from 'utils'; @@ -49,9 +49,9 @@ function EstimateNumberDialogContent({ }); }; - const handleClose = () => { + const handleClose = useCallback(() => { closeDialog('estimate-number-form'); - }; + }, [closeDialog]); return ( @@ -69,8 +69,8 @@ export default compose( withDialogActions, withSettingsActions, withSettings(({ estimatesSettings }) => ({ - nextNumber: estimatesSettings?.next_number, - numberPrefix: estimatesSettings?.number_prefix, + nextNumber: estimatesSettings?.nextNumber, + numberPrefix: estimatesSettings?.numberPrefix, })), withEstimateActions, )(EstimateNumberDialogContent); diff --git a/client/src/containers/Dialogs/InvoiceNumberDialog/InvoiceNumberDialogContent.js b/client/src/containers/Dialogs/InvoiceNumberDialog/InvoiceNumberDialogContent.js index 5282a0226..33783df40 100644 --- a/client/src/containers/Dialogs/InvoiceNumberDialog/InvoiceNumberDialogContent.js +++ b/client/src/containers/Dialogs/InvoiceNumberDialog/InvoiceNumberDialogContent.js @@ -1,12 +1,13 @@ -import React from 'react'; +import React, { useCallback } 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 withSettingsActions from 'containers/Settings/withSettingsActions'; +import withInvoicesActions from 'containers/Sales/Invoice/withInvoiceActions'; import { compose, optionsMapToArray } from 'utils'; @@ -25,6 +26,9 @@ function InvoiceNumberDialogContent({ // #withDialogActions closeDialog, + + // #withInvoicesActions + setInvoiceNumberChanged, }) { const fetchSettings = useQuery(['settings'], () => requestFetchOptions({})); @@ -40,6 +44,7 @@ function InvoiceNumberDialogContent({ setTimeout(() => { queryCache.invalidateQueries('settings'); + setInvoiceNumberChanged(true); }, 250); }) .catch(() => { @@ -47,9 +52,9 @@ function InvoiceNumberDialogContent({ }); }; - const handleClose = () => { + const handleClose = useCallback(() => { closeDialog('invoice-number-form'); - }; + }, [closeDialog]); return ( @@ -67,8 +72,8 @@ export default compose( withDialogActions, withSettingsActions, withSettings(({ invoiceSettings }) => ({ - nextNumber: invoiceSettings?.next_number, - numberPrefix: invoiceSettings?.number_prefix, + nextNumber: invoiceSettings?.nextNumber, + numberPrefix: invoiceSettings?.numberPrefix, })), - -) (InvoiceNumberDialogContent); + withInvoicesActions, +)(InvoiceNumberDialogContent); diff --git a/client/src/containers/Dialogs/InvoiceNumberDialog/index.js b/client/src/containers/Dialogs/InvoiceNumberDialog/index.js index 78a44194a..bac958bd3 100644 --- a/client/src/containers/Dialogs/InvoiceNumberDialog/index.js +++ b/client/src/containers/Dialogs/InvoiceNumberDialog/index.js @@ -11,7 +11,7 @@ const InvoiceNumberDialogContent = lazy(() => function InvoiceNumberDialog({ dialogName, payload = { id: null }, isOpen }) { return ( } + title={} name={dialogName} autoFocus={true} canEscapeKeyClose={true} diff --git a/client/src/containers/Dialogs/ReceiptNumberDialog/ReceiptNumberDialogContent.js b/client/src/containers/Dialogs/ReceiptNumberDialog/ReceiptNumberDialogContent.js index 701056e49..39eee1f0d 100644 --- a/client/src/containers/Dialogs/ReceiptNumberDialog/ReceiptNumberDialogContent.js +++ b/client/src/containers/Dialogs/ReceiptNumberDialog/ReceiptNumberDialogContent.js @@ -1,12 +1,13 @@ -import React from 'react'; +import React, { useCallback } 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 withSettingsActions from 'containers/Settings/withSettingsActions'; +import withReceiptActions from 'containers/Sales/Receipt/withReceiptActions'; import { compose, optionsMapToArray } from 'utils'; @@ -25,6 +26,9 @@ function ReceiptNumberDialogContent({ // #withDialogActions closeDialog, + + // #withReceiptActions + setReceiptNumberChanged, }) { const fetchSettings = useQuery(['settings'], () => requestFetchOptions({})); @@ -40,6 +44,7 @@ function ReceiptNumberDialogContent({ setTimeout(() => { queryCache.invalidateQueries('settings'); + setReceiptNumberChanged(true); }, 250); }) .catch(() => { @@ -47,9 +52,9 @@ function ReceiptNumberDialogContent({ }); }; - const handleClose = () => { + const handleClose = useCallback(() => { closeDialog('receipt-number-form'); - }; + }, [closeDialog]); return ( @@ -67,7 +72,8 @@ export default compose( withDialogActions, withSettingsActions, withSettings(({ receiptSettings }) => ({ - nextNumber: receiptSettings?.next_number, - numberPrefix: receiptSettings?.number_prefix, + nextNumber: receiptSettings?.nextNumber, + numberPrefix: receiptSettings?.numberPrefix, })), + withReceiptActions, )(ReceiptNumberDialogContent); diff --git a/client/src/containers/Sales/Estimate/EstimateForm.js b/client/src/containers/Sales/Estimate/EstimateForm.js index c696bf93b..dbd8250f8 100644 --- a/client/src/containers/Sales/Estimate/EstimateForm.js +++ b/client/src/containers/Sales/Estimate/EstimateForm.js @@ -18,9 +18,10 @@ import EstimateFormHeader from './EstimateFormHeader'; import EntriesItemsTable from './EntriesItemsTable'; import EstimateFloatingActions from './EstimateFloatingActions'; +import withEstimates from './withEstimates'; import withEstimateActions from './withEstimateActions'; import withEstimateDetail from './withEstimateDetail'; -import withEstimates from './withEstimates'; + import withDashboardActions from 'containers/Dashboard/withDashboardActions'; import withMediaActions from 'containers/Media/withMediaActions'; import withSettings from 'containers/Settings/withSettings'; @@ -34,6 +35,10 @@ import { compose, repeatValue } from 'utils'; const MIN_LINES_NUMBER = 4; +/** + * Estimate form. + */ + const EstimateForm = ({ //#WithMedia requestSubmitMedia, @@ -43,6 +48,7 @@ const EstimateForm = ({ requestSubmitEstimate, requestEditEstimate, setEstimateNumberChanged, + //#withDashboard changePageTitle, changePageSubtitle, @@ -378,6 +384,7 @@ const EstimateForm = ({
+ {/* --------- Customer Note --------- */} } className={'form-group--customer_note'} @@ -387,7 +394,7 @@ const EstimateForm = ({ {...formik.getFieldProps('note')} /> - + {/* --------- Terms and conditions --------- */} } className={'form-group--terms_conditions'} diff --git a/client/src/containers/Sales/Estimate/withEstimates.js b/client/src/containers/Sales/Estimate/withEstimates.js index a27aa83d3..9d637e4b6 100644 --- a/client/src/containers/Sales/Estimate/withEstimates.js +++ b/client/src/containers/Sales/Estimate/withEstimates.js @@ -23,7 +23,7 @@ export default (mapState) => { estimatesPageination: getEstimatesPaginationMeta(state, props, query), estimatesLoading: state.salesEstimates.loading, - estimateNumberChanged: state.salesEstimates.estimateNumberChanged, + estimateNumberChanged: state.salesEstimates.journalNumberChanged, }; return mapState ? mapState(mapped, state, props) : mapped; }; diff --git a/client/src/containers/Sales/Invoice/InvoiceForm.js b/client/src/containers/Sales/Invoice/InvoiceForm.js index bee436764..9de925a43 100644 --- a/client/src/containers/Sales/Invoice/InvoiceForm.js +++ b/client/src/containers/Sales/Invoice/InvoiceForm.js @@ -18,8 +18,10 @@ import InvoiceFormHeader from './InvoiceFormHeader'; import EntriesItemsTable from 'containers/Sales/Estimate/EntriesItemsTable'; import InvoiceFloatingActions from './InvoiceFloatingActions'; +import withInvoices from './withInvoices'; import withInvoiceActions from './withInvoiceActions'; import withInvoiceDetail from './withInvoiceDetail'; + import withDashboardActions from 'containers/Dashboard/withDashboardActions'; import withMediaActions from 'containers/Media/withMediaActions'; import withSettings from 'containers/Settings/withSettings'; @@ -33,26 +35,35 @@ import { compose, repeatValue } from 'utils'; const MIN_LINES_NUMBER = 4; +/** + * Invoice form. + */ + function InvoiceForm({ - //#WithMedia + // #WithMedia requestSubmitMedia, requestDeleteMedia, - //#WithInvoiceActions + // #WithInvoiceActions requestSubmitInvoice, requestEditInvoice, + setInvoiceNumberChanged, - //#withDashboard + // #withDashboard changePageTitle, + changePageSubtitle, // #withSettings invoiceNextNumber, invoiceNumberPrefix, - //#withInvoiceDetail + // #withInvoiceDetail invoice, - //#own Props + // #withInvoices + invoiceNumberChanged, + + // #own Props invoiceId, onFormSubmit, onCancelForm, @@ -79,13 +90,20 @@ function InvoiceForm({ const clearSavedMediaIds = () => { savedMediaIds.current = []; }; + + const invoiceNumber = invoiceNumberPrefix + ? `${invoiceNumberPrefix}-${invoiceNextNumber}` + : invoiceNextNumber; + useEffect(() => { if (invoice && invoice.id) { changePageTitle(formatMessage({ id: 'edit_invoice' })); + changePageSubtitle(`No. ${invoice.invoice_no}`); } else { + changePageSubtitle(`No. ${invoiceNumber}`); changePageTitle(formatMessage({ id: 'new_invoice' })); } - }, [changePageTitle, invoice, formatMessage]); + }, [changePageTitle, changePageSubtitle, invoice, formatMessage]); const validationSchema = Yup.object().shape({ customer_id: Yup.string() @@ -151,10 +169,6 @@ function InvoiceForm({ [], ); - const invoiceNumber = invoiceNumberPrefix - ? `${invoiceNumberPrefix}-${invoiceNextNumber}` - : invoiceNextNumber; - const defaultInitialValues = useMemo( () => ({ customer_id: '', @@ -290,10 +304,18 @@ function InvoiceForm({ } }, }); - useEffect(() => { - formik.setFieldValue('invoice_no', invoiceNumber); - }, [invoiceNumber]); + if (invoiceNumberChanged) { + formik.setFieldValue('invoice_no', invoiceNumber); + changePageSubtitle(`No. ${invoiceNumber}`); + setInvoiceNumberChanged(false); + } + }, [ + invoiceNumber, + invoiceNumberChanged, + formik.setFieldValue, + changePageSubtitle, + ]); const handleSubmitClick = useCallback( (payload) => { @@ -335,10 +357,20 @@ function InvoiceForm({ ); }; + const handleInvoiceNumberChanged = useCallback( + (invoiceNumber) => { + changePageSubtitle(`No. ${invoiceNumber}`); + }, + [changePageSubtitle], + ); + return (
- + ({ invoiceNumberChanged })), )(InvoiceForm); diff --git a/client/src/containers/Sales/Invoice/InvoiceFormHeader.js b/client/src/containers/Sales/Invoice/InvoiceFormHeader.js index ea9512e4f..6dd7305f7 100644 --- a/client/src/containers/Sales/Invoice/InvoiceFormHeader.js +++ b/client/src/containers/Sales/Invoice/InvoiceFormHeader.js @@ -9,7 +9,7 @@ import { import { DateInput } from '@blueprintjs/datetime'; import { FormattedMessage as T } from 'react-intl'; import moment from 'moment'; -import { momentFormatter, compose, tansformDateValue } from 'utils'; +import { momentFormatter, compose, tansformDateValue, saveInvoke } from 'utils'; import classNames from 'classnames'; import { CLASSES } from 'common/classes'; import { @@ -32,6 +32,9 @@ function InvoiceFormHeader({ customers, //#withDialogActions openDialog, + + // #ownProps + onInvoiceNumberChanged, }) { const handleDateChange = useCallback( (date_filed) => (date) => { @@ -41,17 +44,6 @@ function InvoiceFormHeader({ [setFieldValue], ); - const CustomerRenderer = useCallback( - (cutomer, { handleClick }) => ( - - ), - [], - ); - // handle change customer const onChangeCustomer = useCallback( (filedName) => { @@ -66,6 +58,10 @@ function InvoiceFormHeader({ openDialog('invoice-number-form', {}); }, [openDialog]); + const handleInvoiceNumberChanged = (event) => { + saveInvoke(onInvoiceNumberChanged, event.currentTarget.value); + }; + return (
@@ -144,6 +140,7 @@ function InvoiceFormHeader({ + {/* ----------- Invoice number ----------- */} } @@ -171,6 +168,7 @@ function InvoiceFormHeader({ /> } {...getFieldProps('invoice_no')} + onBlur={handleInvoiceNumberChanged} /> diff --git a/client/src/containers/Sales/Invoice/withInvoiceActions.js b/client/src/containers/Sales/Invoice/withInvoiceActions.js index 15a5b8a9e..ab11b52f1 100644 --- a/client/src/containers/Sales/Invoice/withInvoiceActions.js +++ b/client/src/containers/Sales/Invoice/withInvoiceActions.js @@ -27,6 +27,11 @@ const mapDipatchToProps = (dispatch) => ({ type: t.INVOICES_TABLE_QUERIES_ADD, _queries, }), + + setInvoiceNumberChanged: (isChanged) => dispatch({ + type: t.INVOICE_NUMBER_CHANGED, + payload: { isChanged }, + }), }); export default connect(null, mapDipatchToProps); diff --git a/client/src/containers/Sales/Invoice/withInvoices.js b/client/src/containers/Sales/Invoice/withInvoices.js index 122aaaf80..dd2d1a474 100644 --- a/client/src/containers/Sales/Invoice/withInvoices.js +++ b/client/src/containers/Sales/Invoice/withInvoices.js @@ -4,7 +4,7 @@ import { getInvoiceCurrentPageFactory, getInvoicePaginationMetaFactory, getInvoiceTableQueryFactory, - getCustomerReceivableInvoicesEntriesFactory + getCustomerReceivableInvoicesEntriesFactory, } from 'store/Invoice/invoices.selector'; export default (mapState) => { @@ -25,7 +25,12 @@ export default (mapState) => { invoicesTableQuery: query, invoicesPageination: getInvoicesPaginationMeta(state, props, query), invoicesLoading: state.salesInvoices.loading, - customerInvoiceEntries: getCustomerReceivableInvoicesEntries(state, props), + customerInvoiceEntries: getCustomerReceivableInvoicesEntries( + state, + props, + ), + + invoiceNumberChanged: state.salesInvoices.journalNumberChanged, }; return mapState ? mapState(mapped, state, props) : mapped; }; diff --git a/client/src/containers/Sales/Receipt/ReceiptForm.js b/client/src/containers/Sales/Receipt/ReceiptForm.js index 93e9a2414..e90bf2399 100644 --- a/client/src/containers/Sales/Receipt/ReceiptForm.js +++ b/client/src/containers/Sales/Receipt/ReceiptForm.js @@ -11,17 +11,20 @@ import { useFormik } from 'formik'; import moment from 'moment'; import { Intent, FormGroup, TextArea } from '@blueprintjs/core'; import { FormattedMessage as T, useIntl } from 'react-intl'; -import { pick,sumBy } from 'lodash'; +import { pick, sumBy } from 'lodash'; import classNames from 'classnames'; import { CLASSES } from 'common/classes'; import { ERROR } from 'common/errors'; + import ReceiptFromHeader from './ReceiptFormHeader'; import EntriesItemsTable from 'containers/Sales/Estimate/EntriesItemsTable'; import ReceiptReceiveFloatingActions from './ReceiptReceiveFloatingActions'; +import withReceipts from './withReceipts'; import withReceiptActions from './withReceiptActions'; import withReceiptDetail from './withReceiptDetail'; + import withDashboardActions from 'containers/Dashboard/withDashboardActions'; import withMediaActions from 'containers/Media/withMediaActions'; import withSettings from 'containers/Settings/withSettings'; @@ -34,6 +37,10 @@ import { compose, repeatValue } from 'utils'; const MIN_LINES_NUMBER = 4; +/** + * Receipt form. + */ + function ReceiptForm({ //#withMedia requestSubmitMedia, @@ -42,17 +49,22 @@ function ReceiptForm({ //#withReceiptActions requestSubmitReceipt, requestEditReceipt, + setReceiptNumberChanged, //#withReceiptDetail receipt, //#withDashboard changePageTitle, + changePageSubtitle, // #withSettings receiptNextNumber, receiptNumberPrefix, + // #withReceipts + receiptNumberChanged, + //#own Props receiptId, onFormSubmit, @@ -81,13 +93,19 @@ function ReceiptForm({ savedMediaIds.current = []; }; + const receiptNumber = receiptNumberPrefix + ? `${receiptNumberPrefix}-${receiptNextNumber}` + : receiptNextNumber; + useEffect(() => { if (receipt && receipt.id) { changePageTitle(formatMessage({ id: 'edit_receipt' })); + changePageSubtitle(`No. ${receipt.receipt_number}`); } else { + changePageSubtitle(`No. ${receiptNumber}`); changePageTitle(formatMessage({ id: 'new_receipt' })); } - }, [changePageTitle, receipt, formatMessage]); + }, [changePageTitle, changePageSubtitle, receipt, formatMessage]); const validationSchema = Yup.object().shape({ customer_id: Yup.string() @@ -153,10 +171,6 @@ function ReceiptForm({ [], ); - const receiptNumber = receiptNumberPrefix - ? `${receiptNumberPrefix}-${receiptNextNumber}` - : receiptNextNumber; - const defaultInitialValues = useMemo( () => ({ customer_id: '', @@ -293,6 +307,19 @@ function ReceiptForm({ }, }); + useEffect(() => { + if (receiptNumberChanged) { + formik.setFieldValue('receipt_number', receiptNumber); + changePageSubtitle(`No. ${receiptNumber}`); + setReceiptNumberChanged(false); + } + }, [ + receiptNumber, + receiptNumberChanged, + formik.setFieldValue, + changePageSubtitle, + ]); + const handleDeleteFile = useCallback( (_deletedFiles) => { _deletedFiles.forEach((deletedFile) => { @@ -333,14 +360,20 @@ function ReceiptForm({ ); }; - useEffect(() => { - formik.setFieldValue('receipt_number', receiptNumber); - }, [receiptNumber]); + const handleReceiptNumberChanged = useCallback( + (receiptNumber) => { + changePageSubtitle(`No. ${receiptNumber}`); + }, + [changePageSubtitle], + ); return (
- + + {/* --------- Receipt message --------- */} } className={'form-group--receipt_message'} @@ -362,6 +396,7 @@ function ReceiptForm({ /> + {/* --------- Statement--------- */} } className={'form-group--statement'} @@ -403,4 +438,5 @@ export default compose( receiptNextNumber: receiptSettings?.nextNumber, receiptNumberPrefix: receiptSettings?.numberPrefix, })), + withReceipts(({ receiptNumberChanged }) => ({ receiptNumberChanged })), )(ReceiptForm); diff --git a/client/src/containers/Sales/Receipt/ReceiptFormHeader.js b/client/src/containers/Sales/Receipt/ReceiptFormHeader.js index 004f71d76..d68dfc47f 100644 --- a/client/src/containers/Sales/Receipt/ReceiptFormHeader.js +++ b/client/src/containers/Sales/Receipt/ReceiptFormHeader.js @@ -1,16 +1,10 @@ import React, { useMemo, useCallback, useState } from 'react'; -import { - FormGroup, - InputGroup, - Intent, - Position, - MenuItem, -} from '@blueprintjs/core'; +import { FormGroup, InputGroup, Intent, Position } from '@blueprintjs/core'; import { DateInput } from '@blueprintjs/datetime'; import { FormattedMessage as T } from 'react-intl'; import moment from 'moment'; -import { momentFormatter, compose, tansformDateValue } from 'utils'; +import { momentFormatter, compose, tansformDateValue, saveInvoke } from 'utils'; import classNames from 'classnames'; import { CLASSES } from 'common/classes'; import { @@ -31,10 +25,15 @@ function ReceiptFormHeader({ //#withCustomers customers, + //#withAccouts accountsList, + //#withDialogActions openDialog, + + // #ownProps + onReceiptNumberChanged, }) { const handleDateChange = useCallback( (date) => { @@ -64,10 +63,14 @@ function ReceiptFormHeader({ openDialog('receipt-number-form', {}); }, [openDialog]); + const handleReceiptNumberChanged = (event) => { + saveInvoke(onReceiptNumberChanged, event.currentTarget.value); + }; + return (
- {/*- Customer name -*/} + {/* ----------- Customer name ----------- */} } inline={true} @@ -90,7 +93,7 @@ function ReceiptFormHeader({ /> - {/*- Deposit account -*/} + {/* ----------- Deposit account ----------- */} } className={classNames( @@ -119,7 +122,7 @@ function ReceiptFormHeader({ selectedAccountId={values.deposit_account_id} /> - + {/* ----------- Receipt date ----------- */} } inline={true} @@ -137,7 +140,7 @@ function ReceiptFormHeader({ /> - {/* receipt_no */} + {/* ----------- Receipt number ----------- */} } inline={true} @@ -169,10 +172,11 @@ function ReceiptFormHeader({ /> } {...getFieldProps('receipt_number')} + onBlur={handleReceiptNumberChanged} /> - {/*- Reference -*/} + {/* ----------- Reference ----------- */} } inline={true} diff --git a/client/src/containers/Sales/Receipt/withReceiptActions.js b/client/src/containers/Sales/Receipt/withReceiptActions.js index 3d20263fd..34c6b8938 100644 --- a/client/src/containers/Sales/Receipt/withReceiptActions.js +++ b/client/src/containers/Sales/Receipt/withReceiptActions.js @@ -28,6 +28,10 @@ const mapDispatchToProps = (dispatch) => ({ type: t.RECEIPTS_TABLE_QUERIES_ADD, queries, }), -}); + setReceiptNumberChanged:(isChanged) => dispatch({ + type: t.RECEIPT_NUMBER_CHANGED, + payload: { isChanged }, + }), + }); export default connect(null, mapDispatchToProps); diff --git a/client/src/containers/Sales/Receipt/withReceipts.js b/client/src/containers/Sales/Receipt/withReceipts.js index 556d7c204..ab69a2f86 100644 --- a/client/src/containers/Sales/Receipt/withReceipts.js +++ b/client/src/containers/Sales/Receipt/withReceipts.js @@ -16,11 +16,14 @@ export default (mapState) => { const mapped = { receiptsCurrentPage: getReceiptsItems(state, props, tableQuery), - receiptview:getResourceViews(state, props, 'sales_receipts'), + receiptview: getResourceViews(state, props, 'sales_receipts'), receiptItems: state.salesReceipts.items, receiptTableQuery: tableQuery, receiptsPagination: getReceiptPaginationMeta(state, props, tableQuery), + receiptsLoading: state.salesReceipts.loading, + + receiptNumberChanged: state.salesReceipts.journalNumberChanged, }; return mapState ? mapState(mapped, state, props) : mapped; diff --git a/client/src/store/Estimate/estimates.reducer.js b/client/src/store/Estimate/estimates.reducer.js index 8171b5739..d3548748e 100644 --- a/client/src/store/Estimate/estimates.reducer.js +++ b/client/src/store/Estimate/estimates.reducer.js @@ -13,8 +13,7 @@ const initialState = { page: 1, }, currentViewId: -1, - - estimateNumberChanged: false, + }; const defaultEstimate = { diff --git a/client/src/store/Invoice/invoices.reducer.js b/client/src/store/Invoice/invoices.reducer.js index 424697d91..1c5ecbe4c 100644 --- a/client/src/store/Invoice/invoices.reducer.js +++ b/client/src/store/Invoice/invoices.reducer.js @@ -1,5 +1,6 @@ import { createReducer } from '@reduxjs/toolkit'; import { createTableQueryReducers } from 'store/queryReducers'; +import { journalNumberChangedReducer } from 'store/journalNumber.reducer'; import t from 'store/types'; @@ -114,7 +115,7 @@ const reducer = createReducer(initialState, { const { customerId, saleInvoices } = action.payload; const saleInvoiceIds = saleInvoices.map((saleInvoice) => saleInvoice.id); - state.receivable.byCustomerId[customerId] = saleInvoiceIds + state.receivable.byCustomerId[customerId] = saleInvoiceIds; }, [t.INVOICES_BY_PAYMENT_ID]: (state, action) => { @@ -123,6 +124,8 @@ const reducer = createReducer(initialState, { state.byPaymentReceiveId[paymentReceiveId] = saleInvoiceIds; }, + + ...journalNumberChangedReducer(t.INVOICE_NUMBER_CHANGED), }); export default createTableQueryReducers('sales_invoices', reducer); diff --git a/client/src/store/Invoice/invoices.types.js b/client/src/store/Invoice/invoices.types.js index d2111a679..ee504ba2b 100644 --- a/client/src/store/Invoice/invoices.types.js +++ b/client/src/store/Invoice/invoices.types.js @@ -14,5 +14,7 @@ export default { INVOICES_RECEIVABLE_BY_PAYMENT_ID: 'INVOICES_RECEIVABLE_BY_PAYMENT_ID', INVOICES_RECEIVABLE_BY_CUSTOMER_ID: 'INVOICES_RECEIVABLE_BY_CUSTOMER_ID', - INVOICES_BY_PAYMENT_ID: 'INVOICES_BY_PAYMENT_ID' + INVOICES_BY_PAYMENT_ID: 'INVOICES_BY_PAYMENT_ID', + + INVOICE_NUMBER_CHANGED: 'INVOICE_NUMBER_CHANGED', }; diff --git a/client/src/store/receipt/receipt.reducer.js b/client/src/store/receipt/receipt.reducer.js index 7f6a67015..6c5f7a8b9 100644 --- a/client/src/store/receipt/receipt.reducer.js +++ b/client/src/store/receipt/receipt.reducer.js @@ -1,6 +1,7 @@ import { createReducer } from '@reduxjs/toolkit'; import { createTableQueryReducers } from 'store/queryReducers'; import t from 'store/types'; +import { journalNumberChangedReducer } from 'store/journalNumber.reducer'; const initialState = { items: {}, @@ -18,14 +19,12 @@ const defaultReceipt = { }; const reducer = createReducer(initialState, { - [t.RECEIPT_SET]: (state, action) => { const { id, sale_receipt } = action.payload; const _receipt = state.items[id] || {}; state.items[id] = { ...defaultReceipt, ..._receipt, ...sale_receipt }; }, - [t.RECEIPTS_ITEMS_SET]: (state, action) => { const { sales_receipts } = action.payload; const _receipts = {}; @@ -94,6 +93,7 @@ const reducer = createReducer(initialState, { }, }; }, + ...journalNumberChangedReducer(t.RECEIPT_NUMBER_CHANGED), }); export default createTableQueryReducers('sales_receipts', reducer); diff --git a/client/src/store/receipt/receipt.type.js b/client/src/store/receipt/receipt.type.js index c50dc5a0d..b68ae5984 100644 --- a/client/src/store/receipt/receipt.type.js +++ b/client/src/store/receipt/receipt.type.js @@ -9,4 +9,5 @@ export default { RECEIPTS_PAGINATION_SET: 'RECEIPTS_PAGINATION_SET', RECEIPTS_PAGE_SET: 'RECEIPTS_PAGE_SET', RECEIPTS_ITEMS_SET: 'RECEIPTS_ITEMS_SET', + RECEIPT_NUMBER_CHANGED:'RECEIPT_NUMBER_CHANGED' };