Back to Thymeleaf Templates
THYMELEAFHTMLBillingv1.0.0beginnerwatermark30m expiryROLE_REPORT_ADMIN

Print-Ready A4 Invoice for Thymeleaf

Print-optimised A4 invoice: 14pt base font, @media print CSS, page-break controls and a browser Print button. Watermarked and UUID-protected.

invoicebillinghtmlprintthymeleaf

Package metadata

Template file

classpath:/reports/templates/invoice-thymeleaf-print.html

File-name pattern

invoice-${invoiceNumber}-print.html

Provider module

report-boot-thymeleaf

Template type

.html

What's inside the package

  • InvoiceThymeleafPrintReportDto.java
  • InvoiceItemDto.java
  • invoice-thymeleaf-print.html

Annotations used

Every annotation declared on the DTO, with a paste-ready example.

AnnotationDescription
@ReportTemplate

Template identity and HTML output.

@ReportTemplate(code = "invoice-thymeleaf-print", templateFile = "classpath:/reports/templates/invoice-thymeleaf-print.html", output = ReportOutput.HTML)
@ReportEngineType

Selects the Thymeleaf renderer.

@ReportEngineType(ReportEngine.THYMELEAF)
@ReportSecured

Watermark + 30 minute download expiry.

@ReportSecured(watermark = true, expiryMinutes = 30)
@ReportAccess

Required role for generate / download.

@ReportAccess(role = "ROLE_REPORT_ADMIN")
@ReportField

Exposes a value to the Thymeleaf context.

@ReportField("invoiceNumber")
@ReportTable

Iterable source for the printed item table.

@ReportTable("items")

Field contract

Template keys ↔ DTO fields. Use this when designing or editing the underlying template file.

Template keySourceTypeRequired
invoiceNumber@ReportFieldStringYes
customerName@ReportFieldStringYes
invoiceDate@ReportFieldLocalDateNo
totalAmount@ReportFieldBigDecimalNo
items@ReportTableList<InvoiceItemDto>No
items.itemNamerow @ReportFieldStringNo
items.quantityrow @ReportFieldIntegerNo
items.unitPricerow @ReportFieldBigDecimalNo
items.totalrow @ReportFieldBigDecimalNo

Ready-to-use DTO

ThymeleafPrintReadyInvoiceHtml.java
@ReportTemplate(
    code = "invoice-thymeleaf-print",
    title = "Invoice (Thymeleaf Print-Ready)",
    templateFile = "classpath:/reports/templates/invoice-thymeleaf-print.html",
    output = ReportOutput.HTML
)
@ReportEngineType(ReportEngine.THYMELEAF)
@ReportSecured(watermark = true, expiryMinutes = 30)
@ReportFileName("invoice-${invoiceNumber}-print.html")
@ReportAccess(role = "ROLE_REPORT_ADMIN")
@ReportTitle("Print-Ready Invoice Report")
@ReportDescription("A4 print-optimised invoice. 14pt base font, @media print CSS, page-break controls and a browser Print button.")
@ReportVersion("1.0.0")
@ReportCategory("Billing")
public class InvoiceThymeleafPrintReportDto {

    @ReportField("invoiceNumber") @ReportRequired
    private String invoiceNumber;

    @ReportField("customerName")  @ReportRequired
    private String customerName;

    @ReportField("invoiceDate") @ReportDateFormat("yyyy-MM-dd")
    private LocalDate invoiceDate;

    @ReportField("totalAmount")
    @ReportFormat(pattern = "#,##0.00") @ReportCurrency("USD") @ReportLocale("en_US")
    private BigDecimal totalAmount;

    @ReportTable("items")
    private List<InvoiceItemDto> items;
}

public class InvoiceItemDto {

    @ReportField("itemName")  private String itemName;
    @ReportField("quantity")  private Integer quantity;
    @ReportField("unitPrice") private BigDecimal unitPrice;
    @ReportField("total")     private BigDecimal total;

    // getters / setters
}

Controller example

Standard generate + download flow. Returns a JSON body with the report-order UUID and a download URL.

ReportController.java
@RestController
@RequestMapping("/api/reports/thymeleaf/invoice")
public class ThymeleafInvoiceReportController {

    private final ReportService reportService;

    public ThymeleafInvoiceReportController(ReportService reportService) {
        this.reportService = reportService;
    }

    @PostMapping
    public ResponseEntity<Map<String, Object>> generate(@RequestBody InvoiceThymeleafPrintReportDto dto) {
        GeneratedReport report = reportService.generate(dto);

        String url = ServletUriComponentsBuilder.fromCurrentContextPath()
                .path("/api/reports/thymeleaf/invoice/")
                .path(report.getReportOrderUuid().toString())
                .path("/download")
                .toUriString();

        return ResponseEntity.status(HttpStatus.CREATED)
                .body(Map.of(
                    "reportOrderUuid", report.getReportOrderUuid(),
                    "fileName",        report.getFileName(),
                    "contentType",     report.getContentType(),
                    "generatedAt",     report.getGeneratedAt(),
                    "downloadUrl",     url
                ));
    }

    @GetMapping("/{uuid}/download")
    public ResponseEntity<byte[]> download(@PathVariable UUID uuid) {
        GeneratedReport report = reportService.download(uuid);
        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION,
                        "attachment; filename=\"" + report.getFileName() + "\"")
                .contentType(MediaType.parseMediaType(report.getContentType()))
                .body(report.getContent());
    }
}
// File extension for this provider: .html

Sample request

request.json
{
  "invoiceNumber": "INV-1001",
  "customerName": "ACME Corp",
  "invoiceDate": "2026-05-31",
  "totalAmount": 1200.50,
  "items": [
    { "itemName": "Implementation package", "quantity": 1, "unitPrice": 950.00, "total": 950.00 },
    { "itemName": "Support hours",          "quantity": 5, "unitPrice": 50.10,  "total": 250.50 }
  ]
}

Security notes

  • Downloads are served by report-order UUID, never by file path.
  • Expiry is enforced after 30 minutes (@ReportSecured).
  • Access requires role ROLE_REPORT_ADMIN (@ReportAccess).
  • Watermark metadata is applied at render time (@ReportSecured(watermark = true)).

AI installer prompt

Paste this prompt into Cursor, Copilot Chat or any IDE assistant. It will add dependencies, copy the DTO + template, register the controller and respect the security policy declared on the DTO. Each marketplace package ships its own curated prompt.

ai-installer.prompt
You are a Report-Boot assistant embedded in the developer's IDE.

Goal: integrate the "InvoiceThymeleafPrintReportDto" template into the user's Spring Boot project.

Steps:
1. Confirm Java 17+ and Spring Boot 3.x are present.
2. Add Maven dependencies:
   - com.reportboot:report-boot-spring-boot-starter:0.1.0-MVP
   - com.reportboot:report-boot-thymeleaf:0.1.0-MVP
   - the matching third-party engine dependency (the user is responsible for its license).
3. Copy invoice-thymeleaf-print.html into src/main/resources/reports/templates/.
4. Copy InvoiceThymeleafPrintReportDto.java and InvoiceItemDto.java into the user's DTO package and adjust the package declaration.
5. Inject ReportService and call reportService.generate(dto) then expose a download endpoint by UUID.
6. Surface the secured download URL and respect the expiry / role declared by the @ReportSecured and @ReportAccess annotations.
7. Verify with a smoke test POST using the provided sample JSON.

Output a concise change-list and the exact files to create or modify. Do not invent annotations; only use the ones declared on the DTO.