Merge pull request #740 from bigcapitalhq/fix-invoice-preview

feat: getting invoice preview on send mail view
This commit is contained in:
Ahmed Bouhuolia
2024-11-05 22:31:40 +02:00
committed by GitHub
5 changed files with 102 additions and 17 deletions

View File

@@ -449,6 +449,7 @@ export default class SaleInvoicesController extends BaseController {
const acceptType = accept.types([
ACCEPT_TYPE.APPLICATION_JSON,
ACCEPT_TYPE.APPLICATION_PDF,
ACCEPT_TYPE.APPLICATION_TEXT_HTML,
]);
// Retrieves invoice in PDF format.
if (ACCEPT_TYPE.APPLICATION_PDF === acceptType) {
@@ -463,7 +464,13 @@ export default class SaleInvoicesController extends BaseController {
'Content-Disposition': `attachment; filename="${filename}"`,
});
res.send(pdfContent);
// Retrieves invoice in json format.
// Retrieves invoice in html json format.
} else if (ACCEPT_TYPE.APPLICATION_TEXT_HTML === acceptType) {
const htmlContent = await this.saleInvoiceApplication.saleInvoiceHtml(
tenantId,
saleInvoiceId
);
return res.status(200).send({ htmlContent });
} else {
const saleInvoice = await this.saleInvoiceApplication.getSaleInvoice(
tenantId,

View File

@@ -31,6 +31,25 @@ export class SaleInvoicePdf {
@Inject()
private eventPublisher: EventPublisher;
/**
* Retrieve sale invoice html content.
* @param {number} tenantId - Tenant Id.
* @param {ISaleInvoice} saleInvoice -
* @returns {Promise<string>}
*/
public async saleInvoiceHtml(
tenantId: number,
invoiceId: number
): Promise<string> {
const brandingAttributes = await this.getInvoiceBrandingAttributes(
tenantId,
invoiceId
);
return renderInvoicePaperTemplateHtml({
...brandingAttributes,
});
}
/**
* Retrieve sale invoice pdf content.
* @param {number} tenantId - Tenant Id.
@@ -43,13 +62,8 @@ export class SaleInvoicePdf {
): Promise<[Buffer, string]> {
const filename = await this.getInvoicePdfFilename(tenantId, invoiceId);
const brandingAttributes = await this.getInvoiceBrandingAttributes(
tenantId,
invoiceId
);
const htmlContent = renderInvoicePaperTemplateHtml({
...brandingAttributes,
});
const htmlContent = await this.saleInvoiceHtml(tenantId, invoiceId);
// Converts the given html content to pdf document.
const buffer = await this.chromiumlyTenancy.convertHtmlContent(
tenantId,

View File

@@ -273,6 +273,19 @@ export class SaleInvoiceApplication {
return this.pdfSaleInvoiceService.saleInvoicePdf(tenantId, saleInvoiceId);
}
/**
* Retrieves the html content of the given sale invoice.
* @param {number} tenantId
* @param {number} saleInvoiceId
* @returns {Promise<string>}
*/
public saleInvoiceHtml(
tenantId: number,
saleInvoiceId: number
): Promise<string> {
return this.pdfSaleInvoiceService.saleInvoiceHtml(tenantId, saleInvoiceId);
}
/**
*
* @param {number} tenantId

View File

@@ -1,18 +1,41 @@
import { Spinner } from '@blueprintjs/core';
import { css } from '@emotion/css';
import { Box } from '@/components';
import { InvoicePaperTemplate } from '../InvoiceCustomize/InvoicePaperTemplate';
import { Stack } from '@/components';
import { InvoiceSendMailPreviewWithHeader } from './InvoiceSendMailHeaderPreview';
import { useInvoiceHtml } from '@/hooks/query';
import { useDrawerContext } from '@/components/Drawer/DrawerProvider';
export function InvoiceSendPdfPreviewConnected() {
return (
<InvoiceSendMailPreviewWithHeader>
<Box px={4} py={6}>
<InvoicePaperTemplate
className={css`
margin: 0 auto;
`}
/>
</Box>
<Stack px={4} py={6}>
<InvoiceSendPdfPreviewIframe />
</Stack>
</InvoiceSendMailPreviewWithHeader>
);
}
function InvoiceSendPdfPreviewIframe() {
const { payload } = useDrawerContext();
const { data, isLoading } = useInvoiceHtml(payload?.invoiceId);
if (isLoading && data) {
return <Spinner size={20} />;
}
const iframeSrcDoc = data?.htmlContent;
return (
<iframe
title={'invoice-pdf-preview'}
srcDoc={iframeSrcDoc}
className={css`
height: 1123px;
width: 794px;
border: 0;
border-radius: 5px;
box-shadow: 0 10px 15px rgba(0, 0, 0, 0.05);
margin: 0 auto;
`}
/>
);
}

View File

@@ -201,6 +201,34 @@ export function usePdfInvoice(invoiceId) {
});
}
interface GetInvoiceHtmlResponse {
htmlContent: string;
}
/**
* Retrieves the invoice html content.
* @param {number} invoiceId
* @param {UseQueryOptions<GetInvoiceHtmlResponse>} options
* @returns {UseQueryResult<GetInvoiceHtmlResponse>}
*/
export const useInvoiceHtml = (
invoiceId: number,
options?: UseQueryOptions<GetInvoiceHtmlResponse>,
): UseQueryResult<GetInvoiceHtmlResponse> => {
const apiRequest = useApiRequest();
return useQuery<GetInvoiceHtmlResponse>(
['SALE_INVOICE_HTML', invoiceId],
() =>
apiRequest
.get(`sales/invoices/${invoiceId}`, {
headers: {
Accept: 'application/json+html',
},
})
.then((res) => transformToCamelCase(res.data)),
);
};
/**
* Retrieve due invoices of the given customer id.
* @param {number} customerId - Customer id.