-
|
I need to create a quote (pre-sale offer) that also includes a list of BoM items of Variants and Templates part. Can you suggest if it is possible or what needs to be done to activate the same ;-) Thanks! |
Beta Was this translation helpful? Give feedback.
Answered by
virco
Jan 5, 2026
Replies: 1 comment
-
|
In case someone is interested, here is a multi-assembly BOM report template, typically for internal price map usage: {% extends "report/inventree_order_report_base.html" %}
{% load i18n %}
{% load report %}
{% load barcode %}
{% load inventree_extras %}
{% load markdownify %}
{% block header_content %}
<div style="display: grid; grid-template-columns: auto auto auto auto; align-items: center; gap: 15px; width: 100%; margin-bottom: 15px;">
<!-- Column 1: First logo -->
<img class='logo' src='{% logo_image %}' width='20' height='20'/>
<!-- Column 2: Text (takes remaining space) -->
<div class="header-text" style="white-space: nowrap;font-size: 12px;">
Intelligent Bench Solution.<br>
Modular Validation Platform.
</div>
<!-- Column 3: Second logo -->
<img class='logo' src='{% company_image customer %}' />
<div class='header-right'>
<h3 style="margin: 0,0,0,0">{% trans "Quote BoM" %} {{ prefix }}{{ reference }}</h3>
{{ customer.name }}
</div>
</div>
{% endblock header_content %}
{% block page_content %}
<style>
.part-separator {
border-top: 1px solid #ccc;
margin: 4px 0 6px 0;
width: 96%;
}
.part-text {
line-height: 1.3em;
}
</style>
<h3>{% trans "Modules" %} - {{ description }}</h3>
<table class='table table-striped table-condensed'>
<thead>
<tr>
<th>{% trans "Line" %}</th>
<th>{% trans "Part" %}</th>
<th>{% trans "Quantity" %}</th>
<th>{% trans "Unit Price" %}</th>
<th>{% trans "Total Price" %}</th>
<th>{% trans "Note" %}</th>
</tr>
</thead>
<tbody>
{% for line in lines.all|dictsort:"reference" %}
<tr >
<td style="font-size: 10px;">{{ line.reference }}</td>
<td>
<div class='thumb-container'>
<img src='{% part_image line.part height=240 %}' alt='{% trans "Part image" %}' class='part-thumb'>
</div>
<div class='part-text' style="color: #00008B;">
{{ line.part.name }}
{% if line.part.revision %}
| {{ line.part.revision }}
{% endif %}
</div>
<div class="part-separator"></div>
<div class='part-text' style="color: #333333;">
{{ line.part.description }}<br/>
</div>
{% for param in line.part.parameters.all %}
{% if param.name == "ECAD Status" %}
<span style="font-size: 10px;">
<strong>{{ param.name }}</strong>: {{ param.data }}
</span><br/>
{% endif %}
{% endfor %}
{% for param in line.part.parameters.all %}
{% if param.name == "Custom Board" %}
<span style="font-size: 10px;">
<strong>{{ param.name }}</strong>: {{ param.data }}
</span><br/>
{% endif %}
{% endfor %}
{% if line.part.bom_items.exists %}
<span style="font-size: 10px;">
<strong>BoM Sub-Parts</strong>: </span><br/>
</td>
<td> <strong>{% decimal line.quantity %} {% decimal line.part.units %}</strong></td>
<td>{% render_currency line.price max_decimal_places=2 %}</td>
<td>{% render_currency line.total_line_price max_decimal_places=2 %}</td>
<td style="font-size: 10px;">{{ line.notes }}</td>
{% for bomItm in line.part.get_bom_items %}
<tr >
<td></td>
<td>
<span style="font-size: 12px;margin-left: 5px;">
<div class='thumb-container'>
<img src='{% part_image bomItm.sub_part height=240 %}' alt='{% trans "Part image" %}' class='part-thumb'>
</div>
{{bomItm.quantity|floatformat:-2}}{% decimal bomItm.sub_part.units %} x {{ bomItm.sub_part.full_name }}
{% for param in bomItm.sub_part.parameters.all %}
{% if param.name == "count_once" %}
<span style="font-size: 10px;">
<strong>{{ param.name }}</strong>: {{ param.data }}
</span><br/>
{% endif %}
{% endfor %}
</span><br/>
</td>
<td>
<span style="font-size: 12px;padding-left: 5px; display: inline-block;">
{% multiply line.quantity bomItm.quantity float as qtyTot %}
{% with 0 as done %}
{% for param in bomItm.sub_part.parameters.all %}
{% add done 0 as done %}
{% if param.name == "count_once" and done == 0 %}
{{ bomItm.quantity|floatformat:"-1" }} {% decimal bomItm.sub_part.units %}
{% add done 1 as done %}
{% endif %}
{% if forloop.last %}
{% if done == 0 %}
{{ qtyTot|floatformat:"-2" }} {% decimal bomItm.sub_part.units %}
{% endif %}
{% endif %}
{% empty %}
{{ qtyTot|floatformat:"-2" }} {% decimal bomItm.sub_part.units %}
{% endfor %}
{% endwith %}
</span></td>
<td colspan="3"> <span style="font-size: 9px !important;margin-left: 15px;">{{ bomItm.note|default:"" }}</span></td>
{% for bomItm2 in bomItm.sub_part.bom_items.all %}
<tr >
<td></td>
<td style="padding-left: 30px;">
<div class='thumb-container'>
<img src='{% part_image bomItm2.sub_part height=240 %}' alt='{% trans "Part image" %}' class='part-thumb'>
</div>
<span style="font-size: 10px;margin-left: 5px;">
{{bomItm2.quantity|floatformat:-2}}{% decimal bomItm2.sub_part.units %} x {{ bomItm2.sub_part.full_name }}
{% for param in bomItm2.sub_part.parameters.all %}
{% if param.name == "count_once" %}
<span style="font-size: 10px;">
<strong>{{ param.name }}</strong>: {{ param.data }}
</span><br/>
{% endif %}
{% endfor %}
</span><br/>
</td>
<td><span style="font-size: 10px; display: inline-block;">
{% multiply bomItm.quantity line.quantity float as qtyTot %}
{% multiply bomItm2.quantity qtyTot float as qtyTot %}
{% with 0 as done %}
{% for param in bomItm2.sub_part.parameters.all %}
{% add done 0 as done %}
{% if param.name == "count_once" and done == 0 %}
⇒ {{ bomItm2.quantity|floatformat:"-2" }} {% decimal bomItm2.sub_part.units %}
{% add done 1 as done %}
{% endif %}
{% if forloop.last %}
{% if done == 0 %}
⇒ {{ qtyTot|floatformat:"-2" }} {% decimal bomItm2.sub_part.units %}
{% endif %}
{% endif %}
{% empty %}
⇒ {{ qtyTot|floatformat:"-2" }} {% decimal bomItm2.sub_part.units %}
{% endfor %}
{% endwith %}
</span></td>
<td colspan="3"> <span style="font-size: 9px !important;margin-left: 15px;">{{ bomItm2.note|default:"" }}</span></td>
{% for bomItm3 in bomItm2.sub_part.bom_items.all %}
<tr>
<td></td>
<td style="padding-left: 50px;">
<div class='thumb-container'>
<img src='{% part_image bomItm3.sub_part height=240 %}' alt='{% trans "Part image" %}' class='part-thumb'>
</div>
<span style="font-size: 10px;margin-left: 5px;">
{{bomItm3.quantity|floatformat:-2}}x {{ bomItm3.sub_part.full_name }}
{% for param in bomItm3.sub_part.parameters.all %}
{% if param.name == "count_once" %}
<span style="font-size: 10px;">
<strong>{{ param.name }}</strong>: {{ param.data }}
</span><br/>
{% endif %}
{% endfor %}
</span><br/>
</td>
<td><span style="font-size: 10px; display: inline-block;">
{% multiply bomItm.quantity line.quantity float as qtyTot %}
{% multiply bomItm2.quantity qtyTot float as qtyTot %}
{% multiply bomItm3.quantity qtyTot float as qtyTot %}
→ {{ qtyTot|floatformat:"-1" }} {% decimal bomItm3.sub_part.units %}
</span></td>
<td colspan="3">{{ bomItm3.note|default:"" }}</td>
{% endfor %}
{% endfor %}
{% endfor %}
</td>
{% else %}
</td>
<td><strong>{% decimal line.quantity %} {% decimal line.part.units %}</strong></td>
<td>{% render_currency line.price max_decimal_places=2 %}</td>
<td>{% render_currency line.total_line_price max_decimal_places=2 %}</td>
<td style="font-size: 10px;">{{ line.notes }}</td>
{% endif %}
</tr>
<tr style="border-bottom: 2px solid #909090; width: 80%; padding-bottom: 5px;">
</tr>
{% endfor %}
{% if extra_lines %}
<tr><th colspan='6'>{% trans "Extra Line Items" %}</th></tr>
{% for line in extra_lines.all %}
<tr>
<td><!-- No part --></td>
<td>{{ line.reference }}</td>
<td></td>
<td>{% decimal line.quantity %}</td>
<td>{% render_currency line.price max_decimal_places=2 %}</td>
<td>{% render_currency line.total_line_price max_decimal_places=2 %}</td>
<td>{{ line.notes }}</td>
</tr>
{% endfor %}
{% endif %}
<tr>
<th colspan="2" style="text-align: right;">{% trans "Assemblies (Total):" %}</th>
{% with 0 as cntModules %}
{% for line in lines.all %}
{% if line.price %}
{% add cntModules line.quantity as cntModules %}
{% endif %}
{% if forloop.last %}
<td style="text-align: left; padding-left: 10px;"> {% format_number cntModules integer=True %} pcs</td>
{% endif %}
{% endfor %}
{% endwith %}
<th colspan="2" style="text-align: right;">{% trans "Total Price:" %}</th>
<td>{% render_currency order.total_price currency=order.currency max_decimal_places=2 %}</td>
<td></td>
</tr>
<tr>
<th colspan="2" style="text-align: right;">{% trans "Total Labor:" %}</th>
{% with 0 as cntLabor %}
{% for line in lines.all %}
{% add cntLabor line.part.total_virtual_countonce_qty|default:0 as cntLabor %}
{% multiply line.quantity line.part.total_virtual_qty float as qtyTot %}
{% add cntLabor qtyTot as cntLabor %}
{% if line.part.virtual and line.part.units|lower in "hrs" %}
{% add cntLabor line.quantity as cntLabor %}
{% endif %}
{% if forloop.last %}
<td colspan="4" style="text-align: left; padding-left: 10px;"> {{ cntLabor|floatformat:"-1" }} hrs</td>
{% endif %}
{% endfor %}
{% endwith %}
<td></td>
<td></td>
</tr>
</tbody>
</table>
<h4>Reference:</h4>
<p>This quotation has been prepared to fulfill the project request as tracked in Jira issue {{ order.customer_reference|default:"N/A" }}</p>
<h3>Notes</h3>
<p>{{ order.notes }}</p>
<table style="width:100%; border-collapse: collapse; font-size: 14px;">
<thead>
<tr style="background-color:#f2f2f2;">
<th style="width:15px; padding:8px; text-align:left; border-bottom:2px solid #000;">#</th>
<th style="padding:8px; text-align:left; border-bottom:2px solid #000;">Remarks</th>
</tr>
</thead>
<tbody>
<tr>
<td style="padding:6px; border-bottom:1px solid #555;">1</td>
<td style="padding:6px; border-bottom:1px solid #555;">
Some functionality may not be delivered in the initial firmware. It will be provided later via OTA updates according to the defined priority.
</td>
</tr>
<tr>
<td style="padding:6px; border-bottom:1px solid #555;">2</td>
<td style="padding:6px; border-bottom:1px solid #555;">
For orders exceeding 30 pcs (samples) per month, a surcharge will be applied.
</td>
</tr>
<tr>
<td style="padding:6px; border-bottom:1px solid #555;">3</td>
<td style="padding:6px; border-bottom:1px solid #555;">
Prices are valid on the date the report is generated. Please consider a ±10% range for the estimated cost.
</td>
</tr>
<tr>
<td style="padding:6px; border-bottom:1px solid #555;">4</td>
<td style="padding:6px; border-bottom:1px solid #555;">
All custom board prices are based on a bulk quantity of either 5 pcs (10×10 cm) or 10 pcs (5×10 cm).
</td>
</tr>
<tr>
<td style="padding:6px; border-bottom:1px solid #555;">5</td>
<td style="padding:6px; border-bottom:1px solid #555;">
VAT is not included.
</td>
</tr>
<tr>
<td style="padding:6px; border-bottom:1px solid #555;">6</td>
<td style="padding:6px; border-bottom:1px solid #555;">
Lead time: 4–6 weeks.
</td>
</tr>
<tr>
<td style="padding:6px; border-bottom:1px solid #555;">7</td>
<td style="padding:6px; border-bottom:1px solid #555;">
Fabrication lead time (4–6 weeks) shall commence only upon completion and acceptance of the corresponding ECAD development activities.
</td>
</tr>
<tr>
<tr>
<td style="padding:6px; border-bottom:1px solid #555;">8</td>
<td style="padding:6px; border-bottom:1px solid #555;">
The quoted price represents the estimated cost for the assembly, including standard and non-standard parts. A detailed PO BoM list of sub-parts for each individual assembly can be provided on request after project kick-off and as the project progresses.
</td>
</tr>
</tbody>
</table>
{% endblock page_content %} |
Beta Was this translation helpful? Give feedback.
0 replies
Answer selected by
matmair
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
In case someone is interested, here is a multi-assembly BOM report template, typically for internal price map usage:
{% extends "report/inventree_order_report_base.html" %} {% load i18n %} {% load report %} {% load barcode %} {% load inventree_extras %} {% load markdownify %} {% block header_content %} <div style="display: grid; grid-template-columns: auto auto auto auto; align-items: center; gap: 15px; width: 100%; margin-bottom: 15px;"> <!-- Column 1: First logo --> <img class='logo' src='{% logo_image %}' width='20' height='20'/> <!-- Column 2: Text (takes remaining space) --> <div class="header-text" style="white-space: nowrap;font-size:…