Output documents rely on a number of settings described throughout the documentation. This walkthrough guides you through all the necessary steps to get your first output document up and running.
There are two types of output documents: product-based and quote-based. This article introduces you to the product-based document builder. We will be creating an output document at the configured product level, and adding each of the different output field types.
Prerequisites
Before starting this How-To, you should already...
- have a configurator
- have price object items in that configurator
- have installed the Epicor CPQ Capture Tool
Step-by-Step guide
Output Documents are the product of data and a template, merged together by a builder.
In this walkthrough, we are creating the output document template (2) and the instructions for the builder (3). Follow the steps below to create a working output document.
Create your source data
You should already have a working configurator with:
- At least one pricing rule, which creates a PriceObject with at least one LineItem.
- A default product image, defined under the "Media" section of your configurator's properties.
For our example, we're using a configuator with this simple pricing rule:
Upload a template
Full details on creating a word template can be found here. For this How-To, you can use an example template file we've created for you.
- Download this .docx file to your computer: bom_template.docx
- Change the filename to something unique, so your template won't be confused with someone else's.
- Open the file in Microsoft Word. You'll see this example is populated with real-life sample data. This is a good habit: business colleagues can see a example data that could appear, and template designers can size fonts/columns appropriately to match the sample data.
- Upload the file to your Epicor CPQ environment into Resources > Templates.
- You may want to create subfolders within the templates directory to stay organized.
- Keep the filenames short: fewer than 14 characters. Avoid special characters.
Create a builder, and an output document within that builder
- In your configurator, under builds, create a new or select an existing build type.
- Here, we created a build type of "Sales"
- Under the new build of that type, add a new Word output
- We gave our word output the name "BOM", so it appears with that name in the tree. The blue Word icon reminds you this is a Word output.
- A description is optional.
- The output must be enabled by default, or it won't be generated.
- Post To Cloud to use our cloud-based builder.
- Overwrite Pre-Existing Builds is always a good choice when testing.
- Add one or more Tags to this output, so you can control the visibility of the files later in your workflow.
- Here, we created a tag "VisibleToCubeCustomers".
- Select the template you uploaded in the previous step.
- Save your work.
Define output fields
While you can define and capture output fields on-the-fly in the capture tool itself, for simplicity's sake we will first define them in our configurator, and then capture locations in the document as a second step.
1. In the same screen above, drill down into your word output document to see the fields folder. Select that folder to see the "+" add button appear to the right of it. Use that button to create each of the fields described here:
Text field wQuoteName
Text field wDate
Image field wItemImage
(edit the "source" property of the image field: ensure it is "Media", not "Template")List field wBomList
Container wHazardousText
Text field wTotal
Your configurator tree should look like this. (Unlike UI fields, the order of output fields in the tree is not important.)
Capture output fields in the template
- You've been working on the fields under your output document. Click on the icon for your output document itself (the blue Word icon with the name "BOM").
- Under the "Template File" group on the right, click "Capture Output Fields".
If your workstation is setup correctly, the Epicor CPQ capture tool will launch, download the template, and launch word so you can edit the template – all in one click as shown in the animation here. If you don't have this experience, you can...- review your setup of the Epicor CPQ capture tool.
- launch the capture tool, then from within the capture tool log into your environment and open the template for editing manually.
- Use the capture tool to map your fields to locations in the document.
- To capture a text field, image, or container, simply select the example text in your template you want to replace, and click "add to doc".
- To capture a list field, you must select one entire row of a table. Be sure the entire row is selected. Then click "add to doc".
For every list output field, capture properties
List fields are different from other output fields: they are tables, showing one or more columns. Therefore, each list field must have at least one property, like the row of a table must have at least one column. After you create a list field, you create its properties in the capture tool. The animation below will help you.
- Consider the example text in each column of your repeating row in Word, and think of an attribute name for that text. For our list field in this example, we might use the following attributes:
- BOMquantity
- BOMitemNumber
- BOMdescription
- BOMextNetPrice
- BOMdiscount
- BOMnetPrice
- For each attribute, you will...
- Select the text in the table cell you'd like to replace with the attribute data
- Select the list field in the capture tool, and select "Add Property" to create a new property.
- Rename the property to a unique field name you decided on this name in the previous step. This will match the code you will write in a later step).
- Click "Add to Doc" next to the newly-created attribute, so it is inserted into the document.
3. Save your work, and close the Epicor CPQ Capture Tool. The capture tool will automatically close the instance of Word that it launched.
Create a rule to populate fields
Now that the output fields are captured, use Snap rules to fill them with data from your configurator, or from calculations you perform.
- Create a new rule under your "BOM" Word Output. The rules list is below the fields list.
-
First, define a type to store the data you will place into your List field. Each parameter of the type must be spelled exactly like the parameter of your List field. Since our word output fields are text, we define the type's parameters as text as well.
We will populate the values of this list field in a moment.If you don't feel like writing this Snap code yourself, copy the following JSON, and paste it into your Snap workspace by right-clicking anywhere in the workspace, selecting "paste json", and pasting this JSON into the box:
[{"$type":"DeclareTypeBlock","x":92,"y":98,"parts":{"type":{"value":"BOMitem"},"declarations":{"$type":"DeclarePropertyBlock","parts":{"itemVar":{"value":"BOMquantity"},"type":{"value":"text"},"next":{"$type":"DeclarePropertyBlock","parts":{"itemVar":{"value":"BOMitemNumber"},"type":{"value":"text"},"next":{"$type":"DeclarePropertyBlock","parts":{"itemVar":{"value":"BOMdescription"},"type":{"value":"text"},"next":{"$type":"DeclarePropertyBlock","parts":{"itemVar":{"value":"BOMextNetPrice"},"type":{"value":"text"},"next":{"$type":"DeclarePropertyBlock","parts":{"itemVar":{"value":"BOMdiscount"},"type":{"value":"text"},"next":{"$type":"DeclarePropertyBlock","parts":{"itemVar":{"value":"BOMnetPrice"},"type":{"value":"text"}}}}}}}}}}}}}}}]
- Populate the value property of text fields:
- Populate the deleted property of container fields as true or false. Here, we hard-code it to false, but you can use other logic to make that section of the document appear only during a certain month, for certain customers, or if other criteria are met.
- Populate the filepath property of image fields:
- Optionally, you can set other attributes of the output, such as the filename
- Finally, to set the parameters of your List field, loop through the array of PriceObject Items, creating a matching array of your custom type. (Note we also keep a running tally of the total price, which we want to show later.)
- This array of your custom type is then assigned to the List field.
- Finally, after calculating the total in the loop, populate the value property of the text field that shows the total:
If you don't feel like writing this Snap code yourself, copy the following JSON, and paste it into your Snap workspace by right-clicking anywhere in the workspace, selecting "paste json", and pasting this JSON into the box:
[{"$type":"CommentBlock","x":55,"y":411.0000305175781,"parts":{"comment":{"value":"populate text fields"},"next":{"$type":"SetOutputFieldPropertyBlock","parts":{"field":{"value":"nxq1dwdqi"},"property":{"value":"value"},"value":{"$type":"FormatDateBlock","parts":{"date":{"$type":"NowBlock"},"format":{"$type":"LiteralStringBlock","parts":{"text":{"value":"fullDate"}}}}},"next":{"$type":"SetOutputFieldPropertyBlock","parts":{"field":{"value":"lcw4ta1dg"},"property":{"value":"value"},"value":{"$type":"GetVariableBlock","parts":{"variable1":{"value":"configurator"},"variable2":{"value":"name"}}},"next":{"$type":"CommentBlock","parts":{"comment":{"value":"hide the hazardous text"},"next":{"$type":"SetOutputFieldPropertyBlock","parts":{"field":{"value":"xr16mhcww"},"property":{"value":"deleted"},"value":{"$type":"TrueFalseBlock","parts":{"value":{"value":"true"}}},"next":{"$type":"CommentBlock","parts":{"comment":{"value":"click the \"media\" block to set the output image to some image in your media folder"},"next":{"$type":"SetOutputFieldPropertyBlock","parts":{"field":{"value":"3d7js30n6"},"property":{"value":"filePath"},"value":{"$type":"ImageMediaBlock","parts":{"image":{"value":"logos/kbmax_logo_stacked@4x.png"}}},"next":{"$type":"CommentBlock","parts":{"comment":{"value":"set other attributes of the output file"},"next":{"$type":"SetOutputPropertyBlock","parts":{"property":{"value":"targetFilename"},"value":{"$type":"StringConcatBlock","parts":{"v":2,"parts":[{"$type":"LiteralStringBlock","parts":{"text":{"value":"BOM."}}},{"$type":"GetVariableBlock","parts":{"variable1":{"value":"configurator"},"variable2":{"value":"id"}}},{"$type":"LiteralStringBlock","parts":{"text":{"value":".docx"}}}]}},"next":{"$type":"CommentBlock","parts":{"comment":{"value":"create array of BOM items"},"next":{"$type":"DeclareVariableBlock","parts":{"itemVar":{"value":"myTotal"},"type":{"value":"number"},"default":{"$type":"NumberBlock","parts":{"number":{"value":"0"}}},"next":{"$type":"DeclareVariableBlock","parts":{"itemVar":{"value":"BOMitems"},"type":{"value":"BOMitem[]"},"next":{"$type":"ForEachBlock","parts":{"itemVar":{"value":"p"},"arrayVar":{"$type":"GetVariableBlock","parts":{"variable1":{"value":"configurator"},"variable2":{"value":"priceObject"},"variable3":{"value":"items"}}},"statement":{"$type":"WriteLogBlock","parts":{"logType":{"value":"info"},"value":{"$type":"StringConcatBlock","parts":{"v":2,"parts":[{"$type":"LiteralStringBlock","parts":{"text":{"value":"Found Price item - "}}},{"$type":"GetVariableBlock","parts":{"variable1":{"value":"p"},"variable2":{"value":"sku"}}}]}},"next":{"$type":"DeclareVariableToNewTypeBlock","parts":{"$typeName":"BOMitem","$variableName":"Item","$next":{"$type":"AddToArrayBlock","parts":{"Item":{"$type":"GetVariableBlock","parts":{"variable1":{"value":"Item"},"variable2":{"value":""}}},"Array":{"$type":"GetVariableBlock","parts":{"variable1":{"value":"BOMitems"}}},"next":{"$type":"SetVariableBlock","parts":{"variable1":{"value":"myTotal"},"value":{"$type":"MathOperationBlock","parts":{"v":2,"parts":[{"$type":"GetVariableBlock","parts":{"variable1":{"value":"myTotal"}}},"+",{"$type":"GetVariableBlock","parts":{"variable1":{"value":"p"},"variable2":{"value":"extNetPrice"}}}]}}}}}},"$propertySettings":{"BOMdescription":{"$type":"GetVariableBlock","parts":{"variable1":{"value":"p"},"variable2":{"value":"description"}}},"BOMdiscount":{"$type":"CastBlock","parts":{"value":{"$type":"GetVariableBlock","parts":{"variable1":{"value":"p"},"variable2":{"value":"discount"}}},"type":{"value":"text"}}},"BOMitemNumber":{"$type":"GetVariableBlock","parts":{"variable1":{"value":"p"},"variable2":{"value":"sku"}}},"BOMnetPrice":{"$type":"CastBlock","parts":{"value":{"$type":"GetVariableBlock","parts":{"variable1":{"value":"p"},"variable2":{"value":"netPrice"}}},"type":{"value":"text"}}},"BOMquantity":{"$type":"CastBlock","parts":{"value":{"$type":"GetVariableBlock","parts":{"variable1":{"value":"p"},"variable2":{"value":"qty"}}},"type":{"value":"text"}}},"BOMextNetPrice":{"$type":"CastBlock","parts":{"value":{"$type":"GetVariableBlock","parts":{"variable1":{"value":"p"},"variable2":{"value":"extNetPrice"}}},"type":{"value":"text"}}}}}}}},"next":{"$type":"SetOutputFieldPropertyBlock","parts":{"field":{"value":"3zcbh2at6"},"property":{"value":"value"},"value":{"$type":"GetVariableBlock","parts":{"variable1":{"value":"BOMitems"}}},"next":{"$type":"SetOutputFieldPropertyBlock","parts":{"field":{"value":"yjsv2zjkq"},"property":{"value":"value"},"value":{"$type":"FormatNumberBlock","parts":{"value":{"$type":"GetVariableBlock","parts":{"variable1":{"value":"myTotal"}}},"type":{"value":"number"},"prependWith":{"$type":"LiteralStringBlock","parts":{"text":{"value":"$"}}},"appendWith":{"$type":"LiteralStringBlock","parts":{"text":{"value":""}}},"minPrecision":{"$type":"NumberBlock","parts":{"number":{"value":"2"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}]
10. If you have any custom Price Columns you want to use, the syntax is different. Custom price columns are stored in a map. You can see in the following example how to get data from a custom "EngineeringHours" column, and use the cast Snap block to cast the data "as text".
11. If you use multiple currencies, then when writing currency fields to your output document (such as the quote price or an item's price), remember to use the "convert currency" Snap block to ensure the amount for costs and prices appears in the quote's native currency.
4. Test your finished output document
- Click "run" at the bottom of your configurator: It will show in a new test window.
- At the bottom of your running configurator, you should see a new "Test Build" button. This appears whenever a configurator has one or more builds defined within it.
- Click "Test Build" to get a list of all builds in this configurator.
- Click "Sales" (the name of the build we created).
- You'll be asked for a name for the build log, and what queue it should be built by. The defaults are fine, so just click "OK"
- Acknowledge that the build has started, and that you want to see the results of the build.
- The build page appears, with a log of steps that were performed. It will refresh every few seconds to show you the current status of the build process. Wait for the build to complete, usually within 10 seconds. You can also refresh this web page yourself.
- When the name and an icon for your attachment file appears, click the name to download and review the build file.
- You should see the data in the document from the rules you've written.
Did a column or two not appear correctly in your List field? Ensure the spelling of your list field attributes matches the spelling of your custom type attributes.