Fix : Auto-Increment Dialog

This commit is contained in:
elforjani3
2020-11-08 21:19:54 +02:00
parent 3ab6c4da2a
commit 6c8ff20847
19 changed files with 194 additions and 83 deletions

View File

@@ -1,12 +1,12 @@
import React from 'react'; import React, { useCallback } from 'react';
import { DialogContent } from 'components'; import { DialogContent } from 'components';
import { useQuery, queryCache } from 'react-query'; import { useQuery, queryCache } from 'react-query';
import ReferenceNumberForm from 'containers/JournalNumber/ReferenceNumberForm'; import ReferenceNumberForm from 'containers/JournalNumber/ReferenceNumberForm';
import withDialogActions from 'containers/Dialog/withDialogActions'; import withDialogActions from 'containers/Dialog/withDialogActions';
import withSettings from 'containers/Settings/withSettings';
import withSettingsActions from 'containers/Settings/withSettingsActions'; import withSettingsActions from 'containers/Settings/withSettingsActions';
import withEstimateActions from 'containers/Sales/Estimate/withEstimateActions'; import withEstimateActions from 'containers/Sales/Estimate/withEstimateActions';
import withSettings from 'containers/Settings/withSettings';
import { compose, optionsMapToArray } from 'utils'; import { compose, optionsMapToArray } from 'utils';
@@ -49,9 +49,9 @@ function EstimateNumberDialogContent({
}); });
}; };
const handleClose = () => { const handleClose = useCallback(() => {
closeDialog('estimate-number-form'); closeDialog('estimate-number-form');
}; }, [closeDialog]);
return ( return (
<DialogContent isLoading={fetchSettings.isFetching}> <DialogContent isLoading={fetchSettings.isFetching}>
@@ -69,8 +69,8 @@ export default compose(
withDialogActions, withDialogActions,
withSettingsActions, withSettingsActions,
withSettings(({ estimatesSettings }) => ({ withSettings(({ estimatesSettings }) => ({
nextNumber: estimatesSettings?.next_number, nextNumber: estimatesSettings?.nextNumber,
numberPrefix: estimatesSettings?.number_prefix, numberPrefix: estimatesSettings?.numberPrefix,
})), })),
withEstimateActions, withEstimateActions,
)(EstimateNumberDialogContent); )(EstimateNumberDialogContent);

View File

@@ -1,12 +1,13 @@
import React from 'react'; import React, { useCallback } from 'react';
import { DialogContent } from 'components'; import { DialogContent } from 'components';
import { useQuery, queryCache } from 'react-query'; import { useQuery, queryCache } from 'react-query';
import ReferenceNumberForm from 'containers/JournalNumber/ReferenceNumberForm'; import ReferenceNumberForm from 'containers/JournalNumber/ReferenceNumberForm';
import withDialogActions from 'containers/Dialog/withDialogActions'; import withDialogActions from 'containers/Dialog/withDialogActions';
import withSettingsActions from 'containers/Settings/withSettingsActions';
import withSettings from 'containers/Settings/withSettings'; import withSettings from 'containers/Settings/withSettings';
import withSettingsActions from 'containers/Settings/withSettingsActions';
import withInvoicesActions from 'containers/Sales/Invoice/withInvoiceActions';
import { compose, optionsMapToArray } from 'utils'; import { compose, optionsMapToArray } from 'utils';
@@ -25,6 +26,9 @@ function InvoiceNumberDialogContent({
// #withDialogActions // #withDialogActions
closeDialog, closeDialog,
// #withInvoicesActions
setInvoiceNumberChanged,
}) { }) {
const fetchSettings = useQuery(['settings'], () => requestFetchOptions({})); const fetchSettings = useQuery(['settings'], () => requestFetchOptions({}));
@@ -40,6 +44,7 @@ function InvoiceNumberDialogContent({
setTimeout(() => { setTimeout(() => {
queryCache.invalidateQueries('settings'); queryCache.invalidateQueries('settings');
setInvoiceNumberChanged(true);
}, 250); }, 250);
}) })
.catch(() => { .catch(() => {
@@ -47,9 +52,9 @@ function InvoiceNumberDialogContent({
}); });
}; };
const handleClose = () => { const handleClose = useCallback(() => {
closeDialog('invoice-number-form'); closeDialog('invoice-number-form');
}; }, [closeDialog]);
return ( return (
<DialogContent isLoading={fetchSettings.isFetching}> <DialogContent isLoading={fetchSettings.isFetching}>
@@ -67,8 +72,8 @@ export default compose(
withDialogActions, withDialogActions,
withSettingsActions, withSettingsActions,
withSettings(({ invoiceSettings }) => ({ withSettings(({ invoiceSettings }) => ({
nextNumber: invoiceSettings?.next_number, nextNumber: invoiceSettings?.nextNumber,
numberPrefix: invoiceSettings?.number_prefix, numberPrefix: invoiceSettings?.numberPrefix,
})), })),
withInvoicesActions,
) (InvoiceNumberDialogContent); )(InvoiceNumberDialogContent);

View File

@@ -11,7 +11,7 @@ const InvoiceNumberDialogContent = lazy(() =>
function InvoiceNumberDialog({ dialogName, payload = { id: null }, isOpen }) { function InvoiceNumberDialog({ dialogName, payload = { id: null }, isOpen }) {
return ( return (
<Dialog <Dialog
title={<T id={'bill_number_settings'} />} title={<T id={'invoice_number_settings'} />}
name={dialogName} name={dialogName}
autoFocus={true} autoFocus={true}
canEscapeKeyClose={true} canEscapeKeyClose={true}

View File

@@ -1,12 +1,13 @@
import React from 'react'; import React, { useCallback } from 'react';
import { DialogContent } from 'components'; import { DialogContent } from 'components';
import { useQuery, queryCache } from 'react-query'; import { useQuery, queryCache } from 'react-query';
import ReferenceNumberForm from 'containers/JournalNumber/ReferenceNumberForm'; import ReferenceNumberForm from 'containers/JournalNumber/ReferenceNumberForm';
import withDialogActions from 'containers/Dialog/withDialogActions'; import withDialogActions from 'containers/Dialog/withDialogActions';
import withSettingsActions from 'containers/Settings/withSettingsActions';
import withSettings from 'containers/Settings/withSettings'; import withSettings from 'containers/Settings/withSettings';
import withSettingsActions from 'containers/Settings/withSettingsActions';
import withReceiptActions from 'containers/Sales/Receipt/withReceiptActions';
import { compose, optionsMapToArray } from 'utils'; import { compose, optionsMapToArray } from 'utils';
@@ -25,6 +26,9 @@ function ReceiptNumberDialogContent({
// #withDialogActions // #withDialogActions
closeDialog, closeDialog,
// #withReceiptActions
setReceiptNumberChanged,
}) { }) {
const fetchSettings = useQuery(['settings'], () => requestFetchOptions({})); const fetchSettings = useQuery(['settings'], () => requestFetchOptions({}));
@@ -40,6 +44,7 @@ function ReceiptNumberDialogContent({
setTimeout(() => { setTimeout(() => {
queryCache.invalidateQueries('settings'); queryCache.invalidateQueries('settings');
setReceiptNumberChanged(true);
}, 250); }, 250);
}) })
.catch(() => { .catch(() => {
@@ -47,9 +52,9 @@ function ReceiptNumberDialogContent({
}); });
}; };
const handleClose = () => { const handleClose = useCallback(() => {
closeDialog('receipt-number-form'); closeDialog('receipt-number-form');
}; }, [closeDialog]);
return ( return (
<DialogContent isLoading={fetchSettings.isFetching}> <DialogContent isLoading={fetchSettings.isFetching}>
@@ -67,7 +72,8 @@ export default compose(
withDialogActions, withDialogActions,
withSettingsActions, withSettingsActions,
withSettings(({ receiptSettings }) => ({ withSettings(({ receiptSettings }) => ({
nextNumber: receiptSettings?.next_number, nextNumber: receiptSettings?.nextNumber,
numberPrefix: receiptSettings?.number_prefix, numberPrefix: receiptSettings?.numberPrefix,
})), })),
withReceiptActions,
)(ReceiptNumberDialogContent); )(ReceiptNumberDialogContent);

View File

@@ -18,9 +18,10 @@ import EstimateFormHeader from './EstimateFormHeader';
import EntriesItemsTable from './EntriesItemsTable'; import EntriesItemsTable from './EntriesItemsTable';
import EstimateFloatingActions from './EstimateFloatingActions'; import EstimateFloatingActions from './EstimateFloatingActions';
import withEstimates from './withEstimates';
import withEstimateActions from './withEstimateActions'; import withEstimateActions from './withEstimateActions';
import withEstimateDetail from './withEstimateDetail'; import withEstimateDetail from './withEstimateDetail';
import withEstimates from './withEstimates';
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 withSettings from 'containers/Settings/withSettings';
@@ -34,6 +35,10 @@ import { compose, repeatValue } from 'utils';
const MIN_LINES_NUMBER = 4; const MIN_LINES_NUMBER = 4;
/**
* Estimate form.
*/
const EstimateForm = ({ const EstimateForm = ({
//#WithMedia //#WithMedia
requestSubmitMedia, requestSubmitMedia,
@@ -43,6 +48,7 @@ const EstimateForm = ({
requestSubmitEstimate, requestSubmitEstimate,
requestEditEstimate, requestEditEstimate,
setEstimateNumberChanged, setEstimateNumberChanged,
//#withDashboard //#withDashboard
changePageTitle, changePageTitle,
changePageSubtitle, changePageSubtitle,
@@ -378,6 +384,7 @@ const EstimateForm = ({
<div class={classNames(CLASSES.PAGE_FORM_FOOTER)}> <div class={classNames(CLASSES.PAGE_FORM_FOOTER)}>
<Row> <Row>
<Col md={8}> <Col md={8}>
{/* --------- Customer Note --------- */}
<FormGroup <FormGroup
label={<T id={'customer_note'} />} label={<T id={'customer_note'} />}
className={'form-group--customer_note'} className={'form-group--customer_note'}
@@ -387,7 +394,7 @@ const EstimateForm = ({
{...formik.getFieldProps('note')} {...formik.getFieldProps('note')}
/> />
</FormGroup> </FormGroup>
{/* --------- Terms and conditions --------- */}
<FormGroup <FormGroup
label={<T id={'terms_conditions'} />} label={<T id={'terms_conditions'} />}
className={'form-group--terms_conditions'} className={'form-group--terms_conditions'}

View File

@@ -23,7 +23,7 @@ export default (mapState) => {
estimatesPageination: getEstimatesPaginationMeta(state, props, query), estimatesPageination: getEstimatesPaginationMeta(state, props, query),
estimatesLoading: state.salesEstimates.loading, estimatesLoading: state.salesEstimates.loading,
estimateNumberChanged: state.salesEstimates.estimateNumberChanged, estimateNumberChanged: state.salesEstimates.journalNumberChanged,
}; };
return mapState ? mapState(mapped, state, props) : mapped; return mapState ? mapState(mapped, state, props) : mapped;
}; };

View File

@@ -18,8 +18,10 @@ import InvoiceFormHeader from './InvoiceFormHeader';
import EntriesItemsTable from 'containers/Sales/Estimate/EntriesItemsTable'; import EntriesItemsTable from 'containers/Sales/Estimate/EntriesItemsTable';
import InvoiceFloatingActions from './InvoiceFloatingActions'; import InvoiceFloatingActions from './InvoiceFloatingActions';
import withInvoices from './withInvoices';
import withInvoiceActions from './withInvoiceActions'; import withInvoiceActions from './withInvoiceActions';
import withInvoiceDetail from './withInvoiceDetail'; import withInvoiceDetail from './withInvoiceDetail';
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 withSettings from 'containers/Settings/withSettings';
@@ -33,26 +35,35 @@ import { compose, repeatValue } from 'utils';
const MIN_LINES_NUMBER = 4; const MIN_LINES_NUMBER = 4;
/**
* Invoice form.
*/
function InvoiceForm({ function InvoiceForm({
//#WithMedia // #WithMedia
requestSubmitMedia, requestSubmitMedia,
requestDeleteMedia, requestDeleteMedia,
//#WithInvoiceActions // #WithInvoiceActions
requestSubmitInvoice, requestSubmitInvoice,
requestEditInvoice, requestEditInvoice,
setInvoiceNumberChanged,
//#withDashboard // #withDashboard
changePageTitle, changePageTitle,
changePageSubtitle,
// #withSettings // #withSettings
invoiceNextNumber, invoiceNextNumber,
invoiceNumberPrefix, invoiceNumberPrefix,
//#withInvoiceDetail // #withInvoiceDetail
invoice, invoice,
//#own Props // #withInvoices
invoiceNumberChanged,
// #own Props
invoiceId, invoiceId,
onFormSubmit, onFormSubmit,
onCancelForm, onCancelForm,
@@ -79,13 +90,20 @@ function InvoiceForm({
const clearSavedMediaIds = () => { const clearSavedMediaIds = () => {
savedMediaIds.current = []; savedMediaIds.current = [];
}; };
const invoiceNumber = invoiceNumberPrefix
? `${invoiceNumberPrefix}-${invoiceNextNumber}`
: invoiceNextNumber;
useEffect(() => { useEffect(() => {
if (invoice && invoice.id) { if (invoice && invoice.id) {
changePageTitle(formatMessage({ id: 'edit_invoice' })); changePageTitle(formatMessage({ id: 'edit_invoice' }));
changePageSubtitle(`No. ${invoice.invoice_no}`);
} else { } else {
changePageSubtitle(`No. ${invoiceNumber}`);
changePageTitle(formatMessage({ id: 'new_invoice' })); changePageTitle(formatMessage({ id: 'new_invoice' }));
} }
}, [changePageTitle, invoice, formatMessage]); }, [changePageTitle, changePageSubtitle, invoice, formatMessage]);
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
customer_id: Yup.string() customer_id: Yup.string()
@@ -151,10 +169,6 @@ function InvoiceForm({
[], [],
); );
const invoiceNumber = invoiceNumberPrefix
? `${invoiceNumberPrefix}-${invoiceNextNumber}`
: invoiceNextNumber;
const defaultInitialValues = useMemo( const defaultInitialValues = useMemo(
() => ({ () => ({
customer_id: '', customer_id: '',
@@ -290,10 +304,18 @@ function InvoiceForm({
} }
}, },
}); });
useEffect(() => { useEffect(() => {
formik.setFieldValue('invoice_no', invoiceNumber); if (invoiceNumberChanged) {
}, [invoiceNumber]); formik.setFieldValue('invoice_no', invoiceNumber);
changePageSubtitle(`No. ${invoiceNumber}`);
setInvoiceNumberChanged(false);
}
}, [
invoiceNumber,
invoiceNumberChanged,
formik.setFieldValue,
changePageSubtitle,
]);
const handleSubmitClick = useCallback( const handleSubmitClick = useCallback(
(payload) => { (payload) => {
@@ -335,10 +357,20 @@ function InvoiceForm({
); );
}; };
const handleInvoiceNumberChanged = useCallback(
(invoiceNumber) => {
changePageSubtitle(`No. ${invoiceNumber}`);
},
[changePageSubtitle],
);
return ( return (
<div className={classNames(CLASSES.PAGE_FORM, CLASSES.PAGE_FORM_INVOICE)}> <div className={classNames(CLASSES.PAGE_FORM, CLASSES.PAGE_FORM_INVOICE)}>
<form onSubmit={formik.handleSubmit}> <form onSubmit={formik.handleSubmit}>
<InvoiceFormHeader formik={formik} /> <InvoiceFormHeader
onInvoiceNumberChanged={handleInvoiceNumberChanged}
formik={formik}
/>
<EntriesItemsTable <EntriesItemsTable
entries={formik.values.entries} entries={formik.values.entries}
onClickAddNewRow={handleClickAddNewRow} onClickAddNewRow={handleClickAddNewRow}
@@ -404,4 +436,5 @@ export default compose(
invoiceNextNumber: invoiceSettings?.nextNumber, invoiceNextNumber: invoiceSettings?.nextNumber,
invoiceNumberPrefix: invoiceSettings?.numberPrefix, invoiceNumberPrefix: invoiceSettings?.numberPrefix,
})), })),
withInvoices(({ invoiceNumberChanged }) => ({ invoiceNumberChanged })),
)(InvoiceForm); )(InvoiceForm);

View File

@@ -9,7 +9,7 @@ import {
import { DateInput } from '@blueprintjs/datetime'; import { DateInput } from '@blueprintjs/datetime';
import { FormattedMessage as T } from 'react-intl'; import { FormattedMessage as T } from 'react-intl';
import moment from 'moment'; import moment from 'moment';
import { momentFormatter, compose, tansformDateValue } from 'utils'; import { momentFormatter, compose, tansformDateValue, saveInvoke } from 'utils';
import classNames from 'classnames'; import classNames from 'classnames';
import { CLASSES } from 'common/classes'; import { CLASSES } from 'common/classes';
import { import {
@@ -32,6 +32,9 @@ function InvoiceFormHeader({
customers, customers,
//#withDialogActions //#withDialogActions
openDialog, openDialog,
// #ownProps
onInvoiceNumberChanged,
}) { }) {
const handleDateChange = useCallback( const handleDateChange = useCallback(
(date_filed) => (date) => { (date_filed) => (date) => {
@@ -41,17 +44,6 @@ function InvoiceFormHeader({
[setFieldValue], [setFieldValue],
); );
const CustomerRenderer = useCallback(
(cutomer, { handleClick }) => (
<MenuItem
key={cutomer.id}
text={cutomer.display_name}
onClick={handleClick}
/>
),
[],
);
// handle change customer // handle change customer
const onChangeCustomer = useCallback( const onChangeCustomer = useCallback(
(filedName) => { (filedName) => {
@@ -66,6 +58,10 @@ function InvoiceFormHeader({
openDialog('invoice-number-form', {}); openDialog('invoice-number-form', {});
}, [openDialog]); }, [openDialog]);
const handleInvoiceNumberChanged = (event) => {
saveInvoke(onInvoiceNumberChanged, event.currentTarget.value);
};
return ( return (
<div className={classNames(CLASSES.PAGE_FORM_HEADER)}> <div className={classNames(CLASSES.PAGE_FORM_HEADER)}>
<div className={classNames(CLASSES.PAGE_FORM_HEADER_PRIMARY)}> <div className={classNames(CLASSES.PAGE_FORM_HEADER_PRIMARY)}>
@@ -144,6 +140,7 @@ function InvoiceFormHeader({
</FormGroup> </FormGroup>
</Col> </Col>
</Row> </Row>
{/* ----------- Invoice number ----------- */} {/* ----------- Invoice number ----------- */}
<FormGroup <FormGroup
label={<T id={'invoice_no'} />} label={<T id={'invoice_no'} />}
@@ -171,6 +168,7 @@ function InvoiceFormHeader({
/> />
} }
{...getFieldProps('invoice_no')} {...getFieldProps('invoice_no')}
onBlur={handleInvoiceNumberChanged}
/> />
</FormGroup> </FormGroup>

View File

@@ -27,6 +27,11 @@ const mapDipatchToProps = (dispatch) => ({
type: t.INVOICES_TABLE_QUERIES_ADD, type: t.INVOICES_TABLE_QUERIES_ADD,
_queries, _queries,
}), }),
setInvoiceNumberChanged: (isChanged) => dispatch({
type: t.INVOICE_NUMBER_CHANGED,
payload: { isChanged },
}),
}); });
export default connect(null, mapDipatchToProps); export default connect(null, mapDipatchToProps);

View File

@@ -4,7 +4,7 @@ import {
getInvoiceCurrentPageFactory, getInvoiceCurrentPageFactory,
getInvoicePaginationMetaFactory, getInvoicePaginationMetaFactory,
getInvoiceTableQueryFactory, getInvoiceTableQueryFactory,
getCustomerReceivableInvoicesEntriesFactory getCustomerReceivableInvoicesEntriesFactory,
} from 'store/Invoice/invoices.selector'; } from 'store/Invoice/invoices.selector';
export default (mapState) => { export default (mapState) => {
@@ -25,7 +25,12 @@ export default (mapState) => {
invoicesTableQuery: query, invoicesTableQuery: query,
invoicesPageination: getInvoicesPaginationMeta(state, props, query), invoicesPageination: getInvoicesPaginationMeta(state, props, query),
invoicesLoading: state.salesInvoices.loading, invoicesLoading: state.salesInvoices.loading,
customerInvoiceEntries: getCustomerReceivableInvoicesEntries(state, props), customerInvoiceEntries: getCustomerReceivableInvoicesEntries(
state,
props,
),
invoiceNumberChanged: state.salesInvoices.journalNumberChanged,
}; };
return mapState ? mapState(mapped, state, props) : mapped; return mapState ? mapState(mapped, state, props) : mapped;
}; };

View File

@@ -11,17 +11,20 @@ import { useFormik } from 'formik';
import moment from 'moment'; import moment from 'moment';
import { Intent, FormGroup, TextArea } from '@blueprintjs/core'; import { Intent, FormGroup, TextArea } from '@blueprintjs/core';
import { FormattedMessage as T, useIntl } from 'react-intl'; import { FormattedMessage as T, useIntl } from 'react-intl';
import { pick,sumBy } from 'lodash'; import { pick, sumBy } from 'lodash';
import classNames from 'classnames'; import classNames from 'classnames';
import { CLASSES } from 'common/classes'; import { CLASSES } from 'common/classes';
import { ERROR } from 'common/errors'; import { ERROR } from 'common/errors';
import ReceiptFromHeader from './ReceiptFormHeader'; import ReceiptFromHeader from './ReceiptFormHeader';
import EntriesItemsTable from 'containers/Sales/Estimate/EntriesItemsTable'; import EntriesItemsTable from 'containers/Sales/Estimate/EntriesItemsTable';
import ReceiptReceiveFloatingActions from './ReceiptReceiveFloatingActions'; import ReceiptReceiveFloatingActions from './ReceiptReceiveFloatingActions';
import withReceipts from './withReceipts';
import withReceiptActions from './withReceiptActions'; import withReceiptActions from './withReceiptActions';
import withReceiptDetail from './withReceiptDetail'; import withReceiptDetail from './withReceiptDetail';
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 withSettings from 'containers/Settings/withSettings';
@@ -34,6 +37,10 @@ import { compose, repeatValue } from 'utils';
const MIN_LINES_NUMBER = 4; const MIN_LINES_NUMBER = 4;
/**
* Receipt form.
*/
function ReceiptForm({ function ReceiptForm({
//#withMedia //#withMedia
requestSubmitMedia, requestSubmitMedia,
@@ -42,17 +49,22 @@ function ReceiptForm({
//#withReceiptActions //#withReceiptActions
requestSubmitReceipt, requestSubmitReceipt,
requestEditReceipt, requestEditReceipt,
setReceiptNumberChanged,
//#withReceiptDetail //#withReceiptDetail
receipt, receipt,
//#withDashboard //#withDashboard
changePageTitle, changePageTitle,
changePageSubtitle,
// #withSettings // #withSettings
receiptNextNumber, receiptNextNumber,
receiptNumberPrefix, receiptNumberPrefix,
// #withReceipts
receiptNumberChanged,
//#own Props //#own Props
receiptId, receiptId,
onFormSubmit, onFormSubmit,
@@ -81,13 +93,19 @@ function ReceiptForm({
savedMediaIds.current = []; savedMediaIds.current = [];
}; };
const receiptNumber = receiptNumberPrefix
? `${receiptNumberPrefix}-${receiptNextNumber}`
: receiptNextNumber;
useEffect(() => { useEffect(() => {
if (receipt && receipt.id) { if (receipt && receipt.id) {
changePageTitle(formatMessage({ id: 'edit_receipt' })); changePageTitle(formatMessage({ id: 'edit_receipt' }));
changePageSubtitle(`No. ${receipt.receipt_number}`);
} else { } else {
changePageSubtitle(`No. ${receiptNumber}`);
changePageTitle(formatMessage({ id: 'new_receipt' })); changePageTitle(formatMessage({ id: 'new_receipt' }));
} }
}, [changePageTitle, receipt, formatMessage]); }, [changePageTitle, changePageSubtitle, receipt, formatMessage]);
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
customer_id: Yup.string() customer_id: Yup.string()
@@ -153,10 +171,6 @@ function ReceiptForm({
[], [],
); );
const receiptNumber = receiptNumberPrefix
? `${receiptNumberPrefix}-${receiptNextNumber}`
: receiptNextNumber;
const defaultInitialValues = useMemo( const defaultInitialValues = useMemo(
() => ({ () => ({
customer_id: '', 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( const handleDeleteFile = useCallback(
(_deletedFiles) => { (_deletedFiles) => {
_deletedFiles.forEach((deletedFile) => { _deletedFiles.forEach((deletedFile) => {
@@ -333,14 +360,20 @@ function ReceiptForm({
); );
}; };
useEffect(() => { const handleReceiptNumberChanged = useCallback(
formik.setFieldValue('receipt_number', receiptNumber); (receiptNumber) => {
}, [receiptNumber]); changePageSubtitle(`No. ${receiptNumber}`);
},
[changePageSubtitle],
);
return ( return (
<div className={classNames(CLASSES.PAGE_FORM_RECEIPT, CLASSES.PAGE_FORM)}> <div className={classNames(CLASSES.PAGE_FORM_RECEIPT, CLASSES.PAGE_FORM)}>
<form onSubmit={formik.handleSubmit}> <form onSubmit={formik.handleSubmit}>
<ReceiptFromHeader formik={formik} /> <ReceiptFromHeader
onReceiptNumberChanged={handleReceiptNumberChanged}
formik={formik}
/>
<EntriesItemsTable <EntriesItemsTable
entries={formik.values.entries} entries={formik.values.entries}
@@ -352,6 +385,7 @@ function ReceiptForm({
<div className={classNames(CLASSES.PAGE_FORM_FOOTER)}> <div className={classNames(CLASSES.PAGE_FORM_FOOTER)}>
<Row> <Row>
<Col md={8}> <Col md={8}>
{/* --------- Receipt message --------- */}
<FormGroup <FormGroup
label={<T id={'receipt_message'} />} label={<T id={'receipt_message'} />}
className={'form-group--receipt_message'} className={'form-group--receipt_message'}
@@ -362,6 +396,7 @@ function ReceiptForm({
/> />
</FormGroup> </FormGroup>
{/* --------- Statement--------- */}
<FormGroup <FormGroup
label={<T id={'statement'} />} label={<T id={'statement'} />}
className={'form-group--statement'} className={'form-group--statement'}
@@ -403,4 +438,5 @@ export default compose(
receiptNextNumber: receiptSettings?.nextNumber, receiptNextNumber: receiptSettings?.nextNumber,
receiptNumberPrefix: receiptSettings?.numberPrefix, receiptNumberPrefix: receiptSettings?.numberPrefix,
})), })),
withReceipts(({ receiptNumberChanged }) => ({ receiptNumberChanged })),
)(ReceiptForm); )(ReceiptForm);

View File

@@ -1,16 +1,10 @@
import React, { useMemo, useCallback, useState } from 'react'; import React, { useMemo, useCallback, useState } from 'react';
import { import { FormGroup, InputGroup, Intent, Position } from '@blueprintjs/core';
FormGroup,
InputGroup,
Intent,
Position,
MenuItem,
} from '@blueprintjs/core';
import { DateInput } from '@blueprintjs/datetime'; import { DateInput } from '@blueprintjs/datetime';
import { FormattedMessage as T } from 'react-intl'; import { FormattedMessage as T } from 'react-intl';
import moment from 'moment'; import moment from 'moment';
import { momentFormatter, compose, tansformDateValue } from 'utils'; import { momentFormatter, compose, tansformDateValue, saveInvoke } from 'utils';
import classNames from 'classnames'; import classNames from 'classnames';
import { CLASSES } from 'common/classes'; import { CLASSES } from 'common/classes';
import { import {
@@ -31,10 +25,15 @@ function ReceiptFormHeader({
//#withCustomers //#withCustomers
customers, customers,
//#withAccouts //#withAccouts
accountsList, accountsList,
//#withDialogActions //#withDialogActions
openDialog, openDialog,
// #ownProps
onReceiptNumberChanged,
}) { }) {
const handleDateChange = useCallback( const handleDateChange = useCallback(
(date) => { (date) => {
@@ -64,10 +63,14 @@ function ReceiptFormHeader({
openDialog('receipt-number-form', {}); openDialog('receipt-number-form', {});
}, [openDialog]); }, [openDialog]);
const handleReceiptNumberChanged = (event) => {
saveInvoke(onReceiptNumberChanged, event.currentTarget.value);
};
return ( return (
<div className={classNames(CLASSES.PAGE_FORM_HEADER)}> <div className={classNames(CLASSES.PAGE_FORM_HEADER)}>
<div className={classNames(CLASSES.PAGE_FORM_HEADER_PRIMARY)}> <div className={classNames(CLASSES.PAGE_FORM_HEADER_PRIMARY)}>
{/*- Customer name -*/} {/* ----------- Customer name ----------- */}
<FormGroup <FormGroup
label={<T id={'customer_name'} />} label={<T id={'customer_name'} />}
inline={true} inline={true}
@@ -90,7 +93,7 @@ function ReceiptFormHeader({
/> />
</FormGroup> </FormGroup>
{/*- Deposit account -*/} {/* ----------- Deposit account ----------- */}
<FormGroup <FormGroup
label={<T id={'deposit_account'} />} label={<T id={'deposit_account'} />}
className={classNames( className={classNames(
@@ -119,7 +122,7 @@ function ReceiptFormHeader({
selectedAccountId={values.deposit_account_id} selectedAccountId={values.deposit_account_id}
/> />
</FormGroup> </FormGroup>
{/* ----------- Receipt date ----------- */}
<FormGroup <FormGroup
label={<T id={'receipt_date'} />} label={<T id={'receipt_date'} />}
inline={true} inline={true}
@@ -137,7 +140,7 @@ function ReceiptFormHeader({
/> />
</FormGroup> </FormGroup>
{/* receipt_no */} {/* ----------- Receipt number ----------- */}
<FormGroup <FormGroup
label={<T id={'receipt'} />} label={<T id={'receipt'} />}
inline={true} inline={true}
@@ -169,10 +172,11 @@ function ReceiptFormHeader({
/> />
} }
{...getFieldProps('receipt_number')} {...getFieldProps('receipt_number')}
onBlur={handleReceiptNumberChanged}
/> />
</FormGroup> </FormGroup>
{/*- Reference -*/} {/* ----------- Reference ----------- */}
<FormGroup <FormGroup
label={<T id={'reference'} />} label={<T id={'reference'} />}
inline={true} inline={true}

View File

@@ -28,6 +28,10 @@ const mapDispatchToProps = (dispatch) => ({
type: t.RECEIPTS_TABLE_QUERIES_ADD, type: t.RECEIPTS_TABLE_QUERIES_ADD,
queries, queries,
}), }),
}); setReceiptNumberChanged:(isChanged) => dispatch({
type: t.RECEIPT_NUMBER_CHANGED,
payload: { isChanged },
}),
});
export default connect(null, mapDispatchToProps); export default connect(null, mapDispatchToProps);

View File

@@ -16,11 +16,14 @@ export default (mapState) => {
const mapped = { const mapped = {
receiptsCurrentPage: getReceiptsItems(state, props, tableQuery), receiptsCurrentPage: getReceiptsItems(state, props, tableQuery),
receiptview:getResourceViews(state, props, 'sales_receipts'), receiptview: getResourceViews(state, props, 'sales_receipts'),
receiptItems: state.salesReceipts.items, receiptItems: state.salesReceipts.items,
receiptTableQuery: tableQuery, receiptTableQuery: tableQuery,
receiptsPagination: getReceiptPaginationMeta(state, props, tableQuery), receiptsPagination: getReceiptPaginationMeta(state, props, tableQuery),
receiptsLoading: state.salesReceipts.loading, receiptsLoading: state.salesReceipts.loading,
receiptNumberChanged: state.salesReceipts.journalNumberChanged,
}; };
return mapState ? mapState(mapped, state, props) : mapped; return mapState ? mapState(mapped, state, props) : mapped;

View File

@@ -13,8 +13,7 @@ const initialState = {
page: 1, page: 1,
}, },
currentViewId: -1, currentViewId: -1,
estimateNumberChanged: false,
}; };
const defaultEstimate = { const defaultEstimate = {

View File

@@ -1,5 +1,6 @@
import { createReducer } from '@reduxjs/toolkit'; import { createReducer } from '@reduxjs/toolkit';
import { createTableQueryReducers } from 'store/queryReducers'; import { createTableQueryReducers } from 'store/queryReducers';
import { journalNumberChangedReducer } from 'store/journalNumber.reducer';
import t from 'store/types'; import t from 'store/types';
@@ -114,7 +115,7 @@ const reducer = createReducer(initialState, {
const { customerId, saleInvoices } = action.payload; const { customerId, saleInvoices } = action.payload;
const saleInvoiceIds = saleInvoices.map((saleInvoice) => saleInvoice.id); const saleInvoiceIds = saleInvoices.map((saleInvoice) => saleInvoice.id);
state.receivable.byCustomerId[customerId] = saleInvoiceIds state.receivable.byCustomerId[customerId] = saleInvoiceIds;
}, },
[t.INVOICES_BY_PAYMENT_ID]: (state, action) => { [t.INVOICES_BY_PAYMENT_ID]: (state, action) => {
@@ -123,6 +124,8 @@ const reducer = createReducer(initialState, {
state.byPaymentReceiveId[paymentReceiveId] = saleInvoiceIds; state.byPaymentReceiveId[paymentReceiveId] = saleInvoiceIds;
}, },
...journalNumberChangedReducer(t.INVOICE_NUMBER_CHANGED),
}); });
export default createTableQueryReducers('sales_invoices', reducer); export default createTableQueryReducers('sales_invoices', reducer);

View File

@@ -14,5 +14,7 @@ export default {
INVOICES_RECEIVABLE_BY_PAYMENT_ID: 'INVOICES_RECEIVABLE_BY_PAYMENT_ID', INVOICES_RECEIVABLE_BY_PAYMENT_ID: 'INVOICES_RECEIVABLE_BY_PAYMENT_ID',
INVOICES_RECEIVABLE_BY_CUSTOMER_ID: 'INVOICES_RECEIVABLE_BY_CUSTOMER_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',
}; };

View File

@@ -1,6 +1,7 @@
import { createReducer } from '@reduxjs/toolkit'; import { createReducer } from '@reduxjs/toolkit';
import { createTableQueryReducers } from 'store/queryReducers'; import { createTableQueryReducers } from 'store/queryReducers';
import t from 'store/types'; import t from 'store/types';
import { journalNumberChangedReducer } from 'store/journalNumber.reducer';
const initialState = { const initialState = {
items: {}, items: {},
@@ -18,14 +19,12 @@ const defaultReceipt = {
}; };
const reducer = createReducer(initialState, { const reducer = createReducer(initialState, {
[t.RECEIPT_SET]: (state, action) => { [t.RECEIPT_SET]: (state, action) => {
const { id, sale_receipt } = action.payload; const { id, sale_receipt } = action.payload;
const _receipt = state.items[id] || {}; const _receipt = state.items[id] || {};
state.items[id] = { ...defaultReceipt, ..._receipt, ...sale_receipt }; state.items[id] = { ...defaultReceipt, ..._receipt, ...sale_receipt };
}, },
[t.RECEIPTS_ITEMS_SET]: (state, action) => { [t.RECEIPTS_ITEMS_SET]: (state, action) => {
const { sales_receipts } = action.payload; const { sales_receipts } = action.payload;
const _receipts = {}; const _receipts = {};
@@ -94,6 +93,7 @@ const reducer = createReducer(initialState, {
}, },
}; };
}, },
...journalNumberChangedReducer(t.RECEIPT_NUMBER_CHANGED),
}); });
export default createTableQueryReducers('sales_receipts', reducer); export default createTableQueryReducers('sales_receipts', reducer);

View File

@@ -9,4 +9,5 @@ export default {
RECEIPTS_PAGINATION_SET: 'RECEIPTS_PAGINATION_SET', RECEIPTS_PAGINATION_SET: 'RECEIPTS_PAGINATION_SET',
RECEIPTS_PAGE_SET: 'RECEIPTS_PAGE_SET', RECEIPTS_PAGE_SET: 'RECEIPTS_PAGE_SET',
RECEIPTS_ITEMS_SET: 'RECEIPTS_ITEMS_SET', RECEIPTS_ITEMS_SET: 'RECEIPTS_ITEMS_SET',
RECEIPT_NUMBER_CHANGED:'RECEIPT_NUMBER_CHANGED'
}; };