371 lines
15 KiB
Python
371 lines
15 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from odoo.tests import Form
|
|
from odoo.addons.mail.tests.common import mail_new_test_user
|
|
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
|
|
receipt.button_validate()
|
|
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.
|
|
receipt.button_validate()
|
|
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)
|
|
|
|
def test_report_forecast_3_report_line_corresponding_to_po_line_highlighted(self):
|
|
""" When accessing the report from a PO line, checks if the correct PO line is highlighted in the report
|
|
"""
|
|
# We create 2 identical PO
|
|
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
|
|
po1 = po_form.save()
|
|
po1.button_confirm()
|
|
po2 = po1.copy()
|
|
po2.button_confirm()
|
|
|
|
# Check for both PO if the highlight (is_matched) corresponds to the correct PO
|
|
for po in [po1, po2]:
|
|
context = po.order_line[0].action_product_forecast_report()['context']
|
|
_, _, lines = self.get_report_forecast(product_template_ids=self.product_template.ids, context=context)
|
|
for line in lines:
|
|
if line['document_in']['id'] == po.id:
|
|
self.assertTrue(line['is_matched'], "The corresponding PO line should be matched in the forecast report.")
|
|
else:
|
|
self.assertFalse(line['is_matched'], "A line of the forecast report not linked to the PO shoud not be matched.")
|
|
|
|
def test_approval_and_forecasted_qty(self):
|
|
"""
|
|
When a PO is waiting for an approval, its quantities should be included
|
|
in the draft quantity count
|
|
"""
|
|
self.env.company.po_double_validation = 'two_step'
|
|
self.env.company.po_double_validation_amount = 0
|
|
|
|
basic_purchase_user = mail_new_test_user(
|
|
self.env,
|
|
login='basic_purchase_user',
|
|
groups='base.group_user,purchase.group_purchase_user',
|
|
)
|
|
|
|
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 = 50
|
|
po_form.save()
|
|
|
|
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 = 100
|
|
po = po_form.save()
|
|
po.with_user(basic_purchase_user).button_confirm()
|
|
|
|
docs = self.get_report_forecast(product_template_ids=self.product_template.ids)[1]
|
|
self.assertEqual(docs['draft_purchase_qty'], 150)
|
|
|
|
def test_vendor_delay_report_with_uom(self):
|
|
"""
|
|
PO 12 units x P
|
|
Receive 1 dozen x P
|
|
-> 100% received
|
|
"""
|
|
uom_12 = self.env.ref('uom.product_uom_dozen')
|
|
|
|
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 = 12
|
|
po = po_form.save()
|
|
po.button_confirm()
|
|
|
|
receipt = po.picking_ids
|
|
receipt_move = receipt.move_ids
|
|
receipt_move.move_line_ids.unlink()
|
|
receipt_move.move_line_ids = [(0, 0, {
|
|
'location_id': receipt_move.location_id.id,
|
|
'location_dest_id': receipt_move.location_dest_id.id,
|
|
'product_id': self.product.id,
|
|
'product_uom_id': uom_12.id,
|
|
'quantity': 1,
|
|
'picking_id': receipt.id,
|
|
})]
|
|
receipt.move_ids.picked = True
|
|
receipt.button_validate()
|
|
|
|
data = self.env['vendor.delay.report'].read_group(
|
|
[('partner_id', '=', self.partner.id)],
|
|
['product_id', 'on_time_rate', 'qty_on_time', 'qty_total'],
|
|
['product_id'],
|
|
)[0]
|
|
self.assertEqual(data['qty_on_time'], 12)
|
|
self.assertEqual(data['qty_total'], 12)
|
|
self.assertEqual(data['on_time_rate'], 100)
|
|
|
|
def test_vendor_delay_report_with_multi_location(self):
|
|
"""
|
|
PO 10 units x P
|
|
Receive
|
|
- 6 x P in Child Location 01
|
|
- 4 x P in Child Location 02
|
|
-> 100% received
|
|
"""
|
|
if not self.stock_location.child_ids:
|
|
self.env['stock.location'].create([{
|
|
'name': 'Shelf 1',
|
|
'location_id': self.stock_location.id,
|
|
}, {
|
|
'name': 'Shelf 2',
|
|
'location_id': self.stock_location.id,
|
|
}])
|
|
|
|
child_loc_01, child_loc_02 = self.stock_location.child_ids
|
|
|
|
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 = 10
|
|
po = po_form.save()
|
|
po.button_confirm()
|
|
|
|
receipt = po.picking_ids
|
|
receipt_move = receipt.move_ids
|
|
receipt_move.move_line_ids.unlink()
|
|
receipt_move.move_line_ids = [(0, 0, {
|
|
'location_id': receipt_move.location_id.id,
|
|
'location_dest_id': child_loc_01.id,
|
|
'product_id': self.product.id,
|
|
'product_uom_id': self.product.uom_id.id,
|
|
'quantity': 6,
|
|
'picking_id': receipt.id,
|
|
}), (0, 0, {
|
|
'location_id': receipt_move.location_id.id,
|
|
'location_dest_id': child_loc_02.id,
|
|
'product_id': self.product.id,
|
|
'product_uom_id': self.product.uom_id.id,
|
|
'quantity': 4,
|
|
'picking_id': receipt.id,
|
|
})]
|
|
receipt.move_ids.picked = True
|
|
receipt.button_validate()
|
|
|
|
data = self.env['vendor.delay.report'].read_group(
|
|
[('partner_id', '=', self.partner.id)],
|
|
['product_id', 'on_time_rate', 'qty_on_time', 'qty_total'],
|
|
['product_id'],
|
|
)[0]
|
|
self.assertEqual(data['qty_on_time'], 10)
|
|
self.assertEqual(data['qty_total'], 10)
|
|
self.assertEqual(data['on_time_rate'], 100)
|
|
|
|
def test_vendor_delay_report_with_backorder(self):
|
|
"""
|
|
PO 10 units x P
|
|
Receive 6 x P with backorder
|
|
-> 60% received
|
|
Process the backorder
|
|
-> 100% received
|
|
"""
|
|
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 = 10
|
|
po = po_form.save()
|
|
po.button_confirm()
|
|
|
|
receipt01 = po.picking_ids
|
|
receipt01_move = receipt01.move_ids
|
|
receipt01_move.quantity = 6
|
|
Form.from_action(self.env, receipt01.button_validate()).save().process()
|
|
|
|
data = self.env['vendor.delay.report'].read_group(
|
|
[('partner_id', '=', self.partner.id)],
|
|
['product_id', 'on_time_rate', 'qty_on_time', 'qty_total'],
|
|
['product_id'],
|
|
)[0]
|
|
self.assertEqual(data['qty_on_time'], 6)
|
|
self.assertEqual(data['qty_total'], 10)
|
|
self.assertEqual(data['on_time_rate'], 60)
|
|
|
|
receipt02 = receipt01.backorder_ids
|
|
receipt02.move_ids.quantity = 4
|
|
receipt02.move_ids.picked = True
|
|
receipt02.button_validate()
|
|
|
|
(receipt01 | receipt02).move_ids.invalidate_recordset()
|
|
data = self.env['vendor.delay.report'].read_group(
|
|
[('partner_id', '=', self.partner.id)],
|
|
['product_id', 'on_time_rate', 'qty_on_time', 'qty_total'],
|
|
['product_id'],
|
|
)[0]
|
|
self.assertEqual(data['qty_on_time'], 10)
|
|
self.assertEqual(data['qty_total'], 10)
|
|
self.assertEqual(data['on_time_rate'], 100)
|
|
|
|
def test_vendor_delay_report_without_backorder(self):
|
|
"""
|
|
PO 10 units x P
|
|
Receive 6 x P without backorder
|
|
-> 60% received
|
|
"""
|
|
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 = 10
|
|
po = po_form.save()
|
|
po.button_confirm()
|
|
|
|
receipt01 = po.picking_ids
|
|
receipt01_move = receipt01.move_ids
|
|
receipt01_move.quantity = 6
|
|
receipt01_move.picked = True
|
|
Form.from_action(self.env, receipt01.button_validate()).save().process_cancel_backorder()
|
|
|
|
data = self.env['vendor.delay.report'].read_group(
|
|
[('partner_id', '=', self.partner.id)],
|
|
['product_id', 'on_time_rate', 'qty_on_time', 'qty_total'],
|
|
['product_id'],
|
|
)[0]
|
|
self.assertEqual(data['qty_on_time'], 6)
|
|
self.assertEqual(data['qty_total'], 10)
|
|
self.assertEqual(data['on_time_rate'], 60)
|