Files
odoo_source/addons/stock/tests/test_report.py
T
Arnold Moyaux bdcb3d192b [REF] stock: move stock.inventory feature into stock.quant
This commit removes stock.inventory(.line) and moves its general
functionality into stock.quant. Some features are lost during this
switch as well.

Feature Additions:
- New single list view for inventory adjustments (no more multiple
  inventory adjustment records to keep track of!)
- Improved cyclic counts (annual inventory day setting) + next inventory
  dates are immediately viewable in view (vs auto-generated inventories
  based only on location)
- Specific quants (i.e. counts) can be assigned to users for more
  flexibility (vs only able to restrict by location + product
  combinations)
- Counts can be requested (i.e. bulk assigned to user/for a specific
  inventory date)

Feature Removals:
- Can no longer look at previous inventory adjustments linked to a
  specific record. Each quant has a history button to show inventory
  related moves. [relevant account moves are also now harder to see via
  stock as well]

Other changes:
- Bulk of changes were for demo/test
- Some changes were done to ensure "Update Quantity"/"Inventory Report"
  views still mainly function the same as before with the exception of a
  new column added to support updating quant quantities in these views.

Task: 2440026
ENT PR: odoo/enterprise#17329
Upgrade PR: odoo/upgrade#2326

closes odoo/odoo#68409

Signed-off-by: Arnold Moyaux <amoyaux@users.noreply.github.com>
2021-04-02 11:51:38 +00:00

