From 43b91503d2d8e947d3af8cc33db4877ebfce9d94 Mon Sep 17 00:00:00 2001
From: elforjani13 <39470382+elforjani13@users.noreply.github.com>
Date: Wed, 1 Dec 2021 14:02:54 +0200
Subject: [PATCH] feat: add auto increment in vendor credit number.
---
.../VendorCreditNumberDialogContent.js | 102 ++++++++++++++++++
.../VendorCreditNumberDilaogProvider.js | 28 +++++
.../Dialogs/VendorCreditNumberDialog/index.js | 40 +++++++
.../CreditNoteForm/VendorCreditNoteForm.js | 32 +++++-
.../VendorCreditNoteFormDialogs.js | 27 +++++
.../VendorCreditNoteFormHeaderFields.js | 91 ++++++++++++++--
.../VendorCreditNoteFormProvider.js | 4 +
.../CreditNotes/CreditNoteForm/utils.js | 15 +++
.../VendorsCreditNoteActionsBar.js | 2 +-
src/containers/Settings/withSettings.js | 4 +-
src/hooks/query/settings.js | 21 ++++
src/hooks/query/types.js | 2 +
src/hooks/query/vendorCredit.js | 3 +
src/lang/en/index.json | 10 +-
src/store/settings/settings.reducer.js | 4 +-
15 files changed, 366 insertions(+), 19 deletions(-)
create mode 100644 src/containers/Dialogs/VendorCreditNumberDialog/VendorCreditNumberDialogContent.js
create mode 100644 src/containers/Dialogs/VendorCreditNumberDialog/VendorCreditNumberDilaogProvider.js
create mode 100644 src/containers/Dialogs/VendorCreditNumberDialog/index.js
create mode 100644 src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormDialogs.js
diff --git a/src/containers/Dialogs/VendorCreditNumberDialog/VendorCreditNumberDialogContent.js b/src/containers/Dialogs/VendorCreditNumberDialog/VendorCreditNumberDialogContent.js
new file mode 100644
index 000000000..b9dcecc61
--- /dev/null
+++ b/src/containers/Dialogs/VendorCreditNumberDialog/VendorCreditNumberDialogContent.js
@@ -0,0 +1,102 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+import { useSaveSettings } from 'hooks/query';
+
+import { VendorCreditNumberDilaogProvider } from './VendorCreditNumberDilaogProvider';
+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 { compose } from 'utils';
+import {
+ transformFormToSettings,
+ transformSettingsToForm,
+} from 'containers/JournalNumber/utils';
+
+/**
+ * Vendor credit number dialog
+ */
+function VendorCreditNumberDialogContent({
+ // #ownProps
+ initialValues,
+ onConfirm,
+
+ // #withSettings
+ nextNumber,
+ numberPrefix,
+ autoIncrement,
+
+ // #withDialogActions
+ closeDialog,
+}) {
+ const { mutateAsync: saveSettings } = useSaveSettings();
+ const [referenceFormValues, setReferenceFormValues] = React.useState(null);
+
+ // Handle the submit form.
+ const handleSubmitForm = (values, { setSubmitting }) => {
+ // Handle the form success.
+ const handleSuccess = () => {
+ setSubmitting(false);
+ closeDialog('vendor-credit-form');
+ onConfirm(values);
+ };
+ // Handle the form errors.
+ const handleErrors = () => {
+ setSubmitting(false);
+ };
+ if (values.incrementMode === 'manual-transaction') {
+ handleSuccess();
+ return;
+ }
+ // Transformes the form values to settings to save it.
+ const options = transformFormToSettings(values, 'vendor_credit');
+
+ // Save the settings.
+ saveSettings({ options }).then(handleSuccess).catch(handleErrors);
+ };
+
+ // Handle the dialog close.
+ const handleClose = () => {
+ closeDialog('vendor-credit-form');
+ };
+ // Handle form change.
+ const handleChange = (values) => {
+ setReferenceFormValues(values);
+ };
+
+ // Description.
+ const description =
+ referenceFormValues?.incrementMode === 'auto'
+ ? intl.get('vendor_credit.auto_increment.auto')
+ : intl.get('vendor_credit.auto_increment.manually');
+
+ return (
+
+
+
+ );
+}
+
+export default compose(
+ withDialogActions,
+ withSettingsActions,
+ withSettings(({ vendorsCreditNoteSetting }) => ({
+ autoIncrement: vendorsCreditNoteSetting?.autoIncrement,
+ nextNumber: vendorsCreditNoteSetting?.nextNumber,
+ numberPrefix: vendorsCreditNoteSetting?.numberPrefix,
+ })),
+)(VendorCreditNumberDialogContent);
diff --git a/src/containers/Dialogs/VendorCreditNumberDialog/VendorCreditNumberDilaogProvider.js b/src/containers/Dialogs/VendorCreditNumberDialog/VendorCreditNumberDilaogProvider.js
new file mode 100644
index 000000000..0d285b6fc
--- /dev/null
+++ b/src/containers/Dialogs/VendorCreditNumberDialog/VendorCreditNumberDilaogProvider.js
@@ -0,0 +1,28 @@
+import React from 'react';
+import { DialogContent } from 'components';
+import { useSettingsVendorCredits } from 'hooks/query';
+
+const VendorCreditNumberDialogContext = React.createContext();
+
+/**
+ * Vendor credit number dialog provider
+ */
+function VendorCreditNumberDilaogProvider({ query, ...props }) {
+ const { isLoading: isSettingsLoading } = useSettingsVendorCredits();
+
+ // Provider payload.
+ const provider = {
+ isSettingsLoading,
+ };
+
+ return (
+
+
+
+ );
+}
+
+const useVendorCreditNumberDialogContext = () =>
+ React.useContext(VendorCreditNumberDialogContext);
+
+export { VendorCreditNumberDilaogProvider, useVendorCreditNumberDialogContext };
diff --git a/src/containers/Dialogs/VendorCreditNumberDialog/index.js b/src/containers/Dialogs/VendorCreditNumberDialog/index.js
new file mode 100644
index 000000000..e92fdf702
--- /dev/null
+++ b/src/containers/Dialogs/VendorCreditNumberDialog/index.js
@@ -0,0 +1,40 @@
+import React from 'react';
+import { Dialog, DialogSuspense, FormattedMessage as T } from 'components';
+import withDialogRedux from 'components/DialogReduxConnect';
+import { compose, saveInvoke } from 'utils';
+
+const VendorCreditNumberDialogContent = React.lazy(() =>
+ import('./VendorCreditNumberDialogContent'),
+);
+
+/**
+ * Vendor Credit number dialog.
+ */
+function VendorCreditNumberDialog({
+ dialogName,
+ payload: { initialFormValues },
+ isOpen,
+ onConfirm,
+}) {
+ const handleConfirm = (values) => {
+ saveInvoke(onConfirm, values);
+ };
+
+ return (
+ }
+ name={dialogName}
+ autoFocus={true}
+ canEscapeKeyClose={true}
+ isOpen={isOpen}
+ >
+
+
+
+
+ );
+}
+export default compose(withDialogRedux())(VendorCreditNumberDialog);
diff --git a/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteForm.js b/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteForm.js
index e48b31edf..05fed2f74 100644
--- a/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteForm.js
+++ b/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteForm.js
@@ -15,23 +15,31 @@ import VendorCreditNoteFormHeader from './VendorCreditNoteFormHeader';
import VendorCreditNoteItemsEntriesEditor from './VendorCreditNoteItemsEntriesEditor';
import VendorCreditNoteFormFooter from './VendorCreditNoteFormFooter';
import VendorCreditNoteFloatingActions from './VendorCreditNoteFloatingActions';
+import VendorCreditNoteFormDialogs from './VendorCreditNoteFormDialogs';
+
import { useVendorCreditNoteFormContext } from './VendorCreditNoteFormProvider';
import { AppToaster } from 'components';
-
-import { compose, safeSumBy } from 'utils';
+import { compose, safeSumBy, transactionNumber } from 'utils';
import {
defaultVendorsCreditNote,
filterNonZeroEntries,
transformToEditForm,
transformFormValuesToRequest,
} from './utils';
+
+import withSettings from 'containers/Settings/withSettings';
import withCurrentOrganization from 'containers/Organization/withCurrentOrganization';
/**
* Vendor Credit note form.
*/
function VendorCreditNoteForm({
+ // #withSettings
+ vendorcreditAutoIncrement,
+ vendorcreditNumberPrefix,
+ vendorcreditNextNumber,
+
// #withCurrentOrganization
organization: { base_currency },
}) {
@@ -46,6 +54,12 @@ function VendorCreditNoteForm({
editVendorCreditMutate,
} = useVendorCreditNoteFormContext();
+ // Credit number.
+ const vendorCreditNumber = transactionNumber(
+ vendorcreditNumberPrefix,
+ vendorcreditNextNumber,
+ );
+
// Initial values.
const initialValues = React.useMemo(
() => ({
@@ -55,6 +69,9 @@ function VendorCreditNoteForm({
}
: {
...defaultVendorsCreditNote,
+ ...(vendorcreditAutoIncrement && {
+ vendor_credit_number: vendorCreditNumber,
+ }),
}),
}),
[vendorCredit, base_currency],
@@ -134,12 +151,19 @@ function VendorCreditNoteForm({
-
+
);
}
-export default compose(withCurrentOrganization())(VendorCreditNoteForm);
+export default compose(
+ withSettings(({ vendorsCreditNoteSetting }) => ({
+ vendorcreditAutoIncrement: vendorsCreditNoteSetting?.autoIncrement,
+ vendorcreditNextNumber: vendorsCreditNoteSetting?.nextNumber,
+ vendorcreditNumberPrefix: vendorsCreditNoteSetting?.numberPrefix,
+ })),
+ withCurrentOrganization(),
+)(VendorCreditNoteForm);
diff --git a/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormDialogs.js b/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormDialogs.js
new file mode 100644
index 000000000..5d5d69df2
--- /dev/null
+++ b/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormDialogs.js
@@ -0,0 +1,27 @@
+import React from 'react';
+import VendorCreditNumberDialog from '../../../Dialogs/VendorCreditNumberDialog';
+import { useFormikContext } from 'formik';
+
+/**
+ * Vendor credit form dialog.
+ */
+export default function VendorCreditNoteFormDialogs() {
+ // Update the form once the vendor credit number form submit confirm.
+ const handleVendorCreditNumberFormConfirm = ({
+ incrementNumber,
+ manually,
+ }) => {
+ setFieldValue('vendor_credit_number', incrementNumber || '');
+ setFieldValue('vendor_credit_no_manually', manually);
+ };
+ const { setFieldValue } = useFormikContext();
+
+ return (
+
+
+
+ );
+}
diff --git a/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormHeaderFields.js b/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormHeaderFields.js
index 120d59b5d..e93db9c63 100644
--- a/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormHeaderFields.js
+++ b/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormHeaderFields.js
@@ -1,5 +1,10 @@
import React from 'react';
-import { FormGroup, InputGroup, Position } from '@blueprintjs/core';
+import {
+ FormGroup,
+ InputGroup,
+ Position,
+ ControlGroup,
+} from '@blueprintjs/core';
import { DateInput } from '@blueprintjs/datetime';
import { FastField, Field, ErrorMessage } from 'formik';
import { CLASSES } from 'common/classes';
@@ -7,10 +12,14 @@ import classNames from 'classnames';
import {
ContactSelecetList,
FieldRequiredHint,
+ InputPrependButton,
Icon,
FormattedMessage as T,
} from 'components';
-import { vendorsFieldShouldUpdate } from './utils';
+import {
+ vendorsFieldShouldUpdate,
+ useObserveVendorCreditNoSettings,
+} from './utils';
import { useVendorCreditNoteFormContext } from './VendorCreditNoteFormProvider';
@@ -22,13 +31,48 @@ import {
handleDateChange,
} from 'utils';
+import withSettings from 'containers/Settings/withSettings';
+import withDialogActions from 'containers/Dialog/withDialogActions';
+
/**
* Vendor Credit note form header fields.
*/
+function VendorCreditNoteFormHeaderFields({
+ // #withDialogActions
+ openDialog,
-function VendorCreditNoteFormHeaderFields() {
- // Credit note form context.
+ // #withSettings
+ vendorcreditAutoIncrement,
+ vendorcreditNumberPrefix,
+ vendorcreditNextNumber,
+}) {
+ // Vendor Credit form context.
const { vendors } = useVendorCreditNoteFormContext();
+
+ // Handle vendor credit number changing.
+ const handleVendorCreditNumberChange = () => {
+ openDialog('vendor-credit-form');
+ };
+
+ // Handle vendor credit no. field blur.
+ const handleVendorCreditNoBlur = (form, field) => (event) => {
+ const newValue = event.target.value;
+
+ if (field.value !== newValue && vendorcreditAutoIncrement) {
+ openDialog('vendor-credit-form', {
+ initialFormValues: {
+ manualTransactionNo: newValue,
+ incrementMode: 'manual-transaction',
+ },
+ });
+ }
+ };
+ // Syncs vendor credit number settings with form.
+ useObserveVendorCreditNoSettings(
+ vendorcreditNumberPrefix,
+ vendorcreditNextNumber,
+ );
+
return (
{/* ----------- Vendor name ----------- */}
@@ -94,7 +138,7 @@ function VendorCreditNoteFormHeaderFields() {
{/* ----------- Vendor Credit No # ----------- */}
- {({ field, meta: { error, touched } }) => (
+ {({ form, field, meta: { error, touched } }) => (
}
inline={true}
@@ -102,12 +146,34 @@ function VendorCreditNoteFormHeaderFields() {
intent={inputIntent({ error, touched })}
helperText={}
>
-
+
+
+ ,
+ }}
+ tooltip={true}
+ tooltipProps={{
+ content: (
+
+ ),
+ position: Position.BOTTOM_LEFT,
+ }}
+ />
+
)}
{/* ----------- Reference ----------- */}
- {/*
+
{({ field, meta: { error, touched } }) => (
}
@@ -119,9 +185,16 @@ function VendorCreditNoteFormHeaderFields() {
)}
- */}
+
);
}
-export default VendorCreditNoteFormHeaderFields;
+export default compose(
+ withDialogActions,
+ withSettings(({ vendorsCreditNoteSetting }) => ({
+ vendorcreditAutoIncrement: vendorsCreditNoteSetting?.autoIncrement,
+ vendorcreditNextNumber: vendorsCreditNoteSetting?.nextNumber,
+ vendorcreditNumberPrefix: vendorsCreditNoteSetting?.numberPrefix,
+ })),
+)(VendorCreditNoteFormHeaderFields);
diff --git a/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormProvider.js b/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormProvider.js
index b3e74703b..184c68772 100644
--- a/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormProvider.js
+++ b/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormProvider.js
@@ -7,6 +7,7 @@ import {
useVendorCredit,
useItems,
useVendors,
+ useSettingsVendorCredits,
} from 'hooks/query';
const VendorCreditNoteFormContext = React.createContext();
@@ -23,6 +24,9 @@ function VendorCreditNoteFormProvider({ vendorCreditId, ...props }) {
page_size: 10000,
});
+ // Handle fetching settings.
+ useSettingsVendorCredits();
+
// Handle fetch vendors data table or list
const {
data: { vendors },
diff --git a/src/containers/Purchases/CreditNotes/CreditNoteForm/utils.js b/src/containers/Purchases/CreditNotes/CreditNoteForm/utils.js
index 114dc1580..4e2232e70 100644
--- a/src/containers/Purchases/CreditNotes/CreditNoteForm/utils.js
+++ b/src/containers/Purchases/CreditNotes/CreditNoteForm/utils.js
@@ -6,12 +6,14 @@ import {
defaultFastFieldShouldUpdate,
transformToForm,
repeatValue,
+ transactionNumber,
orderingLinesIndexes,
} from 'utils';
import {
updateItemsEntriesTotal,
ensureEntriesHaveEmptyLine,
} from 'containers/Entries/utils';
+import { useFormikContext } from 'formik';
export const MIN_LINES_NUMBER = 4;
@@ -30,6 +32,7 @@ export const defaultCreditNoteEntry = {
export const defaultVendorsCreditNote = {
vendor_id: '',
vendor_credit_number: '',
+ vendor_credit_no_manually: false,
vendor_credit_date: moment(new Date()).format('YYYY-MM-DD'),
// reference_no: '',
note: '',
@@ -112,3 +115,15 @@ export const entriesFieldShouldUpdate = (newProps, oldProps) => {
defaultFastFieldShouldUpdate(newProps, oldProps)
);
};
+
+/**
+ * Syncs invoice no. settings with form.
+ */
+ export const useObserveVendorCreditNoSettings = (prefix, nextNumber) => {
+ const { setFieldValue } = useFormikContext();
+
+ React.useEffect(() => {
+ const creditNo = transactionNumber(prefix, nextNumber);
+ setFieldValue('vendor_credit_number', creditNo);
+ }, [setFieldValue, prefix, nextNumber]);
+};
diff --git a/src/containers/Purchases/CreditNotes/CreditNotesLanding/VendorsCreditNoteActionsBar.js b/src/containers/Purchases/CreditNotes/CreditNotesLanding/VendorsCreditNoteActionsBar.js
index e52077150..681b5da68 100644
--- a/src/containers/Purchases/CreditNotes/CreditNotesLanding/VendorsCreditNoteActionsBar.js
+++ b/src/containers/Purchases/CreditNotes/CreditNotesLanding/VendorsCreditNoteActionsBar.js
@@ -66,7 +66,7 @@ function VendorsCreditNoteActionsBar({
// Handle table row size change.
const handleTableRowSizeChange = (size) => {
- addSetting('vendorCredits', 'tableSize', size);
+ addSetting('vendorCredit', 'tableSize', size);
};
return (
diff --git a/src/containers/Settings/withSettings.js b/src/containers/Settings/withSettings.js
index 6acdcb53b..867e56dc7 100644
--- a/src/containers/Settings/withSettings.js
+++ b/src/containers/Settings/withSettings.js
@@ -19,8 +19,8 @@ export default (mapState) => {
cashflowSettings: state.settings.data.cashflowAccounts,
cashflowTransactionsSettings: state.settings.data.cashflowTransactions,
cashflowSetting: state.settings.data.cashflow,
- creditNoteSettings: state.settings.data.creditNotes,
- vendorsCreditNoteSetting: state.settings.data.vendorCredits,
+ creditNoteSettings: state.settings.data.creditNote,
+ vendorsCreditNoteSetting: state.settings.data.vendorCredit,
};
return mapState ? mapState(mapped, state, props) : mapped;
};
diff --git a/src/hooks/query/settings.js b/src/hooks/query/settings.js
index b7c70b335..4575307aa 100644
--- a/src/hooks/query/settings.js
+++ b/src/hooks/query/settings.js
@@ -123,6 +123,27 @@ export function useSettingCashFlow(props) {
);
}
+/**
+ * Retrieve credit notes settings.
+ */
+export function useSettingsCreditNotes(props) {
+ return useSettingsQuery(
+ [t.SETTING, t.SETTING_CREDIT_NOTES],
+ { group: 'credit_note' },
+ props,
+ );
+}
+/**
+ * Retrieve vendor credit settings.
+ */
+export function useSettingsVendorCredits(props) {
+ return useSettingsQuery(
+ [t.SETTING, t.SETTING_VENDOR_CREDITS],
+ { group: 'vendor_credit' },
+ props,
+ );
+}
+
/**
* Retrieve SMS Notifications settings.
*/
diff --git a/src/hooks/query/types.js b/src/hooks/query/types.js
index a32093703..374c6540c 100644
--- a/src/hooks/query/types.js
+++ b/src/hooks/query/types.js
@@ -130,6 +130,8 @@ const SETTING = {
SETTING_SMS_NOTIFICATION: 'SETTING_SMS_NOTIFICATION',
SETTING_SMS_NOTIFICATIONS: 'SETTING_SMS_NOTIFICATIONS',
SETTING_EDIT_SMS_NOTIFICATION: 'SETTING_EDIT_SMS_NOTIFICATION',
+ SETTING_CREDIT_NOTES: 'SETTING_CREDIT_NOTES',
+ SETTING_VENDOR_CREDITS: 'SETTING_VENDOR_CREDITS',
};
const ORGANIZATIONS = {
diff --git a/src/hooks/query/vendorCredit.js b/src/hooks/query/vendorCredit.js
index f4867aceb..272d30ab7 100644
--- a/src/hooks/query/vendorCredit.js
+++ b/src/hooks/query/vendorCredit.js
@@ -21,6 +21,9 @@ const commonInvalidateQueries = (queryClient) => {
queryClient.invalidateQueries(t.ACCOUNTS);
queryClient.invalidateQueries(t.ACCOUNT);
+ // Invalidate settings.
+ queryClient.invalidateQueries([t.SETTING, t.SETTING_VENDOR_CREDITS]);
+
// Invalidate financial reports.
queryClient.invalidateQueries(t.FINANCIAL_REPORT);
};
diff --git a/src/lang/en/index.json b/src/lang/en/index.json
index 17677d624..6c2ef8dcd 100644
--- a/src/lang/en/index.json
+++ b/src/lang/en/index.json
@@ -1516,5 +1516,13 @@
"vendor_credits.success_message": "The vendor credit has been created successfully",
"vendor_credits.edit_success_message": "The vendor credit has been edited successfully.",
"vendor_credits.alert.success_message": "The given vendor credit has been deleted successfully.",
- "vendor_credits.note.once_delete_this_vendor_credit_note": "Once you delete this vendor credit , you won't be able to restore it later. Are you sure you want to delete this vendor credit ?"
+ "vendor_credits.note.once_delete_this_vendor_credit_note": "Once you delete this vendor credit , you won't be able to restore it later. Are you sure you want to delete this vendor credit ?",
+ "credit_note_number_settings": "Credit Note Number Settings",
+ "credit_note.auto_increment.auto": "Your credit note numbers are set on auto-increment mode. Are you sure changing this setting?",
+ "credit_note.auto_increment.manually": "Your credit note numbers are set on manual mode. Are you sure chaning this settings?",
+ "setting_your_auto_generated_credit_note_number": "Setting your auto-generated credit note number",
+ "vendor_credit_number_settings": "Vendor Credit Number Settings",
+ "vendor_credit.auto_increment.auto": "Your vendor credit numbers are set on auto-increment mode. Are you sure changing this setting?",
+ "vendor_credit.auto_increment.manually": "Your vendor credit numbers are set on manual mode. Are you sure chaning this settings?",
+ "setting_your_auto_generated_vendor_credit_number": "Setting your auto-generated vendor credit number"
}
\ No newline at end of file
diff --git a/src/store/settings/settings.reducer.js b/src/store/settings/settings.reducer.js
index 2498a04bd..853ab0589 100644
--- a/src/store/settings/settings.reducer.js
+++ b/src/store/settings/settings.reducer.js
@@ -52,10 +52,10 @@ const initialState = {
cashflowTransactions: {
tableSize: 'medium',
},
- creditNotes: {
+ creditNote: {
tableSize: 'medium',
},
- vendorCredits: {
+ vendorCredit: {
tableSize: 'medium',
},
},