Transformation Templates
As explained in the Transformations Overview, CloudBilling’s output is a set of pricing rule results. A transformation can be used to generate text or PDF output based on this set of rule results. This is achieved through the use of a transformation template. On this page we describe how the templates work and the features available to you.
View Engine
The Razor view engine is used to generate the output. This means the templates have to be in the Razor format. They can output any plain text format, but if the PDF output type is specified on the transformation the corresponding template should output HTML. Since PDF output is achieved by applying an HTML to PDF conversion.
Header - Model
Here we describe the model that defines an invoice object, it’s properties and methods that can be used in the Razor template. The base of the model is an ExportInvoice object and it has the following properties:
Property | Type | Description |
---|---|---|
Addresses | List<Address> | A list of address objects, property of the customer. |
BillingPeriodEnd | DateTimeOffset | DateTimeOffset object representing the end of the billing period |
BillingPeriodEndString | string | String representation of the end of the billing period |
BillingPeriodStart | DateTimeOffset | DateTimeOffset object representing the start of the billing period |
BillingPeriodStartString | string | String representation of the start of the billing period |
CustomerCode | string | The CustomerCode of the customer this invoice is for |
CustomerName | string | The CustomerName of the customer this invoice is for |
InvoiceCalculationDate | DateTimeOffset | DateTimeOffset object representing the date and time this invoice was calculated |
InvoiceCalculationDateString | string | String representation of the date and time this invoice was calculated |
InvoiceExportDate | DateTimeOffset | DateTimeOffset object representing the date and time this invoice was exported |
InvoiceExportDateString | string | String representation of the date and time this invoice was exported |
InvoiceItems | List<ExportInvoiceItem> | A list of ExportInvoiceItem objects. Each of these contains a single InvoiceRuleResult |
InvoiceNumber | string | A string representing the invoice number of this invoice |
DateValues | Dictionary<string, UniDateTime> | A dictionary from key to value for dateValue metadata of the customer |
DateValuesList | List<DateNameValuePair> | A list of DateNameValuePairs. Each DateNameValuePair is a mapping between a Name and a Value representing date metadata of the customer |
NumericValues | Dictionary<string, double> | A dictionary from key to value for numericValue metadata of the customer |
NumericValuesList | List<NumericNameValuePair> | A list of NumericNameValuePairs. Each NumericNameValuePair is a mapping between a Name and a Value representing numeric metadata of the customer |
StringValues | Dictionary<string, string> | A dictionary from key to value for stringValue metadata of the customer |
StringValuesList | List<StringNameValuePair> | A list of StringNameValuePairs. Each StringNameValuePair is a mapping between a Name and a Value representing string metadata of the customer |
Method | Type | Description |
GetDateValue(string key, DateTimeOffset? default = null) | UniDateTime | Helper method to directly get the value of a piece of customer date metadata specified by key |
GetNumericValue(string key, double default = null) | double | Helper method to directly get the value of a piece of customer numeric metadata specified by key |
GetStringValue(string key, double default = null) | string | Helper method to directly get the value of a piece of customer string metadata specified by key |
HasDateValue(string key) | boolean | Helper method to determine whether the customer has a piece of date metadata specified by key |
HasNumericValue(string key) | boolean | Helper method to determine whether the customer has a piece of numeric metadata specified by key |
HasStringValue(string key) | boolean | Helper method to determine whether the customer has a piece of string metadata specified by key |
Line Items - Model
The actual rule results are represented in the InvoiceItems list of ExportInvoiceItems. Each of these is a thin wrapper around an InvoiceRuleResult, which contains the actual pricing rule result and has the following properties:
Property | Type | Description |
---|---|---|
BillingOutputTags | List<string> | A list of Strings, each representing a BillingOutputTag. BillingOutputTags (BOTs) are used to add additional information to rule results defined on the pricing rules. They are also commonly used in the templates to, e.g., filter the set of results to those having the ‘Summary’ tag for display on the summary page. Furthermore, they are used to enrich the results with general ledger information. |
CalculationDate | DateTimeOffset | The date this result was calculated |
CalculationDateString | string | String representation of the calculation date |
Cost | double | The cost value of the result |
CostRuleValueUsed | double | The cost value used in the rule (unit cost) |
CostString | string | String representation of the cost |
FromDate | DateTimeOffset? | The FromDate of the result, can correspond with either the purchaseDate of the underlying purchase or the start of the period in case of a recurring purchase with an earlier purchaseDate |
FromDateString | string | String representation of the FromDate |
Id | string | A unique identifier for this result |
InvoiceLabel | string | The label generated for this result through the InvoiceLabelKey. This is the label displayed in the View Invoice screen in the UI |
isIntermediateResult | boolean | Indicates whether or not this is an intermediate result. This applies to SUM rule results, which can sometimes be split into several intermediate results. We can indicate on the SUM rule, whether we want to export these intermediate results at all. The default is to not export them |
MeasuredQuantity | double | The measured quantity of this result. Generally, this will be equal to the quantity, unless we apply pro-rata calculations |
OperatorUsed | string | Indicates which operator was used on the rule (PRICE, SUM, …) |
OperatorValueUsed | double | The operator value used in the rule. This is important to, e.g., determine the VAT percentage that was applied in a generic way |
ProductTagName | string | The name of the product cluster this result is for |
Quantiy | double | The quantity associated with the result. Can simply be the quantity on the underlying purchase or, e.g., the sum of all quantities of underlying results in case of a SUM result |
SourceIds | List<string> | A list of strings, each representing an Id of an item that was a source (input) for this rule. Items can include previous rule results as well as purchases. This list along with the Id values on the results can be used to construct a ‘calculation audit trail’ for the invoice, backtracking how the entire invoice was built up |
ToDate | DateTimeOffset? | The ToDate of the result, can also correspond with either the purchaseDate (in case of a non-recurring, non-pro-rata purchase) or the endDate of the underlying result, or the end of the period in case of a recurring purchase being the underlying result |
ToDateString | string | A string representation of the ToDate |
Value | double | The value of this rule result. This is the actual outcome of the calculation |
ValueString | string | A string representation of the value |
DateValues | Dictionary<string, UniDateTime> | A dictionary from key to value for dateValue metadata of the result |
DateValuesList | List<DateNameValuePair> | A list of DateNameValuePairs. Each DateNameValuePair is a mapping between a Name and a Value representing date metadata of the result |
NumericValues | Dictionary<string, double> | A dictionary from key to value for numericValue metadata of the result |
NumericValuesList | List<NumericNameValuePair> | A list of NumericNameValuePairs. Each NumericNameValuePair is a mapping between a Name and a Value representing numeric metadata of the result |
StringValues | Dictionary<string, string> | A dictionary from key to value for stringValue metadata of the result |
StringValuesList | List<StringNameValuePair> | A list of StringNameValuePairs. Each StringNameValuePair is a mapping between a Name and a Value representing string metadata of the result |
Method | Type | Description |
GetDateValue(string key, DateTimeOffset? default = null) | UniDateTime | Helper method to directly get the value of a piece of result date metadata specified by key |
GetNumericValue(string key, double default = null) | double | Helper method to directly get the value of a piece of result numeric metadata specified by key |
GetStringValue(string key, double default = null) | string | Helper method to directly get the value of a piece of result string metadata specified by key |
HasDateValue(string key) | boolean | Helper method to determine whether the result has a piece of date metadata specified by key |
HasNumericValue(string key) | boolean | Helper method to determine whether the result has a piece of numeric metadata specified by key |
HasStringValue(string key) | boolean | Helper method to determine whether the result has a piece of string metadata specified by key |
Using the Models
In the actual template, we have to begin by importing the namespace for the model described above. This is achieved by starting the template with the following statement:
@using Kolonel.Domain.Model
From this point on the template can use the model described above to generate output. When applying a transformation to an invoice, that invoice is represented by a single ExportInvoice object, containing a list of invoiceItems. The template is then applied to that specific instance of the model, thus generating output. Specifically, in the template we can now say something like:
Model.CustomerName
to print out the customer name.
Grouped Templates
When adding a template, you can indicate whether or not it is a grouped template. If this is the case, the model is slightly different. Instead of a single ExportInvoice object (representing a single invoice), the model contains a list of ExportInvoice objects, each representing an invoice that the template is applied to. We import the same namespace at the start of the template, only now to use it, we generally iterate over the ExportInvoice objects and generate output for each one sequentially, like this:
foreach(var inv in Model.ExportInvoices){
inv.CustomerName
}
to print out the customer name for each invoice.
Metadata
One of the more complex aspects of transformation templates and rule application is metadata, so we cover it separately. Customer metadata is fairly straightforward. Any metadata specified on a customer will be available as metadata in the template on the ExportInvoice object. Purchase metadata is slightly more complex, since purchases are not part of the set of information available to the template. The template does have access to all of the pricing rule results though. In general (and by default), CloudBilling tries to maintain as much metadata on results as possible. Sometimes this will be all metadata of a purchase, e.g., a price rule will just copy over all metadata from the purchase onto the result. In other cases this might be more challenging, consider 3 different purchases for a bicycle. Each has a string metadata attribute ‘color’, but each has a different value for this attribute, say ‘red’, ‘white’, and ‘blue’ respectively. Then a price rule will generate 3 separate results, each with the metadata intact and corresponding to the respective purchase that’s underlying to the result. However, if we want to get a subtotal of the amount for bicycles, we get a single SUM results with these 3 price results as underlying, there is no clear way to fill the ‘color’ metadata on the result of the SUM, since there are 3 different input values. In this case, we can’t retain the metadata.
The general rule of thumb is, unless it’s a 1-to-1 relationship, we will lose metadata. We do try to keep as much as possible (if all source items have the same value for a piece of metadata, it will persist). Furthermore, we have a concept called grouping on, for instance, sums. Where we can group on a piece of metadata. Let’s go back to the bicycle example and pretend instead of 3 different colors, we have 2 ‘red’ bikes and a ‘blue’ bike. Now if we group on the ‘color’ metadata key in the SUM rule, it will generate 2 results instead of 1. One of the results will contain the total for the red bikes, whereas the other will contain the total for the blue bike. We can of course SUM again afterwards to also get a ‘grand total’ for all 3 bikes.
Now that we’ve explained how the metadata persists through the mechanism of rule application, what can we actually do with it in the template? Through the properties and helper methods, we can split the set of results on a piece of metadata. Which in turn allows us to split output for, e.g., a specification page based on metadata present on the results. We will demonstrate the use of metadata to achieve something like this in one of the examples in the next section.
Examples
The template engine is extremely flexible, but can also be complex, especially to start with. Therefore we will provide some examples here to demonstrate the concepts.
Examples will be added in the near future (End of May)