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

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": {}
        }
    }
}

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 next section.

{
    "locator": string,
    "policyholder_locator": string,
    "product_locator": string,
    "display_id": string,
    "created_timestamp": long,
    "updated_timestamp": long,
    "issued_timestamp": long,
    "gross_fees": BigDecimal,
    "gross_fees_currency": String,
    "characteristics": [{}],
    "exposures": [{}],
    "modifications": [{}],
    "invoices": [{}],
    "fees": [{}],
    "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": BigDecimal,
        "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,
        "tax_groups": [
          {
            "name": string,
            "amount": BigDecimal,
            "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,
                "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": BigDecimal,
                        "indemnity_per_event": BigDecimal,
                        "indemnity_in_aggregate": BigDecimal,
                        "lump_sum_payment": BigDecimal,
                        "deductible": BigDecimal,
                        "premium": BigDecimal,
                        "technical_premium": BigDecimal // 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,
                    }
                ],
                "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,
                    }
                ]
            }
        ],
        "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": BigDecimal,
        "total_due_currency": string,
        "payments": [
            {
                "payment_locator": string,
                "amount": BigDecimal,
                "timestamp": long
            }
        ]
    }
]

data.policy.fees

[
  {
    "name": string,
    "amount": BigDecimal,
    "amount_currency": string,
    "description": 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 %}