Basic Invoice PDF for BIRT
Billing invoice package rendered by the optional BIRT provider. Uses a .rptdesign template with a UUID-protected download flow.
Package metadata
Template file
classpath:/reports/templates/invoice-basic.rptdesign
File-name pattern
invoice-${invoiceNumber}-birt.pdf
Provider module
report-boot-birt
Template type
.rptdesign
What's inside the package
- InvoiceBirtReportDto.java
- InvoiceItemDto.java
- invoice-basic.rptdesign
Annotations used
Every annotation declared on the DTO, with a paste-ready example.
| Annotation | Description |
|---|---|
| @ReportTemplate | Template identity and PDF output. @ReportTemplate(code = "invoice-basic-birt", templateFile = "classpath:/reports/templates/invoice-basic.rptdesign", output = ReportOutput.PDF) |
| @ReportEngineType | Selects the BIRT renderer. @ReportEngineType(ReportEngine.BIRT) |
| @ReportSecured | 30-minute download expiry. @ReportSecured(watermark = false, expiryMinutes = 30) |
| @ReportAccess | Required role for generate / download. @ReportAccess(role = "ROLE_REPORT_ADMIN") |
| @ReportField | Scalar BIRT parameter. @ReportField("invoiceNumber") |
| @ReportTable | BIRT data set for line items. @ReportTable("items") |
Field contract
Template keys ↔ DTO fields. Use this when designing or editing the underlying template file.
| Template key | Source | Type | Required |
|---|---|---|---|
| invoiceNumber | @ReportField | String | Yes |
| customerName | @ReportField | String | Yes |
| invoiceDate | @ReportField | LocalDate | No |
| totalAmount | @ReportField | BigDecimal | No |
| items | @ReportTable | List<InvoiceItemDto> | No |
| items.itemName | row @ReportField | String | No |
| items.quantity | row @ReportField | Integer | No |
| items.unitPrice | row @ReportField | BigDecimal | No |
| items.total | row @ReportField | BigDecimal | No |
Ready-to-use DTO
@ReportTemplate(
code = "invoice-basic-birt",
title = "Basic Invoice BIRT",
templateFile = "classpath:/reports/templates/invoice-basic.rptdesign",
output = ReportOutput.PDF
)
@ReportEngineType(ReportEngine.BIRT)
@ReportSecured(watermark = false, expiryMinutes = 30)
@ReportFileName("invoice-${invoiceNumber}-birt.pdf")
@ReportAccess(role = "ROLE_REPORT_ADMIN")
@ReportTitle("Invoice BIRT Report")
@ReportDescription("Demo invoice report rendered by the optional BIRT provider.")
@ReportVersion("1.0.0")
@ReportCategory("Billing")
public class InvoiceBirtReportDto {
@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")
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.
@RestController
@RequestMapping("/api/reports/birt/invoice")
public class BirtInvoiceReportController {
private final ReportService reportService;
public BirtInvoiceReportController(ReportService reportService) {
this.reportService = reportService;
}
@PostMapping
public ResponseEntity<Map<String, Object>> generate(@RequestBody InvoiceBirtReportDto dto) {
GeneratedReport report = reportService.generate(dto);
String url = ServletUriComponentsBuilder.fromCurrentContextPath()
.path("/api/reports/birt/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: .rptdesignSample request
{
"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).
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.
You are a Report-Boot assistant embedded in the developer's IDE.
Goal: integrate the "InvoiceBirtReportDto" 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-birt:0.1.0-MVP
- the matching third-party engine dependency (the user is responsible for its license).
3. Copy invoice-basic.rptdesign into src/main/resources/reports/templates/.
4. Copy InvoiceBirtReportDto.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.