Display bundle items nested under bundle in Order Printer packing slips / invoices

 
This guide shows you how to modify your Shopify Order Printer packing slip / invoice template to display bundle items (products within the bundle) nested under their dummy bundle products.
 

Prerequisite

  • Enable “Enable bundle metafields” setting in Bundle Kit > Settings > Bundle Metafields.
  • Enable “Add bundle items (products within the bundle) to orders” setting in Bundle Kit > Settings > Bundle Order.
  • Have the “Shopify Order Printer” app installed.
 

A. Packing Slip

Steps

1. Access Your Packing Slip Template
Go to Shopify admin > Apps > Shopify Order Printer > Templates > Packing slip.
 
We recommend backing up your packing slip template in case you would like to revert to the original version.
 
notion image
 
2. Locate the Line Items Section
Find this similar section in your template:
<tbody> {% for line_item in order.line_items %} <tr> <td style="text-align: left;">{{ line_item.quantity }}</td> <td style="text-align: left;">{{ line_item.title }}</td> </tr> {% endfor %} </tbody>
 
notion image
 
3. Replace with Bundle-Aware Code
Replace the entire <tbody> section with:
<tbody> {% assign nested_quantities = '' %} {% comment %}First pass: Display bundle products with their nested bundle items{% endcomment %} {% for line_item in order.line_items %} {% assign bundle_items = line_item.variant.metafields.app--5234301.bundle_items %} {% if bundle_items and bundle_items.size > 0 %} <tr> <td style="text-align: left;">{{ line_item.quantity }}</td> <td style="text-align: left;"><strong>{{ line_item.title }}</strong></td> </tr> {% for bundle_item in bundle_items %} {% assign nested_quantity = bundle_item.bundle_item_quantity | times: line_item.quantity %} <tr> <td style="text-align: left; padding-left: 20px;">{{ nested_quantity }}</td> <td style="text-align: left; padding-left: 20px; font-style: italic;"> {% if bundle_item.variant_title == "Default Title" %}{{ bundle_item.product_title }}{% else %}{{ bundle_item.product_title }} - {{ bundle_item.variant_title }}{% endif %} </td> </tr> {% comment %}Track nested quantities by variant_id{% endcomment %} {% assign variant_key = bundle_item.variant_id | append: ':' %} {% assign existing_quantity = 0 %} {% assign nested_entries = nested_quantities | split: ',' %} {% for nested_entry in nested_entries %} {% if nested_entry contains variant_key %} {% assign entry_parts = nested_entry | split: ':' %} {% assign existing_quantity = entry_parts[1] | plus: 0 %} {% assign old_entry = bundle_item.variant_id | append: ':' | append: existing_quantity %} {% assign nested_quantities = nested_quantities | remove: old_entry %} {% break %} {% endif %} {% endfor %} {% assign new_quantity = existing_quantity | plus: nested_quantity %} {% assign new_entry = bundle_item.variant_id | append: ':' | append: new_quantity %} {% if nested_quantities == blank %} {% assign nested_quantities = new_entry %} {% else %} {% assign nested_quantities = nested_quantities | append: ',' | append: new_entry %} {% endif %} {% endfor %} {% endif %} {% endfor %} {% comment %}Second pass: Display remaining quantities for each unique variant{% endcomment %} {% assign displayed_variants = ',' %} {% for line_item in order.line_items %} {% assign bundle_items = line_item.variant.metafields.app--5234301.bundle_items %} {% unless bundle_items and bundle_items.size > 0 %} {% assign variant_check = ',' | append: line_item.variant_id | append: ',' %} {% unless displayed_variants contains variant_check %} {% comment %}Calculate total quantity for this variant{% endcomment %} {% assign total_quantity = 0 %} {% for all_line_items in order.line_items %} {% assign check_bundle = all_line_items.variant.metafields.app--5234301.bundle_items %} {% unless check_bundle and check_bundle.size > 0 %} {% if all_line_items.variant_id == line_item.variant_id %} {% assign total_quantity = total_quantity | plus: all_line_items.quantity %} {% endif %} {% endunless %} {% endfor %} {% comment %}Get nested quantity for this variant{% endcomment %} {% assign nested_quantity = 0 %} {% assign variant_key = line_item.variant_id | append: ':' %} {% assign nested_entries = nested_quantities | split: ',' %} {% for nested_entry in nested_entries %} {% if nested_entry contains variant_key %} {% assign entry_parts = nested_entry | split: ':' %} {% assign nested_quantity = entry_parts[1] | plus: 0 %} {% break %} {% endif %} {% endfor %} {% assign remaining_quantity = total_quantity | minus: nested_quantity %} {% if remaining_quantity > 0 %} <tr> <td style="text-align: left;">{{ remaining_quantity }}</td> <td style="text-align: left;">{{ line_item.title }}</td> </tr> {% endif %} {% assign displayed_variants = displayed_variants | append: line_item.variant_id | append: ',' %} {% endunless %} {% endunless %} {% endfor %} </tbody>
 
