[IMP] sale_stock: extend replenishment report

Adds Sale Order as consuming document for the report.
Also, make the SO line `warehouse_id` field related to SO warehouse.

task-2058495
This commit is contained in:
svs-odoo
2020-07-31 12:36:54 +00:00
parent 38018469a7
commit 61300f6817
8 changed files with 110 additions and 4 deletions
+1
View File
@@ -30,6 +30,7 @@ Preferences
'views/stock_production_lot_views.xml',
'views/report_invoice.xml',
'views/res_users_views.xml',
'report/report_stock_forecasted.xml',
'report/sale_order_report_templates.xml',
'report/stock_report_deliveryslip.xml',
'data/sale_stock_data.xml',
+2 -4
View File
@@ -263,7 +263,7 @@ class SaleOrderLine(models.Model):
scheduled_date = fields.Datetime(compute='_compute_qty_at_date')
free_qty_today = fields.Float(compute='_compute_qty_at_date')
qty_available_today = fields.Float(compute='_compute_qty_at_date')
warehouse_id = fields.Many2one('stock.warehouse', compute='_compute_qty_at_date')
warehouse_id = fields.Many2one(related='order_id.warehouse_id')
qty_to_deliver = fields.Float(compute='_compute_qty_to_deliver')
is_mto = fields.Boolean(compute='_compute_is_mto')
display_qty_widget = fields.Boolean(compute='_compute_qty_to_deliver')
@@ -278,7 +278,7 @@ class SaleOrderLine(models.Model):
else:
line.display_qty_widget = False
@api.depends('product_id', 'customer_lead', 'product_uom_qty', 'product_uom', 'order_id.warehouse_id', 'order_id.commitment_date')
@api.depends('product_id', 'customer_lead', 'product_uom_qty', 'product_uom', 'order_id.commitment_date')
def _compute_qty_at_date(self):
""" Compute the quantity forecasted of product at delivery date. There are
two cases:
@@ -292,7 +292,6 @@ class SaleOrderLine(models.Model):
for line in self:
if not line.display_qty_widget:
continue
line.warehouse_id = line.order_id.warehouse_id
if line.order_id.commitment_date:
date = line.order_id.commitment_date
else:
@@ -327,7 +326,6 @@ class SaleOrderLine(models.Model):
remaining.scheduled_date = False
remaining.free_qty_today = False
remaining.qty_available_today = False
remaining.warehouse_id = False
@api.depends('product_id', 'route_id', 'order_id.warehouse_id', 'product_id.route_ids')
def _compute_is_mto(self):
+4
View File
@@ -36,6 +36,10 @@ class StockMove(models.Model):
#rslt += invoices.mapped('reverse_entry_ids')
return rslt
def _get_source_document(self):
res = super()._get_source_document()
return self.sale_line_id.order_id or res
def _assign_picking_post_process(self, new=False):
super(StockMove, self)._assign_picking_post_process(new=new)
if new:
+1
View File
@@ -2,4 +2,5 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import sale_report
from . import report_stock_forecasted
from . import report_stock_rule
@@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import models
class ReplenishmentReport(models.AbstractModel):
_inherit = 'report.stock.report_product_product_replenishment'
def _compute_draft_quantity_count(self, product_template_ids, product_variant_ids, wh_location_ids):
res = super()._compute_draft_quantity_count(product_template_ids, product_variant_ids, wh_location_ids)
domain = self._product_sale_domain(product_template_ids, product_variant_ids)
so_lines = self.env['sale.order.line'].search(domain)
out_sum = 0
if so_lines:
product_uom = so_lines[0].product_id.uom_id
quantities = so_lines.mapped(lambda line: line.product_uom._compute_quantity(line.product_uom_qty, product_uom))
out_sum = sum(quantities)
res['draft_sale_qty'] = out_sum
res['qty']['out'] += out_sum
return res
def _product_sale_domain(self, product_template_ids, product_variant_ids):
domain = [('state', 'in', ['draft', 'sent'])]
if product_template_ids:
domain += [('product_template_id', 'in', product_template_ids)]
elif product_variant_ids:
domain += [('product_id', 'in', product_variant_ids)]
warehouse_id = self.env.context.get('warehouse', False)
if warehouse_id:
domain += [('warehouse_id', '=', warehouse_id)]
return domain
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="sale_report_product_product_replenishment" inherit_id="stock.report_product_product_replenishment">
<xpath expr="//tr[@name='draft_picking_out']" position="after">
<tr t-if="docs['draft_sale_qty']" name="draft_so_out">
<td colspan="2">Draft SO</td>
<td t-esc="docs['draft_sale_qty']" class="text-right"/>
<td t-esc="docs['uom']" groups="uom.group_uom"/>
</tr>
</xpath>
</template>
</odoo>
+1
View File
@@ -5,5 +5,6 @@ from . import test_anglo_saxon_valuation
from . import test_anglo_saxon_valuation_reconciliation
from . import test_sale_stock
from . import test_sale_stock_lead_time
from . import test_sale_stock_report
from . import test_sale_order_dates
from . import test_sale_stock_multicompany
@@ -0,0 +1,57 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from datetime import datetime, timedelta
from odoo.tests.common import Form
from odoo.addons.stock.tests.test_report import TestReportsCommon
class TestSaleStockReports(TestReportsCommon):
def test_report_forecast_1_sale_order_replenishment(self):
""" Create and confirm two sale orders: one for the next week and one
for tomorrow. Then check in the report it's the most urgent who is
linked to the qty. on stock.
"""
today = datetime.today()
# Put some quantity in stock.
quant_vals = {
'product_id': self.product.id,
'product_uom_id': self.product.uom_id.id,
'location_id': self.stock_location.id,
'quantity': 5,
'reserved_quantity': 0,
}
self.env['stock.quant'].create(quant_vals)
# Create a first SO for the next week.
so_form = Form(self.env['sale.order'])
so_form.partner_id = self.partner
# so_form.validity_date = today + timedelta(days=7)
with so_form.order_line.new() as so_line:
so_line.product_id = self.product
so_line.product_uom_qty = 5
so_1 = so_form.save()
so_1.action_confirm()
so_1.picking_ids.scheduled_date = today + timedelta(days=7)
# Create a second SO for tomorrow.
so_form = Form(self.env['sale.order'])
so_form.partner_id = self.partner
# so_form.validity_date = today + timedelta(days=1)
with so_form.order_line.new() as so_line:
so_line.product_id = self.product
so_line.product_uom_qty = 5
so_2 = so_form.save()
so_2.action_confirm()
so_2.picking_ids.scheduled_date = today + timedelta(days=1)
report_values, docs, lines = self.get_report_forecast(product_template_ids=self.product_template.ids)
self.assertEqual(len(lines), 2)
line_1 = lines[0]
line_2 = lines[1]
self.assertEqual(line_1['quantity'], 5)
self.assertTrue(line_1['replenishment_filled'])
self.assertEqual(line_1['document_out'].id, so_2.id)
self.assertEqual(line_2['quantity'], 5)
self.assertEqual(line_2['replenishment_filled'], False)
self.assertEqual(line_2['document_out'].id, so_1.id)