diff --git a/apps/edr-freight-api/src/modules/billing/documents/pdf-render.service.ts b/apps/edr-freight-api/src/modules/billing/documents/pdf-render.service.ts index 21676c160..3767637a7 100644 --- a/apps/edr-freight-api/src/modules/billing/documents/pdf-render.service.ts +++ b/apps/edr-freight-api/src/modules/billing/documents/pdf-render.service.ts @@ -84,7 +84,13 @@ export class PdfRenderService { const page = await browser.newPage(); const thermal = opts.thermal ?? false; const viewportWidth = thermal ? Math.round((THERMAL_PAGE_WIDTH_MM / 25.4) * 96) : 794; - await page.setViewport({ width: viewportWidth, height: 1123, deviceScaleFactor: 1 }); + // Thermal viewport height is deliberately tiny (not a real page height at all): scrollHeight + // is defined as the LARGER of the content's height and the viewport's own height, so a + // receipt shorter than the viewport would otherwise report the viewport height back, not + // its true content height — a real page-length trailing blank space bug, not theoretical + // (confirmed by actually rendering one). A short viewport forces content to overflow it, + // so scrollHeight always reflects the content, never the viewport. + await page.setViewport({ width: viewportWidth, height: thermal ? 100 : 1123, deviceScaleFactor: 1 }); await page.setContent(preparedHtml, { waitUntil: "load", timeout: 60_000 }); await page.emulateMediaType("print"); await new Promise((resolve) => setTimeout(resolve, 250)); @@ -154,7 +160,7 @@ export class PdfRenderService { // browser context regardless, same as the closure form would be. const scrollPx = (await page.evaluate("document.documentElement.scrollHeight")) as number; const contentMm = (scrollPx / 96) * 25.4 + THERMAL_MARGIN_MM * 2 + THERMAL_FEED_MM; - return Math.min(THERMAL_MAX_HEIGHT_MM, contentMm); + return Math.min(THERMAL_MAX_HEIGHT_MM, Math.round(contentMm * 100) / 100); } private injectPdfPrintStyles(html: string): string {