mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-21 15:20:34 +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 PaymentMadeFooter from './PaymentMadeFooter';
|
||||||
import PaymentMadeFormBody from './PaymentMadeFormBody';
|
import PaymentMadeFormBody from './PaymentMadeFormBody';
|
||||||
import PaymentMadeFormTopBar from './PaymentMadeFormTopBar';
|
import PaymentMadeFormTopBar from './PaymentMadeFormTopBar';
|
||||||
|
import { PaymentMadeDialogs } from './PaymentMadeDialogs';
|
||||||
|
|
||||||
import { PaymentMadeInnerProvider } from './PaymentMadeInnerProvider';
|
import { PaymentMadeInnerProvider } from './PaymentMadeInnerProvider';
|
||||||
import { usePaymentMadeFormContext } from './PaymentMadeFormProvider';
|
import { usePaymentMadeFormContext } from './PaymentMadeFormProvider';
|
||||||
@@ -21,6 +22,7 @@ import { compose, orderingLinesIndexes } from '@/utils';
|
|||||||
|
|
||||||
import withSettings from '@/containers/Settings/withSettings';
|
import withSettings from '@/containers/Settings/withSettings';
|
||||||
import withCurrentOrganization from '@/containers/Organization/withCurrentOrganization';
|
import withCurrentOrganization from '@/containers/Organization/withCurrentOrganization';
|
||||||
|
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
EditPaymentMadeFormSchema,
|
EditPaymentMadeFormSchema,
|
||||||
@@ -42,6 +44,9 @@ function PaymentMadeForm({
|
|||||||
|
|
||||||
// #withCurrentOrganization
|
// #withCurrentOrganization
|
||||||
organization: { base_currency },
|
organization: { base_currency },
|
||||||
|
|
||||||
|
// #withDialogActions
|
||||||
|
openDialog,
|
||||||
}) {
|
}) {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
|
||||||
@@ -149,6 +154,7 @@ function PaymentMadeForm({
|
|||||||
<PaymentMadeFormBody />
|
<PaymentMadeFormBody />
|
||||||
<PaymentMadeFooter />
|
<PaymentMadeFooter />
|
||||||
<PaymentMadeFloatingActions />
|
<PaymentMadeFloatingActions />
|
||||||
|
<PaymentMadeDialogs />
|
||||||
</PaymentMadeInnerProvider>
|
</PaymentMadeInnerProvider>
|
||||||
</Form>
|
</Form>
|
||||||
</Formik>
|
</Formik>
|
||||||
@@ -163,4 +169,5 @@ export default compose(
|
|||||||
preferredPaymentAccount: parseInt(billPaymentSettings?.withdrawalAccount),
|
preferredPaymentAccount: parseInt(billPaymentSettings?.withdrawalAccount),
|
||||||
})),
|
})),
|
||||||
withCurrentOrganization(),
|
withCurrentOrganization(),
|
||||||
|
withDialogActions,
|
||||||
)(PaymentMadeForm);
|
)(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 withSettings from '@/containers/Settings/withSettings';
|
||||||
import withCurrentOrganization from '@/containers/Organization/withCurrentOrganization';
|
import withCurrentOrganization from '@/containers/Organization/withCurrentOrganization';
|
||||||
|
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
EditPaymentReceiveFormSchema,
|
EditPaymentReceiveFormSchema,
|
||||||
@@ -51,6 +52,9 @@ function PaymentReceiveForm({
|
|||||||
|
|
||||||
// #withCurrentOrganization
|
// #withCurrentOrganization
|
||||||
organization: { base_currency },
|
organization: { base_currency },
|
||||||
|
|
||||||
|
// #withDialogActions
|
||||||
|
openDialog
|
||||||
}) {
|
}) {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
|
||||||
@@ -102,6 +106,11 @@ function PaymentReceiveForm({
|
|||||||
) => {
|
) => {
|
||||||
setSubmitting(true);
|
setSubmitting(true);
|
||||||
|
|
||||||
|
if (true) {
|
||||||
|
openDialog('payment-received-excessed-payment');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Transformes the form values to request body.
|
// Transformes the form values to request body.
|
||||||
const form = transformFormToRequest(values);
|
const form = transformFormToRequest(values);
|
||||||
|
|
||||||
@@ -191,4 +200,5 @@ export default compose(
|
|||||||
preferredDepositAccount: paymentReceiveSettings?.preferredDepositAccount,
|
preferredDepositAccount: paymentReceiveSettings?.preferredDepositAccount,
|
||||||
})),
|
})),
|
||||||
withCurrentOrganization(),
|
withCurrentOrganization(),
|
||||||
|
withDialogActions
|
||||||
)(PaymentReceiveForm);
|
)(PaymentReceiveForm);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useFormikContext } from 'formik';
|
import { useFormikContext } from 'formik';
|
||||||
import PaymentReceiveNumberDialog from '@/containers/Dialogs/PaymentReceiveNumberDialog';
|
import PaymentReceiveNumberDialog from '@/containers/Dialogs/PaymentReceiveNumberDialog';
|
||||||
|
import { ExcessPaymentDialog } from './dialogs/ExcessPaymentDialog';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Payment receive form dialogs.
|
* Payment receive form dialogs.
|
||||||
@@ -21,9 +22,12 @@ export default function PaymentReceiveFormDialogs() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<PaymentReceiveNumberDialog
|
<PaymentReceiveNumberDialog
|
||||||
dialogName={'payment-receive-number-form'}
|
dialogName={'payment-receive-number-form'}
|
||||||
onConfirm={handleUpdatePaymentNumber}
|
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: '',
|
branch_id: '',
|
||||||
exchange_rate: 1,
|
exchange_rate: 1,
|
||||||
entries: [],
|
entries: [],
|
||||||
attachments: []
|
attachments: [],
|
||||||
|
unearned_revenue_account_id: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const defaultRequestPaymentEntry = {
|
export const defaultRequestPaymentEntry = {
|
||||||
|
|||||||
Reference in New Issue
Block a user