fix: the auto-increment of transactions.

This commit is contained in:
a.bouhuolia
2023-05-19 00:29:35 +02:00
parent 425d0293cc
commit d369f0bb17
37 changed files with 383 additions and 221 deletions

View File

@@ -4,7 +4,7 @@ import { Formik, Form } from 'formik';
import { Intent } from '@blueprintjs/core';
import intl from 'react-intl-universal';
import * as R from 'ramda';
import { defaultTo, isEmpty, omit } from 'lodash';
import { isEmpty, omit } from 'lodash';
import classNames from 'classnames';
import { useHistory } from 'react-router-dom';
@@ -31,6 +31,7 @@ import {
transformToEditForm,
defaultManualJournal,
} from './utils';
import { JournalSyncIncrementSettingsToForm } from './components';
/**
* Journal entries form.
@@ -40,6 +41,7 @@ function MakeJournalEntriesForm({
journalNextNumber,
journalNumberPrefix,
journalAutoIncrement,
// #withCurrentOrganization
organization: { base_currency },
}) {
@@ -179,6 +181,9 @@ function MakeJournalEntriesForm({
{/* --------- Dialogs --------- */}
<MakeJournalFormDialogs />
{/* --------- Effects --------- */}
<JournalSyncIncrementSettingsToForm />
</Form>
</Formik>
</div>

View File

