ConceptReviewed 2026-09-29

Merge fields and filters

Merge fields are the double-brace placeholders in document and message templates ({{ entity.demand_no }}, {{ contact.name }}) that are replaced with the record's values when a document or message is rendered; filters such as inr, words and date format the value, and Repeat row / Show when add tables and conditional blocks.

Merge fields and filters

A merge field is a placeholder in a template, written between double braces, that is replaced with a value from the record when the template is rendered: {{ entity.demand_no }} becomes DM-2026-27-00012, {{ contact.name }} becomes Mr Rakesh Shah. A filter after a vertical bar changes how the value is written, so {{ entity.total_amount | inr }} prints 26,89,575.00 with Indian grouping. The same language serves document templates (letters, term sheets, cost sheets), workflow message templates (email, WhatsApp, SMS, in-app) and the templated settings of workflow actions.

How it works in NirmaanOne

What a template can refer to

Every template is written for one record type, and the record type decides the names available:

  • entity: the record itself, one field per column (entity.demand_no, entity.due_date, entity.total_amount). A unit adds floor_number, floor_name, tower_name and configuration_name; a contact adds name (salutation, first and last name together); a termsheet adds allotted_carpet_area_sqft. Sensitive columns are never exposed.
  • Related rows, each by its own name: for a demand booking, contact, unit, project; for a booking contact, unit, project, opportunity, assigned_user; for a termsheet project, tenant, booking, society, allotted_unit, contact; for an estimate opportunity, contact, unit, project, assigned_user and payment_plan (version_no, status, summary); for a payment contact, company, tenant, booking, project, unit; and so on for commissions, construction stages, units, tasks, projects and books. Write {{ contact.first_name }}, {{ unit.unit_number }}, {{ project.name }}.
  • Collections (documents only), lists that sit at the top level, never under entity: a demand's lines; a termsheet's items, payments, allotments; a booking's parties, parking_slots, demands, payments, schedule; an opportunity's estimates; an estimate's items, groups (each with code, name, subtotal, gst, total and its own lines), payment_terms, instalments and plan_schedules. Rows carry helpful extras such as component_name, due_date, milestone_name, line_total, parking_type or a party's name, pan_no and address. {{ lines | length }} counts the items.
  • totals (documents only): a termsheet's items, benefits, charges and schedule; a demand's lines; an estimate's subtotal, gst and total.
  • document (documents only): document_no, title, generated_at, kind, filled once the document is numbered; a preview shows "<PREFIX>-PREVIEW".
  • organization.name, today (the date in UTC), and in letterhead and template headers or footers {{ logo }} for the letterhead's logo.
  • In workflow messages and actions also input (values typed on a manual run), event (extras such as days_until_due or reason), changes ({column: {old, new}} on an update event), actions (results of earlier actions in the run, for example {{ actions[0].run_no }}) and frontend_url.

A name that does not exist renders as blank, not as an error, so a mistyped field prints an empty cell silently; use Preview against a real record to check.

Filters

Filter Example Prints
inr {{ entity.total_amount | inr }} 26,89,575.00 (Indian grouping, 2 decimals, rounded half-up)
inr(true) {{ entity.total_amount | inr(true) }} ₹ 26,89,575.00
words {{ entity.total_amount | words }} the amount in words in lakh and crore, ending "Only"
money {{ entity.total_amount | money }} 2,689,575.00 (international grouping)
date {{ entity.due_date | date }} 30 Nov 2026
date("%d/%m/%Y") {{ entity.due_date | date("%d/%m/%Y") }} 30/11/2026

The designer's Merge fields sidebar inserts money fields with | inr and dates with | date already attached, and lists the filters under Formatting. Message templates offer the same four filters (money, date, inr, words).

Tables and conditions in documents

The document designer has three toolbar tools besides typing a field:

  • {{ }} Field ("Insert a merge field") opens the same picker as the sidebar.
  • Repeat row ("Repeat the current table row for every item of a list"): put the cursor in a table row, choose the list (lines, schedule, items…) and a row name (default row). It writes {% for row in lines %} at the start of the row's first cell and {% endfor %} at the end of its last cell; inside the row you write {{ row.component_name }}, {{ row.amount | inr }}. The renderer wraps the whole row, so one row prints per item. A loop that opens in one row and closes in another is not repeated, and Jinja placed between the table body and a row is pushed out of the table by the HTML cleaner, so keep the tags inside the cells. Inside a loop, do not call the row variable items.
  • Show when ("Show the current paragraph or table only when a condition holds") wraps the block under the cursor in {% if … %} / {% endif %} paragraphs; conditions such as entity.tds_amount > 0, contact.pan_no or entity.status == "Issued" work. The same trick, a paragraph holding only {% for g in groups %} … {% endfor %}, repeats a whole table per charge group, which is how the cost sheet prints one table per group.

Values are escaped when they are merged into a document, so a value can never inject markup, and templates are checked for syntax when saved (the message names the line at fault) and rendered in a sandbox. A message template's output is capped at 20,000 characters.

