Journey Manager (JM) The transaction engine for the platform. | System Manager / DevOps | All versions This feature is related to all versions.
Sometimes it is necessary to generate multiple different PDF receipts from a single submission. There are several use cases for this, for example:
For this particular example, we are going to generate a certificate for a course attendee. When the user fills in the form, they will be able to choose between different PDF receipts, and green receipt, and a receipt with a picture of flowers on it.
In this case, we are going to generate “pixel perfect” or AcroForm receipts. Please refer to this article for more information about AcroForm Receipts: How to import an Acrobat PDF form as a Transact receipt template (AcroForms).
The code is slightly different if you want to generate other types of receipts, but the principles are similar.
Each of the Acroforms has a single Acroform field placed on it – this field is named “FullName”. For consistency, both forms have the identical field name – but in a real scenario there can be a combination of common fields and form-specific fields. You just need to make sure that the data entry form provides all the necessary fields.
The data entry form has two fields, a field for the person’s name, and a dropdown containing the values “Green” and “Flowers”.
Each of these fields has a data extract name. We will use the data extract values for binding to the Acroform, as well as for the logic in our script.
The techniques for creating and generating an AcroForm receipt is described in the AcroForm article. But for the multiple receipt example, we have to solve two additional problems.
In order to store multiple receipts, we will create a “dummy” form in Transact Manager for each receipt. This form is not intended for data entry, and it will never be visible externally. It’s simply used as a place to store the receipt.
There are two ways to do this. Either:
Once you have defined your data entry form plus your additional “dummy” forms, you can upload the AcroForm PDF receipts to each of these form codes as shown below:
The Groovy code is shown below. This is an example of how you might write this script, and of course your needs may vary. The code is hopefully reasonably self-evident for Groovy programmers. You may want to refer to http://itextpdf.com/ for more details about the iText PDF library which does the work of merging the field data into the AcroForm.
/* Render Receipt Groovy script.
Script parameters include:
form : com.avoka.fc.core.entity.Form
request : javax.servlet.http.HttpServletRequest
submission : com.avoka.fc.core.entity.Submission
serviceDefinition : com.avoka.fc.core.entity.ServiceDefinition
serviceParameters : Map<String, String>
Script return:
a PDF receipt document of type com.avoka.fc.form.service.DataDocument
*/
import com.avoka.core.groovy.GroovyLogger as logger
import com.avoka.fc.core.dao.DaoFactory
import com.avoka.fc.form.service.DataDocument
import com.itextpdf.text.pdf.AcroFields
import com.itextpdf.text.pdf.AcroFields.Item
import com.itextpdf.text.pdf.PdfReader
import com.itextpdf.text.pdf.PdfStamper
import org.apache.commons.lang.Validate
logger.info "Start render"
final DATA_EXTRACT_CERTIFICATE_TYPE = "Certificate Type"
final FLOWER_FORM = "certificate-flowers"
final GREEN_FORM = "certificate-green"
// Get the Data Extract
Map<String, String> dataExtractMap = submission.dataExtractMap
logger.info "dataExtractMap=" + dataExtractMap
// Using the Certificate Type field data to determine which form code to use
def certificateType = dataExtractMap.get(DATA_EXTRACT_CERTIFICATE_TYPE)
def formCode = ""
if (certificateType == "Green") {
formCode = GREEN_FORM
} else {
formCode = FLOWER_FORM
}
logger.info "formCode=" + formCode
// Get the appropriate form object
def form = DaoFactory.getFormDao().getFormByFormCode(formCode.toLowerCase())
// Call the function to render the AcroForm and return the result
def receiptDocument = renderAcroForm(form, dataExtractMap)
logger.info "End render"
return receiptDocument
// This function uses iText to inject the fields from the data extract map into the AcroForm receipt
def renderAcroForm(form, dataExtractMap) {
final CONTENT_TYPE_PDF = "application/pdf"
Validate.notNull(form, "form parameter is null")
Validate.notEmpty(dataExtractMap, "dataExtractMap parameter is null")
def templateVersion = form.getCurrentVersion()
Validate.notNull(templateVersion, "form.currentVersion parameter is null")
byte [] templateData = templateVersion.getTemplateVersionData().getReceiptFileData()
Validate.notNull(templateData, "form.currentVersion.templateVersionDate.receiptFileData parameter is null")
// Create the output stream
ByteArrayOutputStream stream = new ByteArrayOutputStream(256 * 1024)
// Setup the PDF receipt template
PdfReader templatePdfReader = new PdfReader(templateData)
PdfStamper pdfStamper = new PdfStamper(templatePdfReader, stream)
// Bind the AcroForm field values
AcroFields acroFields = pdfStamper.getAcroFields()
Map<String, Item> fieldMap = acroFields.getFields()
for (String fieldName : fieldMap.keySet()) {
if (dataExtractMap.containsKey(fieldName)) {
acroFields.setField(fieldName, dataExtractMap.get(fieldName))
}
}
// "Flatten" the AcroForm with the bound field data - the fields will no longer be editable
pdfStamper.setFormFlattening(true)
pdfStamper.close()
return new DataDocument(stream.toByteArray(), CONTENT_TYPE_PDF)
Next, learn how to configure receipts server node.