From 377fb07c70394ac6022e9eea5095be9c849082dd Mon Sep 17 00:00:00 2001 From: elforjani13 <39470382+elforjani13@users.noreply.github.com> Date: Mon, 15 Nov 2021 21:43:39 +0200 Subject: [PATCH 001/164] feat: bill payment transactions. --- .../Drawers/BillDrawer/BillDrawerDetails.js | 11 +- .../Drawers/BillDrawer/BillDrawerProvider.js | 19 ++- .../BillDrawer/BillPaymentTransactionTable.js | 30 ++++ src/containers/Drawers/BillDrawer/utils.js | 134 ++++++++++++------ src/hooks/query/bills.js | 15 ++ src/hooks/query/paymentMades.js | 3 + 6 files changed, 163 insertions(+), 49 deletions(-) create mode 100644 src/containers/Drawers/BillDrawer/BillPaymentTransactionTable.js diff --git a/src/containers/Drawers/BillDrawer/BillDrawerDetails.js b/src/containers/Drawers/BillDrawer/BillDrawerDetails.js index 8369fb7b8..288771b42 100644 --- a/src/containers/Drawers/BillDrawer/BillDrawerDetails.js +++ b/src/containers/Drawers/BillDrawer/BillDrawerDetails.js @@ -8,6 +8,7 @@ import { DrawerMainTabs } from 'components'; import BillDetailTab from './BillDetailTab'; import LocatedLandedCostTable from './LocatedLandedCostTable'; import JournalEntriesTable from '../../JournalEntriesTable/JournalEntriesTable'; +import BillPaymentTransactionTable from './BillPaymentTransactionTable'; import { useBillDrawerContext } from './BillDrawerProvider'; import BillDrawerCls from 'style/components/Drawers/BillDrawer.module.scss'; @@ -33,16 +34,16 @@ export default function BillDrawerDetails() { id={'journal_entries'} panel={} /> + } + /> } /> - {/* */} ); diff --git a/src/containers/Drawers/BillDrawer/BillDrawerProvider.js b/src/containers/Drawers/BillDrawer/BillDrawerProvider.js index bef541bb0..4bc138362 100644 --- a/src/containers/Drawers/BillDrawer/BillDrawerProvider.js +++ b/src/containers/Drawers/BillDrawer/BillDrawerProvider.js @@ -5,6 +5,7 @@ import { useBill, useTransactionsByReference, useBillLocatedLandedCost, + useBillPaymentTransactions, } from 'hooks/query'; const BillDrawerContext = React.createContext(); @@ -33,15 +34,31 @@ function BillDrawerProvider({ billId, ...props }) { enabled: !!billId, }); + // Handle fetch bill payment transaction. + const { + isLoading: isPaymentTransactionsLoading, + isFetching: isPaymentTransactionFetching, + data: paymentTransactions, + } = useBillPaymentTransactions(billId, { + enabled: !!billId, + }); + //provider. const provider = { transactions, billId, data, bill, + paymentTransactions, + isPaymentTransactionsLoading, + isPaymentTransactionFetching, }; - const loading = isLandedCostLoading || isTransactionLoading || isBillLoading; + const loading = + isLandedCostLoading || + isTransactionLoading || + isPaymentTransactionsLoading || + isBillLoading; return ( diff --git a/src/containers/Drawers/BillDrawer/BillPaymentTransactionTable.js b/src/containers/Drawers/BillDrawer/BillPaymentTransactionTable.js new file mode 100644 index 000000000..4165231e0 --- /dev/null +++ b/src/containers/Drawers/BillDrawer/BillPaymentTransactionTable.js @@ -0,0 +1,30 @@ +import React from 'react'; +import { DataTable, Card } from 'components'; + +import { useBillPaymentTransactionsColumns } from './utils'; +import { useBillDrawerContext } from './BillDrawerProvider'; + +/** + * Bill payment transactions datatable. + */ +export default function BillPaymentTransactionTable() { + const columns = useBillPaymentTransactionsColumns(); + + const { + paymentTransactions, + isPaymentTransactionsLoading, + isPaymentTransactionFetching, + } = useBillDrawerContext(); + + return ( + + + + ); +} diff --git a/src/containers/Drawers/BillDrawer/utils.js b/src/containers/Drawers/BillDrawer/utils.js index fea0879cd..5d075f3b7 100644 --- a/src/containers/Drawers/BillDrawer/utils.js +++ b/src/containers/Drawers/BillDrawer/utils.js @@ -1,51 +1,99 @@ import React from 'react'; import intl from 'react-intl-universal'; -import { FormatNumberCell } from '../../../components'; +import clsx from 'classnames'; +import { CLASSES } from '../../../common/classes'; +import { FormatNumberCell, FormatDateCell } from '../../../components'; /** * Retrieve bill readonly details entries table columns. */ export const useBillReadonlyEntriesTableColumns = () => -React.useMemo( - () => [ - { - Header: intl.get('product_and_service'), - accessor: 'item.name', - width: 150, - className: 'item', - disableSortBy: true - }, - { - Header: intl.get('description'), - accessor: 'description', - className: 'description', - disableSortBy: true - }, - { - Header: intl.get('quantity'), - accessor: 'quantity', - Cell: FormatNumberCell, - width: 100, - align: 'right', - disableSortBy: true - }, - { - Header: intl.get('rate'), - accessor: 'rate', - Cell: FormatNumberCell, - width: 100, - align: 'right', - disableSortBy: true - }, - { - Header: intl.get('amount'), - accessor: 'amount', - Cell: FormatNumberCell, - width: 100, - align: 'right', - disableSortBy: true - }, - ], - [], -); \ No newline at end of file + React.useMemo( + () => [ + { + Header: intl.get('product_and_service'), + accessor: 'item.name', + width: 150, + className: 'item', + disableSortBy: true, + }, + { + Header: intl.get('description'), + accessor: 'description', + className: 'description', + disableSortBy: true, + }, + { + Header: intl.get('quantity'), + accessor: 'quantity', + Cell: FormatNumberCell, + width: 100, + align: 'right', + disableSortBy: true, + }, + { + Header: intl.get('rate'), + accessor: 'rate', + Cell: FormatNumberCell, + width: 100, + align: 'right', + disableSortBy: true, + }, + { + Header: intl.get('amount'), + accessor: 'amount', + Cell: FormatNumberCell, + width: 100, + align: 'right', + disableSortBy: true, + }, + ], + [], + ); + +/** + * Retrieve bill payment transactions table columns. + */ +export const useBillPaymentTransactionsColumns = () => { + return React.useMemo( + () => [ + { + id: 'date', + Header: intl.get('payment_date'), + accessor: 'date', + Cell: FormatDateCell, + width: 110, + className: 'date', + textOverview: true, + }, + { + id: 'amount', + Header: intl.get('amount'), + accessor: 'amount', + // accessor: 'formatted_amount', + align: 'right', + width: 100, + className: clsx(CLASSES.FONT_BOLD), + textOverview: true, + }, + { + id: 'payment_number', + Header: intl.get('payment_no'), + accessor: 'payment_number', + width: 100, + className: 'payment_number', + }, + { + id: 'reference', + Header: intl.get('reference_no'), + accessor: 'reference', + width: 90, + className: 'reference', + clickable: true, + textOverview: true, + }, + ], + [], + ); +}; diff --git a/src/hooks/query/bills.js b/src/hooks/query/bills.js index d46225079..85eb70f92 100644 --- a/src/hooks/query/bills.js +++ b/src/hooks/query/bills.js @@ -178,3 +178,18 @@ export function useRefreshBills() { }, }; } + +export function useBillPaymentTransactions(id, props) { + return useRequestQuery( + [t.BILLS_PAYMENT_TRANSACTIONS, id], + { + method: 'get', + url: `purchases/bills/${id}/payment-transactions`, + }, + { + select: (res) => res.data.data, + defaultData: [], + ...props, + }, + ); +} diff --git a/src/hooks/query/paymentMades.js b/src/hooks/query/paymentMades.js index f4589b480..9cfad50d8 100644 --- a/src/hooks/query/paymentMades.js +++ b/src/hooks/query/paymentMades.js @@ -30,6 +30,9 @@ const commonInvalidateQueries = (client) => { // Invalidate the cashflow transactions. client.invalidateQueries(t.CASH_FLOW_TRANSACTIONS); client.invalidateQueries(t.CASHFLOW_ACCOUNT_TRANSACTIONS_INFINITY); + + // Invalidate bills payment transactions. + client.invalidateQueries(t.BILLS_PAYMENT_TRANSACTIONS); }; /** From bd282acae4bb0af4ebf6db70fba5d48d5c2cfae4 Mon Sep 17 00:00:00 2001 From: elforjani13 <39470382+elforjani13@users.noreply.github.com> Date: Mon, 15 Nov 2021 21:44:46 +0200 Subject: [PATCH 002/164] feat: invoice payment transactions. --- .../InvoiceDetailDrawer/InvoiceDetail.js | 7 ++- .../InvoiceDetailDrawerProvider.js | 24 +++++++- .../InvoicePaymentTransactionsTable.js | 29 ++++++++++ .../Drawers/InvoiceDetailDrawer/utils.js | 57 ++++++++++++++++++- src/hooks/query/invoices.js | 15 +++++ src/hooks/query/paymentReceives.js | 3 + src/hooks/query/types.js | 2 + src/lang/ar/index.json | 3 +- src/lang/en/index.json | 3 +- 9 files changed, 134 insertions(+), 9 deletions(-) create mode 100644 src/containers/Drawers/InvoiceDetailDrawer/InvoicePaymentTransactionsTable.js diff --git a/src/containers/Drawers/InvoiceDetailDrawer/InvoiceDetail.js b/src/containers/Drawers/InvoiceDetailDrawer/InvoiceDetail.js index 224e948a0..de075c2e4 100644 --- a/src/containers/Drawers/InvoiceDetailDrawer/InvoiceDetail.js +++ b/src/containers/Drawers/InvoiceDetailDrawer/InvoiceDetail.js @@ -6,6 +6,7 @@ import clsx from 'classnames'; import { DrawerMainTabs } from 'components'; import JournalEntriesTable from '../../JournalEntriesTable/JournalEntriesTable'; +import InvoicePaymentTransactionsTable from './InvoicePaymentTransactionsTable'; import InvoiceDetailTab from './InvoiceDetailTab'; import { useInvoiceDetailDrawerContext } from './InvoiceDetailDrawerProvider'; @@ -30,11 +31,11 @@ export default function InvoiceDetail() { id={'journal_entries'} panel={} /> - {/* */} + panel={} + /> ); diff --git a/src/containers/Drawers/InvoiceDetailDrawer/InvoiceDetailDrawerProvider.js b/src/containers/Drawers/InvoiceDetailDrawer/InvoiceDetailDrawerProvider.js index ccb64799b..9b59028a5 100644 --- a/src/containers/Drawers/InvoiceDetailDrawer/InvoiceDetailDrawerProvider.js +++ b/src/containers/Drawers/InvoiceDetailDrawer/InvoiceDetailDrawerProvider.js @@ -1,7 +1,11 @@ import React from 'react'; import intl from 'react-intl-universal'; import { DrawerHeaderContent, DrawerLoading } from 'components'; -import { useTransactionsByReference, useInvoice } from 'hooks/query'; +import { + useTransactionsByReference, + useInvoice, + useInvoicePaymentTransactions, +} from 'hooks/query'; const InvoiceDetailDrawerContext = React.createContext(); /** @@ -25,14 +29,30 @@ function InvoiceDetailDrawerProvider({ invoiceId, ...props }) { enabled: !!invoiceId, }); + // Fetch invoice payment transactions. + const { + data: paymentTransactions, + isFetching: isPaymentTransactionFetching, + isLoading: isPaymentTransactionLoading, + } = useInvoicePaymentTransactions(invoiceId, { + enabled: !!invoiceId, + }); + //provider. const provider = { transactions, + paymentTransactions, + isPaymentTransactionLoading, + isPaymentTransactionFetching, invoiceId, invoice, }; return ( - + + + + ); +} diff --git a/src/containers/Drawers/InvoiceDetailDrawer/utils.js b/src/containers/Drawers/InvoiceDetailDrawer/utils.js index 68c4cbc29..197b84ba7 100644 --- a/src/containers/Drawers/InvoiceDetailDrawer/utils.js +++ b/src/containers/Drawers/InvoiceDetailDrawer/utils.js @@ -8,8 +8,15 @@ import { MenuItem, Menu, } from '@blueprintjs/core'; -import { Icon, FormattedMessage as T, Choose } from 'components'; -import { FormatNumberCell } from '../../../components'; +import clsx from 'classnames'; +import { CLASSES } from '../../../common/classes'; +import { + Icon, + FormattedMessage as T, + Choose, + FormatDateCell, + FormatNumberCell, +} from '../../../components'; import { useInvoiceDetailDrawerContext } from './InvoiceDetailDrawerProvider'; /** @@ -99,3 +106,49 @@ export const BadDebtMenuItem = ({ ); }; + +/** + * Retrieve invoice payment transactions table columns. + */ +export const useInvoicePaymentTransactionsColumns = () => { + return React.useMemo( + () => [ + { + id: 'date', + Header: intl.get('payment_date'), + accessor: 'date', + Cell: FormatDateCell, + width: 110, + className: 'date', + textOverview: true, + }, + { + id: 'amount', + Header: intl.get('amount'), + accessor: 'amount', + // accessor: 'formatted_amount', + align: 'right', + width: 120, + className: clsx(CLASSES.FONT_BOLD), + textOverview: true, + }, + { + id: 'payment_receive_no.', + Header: intl.get('payment_no'), + accessor: 'payment_receive_no', + width: 100, + className: 'payment_receive_no', + }, + { + id: 'reference_no', + Header: intl.get('reference_no'), + accessor: 'reference_no', + width: 90, + className: 'reference_no', + clickable: true, + textOverview: true, + }, + ], + [], + ); +}; diff --git a/src/hooks/query/invoices.js b/src/hooks/query/invoices.js index aabe2fa07..9a0b5f4e3 100644 --- a/src/hooks/query/invoices.js +++ b/src/hooks/query/invoices.js @@ -269,3 +269,18 @@ export function useInvoiceSMSDetail(invoiceId, query, props) { }, ); } + +export function useInvoicePaymentTransactions(invoiceId, props) { + return useRequestQuery( + [t.SALE_INVOICE_PAYMENT_TRANSACTIONS, invoiceId], + { + method: 'get', + url: `sales/invoices/${invoiceId}/payment-transactions`, + }, + { + select: (res) => res.data.data, + defaultData: [], + ...props, + }, + ); +} diff --git a/src/hooks/query/paymentReceives.js b/src/hooks/query/paymentReceives.js index 06e7b39cb..3ff52d0f1 100644 --- a/src/hooks/query/paymentReceives.js +++ b/src/hooks/query/paymentReceives.js @@ -28,6 +28,9 @@ const commonInvalidateQueries = (client) => { // Invalidate the cashflow transactions. client.invalidateQueries(t.CASH_FLOW_TRANSACTIONS); client.invalidateQueries(t.CASHFLOW_ACCOUNT_TRANSACTIONS_INFINITY); + + // Invalidate invoices payment transactions. + client.invalidateQueries(t.SALE_INVOICE_PAYMENT_TRANSACTIONS); }; // Transform payment receives. diff --git a/src/hooks/query/types.js b/src/hooks/query/types.js index 1aebbd8e1..851d5dc91 100644 --- a/src/hooks/query/types.js +++ b/src/hooks/query/types.js @@ -30,6 +30,7 @@ const BILLS = { BILLS: 'BILLS', BILL: 'BILL', BILLS_DUE: 'BILLS_DUE', + BILLS_PAYMENT_TRANSACTIONS: 'BILLS_PAYMENT_TRANSACTIONS', }; const VENDORS = { @@ -95,6 +96,7 @@ const SALE_INVOICES = { NOTIFY_SALE_INVOICE_BY_SMS: 'NOTIFY_SALE_INVOICE_BY_SMS', BAD_DEBT: 'BAD_DEBT', CANCEL_BAD_DEBT: 'CANCEL_BAD_DEBT', + SALE_INVOICE_PAYMENT_TRANSACTIONS: 'SALE_INVOICE_PAYMENT_TRANSACTIONS', }; const USERS = { diff --git a/src/lang/ar/index.json b/src/lang/ar/index.json index 913afc98d..bcbb5a384 100644 --- a/src/lang/ar/index.json +++ b/src/lang/ar/index.json @@ -1480,5 +1480,6 @@ "sms_notification.payment_details.type": "شكر علي عملية الدفع", "sms_notification.receipt_details.type": "تفاصيل إيصال البيع", "personal": "المحمول", - "list.create":"إضافة {value}" + "list.create":"إضافة {value}", + "payment_transactions":"معاملات الدفع" } \ No newline at end of file diff --git a/src/lang/en/index.json b/src/lang/en/index.json index 3a1f34b77..5cd4fcf36 100644 --- a/src/lang/en/index.json +++ b/src/lang/en/index.json @@ -1467,5 +1467,6 @@ "sms_notification.payment_details.type": "Payment receive thank you.", "sms_notification.receipt_details.type": "Sale receipt details", "personal": "Personal", - "list.create":"Create {value}" + "list.create":"Create {value}", + "payment_transactions":"Payment transactions" } \ No newline at end of file From 0ad5a9ed0308e153286b9c35a6370628eca04287 Mon Sep 17 00:00:00 2001 From: elforjani13 <39470382+elforjani13@users.noreply.github.com> Date: Mon, 15 Nov 2021 21:45:24 +0200 Subject: [PATCH 003/164] feat: item payment transactions. --- .../ItemDetailDrawer/ItemContentDetails.js | 4 +- .../BillPaymentTransactionsDataTable.js | 78 +++++++++++++++++ .../EstimatePaymentTransactionsDataTable.js | 73 ++++++++++++++++ .../InvoicePaymentTransactionsDataTable.js | 83 +++++++++++++++++++ .../ReceiptPaymentTransactionsDataTable.js | 83 +++++++++++++++++++ .../ItemPaymentTransactions/index.js | 40 +++++++++ .../ItemPaymentTransactions/utils.js | 59 +++++++++++++ .../Drawers/ItemDetailDrawer/index.js | 7 +- src/style/components/Drawers/ItemDrawer.scss | 11 +-- 9 files changed, 431 insertions(+), 7 deletions(-) create mode 100644 src/containers/Drawers/ItemDetailDrawer/ItemPaymentTransactions/BillPaymentTransactionsDataTable.js create mode 100644 src/containers/Drawers/ItemDetailDrawer/ItemPaymentTransactions/EstimatePaymentTransactionsDataTable.js create mode 100644 src/containers/Drawers/ItemDetailDrawer/ItemPaymentTransactions/InvoicePaymentTransactionsDataTable.js create mode 100644 src/containers/Drawers/ItemDetailDrawer/ItemPaymentTransactions/ReceiptPaymentTransactionsDataTable.js create mode 100644 src/containers/Drawers/ItemDetailDrawer/ItemPaymentTransactions/index.js create mode 100644 src/containers/Drawers/ItemDetailDrawer/ItemPaymentTransactions/utils.js diff --git a/src/containers/Drawers/ItemDetailDrawer/ItemContentDetails.js b/src/containers/Drawers/ItemDetailDrawer/ItemContentDetails.js index 140e72543..108b23779 100644 --- a/src/containers/Drawers/ItemDetailDrawer/ItemContentDetails.js +++ b/src/containers/Drawers/ItemDetailDrawer/ItemContentDetails.js @@ -2,6 +2,8 @@ import React from 'react'; import ItemDetailActionsBar from './ItemDetailActionsBar'; import ItemDetailHeader from './ItemDetailHeader'; +import { ItemPaymentTransactions } from './ItemPaymentTransactions'; +import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar'; import { Card } from 'components'; @@ -12,7 +14,7 @@ export default function ItemDetail() { return (
- + diff --git a/src/containers/Drawers/ItemDetailDrawer/ItemPaymentTransactions/BillPaymentTransactionsDataTable.js b/src/containers/Drawers/ItemDetailDrawer/ItemPaymentTransactions/BillPaymentTransactionsDataTable.js new file mode 100644 index 000000000..08a9f7fea --- /dev/null +++ b/src/containers/Drawers/ItemDetailDrawer/ItemPaymentTransactions/BillPaymentTransactionsDataTable.js @@ -0,0 +1,78 @@ +import React from 'react'; +import intl from 'react-intl-universal'; +import clsx from 'classnames'; +import { CLASSES } from '../../../../common/classes'; +import { DataTable, Card, FormatDateCell } from '../../../../components'; + +/** + * Bill payment transactions data table. + */ +export default function BillPaymentTransactions() { + const columns = React.useMemo( + () => [ + { + id: 'bill_date', + Header: intl.get('date'), + accessor: 'bill_date', + Cell: FormatDateCell, + width: 110, + className: 'bill_date', + }, + { + id: 'bill_number', + Header: intl.get('bill_number'), + accessor: (row) => (row.bill_number ? `${row.bill_number}` : null), + width: 100, + className: 'bill_number', + }, + { + id: 'vendor', + Header: intl.get('vendor_name'), + accessor: 'vendor.display_name', + width: 180, + className: 'vendor', + }, + { + id: 'reference_no', + Header: intl.get('reference_no'), + accessor: 'reference_no', + width: 90, + className: 'reference_no', + }, + { + id: 'qunatity', + Header: 'Quantity Purchase', + }, + { + id: 'rate', + Header: 'Rate', + }, + { + id: 'total', + Header: intl.get('total'), + }, + { + id: 'status', + Header: intl.get('status'), + // accessor: (row) => statusAccessor(row), + width: 160, + className: 'status', + }, + ], + [], + ); + + return ( +
+ + + +
+ ); +} diff --git a/src/containers/Drawers/ItemDetailDrawer/ItemPaymentTransactions/EstimatePaymentTransactionsDataTable.js b/src/containers/Drawers/ItemDetailDrawer/ItemPaymentTransactions/EstimatePaymentTransactionsDataTable.js new file mode 100644 index 000000000..507c48249 --- /dev/null +++ b/src/containers/Drawers/ItemDetailDrawer/ItemPaymentTransactions/EstimatePaymentTransactionsDataTable.js @@ -0,0 +1,73 @@ +import React from 'react'; +import intl from 'react-intl-universal'; +import clsx from 'classnames'; +import { CLASSES } from '../../../../common/classes'; +import { DataTable, Card, FormatDateCell } from '../../../../components'; + +/** + * Esimtate payment transactions datatable. + */ +export default function EstimatePaymentTransactions() { + const columns = React.useMemo( + () => [ + { + id: 'estimate_date', + Header: intl.get('date'), + accessor: 'estimate_date', + Cell: FormatDateCell, + width: 110, + className: 'estimate_date', + textOverview: true, + }, + { + id: 'estimate_number', + Header: intl.get('estimate_no'), + accessor: 'estimate_number', + width: 100, + className: 'estimate_number', + textOverview: true, + }, + { + id: 'reference', + Header: intl.get('reference_no'), + accessor: 'reference', + width: 140, + className: 'reference', + }, + { + id: 'customer_id', + Header: intl.get('customer_name'), + accessor: 'customer.display_name', + width: 140, + className: 'customer_id', + }, + { + id: 'qunatity', + Header: 'Quantity Sold', + }, + { + id: 'rate', + Header: 'Rate', + }, + { + id: 'total', + Header: intl.get('total'), + }, + ], + [], + ); + + return ( +
+ + + +
+ ); +} diff --git a/src/containers/Drawers/ItemDetailDrawer/ItemPaymentTransactions/InvoicePaymentTransactionsDataTable.js b/src/containers/Drawers/ItemDetailDrawer/ItemPaymentTransactions/InvoicePaymentTransactionsDataTable.js new file mode 100644 index 000000000..d0bd96ec9 --- /dev/null +++ b/src/containers/Drawers/ItemDetailDrawer/ItemPaymentTransactions/InvoicePaymentTransactionsDataTable.js @@ -0,0 +1,83 @@ +import React from 'react'; +import intl from 'react-intl-universal'; +import clsx from 'classnames'; +import { CLASSES } from '../../../../common/classes'; +import { DataTable, Card, FormatDateCell } from '../../../../components'; + +/** + * Invoice payment transactions datatable. + */ +export default function InvoicePaymentTransactionsTable() { + const columns = React.useMemo( + () => [ + { + id: 'invoice_date', + Header: intl.get('date'), + accessor: 'invoice_date', + Cell: FormatDateCell, + width: 110, + className: 'invoice_date', + textOverview: true, + }, + { + id: 'invoice_no', + Header: intl.get('invoice_no__'), + accessor: 'invoice_no', + width: 100, + className: 'invoice_no', + textOverview: true, + }, + { + id: 'customer', + Header: intl.get('customer_name'), + accessor: 'customer.display_name', + width: 180, + className: 'customer_id', + clickable: true, + textOverview: true, + }, + { + id: 'reference_no', + Header: intl.get('reference_no'), + accessor: 'reference_no', + width: 90, + className: 'reference_no', + textOverview: true, + }, + { + id: 'qunatity', + Header: 'Quantity Sold', + }, + { + id: 'rate', + Header: 'Rate', + }, + { + id: 'total', + Header: intl.get('total'), + }, + { + id: 'status', + Header: intl.get('status'), + // accessor: (row) => statusAccessor(row), + width: 160, + className: 'status', + }, + ], + [], + ); + + return ( +
+ + + +
+ ); +} diff --git a/src/containers/Drawers/ItemDetailDrawer/ItemPaymentTransactions/ReceiptPaymentTransactionsDataTable.js b/src/containers/Drawers/ItemDetailDrawer/ItemPaymentTransactions/ReceiptPaymentTransactionsDataTable.js new file mode 100644 index 000000000..2566266ef --- /dev/null +++ b/src/containers/Drawers/ItemDetailDrawer/ItemPaymentTransactions/ReceiptPaymentTransactionsDataTable.js @@ -0,0 +1,83 @@ +import React from 'react'; +import intl from 'react-intl-universal'; +import clsx from 'classnames'; +import { CLASSES } from '../../../../common/classes'; +import { DataTable, Card, FormatDateCell } from '../../../../components'; + +/** + * Receipt payment transactions datatable. + */ +export default function ReceiptPaymentTransactions() { + const columns = React.useMemo( + () => [ + { + id: 'receipt_date', + Header: intl.get('date'), + accessor: 'receipt_date', + Cell: FormatDateCell, + width: 110, + className: 'receipt_date', + textOverview: true, + }, + { + id: 'receipt_number', + Header: intl.get('receipt_no'), + accessor: 'receipt_number', + width: 140, + className: 'receipt_number', + clickable: true, + textOverview: true, + }, + { + id: 'customer', + Header: intl.get('customer_name'), + accessor: 'customer.display_name', + width: 140, + className: 'customer_id', + textOverview: true, + }, + { + id: 'reference_no', + Header: intl.get('reference_no'), + accessor: 'reference_no', + width: 140, + className: 'reference_no', + textOverview: true, + }, + { + id: 'status', + Header: intl.get('status'), + // accessor: StatusAccessor, + width: 140, + className: 'status', + }, + { + id: 'qunatity', + Header: 'Quantity Sold', + }, + { + id: 'rate', + Header: 'Rate', + }, + { + id: 'total', + Header: intl.get('total'), + }, + ], + [], + ); + + return ( +
+ + + +
+ ); +} diff --git a/src/containers/Drawers/ItemDetailDrawer/ItemPaymentTransactions/index.js b/src/containers/Drawers/ItemDetailDrawer/ItemPaymentTransactions/index.js new file mode 100644 index 000000000..7c6b78828 --- /dev/null +++ b/src/containers/Drawers/ItemDetailDrawer/ItemPaymentTransactions/index.js @@ -0,0 +1,40 @@ +import React from 'react'; +import { Tab } from '@blueprintjs/core'; +import { DrawerMainTabs } from 'components'; +import InvoicePaymentTransactionsTable from './InvoicePaymentTransactionsDataTable'; +import EstimatePaymentTransactionsTable from './EstimatePaymentTransactionsDataTable'; +import ReceiptPaymentTransactionsTable from './ReceiptPaymentTransactionsDataTable'; +import BillPaymentTransactionsTable from './BillPaymentTransactionsDataTable'; + +import ItemSwitchMenuItem from './utils'; + +export const ItemPaymentTransactions = () => { + return ( + + } + /> + } + /> + } + /> + } + /> + + ); +}; + +{ + /* */ +} diff --git a/src/containers/Drawers/ItemDetailDrawer/ItemPaymentTransactions/utils.js b/src/containers/Drawers/ItemDetailDrawer/ItemPaymentTransactions/utils.js new file mode 100644 index 000000000..783e6dde0 --- /dev/null +++ b/src/containers/Drawers/ItemDetailDrawer/ItemPaymentTransactions/utils.js @@ -0,0 +1,59 @@ +import React from 'react'; +import intl from 'react-intl-universal'; +import { + Popover, + Menu, + Position, + Button, + MenuItem, + Classes, + NavbarGroup, + PopoverInteractionKind, +} from '@blueprintjs/core'; +import { Icon } from '../../../../components'; +import { curry } from 'lodash/fp'; +import { Select } from '@blueprintjs/select'; + +function ItemSwitchMenuItem({ onChange }) { + const Transaction = [ + { name: 'Invoice' }, + { name: 'Estimate' }, + { name: 'Bill' }, + { name: 'Receipt' }, + ]; + + const handleSwitchMenutItem = (item) => { + onChange && onChange(item); + }; + + const content = ( + + {Transaction.map((item) => ( + handleSwitchMenutItem(item.name)} + text={item.name} + /> + ))} + + ); + + return ( + +
+ ); +} diff --git a/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteForm.js b/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteForm.js new file mode 100644 index 000000000..503ce1000 --- /dev/null +++ b/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteForm.js @@ -0,0 +1,118 @@ +import React from 'react'; +import { useHistory } from 'react-router-dom'; +import { Formik, Form } from 'formik'; +import { Intent } from '@blueprintjs/core'; +import intl from 'react-intl-universal'; +import { sumBy, omit, isEmpty } from 'lodash'; +import classNames from 'classnames'; +import { CLASSES } from 'common/classes'; +import { + getCreateCreditNoteFormSchema, + getEditCreditNoteFormSchema, +} from './CreditNoteForm.schema'; + +import CreditNoteFormHeader from './CreditNoteFormHeader'; +import CreditNoteItemsEntriesEditorField from './CreditNoteItemsEntriesEditorField'; +import CreditNoteFormFooter from './CreditNoteFormFooter'; +import CreditNoteFloatingActions from './CreditNoteFloatingActions'; + +import { AppToaster } from 'components'; +import { compose, orderingLinesIndexes, transactionNumber } from 'utils'; +import { useCreditNoteFormContext } from './CreditNoteFormProvider'; +import { transformToEditForm, defaultCreditNote } from './utils'; + +import withSettings from 'containers/Settings/withSettings'; +import withCurrentOrganization from 'containers/Organization/withCurrentOrganization'; + +/** + * Credit note form. + */ +function CreditNoteForm({ + // #withSettings + + // #withCurrentOrganization + organization: { base_currency }, +}) { + const history = useHistory(); + + // Credit note form context. + const { invoice } = useCreditNoteFormContext(); + + // Initial values. + const initialValues = React.useMemo( + () => ({ + ...(!isEmpty(invoice) + ? { ...transformToEditForm(invoice), currency_code: base_currency } + : { + ...defaultCreditNote, + entries: orderingLinesIndexes(defaultCreditNote.entries), + currency_code: base_currency, + }), + }), + [], + ); + + // Handle form submit. + const handleSubmit = (values, { setSubmitting, setErrors, resetForm }) => { + setSubmitting(true); + + const entries = values.entries.filter( + (item) => item.item_id && item.quantity, + ); + + const totalQuantity = sumBy(entries, (entry) => parseInt(entry.quantity)); + + // Throw danger toaster in case total quantity equals zero. + if (totalQuantity === 0) { + AppToaster.show({ + message: intl.get('quantity_cannot_be_zero_or_empty'), + intent: Intent.DANGER, + }); + setSubmitting(false); + return; + } + // Transformes the values of the form to request. + const form = { + // ...transformValueToRequest(values), + }; + + // Handle the request success. + const onSuccess = () => {}; + // Handle the request error. + const onError = ({ + response: { + data: { errors }, + }, + }) => {}; + }; + + const CreateCreditNoteFormSchema = getCreateCreditNoteFormSchema(); + const EditCreditNoteFormSchema = getEditCreditNoteFormSchema(); + + return ( +
+ +
+ + + + + +
+
+ ); +} + +export default compose(withCurrentOrganization())(CreditNoteForm); diff --git a/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteForm.schema.js b/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteForm.schema.js new file mode 100644 index 000000000..69aa5ee38 --- /dev/null +++ b/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteForm.schema.js @@ -0,0 +1,51 @@ +import * as Yup from 'yup'; +import intl from 'react-intl-universal'; +import { DATATYPES_LENGTH } from 'common/dataTypes'; +import { isBlank } from 'utils'; + +const getSchema = () => Yup.object().shape({ + customer_id: Yup.string() + .label(intl.get('customer_name_')) + .required(), + invoice_date: Yup.date() + .required() + .label(intl.get('invoice_date_')), + invoice_no: Yup.string() + .max(DATATYPES_LENGTH.STRING) + .label(intl.get('invoice_no_')), + reference_no: Yup.string().min(1).max(DATATYPES_LENGTH.STRING), + delivered: Yup.boolean(), + invoice_message: Yup.string() + .trim() + .min(1) + .max(DATATYPES_LENGTH.TEXT) + .label(intl.get('note')), + terms_conditions: Yup.string() + .trim() + .min(1) + .max(DATATYPES_LENGTH.TEXT) + .label(intl.get('note')), + entries: Yup.array().of( + Yup.object().shape({ + quantity: Yup.number() + .nullable() + .max(DATATYPES_LENGTH.INT_10) + .when(['rate'], { + is: (rate) => rate, + then: Yup.number().required(), + }), + rate: Yup.number().nullable().max(DATATYPES_LENGTH.INT_10), + item_id: Yup.number() + .nullable() + .when(['quantity', 'rate'], { + is: (quantity, rate) => !isBlank(quantity) && !isBlank(rate), + then: Yup.number().required(), + }), + discount: Yup.number().nullable().min(0).max(100), + description: Yup.string().nullable().max(DATATYPES_LENGTH.TEXT), + }), + ), +}); + +export const getCreateCreditNoteFormSchema = getSchema; +export const getEditCreditNoteFormSchema = getSchema; \ No newline at end of file diff --git a/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFormFooter.js b/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFormFooter.js new file mode 100644 index 000000000..9f4b1af1b --- /dev/null +++ b/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFormFooter.js @@ -0,0 +1,51 @@ +import React from 'react'; +import { FastField } from 'formik'; +import { FormGroup, TextArea } from '@blueprintjs/core'; +import { FormattedMessage as T } from 'components'; +import { CLASSES } from 'common/classes'; +import { Row, Col, Postbox } from 'components'; +import { inputIntent } from 'utils'; +import classNames from 'classnames'; + +/** + * Credit note form footer. + */ +export default function CreditNoteFormFooter() { + return ( +
+ } + defaultOpen={false} + > + + + {/* --------- Customer notes --------- */} + + {({ field, meta: { error, touched } }) => ( + } + className={'form-group--customer_notes'} + intent={inputIntent({ error, touched })} + > +