Why

Templates are written once by the office and rendered thousands of times by staff who never see the markup, so the field names mirror what the app shows, undefined names fail soft, formatting is a filter rather than something typed by hand, and money always comes out with the Indian grouping the buyer and the auditor expect.

Example

Demand DM-2026-27-00012 on booking BK-2026-27-00007 for Mr Rakesh Shah: five lines, ₹25,61,500.00 before GST, GST ₹1,28,075.00, Total amount ₹26,89,575.00, TDS ₹25,615.00, Due date 30 November 2026. In "Demand letter (standard)":

In the template Rendered
Dear {{ contact.name }}, Dear Mr Rakesh Shah,
Demand {{ entity.demand_no }} dated {{ entity.demand_date | date }} Demand DM-2026-27-00012 dated 15 Nov 2026
for unit {{ unit.unit_number }}, {{ unit.tower_name }}, {{ project.name }} for unit A-1203, Tower A, Sea Breeze Residency
is due on {{ entity.due_date | date("%d/%m/%Y") }} is due on 30/11/2026
Amount payable: Rs. {{ entity.total_amount | inr }} Amount payable: Rs. 26,89,575.00
({{ entity.total_amount | words }}) (Rupees Twenty-six Lakh Eighty-nine Thousand Five Hundred and Seventy-five Only)
{{ lines | length }} charges 5 charges
Ref. {{ document.document_no }} of {{ document.generated_at | date }} Ref. DL-2026-27-00118 of 16 Nov 2026

A table row marked Repeat row over lines with the cells {{ row.component_name }}, {{ row.amount | inr }} prints five rows, "Unit Price 23,86,500.00" down to "GST 1,28,075.00". A paragraph wrapped with Show when entity.tds_amount > 0 reading "Please deposit TDS of Rs. {{ entity.tds_amount | inr }} under section 194-IA and hand over Form 16B." appears on this letter (25,615.00) and is left out on a member's demand where the TDS is nil. Had the template said {{ entity.amount_due }}, a field that does not exist, the letter would simply print nothing there.

The seeded message "Payment reminder" uses the same fields in plain text: "demand {{ entity.demand_no }} dated {{ entity.demand_date | date }} … is due on {{ entity.due_date | date }}" and "Amount payable: Rs {{ entity.payable_amount | inr }}" become "demand DM-2026-27-00012 dated 15 Nov 2026 … is due on 30 Nov 2026" and "Amount payable: Rs 26,63,960.00" (the total less TDS); when the overdue rule sends it, {% if event.days_overdue %} switches the sentence to "was due on 30 Nov 2026 and is overdue by 7 days", and a note typed on the manual Send payment reminder run appears through {{ input.note }}.

Where you see it

  • Document template: the Merge fields sidebar, {{ }} Field, Repeat row, Show when, the Document title and the Preview.
  • Letterheads: {{ logo }}, {{ organization.name }} and {{ project.name }} in the header and footer.
  • New message template and Message template: Subject ("Merge fields work here too."), Email body and Plain-text version with the variables reference.
  • Workflow rule: templated action settings such as the email address or a task title; Event types: the event extras each event provides.

Related

  • Document templateScreen

    The template designer: write a template's wording with merge fields, set its letterhead, title and page layout, preview it against a real record, and publish, retire or restore its versions.

  • LetterheadsScreen

    Set up the branding wrapped around generated documents: logo, header and footer, page size, orientation, margins and page numbers, for the whole organization or for one project.

  • New message templateScreen

    Write a message template on its own page: code, name, channel, record type, subject, the designed email body and its plain-text version, attachments, and the merge-field reference.

  • Message templateScreen

    One message template's page: change its wording, attachments and settings, and preview it filled in for a real record.

  • RuleScreen

    One automation rule's page: read or change its basics, trigger, conditions and actions, test it against a record, clone or delete it, and switch a system rule on or off.

  • Event typesScreen

    The named events a rule can listen to: the system events NirmaanOne raises itself and the custom events you add to chain rules or to raise from your own integrations.

  • Document templates, published versions and letterheadsConcept

    A document template is an HTML letter with merge fields written for one record type; publishing it freezes a numbered version that generation uses while the draft stays editable, and a letterhead (the template's own, else the project's, else the organization's default) supplies the logo, header, footer and page layout around it.

  • Generated documents: offer letters, cost sheets, void and supersededConcept

    A generated document is a numbered, filed rendering of a published template against one record, kept with its merged text, template version and file; offer letters are generated when an offer is issued and supersede the earlier ones, cost sheets print an estimate for the buyer, and a void or superseded document keeps its number and shows a watermark saying what replaced it.

  • Numbers and series: documents, bookings, demands, payments and vouchersConcept

    How NirmaanOne numbers what it creates: generated documents, bookings, demands, demand runs, payments, payout runs and revenue runs take a prefix, the Indian financial year and a five-digit serial (BK-2026-27-00007), while vouchers are numbered on posting from their voucher type's prefix, padded counter and suffix.