- 7 minutes to read

Order Confirmation Stylesheet

This page provides the Liquid Stylesheet O2C - View Order Confirmation for the CSV Order Confirmation messages (Step 3) in the Order-to-Cash demo.

Order Confirmation CONF-2025-10005 for order ORD-10005 and Tailspin Toys rendered by the O2C - View Order Confirmation Stylesheet, with the e-mail, the status CONFIRMED, one confirmed line, the total, and the estimated ship date (7.12)
The CSV Order Confirmation message rendered as a confirmation: confirmation number, order, customer with e-mail, the confirmed lines with the total, and the estimated ship date.

Read a flat file as a document. A CSV body has no structure that Liquid can read by name, but Liquid can still split it. With Nodinite Stylesheets, operators see the confirmation the customer received instead of comma-separated rows. On this page, you will:

  • ✅ Render a CSV message with Liquid, without a CSV parser
  • ✅ Split the raw body into lines and fields, section by section
  • ✅ Open the confirmation from Log Views and from BPM Log Search New 7.11

Understanding the Order Confirmation Stylesheet

A Stylesheet is tied to a Message Type. The business Log Event of Step 3, Order Confirmation Delivered to Customer, carries the Message Type O2C.Order.Confirmation/1.0, so Nodinite offers O2C - View Order Confirmation for it.

When the body is not JSON, Nodinite hands the whole body to Liquid as one string in the variable data. The template splits it with standard Liquid filters:

  1. data | newline_to_br | split: '<br />' gives the lines.
  2. strip cleans each line.
  3. A line that is a section name (OrderConfirmationHeader, OrderConfirmationDetails, OrderConfirmationFooter) starts a section; the first line after it is the column header row and is skipped.
  4. split: ',' gives the fields of each data line, addressed by position (f[0], f[1], …).
