# Automating PDF Reports

This step-by-step guide will walk you through a complete, real-world example: building an application that allows a user to fill out and sign an acceptance report, which is then saved to a database and emailed as a PDF.

### Before You Begin

To get started, the first step for everyone is to download the blank `acceptance_report.pdf` file. You will need to upload this file to your File Server to serve as the template's background, regardless of which method you choose below.

Once you have the PDF, you have two options:

1. Build from Scratch: Follow all the steps in this guide to learn the entire process.
2. Start from a Template: If you'd like to start with the finished application logic, download the Heisenware Tag (`acceptance-report-app.hwt`) file below and import it into your account. You will still need to link your uploaded PDF to the template.

#### Downloads

{% file src="<https://3495989837-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE5Ketpww1s7TauSAJrJ8%2Fuploads%2FYwDg21ypz8ePOg8ImMcI%2Facceptance_report.pdf?alt=media&token=79f84eb5-6502-41b4-a2f8-096236b4b2a4>" %}

{% file src="<https://3495989837-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE5Ketpww1s7TauSAJrJ8%2Fuploads%2F61TVR9ftTbU9pwhvpKLu%2Facceptance-report-app.hwt?alt=media&token=445c6c66-7dac-4b0a-a0f7-0e06c573b439>" %}

## Step 1: Create the Database Table

First, we need a place to store the submitted reports. We'll use the `defineTable` function to create a table in the internal PostgreSQL database.

In the Flow Builder, place the `defineTable` function on the canvas and configure its inputs as shown below.

```yaml
#name
acceptanceReports
#fields
customerName: string
projectID: string
acceptanceDate: date
comments: text
signature: text
```

{% hint style="info" %}
The 'id', 'createdAt', and 'updatedAt' fields are added automatically.
{% endhint %}

After configuring the function, you must trigger it once to execute the logic and create the table in your database.

<figure><img src="https://3495989837-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE5Ketpww1s7TauSAJrJ8%2Fuploads%2FXdRFdoXRtZ11x615dU1J%2Fimage.png?alt=media&#x26;token=e75a7104-8282-459b-9f41-c11fded3b753" alt=""><figcaption></figcaption></figure>

## Step 2: Build the Form and Submission Logic

Now, we will create the user interface for data entry and build the backend logic to save the submitted data to our database table.

### Build the User Interface

First, in the UI Builder, add the widgets for your form.

