Skip to content

Instantly share code, notes, and snippets.

@almet
Last active April 28, 2022 14:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save almet/fcef4c813c249d3d62ee37f9e6e843a8 to your computer and use it in GitHub Desktop.
Save almet/fcef4c813c249d3d62ee37f9e6e843a8 to your computer and use it in GitHub Desktop.
Add packaging quanity to Odoo report delivery. Permet d'ajouter le nombre de cartons à côté du nombre d'unités commandées, ainsi que le total, et quelques autres changements mineurs
<?xml version="1.0"?>
<t t-name="stock.report_delivery_document">
<t t-call="web.html_container">
<t t-call="web.external_layout">
<t t-set="o" t-value="o.with_context(lang=o.partner_id.lang)"/>
<t t-set="partner" t-value="o.partner_id or (o.move_lines and o.move_lines[0].partner_id) or False"/>
<div class="page">
<h2><span t-field="partner.self.name"/></h2>
<div class="row">
<div class="col-6" name="div_outgoing_address">
<div t-if="o.move_ids_without_package and o.move_ids_without_package[0].partner_id and o.move_ids_without_package[0].partner_id.id != o.partner_id.id">
<span><strong>Delivery Address:</strong></span>
<div t-field="o.move_ids_without_package[0].partner_id" t-options="{&quot;widget&quot;: &quot;contact&quot;, &quot;fields&quot;: [&quot;address&quot;, &quot;name&quot;, &quot;phone&quot;], &quot;no_marker&quot;: True, &quot;phone_icons&quot;: True}"/>
</div>
<div t-if="o.picking_type_id.code != 'internal' and (not o.move_ids_without_package or not o.move_ids_without_package[0].partner_id) and o.picking_type_id.warehouse_id.partner_id">
<span><strong>Warehouse Address:</strong></span>
<div t-field="o.picking_type_id.warehouse_id.partner_id" t-options="{&quot;widget&quot;: &quot;contact&quot;, &quot;fields&quot;: [&quot;address&quot;, &quot;name&quot;, &quot;phone&quot;], &quot;no_marker&quot;: True, &quot;phone_icons&quot;: True}"/>
</div>
<div t-if="o.picking_type_id.code=='incoming' and partner">
<span><strong>Vendor Address:</strong></span>
</div>
<div t-if="o.picking_type_id.code=='internal' and partner">
<span><strong>Warehouse Address:</strong></span>
</div>
<div t-if="partner" name="partner_header">
<span t-field="partner.self.phone"/>
<p t-if="partner.sudo().vat"><t t-esc="o.company_id.country_id.vat_label or 'Tax ID'"/>: <span t-field="partner.sudo().vat"/></p>
</div>
<div t-if="partner">
<span><span t-field="partner.street"/>&amp;nbsp;<span t-field="partner.street2"/>&amp;nbsp;<span t-field="partner.zip"/>&amp;nbsp;<span t-field="partner.city"/></span>
</div>
</div>
<div class="col-5 offset-1" name="div_incoming_address">
<div t-if="partner.x_hours">
<span><span t-field="partner.x_hours"/></span>
</div>
</div>
</div>
<br />
<h4>
Bon de livraison
</h4>
<div class="row mt32 mb32">
<div t-if="o.origin" class="col-auto" name="div_origin">
<strong>N° de BL:</strong>
<p t-field="o.name"/>
</div>
<div t-if="o.origin" class="col-auto" name="div_origin">
<strong>Commande:</strong>
<p t-field="o.origin"/>
</div>
<div t-if="o.state" class="col-auto" name="div_sched_date">
<strong>Date:</strong>
<t t-if="o.state == 'done'">
<p t-field="o.date_done"/>
</t>
<t t-if="o.state != 'done'">
<p t-field="o.scheduled_date"/>
</t>
</div>
</div>
<table class="table table-sm" t-if="o.state!='done'" name="stock_move_table">
<thead>
<tr>
<th>Colisage</th>
<th name="th_sm_product"><strong>Product</strong></th>
<th name="th_sm_ordered"><strong>Commande</strong></th>
</tr>
</thead>
<tbody>
<t t-set="lines" t-value="o.move_lines.filtered(lambda x: x.product_uom_qty)"/>
<tr t-foreach="lines" t-as="move">
<td>
<span t-foreach="move.product_id.packaging_ids" t-as="packaging">
<span t-esc="int(move.product_uom_qty // packaging.qty)"/>
<span t-if="move.product_uom_qty % packaging.qty">
+ <span t-esc="int(move.product_uom_qty % packaging.qty)"/>
</span>
</span>
</td>
<td>
<span t-field="move.product_id"/>
<p t-if="move.description_picking != move.product_id.name and move.description_picking != move.product_id.display_name">
<span t-field="move.description_picking"/>
</p>
</td>
<td>
<span t-field="move.product_uom_qty"/>
<span t-field="move.product_uom"/>
</td>
</tr>
<tr><td>
<t t-set="packaging_count" t-value="0" />
<t t-foreach="lines" t-as="move">
<t t-foreach="move.product_id.packaging_ids" t-as="packaging">
<t t-set="current_packaging" t-value="int(move.product_uom_qty // packaging.qty)" />
<t t-set="packaging_count" t-value="packaging_count + current_packaging"/>
</t>
<t t-if="move_last">
<t t-if="packaging_count"><t t-out="packaging_count" /> cartons</t>
</t>
</t>
</td><td></td><td></td></tr>
</tbody>
</table>
<table class="table table-sm mt48" t-if="o.move_line_ids and o.state=='done'" name="stock_move_line_table">
<t t-set="has_serial_number" t-value="False"/>
<t t-set="has_serial_number" t-value="o.move_line_ids.mapped('lot_id')" groups="stock.group_lot_on_delivery_slip"/>
<thead>
<tr>
<th name="th_sml_product"><strong>Product</strong></th>
<t name="lot_serial" t-if="has_serial_number">
<th>
Lot/Serial Number
</th>
</t>
<th name="th_sml_qty_ordered" class="text-center" t-if="not has_serial_number">
<strong>Ordered</strong>
</th>
<th name="th_sml_quantity" class="text-center"><strong>Delivered</strong></th>
</tr>
</thead>
<tbody>
<!-- This part gets complicated with different use cases (additional use cases in extensions of this report):
1. If serial numbers are used and set to print on delivery slip => print lines as is, otherwise group them by overlapping
product + description + uom combinations
2. If any packages are assigned => split products up by package (or non-package) and then apply use case 1 -->
<!-- If has destination packages => create sections of corresponding products -->
<t t-if="o.has_packages" name="has_packages">
<t t-set="packages" t-value="o.move_line_ids.mapped('result_package_id')"/>
<t t-foreach="packages" t-as="package">
<t t-call="stock.stock_report_delivery_package_section_line"/>
<t t-set="package_move_lines" t-value="o.move_line_ids.filtered(lambda l: l.result_package_id == package)"/>
<!-- If printing lots/serial numbers => keep products in original lines -->
<t t-if="has_serial_number">
<tr t-foreach="package_move_lines" t-as="move_line">
<t t-call="stock.stock_report_delivery_has_serial_move_line"/>
</tr>
</t>
<!-- If not printing lots/serial numbers => merge lines with same product+description+uom -->
<t t-else="">
<t t-set="aggregated_lines" t-value="package_move_lines._get_aggregated_product_quantities()"/>
<t t-call="stock.stock_report_delivery_aggregated_move_lines"/>
</t>
</t>
<!-- Make sure we do another section for package-less products if they exist -->
<t t-set="move_lines" t-value="o.move_line_ids.filtered(lambda l: not l.result_package_id)"/>
<t t-if="move_lines" name="no_package_move_lines">
<t t-call="stock.stock_report_delivery_no_package_section_line" name="no_package_section"/>
<t t-if="has_serial_number">
<tr t-foreach="move_lines" t-as="move_line">
<t t-call="stock.stock_report_delivery_has_serial_move_line"/>
</tr>
</t>
<t t-else="">
<t t-set="aggregated_lines" t-value="move_lines._get_aggregated_product_quantities()"/>
<t t-if="aggregated_lines">
<t t-call="stock.stock_report_delivery_aggregated_move_lines"/>
</t>
</t>
</t>
</t>
<!-- No destination packages -->
<t t-else="">
<!-- If printing lots/serial numbers => keep products in original lines -->
<t t-if="has_serial_number">
<tr t-foreach="o.move_line_ids" t-as="move_line">
<t t-call="stock.stock_report_delivery_has_serial_move_line"/>
</tr>
</t>
<!-- If not printing lots/serial numbers => merge lines with same product -->
<t t-else="" name="aggregated_move_lines">
<t t-set="aggregated_lines" t-value="o.move_line_ids._get_aggregated_product_quantities()"/>
<t t-call="stock.stock_report_delivery_aggregated_move_lines"/>
</t>
</t>
</tbody>
</table>
<t t-set="backorders" t-value="o.backorder_ids.filtered(lambda x: x.state not in ('done', 'cancel'))"/>
<t t-if="o.backorder_ids and backorders">
<p class="mt-5">
<span>Remaining quantities not yet delivered:</span>
</p>
<table class="table table-sm" name="stock_backorder_table" style="table-layout: fixed;">
<thead>
<tr>
<th name="th_sb_product"><strong>Product</strong></th>
<th/>
<th name="th_sb_quantity" class="text-center"><strong>Quantity</strong></th>
</tr>
</thead>
<tbody>
<t t-foreach="backorders" t-as="backorder">
<t t-set="bo_lines" t-value="backorder.move_lines.filtered(lambda x: x.product_uom_qty)"/>
<tr t-foreach="bo_lines" t-as="bo_line">
<td class="w-auto">
<span t-field="bo_line.product_id"/>
<p t-if="bo_line.description_picking != bo_line.product_id.name and bo_line.description_picking != bo_line.product_id.display_name">
<span t-field="bo_line.description_picking"/>
</p>
</td>
<td/>
<td class="text-center w-auto">
<span t-field="bo_line.product_uom_qty"/>
<span t-field="bo_line.product_uom"/>
</td>
</tr>
</t>
</tbody>
</table>
</t>
<div t-if="o.signature" class="mt32 ml64 mr4" name="signature">
<div class="offset-8">
<strong>Signature</strong>
</div>
<div class="offset-8">
<img t-att-src="image_data_uri(o.signature)" style="max-height: 4cm; max-width: 8cm;"/>
</div>
<div class="offset-8 text-center">
<p t-field="o.partner_id.name"/>
</div>
</div>
</div>
</t>
</t>
</t>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment