feat: close status in receipt.

This commit is contained in:
elforjani3
2020-12-16 12:50:36 +02:00
parent 57d05102a9
commit 153b71184f
7 changed files with 122 additions and 31 deletions

View File

@@ -58,6 +58,7 @@ const defaultInitialValues = {
reference_no: '',
receipt_message: '',
statement: '',
closed:'',
entries: [...repeatValue(defaultReceipt, MIN_LINES_NUMBER)],
};
@@ -182,6 +183,7 @@ function ReceiptForm({
}
const form = {
...values,
closed: submitPayload.status,
entries: entries.map((entry) => ({
// Exclude all properties that out of request entries schema.
...pick(entry, Object.keys(defaultReceipt)),
@@ -259,7 +261,7 @@ function ReceiptForm({
initialValues={initialValues}
onSubmit={handleFormSubmit}
>
{({ isSubmitting }) => (
{({ isSubmitting ,values }) => (
<Form>
<ReceiptFromHeader
onReceiptNumberChanged={handleReceiptNumberChanged}
@@ -270,7 +272,7 @@ function ReceiptForm({
<ReceiptFormFloatingActions
isSubmitting={isSubmitting}
receiptId={receiptId}
receiptPublished={true}
isClosed={values.closed}
onSubmitClick={handleSubmitClick}
onCancelClick={handleCancelClick}
/>

View File

@@ -28,6 +28,7 @@ const Schema = Yup.object().shape({
.min(1)
.max(DATATYPES_LENGTH.TEXT)
.label(formatMessage({ id: 'note' })),
closed: Yup.boolean().required(),
entries: Yup.array().of(
Yup.object().shape({
quantity: Yup.number()

View File

@@ -22,41 +22,41 @@ import { If, Icon } from 'components';
export default function ReceiptFormFloatingActions({
isSubmitting,
receiptId,
receiptPublished,
isClosed,
onSubmitClick,
onCancelClick,
onClearClick,
}) {
const { resetForm, submitForm } = useFormikContext();
const handleSubmitPublishBtnClick = (event) => {
const handleSubmitCloseBtnClick = (event) => {
saveInvoke(onSubmitClick, event, {
redirect: true,
publish: true,
status: true,
});
};
const handleSubmitPublishAndNewBtnClick = (event) => {
const handleSubmitCloseAndNewBtnClick = (event) => {
submitForm();
saveInvoke(onSubmitClick, event, {
redirect: false,
publish: true,
status: true,
resetForm: true,
});
};
const handleSubmitPublishContinueEditingBtnClick = (event) => {
const handleSubmitCloseContinueEditingBtnClick = (event) => {
submitForm();
saveInvoke(onSubmitClick, event, {
redirect: false,
publish: true,
status: true,
});
};
const handleSubmitDraftBtnClick = (event) => {
saveInvoke(onSubmitClick, event, {
redirect: true,
publish: false,
status: false,
});
};
@@ -64,7 +64,7 @@ export default function ReceiptFormFloatingActions({
submitForm();
saveInvoke(onSubmitClick, event, {
redirect: false,
publish: false,
status: false,
resetForm: true,
});
};
@@ -73,7 +73,7 @@ export default function ReceiptFormFloatingActions({
submitForm();
saveInvoke(onSubmitClick, event, {
redirect: false,
publish: false,
status: false,
});
};
@@ -88,26 +88,26 @@ export default function ReceiptFormFloatingActions({
return (
<div className={classNames(CLASSES.PAGE_FORM_FLOATING_ACTIONS)}>
{/* ----------- Save And Publish ----------- */}
<If condition={!receiptId || !receiptPublished}>
{/* ----------- Save And Close ----------- */}
<If condition={!receiptId || !isClosed}>
<ButtonGroup>
<Button
disabled={isSubmitting}
intent={Intent.PRIMARY}
type="submit"
onClick={handleSubmitPublishBtnClick}
text={<T id={'save_publish'} />}
onClick={handleSubmitCloseBtnClick}
text={<T id={'save_close'} />}
/>
<Popover
content={
<Menu>
<MenuItem
text={<T id={'publish_and_new'} />}
onClick={handleSubmitPublishAndNewBtnClick}
text={<T id={'close_and_new'} />}
onClick={handleSubmitCloseAndNewBtnClick}
/>
<MenuItem
text={<T id={'publish_continue_editing'} />}
onClick={handleSubmitPublishContinueEditingBtnClick}
text={<T id={'close_continue_editing'} />}
onClick={handleSubmitCloseContinueEditingBtnClick}
/>
</Menu>
}
@@ -156,13 +156,13 @@ export default function ReceiptFormFloatingActions({
</ButtonGroup>
</If>
{/* ----------- Save and New ----------- */}
<If condition={receiptId && receiptPublished}>
<If condition={receiptId && isClosed}>
<ButtonGroup>
<Button
disabled={isSubmitting}
intent={Intent.PRIMARY}
type="submit"
onClick={handleSubmitPublishBtnClick}
onClick={handleSubmitCloseBtnClick}
text={<T id={'save'} />}
/>
<Popover
@@ -170,7 +170,7 @@ export default function ReceiptFormFloatingActions({
<Menu>
<MenuItem
text={<T id={'save_and_new'} />}
onClick={handleSubmitPublishAndNewBtnClick}
onClick={handleSubmitCloseAndNewBtnClick}
/>
</Menu>
}

View File

@@ -34,11 +34,13 @@ function ReceiptList({
//#withReceiptActions
requestFetchReceiptsTable,
requestDeleteReceipt,
requestCloseReceipt,
addReceiptsTableQueries,
}) {
const history = useHistory();
const { formatMessage } = useIntl();
const [deleteReceipt, setDeleteReceipt] = useState(false);
const [closeReceipt, setCloseReceipt] = useState(false);
const [selectedRows, setSelectedRows] = useState([]);
const fetchReceipts = useQuery(['receipts-table', receiptTableQuery], () =>
@@ -85,6 +87,34 @@ function ReceiptList({
});
}, [deleteReceipt, requestDeleteReceipt, formatMessage]);
// Handle cancel/confirm receipt deliver.
const handleCloseReceipt = useCallback((receipt) => {
setCloseReceipt(receipt);
}, []);
// Handle cancel close receipt alert.
const handleCancelCloseReceipt = useCallback(() => {
setCloseReceipt(false);
}, []);
// Handle confirm receipt close.
const handleConfirmReceiptClose = useCallback(() => {
requestCloseReceipt(closeReceipt.id)
.then(() => {
setCloseReceipt(false);
AppToaster.show({
message: formatMessage({
id: 'the_receipt_has_been_successfully_closed',
}),
intent: Intent.SUCCESS,
});
queryCache.invalidateQueries('receipts-table');
})
.catch((error) => {
setCloseReceipt(false);
});
}, [closeReceipt, requestCloseReceipt, formatMessage]);
// Handle filter change to re-fetch data-table.
// const handleFilterChanged = useCallback(
// (filterConditions) => {
@@ -136,6 +166,7 @@ function ReceiptList({
<ReceiptsDataTable
onDeleteReceipt={handleDeleteReceipt}
onEditReceipt={handleEditReceipt}
onCloseReceipt={handleCloseReceipt}
onSelectedRowsChange={handleSelectedRowsChange}
/>
</Route>
@@ -154,6 +185,18 @@ function ReceiptList({
<T id={'once_delete_this_receipt_you_will_able_to_restore_it'} />
</p>
</Alert>
<Alert
cancelButtonText={<T id={'cancel'} />}
confirmButtonText={<T id={'close'} />}
intent={Intent.WARNING}
isOpen={closeReceipt}
onCancel={handleCancelCloseReceipt}
onConfirm={handleConfirmReceiptClose}
>
<p>
<T id={'are_sure_to_close_this_receipt'} />
</p>
</Alert>
</DashboardPageContent>
</DashboardInsider>
);

View File

@@ -7,6 +7,7 @@ import {
MenuItem,
MenuDivider,
Position,
Tag,
} from '@blueprintjs/core';
import { withRouter } from 'react-router';
import { FormattedMessage as T, useIntl } from 'react-intl';
@@ -17,7 +18,14 @@ import { compose, saveInvoke } from 'utils';
import { useIsValuePassed } from 'hooks';
import { CLASSES } from 'common/classes';
import { Choose, LoadingIndicator, DataTable, Money, Icon } from 'components';
import {
Choose,
LoadingIndicator,
DataTable,
Money,
Icon,
If,
} from 'components';
import ReceiptsEmptyStatus from './ReceiptsEmptyStatus';
@@ -42,6 +50,7 @@ function ReceiptsDataTable({
loading,
onEditReceipt,
onDeleteReceipt,
onCloseReceipt,
onSelectedRowsChange,
}) {
const { formatMessage } = useIntl();
@@ -62,7 +71,7 @@ function ReceiptsDataTable({
);
const actionMenuList = useCallback(
(estimate) => (
(receipt) => (
<Menu>
<MenuItem
icon={<Icon icon="reader-18" />}
@@ -72,12 +81,18 @@ function ReceiptsDataTable({
<MenuItem
icon={<Icon icon="pen-18" />}
text={formatMessage({ id: 'edit_receipt' })}
onClick={handleEditReceipt(estimate)}
onClick={handleEditReceipt(receipt)}
/>
<If condition={!receipt.is_closed}>
<MenuItem
text={formatMessage({ id: 'mark_as_closed' })}
onClick={() => onCloseReceipt(receipt)}
/>
</If>
<MenuItem
text={formatMessage({ id: 'delete_receipt' })}
intent={Intent.DANGER}
onClick={handleDeleteReceipt(estimate)}
onClick={handleDeleteReceipt(receipt)}
icon={<Icon icon="trash-16" iconSize={16} />}
/>
</Menu>
@@ -111,7 +126,8 @@ function ReceiptsDataTable({
{
id: 'receipt_number',
Header: formatMessage({ id: 'receipt_number' }),
accessor: (row) => (row.receipt_number ? `#${row.receipt_number}` : null),
accessor: (row) =>
row.receipt_number ? `#${row.receipt_number}` : null,
width: 140,
className: 'receipt_number',
},
@@ -137,6 +153,28 @@ function ReceiptsDataTable({
width: 140,
className: 'amount',
},
{
id: 'status',
Header: formatMessage({ id: 'status' }),
accessor: (row) => (
<Choose>
<Choose.When condition={row.is_closed}>
<Tag minimal={true}>
<T id={'closed'} />
</Tag>
</Choose.When>
<Choose.Otherwise>
<Tag minimal={true} intent={Intent.WARNING}>
<T id={'draft'} />
</Tag>
</Choose.Otherwise>
</Choose>
),
width: 140,
className: 'amount',
},
{
id: 'reference_no',
Header: formatMessage({ id: 'reference_no' }),

View File

@@ -5,16 +5,18 @@ import {
fetchReceipt,
fetchReceiptsTable,
editReceipt,
closeReceipt,
} from 'store/receipt/receipt.actions';
import t from 'store/types';
const mapDispatchToProps = (dispatch) => ({
requestSubmitReceipt: (form) => dispatch(submitReceipt({ form })),
requestFetchReceipt: (id) => dispatch(fetchReceipt({ id })),
requestEditReceipt: (id, form) => dispatch(editReceipt( id, form )),
requestEditReceipt: (id, form) => dispatch(editReceipt(id, form)),
requestDeleteReceipt: (id) => dispatch(deleteReceipt({ id })),
requestFetchReceiptsTable: (query = {}) =>
dispatch(fetchReceiptsTable({ query: { ...query } })),
requestCloseReceipt: (id) => dispatch(closeReceipt({ id })),
// requestDeleteBulkReceipt: (ids) => dispatch(deleteBulkReceipt({ ids })),
changeReceiptView: (id) =>
@@ -28,10 +30,11 @@ const mapDispatchToProps = (dispatch) => ({
type: t.RECEIPTS_TABLE_QUERIES_ADD,
payload: { queries },
}),
setReceiptNumberChanged:(isChanged) => dispatch({
setReceiptNumberChanged: (isChanged) =>
dispatch({
type: t.RECEIPT_NUMBER_CHANGED,
payload: { isChanged },
}),
});
});
export default connect(null, mapDispatchToProps);

View File

@@ -116,3 +116,7 @@ export const fetchReceiptsTable = ({ query = {} }) => {
});
});
};
export const closeReceipt = ({ id }) => {
return (dispatch) => ApiService.post(`sales/receipts/${id}/close`);
};