139 lines
5.6 KiB
Python
139 lines
5.6 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from odoo import Command
|
|
from odoo.addons.account.tests.common import AccountTestInvoicingCommon
|
|
from odoo.tests import common
|
|
|
|
from odoo.tools import html2plaintext
|
|
|
|
|
|
@common.tagged('post_install', '-at_install')
|
|
class TestSaleMrpInvoices(AccountTestInvoicingCommon):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super().setUpClass()
|
|
|
|
cls.product_by_lot = cls.env['product.product'].create({
|
|
'name': 'Product By Lot',
|
|
'is_storable': True,
|
|
'tracking': 'lot',
|
|
})
|
|
cls.warehouse = cls.env['stock.warehouse'].search([('company_id', '=', cls.env.company.id)], limit=1)
|
|
cls.stock_location = cls.warehouse.lot_stock_id
|
|
cls.lot = cls.env['stock.lot'].create({
|
|
'name': 'LOT0001',
|
|
'product_id': cls.product_by_lot.id,
|
|
})
|
|
cls.env['stock.quant']._update_available_quantity(cls.product_by_lot, cls.stock_location, 10, lot_id=cls.lot)
|
|
|
|
cls.tracked_kit = cls.env['product.product'].create({
|
|
'name': 'Simple Kit',
|
|
'type': 'consu',
|
|
})
|
|
cls.env['mrp.bom'].create({
|
|
'product_tmpl_id': cls.tracked_kit.product_tmpl_id.id,
|
|
'type': 'phantom',
|
|
'bom_line_ids': [(0, 0, {
|
|
'product_id': cls.product_by_lot.id,
|
|
'product_qty': 1,
|
|
})]
|
|
})
|
|
cls.partner = cls.env['res.partner'].create({'name': 'Test Partner'})
|
|
|
|
def test_deliver_and_invoice_tracked_components(self):
|
|
"""
|
|
Suppose the lots are printed on the invoices.
|
|
The user sells a kit that has one tracked component.
|
|
The lot of the delivered component should be on the invoice.
|
|
"""
|
|
display_lots = self.env.ref('stock_account.group_lot_on_invoice')
|
|
display_uom = self.env.ref('uom.group_uom')
|
|
self.env.user.write({'groups_id': [(4, display_lots.id), (4, display_uom.id)]})
|
|
|
|
so = self.env['sale.order'].create({
|
|
'partner_id': self.partner.id,
|
|
'order_line': [
|
|
(0, 0, {'name': self.tracked_kit.name, 'product_id': self.tracked_kit.id, 'product_uom_qty': 1}),
|
|
],
|
|
})
|
|
so.action_confirm()
|
|
|
|
so.picking_ids.button_validate()
|
|
|
|
invoice = so._create_invoices()
|
|
invoice.action_post()
|
|
|
|
html = self.env['ir.actions.report']._render_qweb_html(
|
|
'account.report_invoice_with_payments', invoice.ids)[0]
|
|
text = html2plaintext(html.decode())
|
|
self.assertRegex(text, r'Product By Lot\n1.00Units\nLOT0001', "There should be a line that specifies 1 x LOT0001")
|
|
|
|
def test_report_forecast_for_mto_procure_method(self):
|
|
"""
|
|
Check that mto moves are not reported as taking from stock in the forecast report
|
|
"""
|
|
mto_route = self.env.ref('stock.route_warehouse0_mto')
|
|
mto_route.active = True
|
|
manufacturing_route = self.env.ref('mrp.route_warehouse0_manufacture')
|
|
product = self.env['product.product'].create({
|
|
'name': 'SuperProduct',
|
|
'is_storable': True,
|
|
'route_ids': [Command.set((mto_route + manufacturing_route).ids)]
|
|
})
|
|
|
|
product.bom_ids = [Command.create({
|
|
'product_id': product.id,
|
|
'product_tmpl_id': product.product_tmpl_id.id,
|
|
'product_uom_id': product.uom_id.id,
|
|
'bom_line_ids': [Command.create({
|
|
'product_id': self.product_by_lot.id,
|
|
'product_qty': 1,
|
|
})]
|
|
})]
|
|
warehouse = self.warehouse
|
|
# make 2 so: so_1 can be fulfilled and so_2 requires a replenishment
|
|
self.env['stock.quant']._update_available_quantity(product, warehouse.lot_stock_id, 10.0)
|
|
so_1, so_2 = self.env['sale.order'].create([
|
|
{
|
|
'partner_id': self.partner_a.id,
|
|
'order_line': [Command.create({
|
|
'name': product.name,
|
|
'product_id': product.id,
|
|
'product_uom_qty': 8.0,
|
|
'product_uom': product.uom_id.id,
|
|
'price_unit': product.list_price,
|
|
})]
|
|
},
|
|
{
|
|
'partner_id': self.partner_a.id,
|
|
'order_line': [Command.create({
|
|
'name': product.name,
|
|
'product_id': product.id,
|
|
'product_uom_qty': 7.0,
|
|
'product_uom': product.uom_id.id,
|
|
'price_unit': product.list_price,
|
|
})]
|
|
},
|
|
|
|
])
|
|
(so_1 | so_2).action_confirm()
|
|
report_lines = self.env['stock.forecasted_product_product'].with_context(warehouse=warehouse.id).get_report_values(docids=product.ids)['docs']['lines']
|
|
self.assertEqual(len(report_lines), 3)
|
|
so_1_line = report_lines[0]
|
|
self.assertEqual(
|
|
[so_1_line['quantity'], so_1_line['move_out']['id'], so_1_line['replenishment_filled']],
|
|
[8.0, so_1.picking_ids.move_ids.id, True]
|
|
)
|
|
so_2_line = report_lines[1]
|
|
self.assertEqual(
|
|
[so_2_line['quantity'], so_2_line['move_out']['id'], so_2_line['replenishment_filled']],
|
|
[7.0, so_2.picking_ids.move_ids.id, True]
|
|
)
|
|
replenisment_line = report_lines[2]
|
|
self.assertEqual(
|
|
[replenisment_line['document_in'], replenisment_line['document_out'], replenisment_line['quantity'], replenisment_line['move_out'], replenisment_line['replenishment_filled']],
|
|
[False, False, 10.0, None, True]
|
|
)
|