1176 lines
58 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from datetime import date, datetime, timedelta
from odoo.tests.common import Form, TransactionCase
class TestReportsCommon(TransactionCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.partner = cls.env['res.partner'].create({'name': 'Partner'})
cls.ModelDataObj = cls.env['ir.model.data']
cls.picking_type_in = cls.env['stock.picking.type'].browse(cls.ModelDataObj.xmlid_to_res_id('stock.picking_type_in'))
cls.picking_type_out = cls.env['stock.picking.type'].browse(cls.ModelDataObj.xmlid_to_res_id('stock.picking_type_out'))
cls.supplier_location = cls.env['stock.location'].browse(cls.ModelDataObj.xmlid_to_res_id('stock.stock_location_suppliers'))
cls.stock_location = cls.env['stock.location'].browse(cls.ModelDataObj.xmlid_to_res_id('stock.stock_location_stock'))
product_form = Form(cls.env['product.product'])
product_form.type = 'product'
product_form.name = 'Product'
cls.product = product_form.save()
cls.product_template = cls.product.product_tmpl_id
def get_report_forecast(self, product_template_ids=False, product_variant_ids=False, context=False):
if product_template_ids:
report = self.env['report.stock.report_product_template_replenishment']
product_ids = product_template_ids
elif product_variant_ids:
report = self.env['report.stock.report_product_product_replenishment']
product_ids = product_template_ids
if context:
report = report.with_context(context)
report_values = report._get_report_values(docids=product_ids)
docs = report_values['docs']
lines = docs['lines']
return report_values, docs, lines
class TestReports(TestReportsCommon):
def test_reports(self):
product1 = self.env['product.product'].create({
'name': 'Mellohi',
'default_code': 'C418',
'type': 'product',
'categ_id': self.env.ref('product.product_category_all').id,
'tracking': 'lot',
'barcode': 'scan_me'
})
lot1 = self.env['stock.production.lot'].create({
'name': 'Volume-Beta',
'product_id': product1.id,
'company_id': self.env.company.id,
})
report = self.env.ref('stock.label_lot_template')
target = b'\n\n\n^XA\n^FO100,50\n^A0N,44,33^FD[C418]Mellohi^FS\n^FO100,100\n^A0N,44,33^FDLN/SN:Volume-Beta^FS\n^FO100,150^BY3\n^BCN,100,Y,N,N\n^FDVolume-Beta^FS\n^XZ\n\n\n'
rendering, qweb_type = report._render_qweb_text(lot1.id)
self.assertEqual(target, rendering.replace(b' ', b''), 'The rendering is not good')
self.assertEqual(qweb_type, 'text', 'the report type is not good')
def test_report_quantity_1(self):
product_form = Form(self.env['product.product'])
product_form.type = 'product'
product_form.name = 'Product'
product = product_form.save()
warehouse = self.env['stock.warehouse'].search([], limit=1)
stock = self.env['stock.location'].create({
'name': 'New Stock',
'usage': 'internal',
'location_id': warehouse.view_location_id.id,
})
# Inventory Adjustement of 50.0 today.
self.env['stock.quant'].with_context(inventory_mode=True).create({
'product_id': product.id,
'location_id': stock.id,
'inventory_quantity': 50
}).action_apply_inventory()
self.env['stock.move'].flush()
report_records_today = self.env['report.stock.quantity'].read_group(
[('product_id', '=', product.id), ('date', '=', date.today())],
['product_qty'], [], lazy=False)
report_records_tomorrow = self.env['report.stock.quantity'].read_group(
[('product_id', '=', product.id), ('date', '=', date.today() + timedelta(days=1))],
['product_qty'], [])
report_records_yesterday = self.env['report.stock.quantity'].read_group(
[('product_id', '=', product.id), ('date', '=', date.today() - timedelta(days=1))],
['product_qty'], [])
self.assertEqual(sum([r['product_qty'] for r in report_records_today]), 50.0)
self.assertEqual(sum([r['product_qty'] for r in report_records_tomorrow]), 50.0)
self.assertEqual(sum([r['product_qty'] for r in report_records_yesterday]), 0.0)
# Delivery of 20.0 units tomorrow
move_out = self.env['stock.move'].create({
'name': 'Move Out 20',
'date': datetime.now() + timedelta(days=1),
'location_id': stock.id,
'location_dest_id': self.env.ref('stock.stock_location_customers').id,
'product_id': product.id,
'product_uom': product.uom_id.id,
'product_uom_qty': 20.0,
})
self.env['stock.move'].flush()
report_records_tomorrow = self.env['report.stock.quantity'].read_group(
[('product_id', '=', product.id), ('date', '=', date.today() + timedelta(days=1))],
['product_qty'], [])
self.assertEqual(sum([r['product_qty'] for r in report_records_tomorrow]), 50.0)
move_out._action_confirm()
self.env['stock.move'].flush()
report_records_tomorrow = self.env['report.stock.quantity'].read_group(
[('product_id', '=', product.id), ('date', '=', date.today() + timedelta(days=1))],
['product_qty', 'state'], ['state'], lazy=False)
self.assertEqual(sum([r['product_qty'] for r in report_records_tomorrow if r['state'] == 'forecast']), 30.0)
self.assertEqual(sum([r['product_qty'] for r in report_records_tomorrow if r['state'] == 'out']), -20.0)
report_records_today = self.env['report.stock.quantity'].read_group(
[('product_id', '=', product.id), ('date', '=', date.today())],
['product_qty', 'state'], ['state'], lazy=False)
self.assertEqual(sum([r['product_qty'] for r in report_records_today if r['state'] == 'forecast']), 50.0)
# Receipt of 10.0 units tomorrow
move_in = self.env['stock.move'].create({
'name': 'Move In 10',
'date': datetime.now() + timedelta(days=1),
'location_id': self.env.ref('stock.stock_location_suppliers').id,
'location_dest_id': stock.id,
'product_id': product.id,
'product_uom': product.uom_id.id,
'product_uom_qty': 10.0,
})
move_in._action_confirm()
self.env['stock.move'].flush()
report_records_tomorrow = self.env['report.stock.quantity'].read_group(
[('product_id', '=', product.id), ('date', '=', date.today() + timedelta(days=1))],
['product_qty', 'state'], ['state'], lazy=False)
self.assertEqual(sum([r['product_qty'] for r in report_records_tomorrow if r['state'] == 'forecast']), 40.0)
self.assertEqual(sum([r['product_qty'] for r in report_records_tomorrow if r['state'] == 'out']), -20.0)
self.assertEqual(sum([r['product_qty'] for r in report_records_tomorrow if r['state'] == 'in']), 10.0)
report_records_today = self.env['report.stock.quantity'].read_group(
[('product_id', '=', product.id), ('date', '=', date.today())],
['product_qty', 'state'], ['state'], lazy=False)
self.assertEqual(sum([r['product_qty'] for r in report_records_today if r['state'] == 'forecast']), 50.0)
# Delivery of 20.0 units tomorrow
move_out = self.env['stock.move'].create({
'name': 'Move Out 30 - Day-1',
'date': datetime.now() - timedelta(days=1),
'location_id': stock.id,
'location_dest_id': self.env.ref('stock.stock_location_customers').id,
'product_id': product.id,
'product_uom': product.uom_id.id,
'product_uom_qty': 30.0,
})
move_out._action_confirm()
self.env['stock.move'].flush()
report_records_today = self.env['report.stock.quantity'].read_group(
[('product_id', '=', product.id), ('date', '=', date.today())],
['product_qty', 'state'], ['state'], lazy=False)
report_records_tomorrow = self.env['report.stock.quantity'].read_group(
[('product_id', '=', product.id), ('date', '=', date.today() + timedelta(days=1))],
['product_qty', 'state'], ['state'], lazy=False)
report_records_yesterday = self.env['report.stock.quantity'].read_group(
[('product_id', '=', product.id), ('date', '=', date.today() - timedelta(days=1))],
['product_qty', 'state'], ['state'], lazy=False)
self.assertEqual(sum([r['product_qty'] for r in report_records_yesterday if r['state'] == 'forecast']), -30.0)
self.assertEqual(sum([r['product_qty'] for r in report_records_yesterday if r['state'] == 'out']), -30.0)
self.assertEqual(sum([r['product_qty'] for r in report_records_yesterday if r['state'] == 'in']), 0.0)
self.assertEqual(sum([r['product_qty'] for r in report_records_today if r['state'] == 'forecast']), 20.0)
self.assertEqual(sum([r['product_qty'] for r in report_records_today if r['state'] == 'out']), 0.0)
self.assertEqual(sum([r['product_qty'] for r in report_records_today if r['state'] == 'in']), 0.0)
self.assertEqual(sum([r['product_qty'] for r in report_records_tomorrow if r['state'] == 'forecast']), 10.0)
self.assertEqual(sum([r['product_qty'] for r in report_records_tomorrow if r['state'] == 'out']), -20.0)
self.assertEqual(sum([r['product_qty'] for r in report_records_tomorrow if r['state'] == 'in']), 10.0)
def test_report_quantity_2(self):
""" Not supported case.
"""
product_form = Form(self.env['product.product'])
product_form.type = 'product'
product_form.name = 'Product'
product = product_form.save()
warehouse = self.env['stock.warehouse'].search([], limit=1)
stock = self.env['stock.location'].create({
'name': 'Stock Under Warehouse',
'usage': 'internal',
'location_id': warehouse.view_location_id.id,
})
stock_without_wh = self.env['stock.location'].create({
'name': 'Stock Outside Warehouse',
'usage': 'internal',
'location_id': self.env.ref('stock.stock_location_locations').id,
})
self.env['stock.quant'].with_context(inventory_mode=True).create({
'product_id': product.id,
'location_id': stock.id,
'inventory_quantity': 50
}).action_apply_inventory()
self.env['stock.quant'].with_context(inventory_mode=True).create({
'product_id': product.id,
'location_id': stock_without_wh.id,
'inventory_quantity': 50
}).action_apply_inventory()
move = self.env['stock.move'].create({
'name': 'Move outside warehouse',
'location_id': stock.id,
'location_dest_id': stock_without_wh.id,
'product_id': product.id,
'product_uom': product.uom_id.id,
'product_uom_qty': 10.0,
})
move._action_confirm()
self.env['stock.move'].flush()
report_records = self.env['report.stock.quantity'].read_group(
[('product_id', '=', product.id), ('date', '=', date.today()), ('warehouse_id', '!=', False)],
['product_qty', 'state'], ['state'], lazy=False)
self.assertEqual(sum([r['product_qty'] for r in report_records if r['state'] == 'forecast']), 40.0)
report_records = self.env['report.stock.quantity'].read_group(
[('product_id', '=', product.id), ('date', '=', date.today())],
['product_qty', 'state'], ['state'], lazy=False)
self.assertEqual(sum([r['product_qty'] for r in report_records if r['state'] == 'forecast']), 40.0)
move = self.env['stock.move'].create({
'name': 'Move outside warehouse',
'location_id': stock_without_wh.id,
'location_dest_id': self.env.ref('stock.stock_location_customers').id,
'product_id': product.id,
'product_uom': product.uom_id.id,
'product_uom_qty': 10.0,
})
move._action_confirm()
self.env['stock.move'].flush()
report_records = self.env['report.stock.quantity'].read_group(
[('product_id', '=', product.id), ('date', '=', date.today())],
['product_qty', 'state'], ['state'], lazy=False)
self.assertEqual(sum([r['product_qty'] for r in report_records if r['state'] == 'forecast']), 40.0)
def test_report_quantity_3(self):
product_form = Form(self.env['product.product'])
product_form.type = 'product'
product_form.name = 'Product'
product = product_form.save()
warehouse = self.env['stock.warehouse'].search([], limit=1)
stock = self.env['stock.location'].create({
'name': 'Rack',
'usage': 'view',
'location_id': warehouse.view_location_id.id,
})
stock_real_loc = self.env['stock.location'].create({
'name': 'Drawer',
'usage': 'internal',
'location_id': stock.id,
})
self.env['stock.move'].flush()
report_records = self.env['report.stock.quantity'].read_group(
[('product_id', '=', product.id), ('date', '=', date.today())],
['product_qty'], [], lazy=False)
self.assertEqual(sum([r['product_qty'] for r in report_records if r['product_qty']]), 0.0)
# Receipt of 20.0 units tomorrow
move_in = self.env['stock.move'].create({
'name': 'Move In 20',
'location_id': self.env.ref('stock.stock_location_suppliers').id,
'location_dest_id': stock.id,
'product_id': product.id,
'product_uom': product.uom_id.id,
'product_uom_qty': 20.0,
})
move_in._action_confirm()
move_in.move_line_ids.location_dest_id = stock_real_loc.id
move_in.move_line_ids.qty_done = 20.0
move_in._action_done()
self.env['stock.move'].flush()
report_records = self.env['report.stock.quantity'].read_group(
[('product_id', '=', product.id), ('date', '=', date.today())],
['product_qty'], [], lazy=False)
self.assertEqual(sum([r['product_qty'] for r in report_records]), 20.0)
# Delivery of 10.0 units tomorrow
move_out = self.env['stock.move'].create({
'name': 'Move Out 10',
'location_id': stock.id,
'location_dest_id': self.env.ref('stock.stock_location_customers').id,
'product_id': product.id,
'product_uom': product.uom_id.id,
'product_uom_qty': 10.0,
})
move_out._action_confirm()
move_out._action_assign()
move_out.move_line_ids.qty_done = 10.0
move_out._action_done()
self.env['stock.move'].flush()
report_records = self.env['report.stock.quantity'].read_group(
[('product_id', '=', product.id), ('date', '=', date.today())],
['product_qty'], [], lazy=False)
self.assertEqual(sum([r['product_qty'] for r in report_records]), 10.0)
def test_report_forecast_1(self):
""" Checks report data for product is empty. Then creates and process
some operations and checks the report data accords rigthly these operations.
"""
report_values, docs, lines = self.get_report_forecast(product_template_ids=self.product_template.ids)
draft_picking_qty = docs['draft_picking_qty']
self.assertEqual(len(lines), 0, "Must have 0 line.")
self.assertEqual(draft_picking_qty['in'], 0)
self.assertEqual(draft_picking_qty['out'], 0)
# Creates a receipt then checks draft picking quantities.
receipt_form = Form(self.env['stock.picking'].with_context(
force_detailed_view=True
), view='stock.view_picking_form')
receipt_form.partner_id = self.partner
receipt_form.picking_type_id = self.picking_type_in
receipt = receipt_form.save()
with receipt_form.move_ids_without_package.new() as move_line:
move_line.product_id = self.product
move_line.product_uom_qty = 2
receipt = receipt_form.save()
report_values, docs, lines = self.get_report_forecast(product_template_ids=self.product_template.ids)
draft_picking_qty = docs['draft_picking_qty']
self.assertEqual(len(lines), 0, "Must have 0 line.")
self.assertEqual(draft_picking_qty['in'], 2)
self.assertEqual(draft_picking_qty['out'], 0)
# Creates a delivery then checks draft picking quantities.
delivery_form = Form(self.env['stock.picking'].with_context(
force_detailed_view=True
), view='stock.view_picking_form')
delivery_form.partner_id = self.partner
delivery_form.picking_type_id = self.picking_type_out
delivery = delivery_form.save()
with delivery_form.move_ids_without_package.new() as move_line:
move_line.product_id = self.product
move_line.product_uom_qty = 5
delivery = delivery_form.save()
report_values, docs, lines = self.get_report_forecast(product_template_ids=self.product_template.ids)
draft_picking_qty = docs['draft_picking_qty']
self.assertEqual(len(lines), 0, "Must have 0 line.")
self.assertEqual(draft_picking_qty['in'], 2)
self.assertEqual(draft_picking_qty['out'], 5)
# Confirms the delivery: must have one report line and no more pending qty out now.
delivery.action_confirm()
report_values, docs, lines = self.get_report_forecast(product_template_ids=self.product_template.ids)
draft_picking_qty = docs['draft_picking_qty']
self.assertEqual(len(lines), 1, "Must have 1 line.")
self.assertEqual(draft_picking_qty['in'], 2)
self.assertEqual(draft_picking_qty['out'], 0)
delivery_line = lines[0]
self.assertEqual(delivery_line['quantity'], 5)
self.assertEqual(delivery_line['replenishment_filled'], False)
self.assertEqual(delivery_line['document_out'].id, delivery.id)
# Confirms the receipt, must have two report lines now:
# - line with 2 qty (from the receipt to the delivery)
# - line with 3 qty (delivery, unavailable)
receipt.action_confirm()
report_values, docs, lines = self.get_report_forecast(product_template_ids=self.product_template.ids)
draft_picking_qty = docs['draft_picking_qty']
self.assertEqual(len(lines), 2, "Must have 2 line.")
self.assertEqual(draft_picking_qty['in'], 0)
self.assertEqual(draft_picking_qty['out'], 0)
fulfilled_line = lines[0]
unavailable_line = lines[1]
self.assertEqual(fulfilled_line['replenishment_filled'], True)
self.assertEqual(fulfilled_line['quantity'], 2)
self.assertEqual(fulfilled_line['document_in'].id, receipt.id)
self.assertEqual(fulfilled_line['document_out'].id, delivery.id)
self.assertEqual(unavailable_line['replenishment_filled'], False)
self.assertEqual(unavailable_line['quantity'], 3)
self.assertEqual(unavailable_line['document_out'].id, delivery.id)
# Creates a new receipt for the remaining quantity, confirm it...
receipt_form = Form(self.env['stock.picking'].with_context(
force_detailed_view=True
), view='stock.view_picking_form')
receipt_form.partner_id = self.partner
receipt_form.picking_type_id = self.picking_type_in
with receipt_form.move_ids_without_package.new() as move_line:
move_line.product_id = self.product
move_line.product_uom_qty = 3
receipt2 = receipt_form.save()
receipt2.action_confirm()
# ... and valid the first one.
receipt_form = Form(receipt)
with receipt_form.move_ids_without_package.edit(0) as move_line:
move_line.quantity_done = 2
receipt = receipt_form.save()
receipt.button_validate()
report_values, docs, lines = self.get_report_forecast(product_template_ids=self.product_template.ids)
draft_picking_qty = docs['draft_picking_qty']
self.assertEqual(len(lines), 2, "Still must have 2 line.")
self.assertEqual(draft_picking_qty['in'], 0)
self.assertEqual(draft_picking_qty['out'], 0)
line1 = lines[0]
line2 = lines[1]
# First line must be fulfilled thanks to the stock on hand.
self.assertEqual(line1['quantity'], 2)
self.assertEqual(line1['replenishment_filled'], True)
self.assertEqual(line1['document_in'], False)
self.assertEqual(line1['document_out'].id, delivery.id)
# Second line must be linked to the second receipt.
self.assertEqual(line2['quantity'], 3)
self.assertEqual(line2['replenishment_filled'], True)
self.assertEqual(line2['document_in'].id, receipt2.id)
self.assertEqual(line2['document_out'].id, delivery.id)
def test_report_forecast_2_replenishments_order(self):
""" Creates a receipt then creates a delivery using half of the receipt quantity.
Checks replenishment lines are correctly sorted (assigned first, unassigned at the end).
"""
# Creates a receipt then checks draft picking quantities.
receipt_form = Form(self.env['stock.picking'].with_context(
force_detailed_view=True
), view='stock.view_picking_form')
receipt_form.partner_id = self.partner
receipt_form.picking_type_id = self.picking_type_in
with receipt_form.move_ids_without_package.new() as move_line:
move_line.product_id = self.product
move_line.product_uom_qty = 6
receipt = receipt_form.save()
receipt.action_confirm()
# Creates a delivery then checks draft picking quantities.
delivery_form = Form(self.env['stock.picking'].with_context(
force_detailed_view=True
), view='stock.view_picking_form')
delivery_form.partner_id = self.partner
delivery_form.picking_type_id = self.picking_type_out
with delivery_form.move_ids_without_package.new() as move_line:
move_line.product_id = self.product
move_line.product_uom_qty = 3
delivery = delivery_form.save()
delivery.action_confirm()
report_values, docs, lines = self.get_report_forecast(product_template_ids=self.product_template.ids)
self.assertEqual(len(lines), 2, "Must have 2 line.")
line_1 = lines[0]
line_2 = lines[1]
self.assertEqual(line_1['document_in'].id, receipt.id)
self.assertEqual(line_1['document_out'].id, delivery.id)
self.assertEqual(line_2['document_in'].id, receipt.id)
self.assertEqual(line_2['document_out'], False)
def test_report_forecast_3_sort_by_date(self):
""" Creates some deliveries with different dates and checks the report
lines are correctly sorted by date. Then, creates some receipts and
check their are correctly linked according to their date.
"""
today = datetime.today()
one_hours = timedelta(hours=1)
one_day = timedelta(days=1)
one_month = timedelta(days=30)
# Creates a bunch of deliveries with different date.
delivery_form = Form(self.env['stock.picking'].with_context(
force_detailed_view=True
), view='stock.view_picking_form')
delivery_form.partner_id = self.partner
delivery_form.picking_type_id = self.picking_type_out
delivery_form.scheduled_date = today
with delivery_form.move_ids_without_package.new() as move_line:
move_line.product_id = self.product
move_line.product_uom_qty = 5
delivery_1 = delivery_form.save()
delivery_1.action_confirm()
delivery_form = Form(self.env['stock.picking'].with_context(
force_detailed_view=True
), view='stock.view_picking_form')
delivery_form.partner_id = self.partner
delivery_form.picking_type_id = self.picking_type_out
delivery_form.scheduled_date = today + one_hours
with delivery_form.move_ids_without_package.new() as move_line:
move_line.product_id = self.product
move_line.product_uom_qty = 5
delivery_2 = delivery_form.save()
delivery_2.action_confirm()
delivery_form = Form(self.env['stock.picking'].with_context(
force_detailed_view=True
), view='stock.view_picking_form')
delivery_form.partner_id = self.partner
delivery_form.picking_type_id = self.picking_type_out
delivery_form.scheduled_date = today - one_hours
with delivery_form.move_ids_without_package.new() as move_line:
move_line.product_id = self.product
move_line.product_uom_qty = 5
delivery_3 = delivery_form.save()
delivery_3.action_confirm()
delivery_form = Form(self.env['stock.picking'].with_context(
force_detailed_view=True
), view='stock.view_picking_form')
delivery_form.partner_id = self.partner
delivery_form.picking_type_id = self.picking_type_out
delivery_form.scheduled_date = today + one_day
with delivery_form.move_ids_without_package.new() as move_line:
move_line.product_id = self.product
move_line.product_uom_qty = 5
delivery_4 = delivery_form.save()
delivery_4.action_confirm()
delivery_form = Form(self.env['stock.picking'].with_context(
force_detailed_view=True
), view='stock.view_picking_form')
delivery_form.partner_id = self.partner
delivery_form.picking_type_id = self.picking_type_out
delivery_form.scheduled_date = today - one_day
with delivery_form.move_ids_without_package.new() as move_line:
move_line.product_id = self.product
move_line.product_uom_qty = 5
delivery_5 = delivery_form.save()
delivery_5.action_confirm()
delivery_form = Form(self.env['stock.picking'].with_context(
force_detailed_view=True
), view='stock.view_picking_form')
delivery_form.partner_id = self.partner
delivery_form.picking_type_id = self.picking_type_out
delivery_form.scheduled_date = today + one_month
with delivery_form.move_ids_without_package.new() as move_line:
move_line.product_id = self.product
move_line.product_uom_qty = 5
delivery_6 = delivery_form.save()
delivery_6.action_confirm()
delivery_form = Form(self.env['stock.picking'].with_context(
force_detailed_view=True
), view='stock.view_picking_form')
delivery_form.partner_id = self.partner
delivery_form.picking_type_id = self.picking_type_out
delivery_form.scheduled_date = today - one_month
with delivery_form.move_ids_without_package.new() as move_line:
move_line.product_id = self.product
move_line.product_uom_qty = 5
delivery_7 = delivery_form.save()
delivery_7.action_confirm()
# Order must be: 7, 5, 3, 1, 2, 4, 6
report_values, docs, lines = self.get_report_forecast(product_template_ids=self.product_template.ids)
draft_picking_qty = docs['draft_picking_qty']
self.assertEqual(len(lines), 7, "The report must have 7 line.")
self.assertEqual(draft_picking_qty['in'], 0)
self.assertEqual(draft_picking_qty['out'], 0)
self.assertEqual(lines[0]['document_out'].id, delivery_7.id)
self.assertEqual(lines[1]['document_out'].id, delivery_5.id)
self.assertEqual(lines[2]['document_out'].id, delivery_3.id)
self.assertEqual(lines[3]['document_out'].id, delivery_1.id)
self.assertEqual(lines[4]['document_out'].id, delivery_2.id)
self.assertEqual(lines[5]['document_out'].id, delivery_4.id)
self.assertEqual(lines[6]['document_out'].id, delivery_6.id)
# Creates 3 receipts for 20 units.
receipt_form = Form(self.env['stock.picking'].with_context(
force_detailed_view=True
), view='stock.view_picking_form')
receipt_form.partner_id = self.partner
receipt_form.picking_type_id = self.picking_type_in
receipt_form.scheduled_date = today + one_month
with receipt_form.move_ids_without_package.new() as move_line:
move_line.product_id = self.product
move_line.product_uom_qty = 5
receipt_1 = receipt_form.save()
receipt_1.action_confirm()
receipt_form = Form(self.env['stock.picking'].with_context(
force_detailed_view=True
), view='stock.view_picking_form')
receipt_form.partner_id = self.partner
receipt_form.picking_type_id = self.picking_type_in
receipt_form.scheduled_date = today - one_month
with receipt_form.move_ids_without_package.new() as move_line:
move_line.product_id = self.product
move_line.product_uom_qty = 5
receipt_2 = receipt_form.save()
receipt_2.action_confirm()
receipt_form = Form(self.env['stock.picking'].with_context(
force_detailed_view=True
), view='stock.view_picking_form')
receipt_form.partner_id = self.partner
receipt_form.picking_type_id = self.picking_type_in
receipt_form.scheduled_date = today - one_hours
with receipt_form.move_ids_without_package.new() as move_line:
move_line.product_id = self.product
move_line.product_uom_qty = 10
receipt_3 = receipt_form.save()
receipt_3.action_confirm()
# Check report lines (link and order).
report_values, docs, lines = self.get_report_forecast(product_template_ids=self.product_template.ids)
draft_picking_qty = docs['draft_picking_qty']
self.assertEqual(len(lines), 7, "The report must have 7 line.")
self.assertEqual(draft_picking_qty['in'], 0)
self.assertEqual(draft_picking_qty['out'], 0)
self.assertEqual(lines[0]['document_out'].id, delivery_7.id)
self.assertEqual(lines[0]['document_in'].id, receipt_2.id)
self.assertEqual(lines[0]['is_late'], False)
self.assertEqual(lines[1]['document_out'].id, delivery_5.id)
self.assertEqual(lines[1]['document_in'].id, receipt_3.id)
self.assertEqual(lines[1]['is_late'], True)
self.assertEqual(lines[2]['document_out'].id, delivery_3.id)
self.assertEqual(lines[2]['document_in'].id, receipt_3.id)
self.assertEqual(lines[2]['is_late'], False)
self.assertEqual(lines[3]['document_out'].id, delivery_1.id)
self.assertEqual(lines[3]['document_in'].id, receipt_1.id)
self.assertEqual(lines[3]['is_late'], True)
self.assertEqual(lines[4]['document_out'].id, delivery_2.id)
self.assertEqual(lines[4]['document_in'], False)
self.assertEqual(lines[5]['document_out'].id, delivery_4.id)
self.assertEqual(lines[5]['document_in'], False)
self.assertEqual(lines[6]['document_out'].id, delivery_6.id)
self.assertEqual(lines[6]['document_in'], False)
def test_report_forecast_4_intermediate_transfers(self):
""" Create a receipt in 3 steps and check the report line.
"""
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)]})
# Warehouse config.
warehouse = self.env.ref('stock.warehouse0')
warehouse.reception_steps = 'three_steps'
# Product config.
self.product.write({'route_ids': [(4, self.env.ref('stock.route_warehouse0_mto').id)]})
# Create a RR
pg1 = self.env['procurement.group'].create({})
reordering_rule = self.env['stock.warehouse.orderpoint'].create({
'name': 'Product RR',
'location_id': warehouse.lot_stock_id.id,
'product_id': self.product.id,
'product_min_qty': 5,
'product_max_qty': 10,
'group_id': pg1.id,
})
reordering_rule.action_replenish()
report_values, docs, lines = self.get_report_forecast(product_template_ids=self.product_template.ids)
pickings = self.env['stock.picking'].search([('product_id', '=', self.product.id)])
receipt = pickings.filtered(lambda p: p.picking_type_id.id == self.picking_type_in.id)
# The Forecasted Report don't show intermediate moves, it must display only ingoing/outgoing documents.
self.assertEqual(len(lines), 1, "The report must have only 1 line.")
self.assertEqual(lines[0]['document_in'].id, receipt.id, "The report must only show the receipt.")
self.assertEqual(lines[0]['document_out'], False)
self.assertEqual(lines[0]['quantity'], reordering_rule.product_max_qty)
def test_report_forecast_5_multi_warehouse(self):
""" Create some transfer for two different warehouses and check the
report display the good moves according to the selected warehouse.
"""
# Warehouse config.
wh_2 = self.env['stock.warehouse'].create({
'name': 'Evil Twin Warehouse',
'code': 'ETWH',
})
picking_type_out_2 = self.env['stock.picking.type'].search([
('code', '=', 'outgoing'),
('warehouse_id', '=', wh_2.id),
])
# Creates a delivery then checks draft picking quantities.
delivery_form = Form(self.env['stock.picking'].with_context(
force_detailed_view=True
), view='stock.view_picking_form')
delivery_form.partner_id = self.partner
delivery_form.picking_type_id = self.picking_type_out
delivery = delivery_form.save()
with delivery_form.move_ids_without_package.new() as move_line:
move_line.product_id = self.product
move_line.product_uom_qty = 5
delivery = delivery_form.save()
report_values, docs, lines = self.get_report_forecast(product_template_ids=self.product_template.ids)
draft_picking_qty = docs['draft_picking_qty']
self.assertEqual(len(lines), 0, "Must have 0 line.")
self.assertEqual(draft_picking_qty['out'], 5)
report_values, docs, lines = self.get_report_forecast(
product_template_ids=self.product_template.ids,
context={'warehouse': wh_2.id},
)
draft_picking_qty = docs['draft_picking_qty']
self.assertEqual(len(lines), 0)
self.assertEqual(draft_picking_qty['out'], 0)
# Confirm the delivery -> The report must now have 1 line.
delivery.action_confirm()
report_values, docs, lines = self.get_report_forecast(product_template_ids=self.product_template.ids)
draft_picking_qty = docs['draft_picking_qty']
self.assertEqual(len(lines), 1)
self.assertEqual(draft_picking_qty['out'], 0)
self.assertEqual(lines[0]['document_out'].id, delivery.id)
self.assertEqual(lines[0]['quantity'], 5)
report_values, docs, lines = self.get_report_forecast(
product_template_ids=self.product_template.ids,
context={'warehouse': wh_2.id},
)
draft_picking_qty = docs['draft_picking_qty']
self.assertEqual(len(lines), 0)
self.assertEqual(draft_picking_qty['out'], 0)
# Creates a delivery for the second warehouse.
delivery_form = Form(self.env['stock.picking'].with_context(
force_detailed_view=True
), view='stock.view_picking_form')
delivery_form.partner_id = self.partner
delivery_form.picking_type_id = picking_type_out_2
delivery_2 = delivery_form.save()
with delivery_form.move_ids_without_package.new() as move_line:
move_line.product_id = self.product
move_line.product_uom_qty = 8
delivery_2 = delivery_form.save()
report_values, docs, lines = self.get_report_forecast(product_template_ids=self.product_template.ids)
draft_picking_qty = docs['draft_picking_qty']
self.assertEqual(len(lines), 1)
self.assertEqual(draft_picking_qty['out'], 0)
self.assertEqual(lines[0]['document_out'].id, delivery.id)
self.assertEqual(lines[0]['quantity'], 5)
report_values, docs, lines = self.get_report_forecast(
product_template_ids=self.product_template.ids,
context={'warehouse': wh_2.id},
)
draft_picking_qty = docs['draft_picking_qty']
self.assertEqual(len(lines), 0)
self.assertEqual(draft_picking_qty['out'], 8)
# Confirm the second delivery -> The report must now have 1 line.
delivery_2.action_confirm()
report_values, docs, lines = self.get_report_forecast(product_template_ids=self.product_template.ids)
draft_picking_qty = docs['draft_picking_qty']
self.assertEqual(len(lines), 1)
self.assertEqual(draft_picking_qty['out'], 0)
self.assertEqual(lines[0]['document_out'].id, delivery.id)
self.assertEqual(lines[0]['quantity'], 5)
report_values, docs, lines = self.get_report_forecast(
product_template_ids=self.product_template.ids,
context={'warehouse': wh_2.id},
)
draft_picking_qty = docs['draft_picking_qty']
self.assertEqual(len(lines), 1)
self.assertEqual(draft_picking_qty['out'], 0)
self.assertEqual(lines[0]['document_out'].id, delivery_2.id)
self.assertEqual(lines[0]['quantity'], 8)
def test_report_forecast_6_multi_company(self):
""" Create transfers for two different companies and check report
display the right transfers.
"""
# Configure second warehouse.
company_2 = self.env['res.company'].create({'name': 'Aperture Science'})
wh_2 = self.env['stock.warehouse'].search([('company_id', '=', company_2.id)])
wh_2_picking_type_in = wh_2.in_type_id
# Creates a receipt then checks draft picking quantities.
receipt_form = Form(self.env['stock.picking'].with_context(
force_detailed_view=True
), view='stock.view_picking_form')
receipt_form.partner_id = self.partner
receipt_form.picking_type_id = self.picking_type_in
wh_1_receipt = receipt_form.save()
with receipt_form.move_ids_without_package.new() as move_line:
move_line.product_id = self.product
move_line.product_uom_qty = 2
wh_1_receipt = receipt_form.save()
# Creates a receipt then checks draft picking quantities.
receipt_form = Form(self.env['stock.picking'].with_context(
force_detailed_view=True
), view='stock.view_picking_form')
receipt_form.partner_id = self.partner
receipt_form.picking_type_id = wh_2_picking_type_in
wh_2_receipt = receipt_form.save()
with receipt_form.move_ids_without_package.new() as move_line:
move_line.product_id = self.product
move_line.product_uom_qty = 5
wh_2_receipt = receipt_form.save()
report_values, docs, lines = self.get_report_forecast(product_template_ids=self.product_template.ids)
draft_picking_qty = docs['draft_picking_qty']
self.assertEqual(len(lines), 0, "Must have 0 line.")
self.assertEqual(draft_picking_qty['in'], 2)
self.assertEqual(draft_picking_qty['out'], 0)
report_values, docs, lines = self.get_report_forecast(
product_template_ids=self.product_template.ids,
context={'warehouse': wh_2.id},
)
draft_picking_qty = docs['draft_picking_qty']
self.assertEqual(len(lines), 0, "Must have 0 line.")
self.assertEqual(draft_picking_qty['in'], 5)
self.assertEqual(draft_picking_qty['out'], 0)
# Confirm the receipts -> The report must now have one line for each company.
wh_1_receipt.action_confirm()
wh_2_receipt.action_confirm()
report_values, docs, lines = self.get_report_forecast(product_template_ids=self.product_template.ids)
self.assertEqual(len(lines), 1, "Must have 1 line.")
self.assertEqual(lines[0]['document_in'].id, wh_1_receipt.id)
self.assertEqual(lines[0]['quantity'], 2)
report_values, docs, lines = self.get_report_forecast(
product_template_ids=self.product_template.ids,
context={'warehouse': wh_2.id},
)
self.assertEqual(len(lines), 1, "Must have 1 line.")
self.assertEqual(lines[0]['document_in'].id, wh_2_receipt.id)
self.assertEqual(lines[0]['quantity'], 5)
def test_report_forecast_7_multiple_variants(self):
""" Create receipts for different variant products and check the report
work well with them.Also, check the receipt/delivery lines are correctly
linked depending of their product variant.
"""
# Create some variant's attributes.
product_attr_color = self.env['product.attribute'].create({'name': 'Color'})
color_gray = self.env['product.attribute.value'].create({
'name': 'Old Fashioned Gray',
'attribute_id': product_attr_color.id,
})
color_blue = self.env['product.attribute.value'].create({
'name': 'Electric Blue',
'attribute_id': product_attr_color.id,
})
product_attr_size = self.env['product.attribute'].create({'name': 'size'})
size_pocket = self.env['product.attribute.value'].create({
'name': 'Pocket',
'attribute_id': product_attr_size.id,
})
size_xl = self.env['product.attribute.value'].create({
'name': 'XL',
'attribute_id': product_attr_size.id,
})
# Create a new product and set some variants on the product.
product_template = self.env['product.template'].create({
'name': 'Game Joy',
'type': 'product',
'attribute_line_ids': [
(0, 0, {
'attribute_id': product_attr_color.id,
'value_ids': [(6, 0, [color_gray.id, color_blue.id])]
}),
(0, 0, {
'attribute_id': product_attr_size.id,
'value_ids': [(6, 0, [size_pocket.id, size_xl.id])]
}),
],
})
gamejoy_pocket_gray = product_template.product_variant_ids[0]
gamejoy_xl_gray = product_template.product_variant_ids[1]
gamejoy_pocket_blue = product_template.product_variant_ids[2]
gamejoy_xl_blue = product_template.product_variant_ids[3]
# Create two receipts.
receipt_form = Form(self.env['stock.picking'].with_context(
force_detailed_view=True
), view='stock.view_picking_form')
receipt_form.partner_id = self.partner
receipt_form.picking_type_id = self.picking_type_in
with receipt_form.move_ids_without_package.new() as move_line:
move_line.product_id = gamejoy_pocket_gray
move_line.product_uom_qty = 8
with receipt_form.move_ids_without_package.new() as move_line:
move_line.product_id = gamejoy_pocket_blue
move_line.product_uom_qty = 4
receipt_1 = receipt_form.save()
receipt_1.action_confirm()
receipt_form = Form(self.env['stock.picking'].with_context(
force_detailed_view=True
), view='stock.view_picking_form')
receipt_form.partner_id = self.partner
receipt_form.picking_type_id = self.picking_type_in
with receipt_form.move_ids_without_package.new() as move_line:
move_line.product_id = gamejoy_pocket_gray
move_line.product_uom_qty = 2
with receipt_form.move_ids_without_package.new() as move_line:
move_line.product_id = gamejoy_xl_gray
move_line.product_uom_qty = 10
with receipt_form.move_ids_without_package.new() as move_line:
move_line.product_id = gamejoy_xl_blue
move_line.product_uom_qty = 12
receipt_2 = receipt_form.save()
receipt_2.action_confirm()
report_values, docs, lines = self.get_report_forecast(product_template_ids=product_template.ids)
self.assertEqual(len(lines), 5, "Must have 5 lines.")
self.assertEqual(docs['product_variants'].ids, product_template.product_variant_ids.ids)
# Create a delivery for one of these products and check the report lines
# are correctly linked to the good receipts.
delivery_form = Form(self.env['stock.picking'].with_context(
force_detailed_view=True
), view='stock.view_picking_form')
delivery_form.partner_id = self.partner
delivery_form.picking_type_id = self.picking_type_out
with delivery_form.move_ids_without_package.new() as move_line:
move_line.product_id = gamejoy_pocket_gray
move_line.product_uom_qty = 10
delivery = delivery_form.save()
delivery.action_confirm()
report_values, docs, lines = self.get_report_forecast(product_template_ids=product_template.ids)
self.assertEqual(len(lines), 5, "Still must have 5 lines.")
self.assertEqual(docs['product_variants'].ids, product_template.product_variant_ids.ids)
# First and second lines should be about the "Game Joy Pocket (gray)"
# and must link the delivery with the two receipt lines.
line_1 = lines[0]
line_2 = lines[1]
self.assertEqual(line_1['product']['id'], gamejoy_pocket_gray.id)
self.assertEqual(line_1['quantity'], 8)
self.assertTrue(line_1['replenishment_filled'])
self.assertEqual(line_1['document_in'].id, receipt_1.id)
self.assertEqual(line_1['document_out'].id, delivery.id)
self.assertEqual(line_2['product']['id'], gamejoy_pocket_gray.id)
self.assertEqual(line_2['quantity'], 2)
self.assertTrue(line_2['replenishment_filled'])
self.assertEqual(line_2['document_in'].id, receipt_2.id)
self.assertEqual(line_2['document_out'].id, delivery.id)
def test_report_forecast_8_delivery_to_receipt_link(self):
"""
Create 2 deliveries, and 1 receipt tied to the second delivery.
The report should show the source document as the 2nd delivery, and show the first
delivery completely unfilled.
"""
delivery_form = Form(self.env['stock.picking'].with_context(
force_detailed_view=True
), view='stock.view_picking_form')
delivery_form.partner_id = self.partner
delivery_form.picking_type_id = self.picking_type_out
with delivery_form.move_ids_without_package.new() as move_line:
move_line.product_id = self.product
move_line.product_uom_qty = 100
delivery = delivery_form.save()
delivery.action_confirm()
delivery_form = Form(self.env['stock.picking'].with_context(
force_detailed_view=True
), view='stock.view_picking_form')
delivery_form.partner_id = self.partner
delivery_form.picking_type_id = self.picking_type_out
with delivery_form.move_ids_without_package.new() as move_line:
move_line.product_id = self.product
move_line.product_uom_qty = 200
delivery2 = delivery_form.save()
delivery2.action_confirm()
receipt_form = Form(self.env['stock.picking'].with_context(
force_detailed_view=True
), view='stock.view_picking_form')
receipt_form.partner_id = self.partner
receipt_form.picking_type_id = self.picking_type_in
receipt = receipt_form.save()
with receipt_form.move_ids_without_package.new() as move_line:
move_line.product_id = self.product
move_line.product_uom_qty = 200
receipt = receipt_form.save()
receipt.move_lines[0].write({
'move_dest_ids': [(4, delivery2.move_lines[0].id)],
})
receipt.action_confirm()
self.env['base'].flush()
_, _, lines = self.get_report_forecast(product_template_ids=self.product_template.ids)
self.assertEqual(len(lines), 2, 'Only 2 lines')
delivery_line = [l for l in lines if l['document_out'].id == delivery.id][0]
self.assertTrue(delivery_line, 'No line for delivery 1')
self.assertFalse(delivery_line['replenishment_filled'])
delivery2_line = [l for l in lines if l['document_out'].id == delivery2.id][0]
self.assertTrue(delivery2_line, 'No line for delivery 2')
self.assertTrue(delivery2_line['replenishment_filled'])
def test_report_forecast_9_delivery_to_receipt_link_over_received(self):
"""
Create 2 deliveries, and 1 receipt tied to the second delivery.
Set the quantity on the receipt to be enough for BOTH deliveries.
For example, this can happen if they have manually increased the quantity on the generated PO.
The report should show both deliveries fulfilled.
"""
delivery_form = Form(self.env['stock.picking'].with_context(
force_detailed_view=True
), view='stock.view_picking_form')
delivery_form.partner_id = self.partner
delivery_form.picking_type_id = self.picking_type_out
with delivery_form.move_ids_without_package.new() as move_line:
move_line.product_id = self.product
move_line.product_uom_qty = 100
delivery = delivery_form.save()
delivery.action_confirm()
delivery_form = Form(self.env['stock.picking'].with_context(
force_detailed_view=True
), view='stock.view_picking_form')
delivery_form.partner_id = self.partner
delivery_form.picking_type_id = self.picking_type_out
with delivery_form.move_ids_without_package.new() as move_line:
move_line.product_id = self.product
move_line.product_uom_qty = 200
delivery2 = delivery_form.save()
delivery2.action_confirm()
receipt_form = Form(self.env['stock.picking'].with_context(
force_detailed_view=True
), view='stock.view_picking_form')
receipt_form.partner_id = self.partner
receipt_form.picking_type_id = self.picking_type_in
receipt = receipt_form.save()
with receipt_form.move_ids_without_package.new() as move_line:
move_line.product_id = self.product
move_line.product_uom_qty = 300
receipt = receipt_form.save()
receipt.move_lines[0].write({
'move_dest_ids': [(4, delivery2.move_lines[0].id)],
})
receipt.action_confirm()
self.env['base'].flush()
_, _, lines = self.get_report_forecast(product_template_ids=self.product_template.ids)
self.assertEqual(len(lines), 2, 'Only 2 lines')
delivery_line = [l for l in lines if l['document_out'].id == delivery.id][0]
self.assertTrue(delivery_line, 'No line for delivery 1')
self.assertTrue(delivery_line['replenishment_filled'])
delivery2_line = [l for l in lines if l['document_out'].id == delivery2.id][0]
self.assertTrue(delivery2_line, 'No line for delivery 2')
self.assertTrue(delivery2_line['replenishment_filled'])
def test_report_forecast_10_report_line_corresponding_to_picking_highlighted(self):
""" When accessing the report from a stock move, checks if the correct picking is highlighted in the report
and if the forecasted availability for incoming moves is correct
"""
# Creation of one delivery with date 'today'
delivery_form = Form(self.env['stock.picking'])
delivery_form.partner_id = self.partner
delivery_form.picking_type_id = self.picking_type_out
delivery_form.scheduled_date = date.today()
with delivery_form.move_ids_without_package.new() as move:
move.product_id = self.product
move.product_uom_qty = 200
delivery1 = delivery_form.save()
delivery1.action_confirm()
# Creation of one receipt with date 'today + 1' and smaller qty than the delivery
receipt_form = Form(self.env['stock.picking'])
receipt_form.partner_id = self.partner
receipt_form.picking_type_id = self.picking_type_in
receipt_form.scheduled_date = date.today() + timedelta(days=1)
with receipt_form.move_ids_without_package.new() as move:
move.product_id = self.product
move.product_uom_qty = 150
receipt1 = receipt_form.save()
receipt1.action_confirm()
self.assertEqual(receipt1.move_lines.forecast_availability, -50.0)
# Creation of an identical receipt which should lead to a positive forecast availability
receipt2 = receipt1.copy()
receipt2.action_confirm()
for move in receipt2.move_lines:
move.quantity_done = 150
receipt2.button_validate()
self.assertEqual(receipt1.move_lines.forecast_availability, 100.0)
delivery2 = delivery1.copy()
delivery2.action_confirm()
receipt1.move_lines._compute_forecast_information()
self.assertEqual(receipt1.move_lines.forecast_availability, -100.0)
# Check for both deliveries and receipts if the highlight (is_matched) corresponds to the correct picking
for picking in [delivery1, delivery2, receipt1, receipt2]:
context = picking.move_lines[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 picking in [line['document_in'], line['document_out']]:
self.assertTrue(line['is_matched'], "The corresponding picking should be matched in the forecast report.")
else:
self.assertFalse(line['is_matched'], "A line of the forecast report not linked to the picking shoud not be matched.")
def test_report_forecast_11_non_reserved_order(self):
""" Creates deliveries with different operation type reservation methods.
Checks replenishment lines are correctly sorted by reservation_date:
'manual': always last (no reservation_date)
'at_confirm': reservation_date = time of creation
'by_date': reservation_date = scheduled_date - reservation_days_before(_priority)
"""
picking_type_manual = self.picking_type_out.copy()
picking_type_by_date = picking_type_manual.copy()
picking_type_at_confirm = picking_type_manual.copy()
picking_type_manual.reservation_method = 'manual'
picking_type_manual.sequence_code = 'manual'
picking_type_by_date.reservation_method = 'by_date'
picking_type_by_date.sequence_code = 'by'
# artificially make non-priority moves reserve before priority moves to
# check order doesn't prioritize priority
picking_type_by_date.reservation_days_before = '6'
picking_type_by_date.reservation_days_before_priority = '4'
picking_type_at_confirm.reservation_method = 'at_confirm'
picking_type_at_confirm.sequence_code = 'confirm'
# 'manual' reservation => no reservation_date
delivery_form = Form(self.env['stock.picking'].with_context(
force_detailed_view=True
), view='stock.view_picking_form')
delivery_form.partner_id = self.partner
delivery_form.picking_type_id = picking_type_manual
delivery_form.scheduled_date = datetime.now() - timedelta(days=10)
with delivery_form.move_ids_without_package.new() as move_line:
move_line.product_id = self.product
move_line.product_uom_qty = 3
delivery_manual = delivery_form.save()
delivery_manual.action_confirm()
# 'by_date' reservation => reservation_date = 1 day before today
delivery_form = Form(self.env['stock.picking'].with_context(
force_detailed_view=True
), view='stock.view_picking_form')
delivery_form.partner_id = self.partner
delivery_form.picking_type_id = picking_type_by_date
delivery_form.scheduled_date = datetime.now() + timedelta(days=5)
with delivery_form.move_ids_without_package.new() as move_line:
move_line.product_id = self.product
move_line.product_uom_qty = 3
delivery_by_date = delivery_form.save()
delivery_by_date.action_confirm()
# 'by_date' reservation (priority) => reservation_date = 1 day after today
delivery_form = Form(self.env['stock.picking'].with_context(
force_detailed_view=True
), view='stock.view_picking_form')
delivery_form.partner_id = self.partner
delivery_form.picking_type_id = picking_type_by_date
delivery_form.scheduled_date = datetime.now() + timedelta(days=5)
delivery_form.priority = '1'
with delivery_form.move_ids_without_package.new() as move_line:
move_line.product_id = self.product
move_line.product_uom_qty = 3
delivery_by_date_priority = delivery_form.save()
delivery_by_date_priority.action_confirm()
# 'at_confirm' reservation => reservation_date = today
delivery_form = Form(self.env['stock.picking'].with_context(
force_detailed_view=True
), view='stock.view_picking_form')
delivery_form.partner_id = self.partner
delivery_form.picking_type_id = picking_type_at_confirm
with delivery_form.move_ids_without_package.new() as move_line:
move_line.product_id = self.product
move_line.product_uom_qty = 3
delivery_at_confirm = delivery_form.save()
delivery_at_confirm.action_confirm()
# Order should be: delivery_by_date, delivery_at_confirm, delivery_by_date_priority, delivery_manual
_, _, lines = self.get_report_forecast(product_template_ids=self.product_template.ids)
self.assertEqual(len(lines), 4, "The report must have 4 lines.")
self.assertEqual(lines[0]['document_out'].id, delivery_by_date.id)
self.assertEqual(lines[1]['document_out'].id, delivery_at_confirm.id)
self.assertEqual(lines[2]['document_out'].id, delivery_by_date_priority.id)
self.assertEqual(lines[3]['document_out'].id, delivery_manual.id)