New Version of the Commission Report

DZone 's Guide to

New Version of the Commission Report

A Zone Leader continues his case study of building a new application for a family member. Read how his internal dissatisfaction with a prior report caused a re-do.

· Web Dev Zone ·
Free Resource

As a follow-up to my "New Application Journey" article, I wanted to (again) talk about a challenge I encountered while trying to build a report that was manually created each month using Google Sheets. My second attempt was designed to make things even better.


As a TL;DR (too long; didn't read) to the original article, I wasn't happy with the application my mother-in-law was using for her very small business in the southeast section of the United States. So, I used her business needs to create a new application from scratch using Angular, mySQL and the AWS environment. As I started building out reports for the data, I realized that automating the manual report she created in Google Sheets was not going to be as easy as I expected. After trying to use only HTML, I realized I needed to include some additional frameworks into the project.

The Commission Report

The commission report combines property information and agent sale information. To read more background about the report, simply view the following article in this series:

The Challenge of the Commission Report

While the report would display on the screen, even the largest of screens struggled to display all the necessary data for the commission report. My efforts to trick the browser into printing the report in landscape format worked somewhat, but it didn't seem to want to print anything more than the first page of the report.

In talking with my mother-in-law, she indicated it would be nice to break up the report by manager — so she could give each manager a one-page report detailing their team's sales for the reporting period.

I used the additional requirement as an opportunity to re-do the report.

Target a PDF Format Using PDFBox

Since the commission report is distributed to a number of different entities, I thought it might be best to simply build the report as a PDF file. The file would be broken down into the following sections:

  • Commission Data Grouped by Manager

  • Referral Information

  • Report Summary

Each section would begin on a new page and would be designed in landscape format.

To build the PDF file, I opted to use Apache PDFBox, which was added to the project using the following dependency:


Knowing that PDFBox does not include the ability to create tables, I found the boxable framework and included the following dependency:


Now, I could create a table using the following command:

private BaseTable createBaseTable(PDDocument document, PDPage page) throws IOException {
    float margin = 15;
    float yStartNewPage = page.getMediaBox().getHeight() - (2 * margin);
    float tableWidth = page.getMediaBox().getWidth() - (2 * margin);

    float yStart = yStartNewPage;
    float bottomMargin = 70;
    float yPosition = 550;

    return new BaseTable(yPosition, yStartNewPage, bottomMargin, tableWidth, margin, document, page, true, true);

Once inside the table, adding rows is as simple as using the following helper function that I created:

private void writeSummaryRow(BaseTable table, String label, String value) {
    Row<PDPage> row = table.createRow(12);
    Cell<PDPage> cell = row.createCell(25, label);
    cell = row.createCell(25, value);

When the report was finished, the PDFBox document was saved as an OutputStream and then returned back to Angular:

OutputStream outputStream = new ByteArrayOutputStream();

On the Angular side, the getCommissionReportPdf() function sends the start and end dates for the report, then receives the Stream from the Java API, which is cast into a new Blob and then opened in a new tab on the browser.

this.reportService.getCommissionReportPdf(startDate, endDate)
  .subscribe( data => {
    const file = new Blob([data], { type: 'application/pdf' });
    const fileUrl = URL.createObjectURL(file);
    window.open(fileUrl, '_blank');

Leveraging the Existing Report Service

While I was able to re-use a great deal of the work I completed for the original commission report, I did have to add more code to process the properties for each manager. This basically required building a HashMap as follows:

HashMap<String, List<Property>>

The key for the HashMap would be the manager name for the agent making the sell. For those agents who do not have a manager listed, they are considered "Office" accounts, and have a manager named "Office." The first step was to initialize the HashMap with all of the active managers, plus one for "Office." In every case, an initialized List<Property> was added too.

The AgentInfo inner class was updated to include the manager name:

class AgentInfo {
    private Integer id;
    private String fullName;
    private BigDecimal totalCommission;
    private BigDecimal thisCommission;
    private String manager;

    public AgentInfo() {}

When the HashMap<Integer, AgentInfo> agent object was populated, it would have the agent's manager name with the data, so that the given property could be linked to the manager's List<Property>. Of course, agents without a manager would be placed against the Office List<Property>.

With the setup in place, all that was needed was to process the HashMap<String, List<Property>>. For each value, a new page in the PDFBox report was created and subsequent property data included.

Below, is a fuzzy screen shot of one of the pages of the report ... merely showing the format of the report and protecting the confidentiality of my mother-in-law's business:

Image title

Looking Ahead

This article is a continuation of a multi-part series that I am putting together regarding my new application journey to providing a better application experience for my mother-in-law. Below is a list of the current and planned articles, if you are interested in reading more:

Have a really great day!

angular, aws, java, tutorial, web dev

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}