Document Templates

Socotra’s document rendering engine uses templates written in a language called Liquid, created by Shopify. For more information see the Liquid Language Reference.

Socotra supports a set of custom functions in Liquid, documented here: Socotra Liquid Filters

Templates have names of the form *.template.liquid, and are a combination of HTML and liquid markup that accesses and processes policy data.

Data Available in Templates

Data Common to All Transaction Types

All policy information is available in a structure called data.policy. For example, gross premium for the first segment of a policy can be referenced in a document template as data.policy.characteristics[0].gross_premium.

The object hierarchy for data available to the document template is:

{
  "data": {
    "policy": {
      "characteristics": [{
        "tax_groups": [{}]
      }],
      "exposures": [{
        "characteristics": [{}],
        "perils": [{
          "characteristics": [{}]
        }]
      }],
      "modifications": [{
        "exposure_modifications": [{
           "peril_modifications": [{}]
        }]
      }],
      "invoices": [{
        "statuses": [{}],
        "payments": [{}]
      }],
      "fees": [{}]
    },
    "policyholder": {
      "entity": {}
    }
  }
}

For specifics about the structure of each object, see the Details of the data object section below.

Data Specific to Certain Transaction Types

Some properties in the data object are only populated for certain kinds of transactions:

Note

When rendering numerical field values, generally you will want to use a filter for formatting; otherwise numbers will be rendered in exponential format. For example, instead of including the expression {{ data.policy.characteristics[0].field_values.annual_miles }}, instead use {{ data.policy.characteristics[0].field_values.annual_miles | format_number_pattern: "0" }}

Details of the data Object

ValuesMaps

Many objects below refer to a “ValuesMap”, which is an implementation of a multimap data structure. A ValuesMap contains key-value pairs where the value can be a single value or an array, depending on whether that field was configured to be repeatable. The ValuesMap for field values is structured like this:

{
  "field1": "value1",
  "field2": ["value2", "value3"]
}

Note

This map is different from the data structures in the API, where all map data structures are key/array pairs.

Field Groups

In the field_values objects below, the value for fields of the group type is an array of locators. The groups of fields themselves are in an object called field_groups_by_locator. That object contains all field groups, not just those for the field in question. Use this example implementation as a starting point. This outputs the accessory_type field from each “accessory” field group:

{% assign exposure_values = data.exposure_characteristics.field_values %}
{% assign exposure_groups = data.exposure_characteristics.field_groups_by_locator %}

{% for accessory_loc in exposure_values.accessory %}
  {% assign accessory = exposure_groups[accessory_loc] %}
  {{accessory.accessory_type}}
{% endfor %}

data.policy

Details of the policy’s child objects are in the following sections.

{
  "locator": string,
  "policyholder_locator": string,
  "product_locator": string,
  "display_id": string,
  "quote_locator": string,
  "quote_name": string,
  "created_timestamp": long,
  "updated_timestamp": long,
  "issued_timestamp": long,
  "gross_fees": number,
  "gross_fees_currency": string,
  "characteristics": [{}],
  "exposures": [{}],
  "modifications": [{}],
  "invoices": [{}],
  "fees": [{}],
  "commissions": [{}],
  "cancellation": {
    "modification_locator": string,
    "modification_name": string,
    "effective_timestamp": long
  },
  "payment_schedule_name": string,
  "original_contract_start_timestamp": string,
  "original_contract_end_timestamp": string,
  "effective_contract_end_timestamp": string
}

data.policyholder

{
  "locator": string,
  "id": string,
  "created_timestamp": long,
  "updated_timestamp": long,
  "entity": {
    "accountLocator": string,
    "entityType": string,
    "values": ValuesMap,
    "subValuesByLocator": map<String, ValuesMap>,
    "createdTimestamp": long,
    "updatedTimestamp": long
  }
}

data.policy Child Objects

data.policy.characteristics

[
  {
    "locator": string,
    "policyholder_locator": string,
    "product_locator": string,
    "start_timestamp": long,
    "end_timestamp": long,
    "gross_premium": number,
    "gross_premium_currency": string,
    "gross_taxes": string,
    "gross_taxes_currency": string,
    "issued_timestamp": long,
    "field_values": ValuesMap,
    "field_groups_by_locator": map<String, ValuesMap>,
    "created_timestamp": long,
    "updated_timestamp": long,
    "replaced_timestamp": long,  // Optional
    "tax_groups": [
      {
        "name": string,
        "amount": number,
        "amount_currency": string
      }
    ]
  }
]

