Displaying bundle items in a sales invoice

I have created product bundles for items. When I create a sales order and a sales invoice, the product bundle is added to those. However, in the invoice I want to print actual product names that are in a product bundle. For this I thought I could use ‘packed_items’ but not sure how to edit invoice format to do this.

Example scenario,

  1. Let’s say we have three products
- Product A
- Product B
- Product C
  1. I create a product bundle named ‘New Product Bundle’ by adding 1 quantity each from above products.

  2. Create a sales order and create a sales invoice through SO, by adding 2 quantity of ‘New Product Bundle’

  3. Now when I print the invoice, I can see that the ‘New Product Bundle’ is shown in the invoice with a quantity of 2.

  4. Instead of showing ‘New Product Bundle’ in the invoice print format, I want to show the actual products which were associated with it.

I added following code to custom html but it is showing nothing,
{%- for item in doc.packed_items -%}



{{ item.item_code }} - {{item.item_name}}


{%- endfor -%}

Hi @tglk

{%- for item in doc.packed_items -%}


{{ item.item_code }} - {{item.item_name}}


{%- endfor -%}

The code is correct,
Any error during print? Can you share the complete code?

Hi @rohit_w

Below is the complete code.

<style>
	.print-format table, .print-format tr, 
	.print-format td, .print-format div, .print-format p {
		font-family: Monospace;
		line-height: 200%;
		vertical-align: middle;
	}
	@media screen {
		.print-format {
			width: 4in;
			padding: 0.25in;
			min-height: 8in;
		}
	}
</style>

<p class="text-center">
	{{ doc.company }}<br>
	{{ doc.select_print_heading or _("Invoice") }}<br>
</p>
<p>
	<b>{{ _("Receipt No") }}:</b> {{ doc.name }}<br>
	<b>{{ _("Date") }}:</b> {{ doc.get_formatted("posting_date") }}<br>
	<b>{{ _("Customer") }}:</b> {{ doc.customer_name }}
</p>

<hr>
<table class="table table-condensed cart no-border">
	<thead>
		<tr>
			<th width="50%">{{ _("Item") }}</b></th>
			<th width="25%" class="text-right">{{ _("Qty") }}</th>
			<th width="25%" class="text-right">{{ _("Amount") }}</th>
		</tr>
	</thead>
	<tbody>

		{%- for i in doc.packed_items -%}
		<tr>
			<td>
				{{ i.item_code }} - {{ i.item_name }}
			</td>

		</tr>
		{%- endfor -%}

		{%- for item in doc.items -%}
		<tr>
			<td>
				{{ item.item_code }}
				{%- if item.item_name != item.item_code -%}
					<br>{{ item.item_name }}{%- endif -%}
			</td>
			<td class="text-right">{{ item.qty }}<br>@ {{ item.get_formatted("rate") }}</td>
			<td class="text-right">{{ item.get_formatted("amount") }}</td>
		</tr>
		{%- endfor -%}
	</tbody>
</table>
<table class="table table-condensed no-border">
	<tbody>
		<tr>
			<td class="text-right" style="width: 70%">
				{{ _("Net Total") }}
			</td>
			<td class="text-right">
				{{ doc.get_formatted("net_total") }}
			</td>
		</tr>
		{%- for row in doc.taxes -%}
		{%- if not row.included_in_print_rate -%}
		<tr>
			<td class="text-right" style="width: 70%">
				{{ row.description }}
			</td>
			<td class="text-right">
				{{ row.get_formatted("tax_amount", doc) }}
			</td>
		</tr>
		{%- endif -%}
		{%- endfor -%}
		{%- if doc.discount_amount -%}
		<tr>
			<td class="text-right" style="width: 75%">
				{{ _("Discount") }}
			</td>
			<td class="text-right">
				{{ doc.get_formatted("discount_amount") }}
			</td>
		</tr>
		{%- endif -%}
		<tr>
			<td class="text-right" style="width: 75%">
				<b>{{ _("Grand Total") }}</b>
			</td>
			<td class="text-right">
				{{ doc.get_formatted("grand_total") }}
			</td>
		</tr>
	</tbody>
</table>
{% if doc.get("taxes", filters={"included_in_print_rate": 1}) %}
<hr>
<p><b>Taxes Included:</b></p>
<table class="table table-condensed no-border">
	<tbody>
		{%- for row in doc.taxes -%}
		{%- if row.included_in_print_rate -%}
		<tr>
			<td class="text-right" style="width: 70%">
				{{ row.description }}
			</td>
			<td class="text-right">
				{{ row.get_formatted("tax_amount_after_discount_amount", doc) }}
			</td>
		<tr>
		{%- endif -%}
		{%- endfor -%}
	</tbody>
</table>
{%- endif -%}
<hr>
<p>{{ doc.terms or "" }}</p>
<p class="text-center">{{ _("Thank you, please visit again.") }}</p>

Hi @rohit_w

Keep the packing items in a separate table, currently you are adding the packing items into the sales invoice items.
Add below code after the sales invoice items table

<table class="table table-condensed cart no-border">
	<thead>
		<tr>
			<th width="100%">{{ _("Item Name") }}</b></th>
		</tr>
	</thead>
	<tbody>

    	{%- for i in doc.packed_items -%}
	<tr>
		<td>
			{{ i.item_code }} - {{ i.item_name }}
		</td>

	</tr>
	{%- endfor -%}
</tbody>
</table>

I added above code external to the invoice item table and it is not still showing.

My requirement is to print all the items of the bundle in the invoice. Even if I get packed items printed, I will need a way to get quantity and unit price of each item. Is there a way that I can query these information and print in the invoice.

It seems that packing items table is blank

For quantity use: i.qty
for rate use : frappe.db.get_value(‘Item Price’, {‘item_code’: i.item_code, ‘price_list’: doc.selling_price_list}, ‘price_list_rate’)

Thanks @rohit_w!

I will be having lot of other question regarding these. Is there any documentation related to this where I can read and do my homework before asking questions on the forum?

You can check the videos on ERPNext youtube channel and the API Docs:

I often find myself browsing the source as well.

Old post resurrection.
I too am having this same problem.

I introduced product bundles which perfectly fits our needs.
Delivery Note - customize / add packed items (table) under items and all is perfect.

Sales Invoice - customize / add packed items (table) under items and nothing shows in the preview.

Is there a problem with the actual packed items table once its passed to a Sales Invoice?
I have tried un both draft and submitted with same results.

I also tried the custom html variant above with the same reults - showed ok in delivery not but nothing in sales invoice.

Thanks

Brent

How about the batch expiry date? How can i also show it on packed items list?

Ok so it is not working in the sales invoice because the object is not the same.

I found a way to do it (not clean but you are free to clean it) :

{%- for item in frappe.get_doc('Product Bundle', doc.items[0].item_code).items -%}


{{item.parent}} is composed of : {{ item.item_code }} - {{item.description}}


{%- endfor -%}