mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-17 13:20:31 +00:00
feat: excess payment alert
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
import { ExcessPaymentDialog } from './dialogs/PaymentMadeExcessDialog';
|
||||
|
||||
export function PaymentMadeDialogs() {
|
||||
return (
|
||||
<>
|
||||
<ExcessPaymentDialog dialogName={'payment-made-excessed-payment'} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import PaymentMadeFloatingActions from './PaymentMadeFloatingActions';
|
||||
import PaymentMadeFooter from './PaymentMadeFooter';
|
||||
import PaymentMadeFormBody from './PaymentMadeFormBody';
|
||||
import PaymentMadeFormTopBar from './PaymentMadeFormTopBar';
|
||||
import { PaymentMadeDialogs } from './PaymentMadeDialogs';
|
||||
|
||||
import { PaymentMadeInnerProvider } from './PaymentMadeInnerProvider';
|
||||
import { usePaymentMadeFormContext } from './PaymentMadeFormProvider';
|
||||
@@ -21,6 +22,7 @@ import { compose, orderingLinesIndexes } from '@/utils';
|
||||
|
||||
import withSettings from '@/containers/Settings/withSettings';
|
||||
import withCurrentOrganization from '@/containers/Organization/withCurrentOrganization';
|
||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
||||
|
||||
import {
|
||||
EditPaymentMadeFormSchema,
|
||||
@@ -42,6 +44,9 @@ function PaymentMadeForm({
|
||||
|
||||
// #withCurrentOrganization
|
||||
organization: { base_currency },
|
||||
|
||||
// #withDialogActions
|
||||
openDialog,
|
||||
}) {
|
||||
const history = useHistory();
|
||||
|
||||
@@ -149,6 +154,7 @@ function PaymentMadeForm({
|
||||
<PaymentMadeFormBody />
|
||||
<PaymentMadeFooter />
|
||||
<PaymentMadeFloatingActions />
|
||||
<PaymentMadeDialogs />
|
||||
</PaymentMadeInnerProvider>
|
||||
</Form>
|
||||
</Formik>
|
||||
@@ -163,4 +169,5 @@ export default compose(
|
||||
preferredPaymentAccount: parseInt(billPaymentSettings?.withdrawalAccount),
|
||||
})),
|
||||
withCurrentOrganization(),
|
||||
withDialogActions,
|
||||
)(PaymentMadeForm);
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import { Dialog, DialogSuspense } from '@/components';
|
||||
import withDialogRedux from '@/components/DialogReduxConnect';
|
||||
import { compose } from '@/utils';
|
||||
|
||||
const ExcessPaymentDialogContent = React.lazy(() =>
|
||||
import('./PaymentMadeExcessDialogContent').then((module) => ({
|
||||
default: module.ExcessPaymentDialogContent,
|
||||
})),
|
||||
);
|
||||
|
||||
/**
|
||||
* Exess payment dialog of the payment made form.
|
||||
*/
|
||||
function ExcessPaymentDialogRoot({ dialogName, isOpen }) {
|
||||
return (
|
||||
<Dialog
|
||||
name={dialogName}
|
||||
title={'Excess Payment'}
|
||||
isOpen={isOpen}
|
||||
canEscapeJeyClose={true}
|
||||
autoFocus={true}
|
||||
style={{ width: 500 }}
|
||||
>
|
||||
<DialogSuspense>
|
||||
<ExcessPaymentDialogContent dialogName={dialogName} />
|
||||
</DialogSuspense>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
export const ExcessPaymentDialog = compose(withDialogRedux())(
|
||||
ExcessPaymentDialogRoot,
|
||||
);
|
||||
|
||||
ExcessPaymentDialog.displayName = 'ExcessPaymentDialog';
|
||||
@@ -0,0 +1,113 @@
|
||||
// @ts-nocheck
|
||||
import * as R from 'ramda';
|
||||
import * as Yup from 'yup';
|
||||
import { useMemo } from 'react';
|
||||
import { Button, Classes, Intent } from '@blueprintjs/core';
|
||||
import { Form, Formik, FormikHelpers, useFormikContext } from 'formik';
|
||||
import { AccountsSelect, FFormGroup } from '@/components';
|
||||
import { usePaymentMadeFormContext } from '../../PaymentMadeFormProvider';
|
||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
||||
|
||||
interface ExcessPaymentValues {
|
||||
accountId: string;
|
||||
}
|
||||
|
||||
const initialValues = {
|
||||
accountId: '',
|
||||
} as ExcessPaymentValues;
|
||||
|
||||
const Schema = Yup.object().shape({
|
||||
accountId: Yup.number().required(),
|
||||
});
|
||||
|
||||
const DEFAULT_ACCOUNT_SLUG = 'depreciation-expense';
|
||||
|
||||
function ExcessPaymentDialogContentRoot({ dialogName, closeDialog }) {
|
||||
const { setFieldValue } = useFormikContext();
|
||||
|
||||
const handleSubmit = (
|
||||
values: ExcessPaymentValues,
|
||||
{ setSubmitting }: FormikHelpers<ExcessPaymentValues>,
|
||||
) => {
|
||||
closeDialog(dialogName);
|
||||
setFieldValue(values.accountId);
|
||||
};
|
||||
|
||||
// Handle close button click.
|
||||
const handleCloseBtn = () => {
|
||||
closeDialog(dialogName);
|
||||
};
|
||||
const defaultAccountId = useDefaultExcessPaymentDeposit();
|
||||
|
||||
return (
|
||||
<Formik
|
||||
initialValues={{
|
||||
...initialValues,
|
||||
accountId: defaultAccountId,
|
||||
}}
|
||||
validationSchema={Schema}
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
<Form>
|
||||
<ExcessPaymentDialogContentForm onClose={handleCloseBtn} />
|
||||
</Form>
|
||||
</Formik>
|
||||
);
|
||||
}
|
||||
|
||||
export const ExcessPaymentDialogContent = R.compose(withDialogActions)(
|
||||
ExcessPaymentDialogContentRoot,
|
||||
);
|
||||
|
||||
interface ExcessPaymentDialogContentFormProps {
|
||||
onClose?: () => void;
|
||||
}
|
||||
|
||||
function ExcessPaymentDialogContentForm({
|
||||
onClose,
|
||||
}: ExcessPaymentDialogContentFormProps) {
|
||||
const { submitForm } = useFormikContext();
|
||||
const { accounts } = usePaymentMadeFormContext();
|
||||
|
||||
const handleCloseBtn = () => {
|
||||
onClose && onClose();
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<div className={Classes.DIALOG_BODY}>
|
||||
<p>
|
||||
Would you like to record the excess amount of $1000 as advanced
|
||||
payment from the customer.
|
||||
</p>
|
||||
|
||||
<FFormGroup
|
||||
name={'accountId'}
|
||||
label={'The excessed amount will be deposited in the'}
|
||||
>
|
||||
<AccountsSelect
|
||||
name={'accountId'}
|
||||
items={accounts}
|
||||
buttonProps={{ small: true }}
|
||||
/>
|
||||
</FFormGroup>
|
||||
</div>
|
||||
|
||||
<div className={Classes.DIALOG_FOOTER}>
|
||||
<div className={Classes.DIALOG_FOOTER_ACTIONS}>
|
||||
<Button intent={Intent.PRIMARY} onClick={() => submitForm()}>
|
||||
Continue to Payment
|
||||
</Button>
|
||||
<Button onClick={handleCloseBtn}>Cancel</Button>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const useDefaultExcessPaymentDeposit = () => {
|
||||
const { accounts } = usePaymentMadeFormContext();
|
||||
return useMemo(() => {
|
||||
return accounts?.find((a) => a.slug === DEFAULT_ACCOUNT_SLUG)?.id;
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export * from './PaymentMadeExcessDialog';
|
||||
@@ -21,6 +21,7 @@ import { PaymentReceiveInnerProvider } from './PaymentReceiveInnerProvider';
|
||||
|
||||
import withSettings from '@/containers/Settings/withSettings';
|
||||
import withCurrentOrganization from '@/containers/Organization/withCurrentOrganization';
|
||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
||||
|
||||
import {
|
||||
EditPaymentReceiveFormSchema,
|
||||
@@ -51,6 +52,9 @@ function PaymentReceiveForm({
|
||||
|
||||
// #withCurrentOrganization
|
||||
organization: { base_currency },
|
||||
|
||||
// #withDialogActions
|
||||
openDialog
|
||||
}) {
|
||||
const history = useHistory();
|
||||
|
||||
@@ -102,6 +106,11 @@ function PaymentReceiveForm({
|
||||
) => {
|
||||
setSubmitting(true);
|
||||
|
||||
if (true) {
|
||||
openDialog('payment-received-excessed-payment');
|
||||
return;
|
||||
}
|
||||
|
||||
// Transformes the form values to request body.
|
||||
const form = transformFormToRequest(values);
|
||||
|
||||
@@ -191,4 +200,5 @@ export default compose(
|
||||
preferredDepositAccount: paymentReceiveSettings?.preferredDepositAccount,
|
||||
})),
|
||||
withCurrentOrganization(),
|
||||
withDialogActions
|
||||
)(PaymentReceiveForm);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import React from 'react';
|
||||
import { useFormikContext } from 'formik';
|
||||
import PaymentReceiveNumberDialog from '@/containers/Dialogs/PaymentReceiveNumberDialog';
|
||||
import { ExcessPaymentDialog } from './dialogs/ExcessPaymentDialog';
|
||||
|
||||
/**
|
||||
* Payment receive form dialogs.
|
||||
@@ -21,9 +22,12 @@ export default function PaymentReceiveFormDialogs() {
|
||||
};
|
||||
|
||||
return (
|
||||
<PaymentReceiveNumberDialog
|
||||
dialogName={'payment-receive-number-form'}
|
||||
onConfirm={handleUpdatePaymentNumber}
|
||||
/>
|
||||
<>
|
||||
<PaymentReceiveNumberDialog
|
||||
dialogName={'payment-receive-number-form'}
|
||||
onConfirm={handleUpdatePaymentNumber}
|
||||
/>
|
||||
<ExcessPaymentDialog dialogName={'payment-received-excessed-payment'} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import { Dialog, DialogSuspense } from '@/components';
|
||||
import withDialogRedux from '@/components/DialogReduxConnect';
|
||||
import { compose } from '@/utils';
|
||||
|
||||
const ExcessPaymentDialogContent = React.lazy(() =>
|
||||
import('./ExcessPaymentDialogContent').then((module) => ({
|
||||
default: module.ExcessPaymentDialogContent,
|
||||
})),
|
||||
);
|
||||
|
||||
/**
|
||||
* Excess payment dialog of the payment received form.
|
||||
*/
|
||||
function ExcessPaymentDialogRoot({ dialogName, isOpen }) {
|
||||
return (
|
||||
<Dialog
|
||||
name={dialogName}
|
||||
title={'Excess Payment'}
|
||||
isOpen={isOpen}
|
||||
canEscapeJeyClose={true}
|
||||
autoFocus={true}
|
||||
style={{ width: 500 }}
|
||||
>
|
||||
<DialogSuspense>
|
||||
<ExcessPaymentDialogContent dialogName={dialogName} />
|
||||
</DialogSuspense>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
export const ExcessPaymentDialog = compose(withDialogRedux())(
|
||||
ExcessPaymentDialogRoot,
|
||||
);
|
||||
|
||||
ExcessPaymentDialog.displayName = 'ExcessPaymentDialog';
|
||||
@@ -0,0 +1,106 @@
|
||||
// @ts-nocheck
|
||||
import { useMemo } from 'react';
|
||||
import * as Yup from 'yup';
|
||||
import * as R from 'ramda';
|
||||
import { Button, Classes, Intent } from '@blueprintjs/core';
|
||||
import { Form, Formik, FormikHelpers, useFormikContext } from 'formik';
|
||||
import { AccountsSelect, FFormGroup } from '@/components';
|
||||
import { usePaymentReceiveFormContext } from '../../PaymentReceiveFormProvider';
|
||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
||||
|
||||
interface ExcessPaymentValues {
|
||||
accountId: string;
|
||||
}
|
||||
|
||||
const initialValues = {
|
||||
accountId: '',
|
||||
} as ExcessPaymentValues;
|
||||
|
||||
const Schema = Yup.object().shape({
|
||||
accountId: Yup.number().required(),
|
||||
});
|
||||
|
||||
const DEFAULT_ACCOUNT_SLUG = 'depreciation-expense';
|
||||
|
||||
export function ExcessPaymentDialogContentRoot({ dialogName, closeDialog }) {
|
||||
const { setFieldValue } = useFormikContext();
|
||||
const initialAccountId = useDefaultExcessPaymentDeposit();
|
||||
|
||||
const handleSubmit = (
|
||||
values: ExcessPaymentValues,
|
||||
{ setSubmitting }: FormikHelpers<ExcessPaymentValues>,
|
||||
) => {
|
||||
closeDialog(dialogName);
|
||||
setFieldValue('unearned_revenue_account_id', values.accountId);
|
||||
};
|
||||
const handleClose = () => {
|
||||
closeDialog(dialogName);
|
||||
};
|
||||
|
||||
return (
|
||||
<Formik
|
||||
initialValues={{
|
||||
...initialValues,
|
||||
accountId: initialAccountId,
|
||||
}}
|
||||
validationSchema={Schema}
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
<Form>
|
||||
<ExcessPaymentDialogContentForm onClose={handleClose} />
|
||||
</Form>
|
||||
</Formik>
|
||||
);
|
||||
}
|
||||
|
||||
export const ExcessPaymentDialogContent = R.compose(withDialogActions)(
|
||||
ExcessPaymentDialogContentRoot,
|
||||
);
|
||||
|
||||
function ExcessPaymentDialogContentForm({ onClose }) {
|
||||
const { accounts } = usePaymentReceiveFormContext();
|
||||
const { submitForm } = useFormikContext();
|
||||
|
||||
const handleCloseBtn = () => {
|
||||
onClose && onClose();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={Classes.DIALOG_BODY}>
|
||||
<p>
|
||||
Would you like to record the excess amount of $1000 as advanced
|
||||
payment from the customer.
|
||||
</p>
|
||||
|
||||
<FFormGroup
|
||||
name={'accountId'}
|
||||
label={'The excessed amount will be deposited in the'}
|
||||
>
|
||||
<AccountsSelect
|
||||
name={'accountId'}
|
||||
items={accounts}
|
||||
buttonProps={{ small: true }}
|
||||
/>
|
||||
</FFormGroup>
|
||||
</div>
|
||||
|
||||
<div className={Classes.DIALOG_FOOTER}>
|
||||
<div className={Classes.DIALOG_FOOTER_ACTIONS}>
|
||||
<Button intent={Intent.PRIMARY} onClick={() => submitForm()}>
|
||||
Continue to Payment
|
||||
</Button>
|
||||
<Button onClick={handleCloseBtn}>Cancel</Button>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const useDefaultExcessPaymentDeposit = () => {
|
||||
const { accounts } = usePaymentReceiveFormContext();
|
||||
return useMemo(() => {
|
||||
return accounts?.find((a) => a.slug === DEFAULT_ACCOUNT_SLUG)?.id;
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export * from './ExcessPaymentDialog';
|
||||
@@ -47,7 +47,8 @@ export const defaultPaymentReceive = {
|
||||
branch_id: '',
|
||||
exchange_rate: 1,
|
||||
entries: [],
|
||||
attachments: []
|
||||
attachments: [],
|
||||
unearned_revenue_account_id: '',
|
||||
};
|
||||
|
||||
export const defaultRequestPaymentEntry = {
|
||||
|
||||
Reference in New Issue
Block a user