Skip to main content

Logic control and looping

Zuora

Logic control and looping

The HTML Templates feature is in the Early Adopter phase for invoices. We are actively soliciting feedback from a small set of early adopters before releasing it as generally available. If you want to join this early adopter program, submit a request at Zuora Global Support.

Although Mustache is a logicless template engine, you can still use merge fields to conduct basic logic control and looping in HTML invoice templates.

Conditional control 

If the input data meets the condition specified by the merge fields, the content defined in the middle of merge fields is displayed in the rendering result.

The following table lists merge field examples with conditional control.

 

Pseudo-code

Merge Fields

Description

Boolean field

If Invoice.Account.AutoPay == True
  "Auto pay account"
Else
  "AutoPay is not enabled"

{{#Invoice.Account.AutoPay}}
  "Auto pay account"
{{/Invoice.Account.AutoPay}}

{{^Invoice.Account.AutoPay}}
  "AutoPay is not enabled."
{{/Invoice.Account.AutoPay}}

If an account has the AutoPay option enabled, the "Auto pay account" message is displayed in the rendering result. 

If an account has the AutoPay option disabled, the "AutoPay is not enabled." message is displayed in the rendering result..  

Field with Boolean functions

If InvoiceItems.IsEmpty
  "Empty Invoice"
Else
  "Non-Empty Invoice"

{{#InvoiceItems|IsEmpty}}
  "Empty invoice"
{{/InvoiceItems|IsEmpty}}


{{^InvoiceItems|IsEmpty}}
  "Non-Empty Invoice"
{{/InvoiceItems|IsEmpty}}

If the InvoiceItems list is empty, the "Empty invoice" message is displayed in the rendering result.

If the InvoiceItems list is non-empty, the "Non-Empty Invoice" message is displayed in the rendering result.

If Account.AccountNumber == null or Account.AccountNumber.isBlank

  "Show a blank string"

Else

{{Account.AccountNumber}}

{{#Account.AccountNumber|IsBlank}}
  ""
{{/Account.AccountNumber|IsBlank}}

 

{{^Account.AccountNumber|IsBlank}}
{{Account.AccountNumber}}
{{/Account.AccountNumber|IsBlank}}

If the AccountNumber value of an account is blank, a blank string is displayed.

If the AccountNumber value of an account is not blank, the actual account number is displayed in the rendering result.

And

If Account.AutoPay and Balance == 0
  "AutoPay account and zero balance"

{{#Account.AutoPay}}
{{#Balance|EqualToVal(0)}}
  "AutoPay account and zero balance"
{{/Balance|EqualToVal(0)}}
{{/Account.AutoPay}}

If an account has the AutoPay option enabled and the account’s balance is equal to zero, the automatically paid account with zero balance is displayed in the rendering result. 

Exists

If Account.Entity__c == French and Hardware Product exists
  "Display a message."

{{#Invoice}}

{{#Account.Entity__c|EqualToVal(French)}}

{{^InvoiceItems|Map(RatePlanCharge)|Map(ProductRatePlanCharge)|Map(ProductRatePlan)|Map(Product)|FilterByValue(ProductType__c,EQ,Hardware)|IsEmpty}}

“Display message 1”

{{/InvoiceItems|Map(RatePlanCharge)|Map(ProductRatePlanCharge)|Map(ProductRatePlan)|Map(Product)|FilterByValue(ProductType__c,EQ,Hardware)|IsEmpty}}

{{/Account.Entity__c|EqualToVal(French)}}

{{/Invoice}}

If an account has a custom field named name Entity__c and a product has a custom field  named ProductType__c, the Map Map function returns a list of Product values.

Loop control 

You can use list section merge fields to achieve looping. The following table lists merge field examples with loop control.

 

Pseudo-code

Merge fields

Description

Loop lists

for item in Invoice.InvoiceItems
  print item.ChargeName - item.ServiceStartDate -- item.ServiceEndDate

{{#Invoice.InvoiceItems}}
{{ChargeName}} - {{ServiceStartDate}} -- {{ServiceEndDate}}
{{/Invoice.InvoiceItems}}

You can use this example to show the charge name and service period of all invoice items in generated invoices.

Nested loops

for invoiceItem in Invoice.InvoiceItems
  print invoiceItem.ChargeName :
  for taxItem in invoiceItem.TaxationItems
    print taxItem.Name -- taxItem.TaxAmount

{{#Invoice.InvoiceItems}}
{{ChargeName}} :
{{#taxationItems}}
{{Name}} -- {{TaxAmount}}
{{/taxationItems}}
{{/Invoice.InvoiceItems}}

You can use this example to show all taxation items of every invoice item in generated invoices.

Nested loops 

A nested loop is a loop inside another loop. For example, you might want to show all taxation items for every invoice item.

The pseudocode is as follows:

for invoiceItem in Invoice.InvoiceItems
  print invoiceItem.ChargeName :
  for taxItem in invoiceItem.TaxationItems
    print taxItem.Name -- taxItem.TaxAmount

To do the same with merge fields in HTML invoice templates, you can use the following merge fields:

{{#Invoice.InvoiceItems}}
{{ChargeName}} :
{{#taxationItems}}
{{Name}} -- {{TaxAmount}}
{{/taxationItems}}
{{/Invoice.InvoiceItems}}

For example, if you want to show a charge details table for each subscription. One invoice contains multiple subscriptions.

The pseudocode is as follows:

for subscription in Invoice.InvoiceItems.Subscription
  print subscription.Name
  for invoiceItem in invoiceItems of Subscription
    print ChargeName -- ChargeAmount

To do the same with merge fields in HTML invoice templates, you can use the following example HTML code. The GroupBy function transforms an InvoiceItems list into a new list, which consists of two fields only:

  • Subscription.Name: It is the field name used for grouping.

  • _Group: It is a hard-coded key, which contains a list of InvoiceItems with the same subscription name.

See the GroupBy function in Functions used in merge fields for more information.

{{#InvoiceItems|SortBy(ServiceStartDate,ASC)|GroupBy(Subscription.Name)}}
<h4>Subscription: {{Subscription.Name}}</h4>
{{Cmd_Assign(BySubscriptionName,_Group)}}
  <table class="table-grid u_content_custom_generic_table_1">
  <thead><tr>
      <th style="width:auto; text-align:right;">
          Description
      </th>
      <th style="width:auto; text-align:right;">
          Charge Amount
      </th>
      <th style="width:auto;text-align:right; ">
          Tax
      </th>
      <th style="width:auto; text-align:right;">
          Total
      </th></tr></thead>
  <tbody>
  {{#BySubscriptionName}}
    <tr>
      <td style="">{{ChargeName}}</td>
      <td style="text-align:right;">{{ChargeAmount}}</td>
      <td style="text-align:right;">{{TaxAmount}}</td>
      <td style="text-align:right;">{{#Wp_Eval}}{{ChargeAmount}}+{{TaxAmount}}{{/Wp_Eval}}</td>
    </tr>
  {{/BySubscriptionName}}  
    <tr>
      <td style="text-align:right;">Subtotal</td>
      <td style="text-align:right;">{{BySubscriptionName|Sum(ChargeAmount)}}</td>
      <td style="text-align:right;">{{BySubscriptionName|Sum(TaxAmount)}}</td>
      <td style="text-align:right;">{{#Wp_Eval}}{{BySubscriptionName|Sum(ChargeAmount)}}+{{BySubscriptionName|Sum(TaxAmount)}}{{/Wp_Eval}}</td>
    </tr>
  </tbody>
  </table>
  {{/InvoiceItems|SortBy(ServiceStartDate,ASC)|GroupBy(Subscription.Name)}}
{{/Invoice}}