graph LR A["fa:fa-inbox Order Confirmation
Log Event (CSV)"] --> B["fa:fa-font Raw body
in data"] B --> C["fa:fa-scissors Split into lines
and sections"] C --> D["fa:fa-table-columns Split each line
on commas"] D --> E["fa:fa-file-alt Order Confirmation
document"] style A fill:#2678BD style B fill:#9E59BB style C fill:#E47528 style D fill:#E47528 style E fill:#93d16d

The CSV Log Event (blue) reaches the Liquid template as one string (purple); the template splits it into lines, sections, and fields (orange) and renders the confirmation (green).

Note

A quoted field that contains a comma is split too: Liquid has no CSV parser. The demo files have no such fields. XSLT could also read the body, since Nodinite wraps a non-XML body in a <string> element, but XSLT 1.0 has no split function, so Liquid is the practical choice.

Where Users Open the Order Confirmation

Where How
Log Views Search the Log View, open Action on the Order Confirmation Delivered to Customer event, and choose View message formatted as 'O2C - View Order Confirmation'.
BPM Log Search New 7.11 Click Log Search on the Order-to-Cash BPM, search for the order number, and open Action on the Confirmation event in the BPM Viewer.

The dialog is titled View message body formatted as 'O2C - View Order Confirmation' and has the buttons Open in New Window, Print, and Close. The forwarding event of the step, Confirmation Received, logs O2C.Forwarding/1.0, so this Stylesheet isn't offered there.

Stylesheet Settings

Setting Value Why
Name O2C - View Order Confirmation The name users pick in the Action menu
Type Liquid XSLT 1.0 can't split text
Render as HTML Checked The template outputs HTML
Message Body is Json Unchecked It has no effect on a CSV body, which always lands in data; leave it unchecked
Message Types O2C.Order.Confirmation/1.0 Only the Step 3 business event gets the Stylesheet

Input CSV

The Order Confirmation body of order 1 as logged by the demo data script, the same message as on the Step 3 page. The correlation ID differs per order and run.

OrderConfirmationHeader
ConfirmationId,ConfirmationDate,CorrelationId,OrderId,OrderDate,CustomerID,CustomerName,CustomerEmail,ConfirmationStatus
CONF-2025-10001,2025-10-14T09:22:15Z,<correlation id>,ORD-10001,2025-10-14T09:15:00Z,CUST-001,Contoso Corporation,orders@Contoso.example.com,CONFIRMED

OrderConfirmationDetails
LineNumber,SKU,Description,QuantityOrdered,UnitPrice,LineTotal
1,SKU-DEMO-001,Demo Widget,1,99.95,99.95

OrderConfirmationFooter
OrderTotal,Currency,EstimatedShipDate,TrackingEnabled
99.95,USD,2025-10-21,true

CSV to Document Mapping

Section Field (position) Shown in the document as
Header ConfirmationId (h[0]) The title, and Confirmation
Header OrderId (h[3]) Order ID, and Sent to the customer for order under the title
Header CustomerName, CustomerID, CustomerEmail (h[6], h[5], h[7]) Customer, with a mailto link
Header ConfirmationDate (h[1]) Confirmed
Header ConfirmationStatus (h[8]) Status, as a badge
Details every data line Confirmed Lines table: Line, SKU, Description, Qty, Unit Price, Line Total
Footer OrderTotal, Currency (t[0], t[1]) The Total row
Footer EstimatedShipDate (t[2]) Estimated ship date

CSV values show exactly as the message holds them. CorrelationId, OrderDate, and TrackingEnabled are not displayed.

Liquid Template

<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" />
{%- comment -%} The CSV body arrives as one string in 'data': split it into lines, then each data line on ','. {%- endcomment -%}
{%- assign lines = data | newline_to_br | split: '<br />' -%}
{%- assign section = '' -%}
{%- assign pos = 0 -%}
{%- assign rows = '' -%}
{%- for raw in lines -%}
  {%- assign line = raw | strip -%}
  {%- if line == 'OrderConfirmationHeader' or line == 'OrderConfirmationDetails' or line == 'OrderConfirmationFooter' -%}
    {%- assign section = line -%}
    {%- assign pos = 0 -%}
  {%- elsif line != '' -%}
    {%- assign pos = pos | plus: 1 -%}
    {%- if pos > 1 -%}
      {%- assign f = line | split: ',' -%}
      {%- if section == 'OrderConfirmationHeader' -%}
        {%- assign h = f -%}
      {%- elsif section == 'OrderConfirmationFooter' -%}
        {%- assign t = f -%}
      {%- else -%}
        {%- capture rows -%}{{ rows }}<tr><td>{{ f[0] }}</td><td>{{ f[1] }}</td><td>{{ f[2] }}</td><td class="text-center">{{ f[3] }}</td><td class="text-right">{{ f[4] }}</td><td class="text-right">{{ f[5] }}</td></tr>{%- endcapture -%}
      {%- endif -%}
    {%- endif -%}
  {%- endif -%}
{%- endfor -%}
<div class="container mt-4">
  <h1 class="mb-0">Order Confirmation {{ h[0] }}</h1>
  <span class="text-muted">Sent to the customer for order {{ h[3] }}</span>
  <table class="table mt-3">
    <thead>
      <tr><th>Confirmation</th><th>Order ID</th><th>Customer</th><th>Confirmed</th><th>Status</th></tr>
    </thead>
    <tbody>
      <tr>
        <td><strong>{{ h[0] }}</strong></td>
        <td>{{ h[3] }}</td>
        <td><strong>{{ h[6] }}</strong><br/><span class="text-muted">{{ h[5] }}</span><br/><a href="mailto:{{ h[7] }}">{{ h[7] }}</a></td>
        <td>{{ h[1] }}</td>
        <td><span class="badge badge-success">{{ h[8] }}</span></td>
      </tr>
    </tbody>
  </table>
  <h5 class="mt-4">Confirmed Lines</h5>
  <table class="table table-sm">
    <thead>
      <tr><th>Line</th><th>SKU</th><th>Description</th><th class="text-center">Qty</th><th class="text-right">Unit Price</th><th class="text-right">Line Total</th></tr>
    </thead>
    <tbody>{{ rows }}</tbody>
    <tfoot>
      <tr><th colspan="5" class="text-right">Total ({{ t[1] }})</th><th class="text-right">{{ t[0] }}</th></tr>
    </tfoot>
  </table>
  <p>Estimated ship date: <strong>{{ t[2] }}</strong></p>
  <div class="mt-5 pt-3 border-top text-center text-muted"><small>Rendered by a Nodinite Stylesheet (Liquid) from the CSV Order Confirmation message</small></div>
</div>

The same pattern renders the pipe-separated message of Step 6, with split: '|': see the Order Shipped Stylesheet.

Next Steps