data.policy.exposures

[
  {
    "locator": string,
    "name": string,
    "display_id": string,
    "characteristics": [
      {
        "locator": string,
        "policy_locator": string,
        "policyholder_locator": string,
        "product_locator": string,
        "start_timestamp": long,
        "end_timestamp": long,
        "created_timestamp": long,
        "updated_timestamp": long,
        "replaced_timestamp": long,  // Optional
        "field_values": ValuesMap,
        "field_groups_by_locator": map<String, ValuesMap>
      }
    ],
    "perils": [
      {
        "locator": string,
        "display_id": string,
        "name": string,
        "characteristics": [
          {
            "locator": string,
            "issued_timestamp": long,
            "exposure_characteristics_locator": string,
            "policy_characteristics_locator": string,
            "indemnity_per_item": number,
            "indemnity_per_event": number,
            "indemnity_in_aggregate": number,
            "lump_sum_payment": number,
            "deductible": number,
            "premium": number,
            "technical_premium": number // Optional
            "coverage_start_timestamp": long,
            "coverage_end_timestamp": long,
            "original_coverage_end_timestamp": long,
            "field_values": ValuesMap,
            "field_groups_by_locator": map<String, ValuesMap>,
            "end_change_bound": long,
            "policy_modification_locator": string,
            "policyholder_locator": string,
            "policy_locator": string,
            "created_timestamp": long,
            "updated_timestamp": long,
            "replaced_timestamp": long // Optional
          }
        ],
        "created_timestamp": long,
        "updated_timestamp": long
      }
    ],
    "created_timestamp": long,
    "updated_timestamp": long
  }
]

data.policy.modifications

[
  {
    "locator": string,
    "name": string,
    "display_id": string,
    "number": integer,
    "issued_timestamp": long,
    "new_policy_characteristics_locator": string,
    "exposure_modifications": [
      {
        "locator": string,
        "new_exposure_characteristics_locator": string,
        "peril_modifications": [
          {
            "locator": string,
            "peril_locator": string,
            "exposure_modification_locator": string,
            "new_peril_characteristics_locator": string,
            "replaced_peril_characteristics_locator": string,
            "premium_change": number
          }
        ]
      }
    ],
    "created_timestamp": long,
    "updated_timestamp": long
  }
]

data.policy.invoices

[
  {
    "locator": string,
    "type": string,
    "display_id": string,
    "created_timestamp": long,
    "updated_timestamp": long,
    "number": integer,
    "current_status": string,
    "statuses": [
      {
        "status": string,
        "timestamp": long,
        "account_locator": string
      }
    ],
    "due_timestamp": long,
    "total_due": number,
    "total_due_currency": string,
    "payments": [
      {
        "payment_locator": string,
        "amount": number,
        "timestamp": long
      }
    ]
  }
]

data.policy.fees

[
  {
    "name": string,
    "amount": number,
    "amount_currency": string,
    "description": string
  }
]

data.policy.commissions

[
  {
    "peril_characteristics_locator": string,
    "peril_commissions": [{}]
  }
]

data.policy.commissions.peril_commissions

[
  {
    "amount": number,
    "amount_currency": string,
    "recipient": string
  }
]

Headers and footers

  • Headers and footers may be added using HTML enclosed in special header and footer blocks.

  • CSS that applies to the rest of the template will not apply to those blocks, so it must be re-applied within each block.

  • If there are multiple header blocks or footer blocks, the contents of each type of block will be concatenated.

Usage

  • Enclose the header HTML in {% header %} and {% endheader %}

  • Enclose the footer HTML in {% footer %} and {% endfooter %}

  • Add page numbers using <span class="page"></span>

  • Add page count using <span class="topage"></span>

Example

{% header %}
    <center>
        <p>This is at the top of page <span class="page"></span></p>
    </center>
{% endheader %}

{% footer %}
    <center>
        <p>Page <span class="page"></span> of
            <span class="topage"></span></p>
    </center>
{% endfooter %}