mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-21 15:20:34 +00:00
Merge branch 'develop' of https://github.com/bigcapitalhq/client into develop
This commit is contained in:
@@ -27,6 +27,7 @@ import {
|
|||||||
PaymentMadeAction,
|
PaymentMadeAction,
|
||||||
AbilitySubject,
|
AbilitySubject,
|
||||||
} from '../../../common/abilityOption';
|
} from '../../../common/abilityOption';
|
||||||
|
import { BillMenuItem } from './utils';
|
||||||
|
|
||||||
import { safeCallback, compose } from 'utils';
|
import { safeCallback, compose } from 'utils';
|
||||||
|
|
||||||
@@ -50,6 +51,14 @@ function BillDetailActionsBar({
|
|||||||
closeDrawer('bill-drawer');
|
closeDrawer('bill-drawer');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Handle convert to vendor credit.
|
||||||
|
const handleConvertToVendorCredit = () => {
|
||||||
|
history.push(`/vendor-credits/new?from_bill_id=${billId}`, {
|
||||||
|
billId: billId,
|
||||||
|
});
|
||||||
|
closeDrawer('bill-drawer');
|
||||||
|
};
|
||||||
|
|
||||||
// Handle delete bill.
|
// Handle delete bill.
|
||||||
const onDeleteBill = () => {
|
const onDeleteBill = () => {
|
||||||
openAlert('bill-delete', { billId });
|
openAlert('bill-delete', { billId });
|
||||||
@@ -92,6 +101,14 @@ function BillDetailActionsBar({
|
|||||||
onClick={safeCallback(onDeleteBill)}
|
onClick={safeCallback(onDeleteBill)}
|
||||||
/>
|
/>
|
||||||
</Can>
|
</Can>
|
||||||
|
<Can I={BillAction.Edit} a={AbilitySubject.Bill}>
|
||||||
|
<NavbarDivider />
|
||||||
|
<BillMenuItem
|
||||||
|
payload={{
|
||||||
|
onConvert: handleConvertToVendorCredit,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Can>
|
||||||
</NavbarGroup>
|
</NavbarGroup>
|
||||||
</DrawerActionsBar>
|
</DrawerActionsBar>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,51 +1,27 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import styled from 'styled-components';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
TotalLineBorderStyle,
|
CommercialDocFooter,
|
||||||
TotalLineTextStyle,
|
|
||||||
FormatNumber,
|
|
||||||
T,
|
T,
|
||||||
TotalLines,
|
If,
|
||||||
TotalLine,
|
DetailsMenu,
|
||||||
} from '../../../components';
|
DetailItem,
|
||||||
|
} from 'components';
|
||||||
|
|
||||||
import { useBillDrawerContext } from './BillDrawerProvider';
|
import { useBillDrawerContext } from './BillDrawerProvider';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bill read-only details footer.
|
* Bill detail footer.
|
||||||
|
* @returns {React.JSX}
|
||||||
*/
|
*/
|
||||||
export function BillDetailFooter() {
|
export default function BillDetailFooter() {
|
||||||
const { bill } = useBillDrawerContext();
|
const { bill } = useBillDrawerContext();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BillDetailsFooterRoot>
|
<CommercialDocFooter>
|
||||||
<BillTotalLines labelColWidth={'180px'} amountColWidth={'180px'}>
|
<DetailsMenu direction={'horizantal'} minLabelSize={'180px'}>
|
||||||
<TotalLine
|
<If condition={bill.note}>
|
||||||
title={<T id={'bill.details.subtotal'} />}
|
<DetailItem label={<T id={'note'} />}>{bill.note}</DetailItem>
|
||||||
value={<FormatNumber value={bill.amont} />}
|
</If>
|
||||||
borderStyle={TotalLineBorderStyle.SingleDark}
|
</DetailsMenu>
|
||||||
/>
|
</CommercialDocFooter>
|
||||||
<TotalLine
|
|
||||||
title={<T id={'bill.details.total'} />}
|
|
||||||
value={bill.formatted_amount}
|
|
||||||
borderStyle={TotalLineBorderStyle.DoubleDark}
|
|
||||||
textStyle={TotalLineTextStyle.Bold}
|
|
||||||
/>
|
|
||||||
<TotalLine
|
|
||||||
title={<T id={'bill.details.payment_amount'} />}
|
|
||||||
value={bill.formatted_payment_amount}
|
|
||||||
/>
|
|
||||||
<TotalLine
|
|
||||||
title={<T id={'bill.details.due_amount'} />}
|
|
||||||
value={bill.formatted_due_amount}
|
|
||||||
/>
|
|
||||||
</BillTotalLines>
|
|
||||||
</BillDetailsFooterRoot>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const BillDetailsFooterRoot = styled.div``;
|
|
||||||
|
|
||||||
export const BillTotalLines = styled(TotalLines)`
|
|
||||||
margin-left: auto;
|
|
||||||
`;
|
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import { CommercialDocBox } from 'components';
|
|||||||
|
|
||||||
import BillDetailHeader from './BillDetailHeader';
|
import BillDetailHeader from './BillDetailHeader';
|
||||||
import BillDetailTable from './BillDetailTable';
|
import BillDetailTable from './BillDetailTable';
|
||||||
import { BillDetailFooter } from './BillDetailFooter';
|
import { BillDetailTableFooter } from './BillDetailTableFooter';
|
||||||
|
import BillDetailFooter from './BillDetailFooter';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bill detail panel tab.
|
* Bill detail panel tab.
|
||||||
@@ -15,6 +15,7 @@ export default function BillDetailTab() {
|
|||||||
<CommercialDocBox>
|
<CommercialDocBox>
|
||||||
<BillDetailHeader />
|
<BillDetailHeader />
|
||||||
<BillDetailTable />
|
<BillDetailTable />
|
||||||
|
<BillDetailTableFooter />
|
||||||
<BillDetailFooter />
|
<BillDetailFooter />
|
||||||
</CommercialDocBox>
|
</CommercialDocBox>
|
||||||
);
|
);
|
||||||
|
|||||||
51
src/containers/Drawers/BillDrawer/BillDetailTableFooter.js
Normal file
51
src/containers/Drawers/BillDrawer/BillDetailTableFooter.js
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
import {
|
||||||
|
TotalLineBorderStyle,
|
||||||
|
TotalLineTextStyle,
|
||||||
|
FormatNumber,
|
||||||
|
T,
|
||||||
|
TotalLines,
|
||||||
|
TotalLine,
|
||||||
|
} from '../../../components';
|
||||||
|
import { useBillDrawerContext } from './BillDrawerProvider';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bill read-only details table footer.
|
||||||
|
*/
|
||||||
|
export function BillDetailTableFooter() {
|
||||||
|
const { bill } = useBillDrawerContext();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<BillDetailsFooterRoot>
|
||||||
|
<BillTotalLines labelColWidth={'180px'} amountColWidth={'180px'}>
|
||||||
|
<TotalLine
|
||||||
|
title={<T id={'bill.details.subtotal'} />}
|
||||||
|
value={<FormatNumber value={bill.amont} />}
|
||||||
|
borderStyle={TotalLineBorderStyle.SingleDark}
|
||||||
|
/>
|
||||||
|
<TotalLine
|
||||||
|
title={<T id={'bill.details.total'} />}
|
||||||
|
value={bill.formatted_amount}
|
||||||
|
borderStyle={TotalLineBorderStyle.DoubleDark}
|
||||||
|
textStyle={TotalLineTextStyle.Bold}
|
||||||
|
/>
|
||||||
|
<TotalLine
|
||||||
|
title={<T id={'bill.details.payment_amount'} />}
|
||||||
|
value={bill.formatted_payment_amount}
|
||||||
|
/>
|
||||||
|
<TotalLine
|
||||||
|
title={<T id={'bill.details.due_amount'} />}
|
||||||
|
value={bill.formatted_due_amount}
|
||||||
|
/>
|
||||||
|
</BillTotalLines>
|
||||||
|
</BillDetailsFooterRoot>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const BillDetailsFooterRoot = styled.div``;
|
||||||
|
|
||||||
|
export const BillTotalLines = styled(TotalLines)`
|
||||||
|
margin-left: auto;
|
||||||
|
`;
|
||||||
@@ -1,12 +1,21 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import intl from 'react-intl-universal';
|
import intl from 'react-intl-universal';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { Intent, Tag } from '@blueprintjs/core';
|
import {
|
||||||
|
Button,
|
||||||
|
Popover,
|
||||||
|
PopoverInteractionKind,
|
||||||
|
Position,
|
||||||
|
MenuItem,
|
||||||
|
Menu,
|
||||||
|
Intent,
|
||||||
|
Tag,
|
||||||
|
} from '@blueprintjs/core';
|
||||||
import {
|
import {
|
||||||
FormatNumberCell,
|
FormatNumberCell,
|
||||||
FormattedMessage as T,
|
FormattedMessage as T,
|
||||||
Choose,
|
Choose,
|
||||||
|
Icon,
|
||||||
} from '../../../components';
|
} from '../../../components';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -73,7 +82,7 @@ export function BillDetailsStatus({ bill }) {
|
|||||||
<Choose>
|
<Choose>
|
||||||
<Choose.When condition={bill.is_overdue}>
|
<Choose.When condition={bill.is_overdue}>
|
||||||
<StatusTag intent={Intent.WARNING} round={true}>
|
<StatusTag intent={Intent.WARNING} round={true}>
|
||||||
Overdue
|
<T id={'overdue'} />
|
||||||
</StatusTag>
|
</StatusTag>
|
||||||
</Choose.When>
|
</Choose.When>
|
||||||
<Choose.Otherwise>
|
<Choose.Otherwise>
|
||||||
@@ -92,6 +101,29 @@ export function BillDetailsStatus({ bill }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const BillMenuItem = ({ payload: { onConvert } }) => {
|
||||||
|
return (
|
||||||
|
<Popover
|
||||||
|
minimal={true}
|
||||||
|
interactionKind={PopoverInteractionKind.CLICK}
|
||||||
|
position={Position.BOTTOM_LEFT}
|
||||||
|
modifiers={{
|
||||||
|
offset: { offset: '0, 4' },
|
||||||
|
}}
|
||||||
|
content={
|
||||||
|
<Menu>
|
||||||
|
<MenuItem
|
||||||
|
onClick={onConvert}
|
||||||
|
text={<T id={'convert_to_vendor_credit'} />}
|
||||||
|
/>
|
||||||
|
</Menu>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Button icon={<Icon icon="more-vert" iconSize={16} />} minimal={true} />
|
||||||
|
</Popover>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const StatusTag = styled(Tag)`
|
const StatusTag = styled(Tag)`
|
||||||
min-width: 65px;
|
min-width: 65px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
CommercialDocFooter,
|
||||||
|
T,
|
||||||
|
If,
|
||||||
|
DetailsMenu,
|
||||||
|
DetailItem,
|
||||||
|
} from 'components';
|
||||||
|
|
||||||
|
import { useCreditNoteDetailDrawerContext } from './CreditNoteDetailDrawerProvider';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Credit note detail footer
|
||||||
|
* @returns {React.JSX}
|
||||||
|
*/
|
||||||
|
export default function CreditNoteDetailFooter() {
|
||||||
|
const { creditNote } = useCreditNoteDetailDrawerContext();
|
||||||
|
return (
|
||||||
|
<CommercialDocFooter>
|
||||||
|
<DetailsMenu direction={'horizantal'} minLabelSize={'180px'}>
|
||||||
|
<If condition={creditNote.terms_conditions}>
|
||||||
|
<DetailItem label={<T id={'credit_note.drawer.terms_conditions'} />}>
|
||||||
|
{creditNote.terms_conditions}
|
||||||
|
</DetailItem>
|
||||||
|
</If>
|
||||||
|
</DetailsMenu>
|
||||||
|
</CommercialDocFooter>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -4,7 +4,8 @@ import { CommercialDocBox } from 'components';
|
|||||||
|
|
||||||
import CreditNoteDetailHeader from './CreditNoteDetailHeader';
|
import CreditNoteDetailHeader from './CreditNoteDetailHeader';
|
||||||
import CreditNoteDetailTable from './CreditNoteDetailTable';
|
import CreditNoteDetailTable from './CreditNoteDetailTable';
|
||||||
import CreditNoteDetailDrawerFooter from './CreditNoteDetailDrawerFooter';
|
import CreditNoteDetailTableFooter from './CreditNoteDetailTableFooter';
|
||||||
|
import CreditNoteDetailFooter from './CreditNoteDetailFooter';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Credit note details panel.
|
* Credit note details panel.
|
||||||
@@ -14,7 +15,8 @@ export default function CreditNoteDetailPanel() {
|
|||||||
<CommercialDocBox>
|
<CommercialDocBox>
|
||||||
<CreditNoteDetailHeader />
|
<CreditNoteDetailHeader />
|
||||||
<CreditNoteDetailTable />
|
<CreditNoteDetailTable />
|
||||||
<CreditNoteDetailDrawerFooter />
|
<CreditNoteDetailTableFooter />
|
||||||
|
<CreditNoteDetailFooter />
|
||||||
</CommercialDocBox>
|
</CommercialDocBox>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import { useCreditNoteDetailDrawerContext } from './CreditNoteDetailDrawerProvid
|
|||||||
/**
|
/**
|
||||||
* Credit note details panel footer.
|
* Credit note details panel footer.
|
||||||
*/
|
*/
|
||||||
export default function CreditNoteDetailDrawerFooter() {
|
export default function CreditNoteDetailTableFooter() {
|
||||||
const { creditNote } = useCreditNoteDetailDrawerContext();
|
const { creditNote } = useCreditNoteDetailDrawerContext();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -1,43 +1,35 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import styled from 'styled-components';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
CommercialDocFooter,
|
||||||
T,
|
T,
|
||||||
TotalLines,
|
If,
|
||||||
TotalLine,
|
DetailsMenu,
|
||||||
TotalLineBorderStyle,
|
DetailItem,
|
||||||
TotalLineTextStyle,
|
|
||||||
FormatNumber,
|
|
||||||
} from 'components';
|
} from 'components';
|
||||||
import { useEstimateDetailDrawerContext } from './EstimateDetailDrawerProvider';
|
import { useEstimateDetailDrawerContext } from './EstimateDetailDrawerProvider';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Estimate details panel footer content.
|
* Estimate details footer.
|
||||||
|
* @returns {React.JSX}
|
||||||
*/
|
*/
|
||||||
export default function EstimateDetailFooter() {
|
export default function EstimateDetailFooter() {
|
||||||
const { estimate } = useEstimateDetailDrawerContext();
|
const { estimate } = useEstimateDetailDrawerContext();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EstimateDetailsFooterRoot>
|
<CommercialDocFooter>
|
||||||
<EstimateTotalLines labelColWidth={'180px'} amountColWidth={'180px'}>
|
<DetailsMenu direction={'horizantal'} minLabelSize={'180px'}>
|
||||||
<TotalLine
|
<If condition={estimate.terms_conditions}>
|
||||||
title={<T id={'estimate.details.subtotal'} />}
|
<DetailItem label={<T id={'estimate.details.terms_conditions'} />}>
|
||||||
value={<FormatNumber value={estimate.amount} />}
|
{estimate.terms_conditions}
|
||||||
borderStyle={TotalLineBorderStyle.SingleDark}
|
</DetailItem>
|
||||||
/>
|
</If>
|
||||||
<TotalLine
|
<If condition={estimate.note}>
|
||||||
title={<T id={'estimate.details.total'} />}
|
<DetailItem label={<T id={'estimate.details.note'} />}>
|
||||||
value={estimate.formatted_amount}
|
{estimate.note}
|
||||||
borderStyle={TotalLineBorderStyle.DoubleDark}
|
</DetailItem>
|
||||||
textStyle={TotalLineTextStyle.Bold}
|
</If>
|
||||||
/>
|
</DetailsMenu>
|
||||||
</EstimateTotalLines>
|
</CommercialDocFooter>
|
||||||
</EstimateDetailsFooterRoot>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const EstimateDetailsFooterRoot = styled.div``;
|
|
||||||
|
|
||||||
export const EstimateTotalLines = styled(TotalLines)`
|
|
||||||
margin-left: auto;
|
|
||||||
`;
|
|
||||||
|
|||||||
@@ -4,13 +4,16 @@ import { CommercialDocBox } from 'components';
|
|||||||
|
|
||||||
import EstimateDetailHeader from './EstimateDetailHeader';
|
import EstimateDetailHeader from './EstimateDetailHeader';
|
||||||
import EstimateDetailTable from './EstimateDetailTable';
|
import EstimateDetailTable from './EstimateDetailTable';
|
||||||
|
import EstimateDetailTableFooter from './EstimateDetailTableFooter';
|
||||||
import EstimateDetailFooter from './EstimateDetailFooter';
|
import EstimateDetailFooter from './EstimateDetailFooter';
|
||||||
|
|
||||||
|
|
||||||
export default function EstimateDetailTab() {
|
export default function EstimateDetailTab() {
|
||||||
return (
|
return (
|
||||||
<CommercialDocBox>
|
<CommercialDocBox>
|
||||||
<EstimateDetailHeader />
|
<EstimateDetailHeader />
|
||||||
<EstimateDetailTable />
|
<EstimateDetailTable />
|
||||||
|
<EstimateDetailTableFooter />
|
||||||
<EstimateDetailFooter />
|
<EstimateDetailFooter />
|
||||||
</CommercialDocBox>
|
</CommercialDocBox>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
import {
|
||||||
|
T,
|
||||||
|
TotalLines,
|
||||||
|
TotalLine,
|
||||||
|
TotalLineBorderStyle,
|
||||||
|
TotalLineTextStyle,
|
||||||
|
FormatNumber,
|
||||||
|
} from 'components';
|
||||||
|
import { useEstimateDetailDrawerContext } from './EstimateDetailDrawerProvider';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Estimate details panel footer content.
|
||||||
|
*/
|
||||||
|
export default function EstimateDetailTableFooter() {
|
||||||
|
const { estimate } = useEstimateDetailDrawerContext();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<EstimateDetailsFooterRoot>
|
||||||
|
<EstimateTotalLines labelColWidth={'180px'} amountColWidth={'180px'}>
|
||||||
|
<TotalLine
|
||||||
|
title={<T id={'estimate.details.subtotal'} />}
|
||||||
|
value={<FormatNumber value={estimate.amount} />}
|
||||||
|
borderStyle={TotalLineBorderStyle.SingleDark}
|
||||||
|
/>
|
||||||
|
<TotalLine
|
||||||
|
title={<T id={'estimate.details.total'} />}
|
||||||
|
value={estimate.formatted_amount}
|
||||||
|
borderStyle={TotalLineBorderStyle.DoubleDark}
|
||||||
|
textStyle={TotalLineTextStyle.Bold}
|
||||||
|
/>
|
||||||
|
</EstimateTotalLines>
|
||||||
|
</EstimateDetailsFooterRoot>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const EstimateDetailsFooterRoot = styled.div``;
|
||||||
|
|
||||||
|
export const EstimateTotalLines = styled(TotalLines)`
|
||||||
|
margin-left: auto;
|
||||||
|
`;
|
||||||
@@ -5,7 +5,7 @@ export const useInventoryAdjustmentEntriesColumns = () =>
|
|||||||
React.useMemo(
|
React.useMemo(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
Header: intl.get('product_and_service'),
|
Header: intl.get('inventory_adjustment.column.product'),
|
||||||
accessor: 'item.name',
|
accessor: 'item.name',
|
||||||
width: 150,
|
width: 150,
|
||||||
className: 'name',
|
className: 'name',
|
||||||
|
|||||||
@@ -14,7 +14,13 @@ import withDialogActions from 'containers/Dialog/withDialogActions';
|
|||||||
import withAlertsActions from 'containers/Alert/withAlertActions';
|
import withAlertsActions from 'containers/Alert/withAlertActions';
|
||||||
import withDrawerActions from 'containers/Drawer/withDrawerActions';
|
import withDrawerActions from 'containers/Drawer/withDrawerActions';
|
||||||
|
|
||||||
import { If, Can, Icon, DrawerActionsBar, FormattedMessage as T } from 'components';
|
import {
|
||||||
|
If,
|
||||||
|
Can,
|
||||||
|
Icon,
|
||||||
|
DrawerActionsBar,
|
||||||
|
FormattedMessage as T,
|
||||||
|
} from 'components';
|
||||||
import {
|
import {
|
||||||
SaleInvoiceAction,
|
SaleInvoiceAction,
|
||||||
PaymentReceiveAction,
|
PaymentReceiveAction,
|
||||||
@@ -48,6 +54,14 @@ function InvoiceDetailActionsBar({
|
|||||||
closeDrawer('invoice-detail-drawer');
|
closeDrawer('invoice-detail-drawer');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Handle convert to invoice.
|
||||||
|
const handleConvertToCreitNote = () => {
|
||||||
|
history.push(`/credit-notes/new?from_invoice_id=${invoiceId}`, {
|
||||||
|
invoiceId: invoiceId,
|
||||||
|
});
|
||||||
|
closeDrawer('invoice-detail-drawer');
|
||||||
|
};
|
||||||
|
|
||||||
// Handle delete sale invoice.
|
// Handle delete sale invoice.
|
||||||
const handleDeleteInvoice = () => {
|
const handleDeleteInvoice = () => {
|
||||||
openAlert('invoice-delete', { invoiceId });
|
openAlert('invoice-delete', { invoiceId });
|
||||||
@@ -124,6 +138,7 @@ function InvoiceDetailActionsBar({
|
|||||||
onBadDebt: handleBadDebtInvoice,
|
onBadDebt: handleBadDebtInvoice,
|
||||||
onCancelBadDebt: handleCancelBadDebtInvoice,
|
onCancelBadDebt: handleCancelBadDebtInvoice,
|
||||||
onNotifyViaSMS: handleNotifyViaSMS,
|
onNotifyViaSMS: handleNotifyViaSMS,
|
||||||
|
onConvert: handleConvertToCreitNote,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Can>
|
</Can>
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ export const useInvoiceReadonlyEntriesColumns = () =>
|
|||||||
* @returns {React.JSX}
|
* @returns {React.JSX}
|
||||||
*/
|
*/
|
||||||
export const BadDebtMenuItem = ({
|
export const BadDebtMenuItem = ({
|
||||||
payload: { onCancelBadDebt, onBadDebt, onNotifyViaSMS },
|
payload: { onCancelBadDebt, onBadDebt, onNotifyViaSMS, onConvert },
|
||||||
}) => {
|
}) => {
|
||||||
const { invoice } = useInvoiceDetailDrawerContext();
|
const { invoice } = useInvoiceDetailDrawerContext();
|
||||||
|
|
||||||
@@ -104,6 +104,12 @@ export const BadDebtMenuItem = ({
|
|||||||
/>
|
/>
|
||||||
</Choose.When>
|
</Choose.When>
|
||||||
</Choose>
|
</Choose>
|
||||||
|
<Can I={SaleInvoiceAction.Edit} a={AbilitySubject.Invoice}>
|
||||||
|
<MenuItem
|
||||||
|
onClick={onConvert}
|
||||||
|
text={<T id={'convert_to_credit_note'} />}
|
||||||
|
/>
|
||||||
|
</Can>
|
||||||
<Can I={SaleInvoiceAction.NotifyBySms} a={AbilitySubject.Invoice}>
|
<Can I={SaleInvoiceAction.NotifyBySms} a={AbilitySubject.Invoice}>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
onClick={onNotifyViaSMS}
|
onClick={onNotifyViaSMS}
|
||||||
@@ -135,12 +141,12 @@ export function InvoiceDetailsStatus({ invoice }) {
|
|||||||
<Choose>
|
<Choose>
|
||||||
<Choose.When condition={invoice.is_overdue}>
|
<Choose.When condition={invoice.is_overdue}>
|
||||||
<StatusTag intent={Intent.WARNING} round={true}>
|
<StatusTag intent={Intent.WARNING} round={true}>
|
||||||
Overdue
|
<T id={'overdue'} />
|
||||||
</StatusTag>
|
</StatusTag>
|
||||||
</Choose.When>
|
</Choose.When>
|
||||||
<Choose.Otherwise>
|
<Choose.Otherwise>
|
||||||
<StatusTag intent={Intent.PRIMARY} round={true}>
|
<StatusTag intent={Intent.PRIMARY} round={true}>
|
||||||
Delivered
|
<T id={'delivered'} />
|
||||||
</StatusTag>
|
</StatusTag>
|
||||||
</Choose.Otherwise>
|
</Choose.Otherwise>
|
||||||
</Choose>
|
</Choose>
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import styled from 'styled-components';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
FormatNumber,
|
CommercialDocFooter,
|
||||||
TotalLineTextStyle,
|
|
||||||
TotalLineBorderStyle,
|
|
||||||
T,
|
T,
|
||||||
TotalLine,
|
If,
|
||||||
TotalLines,
|
DetailsMenu,
|
||||||
|
DetailItem,
|
||||||
} from 'components';
|
} from 'components';
|
||||||
import { usePaymentReceiveDetailContext } from './PaymentReceiveDetailProvider';
|
import { usePaymentReceiveDetailContext } from './PaymentReceiveDetailProvider';
|
||||||
|
|
||||||
@@ -19,28 +17,14 @@ export default function PaymentReceiveDetailFooter() {
|
|||||||
const { paymentReceive } = usePaymentReceiveDetailContext();
|
const { paymentReceive } = usePaymentReceiveDetailContext();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PaymentReceiveDetailsFooterRoot>
|
<CommercialDocFooter>
|
||||||
<PaymentReceiveTotalLines
|
<DetailsMenu direction={'horizantal'} minLabelSize={'180px'}>
|
||||||
labelColWidth={'180px'}
|
<If condition={paymentReceive.statement}>
|
||||||
amountColWidth={'180px'}
|
<DetailItem label={<T id={'payment_receive.details.statement'} />}>
|
||||||
>
|
{paymentReceive.statement}
|
||||||
<TotalLine
|
</DetailItem>
|
||||||
title={<T id={'payment_receive.details.subtotal'} />}
|
</If>
|
||||||
value={<FormatNumber value={paymentReceive.amount} />}
|
</DetailsMenu>
|
||||||
/>
|
</CommercialDocFooter>
|
||||||
<TotalLine
|
|
||||||
title={<T id={'payment_receive.details.total'} />}
|
|
||||||
value={paymentReceive.formatted_amount}
|
|
||||||
borderStyle={TotalLineBorderStyle.DoubleDark}
|
|
||||||
textStyle={TotalLineTextStyle.Bold}
|
|
||||||
/>
|
|
||||||
</PaymentReceiveTotalLines>
|
|
||||||
</PaymentReceiveDetailsFooterRoot>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PaymentReceiveDetailsFooterRoot = styled.div``;
|
|
||||||
|
|
||||||
export const PaymentReceiveTotalLines = styled(TotalLines)`
|
|
||||||
margin-left: auto;
|
|
||||||
`;
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { CommercialDocBox } from 'components';
|
|||||||
|
|
||||||
import PaymentReceiveDetailHeader from './PaymentReceiveDetailHeader';
|
import PaymentReceiveDetailHeader from './PaymentReceiveDetailHeader';
|
||||||
import PaymentReceiveDetailTable from './PaymentReceiveDetailTable';
|
import PaymentReceiveDetailTable from './PaymentReceiveDetailTable';
|
||||||
|
import PaymentReceiveDetailTableFooter from './PaymentReceiveDetailTableFooter';
|
||||||
import PaymentReceiveDetailFooter from './PaymentReceiveDetailFooter';
|
import PaymentReceiveDetailFooter from './PaymentReceiveDetailFooter';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -17,6 +18,7 @@ export default function PaymentReceiveDetailTab() {
|
|||||||
<CommercialDocBox>
|
<CommercialDocBox>
|
||||||
<PaymentReceiveDetailHeader />
|
<PaymentReceiveDetailHeader />
|
||||||
<PaymentReceiveDetailTable />
|
<PaymentReceiveDetailTable />
|
||||||
|
<PaymentReceiveDetailTableFooter />
|
||||||
<PaymentReceiveDetailFooter />
|
<PaymentReceiveDetailFooter />
|
||||||
</CommercialDocBox>
|
</CommercialDocBox>
|
||||||
</PaymentReceiveDetailsTabPanelRoot>
|
</PaymentReceiveDetailsTabPanelRoot>
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
import {
|
||||||
|
FormatNumber,
|
||||||
|
TotalLineTextStyle,
|
||||||
|
TotalLineBorderStyle,
|
||||||
|
T,
|
||||||
|
TotalLine,
|
||||||
|
TotalLines,
|
||||||
|
} from 'components';
|
||||||
|
import { usePaymentReceiveDetailContext } from './PaymentReceiveDetailProvider';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Payment receive detail table footer.
|
||||||
|
* @returns {React.JSX}
|
||||||
|
*/
|
||||||
|
export default function PaymentReceiveDetailTableFooter() {
|
||||||
|
const { paymentReceive } = usePaymentReceiveDetailContext();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PaymentReceiveDetailsFooterRoot>
|
||||||
|
<PaymentReceiveTotalLines
|
||||||
|
labelColWidth={'180px'}
|
||||||
|
amountColWidth={'180px'}
|
||||||
|
>
|
||||||
|
<TotalLine
|
||||||
|
title={<T id={'payment_receive.details.subtotal'} />}
|
||||||
|
value={<FormatNumber value={paymentReceive.amount} />}
|
||||||
|
/>
|
||||||
|
<TotalLine
|
||||||
|
title={<T id={'payment_receive.details.total'} />}
|
||||||
|
value={paymentReceive.formatted_amount}
|
||||||
|
borderStyle={TotalLineBorderStyle.DoubleDark}
|
||||||
|
textStyle={TotalLineTextStyle.Bold}
|
||||||
|
/>
|
||||||
|
</PaymentReceiveTotalLines>
|
||||||
|
</PaymentReceiveDetailsFooterRoot>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PaymentReceiveDetailsFooterRoot = styled.div``;
|
||||||
|
|
||||||
|
export const PaymentReceiveTotalLines = styled(TotalLines)`
|
||||||
|
margin-left: auto;
|
||||||
|
`;
|
||||||
@@ -1,51 +1,35 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import styled from 'styled-components';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
CommercialDocFooter,
|
||||||
T,
|
T,
|
||||||
TotalLines,
|
If,
|
||||||
TotalLine,
|
DetailsMenu,
|
||||||
TotalLineBorderStyle,
|
DetailItem,
|
||||||
TotalLineTextStyle,
|
|
||||||
FormatNumber,
|
|
||||||
} from 'components';
|
} from 'components';
|
||||||
|
|
||||||
import { useReceiptDetailDrawerContext } from './ReceiptDetailDrawerProvider';
|
import { useReceiptDetailDrawerContext } from './ReceiptDetailDrawerProvider';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Receipts read-only details footer.
|
* Receipt details footer
|
||||||
|
* @returns {React.JSX}
|
||||||
*/
|
*/
|
||||||
export function ReceiptDetailFooter() {
|
export default function ReceiptDetailFooter() {
|
||||||
const { receipt } = useReceiptDetailDrawerContext();
|
const { receipt } = useReceiptDetailDrawerContext();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ReceiptDetailsFooterRoot>
|
<CommercialDocFooter>
|
||||||
<ReceiptTotalLines labelColWidth={'180px'} amountColWidth={'180px'}>
|
<DetailsMenu direction={'horizantal'} minLabelSize={'180px'}>
|
||||||
<TotalLine
|
<If condition={receipt.statement}>
|
||||||
title={<T id={'receipt.details.subtotal'} />}
|
<DetailItem label={<T id={'receipt.details.statement'} />}>
|
||||||
value={<FormatNumber value={receipt.amount} />}
|
{receipt.statement}
|
||||||
/>
|
</DetailItem>
|
||||||
<TotalLine
|
</If>
|
||||||
title={<T id={'receipt.details.total'} />}
|
<If condition={receipt.receipt_message}>
|
||||||
value={receipt.formatted_amount}
|
<DetailItem label={<T id={'receipt.details.receipt_message'} />}>
|
||||||
borderStyle={TotalLineBorderStyle.DoubleDark}
|
{receipt.receipt_message}
|
||||||
textStyle={TotalLineTextStyle.Bold}
|
</DetailItem>
|
||||||
/>
|
</If>
|
||||||
<TotalLine
|
</DetailsMenu>
|
||||||
title={<T id={'receipt.details.payment_amount'} />}
|
</CommercialDocFooter>
|
||||||
value={receipt.formatted_amount}
|
|
||||||
borderStyle={TotalLineBorderStyle.DoubleDark}
|
|
||||||
/>
|
|
||||||
<TotalLine
|
|
||||||
title={<T id={'receipt.details.due_amount'} />}
|
|
||||||
value={'0'}
|
|
||||||
/>
|
|
||||||
</ReceiptTotalLines>
|
|
||||||
</ReceiptDetailsFooterRoot>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ReceiptDetailsFooterRoot = styled.div``;
|
|
||||||
|
|
||||||
export const ReceiptTotalLines = styled(TotalLines)`
|
|
||||||
margin-left: auto;
|
|
||||||
`;
|
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ import { CommercialDocBox } from 'components';
|
|||||||
|
|
||||||
import ReceiptDetailHeader from './ReceiptDetailHeader';
|
import ReceiptDetailHeader from './ReceiptDetailHeader';
|
||||||
import ReceiptDetailTable from './ReceiptDetailTable';
|
import ReceiptDetailTable from './ReceiptDetailTable';
|
||||||
import { ReceiptDetailFooter } from './ReceiptDetailFooter';
|
import ReceiptDetailTableFooter from './ReceiptDetailTableFooter';
|
||||||
|
import ReceiptDetailFooter from './ReceiptDetailFooter';
|
||||||
|
|
||||||
export default function ReceiptDetailTab() {
|
export default function ReceiptDetailTab() {
|
||||||
return (
|
return (
|
||||||
@@ -13,6 +14,7 @@ export default function ReceiptDetailTab() {
|
|||||||
<CommercialDocBox>
|
<CommercialDocBox>
|
||||||
<ReceiptDetailHeader />
|
<ReceiptDetailHeader />
|
||||||
<ReceiptDetailTable />
|
<ReceiptDetailTable />
|
||||||
|
<ReceiptDetailTableFooter />
|
||||||
<ReceiptDetailFooter />
|
<ReceiptDetailFooter />
|
||||||
</CommercialDocBox>
|
</CommercialDocBox>
|
||||||
</ReceiptDetailsOverviewRoot>
|
</ReceiptDetailsOverviewRoot>
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
import {
|
||||||
|
T,
|
||||||
|
TotalLines,
|
||||||
|
TotalLine,
|
||||||
|
TotalLineBorderStyle,
|
||||||
|
TotalLineTextStyle,
|
||||||
|
FormatNumber,
|
||||||
|
} from 'components';
|
||||||
|
import { useReceiptDetailDrawerContext } from './ReceiptDetailDrawerProvider';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Receipts read-only details table footer.
|
||||||
|
*/
|
||||||
|
export default function ReceiptDetailTableFooter() {
|
||||||
|
const { receipt } = useReceiptDetailDrawerContext();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ReceiptDetailsFooterRoot>
|
||||||
|
<ReceiptTotalLines labelColWidth={'180px'} amountColWidth={'180px'}>
|
||||||
|
<TotalLine
|
||||||
|
title={<T id={'receipt.details.subtotal'} />}
|
||||||
|
value={<FormatNumber value={receipt.amount} />}
|
||||||
|
/>
|
||||||
|
<TotalLine
|
||||||
|
title={<T id={'receipt.details.total'} />}
|
||||||
|
value={receipt.formatted_amount}
|
||||||
|
borderStyle={TotalLineBorderStyle.DoubleDark}
|
||||||
|
textStyle={TotalLineTextStyle.Bold}
|
||||||
|
/>
|
||||||
|
<TotalLine
|
||||||
|
title={<T id={'receipt.details.payment_amount'} />}
|
||||||
|
value={receipt.formatted_amount}
|
||||||
|
borderStyle={TotalLineBorderStyle.DoubleDark}
|
||||||
|
/>
|
||||||
|
<TotalLine
|
||||||
|
title={<T id={'receipt.details.due_amount'} />}
|
||||||
|
value={'0'}
|
||||||
|
/>
|
||||||
|
</ReceiptTotalLines>
|
||||||
|
</ReceiptDetailsFooterRoot>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ReceiptDetailsFooterRoot = styled.div``;
|
||||||
|
|
||||||
|
export const ReceiptTotalLines = styled(TotalLines)`
|
||||||
|
margin-left: auto;
|
||||||
|
`;
|
||||||
@@ -70,6 +70,11 @@ function BillsDataTable({
|
|||||||
history.push(`/bills/${bill.id}/edit`);
|
history.push(`/bills/${bill.id}/edit`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Handle convert to vendor credit.
|
||||||
|
const handleConvertToVendorCredit = ({ id }) => {
|
||||||
|
history.push(`/vendor-credits/new?from_bill_id=${id}`, { billId: id });
|
||||||
|
};
|
||||||
|
|
||||||
// Handle bill delete action.
|
// Handle bill delete action.
|
||||||
const handleDeleteBill = (bill) => {
|
const handleDeleteBill = (bill) => {
|
||||||
openAlert('bill-delete', { billId: bill.id });
|
openAlert('bill-delete', { billId: bill.id });
|
||||||
@@ -137,6 +142,7 @@ function BillsDataTable({
|
|||||||
onQuick: handleQuickPaymentMade,
|
onQuick: handleQuickPaymentMade,
|
||||||
onAllocateLandedCost: handleAllocateLandedCost,
|
onAllocateLandedCost: handleAllocateLandedCost,
|
||||||
onViewDetails: handleViewDetailBill,
|
onViewDetails: handleViewDetailBill,
|
||||||
|
onConvert: handleConvertToVendorCredit,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</DashboardContentTable>
|
</DashboardContentTable>
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ export function ActionsMenu({
|
|||||||
onOpen,
|
onOpen,
|
||||||
onDelete,
|
onDelete,
|
||||||
onQuick,
|
onQuick,
|
||||||
|
onConvert,
|
||||||
onViewDetails,
|
onViewDetails,
|
||||||
onAllocateLandedCost,
|
onAllocateLandedCost,
|
||||||
},
|
},
|
||||||
@@ -53,6 +54,11 @@ export function ActionsMenu({
|
|||||||
text={intl.get('edit_bill')}
|
text={intl.get('edit_bill')}
|
||||||
onClick={safeCallback(onEdit, original)}
|
onClick={safeCallback(onEdit, original)}
|
||||||
/>
|
/>
|
||||||
|
<MenuItem
|
||||||
|
icon={<Icon icon="convert_to" />}
|
||||||
|
text={intl.get('convert_to_vendor_credit')}
|
||||||
|
onClick={safeCallback(onConvert, original)}
|
||||||
|
/>
|
||||||
|
|
||||||
<If condition={!original.is_open}>
|
<If condition={!original.is_open}>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { useHistory } from 'react-router-dom';
|
|||||||
import { Formik, Form } from 'formik';
|
import { Formik, Form } from 'formik';
|
||||||
import { Intent } from '@blueprintjs/core';
|
import { Intent } from '@blueprintjs/core';
|
||||||
import intl from 'react-intl-universal';
|
import intl from 'react-intl-universal';
|
||||||
import { isEmpty } from 'lodash';
|
import { isEmpty, pick } from 'lodash';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { CLASSES } from 'common/classes';
|
import { CLASSES } from 'common/classes';
|
||||||
import {
|
import {
|
||||||
@@ -50,6 +50,7 @@ function VendorCreditNoteForm({
|
|||||||
isNewMode,
|
isNewMode,
|
||||||
submitPayload,
|
submitPayload,
|
||||||
vendorCredit,
|
vendorCredit,
|
||||||
|
bill,
|
||||||
createVendorCreditMutate,
|
createVendorCreditMutate,
|
||||||
editVendorCreditMutate,
|
editVendorCreditMutate,
|
||||||
} = useVendorCreditNoteFormContext();
|
} = useVendorCreditNoteFormContext();
|
||||||
@@ -72,6 +73,9 @@ function VendorCreditNoteForm({
|
|||||||
...(vendorcreditAutoIncrement && {
|
...(vendorcreditAutoIncrement && {
|
||||||
vendor_credit_number: vendorCreditNumber,
|
vendor_credit_number: vendorCreditNumber,
|
||||||
}),
|
}),
|
||||||
|
...transformToEditForm({
|
||||||
|
...pick(bill, ['vendor_id', 'entries']),
|
||||||
|
}),
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
[vendorCredit, base_currency],
|
[vendorCredit, base_currency],
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { useLocation } from 'react-router-dom';
|
||||||
|
import { isEmpty, pick } from 'lodash';
|
||||||
import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
||||||
|
import { transformToEditForm } from './utils';
|
||||||
import {
|
import {
|
||||||
useCreateVendorCredit,
|
useCreateVendorCredit,
|
||||||
useEditVendorCredit,
|
useEditVendorCredit,
|
||||||
@@ -8,6 +10,7 @@ import {
|
|||||||
useItems,
|
useItems,
|
||||||
useVendors,
|
useVendors,
|
||||||
useSettingsVendorCredits,
|
useSettingsVendorCredits,
|
||||||
|
useBill,
|
||||||
} from 'hooks/query';
|
} from 'hooks/query';
|
||||||
|
|
||||||
const VendorCreditNoteFormContext = React.createContext();
|
const VendorCreditNoteFormContext = React.createContext();
|
||||||
@@ -16,6 +19,10 @@ const VendorCreditNoteFormContext = React.createContext();
|
|||||||
* Vendor Credit note data provider.
|
* Vendor Credit note data provider.
|
||||||
*/
|
*/
|
||||||
function VendorCreditNoteFormProvider({ vendorCreditId, ...props }) {
|
function VendorCreditNoteFormProvider({ vendorCreditId, ...props }) {
|
||||||
|
const { state } = useLocation();
|
||||||
|
|
||||||
|
const billId = state?.billId;
|
||||||
|
|
||||||
// Handle fetching the items table based on the given query.
|
// Handle fetching the items table based on the given query.
|
||||||
const {
|
const {
|
||||||
data: { items },
|
data: { items },
|
||||||
@@ -39,6 +46,11 @@ function VendorCreditNoteFormProvider({ vendorCreditId, ...props }) {
|
|||||||
enabled: !!vendorCreditId,
|
enabled: !!vendorCreditId,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Handle fetch bill details.
|
||||||
|
const { isLoading: isBillLoading, data: bill } = useBill(billId, {
|
||||||
|
enabled: !!billId,
|
||||||
|
});
|
||||||
|
|
||||||
// Form submit payload.
|
// Form submit payload.
|
||||||
const [submitPayload, setSubmitPayload] = React.useState();
|
const [submitPayload, setSubmitPayload] = React.useState();
|
||||||
|
|
||||||
@@ -56,6 +68,7 @@ function VendorCreditNoteFormProvider({ vendorCreditId, ...props }) {
|
|||||||
vendorCredit,
|
vendorCredit,
|
||||||
submitPayload,
|
submitPayload,
|
||||||
isNewMode,
|
isNewMode,
|
||||||
|
bill,
|
||||||
|
|
||||||
isVendorCreditLoading,
|
isVendorCreditLoading,
|
||||||
|
|
||||||
@@ -70,7 +83,8 @@ function VendorCreditNoteFormProvider({ vendorCreditId, ...props }) {
|
|||||||
isVendorCreditLoading ||
|
isVendorCreditLoading ||
|
||||||
isItemsLoading ||
|
isItemsLoading ||
|
||||||
isVendorsLoading ||
|
isVendorsLoading ||
|
||||||
isVendorCreditLoading
|
isVendorCreditLoading ||
|
||||||
|
isBillLoading
|
||||||
}
|
}
|
||||||
name={'vendor-credit-form'}
|
name={'vendor-credit-form'}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ function CreditNoteForm({
|
|||||||
isNewMode,
|
isNewMode,
|
||||||
submitPayload,
|
submitPayload,
|
||||||
creditNote,
|
creditNote,
|
||||||
|
newCreditNote,
|
||||||
createCreditNoteMutate,
|
createCreditNoteMutate,
|
||||||
editCreditNoteMutate,
|
editCreditNoteMutate,
|
||||||
} = useCreditNoteFormContext();
|
} = useCreditNoteFormContext();
|
||||||
@@ -74,6 +75,7 @@ function CreditNoteForm({
|
|||||||
credit_note_number: creditNumber,
|
credit_note_number: creditNumber,
|
||||||
}),
|
}),
|
||||||
entries: orderingLinesIndexes(defaultCreditNote.entries),
|
entries: orderingLinesIndexes(defaultCreditNote.entries),
|
||||||
|
...newCreditNote,
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
[],
|
[],
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import {
|
|||||||
useItems,
|
useItems,
|
||||||
useCustomers,
|
useCustomers,
|
||||||
useSettingsCreditNotes,
|
useSettingsCreditNotes,
|
||||||
|
useInvoice,
|
||||||
} from 'hooks/query';
|
} from 'hooks/query';
|
||||||
|
|
||||||
const CreditNoteFormContext = React.createContext();
|
const CreditNoteFormContext = React.createContext();
|
||||||
@@ -19,6 +20,9 @@ const CreditNoteFormContext = React.createContext();
|
|||||||
* Credit note data provider.
|
* Credit note data provider.
|
||||||
*/
|
*/
|
||||||
function CreditNoteFormProvider({ creditNoteId, ...props }) {
|
function CreditNoteFormProvider({ creditNoteId, ...props }) {
|
||||||
|
const { state } = useLocation();
|
||||||
|
const invoiceId = state?.invoiceId;
|
||||||
|
|
||||||
// Handle fetch customers data table or list
|
// Handle fetch customers data table or list
|
||||||
const {
|
const {
|
||||||
data: { customers },
|
data: { customers },
|
||||||
@@ -33,13 +37,17 @@ function CreditNoteFormProvider({ creditNoteId, ...props }) {
|
|||||||
page_size: 10000,
|
page_size: 10000,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handle fetch vendor credit details.
|
// Handle fetch credit details.
|
||||||
const { data: creditNote, isLoading: isCreditNoteLoading } = useCreditNote(
|
const { data: creditNote, isLoading: isCreditNoteLoading } = useCreditNote(
|
||||||
creditNoteId,
|
creditNoteId,
|
||||||
{
|
{
|
||||||
enabled: !!creditNoteId,
|
enabled: !!creditNoteId,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
// Handle fetch invoice detail.
|
||||||
|
const { data: invoice, isLoading: isInvoiceLoading } = useInvoice(invoiceId, {
|
||||||
|
enabled: !!invoiceId,
|
||||||
|
});
|
||||||
|
|
||||||
// Handle fetching settings.
|
// Handle fetching settings.
|
||||||
useSettingsCreditNotes();
|
useSettingsCreditNotes();
|
||||||
@@ -54,6 +62,12 @@ function CreditNoteFormProvider({ creditNoteId, ...props }) {
|
|||||||
// Determines whether the form in new mode.
|
// Determines whether the form in new mode.
|
||||||
const isNewMode = !creditNoteId;
|
const isNewMode = !creditNoteId;
|
||||||
|
|
||||||
|
const newCreditNote = !isEmpty(invoice)
|
||||||
|
? transformToEditForm({
|
||||||
|
...pick(invoice, ['customer_id', 'entries']),
|
||||||
|
})
|
||||||
|
: [];
|
||||||
|
|
||||||
// Provider payload.
|
// Provider payload.
|
||||||
const provider = {
|
const provider = {
|
||||||
items,
|
items,
|
||||||
@@ -61,6 +75,7 @@ function CreditNoteFormProvider({ creditNoteId, ...props }) {
|
|||||||
creditNote,
|
creditNote,
|
||||||
submitPayload,
|
submitPayload,
|
||||||
isNewMode,
|
isNewMode,
|
||||||
|
newCreditNote,
|
||||||
|
|
||||||
isItemsLoading,
|
isItemsLoading,
|
||||||
isCustomersLoading,
|
isCustomersLoading,
|
||||||
@@ -70,11 +85,14 @@ function CreditNoteFormProvider({ creditNoteId, ...props }) {
|
|||||||
setSubmitPayload,
|
setSubmitPayload,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isLoading =
|
||||||
|
isItemsLoading ||
|
||||||
|
isCustomersLoading ||
|
||||||
|
isCreditNoteLoading ||
|
||||||
|
isInvoiceLoading;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardInsider
|
<DashboardInsider loading={isLoading} name={'credit-note-form'}>
|
||||||
loading={isItemsLoading || isCustomersLoading || isCreditNoteLoading}
|
|
||||||
name={'credit-note-form'}
|
|
||||||
>
|
|
||||||
<CreditNoteFormContext.Provider value={provider} {...props} />
|
<CreditNoteFormContext.Provider value={provider} {...props} />
|
||||||
</DashboardInsider>
|
</DashboardInsider>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -74,6 +74,11 @@ function InvoicesDataTable({
|
|||||||
history.push(`/invoices/${invoice.id}/edit`);
|
history.push(`/invoices/${invoice.id}/edit`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Handle convert to credit note.
|
||||||
|
const handleConvertToCreitNote = ({ id }) => {
|
||||||
|
history.push(`/credit-notes/new?from_invoice_id=${id}`, { invoiceId: id });
|
||||||
|
};
|
||||||
|
|
||||||
// handle quick payment receive.
|
// handle quick payment receive.
|
||||||
const handleQuickPaymentReceive = ({ id }) => {
|
const handleQuickPaymentReceive = ({ id }) => {
|
||||||
openDialog('quick-payment-receive', { invoiceId: id });
|
openDialog('quick-payment-receive', { invoiceId: id });
|
||||||
@@ -147,6 +152,7 @@ function InvoicesDataTable({
|
|||||||
onQuick: handleQuickPaymentReceive,
|
onQuick: handleQuickPaymentReceive,
|
||||||
onViewDetails: handleViewDetailInvoice,
|
onViewDetails: handleViewDetailInvoice,
|
||||||
onPrint: handlePrintInvoice,
|
onPrint: handlePrintInvoice,
|
||||||
|
onConvert: handleConvertToCreitNote,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</DashboardContentTable>
|
</DashboardContentTable>
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ export function ActionsMenu({
|
|||||||
onEdit,
|
onEdit,
|
||||||
onDeliver,
|
onDeliver,
|
||||||
onDelete,
|
onDelete,
|
||||||
onDrawer,
|
onConvert,
|
||||||
onQuick,
|
onQuick,
|
||||||
onViewDetails,
|
onViewDetails,
|
||||||
onPrint,
|
onPrint,
|
||||||
@@ -145,6 +145,11 @@ export function ActionsMenu({
|
|||||||
text={intl.get('edit_invoice')}
|
text={intl.get('edit_invoice')}
|
||||||
onClick={safeCallback(onEdit, original)}
|
onClick={safeCallback(onEdit, original)}
|
||||||
/>
|
/>
|
||||||
|
<MenuItem
|
||||||
|
icon={<Icon icon="convert_to" />}
|
||||||
|
text={intl.get('convert_to_credit_note')}
|
||||||
|
onClick={safeCallback(onConvert, original)}
|
||||||
|
/>
|
||||||
|
|
||||||
<If condition={!original.is_delivered}>
|
<If condition={!original.is_delivered}>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
|
|||||||
@@ -1659,8 +1659,11 @@
|
|||||||
"transactions": "معاملات ",
|
"transactions": "معاملات ",
|
||||||
"item.drawer_transactions_by": "معاملات حسب :",
|
"item.drawer_transactions_by": "معاملات حسب :",
|
||||||
"item.drawer_quantity_sold": "الكمية المباعة",
|
"item.drawer_quantity_sold": "الكمية المباعة",
|
||||||
"journal_entries.amount_displayed_base_currency":"يتم عرض المبلغ بالعملة الأساسية الخاصة بك "
|
"journal_entries.amount_displayed_base_currency":"يتم عرض المبلغ بالعملة الأساسية الخاصة بك ",
|
||||||
|
"inventory_adjustment.column.product":"المنتج",
|
||||||
|
"convert_to_credit_note":"تحويل إلى إشعار الدائن",
|
||||||
|
"convert_to_vendor_credit":"تحويل إلى إشعار المدين",
|
||||||
|
"overdue":"Overdue"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1195,6 +1195,7 @@
|
|||||||
"payment_receive.details.payment_number": "Payment #",
|
"payment_receive.details.payment_number": "Payment #",
|
||||||
"payment_receive.details.total": "TOTAL",
|
"payment_receive.details.total": "TOTAL",
|
||||||
"payment_receive.details.subtotal": "Subtotal",
|
"payment_receive.details.subtotal": "Subtotal",
|
||||||
|
"payment_receive.details.statement": "Statement",
|
||||||
"estimate.details.estimate_number": "Estimate #",
|
"estimate.details.estimate_number": "Estimate #",
|
||||||
"estimate.details.subtotal": "Subtotal",
|
"estimate.details.subtotal": "Subtotal",
|
||||||
"estimate.details.total": "TOTAL",
|
"estimate.details.total": "TOTAL",
|
||||||
@@ -1202,12 +1203,15 @@
|
|||||||
"estimate.details.due_amount": "Due amount",
|
"estimate.details.due_amount": "Due amount",
|
||||||
"estimate.details.note": "Note",
|
"estimate.details.note": "Note",
|
||||||
"estimate.details.created_at": "Created at",
|
"estimate.details.created_at": "Created at",
|
||||||
|
"estimate.details.terms_conditions": "Terms & Conditions",
|
||||||
"receipt.details.receipt_number": "Receipt #",
|
"receipt.details.receipt_number": "Receipt #",
|
||||||
"receipt.details.subtotal": "Subtotal",
|
"receipt.details.subtotal": "Subtotal",
|
||||||
"receipt.details.total": "TOTAL",
|
"receipt.details.total": "TOTAL",
|
||||||
"receipt.details.payment_amount": "Payment amount",
|
"receipt.details.payment_amount": "Payment amount",
|
||||||
"receipt.details.due_amount": "Due amount",
|
"receipt.details.due_amount": "Due amount",
|
||||||
"receipt.details.created_at": "Created at",
|
"receipt.details.created_at": "Created at",
|
||||||
|
"receipt.details.receipt_message": "Receipt Message",
|
||||||
|
"receipt.details.statement": "Statement",
|
||||||
"invoice.details.created_at": "Created at",
|
"invoice.details.created_at": "Created at",
|
||||||
"invoice.details.total": "TOTAL",
|
"invoice.details.total": "TOTAL",
|
||||||
"invoice.details.subtotal": "Subtotal",
|
"invoice.details.subtotal": "Subtotal",
|
||||||
@@ -1523,6 +1527,7 @@
|
|||||||
"credit_note.drawer.label_subtotal": "Subtotal",
|
"credit_note.drawer.label_subtotal": "Subtotal",
|
||||||
"credit_note.drawer.label_refund_transactions": "Refund Transactions",
|
"credit_note.drawer.label_refund_transactions": "Refund Transactions",
|
||||||
"credit_note.drawer.label_invoices_reconciled": "Invoices Reconciled",
|
"credit_note.drawer.label_invoices_reconciled": "Invoices Reconciled",
|
||||||
|
"credit_note.drawer.terms_conditions": "Terms Conditions",
|
||||||
|
|
||||||
"sidebar_vendor_credits": "Vendor Credits",
|
"sidebar_vendor_credits": "Vendor Credits",
|
||||||
"vendor_credits.lable_vendor_credit_list": "Vendor Credits List",
|
"vendor_credits.lable_vendor_credit_list": "Vendor Credits List",
|
||||||
@@ -1655,5 +1660,10 @@
|
|||||||
"item.drawer_transactions_by": "Transactions by:",
|
"item.drawer_transactions_by": "Transactions by:",
|
||||||
"item.drawer_quantity_sold": "Quantity Sold",
|
"item.drawer_quantity_sold": "Quantity Sold",
|
||||||
"role_name": "Role name",
|
"role_name": "Role name",
|
||||||
"journal_entries.amount_displayed_base_currency":"Amount is displayed in your base currency"
|
"journal_entries.amount_displayed_base_currency":"Amount is displayed in your base currency",
|
||||||
|
"inventory_adjustment.column.product":"Product",
|
||||||
|
"convert_to_credit_note":"Convert to Credit Note",
|
||||||
|
"convert_to_vendor_credit":"Convert to Vendor Credit",
|
||||||
|
"overdue":"Overdue"
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -646,6 +646,21 @@ export const getDashboardRoutes = () => [
|
|||||||
defaultSearchResource: RESOURCES_TYPES.CREDIT_NOTE,
|
defaultSearchResource: RESOURCES_TYPES.CREDIT_NOTE,
|
||||||
subscriptionActive: [SUBSCRIPTION_TYPE.MAIN],
|
subscriptionActive: [SUBSCRIPTION_TYPE.MAIN],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: `/credit-notes/new/?from_invoice_id=/:id`,
|
||||||
|
component: lazy(() =>
|
||||||
|
import(
|
||||||
|
'../containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFormPage'
|
||||||
|
),
|
||||||
|
),
|
||||||
|
name: 'credit-note-new',
|
||||||
|
breadcrumb: intl.get('credit_note.label.new_credit_note'),
|
||||||
|
backLink: true,
|
||||||
|
sidebarExpand: false,
|
||||||
|
pageTitle: intl.get('credit_note.label.new_credit_note'),
|
||||||
|
defaultSearchResource: RESOURCES_TYPES.CREDIT_NOTE,
|
||||||
|
subscriptionActive: [SUBSCRIPTION_TYPE.MAIN],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/credit-notes/new',
|
path: '/credit-notes/new',
|
||||||
component: lazy(() =>
|
component: lazy(() =>
|
||||||
@@ -773,6 +788,21 @@ export const getDashboardRoutes = () => [
|
|||||||
defaultSearchResource: RESOURCES_TYPES.VENDOR_CREDIT,
|
defaultSearchResource: RESOURCES_TYPES.VENDOR_CREDIT,
|
||||||
subscriptionActive: [SUBSCRIPTION_TYPE.MAIN],
|
subscriptionActive: [SUBSCRIPTION_TYPE.MAIN],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/vendor-credits/new/?from_bill_id=/:id',
|
||||||
|
component: lazy(() =>
|
||||||
|
import(
|
||||||
|
'containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormPage'
|
||||||
|
),
|
||||||
|
),
|
||||||
|
name: 'vendor-credits-new',
|
||||||
|
backLink: true,
|
||||||
|
sidebarExpand: false,
|
||||||
|
breadcrumb: intl.get('vendor_credits.label.new_vendor_credit'),
|
||||||
|
pageTitle: intl.get('vendor_credits.label.new_vendor_credit'),
|
||||||
|
defaultSearchResource: RESOURCES_TYPES.VENDOR_CREDIT,
|
||||||
|
subscriptionActive: [SUBSCRIPTION_TYPE.MAIN],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/vendor-credits/new',
|
path: '/vendor-credits/new',
|
||||||
component: lazy(() =>
|
component: lazy(() =>
|
||||||
|
|||||||
Reference in New Issue
Block a user