diff --git a/client/src/containers/Items/ItemsDataTable.js b/client/src/containers/Items/ItemsDataTable.js
index 948d99979..305a21b2c 100644
--- a/client/src/containers/Items/ItemsDataTable.js
+++ b/client/src/containers/Items/ItemsDataTable.js
@@ -12,7 +12,14 @@ import {
import { FormattedMessage as T, useIntl } from 'react-intl';
import classNames from 'classnames';
-import { Icon, DataTable, Money, LoadingIndicator, Choose } from 'components';
+import {
+ Icon,
+ DataTable,
+ Money,
+ LoadingIndicator,
+ Choose,
+ If,
+} from 'components';
import ItemsEmptyStatus from './ItemsEmptyStatus';
import { useIsValuePassed } from 'hooks';
import { CLASSES } from 'common/classes';
@@ -36,6 +43,8 @@ function ItemsDataTable({
// props
onEditItem,
onDeleteItem,
+ onInactiveItem,
+ onActivateItem,
onSelectedRowsChange,
}) {
const { formatMessage } = useIntl();
@@ -83,6 +92,20 @@ function ItemsDataTable({
text={formatMessage({ id: 'edit_item' })}
onClick={handleEditItem(item)}
/>
+
+ }
+ onClick={() => onInactiveItem(item)}
+ />
+
+
+ }
+ onClick={() => onActivateItem(item)}
+ />
+
}
@@ -91,7 +114,13 @@ function ItemsDataTable({
/>
),
- [handleEditItem, handleDeleteItem, formatMessage],
+ [
+ handleEditItem,
+ handleDeleteItem,
+ onInactiveItem,
+ onActivateItem,
+ formatMessage,
+ ],
);
const handleRowContextMenu = useCallback(
@@ -148,11 +177,11 @@ function ItemsDataTable({
{
Header: formatMessage({ id: 'cost_price' }),
accessor: (row) =>
- !isBlank(row.sell_price) ? (
-
- ) : (
- ''
- ),
+ !isBlank(row.sell_price) ? (
+
+ ) : (
+ ''
+ ),
className: 'cost-price',
width: 150,
},
@@ -196,6 +225,12 @@ function ItemsDataTable({
[onSelectedRowsChange],
);
+ const rowClassNames = (row) => {
+ return {
+ inactive: !row.original.active,
+ };
+ };
+
const showEmptyStatus = [
itemsCurrentPage.length === 0,
itemsCurrentViewId === -1,
@@ -221,6 +256,7 @@ function ItemsDataTable({
rowContextMenu={handleRowContextMenu}
expandable={false}
sticky={true}
+ rowClassNames={rowClassNames}
pagination={true}
pagesCount={itemsPagination.pagesCount}
autoResetSortBy={false}
diff --git a/client/src/containers/Items/ItemsList.js b/client/src/containers/Items/ItemsList.js
index 606501507..25f41f142 100644
--- a/client/src/containers/Items/ItemsList.js
+++ b/client/src/containers/Items/ItemsList.js
@@ -1,7 +1,7 @@
import React, { useEffect, useCallback, useState, useMemo } from 'react';
import { Route, Switch, useHistory } from 'react-router-dom';
import { Intent, Alert } from '@blueprintjs/core';
-import { useQuery } from 'react-query';
+import { useQuery, queryCache } from 'react-query';
import {
FormattedMessage as T,
FormattedHTMLMessage,
@@ -38,10 +38,14 @@ function ItemsList({
// #withItemsActions
requestDeleteItem,
requestFetchItems,
+ requestInactiveItem,
+ requestActivateItem,
addItemsTableQueries,
requestDeleteBulkItems,
}) {
const [deleteItem, setDeleteItem] = useState(false);
+ const [inactiveItem, setInactiveItem] = useState(false);
+ const [activateItem, setActivateItem] = useState(false);
const [selectedRows, setSelectedRows] = useState([]);
const [bulkDelete, setBulkDelete] = useState(false);
@@ -65,9 +69,8 @@ function ItemsList({
);
// Handle fetching the items table based on the given query.
- const fetchItems = useQuery(
- ['items-table', itemsTableQuery],
- (key, _query) => requestFetchItems({ ..._query }),
+ const fetchItems = useQuery(['items-table', itemsTableQuery], (key, _query) =>
+ requestFetchItems({ ..._query }),
);
// Handle click delete item.
@@ -92,33 +95,36 @@ function ItemsList({
// handle confirm delete item.
const handleConfirmDeleteItem = useCallback(() => {
- requestDeleteItem(deleteItem.id).then(() => {
- AppToaster.show({
- message: formatMessage({
- id: 'the_item_has_been_successfully_deleted',
- }),
- intent: Intent.SUCCESS,
- });
- setDeleteItem(false);
- }).catch(({ errors }) => {
- if (errors.find(error => error.type === 'ITEM_HAS_ASSOCIATED_TRANSACTINS')) {
+ requestDeleteItem(deleteItem.id)
+ .then(() => {
AppToaster.show({
message: formatMessage({
- id: 'the_item_has_associated_transactions',
+ id: 'the_item_has_been_successfully_deleted',
}),
- intent: Intent.DANGER,
+ intent: Intent.SUCCESS,
});
- }
- setDeleteItem(false);
- });
+ setDeleteItem(false);
+ })
+ .catch(({ errors }) => {
+ if (
+ errors.find(
+ (error) => error.type === 'ITEM_HAS_ASSOCIATED_TRANSACTINS',
+ )
+ ) {
+ AppToaster.show({
+ message: formatMessage({
+ id: 'the_item_has_associated_transactions',
+ }),
+ intent: Intent.DANGER,
+ });
+ }
+ setDeleteItem(false);
+ });
}, [requestDeleteItem, deleteItem, formatMessage]);
- const handleFetchData = useCallback(
- ({ pageIndex, pageSize, sortBy }) => {
-
- },
- [addItemsTableQueries],
- );
+ const handleFetchData = useCallback(({ pageIndex, pageSize, sortBy }) => {}, [
+ addItemsTableQueries,
+ ]);
// Handle filter change to re-fetch the items.
const handleFilterChanged = useCallback(
@@ -174,6 +180,62 @@ function ItemsList({
setBulkDelete(false);
}, []);
+ // Handle cancel/confirm item inactive.
+ const handleInactiveItem = useCallback((item) => {
+ setInactiveItem(item);
+ }, []);
+
+ // Handle cancel inactive item alert.
+ const handleCancelInactiveItem = useCallback(() => {
+ setInactiveItem(false);
+ }, []);
+
+ // Handle confirm item Inactive.
+ const handleConfirmItemInactive = useCallback(() => {
+ requestInactiveItem(inactiveItem.id)
+ .then(() => {
+ setInactiveItem(false);
+ AppToaster.show({
+ message: formatMessage({
+ id: 'the_item_has_been_successfully_inactivated',
+ }),
+ intent: Intent.SUCCESS,
+ });
+ queryCache.invalidateQueries('items-table');
+ })
+ .catch((error) => {
+ setInactiveItem(false);
+ });
+ }, [inactiveItem, requestInactiveItem, formatMessage]);
+
+ // Handle activate item click.
+ const handleActivateItem = useCallback((item) => {
+ setActivateItem(item);
+ });
+
+ // Handle activate item alert cancel.
+ const handleCancelActivateItem = useCallback(() => {
+ setActivateItem(false);
+ });
+
+ // Handle activate item confirm.
+ const handleConfirmItemActivate = useCallback(() => {
+ requestActivateItem(activateItem.id)
+ .then(() => {
+ setActivateItem(false);
+ AppToaster.show({
+ message: formatMessage({
+ id: 'the_item_has_been_successfully_activated',
+ }),
+ intent: Intent.SUCCESS,
+ });
+ queryCache.invalidateQueries('items-table');
+ })
+ .catch((error) => {
+ setActivateItem(false);
+ });
+ }, [activateItem, requestActivateItem, formatMessage]);
+
return (
+ }
+ confirmButtonText={}
+ intent={Intent.WARNING}
+ isOpen={inactiveItem}
+ onCancel={handleCancelInactiveItem}
+ onConfirm={handleConfirmItemInactive}
+ >
+
+
+
+
+ }
+ confirmButtonText={}
+ intent={Intent.WARNING}
+ isOpen={activateItem}
+ onCancel={handleCancelActivateItem}
+ onConfirm={handleConfirmItemActivate}
+ >
+
+
+
+
diff --git a/client/src/containers/Items/withItemsActions.js b/client/src/containers/Items/withItemsActions.js
index f117728c4..4458aace4 100644
--- a/client/src/containers/Items/withItemsActions.js
+++ b/client/src/containers/Items/withItemsActions.js
@@ -6,6 +6,8 @@ import {
submitItem,
editItem,
deleteBulkItems,
+ activateItem,
+ inactiveItem,
} from 'store/items/items.actions';
import t from 'store/types';
@@ -16,6 +18,8 @@ export const mapDispatchToProps = (dispatch) => ({
requestDeleteBulkItems: (ids) => dispatch(deleteBulkItems({ ids })),
requestSubmitItem: (form) => dispatch(submitItem({ form })),
requestEditItem: (id, form) => dispatch(editItem({ id, form })),
+ requestInactiveItem: (id) => dispatch(inactiveItem({ id })),
+ requestActivateItem: (id) => dispatch(activateItem({ id })),
addBulkActionItem: (id) =>
dispatch({
type: t.ITEM_BULK_ACTION_ADD,
diff --git a/client/src/containers/Purchases/Bill/BillsDataTable.js b/client/src/containers/Purchases/Bill/BillsDataTable.js
index c6dc514dc..809e68059 100644
--- a/client/src/containers/Purchases/Bill/BillsDataTable.js
+++ b/client/src/containers/Purchases/Bill/BillsDataTable.js
@@ -185,26 +185,19 @@ function BillsDataTable({
width: 140,
className: 'amount',
},
- {
- id: 'reference_no',
- Header: formatMessage({ id: 'reference_no' }),
- accessor: 'reference_no',
- width: 140,
- className: 'reference_no',
- },
{
id: 'status',
Header: formatMessage({ id: 'status' }),
accessor: (row) => (
-
+
-
+
@@ -213,6 +206,13 @@ function BillsDataTable({
width: 140,
className: 'status',
},
+ {
+ id: 'reference_no',
+ Header: formatMessage({ id: 'reference_no' }),
+ accessor: 'reference_no',
+ width: 140,
+ className: 'reference_no',
+ },
{
id: 'actions',
Header: '',
diff --git a/client/src/containers/Sales/Estimate/EstimateFloatingActions.js b/client/src/containers/Sales/Estimate/EstimateFloatingActions.js
index bb9b4b93a..3864c01fc 100644
--- a/client/src/containers/Sales/Estimate/EstimateFloatingActions.js
+++ b/client/src/containers/Sales/Estimate/EstimateFloatingActions.js
@@ -25,38 +25,38 @@ export default function EstimateFloatingActions({
onCancelClick,
onClearClick,
estimateId,
- estimatePublished,
+ isDelivered,
}) {
const { resetForm, submitForm } = useFormikContext();
- const handleSubmitPublishBtnClick = (event) => {
+ const handleSubmitDeliverBtnClick = (event) => {
saveInvoke(onSubmitClick, event, {
redirect: true,
- publish: true,
+ deliver: true,
});
};
- const handleSubmitPublishAndNewBtnClick = (event) => {
+ const handleSubmitDeliverAndNewBtnClick = (event) => {
submitForm();
saveInvoke(onSubmitClick, event, {
redirect: false,
- publish: true,
+ deliver: true,
resetForm: true,
});
};
- const handleSubmitPublishContinueEditingBtnClick = (event) => {
+ const handleSubmitDeliverContinueEditingBtnClick = (event) => {
submitForm();
saveInvoke(onSubmitClick, event, {
redirect: false,
- publish: true,
+ deliver: true,
});
};
const handleSubmitDraftBtnClick = (event) => {
saveInvoke(onSubmitClick, event, {
redirect: true,
- publish: false,
+ deliver: false,
});
};
@@ -64,7 +64,7 @@ export default function EstimateFloatingActions({
submitForm();
saveInvoke(onSubmitClick, event, {
redirect: false,
- publish: false,
+ deliver: false,
resetForm: true,
});
};
@@ -73,7 +73,7 @@ export default function EstimateFloatingActions({
submitForm();
saveInvoke(onSubmitClick, event, {
redirect: false,
- publish: false,
+ deliver: false,
});
};
@@ -88,26 +88,26 @@ export default function EstimateFloatingActions({
return (
- {/* ----------- Save And Publish ----------- */}
-
+ {/* ----------- Save And Deliver ----------- */}
+
}
+ onClick={handleSubmitDeliverBtnClick}
+ text={}
/>
}
- onClick={handleSubmitPublishAndNewBtnClick}
+ onClick={handleSubmitDeliverAndNewBtnClick}
/>
}
- onClick={handleSubmitPublishContinueEditingBtnClick}
+ onClick={handleSubmitDeliverContinueEditingBtnClick}
/>
}
@@ -156,13 +156,13 @@ export default function EstimateFloatingActions({
{/* ----------- Save and New ----------- */}
-
+
}
/>
}
- onClick={handleSubmitPublishAndNewBtnClick}
+ onClick={handleSubmitDeliverAndNewBtnClick}
/>
}
diff --git a/client/src/containers/Sales/Estimate/EstimateForm.js b/client/src/containers/Sales/Estimate/EstimateForm.js
index 73818f69a..03a90e7ce 100644
--- a/client/src/containers/Sales/Estimate/EstimateForm.js
+++ b/client/src/containers/Sales/Estimate/EstimateForm.js
@@ -54,6 +54,7 @@ const defaultInitialValues = {
estimate_date: moment(new Date()).format('YYYY-MM-DD'),
expiration_date: moment(new Date()).format('YYYY-MM-DD'),
estimate_number: '',
+ delivered: '',
reference: '',
note: '',
terms_conditions: '',
@@ -181,6 +182,7 @@ const EstimateForm = ({
}
const form = {
...values,
+ delivered: submitPayload.deliver,
// Exclude all entries properties that out of request schema.
entries: entries.map((entry) => ({
...pick(entry, Object.keys(defaultEstimate)),
@@ -256,7 +258,7 @@ const EstimateForm = ({
initialValues={initialValues}
onSubmit={handleFormSubmit}
>
- {({ isSubmitting }) => (
+ {({ isSubmitting ,values }) => (
)}
diff --git a/client/src/containers/Sales/Estimate/EstimateForm.schema.js b/client/src/containers/Sales/Estimate/EstimateForm.schema.js
index a7830d9cc..7b7030469 100644
--- a/client/src/containers/Sales/Estimate/EstimateForm.schema.js
+++ b/client/src/containers/Sales/Estimate/EstimateForm.schema.js
@@ -27,6 +27,7 @@ const Schema = Yup.object().shape({
.min(1)
.max(DATATYPES_LENGTH.TEXT)
.label(formatMessage({ id: 'note' })),
+ delivered: Yup.boolean().required(),
entries: Yup.array().of(
Yup.object().shape({
quantity: Yup.number()
diff --git a/client/src/containers/Sales/Estimate/EstimateList.js b/client/src/containers/Sales/Estimate/EstimateList.js
index feab8e7c7..b6dae06e4 100644
--- a/client/src/containers/Sales/Estimate/EstimateList.js
+++ b/client/src/containers/Sales/Estimate/EstimateList.js
@@ -1,6 +1,6 @@
import React, { useEffect, useCallback, useMemo, useState } from 'react';
import { Route, Switch, useHistory } from 'react-router-dom';
-import { useQuery } from 'react-query';
+import { useQuery, queryCache } from 'react-query';
import { Alert, Intent } from '@blueprintjs/core';
import AppToaster from 'components/AppToaster';
@@ -35,11 +35,18 @@ function EstimateList({
//#withEistimateActions
requestFetchEstimatesTable,
requestDeleteEstimate,
+ requestDeliverdEstimate,
+ requestApproveEstimate,
+ requestRejectEstimate,
addEstimatesTableQueries,
}) {
const history = useHistory();
const { formatMessage } = useIntl();
const [deleteEstimate, setDeleteEstimate] = useState(false);
+ const [deliverEstimate, setDeliverEstimate] = useState(false);
+ const [approveEstimate, setApproveEstimate] = useState(false);
+ const [rejectEstimate, setRejectEstimate] = useState(false);
+
const [selectedRows, setSelectedRows] = useState([]);
// const fetchResourceViews = useQuery(
@@ -86,6 +93,88 @@ function EstimateList({
});
}, [deleteEstimate, requestDeleteEstimate, formatMessage]);
+ // Handle cancel/confirm estimate deliver.
+ const handleDeliverEstimate = useCallback((estimate) => {
+ setDeliverEstimate(estimate);
+ }, []);
+
+ // Handle cancel deliver estimate alert.
+ const handleCancelDeliverEstimate = useCallback(() => {
+ setDeliverEstimate(false);
+ }, []);
+
+ // Handle confirm estimate deliver.
+ const handleConfirmEstimateDeliver = useCallback(() => {
+ requestDeliverdEstimate(deliverEstimate.id)
+ .then(() => {
+ setDeliverEstimate(false);
+ AppToaster.show({
+ message: formatMessage({
+ id: 'the_estimate_has_been_successfully_delivered',
+ }),
+ intent: Intent.SUCCESS,
+ });
+ queryCache.invalidateQueries('estimates-table');
+ })
+ .catch((error) => {
+ // setDeliverEstimate(false);
+ });
+ }, [deliverEstimate, requestDeliverdEstimate, formatMessage]);
+
+ // Handle cancel/confirm estimate approve.
+ const handleApproveEstimate = useCallback((estimate) => {
+ setApproveEstimate(estimate);
+ }, []);
+
+ // Handle cancel approve estimate alert.
+ const handleCancelApproveEstimate = useCallback(() => {
+ setApproveEstimate(false);
+ }, []);
+
+ // Handle confirm estimate approve.
+ const handleConfirmEstimateApprove = useCallback(() => {
+ requestApproveEstimate(approveEstimate.id)
+ .then(() => {
+ setApproveEstimate(false);
+ AppToaster.show({
+ message: formatMessage({
+ id: 'the_estimate_has_been_successfully_approved',
+ }),
+ intent: Intent.SUCCESS,
+ });
+ queryCache.invalidateQueries('estimates-table');
+ })
+ .catch((error) => {
+ // setApproveEstimate(false);
+ });
+ }, [approveEstimate, requestApproveEstimate, formatMessage]);
+
+ // Handle cancel/confirm estimate reject.
+ const handleRejectEstimate = useCallback((estimate) => {
+ setRejectEstimate(estimate);
+ }, []);
+
+ // Handle cancel reject estimate alert.
+ const handleCancelRejectEstimate = useCallback(() => {
+ setRejectEstimate(false);
+ }, []);
+
+ // Handle confirm estimate reject.
+ const handleConfirmEstimateReject = useCallback(() => {
+ requestRejectEstimate(rejectEstimate.id)
+ .then(() => {
+ setRejectEstimate(false);
+ AppToaster.show({
+ message: formatMessage({
+ id: 'the_estimate_has_been_successfully_rejected',
+ }),
+ intent: Intent.SUCCESS,
+ });
+ queryCache.invalidateQueries('estimates-table');
+ })
+ .catch((error) => {});
+ }, [rejectEstimate, requestRejectEstimate, formatMessage]);
+
// Handle filter change to re-fetch data-table.
const handleFilterChanged = useCallback(() => {}, [fetchEstimate]);
@@ -127,6 +216,9 @@ function EstimateList({
@@ -145,6 +237,42 @@ function EstimateList({
+ }
+ confirmButtonText={}
+ intent={Intent.WARNING}
+ isOpen={deliverEstimate}
+ onCancel={handleCancelDeliverEstimate}
+ onConfirm={handleConfirmEstimateDeliver}
+ >
+
+
+
+
+ }
+ confirmButtonText={}
+ intent={Intent.WARNING}
+ isOpen={approveEstimate}
+ onCancel={handleCancelApproveEstimate}
+ onConfirm={handleConfirmEstimateApprove}
+ >
+
+
+
+
+ }
+ confirmButtonText={}
+ intent={Intent.WARNING}
+ isOpen={rejectEstimate}
+ onCancel={handleCancelRejectEstimate}
+ onConfirm={handleConfirmEstimateReject}
+ >
+
+
+
+
);
diff --git a/client/src/containers/Sales/Estimate/EstimatesDataTable.js b/client/src/containers/Sales/Estimate/EstimatesDataTable.js
index 55bed075f..ab7d53b26 100644
--- a/client/src/containers/Sales/Estimate/EstimatesDataTable.js
+++ b/client/src/containers/Sales/Estimate/EstimatesDataTable.js
@@ -7,6 +7,7 @@ import {
MenuItem,
MenuDivider,
Position,
+ Tag,
} from '@blueprintjs/core';
import classNames from 'classnames';
import { FormattedMessage as T, useIntl } from 'react-intl';
@@ -17,9 +18,9 @@ import { compose, saveInvoke } from 'utils';
import { useIsValuePassed } from 'hooks';
import LoadingIndicator from 'components/LoadingIndicator';
-import { DataTable, Money, Choose, Icon } from 'components';
+import { DataTable, Money, Choose, Icon, If } from 'components';
import EstimatesEmptyStatus from './EstimatesEmptyStatus';
-
+import { statusAccessor } from './components';
import withEstimates from './withEstimates';
import withEstimateActions from './withEstimateActions';
@@ -38,6 +39,9 @@ function EstimatesDataTable({
// #ownProps
onEditEstimate,
onDeleteEstimate,
+ onDeliverEstimate,
+ onApproveEstimate,
+ onRejectEstimate,
onSelectedRowsChange,
}) {
const { formatMessage } = useIntl();
@@ -70,6 +74,40 @@ function EstimatesDataTable({
text={formatMessage({ id: 'edit_estimate' })}
onClick={handleEditEstimate(estimate)}
/>
+
+
+
+
+
+
+
+
+
+
(row.estimate_number ? `#${row.estimate_number}` : null),
+ accessor: (row) =>
+ row.estimate_number ? `#${row.estimate_number}` : null,
width: 140,
className: 'estimate_number',
},
@@ -126,6 +165,15 @@ function EstimatesDataTable({
width: 140,
className: 'amount',
},
+
+ {
+ id: 'status',
+ Header: formatMessage({ id: 'status' }),
+ accessor: (row) => statusAccessor(row),
+ width: 140,
+ className: 'status',
+ },
+
{
id: 'reference',
Header: formatMessage({ id: 'reference_no' }),
@@ -133,6 +181,7 @@ function EstimatesDataTable({
width: 140,
className: 'reference',
},
+
{
id: 'actions',
Header: '',
@@ -183,7 +232,7 @@ function EstimatesDataTable({
const showEmptyStatus = [
estimatesCurrentPage.length === 0,
estimatesCurrentViewId === -1,
- ].every(d => d === true);
+ ].every((d) => d === true);
return (
diff --git a/client/src/containers/Sales/Estimate/components.js b/client/src/containers/Sales/Estimate/components.js
new file mode 100644
index 000000000..f0e218ddb
--- /dev/null
+++ b/client/src/containers/Sales/Estimate/components.js
@@ -0,0 +1,31 @@
+import React from 'react';
+import { Intent, Tag } from '@blueprintjs/core';
+import { Choose, If } from 'components';
+import { FormattedMessage as T, useIntl } from 'react-intl';
+
+export const statusAccessor = (row) => (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+);
diff --git a/client/src/containers/Sales/Estimate/withEstimateActions.js b/client/src/containers/Sales/Estimate/withEstimateActions.js
index 7145e1a23..5c36a8fd2 100644
--- a/client/src/containers/Sales/Estimate/withEstimateActions.js
+++ b/client/src/containers/Sales/Estimate/withEstimateActions.js
@@ -5,6 +5,9 @@ import {
deleteEstimate,
fetchEstimate,
fetchEstimatesTable,
+ deliverEstimate,
+ approveEstimate,
+ rejectEstimate
} from 'store/Estimate/estimates.actions';
import t from 'store/types';
@@ -15,6 +18,9 @@ const mapDipatchToProps = (dispatch) => ({
requestFetchEstimatesTable: (query = {}) =>
dispatch(fetchEstimatesTable({ query: { ...query } })),
requestDeleteEstimate: (id) => dispatch(deleteEstimate({ id })),
+ requestDeliverdEstimate: (id) => dispatch(deliverEstimate({ id })),
+ requestApproveEstimate: (id) => dispatch(approveEstimate({ id })),
+ requestRejectEstimate: (id) => dispatch(rejectEstimate({ id })),
changeEstimateView: (id) =>
dispatch({
diff --git a/client/src/containers/Sales/Invoice/InvoiceFloatingActions.js b/client/src/containers/Sales/Invoice/InvoiceFloatingActions.js
index 115020160..a6ecc9e56 100644
--- a/client/src/containers/Sales/Invoice/InvoiceFloatingActions.js
+++ b/client/src/containers/Sales/Invoice/InvoiceFloatingActions.js
@@ -32,7 +32,7 @@ export default function InvoiceFloatingActions({
const handleSubmitDeliverBtnClick = (event) => {
saveInvoke(onSubmitClick, event, {
redirect: true,
- delivered: true,
+ deliver: true,
});
};
@@ -40,7 +40,7 @@ export default function InvoiceFloatingActions({
submitForm();
saveInvoke(onSubmitClick, event, {
redirect: false,
- delivered: true,
+ deliver: true,
resetForm: true,
});
};
@@ -49,14 +49,14 @@ export default function InvoiceFloatingActions({
submitForm();
saveInvoke(onSubmitClick, event, {
redirect: false,
- delivered: true,
+ deliver: true,
});
};
const handleSubmitDraftBtnClick = (event) => {
saveInvoke(onSubmitClick, event, {
redirect: true,
- delivered: false,
+ deliver: false,
});
};
@@ -64,7 +64,7 @@ export default function InvoiceFloatingActions({
submitForm();
saveInvoke(onSubmitClick, event, {
redirect: false,
- delivered: false,
+ deliver: false,
resetForm: true,
});
};
@@ -73,7 +73,7 @@ export default function InvoiceFloatingActions({
submitForm();
saveInvoke(onSubmitClick, event, {
redirect: false,
- delivered: false,
+ deliver: false,
});
};
diff --git a/client/src/containers/Sales/Invoice/InvoicesDataTable.js b/client/src/containers/Sales/Invoice/InvoicesDataTable.js
index 7944be3be..704858eb2 100644
--- a/client/src/containers/Sales/Invoice/InvoicesDataTable.js
+++ b/client/src/containers/Sales/Invoice/InvoicesDataTable.js
@@ -145,13 +145,6 @@ function InvoicesDataTable({
width: 140,
className: 'balance',
},
- {
- id: 'reference_no',
- Header: formatMessage({ id: 'reference_no' }),
- accessor: 'reference_no',
- width: 140,
- className: 'reference_no',
- },
{
id: 'status',
Header: formatMessage({ id: 'status' }),
@@ -159,6 +152,13 @@ function InvoicesDataTable({
width: 140,
className: 'status',
},
+ {
+ id: 'reference_no',
+ Header: formatMessage({ id: 'reference_no' }),
+ accessor: 'reference_no',
+ width: 140,
+ className: 'reference_no',
+ },
{
id: 'actions',
Header: '',
diff --git a/client/src/containers/Sales/Receipt/ReceiptsDataTable.js b/client/src/containers/Sales/Receipt/ReceiptsDataTable.js
index ed221b606..488e4d64a 100644
--- a/client/src/containers/Sales/Receipt/ReceiptsDataTable.js
+++ b/client/src/containers/Sales/Receipt/ReceiptsDataTable.js
@@ -159,7 +159,7 @@ function ReceiptsDataTable({
accessor: (row) => (
-
+
diff --git a/client/src/lang/en/index.js b/client/src/lang/en/index.js
index 11c190bf3..7e5a08a84 100644
--- a/client/src/lang/en/index.js
+++ b/client/src/lang/en/index.js
@@ -902,4 +902,33 @@ export default {
open: 'Open',
are_sure_to_open_this_bill: 'Are you sure you want to open this bill?',
opened: 'Opened',
-};
+ the_estimate_has_been_successfully_delivered:
+ 'The estimate has been successfully delivered.',
+ the_estimate_has_been_successfully_approved:
+ 'The estimate has been successfully approved.',
+ the_estimate_has_been_successfully_rejected:
+ 'The estimate has been successfully rejected.',
+ are_sure_to_deliver_this_estimate:
+ 'Are you sure you want to deliver this estimate?',
+ approve: 'Approve',
+ are_sure_to_approve_this_estimate:
+ 'Are you sure you want to approve this estimate?',
+ reject: 'Reject',
+ are_sure_to_reject_this_estimate:
+ 'Are you sure you want to reject this estimate?',
+ mark_as_approved: 'Mark as approved',
+ mark_as_rejected: 'Mark as rejected',
+ delivered: 'Delivered',
+ rejected: 'Rejected',
+ approved: 'Approved',
+ the_item_has_been_successfully_inactivated:
+ 'The item has been successfully inactivated.',
+ the_item_has_been_successfully_activated:
+ 'The item has been successfully activated.',
+ are_sure_to_inactive_this_item:
+ 'Are you sure you want to inactive this item? You will be able to activate it later',
+ are_sure_to_activate_this_item:
+ 'Are you sure you want to activate this item? You will be able to inactivate it later',
+ inactivate_item: 'Inactivate Item',
+ activate_item: 'Activate Item',
+ };
diff --git a/client/src/store/Estimate/estimates.actions.js b/client/src/store/Estimate/estimates.actions.js
index ddb988f4a..b6632dc65 100644
--- a/client/src/store/Estimate/estimates.actions.js
+++ b/client/src/store/Estimate/estimates.actions.js
@@ -75,7 +75,7 @@ export const fetchEstimate = ({ id }) => {
export const fetchEstimatesTable = ({ query = {} }) => {
return (dispatch, getState) =>
- new Promise((resolve, rejcet) => {
+ new Promise((resolve, reject) => {
const pageQuery = getState().salesEstimates.tableQuery;
dispatch({
type: t.ESTIMATES_TABLE_LOADING,
@@ -117,7 +117,17 @@ export const fetchEstimatesTable = ({ query = {} }) => {
resolve(response);
})
.catch((error) => {
- rejcet(error);
+ reject(error);
});
});
};
+
+export const deliverEstimate = ({ id }) => {
+ return (dispatch) => ApiService.post(`sales/estimates/${id}/deliver`);
+};
+export const approveEstimate = ({ id }) => {
+ return (dispatch) => ApiService.post(`sales/estimates/${id}/approve`);
+};
+export const rejectEstimate = ({ id }) => {
+ return (dispatch) => ApiService.post(`sales/estimates/${id}/reject`);
+};
diff --git a/client/src/store/items/items.actions.js b/client/src/store/items/items.actions.js
index d836990aa..f57fc3698 100644
--- a/client/src/store/items/items.actions.js
+++ b/client/src/store/items/items.actions.js
@@ -105,3 +105,11 @@ export const deleteBulkItems = ({ ids }) => {
});
});
};
+
+export const activateItem = ({ id }) => {
+ return (dispatch) => ApiService.post(`items/${id}/activate`);
+};
+
+export const inactiveItem = ({ id }) => {
+ return (dispatch) => ApiService.post(`items/${id}/inactivate`);
+};
diff --git a/client/src/style/pages/items.scss b/client/src/style/pages/items.scss
index 1a5480885..383b524a0 100644
--- a/client/src/style/pages/items.scss
+++ b/client/src/style/pages/items.scss
@@ -1,12 +1,11 @@
-
-.page-form--item{
+.page-form--item {
$self: '.page-form';
padding: 20px;
- #{$self}__header{
+ #{$self}__header {
padding: 0;
}
- #{$self}__primary-section{
+ #{$self}__primary-section {
overflow: hidden;
padding-top: 5px;
margin-bottom: 20px;
@@ -15,89 +14,88 @@
max-width: 1000px;
}
- #{$self}__body{
- .bp3-form-group{
+ #{$self}__body {
+ .bp3-form-group {
max-width: 500px;
margin-bottom: 14px;
-
- &.bp3-inline{
-
- .bp3-label{
+
+ &.bp3-inline {
+ .bp3-label {
min-width: 140px;
}
}
- .bp3-form-content{
+ .bp3-form-content {
width: 100%;
}
}
-
- h3{
+
+ h3 {
font-weight: 500;
font-size: 14px;
margin-bottom: 1.4rem;
}
-
- .bp3-control{
-
- h3{
+
+ .bp3-control {
+ h3 {
display: inline;
margin-bottom: 0;
}
}
-
+
.form-group--sellable,
- .form-group--purchasable{
+ .form-group--purchasable {
margin-bottom: 1rem;
}
}
- #{$self}__section{
+ #{$self}__section {
max-width: 850px;
margin-bottom: 1rem;
- .bp3-form-group{
+ .bp3-form-group {
max-width: 400px;
}
- &--selling-cost{
+ &--selling-cost {
border-bottom: 1px solid #eaeaea;
margin-bottom: 1.25rem;
padding-bottom: 0.25rem;
}
}
- #{$self}__floating-actions{
+ #{$self}__floating-actions {
margin-left: -40px;
margin-right: -40px;
- .form-group--active{
+ .form-group--active {
display: inline-block;
margin: 0;
margin-left: 40px;
}
}
- .bp3-tooltip-indicator{
+ .bp3-tooltip-indicator {
border-bottom: 1px dashed #d0d0d0;
}
}
-
-
-.dashboard__insider--items-list{
-
-
- .bigcapital-datatable{
-
- .table{
- .tbody{
- .item_type.td{
-
- .bp3-tag{
+.dashboard__insider--items-list {
+ .bigcapital-datatable {
+ .table {
+ .tbody {
+ .item_type.td {
+ .bp3-tag {
font-size: 13px;
}
}
+ .tr.inactive .td {
+ color: #646b82;
+
+ &.normal .#{$ns}-icon {
+ color: #9eaab6;
+ }
+ }
}
}
}
-}
\ No newline at end of file
+}