diff --git a/client/src/components/DataTableCells/PaymentReceiveListFieldCell.js b/client/src/components/DataTableCells/PaymentReceiveListFieldCell.js
new file mode 100644
index 000000000..0b37e05f7
--- /dev/null
+++ b/client/src/components/DataTableCells/PaymentReceiveListFieldCell.js
@@ -0,0 +1,35 @@
+import React, { useCallback } from 'react';
+import PaymentReceiveListField from 'components/PaymentReceiveListField';
+import classNames from 'classnames';
+import { FormGroup, Classes, Intent } from '@blueprintjs/core';
+
+function PaymentReceiveListFieldCell({
+ column: { id },
+ row: { index },
+ cell: { value: initialValue },
+ payload: { invoices, updateData, errors },
+}) {
+ const handleInvoicesSelected = useCallback(
+ (_item) => {
+ updateData(index, id, _item.id);
+ },
+ [updateData, index, id],
+ );
+
+ const error = errors?.[index]?.[id];
+
+ return (
+
+
+
+ );
+}
+
+export default PaymentReceiveListFieldCell;
diff --git a/client/src/components/PaymentReceiveListField.js b/client/src/components/PaymentReceiveListField.js
new file mode 100644
index 000000000..4c9f828ba
--- /dev/null
+++ b/client/src/components/PaymentReceiveListField.js
@@ -0,0 +1,38 @@
+import React, { useCallback } from 'react';
+import { MenuItem } from '@blueprintjs/core';
+import ListSelect from 'components/ListSelect';
+import { FormattedMessage as T } from 'react-intl';
+
+function PaymentReceiveListField({
+ invoices,
+ selectedInvoiceId,
+ onInvoiceSelected,
+ defaultSelectText = ,
+}) {
+ const onInvoiceSelect = useCallback((_invoice) => {
+ onInvoiceSelected && onInvoiceSelected(_invoice);
+ });
+
+ const handleInvoiceRenderer = useCallback(
+ (item, { handleClick }) => (
+
+ ),
+ [],
+ );
+
+ return (
+ }
+ itemRenderer={handleInvoiceRenderer}
+ popoverProps={{ minimal: true }}
+ onItemSelect={onInvoiceSelect}
+ selectedItem={`${selectedInvoiceId}`}
+ selectedItemProp={'id'}
+ labelProp={'name'}
+ defaultText={defaultSelectText}
+ />
+ );
+}
+
+export default PaymentReceiveListField;
diff --git a/client/src/config/sidebarMenu.js b/client/src/config/sidebarMenu.js
index 7f6e7bf23..9e72634cf 100644
--- a/client/src/config/sidebarMenu.js
+++ b/client/src/config/sidebarMenu.js
@@ -46,6 +46,13 @@ export default [
text: ,
href: '/invoices/new',
},
+ {
+ text: ,
+ href: '/payment-receive/new',
+ },
+ {
+ divider: true,
+ },
{
text: ,
href: '/receipts/new',
@@ -56,10 +63,11 @@ export default [
text: ,
children: [
{
- icon: 'cut',
- text: 'cut',
- label: '⌘C',
- disabled: false,
+ text: ,
+ href: '/bill/new',
+ },
+ {
+ text: ,
},
],
},
diff --git a/client/src/containers/Purchases/BillForm.js b/client/src/containers/Purchases/BillForm.js
new file mode 100644
index 000000000..fce4b0ae4
--- /dev/null
+++ b/client/src/containers/Purchases/BillForm.js
@@ -0,0 +1,299 @@
+import React, {
+ useMemo,
+ useState,
+ useCallback,
+ useEffect,
+ useRef,
+} from 'react';
+import * as Yup from 'yup';
+import { useFormik } from 'formik';
+import moment from 'moment';
+import { Intent, FormGroup, TextArea } from '@blueprintjs/core';
+
+import { FormattedMessage as T, useIntl } from 'react-intl';
+import { pick, omit } from 'lodash';
+
+import BillFormHeader from './BillFormHeader';
+import EstimatesItemsTable from 'containers/Sales/Estimate/EntriesItemsTable';
+import BillFormFooter from './BillFormFooter';
+
+import withDashboardActions from 'containers/Dashboard/withDashboardActions';
+import withMediaActions from 'containers/Media/withMediaActions';
+import withBillActions from './withBillActions';
+
+import { AppToaster } from 'components';
+import Dragzone from 'components/Dragzone';
+import useMedia from 'hooks/useMedia';
+
+import { compose, repeatValue } from 'utils';
+
+const MIN_LINES_NUMBER = 4;
+
+function BillForm({
+ //#WithMedia
+ requestSubmitMedia,
+ requestDeleteMedia,
+
+ //#withBillActions
+ requestSubmitBill,
+
+ //#withDashboard
+ changePageTitle,
+ changePageSubtitle,
+
+ //#withBillDetail
+ bill,
+
+ //#Own Props
+ onFormSubmit,
+ onCancelForm,
+}) {
+ const { formatMessage } = useIntl();
+ const [payload, setPayload] = useState({});
+
+ const {
+ setFiles,
+ saveMedia,
+ deletedFiles,
+ setDeletedFiles,
+ deleteMedia,
+ } = useMedia({
+ saveCallback: requestSubmitMedia,
+ deleteCallback: requestDeleteMedia,
+ });
+
+ const handleDropFiles = useCallback((_files) => {
+ setFiles(_files.filter((file) => file.uploaded === false));
+ }, []);
+
+ const savedMediaIds = useRef([]);
+ const clearSavedMediaIds = () => {
+ savedMediaIds.current = [];
+ };
+
+ useEffect(() => {
+ if (bill && bill.id) {
+ changePageTitle(formatMessage({ id: 'edit_bill' }));
+ } else {
+ changePageTitle(formatMessage({ id: 'new_bill' }));
+ }
+ });
+
+ const validationSchema = Yup.object().shape({
+ vendor_id: Yup.number()
+ .required()
+ .label(formatMessage({ id: 'vendor_name_' })),
+ bill_date: Yup.date()
+ .required()
+ .label(formatMessage({ id: 'bill_date_' })),
+ due_date: Yup.date()
+ .required()
+ .label(formatMessage({ id: 'due_date_' })),
+ bill_number: Yup.number()
+ .required()
+ .label(formatMessage({ id: 'bill_number_' })),
+ reference_no: Yup.string().min(1).max(255),
+ status: Yup.string().required(),
+ note: Yup.string()
+ .trim()
+ .min(1)
+ .max(1024)
+ .label(formatMessage({ id: 'note' })),
+
+ entries: Yup.array().of(
+ Yup.object().shape({
+ quantity: Yup.number().nullable(),
+ rate: Yup.number().nullable(),
+ item_id: Yup.number()
+ .nullable()
+ .when(['quantity', 'rate'], {
+ is: (quantity, rate) => quantity || rate,
+ then: Yup.number().required(),
+ }),
+ total: Yup.number().nullable(),
+ discount: Yup.number().nullable(),
+ description: Yup.string().nullable(),
+ }),
+ ),
+ });
+
+ const saveBillSubmit = useCallback(
+ (payload) => {
+ onFormSubmit && onFormSubmit(payload);
+ },
+ [onFormSubmit],
+ );
+
+ const defaultBill = useMemo(() => ({
+ index: 0,
+ item_id: null,
+ rate: null,
+ discount: null,
+ quantity: null,
+ description: '',
+ status: '',
+ }));
+
+ const defaultInitialValues = useMemo(
+ () => ({
+ accept: '',
+ vendor_name: '',
+ bill_number: '',
+ bill_date: moment(new Date()).format('YYYY-MM-DD'),
+ due_date: moment(new Date()).format('YYYY-MM-DD'),
+ reference_no: '',
+ note: '',
+ entries: [...repeatValue(defaultBill, MIN_LINES_NUMBER)],
+ }),
+ [defaultBill],
+ );
+
+ const orderingIndex = (_invoice) => {
+ return _invoice.map((item, index) => ({
+ ...item,
+ index: index + 1,
+ }));
+ };
+
+ const initialValues = useMemo(
+ () => ({
+ ...defaultInitialValues,
+ entries: orderingIndex(defaultInitialValues.entries),
+ }),
+ [defaultInitialValues],
+ );
+
+ const initialAttachmentFiles = useMemo(() => {
+ return bill && bill.media
+ ? bill.media.map((attach) => ({
+ preview: attach.attachment_file,
+ uploaded: true,
+ metadata: { ...attach },
+ }))
+ : [];
+ }, [bill]);
+
+ const formik = useFormik({
+ enableReinitialize: true,
+ validationSchema,
+ initialValues: {
+ ...initialValues,
+ },
+ onSubmit: async (values, { setSubmitting, setErrors, resetForm }) => {
+ setSubmitting(true);
+ const entries = values.entries.map((item) => omit(item, ['total']));
+
+ const form = {
+ ...values,
+ entries,
+ };
+ const saveBill = (mediaIds) =>
+ new Promise((resolve, reject) => {
+ const requestForm = { ...form, media_ids: mediaIds };
+
+ requestSubmitBill(requestForm)
+ .then((response) => {
+ AppToaster.show({
+ message: formatMessage(
+ { id: 'the_bill_has_been_successfully_created' },
+ { number: values.bill_number },
+ ),
+ intent: Intent.SUCCESS,
+ });
+ setSubmitting(false);
+ resetForm();
+ saveBillSubmit({ action: 'new', ...payload });
+ clearSavedMediaIds();
+ })
+ .catch((errors) => {
+ setSubmitting(false);
+ });
+ });
+
+ Promise.all([saveMedia(), deleteMedia()])
+ .then(([savedMediaResponses]) => {
+ const mediaIds = savedMediaResponses.map((res) => res.data.media.id);
+ savedMediaIds.current = mediaIds;
+ return savedMediaResponses;
+ })
+ .then(() => {
+ return saveBill(savedMediaIds.current);
+ });
+ },
+ });
+
+ const handleSubmitClick = useCallback(
+ (payload) => {
+ setPayload(payload);
+ formik.submitForm();
+ },
+ [setPayload, formik],
+ );
+
+ const handleCancelClick = useCallback(
+ (payload) => {
+ onCancelForm && onCancelForm(payload);
+ },
+ [onCancelForm],
+ );
+
+ console.log(formik.errors, 'Bill');
+ const handleDeleteFile = useCallback(
+ (_deletedFiles) => {
+ _deletedFiles.forEach((deletedFile) => {
+ if (deletedFile.uploaded && deletedFile.metadata.id) {
+ setDeletedFiles([...deletedFiles, deletedFile.metadata.id]);
+ }
+ });
+ },
+ [setDeletedFiles, deletedFiles],
+ );
+
+ const onClickCleanAllLines = () => {
+ formik.setFieldValue(
+ 'entries',
+ orderingIndex([...repeatValue(defaultBill, MIN_LINES_NUMBER)]),
+ );
+ };
+
+ const onClickAddNewRow = () => {
+ formik.setFieldValue(
+ 'entries',
+ orderingIndex([...formik.values.entries, defaultBill]),
+ );
+ };
+
+ return (
+
+
+
+ );
+}
+
+export default compose(
+ withBillActions,
+ withDashboardActions,
+ withMediaActions,
+)(BillForm);
diff --git a/client/src/containers/Purchases/BillFormFooter.js b/client/src/containers/Purchases/BillFormFooter.js
new file mode 100644
index 000000000..badfa25d3
--- /dev/null
+++ b/client/src/containers/Purchases/BillFormFooter.js
@@ -0,0 +1,41 @@
+import React from 'react';
+import { Intent, Button } from '@blueprintjs/core';
+import { FormattedMessage as T } from 'react-intl';
+
+export default function BillFormFooter({
+ formik: { isSubmitting },
+ onSubmitClick,
+ onCancelClick,
+}) {
+ return (
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/client/src/containers/Purchases/BillFormHeader.js b/client/src/containers/Purchases/BillFormHeader.js
new file mode 100644
index 000000000..27b356217
--- /dev/null
+++ b/client/src/containers/Purchases/BillFormHeader.js
@@ -0,0 +1,185 @@
+import React, { useMemo, useCallback, useState } from 'react';
+import {
+ FormGroup,
+ InputGroup,
+ Intent,
+ Position,
+ MenuItem,
+ Classes,
+} from '@blueprintjs/core';
+import { DateInput } from '@blueprintjs/datetime';
+import { FormattedMessage as T } from 'react-intl';
+import { Row, Col } from 'react-grid-system';
+import moment from 'moment';
+import { momentFormatter, compose, tansformDateValue } from 'utils';
+import classNames from 'classnames';
+import {
+ AccountsSelectList,
+ ListSelect,
+ ErrorMessage,
+ FieldRequiredHint,
+ Hint,
+} from 'components';
+
+import withCustomers from 'containers/Customers/withCustomers';
+import withAccounts from 'containers/Accounts/withAccounts';
+
+function BillFormHeader({
+ formik: { errors, touched, setFieldValue, getFieldProps, values },
+
+ //#withCustomers
+ customers,
+ //#withAccouts
+ accountsList,
+}) {
+ const handleDateChange = useCallback(
+ (date_filed) => (date) => {
+ const formatted = moment(date).format('YYYY-MM-DD');
+ setFieldValue(date_filed, formatted);
+ },
+ [setFieldValue],
+ );
+
+ const onChangeSelected = useCallback(
+ (filedName) => {
+ return (item) => {
+ setFieldValue(filedName, item.id);
+ };
+ },
+ [setFieldValue],
+ );
+
+ const vendorNameRenderer = useCallback(
+ (accept, { handleClick }) => (
+
+ ),
+ [],
+ );
+
+ // Filter vendor name
+ const filterVendorAccount = (query, vendor, _index, exactMatch) => {
+ const normalizedTitle = vendor.display_name.toLowerCase();
+ const normalizedQuery = query.toLowerCase();
+ if (exactMatch) {
+ return normalizedTitle === normalizedQuery;
+ } else {
+ return (
+ `${vendor.display_name} ${normalizedTitle}`.indexOf(normalizedQuery) >=
+ 0
+ );
+ }
+ };
+
+ return (
+
+
+ {/* vendor account name */}
+ }
+ inline={true}
+ className={classNames('form-group--select-list', Classes.FILL)}
+ labelInfo={}
+ intent={errors.vendor_id && touched.vendor_id && Intent.DANGER}
+ helperText={
+
+ }
+ >
+ }
+ itemRenderer={vendorNameRenderer}
+ itemPredicate={filterVendorAccount}
+ popoverProps={{ minimal: true }}
+ onItemSelect={onChangeSelected('vendor_id')}
+ selectedItem={values.vendor_id}
+ selectedItemProp={'id'}
+ defaultText={}
+ labelProp={'display_name'}
+ />
+
+
+
+ }
+ inline={true}
+ labelInfo={}
+ className={classNames('form-group--select-list', Classes.FILL)}
+ intent={errors.bill_date && touched.bill_date && Intent.DANGER}
+ helperText={
+
+ }
+ >
+
+
+
+
+ }
+ inline={true}
+ className={classNames('form-group--select-list', Classes.FILL)}
+ intent={errors.due_date && touched.due_date && Intent.DANGER}
+ helperText={
+
+ }
+ >
+
+
+
+
+ {/* bill number */}
+ }
+ inline={true}
+ className={('form-group--estimate', Classes.FILL)}
+ labelInfo={}
+ intent={errors.bill_number && touched.bill_number && Intent.DANGER}
+ helperText={
+
+ }
+ >
+
+
+
+
}
+ inline={true}
+ className={classNames('form-group--reference', Classes.FILL)}
+ intent={errors.reference_no && touched.reference_no && Intent.DANGER}
+ helperText={
}
+ >
+
+
+
+ );
+}
+
+export default compose(
+ withCustomers(({ customers }) => ({
+ customers,
+ })),
+ withAccounts(({ accountsList }) => ({
+ accountsList,
+ })),
+)(BillFormHeader);
diff --git a/client/src/containers/Purchases/Bills.js b/client/src/containers/Purchases/Bills.js
new file mode 100644
index 000000000..24555328c
--- /dev/null
+++ b/client/src/containers/Purchases/Bills.js
@@ -0,0 +1,62 @@
+import React, { useCallback } from 'react';
+import { useParams, useHistory } from 'react-router-dom';
+import { useQuery } from 'react-query';
+
+import BillForm from './BillForm';
+import DashboardInsider from 'components/Dashboard/DashboardInsider';
+
+import withCustomersActions from 'containers/Customers/withCustomersActions';
+import withAccountsActions from 'containers/Accounts/withAccountsActions';
+import withItemsActions from 'containers/Items/withItemsActions';
+
+import { compose } from 'utils';
+
+function Bills({
+ //#withwithAccountsActions
+ requestFetchAccounts,
+
+ //#withCustomersActions
+ requestFetchCustomers,
+
+ //#withItemsActions
+ requestFetchItems,
+}) {
+ const history = useHistory();
+
+ // Handle fetch accounts
+ const fetchAccounts = useQuery('accounts-list', (key) =>
+ requestFetchAccounts(),
+ );
+
+ // Handle fetch customers data table
+ const fetchCustomers = useQuery('customers-table', () =>
+ requestFetchCustomers({}),
+ );
+
+ // Handle fetch Items data table or list
+ const fetchItems = useQuery('items-table', () => requestFetchItems({}));
+
+ const handleFormSubmit = useCallback((payload) => {}, [history]);
+
+ const handleCancel = useCallback(() => {
+ history.goBack();
+ }, [history]);
+
+ return (
+
+
+
+ );
+}
+
+export default compose(
+ withCustomersActions,
+ withItemsActions,
+ withAccountsActions,
+)(Bills);
diff --git a/client/src/containers/Purchases/withBillActions.js b/client/src/containers/Purchases/withBillActions.js
new file mode 100644
index 000000000..65d982e7b
--- /dev/null
+++ b/client/src/containers/Purchases/withBillActions.js
@@ -0,0 +1,32 @@
+import { connect } from 'react-redux';
+import {
+ submitBill,
+ deleteBill,
+ editBill,
+ fetchBillsTable,
+ fetchBill,
+} from 'store/Bills/bills.actions';
+import t from 'store/types';
+
+const mapDispatchToProps = (dispatch) => ({
+ requestSubmitBill: (form) => dispatch(submitBill({ form })),
+ requestFetchBill: (id) => dispatch(fetchBill({ id })),
+ requestEditBill: (id, form) => dispatch(editBill({ id, form })),
+ requestDeleteBill: (id) => dispatch(deleteBill({ id })),
+ requestFetchBillsTable: (query = {}) =>
+ dispatch(fetchBillsTable({ query: { ...query } })),
+
+ changeBillView: (id) =>
+ dispatch({
+ type: t.BILL_SET_CURRENT_VIEW,
+ currentViewId: parseInt(id, 10),
+ }),
+
+ addBillsTableQueries: (queries) =>
+ dispatch({
+ type: t.BILLS_TABLE_QUERIES_ADD,
+ queries,
+ }),
+});
+
+export default connect(null, mapDispatchToProps);
diff --git a/client/src/containers/Sales/PaymentReceive/PaymentReceiveForm.js b/client/src/containers/Sales/PaymentReceive/PaymentReceiveForm.js
new file mode 100644
index 000000000..c96998400
--- /dev/null
+++ b/client/src/containers/Sales/PaymentReceive/PaymentReceiveForm.js
@@ -0,0 +1,260 @@
+import React, { useMemo, useCallback, useEffect, useState,useRef } from 'react';
+
+import * as Yup from 'yup';
+import { useFormik } from 'formik';
+import moment from 'moment';
+import { Intent, FormGroup, TextArea } from '@blueprintjs/core';
+
+import { FormattedMessage as T, useIntl } from 'react-intl';
+
+import PaymentReceiveHeader from './PaymentReceiveFormHeader';
+// PaymentReceiptItemsTable
+import PaymentReceiveFooter from './PaymentReceiveFormFooter';
+
+import withDashboardActions from 'containers/Dashboard/withDashboardActions';
+import withMediaActions from 'containers/Media/withMediaActions';
+import withPaymentReceivesActions from './withPaymentReceivesActions'
+
+import { AppToaster } from 'components';
+import Dragzone from 'components/Dragzone';
+import useMedia from 'hooks/useMedia';
+
+import { compose, repeatValue } from 'utils';
+
+const MIN_LINES_NUMBER = 4;
+
+function PaymentReceiveForm({
+ //#withMedia
+ requestSubmitMedia,
+ requestDeleteMedia,
+
+ //#WithPaymentReceiveActions
+ requestSubmitPaymentReceive,
+
+
+ //#withDashboard
+ changePageTitle,
+ changePageSubtitle,
+
+ //#withPaymentReceiveDetail
+
+ //#OWn Props
+ payment_receive,
+ onFormSubmit,
+ onCancelForm,
+}) {
+ const { formatMessage } = useIntl();
+ const [payload, setPayload] = useState({});
+
+ const {
+ setFiles,
+ saveMedia,
+ deletedFiles,
+ setDeletedFiles,
+ deleteMedia,
+ } = useMedia({
+ saveCallback: requestSubmitMedia,
+ deleteCallback: requestDeleteMedia,
+ });
+
+ const savedMediaIds = useRef([]);
+ const clearSavedMediaIds = () => {
+ savedMediaIds.current = [];
+ };
+
+ useEffect(() => {
+ if (payment_receive && payment_receive.id) {
+ changePageTitle(formatMessage({ id: 'edit_payment_receive' }));
+ } else {
+ changePageTitle(formatMessage({ id: 'new_payment_receive' }));
+ }
+ }, [changePageTitle, payment_receive, formatMessage]);
+
+ const validationSchema = Yup.object().shape({
+ customer_id: Yup.string()
+ .label(formatMessage({ id: 'customer_name_' }))
+ .required(),
+ deposit_account_id: Yup.number()
+ .required()
+ .label(formatMessage({ id: 'deposit_account_' })),
+ payment_date: Yup.date()
+ .required()
+ .label(formatMessage({ id: 'payment_date_' })),
+ payment_receive_no: Yup.number()
+ .required()
+ .label(formatMessage({ id: 'payment_receive_no_' })),
+ reference_no: Yup.string().min(1).max(255),
+ statement: Yup.string()
+ .trim()
+ .min(1)
+ .max(1024)
+ .label(formatMessage({ id: 'statement' })),
+
+ entries: Yup.array().of(
+ Yup.object().shape({
+ payment_amount: Yup.number().nullable(),
+ item_id: Yup.number()
+ .nullable()
+ .when(['payment_amount'], {
+ is: (payment_amount) => payment_amount,
+ then: Yup.number().required(),
+ }),
+ description: Yup.string().nullable(),
+ }),
+ ),
+ });
+
+ const handleDropFiles = useCallback((_files) => {
+ setFiles(_files.filter((file) => file.uploaded === false));
+ }, []);
+
+ const savePaymentReceiveSubmit = useCallback((payload) => {
+ onFormSubmit && onFormSubmit(payload);
+ });
+
+ const defaultPaymentReceive = useMemo(
+ () => ({
+ item_id: null,
+ payment_amount: null,
+ description: null,
+ }),
+ [],
+ );
+ const defaultInitialValues = useMemo(
+ () => ({
+ customer_id: '',
+ deposit_account_id: '',
+ payment_date: moment(new Date()).format('YYYY-MM-DD'),
+ reference_no: '',
+ statement: '',
+ entries: [...repeatValue(defaultPaymentReceive, MIN_LINES_NUMBER)],
+ }),
+ [defaultPaymentReceive],
+ );
+
+ const initialValues = useMemo(
+ () => ({
+ ...defaultInitialValues,
+ entries: defaultInitialValues.entries,
+ }),
+ [defaultPaymentReceive, defaultInitialValues, payment_receive],
+ );
+
+ const initialAttachmentFiles = useMemo(() => {
+ return payment_receive && payment_receive.media
+ ? payment_receive.media.map((attach) => ({
+ preview: attach.attachment_file,
+ uploaded: true,
+ metadata: { ...attach },
+ }))
+ : [];
+ }, [payment_receive]);
+
+ const formik = useFormik({
+ enableReinitialize: true,
+ validationSchema,
+ initialValues: {
+ ...initialValues,
+ },
+ onSubmit: async (values, { setSubmitting, setErrors, resetForm }) => {
+ const form = {
+ ...values,
+ };
+ const savePaymentReceive = (mediaIds) =>
+ new Promise((resolve, reject) => {
+ const requestForm = { ...form, media_ids: mediaIds };
+
+ requestSubmitPaymentReceive(requestForm)
+ .the((response) => {
+ AppToaster.show({
+ message: formatMessage({
+ id: 'the_payment_receive_has_been_successfully_created',
+ }),
+ intent: Intent.SUCCESS,
+ });
+ setSubmitting(false);
+ clearSavedMediaIds();
+ savePaymentReceiveSubmit({ action: 'new', ...payload });
+ })
+ .catch((errors) => {
+ setSubmitting(false);
+ });
+ });
+ Promise.all([saveMedia(), deleteMedia()])
+ .then(([savedMediaResponses]) => {
+ const mediaIds = savedMediaResponses.map((res) => res.data.media.id);
+ savedMediaIds.current = mediaIds;
+ return savedMediaResponses;
+ })
+ .then(() => {
+ return savePaymentReceive(savedMediaIds.current);
+ });
+ },
+ });
+
+ const handleDeleteFile = useCallback(
+ (_deletedFiles) => {
+ _deletedFiles.forEach((deletedFile) => {
+ if (deletedFile.upload && deletedFile.metadata.id) {
+ setDeletedFiles([...deletedFiles, deletedFile.metadata.id]);
+ }
+ });
+ },
+ [setDeletedFiles, deletedFiles],
+ );
+
+ const handleSubmitClick = useCallback(
+ (payload) => {
+ setPayload(payload);
+ formik.submitForm();
+ },
+ [setPayload, formik],
+ );
+
+ const handleCancelClick = useCallback(
+ (payload) => {
+ onCancelForm && onCancelForm(payload);
+ },
+ [onCancelForm],
+ );
+
+ const handleClearClick = () => {
+ formik.resetForm();
+ };
+
+ return (
+
+
+
+ );
+}
+
+export default compose(
+ withPaymentReceivesActions,
+ withDashboardActions,
+ withMediaActions,
+)(PaymentReceiveForm);
diff --git a/client/src/containers/Sales/PaymentReceive/PaymentReceiveFormFooter.js b/client/src/containers/Sales/PaymentReceive/PaymentReceiveFormFooter.js
new file mode 100644
index 000000000..793b43068
--- /dev/null
+++ b/client/src/containers/Sales/PaymentReceive/PaymentReceiveFormFooter.js
@@ -0,0 +1,46 @@
+import React from 'react';
+import { Intent, Button } from '@blueprintjs/core';
+import { FormattedMessage as T } from 'react-intl';
+
+export default function PaymentReceiveFormFooter({
+ formik: { isSubmitting, resetForm },
+ onSubmitClick,
+ onCancelClick,
+ onClearClick,
+}) {
+ return (
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/client/src/containers/Sales/PaymentReceive/PaymentReceiveFormHeader.js b/client/src/containers/Sales/PaymentReceive/PaymentReceiveFormHeader.js
new file mode 100644
index 000000000..fdda71e9a
--- /dev/null
+++ b/client/src/containers/Sales/PaymentReceive/PaymentReceiveFormHeader.js
@@ -0,0 +1,204 @@
+import React, { useMemo, useCallback, useState } from 'react';
+import {
+ FormGroup,
+ InputGroup,
+ Intent,
+ Position,
+ MenuItem,
+ Classes,
+} from '@blueprintjs/core';
+
+import { DateInput } from '@blueprintjs/datetime';
+import { FormattedMessage as T } from 'react-intl';
+import moment from 'moment';
+import { momentFormatter, compose, tansformDateValue } from 'utils';
+import classNames from 'classnames';
+import {
+ AccountsSelectList,
+ ListSelect,
+ ErrorMessage,
+ FieldRequiredHint,
+} from 'components';
+
+import withCustomers from 'containers/Customers/withCustomers';
+import withAccounts from 'containers/Accounts/withAccounts';
+
+function PaymentReceiveFormHeader({
+ formik: { errors, touched, setFieldValue, getFieldProps, values },
+
+ //#withCustomers
+ customers,
+ //#withAccouts
+ accountsList,
+}) {
+ const handleDateChange = useCallback(
+ (date_filed) => (date) => {
+ const formatted = moment(date).format('YYYY-MM-DD');
+ setFieldValue(date_filed, formatted);
+ },
+ [setFieldValue],
+ );
+
+ const handleCusomterRenderer = useCallback(
+ (custom, { handleClick }) => (
+
+ ),
+ [],
+ );
+
+ const handleFilterCustomer = (query, customer, index, exactMatch) => {
+ const normalizedTitle = customer.display_name.toLowerCase();
+ const normalizedQuery = query.toLowerCase();
+ if (exactMatch) {
+ return normalizedTitle === normalizedQuery;
+ } else {
+ return (
+ `${customer.display_name} ${normalizedTitle}`.indexOf(
+ normalizedQuery,
+ ) >= 0
+ );
+ }
+ };
+
+ const onChangeSelect = useCallback(
+ (filedName) => {
+ return (item) => {
+ setFieldValue(filedName, item.id);
+ };
+ },
+ [setFieldValue],
+ );
+
+ // Filter deposit accounts.
+ const depositAccounts = useMemo(
+ () => accountsList.filter((a) => a?.type?.key === 'current_asset'),
+ [accountsList],
+ );
+
+ return (
+
+
+ {/* Customer name */}
+
}
+ inline={true}
+ className={classNames('form-group--select-list', Classes.FILL)}
+ labelInfo={
}
+ intent={errors.customer_id && touched.customer_id && Intent.DANGER}
+ helperText={
+
+ }
+ >
+
}
+ itemRenderer={handleCusomterRenderer}
+ itemPredicate={handleFilterCustomer}
+ popoverProps={{ minimal: true }}
+ onItemSelect={onChangeSelect('customer_id')}
+ selectedItem={values.customer_id}
+ selectedItemProp={'id'}
+ defaultText={
}
+ labelProp={'display_name'}
+ />
+
+
}
+ className={classNames(
+ 'form-group--deposit_account_id',
+ 'form-group--select-list',
+ Classes.FILL,
+ )}
+ inline={true}
+ labelInfo={
}
+ intent={
+ errors.deposit_account_id &&
+ touched.deposit_account_id &&
+ Intent.DANGER
+ }
+ helperText={
+
+ }
+ >
+
}
+ selectedAccountId={values.deposit_account_id}
+ />
+
+
}
+ inline={true}
+ className={classNames('form-group--select-list', Classes.FILL)}
+ intent={errors.payment_date && touched.payment_date && Intent.DANGER}
+ helperText={
+
+ }
+ >
+
+
+
+ {/* payment receive no */}
+
}
+ inline={true}
+ className={('form-group--payment_receive_no', Classes.FILL)}
+ labelInfo={
}
+ intent={
+ errors.payment_receive_no &&
+ touched.payment_receive_no &&
+ Intent.DANGER
+ }
+ helperText={
+
+ }
+ >
+
+
+ {/* reference_no */}
+
}
+ inline={true}
+ className={classNames('form-group--reference', Classes.FILL)}
+ intent={errors.reference_no && touched.reference_no && Intent.DANGER}
+ helperText={
}
+ >
+
+
+
+ );
+}
+
+export default compose(
+ withCustomers(({ customers }) => ({
+ customers,
+ })),
+ withAccounts(({ accountsList }) => ({
+ accountsList,
+ })),
+)(PaymentReceiveFormHeader);
diff --git a/client/src/containers/Sales/PaymentReceive/PaymentReceiveItemsTable.js b/client/src/containers/Sales/PaymentReceive/PaymentReceiveItemsTable.js
new file mode 100644
index 000000000..777cecb48
--- /dev/null
+++ b/client/src/containers/Sales/PaymentReceive/PaymentReceiveItemsTable.js
@@ -0,0 +1,13 @@
+import React, { useState, useMemo, useEffect, useCallback } from 'react';
+import { Button, Intent, Position, Tooltip } from '@blueprintjs/core';
+import { FormattedMessage as T, useIntl } from 'react-intl';
+import DataTable from 'components/DataTable';
+import Icon from 'components/Icon';
+
+import { compose, formattedAmount, transformUpdatedRows } from 'utils';
+import {
+ InputGroupCell,
+ MoneyFieldCell,
+ EstimatesListFieldCell,
+ DivFieldCell,
+} from 'components/DataTableCells';
diff --git a/client/src/containers/Sales/PaymentReceive/PaymentReceives.js b/client/src/containers/Sales/PaymentReceive/PaymentReceives.js
new file mode 100644
index 000000000..48779ea57
--- /dev/null
+++ b/client/src/containers/Sales/PaymentReceive/PaymentReceives.js
@@ -0,0 +1,69 @@
+import React, { useCallback } from 'react';
+import { useParams, useHistory } from 'react-router-dom';
+import { useQuery } from 'react-query';
+
+import PaymentReceiveForm from './PaymentReceiveForm';
+import DashboardInsider from 'components/Dashboard/DashboardInsider';
+
+import withCustomersActions from 'containers/Customers/withCustomersActions';
+import withAccountsActions from 'containers/Accounts/withAccountsActions';
+import withItemsActions from 'containers/Items/withItemsActions';
+//#withInvoiceActions
+
+import { compose } from 'utils';
+
+function PaymentReceives({
+ //#withwithAccountsActions
+ requestFetchAccounts,
+
+ //#withCustomersActions
+ requestFetchCustomers,
+
+ //#withItemsActions
+ requestFetchItems,
+
+ //#withInvoiceActions
+}) {
+ const history = useHistory();
+
+ // Handle fetch accounts data
+ const fetchAccounts = useQuery('accounts-list', (key) =>
+ requestFetchAccounts(),
+ );
+
+ // Handle fetch Items data table or list
+ const fetchItems = useQuery('items-table', () => requestFetchItems({}));
+
+ // Handle fetch customers data table or list
+ const fetchCustomers = useQuery('customers-table', () =>
+ requestFetchCustomers({}),
+ );
+
+ const handleFormSubmit = useCallback((payload) => {}, [history]);
+
+ const handleCancel = useCallback(() => {
+ history.goBack();
+ }, [history]);
+
+ return (
+
+
+
+ );
+}
+
+export default compose(
+ withCustomersActions,
+ withItemsActions,
+ withAccountsActions,
+ // withInvoiceActions
+)(PaymentReceives);
diff --git a/client/src/containers/Sales/PaymentReceive/withPaymentReceivesActions.js b/client/src/containers/Sales/PaymentReceive/withPaymentReceivesActions.js
new file mode 100644
index 000000000..393fdfc86
--- /dev/null
+++ b/client/src/containers/Sales/PaymentReceive/withPaymentReceivesActions.js
@@ -0,0 +1,34 @@
+import { connect } from 'react-redux';
+import {
+ submitPaymentReceive,
+ editPaymentReceive,
+ deletePaymentReceive,
+ fetchPaymentReceive,
+ fetchPaymentReceivesTable,
+} from 'store/PaymentReceive/paymentReceive.actions';
+import t from 'store/types';
+
+const mapDispatchToProps = (dispatch) => ({
+ requestSubmitPaymentReceive: (form) =>
+ dispatch(submitPaymentReceive({ form })),
+ requestFetchPaymentReceive: (id) => dispatch(fetchPaymentReceive({ id })),
+ requestEditPaymentReceive: (id, form) =>
+ dispatch(editPaymentReceive({ id, form })),
+ requestDeletePaymentReceive: (id) => dispatch(deletePaymentReceive({ id })),
+ requestFetchPaymentReceiveTable: (query = {}) =>
+ dispatch(fetchPaymentReceivesTable({ query: { ...query } })),
+
+ changePaymentReceiveView: (id) =>
+ dispatch({
+ type: t.PAYMENT_RECEIVE_SET_CURRENT_VIEW,
+ currentViewId: parseInt(id, 10),
+ }),
+
+ addPaymentReceivesTableQueries: (queries) =>
+ dispatch({
+ type: t.PAYMENT_RECEIVE_TABLE_QUERIES_ADD,
+ queries,
+ }),
+});
+
+export default connect(null, mapDispatchToProps);
diff --git a/client/src/lang/en/index.js b/client/src/lang/en/index.js
index 57590e1ee..a6d645bd6 100644
--- a/client/src/lang/en/index.js
+++ b/client/src/lang/en/index.js
@@ -633,4 +633,33 @@ export default {
'The receipt has been successfully edited.',
the_receipt_has_been_successfully_deleted:
'The receipt has been successfully deleted.',
+
+ bills: 'Bills',
+ accept: 'Accept',
+ vendor_name: 'Vendor Name',
+ select_vendor_account: 'Select Vendor Account',
+ select_accept_account: 'Select Accept Account',
+ bill_date: 'Bill Date',
+ due_date: 'Due Date',
+ bill_number: 'Bill Number',
+ edit_bill: 'Edit Bill',
+ new_bill: 'New Bill',
+ bill_date_: 'Bill date',
+ bill_number_: 'Bill number',
+ vendor_name_: 'Vendor name',
+
+ the_bill_has_been_successfully_created:
+ 'The bill has been successfully created.',
+
+ edit_payment_receive: 'Edit Payment Receive',
+ new_payment_receive: 'New Payment Receive',
+ payment_receives: 'Payment Receives',
+ payment_receive_no: 'Payment Receive #',
+ payment_receive_no_: 'Payment receive no',
+ the_payment_receive_has_been_successfully_created:
+ 'The payment receive has been successfully created.',
+
+ select_invoice:'Select Invoice',
+
+ payment_mades: 'Payment Mades',
};
diff --git a/client/src/routes/dashboard.js b/client/src/routes/dashboard.js
index d5b73c84a..c1f10a9bd 100644
--- a/client/src/routes/dashboard.js
+++ b/client/src/routes/dashboard.js
@@ -275,4 +275,42 @@ export default [
// }),
// breadcrumb: 'New Receipt',
// }
+
+
+ // Payment Receives
+
+ {
+ path: `/payment-receive/:id/edit`,
+ component: LazyLoader({
+ loader: () => import('containers/Sales/PaymentReceive/PaymentReceives'),
+ }),
+ breadcrumb: 'Edit',
+
+ },
+ {
+ path: `/payment-receive/new`,
+ component: LazyLoader({
+ loader: () => import('containers/Sales/PaymentReceive/PaymentReceives'),
+ }),
+ breadcrumb: 'New Payment Receive',
+
+ },
+
+
+
+ //Bills
+ {
+ path: `/bill/:id/edit`,
+ component: LazyLoader({
+ loader: () => import('containers/Purchases/Bills'),
+ }),
+ breadcrumb: 'Edit',
+ },
+ {
+ path: `/bill/new`,
+ component: LazyLoader({
+ loader: () => import('containers/Purchases/Bills'),
+ }),
+ breadcrumb: 'New Bill',
+ },
];
diff --git a/client/src/store/Bills/bills.actions.js b/client/src/store/Bills/bills.actions.js
new file mode 100644
index 000000000..970bca31c
--- /dev/null
+++ b/client/src/store/Bills/bills.actions.js
@@ -0,0 +1,136 @@
+import ApiService from 'services/ApiService';
+import t from 'store/types';
+
+export const fetchBillsTable = ({ query = {} }) => {
+ return (dispatch, getState) =>
+ new Promise((resolve, rejcet) => {
+ const pageQuery = getState().bill.tableQuery;
+
+ dispatch({
+ type: t.BILLS_TABLE_LOADING,
+ payload: {
+ loading: true,
+ },
+ });
+ ApiService.get('bills', {
+ params: { ...pageQuery, ...query },
+ })
+ .then((response) => {
+ dispatch({
+ type: t.BILLS_PAGE_SET,
+ payload: {
+ bills: response.data.bills.results,
+ pagination: response.data.bills.pagination,
+ customViewId: response.data.customViewId || -1,
+ },
+ });
+ dispatch({
+ type: t.BILLS_ITEMS_SET,
+ payload: {
+ bills: response.data.bills.results,
+ },
+ });
+ dispatch({
+ type: t.BILLS_PAGINATION_SET,
+ payload: {
+ pagination: response.data.bills.pagination,
+ customViewId: response.data.customViewId || -1,
+ },
+ });
+ dispatch({
+ type: t.BILLS_TABLE_LOADING,
+ payload: {
+ loading: false,
+ },
+ });
+ resolve(response);
+ })
+ .catch((error) => {
+ rejcet(error);
+ });
+ });
+};
+
+export const deleteBill = ({ id }) => {
+ return (dispatch) =>
+ new Promise((resovle, reject) => {
+ ApiService.delete(`bills/${id}`)
+ .then((response) => {
+ dispatch({ type: t.BILL_DELETE });
+ resovle(response);
+ })
+ .catch((error) => {
+ reject(error.response.data.errors || []);
+ });
+ });
+};
+
+export const submitBill = ({ form }) => {
+ return (dispatch) =>
+ new Promise((resolve, reject) => {
+ dispatch({
+ type: t.SET_DASHBOARD_REQUEST_LOADING,
+ });
+ ApiService.post('bills', form)
+ .then((response) => {
+ dispatch({
+ type: t.SET_DASHBOARD_REQUEST_COMPLETED,
+ });
+ resolve(response);
+ })
+ .catch((error) => {
+ const { response } = error;
+ const { data } = response;
+ dispatch({
+ type: t.SET_DASHBOARD_REQUEST_COMPLETED,
+ });
+ reject(data?.errors);
+ });
+ });
+};
+
+export const fetchBill = ({ id }) => {
+ return (dispatch) =>
+ new Promise((resovle, reject) => {
+ ApiService.get(`bills/${id}`)
+ .then((response) => {
+ dispatch({
+ type: t.BILL_SET,
+ payload: {
+ id,
+ bill: response.data.bill,
+ },
+ });
+ resovle(response);
+ })
+ .catch((error) => {
+ const { response } = error;
+ const { data } = response;
+ reject(data?.errors);
+ });
+ });
+};
+
+export const editBill = (id, form) => {
+ return (dispatch) =>
+ new Promise((resolve, rejcet) => {
+ dispatch({
+ type: t.SET_DASHBOARD_REQUEST_LOADING,
+ });
+ ApiService.post(`bills/${id}`, form)
+ .then((response) => {
+ dispatch({
+ type: t.SET_DASHBOARD_REQUEST_COMPLETED,
+ });
+ resolve(response);
+ })
+ .catch((error) => {
+ const { response } = error;
+ const { data } = response;
+ dispatch({
+ type: t.SET_DASHBOARD_REQUEST_COMPLETED,
+ });
+ rejcet(data?.errors);
+ });
+ });
+};
diff --git a/client/src/store/Bills/bills.reducer.js b/client/src/store/Bills/bills.reducer.js
new file mode 100644
index 000000000..e69de29bb
diff --git a/client/src/store/Bills/bills.selectors.js b/client/src/store/Bills/bills.selectors.js
new file mode 100644
index 000000000..4b6b8f1d2
--- /dev/null
+++ b/client/src/store/Bills/bills.selectors.js
@@ -0,0 +1,6 @@
+import { createSelector } from '@reduxjs/toolkit';
+
+const billByIdSelector = (state, props) => state.bills.items[props.billId];
+
+export const getBillById = () =>
+ createSelector(billByIdSelector, (_bill) => _bill);
diff --git a/client/src/store/Bills/bills.type.js b/client/src/store/Bills/bills.type.js
new file mode 100644
index 000000000..3ce6797d2
--- /dev/null
+++ b/client/src/store/Bills/bills.type.js
@@ -0,0 +1,12 @@
+export default {
+ BILL_DELETE: 'BILL_DELETE',
+ BILLS_BULK_DELETE: 'BILLS_BULK_DELETE',
+ BILLS_LIST_SET: 'BILLS_LIST_SET',
+ BILL_SET: 'BILL_SET',
+ BILLS_SET_CURRENT_VIEW: 'BILLS_SET_CURRENT_VIEW',
+ BILLS_TABLE_QUERIES_ADD: 'BILLS_TABLE_QUERIES_ADD',
+ BILLS_TABLE_LOADING: 'BILLS_TABLE_LOADING',
+ BILLS_PAGINATION_SET: 'BILLS_PAGINATION_SET',
+ BILLS_PAGE_SET: 'BILLS_PAGE_SET',
+ BILLS_ITEMS_SET: 'BILLS_ITEMS_SET',
+};
diff --git a/client/src/store/PaymentReceive/paymentReceive.actions.js b/client/src/store/PaymentReceive/paymentReceive.actions.js
new file mode 100644
index 000000000..43d00f9cb
--- /dev/null
+++ b/client/src/store/PaymentReceive/paymentReceive.actions.js
@@ -0,0 +1,136 @@
+import ApiService from 'services/ApiService';
+import t from 'store/types';
+
+export const submitPaymentReceive = ({ form }) => {
+ return (dispatch) =>
+ new Promise((resolve, reject) => {
+ dispatch({
+ type: t.SET_DASHBOARD_REQUEST_LOADING,
+ });
+ ApiService.post('sales/payment_receives', form)
+ .then((response) => {
+ dispatch({
+ type: t.SET_DASHBOARD_REQUEST_COMPLETED,
+ });
+ resolve(response);
+ })
+ .catch((error) => {
+ const { response } = error;
+ const { data } = response;
+ dispatch({
+ type: t.SET_DASHBOARD_REQUEST_COMPLETED,
+ });
+ reject(data?.errors);
+ });
+ });
+};
+
+export const editPaymentReceive = (id, form) => {
+ return (dispatch) =>
+ new Promise((resolve, rejcet) => {
+ dispatch({
+ type: t.SET_DASHBOARD_REQUEST_LOADING,
+ });
+ ApiService.post(`sales/payment_receives/${id}`, form)
+ .then((response) => {
+ dispatch({
+ type: t.SET_DASHBOARD_REQUEST_COMPLETED,
+ });
+ resolve(response);
+ })
+ .catch((error) => {
+ const { response } = error;
+ const { data } = response;
+ dispatch({
+ type: t.SET_DASHBOARD_REQUEST_COMPLETED,
+ });
+ rejcet(data?.errors);
+ });
+ });
+};
+
+export const deletePaymentReceive = ({ id }) => {
+ return (dispatch) =>
+ new Promise((resovle, reject) => {
+ ApiService.delete(`payment_receives/${id}`)
+ .then((response) => {
+ dispatch({ type: t.PAYMENT_RECEIVE_DELETE });
+ resovle(response);
+ })
+ .catch((error) => {
+ reject(error.response.data.errors || []);
+ });
+ });
+};
+
+export const fetchPaymentReceive = ({ id }) => {
+ return (dispatch) =>
+ new Promise((resovle, reject) => {
+ ApiService.get(`payment_receives/${id}`)
+ .then((response) => {
+ dispatch({
+ type: t.PAYMENT_RECEIVE_SET,
+ payload: {
+ id,
+ payment_receive: response.data.payment_receive,
+ },
+ });
+ resovle(response);
+ })
+ .catch((error) => {
+ const { response } = error;
+ const { data } = response;
+ reject(data?.errors);
+ });
+ });
+};
+
+export const fetchPaymentReceivesTable = ({ query = {} }) => {
+ return (dispatch, getState) =>
+ new Promise((resolve, rejcet) => {
+ const pageQuery = getState().payment_receive.tableQuery;
+
+ dispatch({
+ type: t.PAYMENT_RECEIVES_TABLE_LOADING,
+ payload: {
+ loading: true,
+ },
+ });
+ ApiService.get('payment_receives', {
+ params: { ...pageQuery, ...query },
+ })
+ .then((response) => {
+ dispatch({
+ type: t.RECEIPTS_PAGE_SET,
+ payload: {
+ payment_receives: response.data.payment_receives.results,
+ pagination: response.data.payment_receives.pagination,
+ customViewId: response.data.customViewId || -1,
+ },
+ });
+ dispatch({
+ type: t.PAYMENT_RECEIVES_ITEMS_SET,
+ payload: {
+ payment_receives: response.data.payment_receives.results,
+ },
+ });
+ dispatch({
+ type: t.PAYMENT_RECEIVES_PAGINATION_SET,
+ payload: {
+ pagination: response.data.payment_receives.pagination,
+ customViewId: response.data.customViewId || -1,
+ },
+ });
+ dispatch({
+ type: t.PAYMENT_RECEIVES_TABLE_LOADING,
+ payload: {
+ loading: false,
+ },
+ });
+ resolve(response);
+ })
+ .catch((error) => {
+ rejcet(error);
+ });
+ });
+};
diff --git a/client/src/store/PaymentReceive/paymentReceive.reducer.js b/client/src/store/PaymentReceive/paymentReceive.reducer.js
new file mode 100644
index 000000000..e69de29bb
diff --git a/client/src/store/PaymentReceive/paymentReceive.selector.js b/client/src/store/PaymentReceive/paymentReceive.selector.js
new file mode 100644
index 000000000..e69de29bb
diff --git a/client/src/store/PaymentReceive/paymentReceive.type.js b/client/src/store/PaymentReceive/paymentReceive.type.js
new file mode 100644
index 000000000..3c08a544c
--- /dev/null
+++ b/client/src/store/PaymentReceive/paymentReceive.type.js
@@ -0,0 +1,11 @@
+export default {
+ PAYMENT_RECEIVE_LIST_SET: 'PAYMENT_RECEIVE_LIST_SET',
+ PAYMENT_RECEIVE_SET: 'PAYMENT_RECEIVE_SET',
+ PAYMENT_RECEIVE_DELETE: 'PAYMENT_RECEIVE_DELETE',
+ PAYMENT_RECEIVE_SET_CURRENT_VIEW: 'PAYMENT_RECEIVE_SET_CURRENT_VIEW',
+ PAYMENT_RECEIVE_TABLE_QUERIES_ADD: 'PAYMENT_RECEIVE_TABLE_QUERIES_ADD',
+ PAYMENT_RECEIVES_TABLE_LOADING: 'PAYMENT_RECEIVES_TABLE_LOADING',
+ PAYMENT_RECEIVES_PAGE_SET: 'PAYMENT_RECEIVES_PAGE_SET',
+ PAYMENT_RECEIVES_ITEMS_SET: 'PAYMENT_RECEIVES_ITEMS_SET',
+ PAYMENT_RECEIVES_PAGINATION_SET: 'PAYMENT_RECEIVES_PAGINATION_SET',
+};
diff --git a/client/src/store/types.js b/client/src/store/types.js
index 6a089d1d0..da7e60037 100644
--- a/client/src/store/types.js
+++ b/client/src/store/types.js
@@ -20,6 +20,8 @@ import customer from './customers/customers.type';
import estimates from './Estimate/estimates.types';
import invoices from './Invoice/invoices.types';
import receipts from './receipt/receipt.type';
+import bills from './Bills/bills.type';
+import paymentReceives from './PaymentReceive/paymentReceive.type';
export default {
...authentication,
@@ -43,5 +45,7 @@ export default {
...customer,
...estimates,
...invoices,
- ...receipts
+ ...receipts,
+ ...bills,
+ ...paymentReceives,
};