@@ -8,6 +8,19 @@ import { PageFormBigNumber, FormattedMessage as T } from '@/components';
import MakeJournalEntriesHeaderFields from './MakeJournalEntriesHeaderFields';
export default function MakeJournalEntriesHeader() {
return (
<div className={classNames(CLASSES.PAGE_FORM_HEADER)}>
<MakeJournalEntriesHeaderFields />
<MakeJournalHeaderBigNumber />
</div>
);
}
/**
* Big total number of make journal header.
* @returns {React.ReactNode}
*/
function MakeJournalHeaderBigNumber() {
const {
values: { entries, currency_code },
} = useFormikContext();
@@ -17,14 +30,10 @@ export default function MakeJournalEntriesHeader() {
const total = Math.max(totalCredit, totalDebit);
return (
<div className={classNames(CLASSES.PAGE_FORM_HEADER)}>
<MakeJournalEntriesHeaderFields />
<PageFormBigNumber
label={<T id={'amount'} />}
amount={total}
currencyCode={currency_code}
/>
</div>
<PageFormBigNumber
label={<T id={'amount'} />}
amount={total}
currencyCode={currency_code}
/>
);
}

View File

@@ -25,30 +25,24 @@ import {
Icon,
InputPrependButton,
CurrencySelectList,
FormattedMessage as T
FormattedMessage as T,
} from '@/components';
import { useMakeJournalFormContext } from './MakeJournalProvider';
import { JournalExchangeRateInputField } from './components';
import { currenciesFieldShouldUpdate } from './utils';
import withSettings from '@/containers/Settings/withSettings';
import withDialogActions from '@/containers/Dialog/withDialogActions';
import {
currenciesFieldShouldUpdate,
useObserveJournalNoSettings,
} from './utils';
/**
* Make journal entries header.
*/
function MakeJournalEntriesHeader({
// #ownProps
onJournalNumberChanged,
// #withDialog
openDialog,
// #withSettings
journalAutoIncrement,
journalNextNumber,
journalNumberPrefix,
}) {
const { currencies } = useMakeJournalFormContext();
@@ -71,8 +65,6 @@ function MakeJournalEntriesHeader({
}
};
useObserveJournalNoSettings(journalNumberPrefix, journalNextNumber);
return (
<div className={classNames(CLASSES.PAGE_FORM_HEADER_FIELDS)}>
{/*------------ Posting date -----------*/}
@@ -224,7 +216,5 @@ export default compose(
withDialogActions,
withSettings(({ manualJournalsSettings }) => ({
journalAutoIncrement: manualJournalsSettings?.autoIncrement,
journalNextNumber: manualJournalsSettings?.nextNumber,
journalNumberPrefix: manualJournalsSettings?.numberPrefix,
})),
)(MakeJournalEntriesHeader);

View File

@@ -16,11 +16,9 @@ export default function MakeJournalFormDialogs() {
};
return (
<>
<JournalNumberDialog
dialogName={'journal-number-form'}
onConfirm={handleConfirm}
/>
</>
<JournalNumberDialog
dialogName={'journal-number-form'}
onConfirm={handleConfirm}
/>
);
}

View File

@@ -1,9 +1,10 @@
// @ts-nocheck
import React from 'react';
import React, { useEffect } from 'react';
import intl from 'react-intl-universal';
import { Menu, MenuItem, Position, Button } from '@blueprintjs/core';
import { Popover2 } from '@blueprintjs/popover2';
import { useFormikContext } from 'formik';
import * as R from 'ramda';
import {
ExchangeRateInputGroup,
@@ -24,6 +25,9 @@ import { CellType, Features, Align } from '@/constants';
import { useCurrentOrganization, useFeatureCan } from '@/hooks/state';
import { useJournalIsForeign } from './utils';
import withSettings from '@/containers/Settings/withSettings';
import { transactionNumber } from '@/utils';
import { useUpdateEffect } from '@/hooks';
/**
* Contact header cell.
@@ -199,3 +203,34 @@ export function JournalExchangeRateInputField({ ...props }) {
/>
);
}
/**
* Syncs journal auto-increment settings to form.
* @return {React.ReactNode}
*/
export const JournalSyncIncrementSettingsToForm = R.compose(
withSettings(({ manualJournalsSettings }) => ({
journalAutoIncrement: manualJournalsSettings?.autoIncrement,
journalNextNumber: manualJournalsSettings?.nextNumber,
journalNumberPrefix: manualJournalsSettings?.numberPrefix,
})),
)(({ journalAutoIncrement, journalNextNumber, journalNumberPrefix }) => {
const { setFieldValue } = useFormikContext();
useUpdateEffect(() => {
if (!journalAutoIncrement) return null;
const journalNo = transactionNumber(journalNumberPrefix, journalNextNumber);
setFieldValue('journal_number', journalNo);
}, [
setFieldValue,
journalNumberPrefix,
journalNextNumber,
journalAutoIncrement,
]);
return null;
});
JournalSyncIncrementSettingsToForm.displayName =
'JournalSyncIncrementSettingsToForm';

View File

@@ -174,15 +174,6 @@ export const transformErrors = (resErrors, { setErrors, errors }) => {
}
};
export const useObserveJournalNoSettings = (prefix, nextNumber) => {
const { setFieldValue } = useFormikContext();
React.useEffect(() => {
const journalNo = transactionNumber(prefix, nextNumber);
setFieldValue('journal_number', journalNo);
}, [setFieldValue, prefix, nextNumber]);
};
/**
* Detarmines entries fast field should update.
*/

View File

@@ -14,6 +14,7 @@ import {
transformFormToSettings,
transformSettingsToForm,
} from '@/containers/JournalNumber/utils';
import { DialogsName } from '@/constants/dialogs';
/**
* invoice number dialog's content.
@@ -39,7 +40,7 @@ function InvoiceNumberDialogContent({
// Handle the form success.
const handleSuccess = () => {
setSubmitting(false);
closeDialog('invoice-number-form');
closeDialog(DialogsName.InvoiceNumberSettings);
onConfirm(values);
};
// Handle the form errors.
@@ -56,10 +57,9 @@ function InvoiceNumberDialogContent({
// Save the settings.
saveSettings({ options }).then(handleSuccess).catch(handleErrors);
};
// Handle the dialog close.
const handleClose = () => {
closeDialog('invoice-number-form');
closeDialog(DialogsName.InvoiceNumberSettings);
};
// Handle form change.
const handleChange = (values) => {
@@ -71,17 +71,19 @@ function InvoiceNumberDialogContent({
? intl.get('invoice.auto_increment.auto')
: intl.get('invoice.auto_increment.manually');
const initialFormValues = {
...transformSettingsToForm({
nextNumber,
numberPrefix,
autoIncrement,
}),
...initialValues,
};
return (
<InvoiceNumberDialogProvider>
<ReferenceNumberForm
initialValues={{
...transformSettingsToForm({
nextNumber,
numberPrefix,
autoIncrement,
}),
...initialValues,
}}
initialValues={initialFormValues}
description={description}
onSubmit={handleSubmitForm}
onClose={handleClose}

View File

@@ -16,10 +16,10 @@ import { saveInvoke } from '@/utils';
* Reference number form.
*/
export default function ReferenceNumberForm({
onSubmit,
onClose,
initialValues,
description,
onSubmit,
onClose,
onChange,
}) {
// Validation schema.

View File

@@ -14,7 +14,7 @@ export const defaultInvoiceNoSettings = {
export const transformSettingsToForm = (settings) => ({
...settings,
incrementMode: settings.autoIncrement === 'true' ? 'auto' : 'manual',
incrementMode: settings.autoIncrement ? 'auto' : 'manual',
});
export const transformFormToSettings = (values, group) => {

View File

@@ -13,6 +13,15 @@ import BillFormHeaderFields from './BillFormHeaderFields';
* Fill form header.
*/
function BillFormHeader() {
return (
<div className={classNames(CLASSES.PAGE_FORM_HEADER)}>
<BillFormHeaderFields />
<BillFormBigTotal />
</div>
);
}
function BillFormBigTotal() {
const {
values: { currency_code, entries },
} = useFormikContext();
@@ -21,14 +30,12 @@ function BillFormHeader() {
const totalDueAmount = useMemo(() => sumBy(entries, 'amount'), [entries]);
return (
<div className={classNames(CLASSES.PAGE_FORM_HEADER)}>
<BillFormHeaderFields />
<PageFormBigNumber
label={intl.get('due_amount')}
amount={totalDueAmount}
currencyCode={currency_code}
/>
</div>
<PageFormBigNumber
label={intl.get('due_amount')}
amount={totalDueAmount}
currencyCode={currency_code}
/>
);
}
export default BillFormHeader;

View File

@@ -38,6 +38,7 @@ import {
import withSettings from '@/containers/Settings/withSettings';
import withCurrentOrganization from '@/containers/Organization/withCurrentOrganization';
import { CreditNoteSyncIncrementSettingsToForm } from './components';
/**
* Credit note form.
@@ -162,6 +163,7 @@ function CreditNoteForm({
<CreditNoteFormFooter />
<CreditNoteFloatingActions />
<CreditNoteFormDialogs />
<CreditNoteSyncIncrementSettingsToForm />
</Form>
</Formik>
</div>

View File

@@ -13,6 +13,19 @@ import { PageFormBigNumber } from '@/components';
* Credit note header.
*/
function CreditNoteFormHeader() {
return (
<div className={classNames(CLASSES.PAGE_FORM_HEADER)}>
<CreditNoteFormHeaderFields />
<CreditNoteFormBigNumber />
</div>
);
}
/**
* Big total number of credit note form header.
* @returns {React.ReactNode}
*/
function CreditNoteFormBigNumber() {
const {
values: { entries, currency_code },
} = useFormikContext();
@@ -21,14 +34,11 @@ function CreditNoteFormHeader() {
const totalAmount = React.useMemo(() => getEntriesTotal(entries), [entries]);
return (
<div className={classNames(CLASSES.PAGE_FORM_HEADER)}>
<CreditNoteFormHeaderFields />
<PageFormBigNumber
label={intl.get('credit_note.label_amount_to_credit')}
amount={totalAmount}
currencyCode={currency_code}
/>
</div>
<PageFormBigNumber
label={intl.get('credit_note.label_amount_to_credit')}
amount={totalAmount}
currencyCode={currency_code}
/>
);
}

View File

@@ -21,7 +21,6 @@ import {
} from '@/components';
import {
customerNameFieldShouldUpdate,
useObserveCreditNoSettings,
} from './utils';
import { useCreditNoteFormContext } from './CreditNoteFormProvider';
@@ -45,8 +44,6 @@ function CreditNoteFormHeaderFields({
// #withSettings
creditAutoIncrement,
creditNumberPrefix,
creditNextNumber,
}) {
// Credit note form context.
const { customers } = useCreditNoteFormContext();
@@ -70,9 +67,6 @@ function CreditNoteFormHeaderFields({
}
};
// Syncs credit number settings with form.
useObserveCreditNoSettings(creditNumberPrefix, creditNextNumber);
return (
<div className={classNames(CLASSES.PAGE_FORM_HEADER_FIELDS)}>
{/* ----------- Customer name ----------- */}

View File

@@ -1,16 +1,18 @@
// @ts-nocheck
import React from 'react';
import React, { useEffect } from 'react';
import { useFormikContext } from 'formik';
import * as R from 'ramda';
import { ExchangeRateInputGroup } from '@/components';
import { useCurrentOrganization } from '@/hooks/state';
import { useCreditNoteIsForeignCustomer } from './utils';
import withSettings from '@/containers/Settings/withSettings';
import { transactionNumber } from '@/utils';
/**
* credit exchange rate input field.
* @returns {JSX.Element}
*/
export function CreditNoteExchangeRateInputField({ ...props }) {
export function CreditNoteExchangeRateInputField({ ...props }) {
const currentOrganization = useCurrentOrganization();
const { values } = useFormikContext();
@@ -27,4 +29,27 @@ import { useCreditNoteIsForeignCustomer } from './utils';
{...props}
/>
);
}
}
/**
* Syncs credit note auto-increment settings to form.
* @return {React.ReactNode}
*/
export const CreditNoteSyncIncrementSettingsToForm = R.compose(
withSettings(({ creditNoteSettings }) => ({
creditAutoIncrement: creditNoteSettings?.autoIncrement,
creditNextNumber: creditNoteSettings?.nextNumber,
creditNumberPrefix: creditNoteSettings?.numberPrefix,
})),
)(({ creditAutoIncrement, creditNextNumber, creditNumberPrefix }) => {
const { setFieldValue } = useFormikContext();
useEffect(() => {
if (!creditAutoIncrement) return;
const creditNo = transactionNumber(creditNumberPrefix, creditNextNumber);
setFieldValue('credit_note_number', creditNo);
}, [setFieldValue, creditNumberPrefix, creditNextNumber]);
return null;
});

View File

@@ -130,18 +130,6 @@ export const entriesFieldShouldUpdate = (newProps, oldProps) => {
);
};
/**
* Syncs invoice no. settings with form.
*/
export const useObserveCreditNoSettings = (prefix, nextNumber) => {
const { setFieldValue } = useFormikContext();
React.useEffect(() => {
const creditNo = transactionNumber(prefix, nextNumber);
setFieldValue('credit_note_number', creditNo);
}, [setFieldValue, prefix, nextNumber]);
};
export const useSetPrimaryBranchToForm = () => {
const { setFieldValue } = useFormikContext();
const { branches, isBranchesSuccess } = useCreditNoteFormContext();

View File

@@ -32,6 +32,7 @@ import {
transfromsFormValuesToRequest,
handleErrors,
} from './utils';
import { EstimateIncrementSyncSettingsToForm } from './components';
/**
* Estimate form.
@@ -160,8 +161,8 @@ function EstimateForm({
<EstimateItemsEntriesField />
<EstimateFormFooter />
<EstimateFloatingActions />
<EstimateFormDialogs />
<EstimateIncrementSyncSettingsToForm />
</Form>
</Formik>
</div>

View File

@@ -12,6 +12,19 @@ import { PageFormBigNumber } from '@/components';
// Estimate form top header.
function EstimateFormHeader() {
return (
<div className={classNames(CLASSES.PAGE_FORM_HEADER)}>
<EstimateFormHeaderFields />
<EstimateFormBigTotal />
</div>
);
}
/**
* Big total of estimate form header.
* @returns {React.ReactNode}
*/
function EstimateFormBigTotal() {
const {
values: { entries, currency_code },
} = useFormikContext();
@@ -20,15 +33,11 @@ function EstimateFormHeader() {
const totalDueAmount = useMemo(() => getEntriesTotal(entries), [entries]);
return (
<div className={classNames(CLASSES.PAGE_FORM_HEADER)}>
<EstimateFormHeaderFields />
<PageFormBigNumber
label={intl.get('amount')}
amount={totalDueAmount}
currencyCode={currency_code}
/>
</div>
<PageFormBigNumber
label={intl.get('amount')}
amount={totalDueAmount}
currencyCode={currency_code}
/>
);
}

View File

@@ -39,7 +39,6 @@ import {
EstimateProjectSelectButton,
} from './components';
import { useObserveEstimateNoSettings } from './utils';
import { useEstimateFormContext } from './EstimateFormProvider';
/**
@@ -71,8 +70,7 @@ function EstimateFormHeader({
});
}
};
// Syncs estimate number settings with the form.
useObserveEstimateNoSettings(estimateNumberPrefix, estimateNextNumber);
return (
<div className={classNames(CLASSES.PAGE_FORM_HEADER_FIELDS)}>

View File

@@ -1,18 +1,20 @@
// @ts-nocheck
import React from 'react';
import React, { useEffect } from 'react';
import intl from 'react-intl-universal';
import { Button } from '@blueprintjs/core';
import * as R from 'ramda';
import { useFormikContext } from 'formik';
import { ExchangeRateInputGroup } from '@/components';
import { useCurrentOrganization } from '@/hooks/state';
import { useEstimateIsForeignCustomer } from './utils';
import withSettings from '@/containers/Settings/withSettings';
import { transactionNumber } from '@/utils';
/**
* Estimate exchange rate input field.
* @returns {JSX.Element}
*/
export function EstimateExchangeRateInputField({ ...props }) {
export function EstimateExchangeRateInputField({ ...props }) {
const currentOrganization = useCurrentOrganization();
const { values } = useFormikContext();
@@ -35,6 +37,32 @@ import { useEstimateIsForeignCustomer } from './utils';
* Estimate project select.
* @returns {JSX.Element}
*/
export function EstimateProjectSelectButton({ label }) {
export function EstimateProjectSelectButton({ label }) {
return <Button text={label ?? intl.get('select_project')} />;
}
/**
* Syncs the estimate auto-increment settings to estimate form.
* @returns {React.ReactNode}
*/
export const EstimateIncrementSyncSettingsToForm = R.compose(
withSettings(({ estimatesSettings }) => ({
estimateNextNumber: estimatesSettings?.nextNumber,
estimateNumberPrefix: estimatesSettings?.numberPrefix,
estimateAutoIncrement: estimatesSettings?.autoIncrement,
})),
)(({ estimateNextNumber, estimateNumberPrefix, estimateAutoIncrement }) => {
const { setFieldValue } = useFormikContext();
useEffect(() => {
if (!estimateAutoIncrement) return null;
const estimateNo = transactionNumber(
estimateNumberPrefix,
estimateNextNumber,
);
setFieldValue('estimate_number', estimateNo);
}, [setFieldValue, estimateNumberPrefix, estimateNextNumber]);
return null;
});

View File

@@ -74,18 +74,6 @@ export const transformToEditForm = (estimate) => {
};
};
/**
* Syncs estimate number of the settings with the context form.
*/
export const useObserveEstimateNoSettings = (prefix, nextNumber) => {
const { setFieldValue } = useFormikContext();
React.useEffect(() => {
const estimateNo = transactionNumber(prefix, nextNumber);
setFieldValue('estimate_number', estimateNo);
}, [setFieldValue, prefix, nextNumber]);
};
/**
* Detarmines customers fast field when update.
*/

View File

@@ -32,6 +32,7 @@ import {
transformErrors,
transformValueToRequest,
} from './utils';
import { InvoiceNoSyncSettingsToForm } from './components';
/**
* Invoice form.
@@ -64,23 +65,19 @@ function InvoiceForm({
invoiceNextNumber,
);
// Form initial values.
const initialValues = useMemo(
() => ({
...(!isEmpty(invoice)
? { ...transformToEditForm(invoice) }
: {
...defaultInvoice,
...(invoiceIncrementMode && {
const initialValues = {
...(!isEmpty(invoice)
? { ...transformToEditForm(invoice) }
: {
...defaultInvoice,
...(invoiceIncrementMode && {
invoice_no: invoiceNumber,
}),
entries: orderingLinesIndexes(defaultInvoice.entries),
currency_code: base_currency,
...newInvoice,
}),
}),
[invoice, newInvoice, invoiceNumber, invoiceIncrementMode, base_currency],
);
...newInvoice,
}),
};
// Handles form submit.
const handleSubmit = (values, { setSubmitting, setErrors, resetForm }) => {
setSubmitting(true);
@@ -105,7 +102,6 @@ function InvoiceForm({
delivered: submitPayload.deliver,
from_estimate_id: estimateId,
};
// Handle the request success.
const onSuccess = () => {
AppToaster.show({
@@ -173,6 +169,7 @@ function InvoiceForm({
<InvoiceFormFooter />
<InvoiceFloatingActions />
<InvoiceFormDialogs />
<InvoiceNoSyncSettingsToForm />
</Form>
</Formik>
</div>

View File

@@ -2,6 +2,7 @@
import React from 'react';
import InvoiceNumberDialog from '@/containers/Dialogs/InvoiceNumberDialog';
import { useFormikContext } from 'formik';
import { DialogsName } from '@/constants/dialogs';
/**
* Invoice form dialogs.
@@ -16,11 +17,9 @@ export default function InvoiceFormDialogs() {
};
return (
<>
<InvoiceNumberDialog
dialogName={'invoice-number-form'}
onConfirm={handleInvoiceNumberFormConfirm}
/>
</>
<InvoiceNumberDialog
dialogName={DialogsName.InvoiceNumberSettings}
onConfirm={handleInvoiceNumberFormConfirm}
/>
);
}

View File

@@ -28,7 +28,6 @@ import { momentFormatter, compose, tansformDateValue } from '@/utils';
import { CLASSES } from '@/constants/classes';
import { inputIntent, handleDateChange } from '@/utils';
import {
useObserveInvoiceNoSettings,
customerNameFieldShouldUpdate,
} from './utils';
@@ -42,6 +41,7 @@ import {
ProjectBillableEntriesLink,
} from '@/containers/Projects/components';
import { Features } from '@/constants';
import { DialogsName } from '@/constants/dialogs';
import withSettings from '@/containers/Settings/withSettings';
import withDialogActions from '@/containers/Dialog/withDialogActions';
@@ -55,8 +55,6 @@ function InvoiceFormHeaderFields({
// #withSettings
invoiceAutoIncrement,
invoiceNumberPrefix,
invoiceNextNumber,
}) {
// Invoice form context.
const { customers, projects } = useInvoiceFormContext();
@@ -66,14 +64,14 @@ function InvoiceFormHeaderFields({
// Handle invoice number changing.
const handleInvoiceNumberChange = () => {
openDialog('invoice-number-form');
openDialog(DialogsName.InvoiceNumberSettings);
};
// Handle invoice no. field blur.
const handleInvoiceNoBlur = (form, field) => (event) => {
const newValue = event.target.value;
if (field.value !== newValue && invoiceAutoIncrement) {
openDialog('invoice-number-form', {
openDialog(DialogsName.InvoiceNumberSettings, {
initialFormValues: {
manualTransactionNo: newValue,
incrementMode: 'manual-transaction',
@@ -81,8 +79,6 @@ function InvoiceFormHeaderFields({
});
}
};
// Syncs invoice number settings with form.
useObserveInvoiceNoSettings(invoiceNumberPrefix, invoiceNextNumber);
return (
<div className={classNames(CLASSES.PAGE_FORM_HEADER_FIELDS)}>
@@ -268,8 +264,6 @@ export default compose(
withDialogActions,
withSettings(({ invoiceSettings }) => ({
invoiceAutoIncrement: invoiceSettings?.autoIncrement,
invoiceNextNumber: invoiceSettings?.nextNumber,
invoiceNumberPrefix: invoiceSettings?.numberPrefix,
})),
)(InvoiceFormHeaderFields);

View File

@@ -1,11 +1,15 @@
// @ts-nocheck
import React from 'react';
import intl from 'react-intl-universal';
import * as R from 'ramda';
import { Button } from '@blueprintjs/core';
import { useFormikContext } from 'formik';
import { ExchangeRateInputGroup } from '@/components';
import { useCurrentOrganization } from '@/hooks/state';
import { useInvoiceIsForeignCustomer } from './utils';
import withSettings from '@/containers/Settings/withSettings';
import { useUpdateEffect } from '@/hooks';
import { transactionNumber } from '@/utils';
/**
* Invoice exchange rate input field.
@@ -37,3 +41,26 @@ export function InvoiceExchangeRateInputField({ ...props }) {
export function InvoiceProjectSelectButton({ label }) {
return <Button text={label ?? intl.get('select_project')} />;
}
/**
* Syncs invoice auto-increment settings to invoice form once update.
*/
export const InvoiceNoSyncSettingsToForm = R.compose(
withSettings(({ invoiceSettings }) => ({
invoiceAutoIncrement: invoiceSettings?.autoIncrement,
invoiceNextNumber: invoiceSettings?.nextNumber,
invoiceNumberPrefix: invoiceSettings?.numberPrefix,
})),
)(({ invoiceAutoIncrement, invoiceNextNumber, invoiceNumberPrefix }) => {
const { setFieldValue } = useFormikContext();
useUpdateEffect(() => {
// Do not update if the invoice auto-increment is disabled.
if (!invoiceAutoIncrement) return null;
const invoiceNo = transactionNumber(invoiceNumberPrefix, invoiceNextNumber);
setFieldValue('invoice_no', invoiceNo);
}, [setFieldValue, invoiceNumberPrefix, invoiceNextNumber]);
return null;
});

View File

@@ -108,18 +108,6 @@ export const transformErrors = (errors, { setErrors }) => {
}
};
/**
* Syncs invoice no. settings with form.
*/
export const useObserveInvoiceNoSettings = (prefix, nextNumber) => {
const { setFieldValue } = useFormikContext();
React.useEffect(() => {
const invoiceNo = transactionNumber(prefix, nextNumber);
setFieldValue('invoice_no', invoiceNo);
}, [setFieldValue, prefix, nextNumber]);
};
/**
* Detarmines customer name field when should update.
*/

View File

@@ -36,6 +36,7 @@ import {
transformFormToRequest,
transformErrors,
} from './utils';
import { PaymentReceiveSyncIncrementSettingsToForm } from './components';
/**
* Payment Receive form.
@@ -176,6 +177,8 @@ function PaymentReceiveForm({
<PaymentReceiveFormFooter />
<PaymentReceiveFloatingActions />
<PaymentReceiveSyncIncrementSettingsToForm />
{/* ------- Alerts & Dialogs ------- */}
<PaymentReceiveFormAlerts />
<PaymentReceiveFormDialogs />

View File

@@ -13,6 +13,21 @@ import PaymentReceiveHeaderFields from './PaymentReceiveHeaderFields';
* Payment receive form header.
*/
function PaymentReceiveFormHeader() {
return (
<div className={classNames(CLASSES.PAGE_FORM_HEADER)}>
<div className={classNames(CLASSES.PAGE_FORM_HEADER_PRIMARY)}>
<PaymentReceiveHeaderFields />
<PaymentReceiveFormBigTotal />
</div>
</div>
);
}
/**
* Big total amount of payment receive form.
* @returns {React.ReactNode}
*/
function PaymentReceiveFormBigTotal() {
// Formik form context.
const {
values: { currency_code, entries },
@@ -25,20 +40,14 @@ function PaymentReceiveFormHeader() {
);
return (
<div className={classNames(CLASSES.PAGE_FORM_HEADER)}>
<div className={classNames(CLASSES.PAGE_FORM_HEADER_PRIMARY)}>
<PaymentReceiveHeaderFields />
<div className={classNames(CLASSES.PAGE_FORM_HEADER_BIG_NUMBERS)}>
<div class="big-amount">
<span class="big-amount__label">
<T id={'amount_received'} />
</span>
<h1 class="big-amount__number">
<Money amount={paymentFullAmount} currency={currency_code} />
</h1>
</div>
</div>
<div className={classNames(CLASSES.PAGE_FORM_HEADER_BIG_NUMBERS)}>
<div class="big-amount">
<span class="big-amount__label">
<T id={'amount_received'} />
</span>
<h1 class="big-amount__number">
<Money amount={paymentFullAmount} currency={currency_code} />
</h1>
</div>
</div>
);

View File

@@ -51,7 +51,6 @@ import withSettings from '@/containers/Settings/withSettings';
import withCurrentOrganization from '@/containers/Organization/withCurrentOrganization';
import {
useObservePaymentNoSettings,
amountPaymentEntries,
fullAmountPaymentEntries,
customersFieldShouldUpdate,
@@ -71,8 +70,6 @@ function PaymentReceiveHeaderFields({
// #withSettings
paymentReceiveAutoIncrement,
paymentReceiveNumberPrefix,
paymentReceiveNextNumber,
}) {
// Payment receive form context.
const { customers, accounts, projects, isNewMode } =
@@ -123,12 +120,6 @@ function PaymentReceiveHeaderFields({
}
};
// Syncs payment receive number from settings to the form.
useObservePaymentNoSettings(
paymentReceiveNumberPrefix,
paymentReceiveNextNumber,
);
return (
<div className={classNames(CLASSES.PAGE_FORM_HEADER_FIELDS)}>
{/* ------------- Customer name ------------- */}
@@ -351,8 +342,6 @@ function PaymentReceiveHeaderFields({
export default compose(
withSettings(({ paymentReceiveSettings }) => ({
paymentReceiveNextNumber: paymentReceiveSettings?.nextNumber,
paymentReceiveNumberPrefix: paymentReceiveSettings?.numberPrefix,
paymentReceiveAutoIncrement: paymentReceiveSettings?.autoIncrement,
})),
withDialogActions,

View File

@@ -1,14 +1,17 @@
// @ts-nocheck
import React from 'react';
import React, { useEffect } from 'react';
import moment from 'moment';
import intl from 'react-intl-universal';
import { Button } from '@blueprintjs/core';
import { useFormikContext } from 'formik';
import * as R from 'ramda';
import { Money, ExchangeRateInputGroup, MoneyFieldCell } from '@/components';
import { useCurrentOrganization } from '@/hooks/state';
import { useEstimateIsForeignCustomer } from './utils';
import { transactionNumber } from '@/utils';
import withSettings from '@/containers/Settings/withSettings';
/**
* Invoice date cell.
@@ -109,6 +112,42 @@ export function PaymentReceiveExchangeRateInputField({ ...props }) {
* payment receive project select.
* @returns {JSX.Element}
*/
export function PaymentReceiveProjectSelectButton({ label }) {
export function PaymentReceiveProjectSelectButton({ label }) {
return <Button text={label ?? intl.get('select_project')} />;
}
/**
* Syncs the auto-increment settings to payment receive form.
* @returns {React.ReactNode}
*/
export const PaymentReceiveSyncIncrementSettingsToForm = R.compose(
withSettings(({ paymentReceiveSettings }) => ({
paymentReceiveNextNumber: paymentReceiveSettings?.nextNumber,
paymentReceiveNumberPrefix: paymentReceiveSettings?.numberPrefix,
paymentReceiveAutoIncrement: paymentReceiveSettings?.autoIncrement,
})),
)(
({
paymentReceiveNextNumber,
paymentReceiveNumberPrefix,
paymentReceiveAutoIncrement,
}) => {
const { setFieldValue } = useFormikContext();
useEffect(() => {
if (!paymentReceiveAutoIncrement) return;
const paymentReceiveNo = transactionNumber(
paymentReceiveNumberPrefix,
paymentReceiveNextNumber,
);
setFieldValue('payment_receive_no', paymentReceiveNo);
}, [
setFieldValue,
paymentReceiveNumberPrefix,
paymentReceiveNextNumber,
paymentReceiveAutoIncrement,
]);
return null;
},
);

View File

@@ -34,6 +34,7 @@ import {
handleErrors,
transformFormValuesToRequest,
} from './utils';
import { ReceiptSyncIncrementSettingsToForm } from './components';
/**
* Receipt form.
@@ -164,8 +165,8 @@ function ReceiptForm({
<ReceiptItemsEntriesEditor />
<ReceiptFormFooter />
<ReceiptFormFloatingActions />
<ReceiptFormDialogs />
<ReceiptSyncIncrementSettingsToForm />
</Form>
</Formik>
</div>

View File

@@ -17,6 +17,21 @@ function ReceiptFormHeader({
// #ownProps
onReceiptNumberChanged,
}) {
return (
<div className={classNames(CLASSES.PAGE_FORM_HEADER)}>
<ReceiptFormHeaderFields
onReceiptNumberChanged={onReceiptNumberChanged}
/>
<ReceiptFormHeaderBigTotal />
</div>
);
}
/**
* The big total amount of receipt form.
* @returns {React.ReactNode}
*/
function ReceiptFormHeaderBigTotal() {
const {
values: { currency_code, entries },
} = useFormikContext();
@@ -25,16 +40,11 @@ function ReceiptFormHeader({
const totalDueAmount = useMemo(() => getEntriesTotal(entries), [entries]);
return (
<div className={classNames(CLASSES.PAGE_FORM_HEADER)}>
<ReceiptFormHeaderFields
onReceiptNumberChanged={onReceiptNumberChanged}
/>
<PageFormBigNumber
label={intl.get('due_amount')}
amount={totalDueAmount}
currencyCode={currency_code}
/>
</div>
<PageFormBigNumber
label={intl.get('due_amount')}
amount={totalDueAmount}
currencyCode={currency_code}
/>
);
}

View File

@@ -39,7 +39,6 @@ import { useReceiptFormContext } from './ReceiptFormProvider';
import {
accountsFieldShouldUpdate,
customersFieldShouldUpdate,
useObserveReceiptNoSettings,
} from './utils';
import {
ReceiptExchangeRateInputField,
@@ -56,8 +55,6 @@ function ReceiptFormHeader({
// #withSettings
receiptAutoIncrement,
receiptNextNumber,
receiptNumberPrefix,
}) {
const { accounts, customers, projects } = useReceiptFormContext();
@@ -78,9 +75,6 @@ function ReceiptFormHeader({
}
};
// Synsc receipt number settings with the form.
useObserveReceiptNoSettings(receiptNumberPrefix, receiptNextNumber);
return (
<div className={classNames(CLASSES.PAGE_FORM_HEADER_FIELDS)}>
{/* ----------- Customer name ----------- */}
@@ -255,8 +249,6 @@ export default compose(
withDialogActions,
withSettings(({ receiptSettings }) => ({
receiptAutoIncrement: receiptSettings?.autoIncrement,
receiptNextNumber: receiptSettings?.nextNumber,
receiptNumberPrefix: receiptSettings?.numberPrefix,
})),
)(ReceiptFormHeader);

View File

@@ -3,9 +3,14 @@ import React from 'react';
import intl from 'react-intl-universal';
import { Button } from '@blueprintjs/core';
import { useFormikContext } from 'formik';
import * as R from 'ramda';
import { ExchangeRateInputGroup } from '@/components';
import { useCurrentOrganization } from '@/hooks/state';
import { useReceiptIsForeignCustomer } from './utils';
import { useUpdateEffect } from '@/hooks';
import withSettings from '@/containers/Settings/withSettings';
import { transactionNumber } from '@/utils';
/**
* Receipt exchange rate input field.
@@ -37,3 +42,31 @@ export function ReceiptExchangeRateInputField({ ...props }) {
export function ReceiptProjectSelectButton({ label }) {
return <Button text={label ?? intl.get('select_project')} />;
}
/**
* Syncs receipt auto-increment settings to form.
* @return {React.ReactNode}
*/
export const ReceiptSyncIncrementSettingsToForm = R.compose(
withSettings(({ receiptSettings }) => ({
receiptAutoIncrement: receiptSettings?.autoIncrement,
receiptNextNumber: receiptSettings?.nextNumber,
receiptNumberPrefix: receiptSettings?.numberPrefix,
})),
)(({ receiptAutoIncrement, receiptNextNumber, receiptNumberPrefix }) => {
const { setFieldValue } = useFormikContext();
useUpdateEffect(() => {
if (!receiptAutoIncrement) return;
const receiptNo = transactionNumber(receiptNumberPrefix, receiptNextNumber);
setFieldValue('receipt_number', receiptNo);
}, [
setFieldValue,
receiptNumberPrefix,
receiptAutoIncrement,
receiptNextNumber,
]);
return null;
});

View File

@@ -77,15 +77,6 @@ export const transformToEditForm = (receipt) => {
};
};
export const useObserveReceiptNoSettings = (prefix, nextNumber) => {
const { setFieldValue } = useFormikContext();
React.useEffect(() => {
const receiptNo = transactionNumber(prefix, nextNumber);
setFieldValue('receipt_number', receiptNo);
}, [setFieldValue, prefix, nextNumber]);
};
/**
* Detarmines entries fast field should update.
*/