{% stepper %}
{% step %}
Drag a [Form widget](https://docs.heisenware.com/app-builder/build-frontend/widgets/input-widgets/form) onto the canvas. Select it and configure its fields. It is critical that the field names and data types exactly match your database columns (`customerName`, `projectID`, `acceptanceDate`, `comments`). You can also set user-friendly labels for each field.
{% endstep %}

{% step %}
Drag a [Signature widget](https://docs.heisenware.com/app-builder/build-frontend/widgets/input-widgets/signature) onto the canvas, placing it below the form.
{% endstep %}

{% step %}
Drag a [Button](https://docs.heisenware.com/app-builder/build-frontend/widgets/trigger-widgets/button) below the `Signature` widget and change its label to `Submit`.
{% endstep %}
{% endstepper %}

<figure><img src="https://3495989837-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE5Ketpww1s7TauSAJrJ8%2Fuploads%2FOklD3qyhH2ZLXJ3p3mfl%2Fimage.png?alt=media&#x26;token=1d6ff267-7290-49f7-92e4-279d2d1d58f3" alt="" width="377"><figcaption></figcaption></figure>

### Construct the Submission Logic

Next, switch to the Flow Builder to define what happens when the user clicks the `Submit` button.

{% stepper %}
{% step %}
Prepare the Signature Data

The `Signature` widget outputs a raw Base64 string, but our database expects an object. We need to format it correctly.

* Drag a [Memory function](https://docs.heisenware.com/tutorials/app-templates/broken-reference) onto the canvas and connect the output of the Signature widget to its input.
* Add a [JavaScript Modifier](https://docs.heisenware.com/tutorials/app-templates/broken-reference) after the `Memory`. Use the following expression in it. This wraps the signature string in an object with the key `signature`, matching our database column.

```javascript
{signature: x}
```

<figure><img src="https://3495989837-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE5Ketpww1s7TauSAJrJ8%2Fuploads%2FdDzLF1McCPiQSgkGQaTU%2Fimage.png?alt=media&#x26;token=637378e7-63b2-44aa-9c0d-8d189afe1685" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}
Combine All Form Data

Now we'll merge the main form data with our newly created signature object.

* Drag the [`mergeObjects`](https://docs.heisenware.com/app-builder/build-backend/functions-library/utilities/data-processing#merging-objects) function onto the canvas.
* Connect the Form widget to the first input of `mergeObjects`.
* Connect the signature modifier to the second input of `mergeObjects`.
* Connect both inputs to the trigger of `mergeObjects` to trigger the function `on input update`.

<figure><img src="https://3495989837-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE5Ketpww1s7TauSAJrJ8%2Fuploads%2F9H5tpYSp8ASKCNNxxurf%2Fimage.png?alt=media&#x26;token=8c3d5fac-c60a-4821-a59a-4b8a88e2553e" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}
Save to the Database & Trigger the Flow

* Drag the [`addRow`](https://docs.heisenware.com/app-builder/build-backend/functions-library/storage/relational-database#addrow) function onto the canvas.
* Set its `table` input to `acceptanceReports`.
* Connect the output of the `mergeObjects` function to the `data` input of `addRow`.
* Finally, connect the Submit Button to the trigger of the `addRow` functions trigger. This makes the button start the entire save process.

<figure><img src="https://3495989837-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE5Ketpww1s7TauSAJrJ8%2Fuploads%2FTUB4Z3CYlZNRTVl7ynuf%2Fimage.png?alt=media&#x26;token=71a50176-59e9-4e5d-a87a-7d26ea76a984" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}
Clear the Form After Submission:

* To provide a good user experience, we'll clear the form after a successful submission.
* Connect the output of the `addRow` function to the Form widget.
* Set the command to `call clear`. This will empty the form for the next entry after the data has been saved.

<figure><img src="https://3495989837-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE5Ketpww1s7TauSAJrJ8%2Fuploads%2FVJhExbgIqBoPZECJQ3Ws%2Fimage.png?alt=media&#x26;token=d8b708bc-6792-44bb-af4a-b0f40506f836" alt=""><figcaption></figcaption></figure>
{% endstep %}
{% endstepper %}

## Step 3: Design and Configure the PDF Template

Now that our data submission logic is in place, we will create the visual PDF template and configure the logic to populate it.

### Design the Template Layout

First, we need to create the visual layout in the Template Editor.

{% stepper %}
{% step %}
Upload the `acceptance_report.pdf` file to the [File server via the Resources panel](https://docs.heisenware.com/app-builder/build-backend/internal-file-server).
{% endstep %}

{% step %}
Navigate to [PDF Template Editing](https://docs.heisenware.com/app-builder/build-frontend/pdf-template-editor) mode.
{% endstep %}

{% step %}
Create a new template and name it `AcceptanceReport`.
{% endstep %}

{% step %}
From the Resources Panel, drag the `acceptance_report.pdf` file onto the page canvas. This sets it as the static background.
{% endstep %}

{% step %}
Using the Add Text Placeholder and Add Image Placeholder tools, place placeholders on the background for each of your fields (`customerName`, `projectID`, `acceptanceDate`, `comments`, and `signature`).
{% endstep %}

{% step %}
Configure each placeholder with the correct Variable Name in its settings. Optionally, adjust sizes and colors of your placeholders.
{% endstep %}
{% endstepper %}

<figure><img src="https://3495989837-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE5Ketpww1s7TauSAJrJ8%2Fuploads%2FNw8u0WQC4ALQs7FFyXMV%2Fimage.png?alt=media&#x26;token=d093b03e-01cc-4b54-9353-470afa70c5db" alt=""><figcaption></figcaption></figure>

### Construct the PDF Generation Logic

Now, return to the Flow Builder to connect the template to your existing logic.

{% stepper %}
{% step %}
From the Functionality Panel, find your `AcceptanceReport` instance (under the [`PDF Templates`](https://docs.heisenware.com/app-builder/build-backend/functions-library/utilities/pdf-templates) Class) and drag its `fillTemplate` function onto the canvas.
{% endstep %}

{% step %}
Connect the output of the `mergeObjects` function (from Step 2) to the `Values` input of `fillTemplate`. This provides the data for the placeholders.
{% endstep %}

{% step %}
Connect the output of the `addRow` function to the trigger of the `fillTemplate` function. This ensures the PDF is only generated *after* the data has been successfully saved to the database.
{% endstep %}
{% endstepper %}

Our flow is now complete up to the point of generating the PDF. The final step will be to email this document.

<figure><img src="https://3495989837-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE5Ketpww1s7TauSAJrJ8%2Fuploads%2FYqT9wqVlzmcg0ypF9rT1%2Fimage.png?alt=media&#x26;token=d7a05826-ae49-4947-aff7-ca9517c48857" alt=""><figcaption></figcaption></figure>

## Step 4: Send the Report via Email

The final step in our workflow is to automatically email the generated PDF report. We will use the `send` function from the [internal mailer](https://docs.heisenware.com/app-builder/build-backend/functions-library/connectors/email) and configure it to send an email automatically whenever a new report is created.

Return to the Flow Builder to add the final piece of logic to your flow.

{% stepper %}
{% step %}
From the Functionality Panel, find your internal mailer instance and drag its `send` function onto the canvas.
{% endstep %}

{% step %}
Configure the static inputs for the email

```yaml
#address
to: [your email address]
#subject
New Acceptance Report
#content
A new report has been submitted for review. Please see attached PDF.
```

{% endstep %}

{% step %}
Format the Attachment Data

The `send` function's `attachment` input requires a specific object format. We can create this directly on the `fillTemplate` function's output using a built-in Modifier.

* Add a JSONata Modifier to the `fillTemplate` function.
* In the Modifier's settings, enter the following JSONata expression. This wraps the raw Base64 output (`$`) with a filename and encoding:

```
{
  "filename": "Acceptance Report.pdf",
  "content": $,
  "encoding": "base64"
}
```

{% endstep %}

{% step %}
Connect the PDF and Set the Trigger

* Connect the Modifier (from the `fillTemplate` function) to the `attachment` input of the `send` function.
* Now, connect the attachment input to the trigger of the `send` function.
* Set the trigger to `on input change`.
  {% endstep %}
  {% endstepper %}

This creates a simple and powerful data-driven workflow. Whenever a new PDF is generated by the `fillTemplate` function, its output is passed to the `attachment` input, and this change automatically triggers the `send` function.

<figure><img src="https://3495989837-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE5Ketpww1s7TauSAJrJ8%2Fuploads%2FanA4KGi0vVi9ftnaIacE%2Fimage.png?alt=media&#x26;token=55371489-b50e-4d0b-b28d-8a95f1e4b76c" alt=""><figcaption></figcaption></figure>

## Step 5: Deployment

Congratulations! 🥳 You have now built a complete application that captures user input, saves it to a database, generates a customized PDF, and emails it as an attachment.

The final step is to deploy your app. Click the Deploy button in the App Builder's toolbar to publish the latest version and make it live.

Once deployed, open the application and test the full workflow. After you fill out and submit the report, the static email address you configured in Step 4 should receive an email with the PDF attachment, which will look similar to the image below.

From here, you can expand on this project by adding more fields, using your own report templates, or integrating this logic into a larger application.

<figure><img src="https://3495989837-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE5Ketpww1s7TauSAJrJ8%2Fuploads%2FGge0pvTdp4XGibfEBRcl%2Fimage.png?alt=media&#x26;token=7c513533-6cd7-432b-a927-f0b0aeb6dab1" alt=""><figcaption></figcaption></figure>
