[IMP] delivery, stock: group delivery slip packages

This commit makes it so if a delivery slip contains 1 or more packages
then move lines will be split by package (and non-package) groups with a
"section line" between them. This only applies to when a stock.picking
is 'State=Done'.

In order to accomodate complexity of splitting by package + grouping by
product unless printing serial numbers/lots + template inheritance,
reoccurring parts of the template are split into their own templates and
called. Relevant inheritance has been updated to match.

Additionally, picking.shipping_weight calculation has been updated so if
a pack.weight = 0 then calculation will default to the calculated
product weight. This prevents inconsistency between the "Total Weight"
at the top of the Delivery Slip and the package sections' displayed
weights. To distinguish which value is being used, package sections that
use the total product weight rather than the pack.weight have
"(estimated)" after it.

This completes subsection 3 of overall Improve delivery slip task.

Task: 2039720
This commit is contained in:
Tiffany Chang (tic)
2020-07-03 11:54:08 +00:00
parent 0accbd6e69
commit d20467bb6a
3 changed files with 142 additions and 43 deletions
+5 -3
View File
@@ -66,7 +66,8 @@ class StockPicking(models.Model):
@api.depends('move_line_ids.result_package_id', 'move_line_ids.result_package_id.shipping_weight', 'weight_bulk')
def _compute_shipping_weight(self):
for picking in self:
picking.shipping_weight = picking.weight_bulk + sum([pack.shipping_weight for pack in picking.package_ids])
# if shipping weight is not assigned => default to calculated product weight
picking.shipping_weight = picking.weight_bulk + sum([pack.shipping_weight or pack.weight for pack in picking.package_ids])
def _get_default_weight_uom(self):
return self.env['product.template']._get_weight_uom_name_from_ir_config_parameter()
@@ -83,8 +84,9 @@ class StockPicking(models.Model):
carrier_tracking_url = fields.Char(string='Tracking URL', compute='_compute_carrier_tracking_url')
weight_uom_name = fields.Char(string='Weight unit of measure label', compute='_compute_weight_uom_name', readonly=True, default=_get_default_weight_uom)
package_ids = fields.Many2many('stock.quant.package', compute='_compute_packages', string='Packages')
weight_bulk = fields.Float('Bulk Weight', compute='_compute_bulk_weight')
shipping_weight = fields.Float("Weight for Shipping", compute='_compute_shipping_weight', help="Total weight of the packages and products which are not in a package. That's the weight used to compute the cost of the shipping.")
weight_bulk = fields.Float('Bulk Weight', compute='_compute_bulk_weight', help="Total weight of products which are not in a package.")
shipping_weight = fields.Float("Weight for Shipping", compute='_compute_shipping_weight',
help="Total weight of packages and products not in a package. Packages with no shipping weight specified will default to their products' total weight. This is the weight used to compute the cost of the shipping.")
is_return_picking = fields.Boolean(compute='_compute_return_picking')
return_label_ids = fields.One2many('ir.attachment', compute='_compute_return_label')
+39 -7
View File
@@ -6,7 +6,7 @@
<p t-field="o.carrier_id"/>
</div>
<div t-if="o.shipping_weight" class="col-auto">
<strong>Weight:</strong>
<strong>Total Weight:</strong>
<br/>
<span t-field="o.shipping_weight"/>
<span t-field="o.weight_uom_name"/>
@@ -22,19 +22,51 @@
<th t-if="has_hs_code"><strong>HS Code</strong></th>
</xpath>
<xpath expr="//table[@name='stock_move_table']/tbody/tr" position="inside">
<td t-if="has_hs_code"><span t-field="move.product_id.hs_code"/></td>
</xpath>
<xpath expr="//table[@name='stock_move_line_table']/thead/tr" position="inside">
<th t-if="has_hs_code"><strong>HS Code</strong></th>
</xpath>
<xpath expr="//t[@name='move_lines_has_serial']/tr" position="inside">
</template>
<!-- HS Code to table rows-->
<template id="stock_report_delivery_has_serial_move_line_inherit_delivery" inherit_id="stock.stock_report_delivery_has_serial_move_line">
<xpath expr="//td[@name='move_line_lot_qty_done']" position="after">
<td t-if="has_hs_code"><span t-field="move_line.product_id.hs_code"/></td>
</xpath>
<xpath expr="//t[@name='aggregated_move_lines']/tr" position="inside">
</template>
<template id="stock_report_delivery_aggregated_move_lines_inherit_delivery" inherit_id="stock.stock_report_delivery_aggregated_move_lines">
<xpath expr="//td[@name='move_line_aggregated_qty_done']" position="after">
<td t-if="has_hs_code"><span t-esc="aggregated_lines[line]['hs_code']"/></td>
</xpath>
</template>
<!-- package related "section lines" -->
<template id="stock_report_delivery_package_section_line_inherit_delivery" inherit_id="stock.stock_report_delivery_package_section_line">
<!-- Add additional Package section line info -->
<xpath expr="//td[@name='package_info']" position="inside">
<t t-if="package.shipping_weight or package.weight">
<!-- assume manually typed in value = priority -->
<t t-if="package.shipping_weight">
<span> - Weight: </span>
<span t-field="package.shipping_weight"/>
<span t-field="package.weight_uom_name"/>
</t>
<!-- otherwise default to calculated value -->
<t t-else="">
<span> - Weight (estimated): </span>
<span t-field="package.weight"/>
<span t-field="package.weight_uom_name"/>
</t>
</t>
</xpath>
</template>
<template id="delivery_stock_report_delivery_no_package_section_line" inherit_id="stock.stock_report_delivery_no_package_section_line">
<!-- Add additional No Package section line info -->
<xpath expr="//td[@name='no_package_info']" position="inside">
<t t-if="o.weight_bulk">
<span> - Weight: </span>
<span t-field="o.weight_bulk"/>
<span t-field="o.weight_uom_name"/>
</t>
</xpath>
</template>
</odoo>
+98 -33
View File
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<template id="report_delivery_document">
<t t-call="web.html_container">
<t t-call="web.external_layout">
@@ -70,39 +69,58 @@
</tr>
</thead>
<tbody>
<!-- If printing lots/serial numbers => keep products in original lines -->
<t t-if="has_serial_number" name="move_lines_has_serial">
<tr t-foreach="o.move_line_ids" t-as="move_line">
<td>
<span t-field="move_line.product_id"/>
<p t-if="move_line.move_id.description_picking != move_line.product_id.name">
<span t-field="move_line.move_id.description_picking"/>
</p>
</td>
<t t-if="has_serial_number" name="move_line_lot">
<td><span t-field="move_line.lot_id.name"/></td>
<!-- This part gets complicated with different use cases:
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">
<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>
<td class="text-center">
<span t-field="move_line.qty_done"/>
<span t-field="move_line.product_uom_id"/>
</td>
</tr>
<!-- 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="package_move_lines" t-value="o.move_line_ids.filtered(lambda l: not l.result_package_id)"/>
<t t-if="package_move_lines">
<t t-call="stock.stock_report_delivery_no_package_section_line"/>
<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>
<t t-else="">
<t t-set="aggregated_lines" t-value="package_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>
<!-- 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()"/>
<tr t-foreach="aggregated_lines" t-as="line">
<td>
<span t-esc="aggregated_lines[line]['name']"/>
<p t-if="aggregated_lines[line]['description']">
<span t-esc="aggregated_lines[line]['description']"/>
</p>
</td>
<td class="text-center">
<span t-esc="aggregated_lines[line]['qty_done']"/>
<span t-esc="aggregated_lines[line]['product_uom']"/>
</td>
</tr>
<!-- 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>
@@ -154,10 +172,57 @@
</t>
</template>
<!-- templates for easier extension + cut back on repeat code due to multiple conditionals -->
<!-- move line(s) printing for tables -->
<template id="stock_report_delivery_has_serial_move_line">
<td>
<span t-field="move_line.product_id"/>
<p t-if="move_line.move_id.description_picking != move_line.product_id.name">
<span t-field="move_line.move_id.description_picking"/>
</p>
</td>
<t t-if="has_serial_number" name="move_line_lot">
<td><span t-field="move_line.lot_id.name"/></td>
</t>
<td class="text-center" name="move_line_lot_qty_done">
<span t-field="move_line.qty_done"/>
<span t-field="move_line.product_uom_id"/>
</td>
</template>
<template id="stock_report_delivery_aggregated_move_lines">
<tr t-foreach="aggregated_lines" t-as="line">
<td>
<span t-esc="aggregated_lines[line]['name']"/>
<p t-if="aggregated_lines[line]['description']">
<span t-esc="aggregated_lines[line]['description']"/>
</p>
</td>
<td class="text-center" name="move_line_aggregated_qty_done">
<span t-esc="aggregated_lines[line]['qty_done']"/>
<span t-esc="aggregated_lines[line]['product_uom']"/>
</td>
</tr>
</template>
<!-- package related "section lines" -->
<template id="stock_report_delivery_package_section_line">
<tr t-att-class="'bg-200 font-weight-bold o_line_section'">
<td colspan="99" name="package_info">
<span t-field="package.name"/>
</td>
</tr>
</template>
<template id="stock_report_delivery_no_package_section_line">
<tr t-att-class="'bg-200 font-weight-bold o_line_section'">
<td colspan="99" name="no_package_info">
<span>Products with no package assigned</span>
</td>
</tr>
</template>
<template id="report_deliveryslip">
<t t-foreach="docs" t-as="o">
<t t-call="stock.report_delivery_document" t-lang="o.partner_id.lang"/>
</t>
</template>
</odoo>