From eb6c1055fde35982155f0958550740015f8795c5 Mon Sep 17 00:00:00 2001 From: igorcampos-dev Date: Sun, 31 Aug 2025 19:16:04 -0300 Subject: [PATCH] feat(spring-jasper-example): implement bill report generation with JasperReports and add related configurations --- spring-jasper-example/README.md | 5 +- .../com/io/example/base/JasperReader.java | 37 ++++ ...Controller.java => ClientsController.java} | 8 +- .../service/ClientsReportDevServiceImpl.java | 26 +++ .../ClientsReportLocalServiceImpl.java | 25 +++ .../service/ClientsReportService.java | 5 + .../clientList/service/ReportDevService.java | 49 ----- .../service/ReportLocalService.java | 39 ---- .../clientList/service/ReportService.java | 5 - .../controller/BillController.java | 29 +++ .../io/example/dataUsageBill/dto/BillDto.java | 37 ++++ .../service/BillReportDevServiceImpl.java | 46 +++++ .../service/BillReportLocalServiceImpl.java | 46 +++++ .../service/BillReportService.java | 5 + .../main/resources/application-bill-dev.yml | 7 + .../main/resources/application-bill-local.yml | 7 + .../application-client-list-local.yml | 2 +- .../resources/reports/bill-template.jasper | Bin 0 -> 27295 bytes .../resources/reports/bill-template.jrxml | 182 ++++++++++++++++++ .../reports/client-list-template.jasper | Bin 0 -> 13520 bytes ...-list.jrxml => client-list-template.jrxml} | 0 21 files changed, 460 insertions(+), 100 deletions(-) create mode 100644 spring-jasper-example/src/main/java/com/io/example/base/JasperReader.java rename spring-jasper-example/src/main/java/com/io/example/clientList/controller/{ReportController.java => ClientsController.java} (78%) create mode 100644 spring-jasper-example/src/main/java/com/io/example/clientList/service/ClientsReportDevServiceImpl.java create mode 100644 spring-jasper-example/src/main/java/com/io/example/clientList/service/ClientsReportLocalServiceImpl.java create mode 100644 spring-jasper-example/src/main/java/com/io/example/clientList/service/ClientsReportService.java delete mode 100644 spring-jasper-example/src/main/java/com/io/example/clientList/service/ReportDevService.java delete mode 100644 spring-jasper-example/src/main/java/com/io/example/clientList/service/ReportLocalService.java delete mode 100644 spring-jasper-example/src/main/java/com/io/example/clientList/service/ReportService.java create mode 100644 spring-jasper-example/src/main/java/com/io/example/dataUsageBill/controller/BillController.java create mode 100644 spring-jasper-example/src/main/java/com/io/example/dataUsageBill/dto/BillDto.java create mode 100644 spring-jasper-example/src/main/java/com/io/example/dataUsageBill/service/BillReportDevServiceImpl.java create mode 100644 spring-jasper-example/src/main/java/com/io/example/dataUsageBill/service/BillReportLocalServiceImpl.java create mode 100644 spring-jasper-example/src/main/java/com/io/example/dataUsageBill/service/BillReportService.java create mode 100644 spring-jasper-example/src/main/resources/application-bill-dev.yml create mode 100644 spring-jasper-example/src/main/resources/application-bill-local.yml create mode 100644 spring-jasper-example/src/main/resources/reports/bill-template.jasper create mode 100644 spring-jasper-example/src/main/resources/reports/bill-template.jrxml create mode 100644 spring-jasper-example/src/main/resources/reports/client-list-template.jasper rename spring-jasper-example/src/main/resources/reports/{client-list.jrxml => client-list-template.jrxml} (100%) diff --git a/spring-jasper-example/README.md b/spring-jasper-example/README.md index 2956a49..e03d3fd 100644 --- a/spring-jasper-example/README.md +++ b/spring-jasper-example/README.md @@ -19,6 +19,7 @@ Includes loading `.jasper` templates, populating them with mock data, and export ## Profiles you can activate -- **client-list-dev** – Used in Docker, in the future, it will use pre-compiled `.jasper` files instead of `.jrxml`. Activates the internal module that generates a simple client report. +- **client-list-dev** – Used in Docker, Activates the internal module that generates a simple client report. - **client-list-local** – Used locally, activates the internal module that generates a simple client report and use `.jrxml`. - +- **bill-dev** – Used in Docker, Activates the internal module that generates a simple bill report. +- **bill-local** – Used locally, activates the internal module that generates a simple bill report and use `.jrxml`. diff --git a/spring-jasper-example/src/main/java/com/io/example/base/JasperReader.java b/spring-jasper-example/src/main/java/com/io/example/base/JasperReader.java new file mode 100644 index 0000000..8227a73 --- /dev/null +++ b/spring-jasper-example/src/main/java/com/io/example/base/JasperReader.java @@ -0,0 +1,37 @@ +package com.io.example.base; + +import net.sf.jasperreports.engine.*; +import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource; +import net.sf.jasperreports.engine.util.JRLoader; +import org.springframework.core.io.ClassPathResource; + +import java.io.InputStream; +import java.util.Collection; +import java.util.HashMap; + +public class JasperReader { + + public static byte[] exportReportJrxmlToPdf(Collection beanCollection, String path){ + try { + InputStream stream = new ClassPathResource(path).getInputStream(); + JasperReport jasperReport = JasperCompileManager.compileReport(stream); + JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(beanCollection); + JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, new HashMap<>(), dataSource); + return JasperExportManager.exportReportToPdf(jasperPrint); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static byte[] exportReportJasperToPdf(Collection beanCollection, String path){ + try (InputStream stream = new ClassPathResource(path).getInputStream()) { + JasperReport jasperReport = (JasperReport) JRLoader.loadObject(stream); + JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(beanCollection); + JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, new HashMap<>(), dataSource); + return JasperExportManager.exportReportToPdf(jasperPrint); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + +} diff --git a/spring-jasper-example/src/main/java/com/io/example/clientList/controller/ReportController.java b/spring-jasper-example/src/main/java/com/io/example/clientList/controller/ClientsController.java similarity index 78% rename from spring-jasper-example/src/main/java/com/io/example/clientList/controller/ReportController.java rename to spring-jasper-example/src/main/java/com/io/example/clientList/controller/ClientsController.java index 494a9fb..4abf9a9 100644 --- a/spring-jasper-example/src/main/java/com/io/example/clientList/controller/ReportController.java +++ b/spring-jasper-example/src/main/java/com/io/example/clientList/controller/ClientsController.java @@ -1,6 +1,6 @@ package com.io.example.clientList.controller; -import com.io.example.clientList.service.ReportService; +import com.io.example.clientList.service.ClientsReportService; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Profile; import org.springframework.http.HttpHeaders; @@ -12,13 +12,13 @@ @RestController @Profile({"client-list-dev", "client-list-local"}) @RequiredArgsConstructor -public class ReportController { +public class ClientsController { - private final ReportService reportService; + private final ClientsReportService clientsReportService; @GetMapping("/reports/clients") public ResponseEntity getClientsReport() { - byte[] pdf = this.reportService.generateClientReport(); + byte[] pdf = this.clientsReportService.generateClientsPdf(); return ResponseEntity.ok() .header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=clients.pdf") .contentType(MediaType.APPLICATION_PDF) diff --git a/spring-jasper-example/src/main/java/com/io/example/clientList/service/ClientsReportDevServiceImpl.java b/spring-jasper-example/src/main/java/com/io/example/clientList/service/ClientsReportDevServiceImpl.java new file mode 100644 index 0000000..e5dbaa7 --- /dev/null +++ b/spring-jasper-example/src/main/java/com/io/example/clientList/service/ClientsReportDevServiceImpl.java @@ -0,0 +1,26 @@ +package com.io.example.clientList.service; + +import com.io.example.clientList.dto.ClientDto; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; +import java.util.*; + +import static com.io.example.base.JasperReader.exportReportJasperToPdf; + +@Service +@Profile({"client-list-dev"}) +public class ClientsReportDevServiceImpl implements ClientsReportService { + + private static final List clients = Arrays.asList( + new ClientDto(1, "Alice", "Brazil"), + new ClientDto(2, "Bob", "USA"), + new ClientDto(3, "Carlos", "Spain") + ); + + @Override + public byte[] generateClientsPdf() { + return exportReportJasperToPdf(clients, "reports/client-list-template.jasper"); + } + + +} diff --git a/spring-jasper-example/src/main/java/com/io/example/clientList/service/ClientsReportLocalServiceImpl.java b/spring-jasper-example/src/main/java/com/io/example/clientList/service/ClientsReportLocalServiceImpl.java new file mode 100644 index 0000000..cbd5ac7 --- /dev/null +++ b/spring-jasper-example/src/main/java/com/io/example/clientList/service/ClientsReportLocalServiceImpl.java @@ -0,0 +1,25 @@ +package com.io.example.clientList.service; + +import com.io.example.clientList.dto.ClientDto; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; +import java.util.*; + +import static com.io.example.base.JasperReader.exportReportJrxmlToPdf; + +@Service +@Profile({"client-list-local"}) +public class ClientsReportLocalServiceImpl implements ClientsReportService { + + private static final List clients = Arrays.asList( + new ClientDto(1, "Alice", "Brazil"), + new ClientDto(2, "Bob", "USA"), + new ClientDto(3, "Carlos", "Spain") + ); + + @Override + public byte[] generateClientsPdf() { + return exportReportJrxmlToPdf(clients, "reports/client-list-template.jrxml"); + } + +} diff --git a/spring-jasper-example/src/main/java/com/io/example/clientList/service/ClientsReportService.java b/spring-jasper-example/src/main/java/com/io/example/clientList/service/ClientsReportService.java new file mode 100644 index 0000000..97260ca --- /dev/null +++ b/spring-jasper-example/src/main/java/com/io/example/clientList/service/ClientsReportService.java @@ -0,0 +1,5 @@ +package com.io.example.clientList.service; + +public interface ClientsReportService { + byte[] generateClientsPdf(); +} diff --git a/spring-jasper-example/src/main/java/com/io/example/clientList/service/ReportDevService.java b/spring-jasper-example/src/main/java/com/io/example/clientList/service/ReportDevService.java deleted file mode 100644 index af9d4e5..0000000 --- a/spring-jasper-example/src/main/java/com/io/example/clientList/service/ReportDevService.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.io.example.clientList.service; - -import com.io.example.clientList.dto.ClientDto; -import net.sf.jasperreports.engine.*; -import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource; -import org.springframework.context.annotation.Profile; -import org.springframework.core.io.ClassPathResource; -import org.springframework.stereotype.Service; - -import java.io.InputStream; -import java.util.*; - -@Service -@Profile({"client-list-dev"}) -public class ReportDevService implements ReportService { - - private static final List clients = Arrays.asList( - new ClientDto(1, "Alice", "Brazil"), - new ClientDto(2, "Bob", "USA"), - new ClientDto(3, "Carlos", "Spain") - ); - - @Override - public byte[] generateClientReport() { - return this.exportReportToPdf(); - } - - /* - * TODO: In the future, this should be migrated to use: - * - * InputStream stream = new ClassPathResource("reports/client-list.jasper").getInputStream(); - * JasperReport jasperReport = (JasperReport) JRLoader.loadObject(stream); - * - * This approach is the recommended way in production environments. - */ - - private byte[] exportReportToPdf(){ - try { - InputStream stream = new ClassPathResource("reports/client-list.jrxml").getInputStream(); - JasperReport jasperReport = JasperCompileManager.compileReport(stream); - JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(clients); - JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, new HashMap<>(), dataSource); - return JasperExportManager.exportReportToPdf(jasperPrint); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - -} diff --git a/spring-jasper-example/src/main/java/com/io/example/clientList/service/ReportLocalService.java b/spring-jasper-example/src/main/java/com/io/example/clientList/service/ReportLocalService.java deleted file mode 100644 index bf8b2ab..0000000 --- a/spring-jasper-example/src/main/java/com/io/example/clientList/service/ReportLocalService.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.io.example.clientList.service; - -import com.io.example.clientList.dto.ClientDto; -import net.sf.jasperreports.engine.*; -import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource; -import org.springframework.context.annotation.Profile; -import org.springframework.core.io.ClassPathResource; -import org.springframework.stereotype.Service; -import java.io.InputStream; -import java.util.*; - -@Service -@Profile({"client-list-local"}) -public class ReportLocalService implements ReportService { - - private static final List clients = Arrays.asList( - new ClientDto(1, "Alice", "Brazil"), - new ClientDto(2, "Bob", "USA"), - new ClientDto(3, "Carlos", "Spain") - ); - - @Override - public byte[] generateClientReport() { - return this.exportReportToPdf(); - } - - private byte[] exportReportToPdf(){ - try { - InputStream stream = new ClassPathResource("reports/client-list.jrxml").getInputStream(); - JasperReport jasperReport = JasperCompileManager.compileReport(stream); - JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(clients); - JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, new HashMap<>(), dataSource); - return JasperExportManager.exportReportToPdf(jasperPrint); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - -} diff --git a/spring-jasper-example/src/main/java/com/io/example/clientList/service/ReportService.java b/spring-jasper-example/src/main/java/com/io/example/clientList/service/ReportService.java deleted file mode 100644 index 31ce34d..0000000 --- a/spring-jasper-example/src/main/java/com/io/example/clientList/service/ReportService.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.io.example.clientList.service; - -public interface ReportService { - byte[] generateClientReport(); -} diff --git a/spring-jasper-example/src/main/java/com/io/example/dataUsageBill/controller/BillController.java b/spring-jasper-example/src/main/java/com/io/example/dataUsageBill/controller/BillController.java new file mode 100644 index 0000000..688e398 --- /dev/null +++ b/spring-jasper-example/src/main/java/com/io/example/dataUsageBill/controller/BillController.java @@ -0,0 +1,29 @@ +package com.io.example.dataUsageBill.controller; + +import com.io.example.clientList.service.ClientsReportService; +import com.io.example.dataUsageBill.service.BillReportService; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Profile; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@Profile({"bill-dev", "bill-local"}) +@RequiredArgsConstructor +public class BillController { + + private final BillReportService billReportService; + + @GetMapping("/reports/bill") + public ResponseEntity getBillData() { + byte[] pdf = this.billReportService.generateBillPdf(); + return ResponseEntity.ok() + .header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=bill.pdf") + .contentType(MediaType.APPLICATION_PDF) + .body(pdf); + } + +} diff --git a/spring-jasper-example/src/main/java/com/io/example/dataUsageBill/dto/BillDto.java b/spring-jasper-example/src/main/java/com/io/example/dataUsageBill/dto/BillDto.java new file mode 100644 index 0000000..ed1c042 --- /dev/null +++ b/spring-jasper-example/src/main/java/com/io/example/dataUsageBill/dto/BillDto.java @@ -0,0 +1,37 @@ +package com.io.example.dataUsageBill.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class BillDto { + private String orgName; + private String depName; + private String devName; + private String groupName; + private String dayStart; + private String dayEnd; + + private Integer dtoOM; + private Integer dtoON; + private Integer dtoOL; + private Integer dtoDL; + private Integer dtoDN; + private Integer dtoD; + + private Integer dtoOMamount; + private Integer dtoONamount; + private Integer dtoOLamount; + private Integer dtoDLamount; + private Integer dtoDNamount; + private Integer dtoDamount; + + private Integer totalHrs; + private Integer toltalAm; + +} diff --git a/spring-jasper-example/src/main/java/com/io/example/dataUsageBill/service/BillReportDevServiceImpl.java b/spring-jasper-example/src/main/java/com/io/example/dataUsageBill/service/BillReportDevServiceImpl.java new file mode 100644 index 0000000..864c6bd --- /dev/null +++ b/spring-jasper-example/src/main/java/com/io/example/dataUsageBill/service/BillReportDevServiceImpl.java @@ -0,0 +1,46 @@ +package com.io.example.dataUsageBill.service; + +import com.io.example.dataUsageBill.dto.BillDto; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +import java.util.List; + +import static com.io.example.base.JasperReader.exportReportJasperToPdf; + +@Service +@Profile({"bill-dev"}) +public class BillReportDevServiceImpl implements BillReportService { + + @Override + public byte[] generateBillPdf() { + return exportReportJasperToPdf(getBillDto(), "reports/bill-template.jasper"); + } + + private List getBillDto(){ + BillDto bill = BillDto.builder() + .orgName("My Organization") + .depName("IT Department") + .devName("Development Team") + .groupName("Network Group") + .dayStart("2025-08-01") + .dayEnd("2025-08-31") + .dtoOM(10) + .dtoON(5) + .dtoOL(3) + .dtoDL(7) + .dtoDN(2) + .dtoD(1) + .dtoOMamount(100) + .dtoONamount(50) + .dtoOLamount(30) + .dtoDLamount(70) + .dtoDNamount(20) + .dtoDamount(10) + .totalHrs(28) + .toltalAm(280) + .build(); + return List.of(bill); + } + +} diff --git a/spring-jasper-example/src/main/java/com/io/example/dataUsageBill/service/BillReportLocalServiceImpl.java b/spring-jasper-example/src/main/java/com/io/example/dataUsageBill/service/BillReportLocalServiceImpl.java new file mode 100644 index 0000000..49dac8a --- /dev/null +++ b/spring-jasper-example/src/main/java/com/io/example/dataUsageBill/service/BillReportLocalServiceImpl.java @@ -0,0 +1,46 @@ +package com.io.example.dataUsageBill.service; + +import com.io.example.dataUsageBill.dto.BillDto; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +import java.util.List; + +import static com.io.example.base.JasperReader.exportReportJrxmlToPdf; + +@Service +@Profile({"bill-local"}) +public class BillReportLocalServiceImpl implements BillReportService { + + @Override + public byte[] generateBillPdf() { + return exportReportJrxmlToPdf(getBillDto(), "reports/bill-template.jrxml"); + } + + private List getBillDto(){ + BillDto bill = BillDto.builder() + .orgName("My Organization") + .depName("IT Department") + .devName("Development Team") + .groupName("Network Group") + .dayStart("2025-08-01") + .dayEnd("2025-08-31") + .dtoOM(10) + .dtoON(5) + .dtoOL(3) + .dtoDL(7) + .dtoDN(2) + .dtoD(1) + .dtoOMamount(100) + .dtoONamount(50) + .dtoOLamount(30) + .dtoDLamount(70) + .dtoDNamount(20) + .dtoDamount(10) + .totalHrs(28) + .toltalAm(280) + .build(); + return List.of(bill); + } + +} diff --git a/spring-jasper-example/src/main/java/com/io/example/dataUsageBill/service/BillReportService.java b/spring-jasper-example/src/main/java/com/io/example/dataUsageBill/service/BillReportService.java new file mode 100644 index 0000000..f88db2b --- /dev/null +++ b/spring-jasper-example/src/main/java/com/io/example/dataUsageBill/service/BillReportService.java @@ -0,0 +1,5 @@ +package com.io.example.dataUsageBill.service; + +public interface BillReportService { + byte[] generateBillPdf(); +} diff --git a/spring-jasper-example/src/main/resources/application-bill-dev.yml b/spring-jasper-example/src/main/resources/application-bill-dev.yml new file mode 100644 index 0000000..769c151 --- /dev/null +++ b/spring-jasper-example/src/main/resources/application-bill-dev.yml @@ -0,0 +1,7 @@ +server: + port: ${SERVER_PORT:8084} + +spring: + + application: + name: spring-jasper-example-bill-dev \ No newline at end of file diff --git a/spring-jasper-example/src/main/resources/application-bill-local.yml b/spring-jasper-example/src/main/resources/application-bill-local.yml new file mode 100644 index 0000000..8db22d9 --- /dev/null +++ b/spring-jasper-example/src/main/resources/application-bill-local.yml @@ -0,0 +1,7 @@ +server: + port: ${SERVER_PORT:8083} + +spring: + + application: + name: spring-jasper-example-bill-local \ No newline at end of file diff --git a/spring-jasper-example/src/main/resources/application-client-list-local.yml b/spring-jasper-example/src/main/resources/application-client-list-local.yml index 872bdd1..ac6e66f 100644 --- a/spring-jasper-example/src/main/resources/application-client-list-local.yml +++ b/spring-jasper-example/src/main/resources/application-client-list-local.yml @@ -4,4 +4,4 @@ server: spring: application: - name: spring-jasper-exampleclient-list-local \ No newline at end of file + name: spring-jasper-example-client-list-local \ No newline at end of file diff --git a/spring-jasper-example/src/main/resources/reports/bill-template.jasper b/spring-jasper-example/src/main/resources/reports/bill-template.jasper new file mode 100644 index 0000000000000000000000000000000000000000..f1f57b84281eaaddd9d2835a5f9e978a03bf99f7 GIT binary patch literal 27295 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 literal 0 HcmV?d00001 diff --git a/spring-jasper-example/src/main/resources/reports/bill-template.jrxml b/spring-jasper-example/src/main/resources/reports/bill-template.jrxml new file mode 100644 index 0000000..bf688d2 --- /dev/null +++ b/spring-jasper-example/src/main/resources/reports/bill-template.jrxml @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <element kind="rectangle" uuid="50312856-42b0-43f4-9483-06d8fe503412" mode="Opaque" x="-1" y="56" width="329" height="100" forecolor="#D9D7E0" backcolor="#D9D7E0" radius="15"/> + <element kind="staticText" uuid="fbf42f07-8a0a-4f7f-a7d9-1b325c83670f" stretchType="ElementGroupHeight" x="60" y="10" width="90" height="40" fontSize="26.0" bold="true"> + <text><![CDATA[LOGO]]></text> + </element> + <element kind="staticText" uuid="8c715988-6da5-4761-a9b0-f04b284f39e7" x="240" y="-10" width="70" height="20" forecolor="#525252" fontSize="12.0" bold="true"> + <text><![CDATA[INVOICE]]></text> + <box leftPadding="10"/> + </element> + <element kind="staticText" uuid="3ee170a9-03ed-4539-bc81-4edd6ebfbc29" x="20" y="70" width="100" height="20"> + <text><![CDATA[Organization Name]]></text> + </element> + <element kind="staticText" uuid="c7dfbb91-16e7-4a72-b7dd-852c724ea867" x="20" y="90" width="100" height="20"> + <text><![CDATA[Department Name]]></text> + </element> + <element kind="staticText" uuid="267f032d-a98a-4177-b5b9-757dba3a7a27" x="20" y="110" width="100" height="20"> + <text><![CDATA[Devision Name]]></text> + </element> + <element kind="staticText" uuid="eb345a07-991c-4aba-9088-e71e38237921" x="20" y="130" width="100" height="20"> + <text><![CDATA[Group Name]]></text> + </element> + <element kind="staticText" uuid="0ea065e5-47b1-4a21-8189-172cc1a9fe8b" x="210" y="10" width="60" height="13"> + <text><![CDATA[Invoice Date:]]></text> + </element> + <element kind="textField" uuid="fed3f44e-c42d-4e85-8eb3-7a6d405e07ec" x="270" y="10" width="100" height="13" fontSize="10.0" pattern="MMMMM dd, yyyy"> + <expression><![CDATA[new java.util.Date()]]></expression> + </element> + <element kind="textField" uuid="70a5b8dc-2c16-413f-af39-93f36a8689b8" x="170" y="70" width="180" height="19"> + <expression><![CDATA[$F{orgName}]]></expression> + </element> + <element kind="textField" uuid="0e07e32e-62ef-40d9-ba1e-d5b1e757a2b5" x="170" y="90" width="180" height="21"> + <expression><![CDATA[$F{depName}]]></expression> + </element> + <element kind="textField" uuid="fb083231-e511-4c79-af82-4fa2549cba04" x="170" y="130" width="180" height="20"> + <expression><![CDATA[$F{devName}]]></expression> + </element> + <element kind="textField" uuid="4106684d-ae0b-4bcd-b1fd-02cd6dda7478" x="170" y="110" width="180" height="20"> + <expression><![CDATA[$F{groupName}]]></expression> + </element> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-jasper-example/src/main/resources/reports/client-list-template.jasper b/spring-jasper-example/src/main/resources/reports/client-list-template.jasper new file mode 100644 index 0000000000000000000000000000000000000000..3ca1f8e2ccdfa110ed9fce92372a0f70605dd814 GIT binary patch literal 13520 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 a(~V_Z#OP{c{i~#KAuKocE