import { Controller, Get, Param, ParseUUIDPipe, Query, Res, } from "@nestjs/common"; import { ApiBearerAuth, ApiOperation, ApiTags } from "@nestjs/swagger"; import type { Response } from "express"; import { BookingView } from "../../common/booking-guards"; import { BillingService } from "./billing.service"; import { FilterInvoiceDto } from "./dto/filter-invoice.dto"; @ApiTags("billing") @Controller("billing") @BookingView() @ApiBearerAuth() export class BillingController { constructor(private readonly billingService: BillingService) {} @Get("invoices") @ApiOperation({ summary: "List invoices (paginated, filterable by company/status/search)", }) findAll(@Query() query: FilterInvoiceDto) { return this.billingService.findAllPaginated(query); } @Get("invoices/:id") @ApiOperation({ summary: "Get an invoice with its line items" }) findById(@Param("id", ParseUUIDPipe) id: string) { return this.billingService.findById(id); } @Get("invoices/:id/document") @ApiOperation({ summary: "Download the sealed invoice PDF" }) async document(@Param("id", ParseUUIDPipe) id: string, @Res() res: Response) { const { filename, buffer } = await this.billingService.document(id); sendPdf(res, filename, buffer); } @Get("invoices/:id/receipt") @ApiOperation({ summary: "Download the sealed payment receipt PDF" }) async receipt(@Param("id", ParseUUIDPipe) id: string, @Res() res: Response) { const { filename, buffer } = await this.billingService.receipt(id); sendPdf(res, filename, buffer); } } /** Stream a generated PDF as a file download. */ export function sendPdf(res: Response, filename: string, buffer: Buffer): void { res.setHeader("Content-Type", "application/pdf"); res.setHeader("Content-Disposition", `attachment; filename="${filename}"`); res.setHeader("Content-Length", buffer.length); res.send(buffer); }