[IMP] purchase_stock: extend replenishment report

Adds Purchase Orders as replenishment/consuming document for the
replenishment report.

task-2058495
This commit is contained in:
svs-odoo
2020-07-31 12:36:54 +00:00
parent 832af92115
commit 38018469a7
7 changed files with 198 additions and 0 deletions
+1
View File
@@ -24,6 +24,7 @@
'views/product_category_views.xml',
'report/purchase_report_views.xml',
'report/purchase_report_templates.xml',
'report/report_stock_forecasted.xml',
'report/report_stock_rule.xml',
],
'demo': [
+4
View File
@@ -105,6 +105,10 @@ class StockMove(models.Model):
rslt += self.mapped('picking_id.purchase_id.invoice_ids').filtered(lambda x: x.state == 'posted')
return rslt
def _get_source_document(self):
res = super()._get_source_document()
return self.purchase_line_id.order_id or res
class StockWarehouse(models.Model):
_inherit = 'stock.warehouse'
+1
View File
@@ -2,5 +2,6 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import purchase_report
from . import report_stock_forecasted
from . import report_stock_rule
from . import vendor_delay_report
@@ -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 = [('state', 'in', ['draft', 'sent'])]
domain += self._product_purchase_domain(product_template_ids, product_variant_ids)
warehouse_id = self.env.context.get('warehouse', False)
if warehouse_id:
domain += [('order_id.picking_type_id.warehouse_id', '=', warehouse_id)]
po_lines = self.env['purchase.order.line'].read_group(domain, ['product_uom_qty'], 'product_id')
in_sum = sum(line['product_uom_qty'] for line in po_lines)
res['draft_purchase_qty'] = in_sum
res['qty']['in'] += in_sum
return res
def _product_purchase_domain(self, product_template_ids, product_variant_ids):
if product_variant_ids:
return [('product_id', 'in', product_variant_ids)]
elif product_template_ids:
products = self.env['product.product'].search_read(
[('product_tmpl_id', 'in', product_template_ids)], ['id']
)
product_ids = [product['id'] for product in products]
return [('product_id', 'in', product_ids)]
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="purchase_report_product_product_replenishment" inherit_id="stock.report_product_product_replenishment">
<xpath expr="//tr[@name='draft_picking_in']" position="after">
<tr t-if="docs['draft_purchase_qty']" name="draft_po_in">
<td colspan="2">Draft PO</td>
<td t-esc="docs['draft_purchase_qty']" class="text-right"/>
<td t-esc="docs['uom']" groups="uom.group_uom"/>
</tr>
</xpath>
</template>
</odoo>
+1
View File
@@ -11,6 +11,7 @@ from . import test_purchase_delete_order
from . import test_purchase_lead_time
from . import test_purchase_order
from . import test_purchase_order_process
from . import test_purchase_stock_report
from . import test_stockvaluation
from . import test_replenish_wizard
from . import test_reordering_rule
@@ -0,0 +1,147 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.tests.common import Form
from odoo.addons.stock.tests.test_report import TestReportsCommon
class TestPurchaseStockReports(TestReportsCommon):
def test_report_forecast_1_purchase_order_multi_receipt(self):
""" Create a PO for 5 product, receive them then increase the quantity to 10.
"""
po_form = Form(self.env['purchase.order'])
po_form.partner_id = self.partner
with po_form.order_line.new() as line:
line.product_id = self.product
line.product_qty = 5
po = po_form.save()
# Checks the report.
report_values, docs, lines = self.get_report_forecast(product_template_ids=self.product_template.ids)
draft_picking_qty_in = docs['draft_picking_qty']['in']
draft_purchase_qty = docs['draft_purchase_qty']
pending_qty_in = docs['qty']['in']
self.assertEqual(len(lines), 0, "Must have 0 line for now.")
self.assertEqual(draft_picking_qty_in, 0)
self.assertEqual(draft_purchase_qty, 5)
self.assertEqual(pending_qty_in, 5)
# Confirms the PO and checks the report again.
po.button_confirm()
report_values, docs, lines = self.get_report_forecast(product_template_ids=self.product_template.ids)
draft_picking_qty_in = docs['draft_picking_qty']['in']
draft_purchase_qty = docs['draft_purchase_qty']
pending_qty_in = docs['qty']['in']
self.assertEqual(len(lines), 1)
self.assertEqual(lines[0]['document_in'].id, po.id)
self.assertEqual(lines[0]['quantity'], 5)
self.assertEqual(lines[0]['document_out'], False)
self.assertEqual(draft_picking_qty_in, 0)
self.assertEqual(draft_purchase_qty, 0)
self.assertEqual(pending_qty_in, 0)
# Receives 5 products.
receipt = po.picking_ids
res_dict = receipt.button_validate()
wizard = Form(self.env[res_dict['res_model']].with_context(res_dict['context'])).save()
wizard.process()
report_values, docs, lines = self.get_report_forecast(product_template_ids=self.product_template.ids)
draft_picking_qty_in = docs['draft_picking_qty']['in']
draft_purchase_qty = docs['draft_purchase_qty']
pending_qty_in = docs['qty']['in']
self.assertEqual(len(lines), 0)
self.assertEqual(draft_picking_qty_in, 0)
self.assertEqual(draft_purchase_qty, 0)
self.assertEqual(pending_qty_in, 0)
# Increase the PO quantity to 10, so must create a second receipt.
po_form = Form(po)
with po_form.order_line.edit(0) as line:
line.product_qty = 10
po = po_form.save()
# Checks the report.
report_values, docs, lines = self.get_report_forecast(product_template_ids=self.product_template.ids)
draft_picking_qty_in = docs['draft_picking_qty']['in']
draft_purchase_qty = docs['draft_purchase_qty']
pending_qty_in = docs['qty']['in']
self.assertEqual(len(lines), 1, "Must have 1 line for now.")
self.assertEqual(lines[0]['document_in'].id, po.id)
self.assertEqual(lines[0]['quantity'], 5)
self.assertEqual(draft_picking_qty_in, 0)
self.assertEqual(draft_purchase_qty, 0)
self.assertEqual(pending_qty_in, 0)
def test_report_forecast_2_purchase_order_three_step_receipt(self):
""" Create a PO for 4 product, receive them then increase the quantity
to 10, but use three steps receipt.
"""
grp_multi_loc = self.env.ref('stock.group_stock_multi_locations')
grp_multi_routes = self.env.ref('stock.group_adv_location')
self.env.user.write({'groups_id': [(4, grp_multi_loc.id)]})
self.env.user.write({'groups_id': [(4, grp_multi_routes.id)]})
# Configure warehouse.
warehouse = self.env.ref('stock.warehouse0')
warehouse.reception_steps = 'three_steps'
po_form = Form(self.env['purchase.order'])
po_form.partner_id = self.partner
with po_form.order_line.new() as line:
line.product_id = self.product
line.product_qty = 4
po = po_form.save()
# Checks the report -> Must be empty for now, just display some pending qty.
report_values, docs, lines = self.get_report_forecast(product_template_ids=self.product_template.ids)
draft_picking_qty_in = docs['draft_picking_qty']['in']
draft_purchase_qty = docs['draft_purchase_qty']
pending_qty_in = docs['qty']['in']
self.assertEqual(len(lines), 0, "Must have 0 line for now.")
self.assertEqual(draft_picking_qty_in, 0)
self.assertEqual(draft_purchase_qty, 4)
self.assertEqual(pending_qty_in, 4)
# Confirms the PO and checks the report again.
po.button_confirm()
report_values, docs, lines = self.get_report_forecast(product_template_ids=self.product_template.ids)
draft_picking_qty_in = docs['draft_picking_qty']['in']
draft_purchase_qty = docs['draft_purchase_qty']
pending_qty_in = docs['qty']['in']
self.assertEqual(len(lines), 1)
self.assertEqual(lines[0]['document_in'].id, po.id)
self.assertEqual(lines[0]['quantity'], 4)
self.assertEqual(lines[0]['document_out'], False)
self.assertEqual(draft_picking_qty_in, 0)
self.assertEqual(draft_purchase_qty, 0)
self.assertEqual(pending_qty_in, 0)
# Get back the different transfers.
receipt = po.picking_ids
# Receives 4 products.
res_dict = receipt.button_validate()
wizard = Form(self.env[res_dict['res_model']].with_context(res_dict['context'])).save()
wizard.process()
report_values, docs, lines = self.get_report_forecast(product_template_ids=self.product_template.ids)
draft_picking_qty_in = docs['draft_picking_qty']['in']
draft_purchase_qty = docs['draft_purchase_qty']
pending_qty_in = docs['qty']['in']
self.assertEqual(len(lines), 0)
self.assertEqual(draft_picking_qty_in, 0)
self.assertEqual(draft_purchase_qty, 0)
self.assertEqual(pending_qty_in, 0)
# Increase the PO quantity to 10, so must create a second receipt.
po_form = Form(po)
with po_form.order_line.edit(0) as line:
line.product_qty = 10
po = po_form.save()
# Checks the report.
report_values, docs, lines = self.get_report_forecast(product_template_ids=self.product_template.ids)
draft_picking_qty_in = docs['draft_picking_qty']['in']
draft_purchase_qty = docs['draft_purchase_qty']
pending_qty_in = docs['qty']['in']
self.assertEqual(len(lines), 1)
self.assertEqual(lines[0]['document_in'].id, po.id)
self.assertEqual(lines[0]['quantity'], 6)
self.assertEqual(draft_picking_qty_in, 0)
self.assertEqual(draft_purchase_qty, 0)
self.assertEqual(pending_qty_in, 0)