mirror of
https://github.com/OCA/manufacture.git
synced 2025-01-28 16:37:15 +02:00
@@ -1 +1,2 @@
|
||||
from . import models
|
||||
from . import wizards
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
With this module, you can restrict Production Orders validation if all
|
||||
product quantities don't correspond to the quantities to do.
|
||||
|
||||
It restricts also the produce action and does not allow void values on lots.
|
||||
|
||||
@@ -14,6 +14,7 @@ class TestNoPartial(common.TransactionCase):
|
||||
self.bom_obj = self.env['mrp.bom']
|
||||
self.location = self.env.ref('stock.stock_location_stock')
|
||||
self.picking_type = self.env.ref('mrp.picking_type_manufacturing')
|
||||
self.produce_wizard_obj = self.env['mrp.product.produce']
|
||||
|
||||
self.picking_type.mrp_no_partial = True
|
||||
|
||||
@@ -24,6 +25,12 @@ class TestNoPartial(common.TransactionCase):
|
||||
'type': 'product',
|
||||
'uom_id': self.uom.id,
|
||||
})
|
||||
|
||||
self.product_2 = self.env['product.product'].create({
|
||||
'name': 'Product MRP 2',
|
||||
'type': 'product',
|
||||
'uom_id': self.uom.id,
|
||||
})
|
||||
self.product_raw_material = self.env['product.product'].create({
|
||||
'name': 'Raw Material',
|
||||
'type': 'product',
|
||||
@@ -50,6 +57,20 @@ class TestNoPartial(common.TransactionCase):
|
||||
})
|
||||
product_qty.change_product_qty()
|
||||
|
||||
self.product_raw_material_lot = self.env['product.product'].create({
|
||||
'name': 'Raw Material Lotted',
|
||||
'tracking': 'lot',
|
||||
'type': 'product',
|
||||
'uom_id': self.uom.id,
|
||||
})
|
||||
|
||||
product_qty = self.env['stock.change.product.qty'].create({
|
||||
'location_id': self.location.id,
|
||||
'product_id': self.product_raw_material_lot.id,
|
||||
'new_quantity': 100.0,
|
||||
})
|
||||
product_qty.change_product_qty()
|
||||
|
||||
self.bom = self.env['mrp.bom'].create({
|
||||
'product_id': self.product.id,
|
||||
'product_tmpl_id': self.product.product_tmpl_id.id,
|
||||
@@ -67,6 +88,28 @@ class TestNoPartial(common.TransactionCase):
|
||||
])
|
||||
})
|
||||
|
||||
self.bom_2 = self.env['mrp.bom'].create({
|
||||
'product_id': self.product_2.id,
|
||||
'product_tmpl_id': self.product_2.product_tmpl_id.id,
|
||||
'bom_line_ids': ([
|
||||
(0, 0, {
|
||||
'product_id': self.product_raw_material.id,
|
||||
'product_qty': 5,
|
||||
'product_uom_id': self.uom.id
|
||||
}),
|
||||
(0, 0, {
|
||||
'product_id': self.product_raw_material2.id,
|
||||
'product_qty': 4,
|
||||
'product_uom_id': self.uom.id
|
||||
}),
|
||||
(0, 0, {
|
||||
'product_id': self.product_raw_material_lot.id,
|
||||
'product_qty': 3,
|
||||
'product_uom_id': self.uom.id
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
# Create Production Order
|
||||
vals = {
|
||||
'picking_type_id': self.picking_type.id,
|
||||
@@ -78,6 +121,17 @@ class TestNoPartial(common.TransactionCase):
|
||||
}
|
||||
self.production = self.production_obj.create(vals)
|
||||
|
||||
# Create Production Order with lot
|
||||
vals = {
|
||||
'picking_type_id': self.picking_type.id,
|
||||
'product_id': self.product_2.id,
|
||||
'product_qty': 1,
|
||||
'product_uom_id': self.uom.id,
|
||||
'bom_id': self.bom_2.id
|
||||
|
||||
}
|
||||
self.production_2 = self.production_obj.create(vals)
|
||||
|
||||
def test_no_partial(self):
|
||||
self.production.action_assign()
|
||||
self.assertEquals(
|
||||
@@ -102,3 +156,17 @@ class TestNoPartial(common.TransactionCase):
|
||||
self.picking_type.mrp_no_partial = False
|
||||
self.production.action_assign()
|
||||
self.production.button_mark_done()
|
||||
|
||||
def test_partial_with_lots(self):
|
||||
# Assign production order
|
||||
# Launch production wizard
|
||||
# Check if error is raised
|
||||
self.production_2.action_assign()
|
||||
wizard = self.produce_wizard_obj.with_context(
|
||||
active_id=self.production_2.id).create({})
|
||||
self.assertEquals(
|
||||
1,
|
||||
len(wizard.consume_line_ids)
|
||||
)
|
||||
with self.assertRaises(ValidationError):
|
||||
wizard.do_produce()
|
||||
|
||||
1
mrp_no_partial/wizards/__init__.py
Normal file
1
mrp_no_partial/wizards/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import mrp_product_produce
|
||||
27
mrp_no_partial/wizards/mrp_product_produce.py
Normal file
27
mrp_no_partial/wizards/mrp_product_produce.py
Normal file
@@ -0,0 +1,27 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2019 ACSONE SA/NV
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import api, models, _
|
||||
from odoo.tools import float_compare
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class MrpProductProduce(models.TransientModel):
|
||||
|
||||
_inherit = 'mrp.product.produce'
|
||||
|
||||
@api.multi
|
||||
def do_produce(self):
|
||||
if self.production_id.picking_type_id.mrp_no_partial:
|
||||
incomplete_move_lots = self.consume_line_ids.filtered(
|
||||
lambda l: float_compare(
|
||||
l.quantity,
|
||||
l.quantity_done,
|
||||
precision_rounding=l.product_id.uom_id.rounding))
|
||||
if incomplete_move_lots:
|
||||
raise ValidationError(
|
||||
_('Please fill in every lot quantity for this '
|
||||
'Production Order. You cannot validate a '
|
||||
'Production Order with not done quantities!'))
|
||||
return super(MrpProductProduce, self).do_produce()
|
||||
Reference in New Issue
Block a user