4. Preview and Save
 
Original version:
notion image
 
Modified version:
notion image
 

B. Invoice

Steps

1. Access Your Invoice Template
Go to Shopify admin > Apps > Shopify Order Printer > Templates > Invoice.
 
We recommend backing up your invoice template in case you would like to revert to the original version.
 
notion image
 
2. Locate the Line Items Section
Find this similar section in your template:
{% for line_item in order.line_items %} <tr> <td>{{ line_item.quantity }}</td> <td>{{ line_item.title }} {% if line_item.line_level_discount_allocations.size > 0 %} <span class="subduedText"> {% for discount_allocation in line_item.line_level_discount_allocations %} <br>{{ discount_allocation.discount_application.title }} (-{{ discount_allocation.amount | money }}) {% endfor %} </span> {% endif %} </td> <td style="text-align: right;"> {% if line_item.original_price != line_item.final_price %} <span class="subduedText"><s>{{ line_item.original_price | money }}</s></span> {% endif %} {{ line_item.final_price | money }} </td> </tr> {% endfor %}
 
notion image
 
3. Replace with Bundle-Aware Code
Replace the entire <tbody> section with:
<tbody> {% assign nested_quantities = '' %} {% comment %}First pass: Display bundle products with their nested bundle items{% endcomment %} {% for line_item in order.line_items %} {% assign bundle_items = line_item.variant.metafields.app--20787593217.bundle_items %} {% if bundle_items and bundle_items.size > 0 %} <tr> <td>{{ line_item.quantity }}</td> <td><strong>{{ line_item.title }}</strong> {% if line_item.line_level_discount_allocations.size > 0 %} <span class="subduedText"> {% for discount_allocation in line_item.line_level_discount_allocations %} <br>{{ discount_allocation.discount_application.title }} (-{{ discount_allocation.amount | money }}) {% endfor %} </span> {% endif %} </td> <td style="text-align: right;"> {% if line_item.original_price != line_item.final_price %} <span class="subduedText"><s>{{ line_item.original_price | money }}</s></span> {% endif %} {{ line_item.final_price | money }} </td> </tr> {% comment %}Display bundle items from metafield data with their discount information{% endcomment %} {% for bundle_item in bundle_items %} {% assign nested_quantity = bundle_item.bundle_item_quantity | times: line_item.quantity %} {% comment %}Find the corresponding bundle item line item for discount information{% endcomment %} {% assign found_bundle_item_line = false %} {% for check_line_item in order.line_items %} {% if check_line_item.variant_id == bundle_item.variant_id and check_line_item.final_price == 0 and found_bundle_item_line == false %} {% assign has_bundle_kit_discount = false %} {% for discount_allocation in check_line_item.line_level_discount_allocations %} {% if discount_allocation.discount_application.title contains 'Bundle Kit' %} {% assign has_bundle_kit_discount = true %} {% break %} {% endif %} {% endfor %} {% if has_bundle_kit_discount %} {% assign found_bundle_item_line = true %} <tr> <td style="padding-left: 20px;">{{ nested_quantity }}</td> <td style="padding-left: 20px; font-style: italic;"> {% if bundle_item.variant_title == "Default Title" %}{{ bundle_item.product_title }}{% else %}{{ bundle_item.product_title }} - {{ bundle_item.variant_title }}{% endif %} {% if check_line_item.line_level_discount_allocations.size > 0 %} <span class="subduedText"> {% for discount_allocation in check_line_item.line_level_discount_allocations %} <br>{{ discount_allocation.discount_application.title }} (-{{ discount_allocation.amount | money }}) {% endfor %} </span> {% endif %} </td> <td style="text-align: right; font-style: italic;"> {% if check_line_item.original_price != check_line_item.final_price %} <span class="subduedText"><s>{{ check_line_item.original_price | money }}</s></span> {% endif %} {{ check_line_item.final_price | money }} </td> </tr> {% endif %} {% endif %} {% endfor %} {% comment %}If no bundle item line found, show generic nested item{% endcomment %} {% unless found_bundle_item_line %} <tr> <td style="padding-left: 20px;">{{ nested_quantity }}</td> <td style="padding-left: 20px; font-style: italic;"> {% if bundle_item.variant_title == "Default Title" %}{{ bundle_item.product_title }}{% else %}{{ bundle_item.product_title }} - {{ bundle_item.variant_title }}{% endif %} </td> <td style="text-align: right; font-style: italic;">$0.00</td> </tr> {% endunless %} {% comment %}Track nested quantities by variant_id{% endcomment %} {% assign variant_key = bundle_item.variant_id | append: ':' %} {% assign existing_quantity = 0 %} {% assign nested_entries = nested_quantities | split: ',' %} {% for nested_entry in nested_entries %} {% if nested_entry contains variant_key %} {% assign entry_parts = nested_entry | split: ':' %} {% assign existing_quantity = entry_parts[1] | plus: 0 %} {% assign old_entry = bundle_item.variant_id | append: ':' | append: existing_quantity %} {% assign nested_quantities = nested_quantities | remove: old_entry %} {% break %} {% endif %} {% endfor %} {% assign new_quantity = existing_quantity | plus: nested_quantity %} {% assign new_entry = bundle_item.variant_id | append: ':' | append: new_quantity %} {% if nested_quantities == blank %} {% assign nested_quantities = new_entry %} {% else %} {% assign nested_quantities = nested_quantities | append: ',' | append: new_entry %} {% endif %} {% endfor %} {% endif %} {% endfor %} {% comment %}Second pass: Display remaining quantities for each unique variant{% endcomment %} {% assign displayed_variants = ',' %} {% for line_item in order.line_items %} {% assign bundle_items = line_item.variant.metafields.app--20787593217.bundle_items %} {% comment %}Check if this is a bundle item line item (has $0 price and Bundle Kit discount){% endcomment %} {% assign is_bundle_item_line = false %} {% if line_item.final_price == 0 and line_item.line_level_discount_allocations.size > 0 %} {% for discount_allocation in line_item.line_level_discount_allocations %} {% if discount_allocation.discount_application.title contains 'Bundle Kit' %} {% assign is_bundle_item_line = true %} {% break %} {% endif %} {% endfor %} {% endif %} {% unless bundle_items and bundle_items.size > 0 or is_bundle_item_line %} {% assign variant_check = ',' | append: line_item.variant_id | append: ',' %} {% unless displayed_variants contains variant_check %} {% comment %}Calculate total quantity for this variant (excluding bundle products and bundle item lines){% endcomment %} {% assign total_quantity = 0 %} {% for all_line_items in order.line_items %} {% assign check_bundle = all_line_items.variant.metafields.app--20787593217.bundle_items %} {% assign check_is_bundle_item_line = false %} {% if all_line_items.final_price == 0 and all_line_items.line_level_discount_allocations.size > 0 %} {% for discount_allocation in all_line_items.line_level_discount_allocations %} {% if discount_allocation.discount_application.title contains 'Bundle Kit' %} {% assign check_is_bundle_item_line = true %} {% break %} {% endif %} {% endfor %} {% endif %} {% unless check_bundle and check_bundle.size > 0 or check_is_bundle_item_line %} {% if all_line_items.variant_id == line_item.variant_id %} {% assign total_quantity = total_quantity | plus: all_line_items.quantity %} {% endif %} {% endunless %} {% endfor %} {% comment %}Get nested quantity for this variant{% endcomment %} {% assign nested_quantity = 0 %} {% assign variant_key = line_item.variant_id | append: ':' %} {% assign nested_entries = nested_quantities | split: ',' %} {% for nested_entry in nested_entries %} {% if nested_entry contains variant_key %} {% assign entry_parts = nested_entry | split: ':' %} {% assign nested_quantity = entry_parts[1] | plus: 0 %} {% break %} {% endif %} {% endfor %} {% assign remaining_quantity = total_quantity | minus: nested_quantity %} {% if remaining_quantity > 0 %} <tr> <td>{{ remaining_quantity }}</td> <td>{{ line_item.title }} {% if line_item.line_level_discount_allocations.size > 0 %} <span class="subduedText"> {% for discount_allocation in line_item.line_level_discount_allocations %} <br>{{ discount_allocation.discount_application.title }} (-{{ discount_allocation.amount | money }}) {% endfor %} </span> {% endif %} </td> <td style="text-align: right;"> {% if line_item.original_price != line_item.final_price %} <span class="subduedText"><s>{{ line_item.original_price | money }}</s></span> {% endif %} {{ line_item.final_price | money }} </td> </tr> {% endif %} {% assign displayed_variants = displayed_variants | append: line_item.variant_id | append: ',' %} {% endunless %} {% endunless %} {% endfor %} <tr> <td colspan="2" style="text-align: right;">{{ "invoice_template.subtotal_label" | t }}</td> <td style="text-align: right;">{{ order.line_items_subtotal_price | money }}</td> </tr> {% assign has_shipping_discount = false %} {% for discount_application in order.discount_applications %} {% if discount_application.target_type == 'shipping_line' %} {% assign has_shipping_discount = true %} {% endif %} {% if discount_application.target_selection == 'all' and discount_application.target_type != 'shipping_line' %} <tr> <td colspan="2" style="text-align: right;">{% if discount_application.title %}<span class="subduedText">{{ discount_application.title }}</span>{% endif %}</td> <td style="text-align: right;">-{{ discount_application.total_allocated_amount | money }}</td> </tr> {% endif %} {% endfor %} <tr> <td colspan="2" style="text-align: right;">{{ "invoice_template.tax_label" | t }}</td> <td style="text-align: right;">{{ order.tax_price | money }}</td> </tr> {% if order.shipping_address %} <tr> <td colspan="2" style="text-align: right;">{{ "invoice_template.shipping_label" | t }}</td> <td style="text-align: right;">{% if has_shipping_discount %}{{ "invoice_template.free_shipping" | t }}{% else %}{{ order.shipping_price | money }}{% endif %}</td> </tr> {% endif %} <tr> <td colspan="2" style="text-align: right;"><strong>{{ "invoice_template.total_label" | t }}</strong></td> <td style="text-align: right;"><strong>{{ order.total_price | money }}</strong></td> </tr> {% if order.net_payment != order.total_net_amount %} <tr> <td colspan="2" style="text-align: right;">{{ "invoice_template.total_paid_label" | t }}</td> <td style="text-align: right;">{{ order.net_payment | money }}</td> </tr> {% endif %} {% if order.total_refunded_amount > 0 %} <tr> <td colspan="2" style="text-align: right;">{{ "invoice_template.total_refunded_label" | t }}</td> <td style="text-align: right;">-{{ order.total_refunded_amount | money }}</td> </tr> {% endif %} {% if order.net_payment != order.total_net_amount %} <tr> <td colspan="2" style="text-align: right;"><strong>{{ "invoice_template.outstanding_amount_label" | t }}</strong></td> <td style="text-align: right;"><strong>{{ order.total_price | minus: order.net_payment | money }}</strong></td> </tr> {% endif %} </tbody>
 
4. Preview and Save
 
Original version:
notion image
 
Modified version:
notion image
Â