BC-17 feat: customer/vendor drawer of readonly details.

This commit is contained in:
a.bouhuolia
2021-09-09 11:56:06 +02:00
parent 6fd47aa884
commit 7b968a43ef
24 changed files with 738 additions and 25 deletions

View File

@@ -32,6 +32,7 @@ straightforward as possible.
- Inventory adjustment publish action.
- Customers and vendors activate and inactivate action.
- Add refresh button on dashboard actions bar to all datatables resources.
- Add clickable datatable rows to display each row details.
### Changed

View File

@@ -18,13 +18,18 @@ export function DetailsMenu({
children,
direction = DIRECTION.VERTICAL,
minLabelSize,
className,
}) {
return (
<div
className={classNames('details-menu', {
'details-menu--vertical': direction === DIRECTION.VERTICAL,
'details-menu--horizantal': direction === DIRECTION.HORIZANTAL,
})}
className={classNames(
'details-menu',
{
'details-menu--vertical': direction === DIRECTION.VERTICAL,
'details-menu--horizantal': direction === DIRECTION.HORIZANTAL,
},
className,
)}
>
<DetailsMenuContext.Provider value={{ minLabelSize }}>
{children}
@@ -36,14 +41,18 @@ export function DetailsMenu({
/**
* Detail item.
*/
export function DetailItem({ label, children, name }) {
export function DetailItem({ label, children, name, className }) {
const { minLabelSize } = useDetailsMenuContext();
return (
<div
className={classNames('detail-item', {
[`detail-item--${name}`]: name,
})}
className={classNames(
'detail-item',
{
[`detail-item--${name}`]: name,
},
className,
)}
>
<div
style={{

View File

@@ -1,8 +1,5 @@
import React from 'react';
// import EstimateDrawer from 'containers/Sales/Estimates/EstimateDetails/EstimateDrawer';
// import InvoiceDrawer from 'containers/Sales/Invoices/InvoiceDetails/InvoiceDrawer';
// import ReceiptDrawer from 'containers/Sales/Receipts/ReceiptDetails/ReceiptDrawer';
// import PaymentReceiveDrawer from 'containers/Sales/PaymentReceives/PaymentDetails/PaymentReceiveDrawer';
import AccountDrawer from 'containers/Drawers/AccountDrawer';
import ManualJournalDrawer from 'containers/Drawers/ManualJournalDrawer';
import ExpenseDrawer from 'containers/Drawers/ExpenseDrawer';
@@ -13,7 +10,8 @@ import PaymentReceiveDetailDrawer from 'containers/Drawers/PaymentReceiveDetailD
import PaymentMadeDetailDrawer from 'containers/Drawers/PaymentMadeDetailDrawer';
import EstimateDetailDrawer from '../containers/Drawers/EstimateDetailDrawer';
import ItemDetailDrawer from '../containers/Drawers/ItemDetailDrawer';
import ContactDetailDrawer from '../containers/Drawers/ContactDetailDrawer';
import CustomerDetailsDrawer from '../containers/Drawers/CustomerDetailsDrawer';
import VendorDetailsDrawer from '../containers/Drawers/VendorDetailsDrawer';
import InventoryAdjustmentDetailDrawer from '../containers/Drawers/InventoryAdjustmentDetailDrawer';
import { DRAWERS } from 'common/drawers';
@@ -34,7 +32,8 @@ export default function DrawersContainer() {
<PaymentReceiveDetailDrawer name={'payment-receive-detail-drawer'} />
<PaymentMadeDetailDrawer name={'payment-made-detail-drawer'} />
<ItemDetailDrawer name={'item-detail-drawer'} />
<ContactDetailDrawer name={'contact-detail-drawer'} />
<CustomerDetailsDrawer name={'customer-details-drawer'} />
<VendorDetailsDrawer name={'vendor-details-drawer'} />
<InventoryAdjustmentDetailDrawer
name={DRAWERS.INVENTORY_ADJUSTMENT_DRAWER}
/>

View File

@@ -2,7 +2,7 @@ import React, { useEffect } from 'react';
import 'style/pages/Customers/List.scss';
import { DashboardContentTable, DashboardPageContent } from 'components';
import { DashboardPageContent } from 'components';
import CustomersActionsBar from './CustomersActionsBar';
import CustomersViewsTabs from './CustomersViewsTabs';

View File

@@ -92,12 +92,12 @@ function CustomersTable({
// Handle view detail contact.
const handleViewDetailCustomer = ({ id }) => {
openDrawer('contact-detail-drawer', { contactId: id });
openDrawer('contact-detail-drawer', { customerId: id });
};
// Handle cell click.
const handleCellClick = (cell, event) => {
openDrawer('contact-detail-drawer', { contactId: cell.row.original.id });
openDrawer('customer-details-drawer', { customerId: cell.row.original.id });
};
if (isEmptyStatus) {

View File

@@ -3,14 +3,23 @@ import intl from 'react-intl-universal';
import { RESOURCES_TYPES } from '../../common/resourcesTypes';
import withDrawerActions from '../Drawer/withDrawerActions';
function CustomerUniversalSearchSelectComponent({ resourceType, resourceId }) {
function CustomerUniversalSearchSelectComponent({
resourceType,
resourceId,
onAction,
// #withDrawerActions
openDrawer,
}) {
if (resourceType === RESOURCES_TYPES.CUSTOMER) {
openDrawer('customer-details-drawer', { customerId: resourceId });
onAction && onAction();
}
return null;
}
const CustomerUniversalSearchSelectAction = withDrawerActions(
CustomerUniversalSearchSelectComponent
CustomerUniversalSearchSelectComponent,
);
/**
@@ -19,6 +28,7 @@ const CustomerUniversalSearchSelectAction = withDrawerActions(
* @returns
*/
const customersToSearch = (contact) => ({
id: contact.id,
text: contact.display_name,
label: contact.formatted_balance,
reference: contact,

View File

@@ -0,0 +1,24 @@
import React from 'react';
import clsx from 'classnames';
import { Card } from 'components';
import CustomerDetailsActionsBar from './CustomerDetailsActionsBar';
import CustomerDetailsHeader from './CustomerDetailsHeader';
import Style from './CustomerDetailsDrawer.module.scss';
/**
* contact detail.
*/
export default function CustomerDetails() {
return (
<div className={clsx(Style.root)}>
<CustomerDetailsActionsBar />
<Card>
<CustomerDetailsHeader />
</Card>
</div>
);
}

View File

@@ -0,0 +1,130 @@
import React from 'react';
import intl from 'react-intl-universal';
import { useHistory } from 'react-router-dom';
import {
Button,
NavbarGroup,
Classes,
NavbarDivider,
Intent,
Position,
PopoverInteractionKind,
Popover,
Menu,
MenuItem,
} from '@blueprintjs/core';
import clsx from 'classnames';
import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
import { useCustomerDetailsDrawerContext } from './CustomerDetailsDrawerProvider';
import withAlertsActions from 'containers/Alert/withAlertActions';
import withDrawerActions from 'containers/Drawer/withDrawerActions';
import { Icon, FormattedMessage as T } from 'components';
import { compose } from 'utils';
/**
* Customer details actions bar.
*/
function CustomerDetailsActionsBar({
// #withAlertsActions
openAlert,
// #withDrawerActions
closeDrawer,
}) {
const { contact, customerId } = useCustomerDetailsDrawerContext();
const history = useHistory();
// Handle new invoice button click.
const handleNewInvoiceClick = () => {
history.push('invoices/new');
closeDrawer('customer-details-drawer');
};
// Handle new receipt button click.
const handleNewReceiptClick = () => {
history.push('receipts/new');
closeDrawer('customer-details-drawer');
};
// Handle new payment receive button click.
const handleNewPaymentClick = () => {
history.push('payment-receives/new');
closeDrawer('customer-details-drawer');
};
// Handle new estimate button click.
const handleNewEstimateClick = () => {
history.push('estimates/new');
closeDrawer('customer-details-drawer');
};
const handleDeleteCustomer = () => {
openAlert(`'customer-delete`, { customerId });
closeDrawer('customer-details-drawer');
};
const handleEditContact = () => {
history.push(`/customers/${customerId}/edit`);
closeDrawer('customer-details-drawer');
};
return (
<DashboardActionsBar>
<NavbarGroup>
<Popover
content={
<Menu>
<MenuItem
text={<T id={'customer.drawer.action.new_invoice'} />}
onClick={handleNewInvoiceClick}
/>
<MenuItem
text={<T id={'customer.drawer.action.new_estimate'} />}
onClick={handleNewEstimateClick}
/>
<MenuItem
text={<T id={'customer.drawer.action.new_receipt'} />}
onClick={handleNewReceiptClick}
/>
<MenuItem
text={<T id={'customer.drawer.action.new_payment'} />}
onClick={handleNewPaymentClick}
/>
</Menu>
}
minimal={true}
interactionKind={PopoverInteractionKind.CLICK}
position={Position.BOTTOM_LEFT}
>
<Button
className={clsx(Classes.MINIMAL)}
text={<T id={'customer.drawer.action.new_transaction'} />}
icon={<Icon icon={'plus'} />}
/>
</Popover>
<NavbarDivider />
<Button
className={Classes.MINIMAL}
icon={<Icon icon="pen-18" />}
text={intl.get('edit_contact', { name: contact?.contact_service })}
onClick={handleEditContact}
/>
<NavbarDivider />
<Button
className={Classes.MINIMAL}
icon={<Icon icon={'trash-16'} iconSize={16} />}
text={<T id={'delete'} />}
intent={Intent.DANGER}
onClick={handleDeleteCustomer}
/>
</NavbarGroup>
</DashboardActionsBar>
);
}
export default compose(
withDrawerActions,
withAlertsActions,
)(CustomerDetailsActionsBar);

View File

@@ -0,0 +1,15 @@
.root {
&_content {
&_primary {
padding-bottom: 15px;
border-bottom: 1px solid #e2e2e2;
}
}
:global .card {
margin: 15px;
padding: 18px;
}
}

View File

@@ -0,0 +1,18 @@
import React from 'react';
import CustomerDetails from './CustomerDetails';
import { CustomerDetailsDrawerProvider } from './CustomerDetailsDrawerProvider';
/**
* Contact detail drawer content.
*/
export default function CustomerDetailsDrawerContent({
// #ownProp
customerId,
}) {
return (
<CustomerDetailsDrawerProvider customerId={customerId}>
<CustomerDetails />
</CustomerDetailsDrawerProvider>
);
}

View File

@@ -0,0 +1,39 @@
import React from 'react';
import { DrawerHeaderContent, DashboardInsider } from 'components';
import { useCustomer } from 'hooks/query';
const ContactDetailDrawerContext = React.createContext();
/**
* Contact detail provider.
*/
function CustomerDetailsDrawerProvider({ customerId, ...props }) {
// Handle fetch customer details.
const { data: customer, isLoading: isCustomerLoading } = useCustomer(
customerId,
{
enabled: !!customerId,
},
);
// Provider.
const provider = {
customer,
customerId,
isCustomerLoading,
};
return (
<DashboardInsider loading={isCustomerLoading}>
<DrawerHeaderContent
name="customer-details-drawer"
title={customer?.display_name}
/>
<ContactDetailDrawerContext.Provider value={provider} {...props} />
</DashboardInsider>
);
}
const useCustomerDetailsDrawerContext = () =>
React.useContext(ContactDetailDrawerContext);
export { CustomerDetailsDrawerProvider, useCustomerDetailsDrawerContext };

View File

@@ -0,0 +1,79 @@
import React from 'react';
import intl from 'react-intl-universal';
import clsx from 'classnames';
import { defaultTo } from 'lodash';
import { DetailsMenu, DetailItem, T } from 'components';
import { useCustomerDetailsDrawerContext } from './CustomerDetailsDrawerProvider';
import Style from './CustomerDetailsDrawer.module.scss';
/**
* Customer details header.
*/
export default function CustomerDetailsHeader() {
const { customer } = useCustomerDetailsDrawerContext();
return (
<div className={clsx(Style.root_content)}>
<DetailsMenu
direction={'vertical'}
className={clsx(Style.root_content_primary)}
>
<DetailItem
name={'outstanding-receivable'}
label={<T id={'customer.drawer.label.outstanding_receivable'} />}
>
<h3 class="big-number">{customer.formatted_balance}</h3>
</DetailItem>
<DetailItem
label={<T id={'customer.drawer.label.customer_name'} />}
name={'name'}
children={customer?.display_name}
/>
<DetailItem
label={<T id={'customer.drawer.label.customer_type'} />}
name={'type'}
children={customer?.customer_type}
/>
<DetailItem label={<T id={'customer.drawer.label.unused_credits'} />}>
0
</DetailItem>
</DetailsMenu>
<DetailsMenu direction={'horizantal'} minLabelSize={'175px'}>
<DetailItem
label={<T id={'customer.drawer.label.company_name'} />}
children={defaultTo(customer?.company_name, '--')}
/>
<DetailItem
label={<T id={'customer.drawer.label.email'} />}
children={defaultTo(customer?.email, '--')}
/>
<DetailItem label={<T id={'customer.drawer.label.phone_number'} />}>
<div>{customer?.personal_phone} </div>
<div>{customer?.work_phone} </div>
</DetailItem>
<DetailItem
label={<T id={'customer.drawer.label.website'} />}
children={defaultTo(customer?.website, '--')}
/>
<DetailItem
label={<T id={'customer.drawer.label.opening_balance'} />}
children={customer?.formatted_opening_balance}
/>
<DetailItem
label={<T id={'customer.drawer.label.opening_balance_at'} />}
children={customer?.formatted_opening_balance_at}
/>
<DetailItem
label={<T id={'customer.drawer.label.currency'} />}
children={customer?.currency_code}
/>
</DetailsMenu>
</div>
);
}

View File

@@ -0,0 +1,30 @@
import React from 'react';
import { Drawer, DrawerSuspense } from 'components';
import withDrawers from 'containers/Drawer/withDrawers';
import { compose } from 'utils';
const CustomerDetailsDrawerContent = React.lazy(() =>
import('./CustomerDetailsDrawerContent'),
);
/**
* Contact detail drawer.
*/
function CustomerDetailsDrawer({
name,
// #withDrawer
isOpen,
payload: { customerId },
}) {
return (
<Drawer isOpen={isOpen} name={name} size={'750px'}>
<DrawerSuspense>
<CustomerDetailsDrawerContent customerId={customerId} />
</DrawerSuspense>
</Drawer>
);
}
export default compose(withDrawers())(CustomerDetailsDrawer);

View File

@@ -0,0 +1,24 @@
import React from 'react';
import clsx from 'classnames';
import { Card } from 'components';
import VendorDetailsActionsBar from './VendorDetailsActionsBar';
import VendorDetailsHeader from './VendorDetailsHeader';
import Style from './VendorDetailsDrawer.module.scss';
/**
* contact detail.
*/
export default function CustomerDetails() {
return (
<div className={clsx(Style.root)}>
<VendorDetailsActionsBar />
<Card>
<VendorDetailsHeader />
</Card>
</div>
);
}

View File

@@ -0,0 +1,113 @@
import React from 'react';
import { useHistory } from 'react-router-dom';
import {
Button,
NavbarGroup,
Classes,
NavbarDivider,
Intent,
PopoverInteractionKind,
Position,
MenuItem,
Menu,
Popover,
} from '@blueprintjs/core';
import clsx from 'classnames';
import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
import { useVendorDetailsDrawerContext } from './VendorDetailsDrawerProvider';
import withAlertsActions from 'containers/Alert/withAlertActions';
import withDrawerActions from 'containers/Drawer/withDrawerActions';
import { Icon, FormattedMessage as T } from 'components';
import { safeCallback, compose } from 'utils';
/**
* Vendor details actions bar.
*/
function VendorDetailsActionsBar({
// #withAlertsActions
openAlert,
// #withDrawerActions
closeDrawer,
}) {
const { vendor, vendorId } = useVendorDetailsDrawerContext();
const history = useHistory();
// Handle edit vendor.
const onEditContact = () => {
history.push(`/vendors/${vendorId}/edit`);
closeDrawer('vendor-details-drawer');
};
// Handle delete vendor.
const onDeleteContact = () => {
openAlert(`'vendor-delete`, { vendorId });
closeDrawer('vendor-details-drawer');
};
const handleNewInvoiceClick = () => {
history.push('bills/new');
closeDrawer('vendor-details-drawer');
};
const handleNewPaymentClick = () => {
history.push('payment-mades/new');
closeDrawer('vendor-details-drawer');
};
return (
<DashboardActionsBar>
<NavbarGroup>
<Popover
content={
<Menu>
<MenuItem
text={<T id={'vendor.drawer.action.new_invoice'} />}
onClick={handleNewInvoiceClick}
/>
<MenuItem
text={<T id={'vendor.drawer.action.new_payment'} />}
onClick={handleNewPaymentClick}
/>
</Menu>
}
minimal={true}
interactionKind={PopoverInteractionKind.CLICK}
position={Position.BOTTOM_LEFT}
>
<Button
className={clsx(Classes.MINIMAL)}
text={<T id={'vendor.drawer.action.new_transaction'} />}
icon={<Icon icon={'plus'} />}
/>
</Popover>
<NavbarDivider />
<Button
className={Classes.MINIMAL}
icon={<Icon icon="pen-18" />}
text={<T id={'vendor.drawer.action.edit_vendor'} />}
onClick={safeCallback(onEditContact)}
/>
<NavbarDivider />
<Button
className={Classes.MINIMAL}
icon={<Icon icon={'trash-16'} iconSize={16} />}
text={<T id={'vendor.drawer.action.delete'} />}
intent={Intent.DANGER}
onClick={safeCallback(onDeleteContact)}
/>
</NavbarGroup>
</DashboardActionsBar>
);
}
export default compose(
withDrawerActions,
withAlertsActions,
)(VendorDetailsActionsBar);

View File

@@ -0,0 +1,17 @@
.root {
&_content {
&_primary {
padding-bottom: 15px;
border-bottom: 1px solid #e2e2e2;
}
}
:global .card {
margin: 15px;
padding: 18px;
}
}

View File

@@ -0,0 +1,18 @@
import React from 'react';
import VendorDetails from './VendorDetails';
import { VendorDetailsDrawerProvider } from './VendorDetailsDrawerProvider';
/**
* Contact detail drawer content.
*/
export default function VendorDetailsDrawerContent({
// #ownProp
vendorId,
}) {
return (
<VendorDetailsDrawerProvider vendorId={vendorId}>
<VendorDetails />
</VendorDetailsDrawerProvider>
);
}

View File

@@ -0,0 +1,39 @@
import React from 'react';
import { DrawerHeaderContent, DashboardInsider } from 'components';
import { useVendor } from 'hooks/query';
const VendorDetailDrawerContext = React.createContext();
/**
* Contact detail provider.
*/
function VendorDetailsDrawerProvider({ vendorId, ...props }) {
// Handle fetch vendor details.
const { data: vendor, isLoading: isVendorLoading } = useVendor(
vendorId,
{
enabled: !!vendorId,
},
);
// Provider.
const provider = {
vendor,
vendorId,
isVendorLoading,
};
return (
<DashboardInsider loading={isVendorLoading}>
<DrawerHeaderContent
name="vendor-details-drawer"
title={vendor?.display_name}
/>
<VendorDetailDrawerContext.Provider value={provider} {...props} />
</DashboardInsider>
);
}
const useVendorDetailsDrawerContext = () =>
React.useContext(VendorDetailDrawerContext);
export { VendorDetailsDrawerProvider, useVendorDetailsDrawerContext };

View File

@@ -0,0 +1,74 @@
import React from 'react';
import intl from 'react-intl-universal';
import clsx from 'classnames';
import { defaultTo } from 'lodash';
import { T, DetailsMenu, DetailItem } from 'components';
import { useVendorDetailsDrawerContext } from './VendorDetailsDrawerProvider';
import Style from './VendorDetailsDrawer.module.scss';
/**
* Vendor details header.
*/
export default function VendorDetailsHeader() {
const { vendor } = useVendorDetailsDrawerContext();
return (
<div className={clsx(Style.root_content)}>
<DetailsMenu
direction={'vertical'}
className={clsx(Style.root_content_primary)}
>
<DetailItem
name={'outstanding-payable'}
label={<T id={'vendor.drawer.label.outstanding_payable'} />}
>
<h3 class="big-number">{vendor.formatted_balance}</h3>
</DetailItem>
<DetailItem
label={<T id={'vendor.drawer.label.vendor'} />}
name={'name'}
children={vendor?.display_name}
/>
<DetailItem label={<T id={'vendor.drawer.label.unused_credits'} />}>
0
</DetailItem>
</DetailsMenu>
<DetailsMenu direction={'horizantal'} minLabelSize={'175px'}>
<DetailItem
label={<T id={'vendor.drawer.label.company_name'} />}
children={defaultTo(vendor?.company_name, '--')}
/>
<DetailItem
label={intl.get('email')}
children={defaultTo(vendor.email, '--')}
/>
<DetailItem label={<T id={'vendor.drawer.label.phone_number'} />}>
<div>{vendor?.personal_phone} </div>
<div>{vendor?.work_phone} </div>
</DetailItem>
<DetailItem
label={<T id={'vendor.drawer.label.website'} />}
children={defaultTo(vendor?.website, '--')}
/>
<DetailItem
label={<T id={'vendor.drawer.label.opening_balance'} />}
children={vendor?.formatted_opening_balance}
/>
<DetailItem
label={<T id={'vendor.drawer.label.opening_balance_at'} />}
children={vendor?.formatted_opening_balance_at}
/>
<DetailItem
label={<T id={'vendor.drawer.label.currency'} />}
children={vendor?.currency_code}
/>
</DetailsMenu>
</div>
);
}

View File

@@ -0,0 +1,30 @@
import React from 'react';
import { Drawer, DrawerSuspense } from 'components';
import withDrawers from 'containers/Drawer/withDrawers';
import { compose } from 'utils';
const VendorDetailsDrawerContent = React.lazy(() =>
import('./VendorDetailsDrawerContent'),
);
/**
* Vendor details drawer.
*/
function VendorDetailsDrawer({
name,
// #withDrawer
isOpen,
payload: { vendorId },
}) {
return (
<Drawer isOpen={isOpen} name={name} size={'750px'}>
<DrawerSuspense>
<VendorDetailsDrawerContent vendorId={vendorId} />
</DrawerSuspense>
</Drawer>
);
}
export default compose(withDrawers())(VendorDetailsDrawer);

View File

@@ -83,12 +83,12 @@ function VendorsTable({
// Handle view detail item.
const handleViewDetailVendor = ({ id }) => {
openDrawer('contact-detail-drawer', { contactId: id });
openDrawer('vendor-details-drawer', { vendorId: id });
};
// Handle cell click.
const handleCellClick = (cell, event) => {
openDrawer('contact-detail-drawer', { contactId: cell.row.original.id });
openDrawer('vendor-details-drawer', { vendorId: cell.row.original.id });
};
// Handle fetch data once the page index, size or sort by of the table change.

View File

@@ -3,20 +3,33 @@ import intl from 'react-intl-universal';
import { RESOURCES_TYPES } from '../../common/resourcesTypes';
import withDrawerActions from '../Drawer/withDrawerActions';
function VendorUniversalSearchSelectComponent({ resourceType, resourceId }) {
/**
* Vendor univesal search item select action.
*/
function VendorUniversalSearchSelectComponent({
resourceType,
resourceId,
onAction,
// #withDrawerActions
openDrawer,
}) {
if (resourceType === RESOURCES_TYPES.VENDOR) {
openDrawer('vendor-details-drawer', { vendorId: resourceId });
onAction && onAction();
}
return null;
}
const VendorUniversalSearchSelectAction = withDrawerActions(
VendorUniversalSearchSelectComponent
VendorUniversalSearchSelectComponent,
);
/**
* Transformes vendor resource item to search.
*/
const vendorToSearch = (contact) => ({
id: contact.id,
text: contact.display_name,
label: contact.balance > 0 ? contact.formatted_balance + '' : '',
reference: contact,

View File

@@ -1250,5 +1250,36 @@
"dashboard.subscription_msg.period_over": "Subscription period is over",
"inventory_adjustment.details_drawer.title": "Inventory adjustment details",
"setup.organization.location": "Location",
"preferences.general.success_message": "The general preferences has been saved."
"preferences.general.success_message": "The general preferences has been saved.",
"customer.drawer.action.new_invoice": "New invoice",
"customer.drawer.action.new_estimate": "New estimate",
"customer.drawer.action.new_payment": "New payment",
"customer.drawer.action.new_receipt": "New receipt",
"customer.drawer.action.new_transaction": "New transaction",
"customer.drawer.label.outstanding_receivable": "Outstanding receivable",
"customer.drawer.label.customer_name": "Customer name",
"customer.drawer.label.customer_type": "Customer type",
"customer.drawer.label.unused_credits": "Unused Credits",
"customer.drawer.label.company_name": "Company name",
"customer.drawer.label.email": "Email",
"customer.drawer.label.phone_number": "Phone number",
"customer.drawer.label.website": "Website",
"customer.drawer.label.opening_balance": "Opening balance",
"customer.drawer.label.opening_balance_at": "Opening balance at",
"customer.drawer.label.currency": "Currency code",
"vendor.drawer.label.outstanding_payable": "Outstanding payable",
"vendor.drawer.label.vendor": "Vendor name",
"vendor.drawer.label.vendor_type": "Vendor type",
"vendor.drawer.label.unused_credits": "Unused Credits",
"vendor.drawer.label.company_name": "Company name",
"vendor.drawer.label.phone_number": "Phone number",
"vendor.drawer.label.website": "Website",
"vendor.drawer.label.opening_balance": "Opening balance",
"vendor.drawer.label.opening_balance_at": "Opening balance at",
"vendor.drawer.label.currency": "Currency",
"vendor.drawer.action.edit_vendor": "Edit vendor",
"vendor.drawer.action.delete": "Delete",
"vendor.drawer.action.new_transaction": "New transaction",
"vendor.drawer.action.new_payment": "New payment",
"vendor.drawer.action.new_invoice": "New purchase invoice"
}

View File

@@ -202,7 +202,7 @@ export default class VendorsService {
* @param {number} vendorId
*/
public async getVendor(tenantId: number, vendorId: number) {
const vendor = this.contactService.getContact(tenantId, vendorId, 'vendor');
const vendor = await this.contactService.getContact(tenantId, vendorId, 'vendor');
return this.vendorTransformer.transform(vendor);
}