I’m generating a PDF from a Price Book and need to control the order of items. Currently, items are printed in the order they were added to the Price Book, which gets messy with larger lists. I’d like to sort (ideally group) items by
the product’s catalog/category, e.g.:
- Category “Group 1” → all items from that category (sorted by name)
- Then Category “Group 2” - all items from that category
- …and so on
Is there a built-in helper for print templates to sort an array by a nested path, e.g. product.category.name (or similar)? If not, is there a recommended way to:
- Define the sort for Price Book items at the relationship level so the template receives them ordered?
- Add a custom Handlebars helper (e.g. sort or groupBy) for PDF templates?
My desired result in template:
- Either simple sort: by product.category then product.name
Example idea (if such a helper exists): {{#each (sort prices "product.category.name" "product.name")}} … {{/each}}
- Or grouped output: category header, then items inside each group
Example idea (if a groupBy helper exists): group by product.category.name and render each group.
The Quote/Order does not solve this for me because I’d have to manually add the full item list each time. I maintain multiple distributor classes with different prices and want to print tailored Price Books per distributor group.
Template snippet I’m currently using (simplified) is below — it shows how I iterate over prices and render product names and net prices:
the product’s catalog/category, e.g.:
- Category “Group 1” → all items from that category (sorted by name)
- Then Category “Group 2” - all items from that category
- …and so on
Is there a built-in helper for print templates to sort an array by a nested path, e.g. product.category.name (or similar)? If not, is there a recommended way to:
- Define the sort for Price Book items at the relationship level so the template receives them ordered?
- Add a custom Handlebars helper (e.g. sort or groupBy) for PDF templates?
My desired result in template:
- Either simple sort: by product.category then product.name
Example idea (if such a helper exists): {{#each (sort prices "product.category.name" "product.name")}} … {{/each}}
- Or grouped output: category header, then items inside each group
Example idea (if a groupBy helper exists): group by product.category.name and render each group.
The Quote/Order does not solve this for me because I’d have to manually add the full item list each time. I maintain multiple distributor classes with different prices and want to print tailored Price Books per distributor group.
Template snippet I’m currently using (simplified) is below — it shows how I iterate over prices and render product names and net prices:
Code:
<!-- Header: 2 columns -->
<table style="width: 100%;">
<tbody>
<tr>
<td style="width: 33.33%; vertical-align: top;">
<h2>Company Name</h2>
<p>
<strong>Company Legal Name</strong><br>
Street Address 1<br>
Postal Code City, Country<br>
Tax ID: <b>1234567890</b><br>
<a href="https://www.example.com" target="_blank">https://www.example.com</a><br>
<a href="mailto:info@example.com" target="_blank">info@example.com</a><br>
Tel: (+00) 000-000-000
</p>
</td>
<!-- Middle column: client data from Account -->
<td style="width: 33.33%; vertical-align: top;">
<h2>Client</h2>
<!-- 1) Direct link to account -->
{{#if cKlientWydruk.name}}
<strong>{{cKlientWydruk.name}}</strong>
<br>
<!-- Street and number -->
{{#if cKlientWydruk.billingAddressStreet}}{{cKlientWydruk.billingAddressStreet}}<br>{{/if}}
<!-- Postal code and city, country -->
{{#if cKlientWydruk.billingAddressPostalCode}}{{cKlientWydruk.billingAddressPostalCode}}{{/if}}{{#if cKlientWydruk.billingAddressPostalCode}}{{#if cKlientWydruk.billingAddressCity}} {{/if}}{{/if}}{{#if
cKlientWydruk.billingAddressCity}}{{cKlientWydruk.billingAddressCity}}{{/if}}{{#if cKlientWydruk.billingAddressPostalCode}}{{#if cKlientWydruk.billingAddressCity}}, {{/if}}{{/if}}
{{#if cKlientWydruk.billingAddressCountry}}{{cKlientWydruk.billingAddressCountry}}<br>{{/if}}
<!-- Tax number -->
{{#if cKlientWydruk.cNumerNIP}}Tax ID: <strong>{{cKlientWydruk.cNumerNIP}}</strong>{{/if}}
<br>
<!-- Email address -->
{{#if cKlientWydruk.emailAddress}}<a href="mailto:{{cKlientWydruk.emailAddress}}" target="_blank">{{cKlientWydruk.emailAddress}}</a><br>{{/if}}
<!-- Phone number -->
{{#if cKlientWydruk.phoneNumber}}Tel: {{cKlientWydruk.phoneNumber}}{{/if}}
{{else}} No client company data. {{/if}}
</td>
<!-- Right column: title and Price Book metadata -->
<td style="width: 33.33%; vertical-align: top; text-align: right;">
<h2>Price Book</h2>
<p>
<strong>{{name}}</strong><br>
Status: {{status}}<br>
{{#if parentPriceBook.name}}Parent: {{parentPriceBook.name}}<br>{{/if}}
<span style="font-size:9pt;color:#777;">
Created: {{createdAt}}<br>
Modified: {{modifiedAt}}</span>
</p>
</td>
</tr>
</tbody>
</table>
<br>
<!-- Items table: Product name | Net price -->
<table class="product-table">
<thead>
<tr>
<th style="width: 80%;">Product Name</th>
<th style="width: 20%;" class="text-right">Net Price</th>
</tr>
</thead>
<tbody>
<!-- {{#each prices}} -->
<tr>
<td>
<!-- Product name: in order product.name -> productName -> name -> fallback -->
<!-- {{#if product.name}} -->{{product.name}}<!-- {{else}} -->
<!-- {{#if productName}} -->{{productName}}<!-- {{else}} -->
<!-- {{#if name}} -->{{name}}<!-- {{else}} -->
<span class="muted"><!-- -->No name<!-- --></span>
<!-- {{/if}} {{/if}} {{/if}} -->
</td>
<td class="text-right">
<!-- Price: listPrice -> unitPrice -> netPrice -> price -> fallback -->
<!-- {{#if listPrice}} -->{{formatCurrency listPrice}} €<!-- {{else}} -->
<!-- {{#if unitPrice}} -->{{formatCurrency unitPrice}} €<!-- {{else}} -->
<!-- {{#if netPrice}} -->{{formatCurrency netPrice}} €<!-- {{else}} -->
<!-- {{#if price}} -->{{formatCurrency price}} €<!-- {{else}} -->
<span class="muted"><!-- -->—<!-- --></span>
<!-- {{/if}} {{/if}} {{/if}} {{/if}} -->
</td>
</tr>
<!-- {{/each}} -->
</tbody>
</table>
<!-- Price Book description (optional) -->
<!-- {{#if description}} -->
<h2 style="margin-top: 10mm;">Additional Information</h2>
<p>{{description}}</p>
<!-- {{/if}} -->
