fix: printing sale receipts

This commit is contained in:
Ahmed Bouhuolia
2025-11-25 23:46:41 +02:00
parent 234b1804b3
commit cd4816aa3b
6 changed files with 48 additions and 23 deletions

View File

@@ -1,3 +1,4 @@
import { Response } from 'express';
import {
ApiTags,
ApiOperation,
@@ -11,10 +12,12 @@ import {
Controller,
Delete,
Get,
Headers,
Param,
Post,
Put,
Query,
Res,
} from '@nestjs/common';
import { CreditNoteApplication } from './CreditNoteApplication.service';
import { ICreditNotesQueryDTO } from './types/CreditNotes.types';
@@ -26,6 +29,7 @@ import {
BulkDeleteDto,
ValidateBulkDeleteResponseDto,
} from '@/common/dtos/BulkDelete.dto';
import { AcceptType } from '@/constants/accept-type';
@Controller('credit-notes')
@ApiTags('Credit Notes')
@@ -65,8 +69,26 @@ export class CreditNotesController {
},
})
@ApiResponse({ status: 404, description: 'Credit note not found' })
getCreditNote(@Param('id') creditNoteId: number) {
return this.creditNoteApplication.getCreditNote(creditNoteId);
async getCreditNote(
@Param('id') creditNoteId: number,
@Headers('accept') acceptHeader: string,
@Res({ passthrough: true }) res: Response,
) {
if (acceptHeader.includes(AcceptType.ApplicationPdf)) {
const [pdfContent, filename] =
await this.creditNoteApplication.getCreditNotePdf(creditNoteId);
res.set({
'Content-Type': 'application/pdf',
'Content-Length': pdfContent.length,
'Content-Disposition': `attachment; filename="${filename}"`,
});
res.status(200).send(pdfContent);
} else {
const creditNote =
await this.creditNoteApplication.getCreditNote(creditNoteId);
return creditNote;
}
}
@Get()
@@ -144,13 +166,10 @@ export class CreditNotesController {
status: 200,
description: 'Credit notes deleted successfully',
})
bulkDeleteCreditNotes(
@Body() bulkDeleteDto: BulkDeleteDto,
): Promise<void> {
return this.creditNoteApplication.bulkDeleteCreditNotes(
bulkDeleteDto.ids,
{ skipUndeletable: bulkDeleteDto.skipUndeletable ?? false },
);
bulkDeleteCreditNotes(@Body() bulkDeleteDto: BulkDeleteDto): Promise<void> {
return this.creditNoteApplication.bulkDeleteCreditNotes(bulkDeleteDto.ids, {
skipUndeletable: bulkDeleteDto.skipUndeletable ?? false,
});
}
@Delete(':id')

View File

@@ -1,3 +1,4 @@
import { Response } from 'express';
import {
ApiExtraModels,
ApiOperation,
@@ -17,6 +18,7 @@ import {
Post,
Put,
Query,
Res,
} from '@nestjs/common';
import { PaymentReceivesApplication } from './PaymentReceived.application';
import {
@@ -225,11 +227,18 @@ export class PaymentReceivesController {
public async getPaymentReceive(
@Param('id', ParseIntPipe) paymentReceiveId: number,
@Headers('accept') acceptHeader: string,
@Res({ passthrough: true }) res: Response,
) {
if (acceptHeader.includes(AcceptType.ApplicationPdf)) {
return this.paymentReceivesApplication.getPaymentReceivePdf(
const [pdfContent, filename] = await this.paymentReceivesApplication.getPaymentReceivePdf(
paymentReceiveId,
);
res.set({
'Content-Type': 'application/pdf',
'Content-Length': pdfContent.length,
'Content-Disposition': `attachment; filename="${filename}"`,
});
res.send(pdfContent);
} else if (acceptHeader.includes(AcceptType.ApplicationTextHtml)) {
const htmlContent =
await this.paymentReceivesApplication.getPaymentReceivedHtml(

View File

@@ -318,7 +318,7 @@ export class SaleEstimatesController {
@Res({ passthrough: true }) res: Response,
) {
if (acceptHeader.includes(AcceptType.ApplicationPdf)) {
const pdfContent =
const [pdfContent] =
await this.saleEstimatesApplication.getSaleEstimatePdf(estimateId);
res.set({

View File

@@ -26,7 +26,7 @@ export class GetSaleEstimatePdf {
@Inject(SaleEstimate.name)
private readonly saleEstimateModel: TenantModelProxy<typeof SaleEstimate>,
) {}
) { }
/**
* Retrieve sale estimate html content.
@@ -50,9 +50,9 @@ export class GetSaleEstimatePdf {
// Retrieves the sale estimate html.
const htmlContent = await this.saleEstimateHtml(saleEstimateId);
const content =
const buffer =
await this.chromiumlyTenancy.convertHtmlContent(htmlContent);
const eventPayload = { saleEstimateId };
// Triggers the `onSaleEstimatePdfViewed` event.
@@ -60,7 +60,7 @@ export class GetSaleEstimatePdf {
events.saleEstimate.onPdfViewed,
eventPayload,
);
return [content, filename];
return [buffer, filename];
}
/**

View File

@@ -82,9 +82,7 @@ export class SaleInvoicesController {
status: 200,
description: 'Sale invoices deleted successfully',
})
bulkDeleteSaleInvoices(
@Body() bulkDeleteDto: BulkDeleteDto,
): Promise<void> {
bulkDeleteSaleInvoices(@Body() bulkDeleteDto: BulkDeleteDto): Promise<void> {
return this.saleInvoiceApplication.bulkDeleteSaleInvoices(
bulkDeleteDto.ids,
{ skipUndeletable: bulkDeleteDto.skipUndeletable ?? false },
@@ -212,7 +210,8 @@ export class SaleInvoicesController {
@Res({ passthrough: true }) res: Response,
) {
if (acceptHeader.includes(AcceptType.ApplicationPdf)) {
const pdfContent = await this.saleInvoiceApplication.saleInvoicePdf(id);
const [pdfContent, filename] =
await this.saleInvoiceApplication.saleInvoicePdf(id);
res.set({
'Content-Type': 'application/pdf',

View File

@@ -74,9 +74,7 @@ export class SaleReceiptsController {
status: 200,
description: 'Sale receipts deleted successfully',
})
bulkDeleteSaleReceipts(
@Body() bulkDeleteDto: BulkDeleteDto,
): Promise<void> {
bulkDeleteSaleReceipts(@Body() bulkDeleteDto: BulkDeleteDto): Promise<void> {
return this.saleReceiptApplication.bulkDeleteSaleReceipts(
bulkDeleteDto.ids,
{ skipUndeletable: bulkDeleteDto.skipUndeletable ?? false },
@@ -165,7 +163,7 @@ export class SaleReceiptsController {
@Res({ passthrough: true }) res: Response,
) {
if (acceptHeader.includes(AcceptType.ApplicationPdf)) {
const pdfContent =
const [pdfContent] =
await this.saleReceiptApplication.getSaleReceiptPdf(id);
res.set({