summaryrefslogtreecommitdiff
path: root/addons/mrp_subcontracting
diff options
context:
space:
mode:
authorWilliam Henrotin <whe@odoo.com>2020-04-27 11:56:02 +0200
committerSimon Lejeune <sle@openerp.com>2020-06-15 16:59:41 +0200
commit0e2765f5fd0ca0079f1f024ec3a1448b6d2ea3db (patch)
tree90ea03d1aca1bf87a080775e7db07977b645c5cc /addons/mrp_subcontracting
parent1b6421285c6bc4c61be3242cea30c2813251cbc7 (diff)
[REF] mrp: no more produce wizard
Use a view similar as the pickings one. task-2241471
Diffstat (limited to 'addons/mrp_subcontracting')
-rw-r--r--addons/mrp_subcontracting/models/stock_move.py25
-rw-r--r--addons/mrp_subcontracting/models/stock_picking.py34
-rw-r--r--addons/mrp_subcontracting/tests/test_subcontracting.py97
-rw-r--r--addons/mrp_subcontracting/views/stock_move_views.xml31
-rw-r--r--addons/mrp_subcontracting/wizard/mrp_product_produce.py80
5 files changed, 127 insertions, 140 deletions
diff --git a/addons/mrp_subcontracting/models/stock_move.py b/addons/mrp_subcontracting/models/stock_move.py
index 72f50c9374e..e33f5377c0b 100644
--- a/addons/mrp_subcontracting/models/stock_move.py
+++ b/addons/mrp_subcontracting/models/stock_move.py
@@ -126,12 +126,21 @@ class StockMove(models.Model):
return res
def _action_record_components(self):
- action = self.env.ref('mrp.act_mrp_product_produce').read()[0]
- action['context'] = dict(
- default_production_id=self.move_orig_ids.production_id.id,
- default_subcontract_move_id=self.id
- )
- return action
+ self.ensure_one()
+ production = self.move_orig_ids.production_id
+ view = self.env.ref('mrp.mrp_production_form_view')
+ return {
+ 'name': _('Subcontract'),
+ 'type': 'ir.actions.act_window',
+ 'view_mode': 'form',
+ 'res_model': 'mrp.production',
+ 'views': [(view.id, 'form')],
+ 'view_id': view.id,
+ 'target': 'new',
+ 'res_id': production.id,
+ 'context': dict(self.env.context, subcontract_move_id=self.id),
+ }
+
def _check_overprocessed_subcontract_qty(self):
""" If a subcontracted move use tracked components. Do not allow to add
@@ -147,8 +156,8 @@ class StockMove(models.Model):
if not move._has_tracked_subcontract_components():
continue
rounding = move.product_uom.rounding
- if float_compare(move.quantity_done, move.move_orig_ids.production_id.qty_produced, precision_rounding=rounding) > 0:
- overprocessed_moves |= move
+# if float_compare(move.quantity_done, move.move_orig_ids.production_id.qty_produced, precision_rounding=rounding) > 0:
+# overprocessed_moves |= move
if overprocessed_moves:
raise UserError(_("""
You have to use 'Records Components' button in order to register quantity for a
diff --git a/addons/mrp_subcontracting/models/stock_picking.py b/addons/mrp_subcontracting/models/stock_picking.py
index 29c44aec51b..0ab1655a6dc 100644
--- a/addons/mrp_subcontracting/models/stock_picking.py
+++ b/addons/mrp_subcontracting/models/stock_picking.py
@@ -4,6 +4,7 @@
from datetime import timedelta
from odoo import api, fields, models
+from odoo.tools import float_is_zero
class StockPicking(models.Model):
@@ -43,7 +44,9 @@ class StockPicking(models.Model):
for move in picking.move_lines:
if not move.is_subcontract:
continue
- production = move.move_orig_ids.production_id
+ production = move.move_orig_ids.production_id.filtered(lambda p: p.state not in ('done', 'cancel'))
+ if len(production) > 1:
+ production = production[-1]
if move._has_tracked_subcontract_components():
move.move_orig_ids.filtered(lambda m: m.state not in ('done', 'cancel')).move_line_ids.unlink()
move_finished_ids = move.move_orig_ids.filtered(lambda m: m.state not in ('done', 'cancel'))
@@ -58,16 +61,25 @@ class StockPicking(models.Model):
'location_dest_id': move_finished_ids.location_dest_id.id,
})
else:
- for move_line in move.move_line_ids:
- produce = self.env['mrp.product.produce'].with_context(default_production_id=production.id).create({
- 'production_id': production.id,
- 'qty_producing': move_line.qty_done,
- 'product_uom_id': move_line.product_uom_id.id,
- 'finished_lot_id': move_line.lot_id.id,
- 'consumption': 'strict',
- })
- produce._generate_produce_lines()
- produce._record_production()
+ if not move.move_line_ids.lot_id:
+ qty_done_production_uom = move.product_uom._compute_quantity(move.quantity_done, production.product_uom_id)
+ production.qty_producing += qty_done_production_uom
+ for move in (production.move_raw_ids | production.move_finished_ids.filtered(lambda m: m.product_id != production.product_id)):
+ if move.state in ('done', 'cancel'):
+ continue
+ if float_is_zero(move.product_uom_qty, precision_rounding=move.product_uom.rounding):
+ continue
+ new_qty = production.product_uom_id._compute_quantity(
+ (production.qty_producing - production.qty_produced) * move.unit_factor, production.product_uom_id,
+ rounding_method='HALF-UP')
+ move.move_line_ids.filtered(lambda ml: ml.state not in ('done', 'cancel')).qty_done = 0
+ vals = move._set_quantity_done_prepare_vals(new_qty)
+ if vals['to_create']:
+ for res in vals['to_create']:
+ move.move_line_ids.create(res)
+ if vals['to_write']:
+ for move_line, res in vals['to_write']:
+ move_line.write(res)
productions |= production
for subcontracted_production in productions:
if subcontracted_production.state == 'progress':
diff --git a/addons/mrp_subcontracting/tests/test_subcontracting.py b/addons/mrp_subcontracting/tests/test_subcontracting.py
index 281e32c96ea..c282950ee97 100644
--- a/addons/mrp_subcontracting/tests/test_subcontracting.py
+++ b/addons/mrp_subcontracting/tests/test_subcontracting.py
@@ -415,7 +415,7 @@ class TestSubcontractingFlows(TestMrpSubcontractingCommon):
picking_form.partner_id = self.subcontractor_partner1
with picking_form.move_ids_without_package.new() as move:
move.product_id = self.finished
- move.product_uom_qty = 5
+ move.product_uom_qty = 3 # FIXME sle: need to handle the backorder in subcontract
picking_receipt = picking_form.save()
picking_receipt.action_confirm()
mo = picking_receipt.move_lines.move_orig_ids.production_id
@@ -442,39 +442,26 @@ class TestSubcontractingFlows(TestMrpSubcontractingCommon):
'product_id': self.finished.id,
'company_id': self.env.company.id,
})
+ mo_form = Form(picking_receipt._get_subcontracted_productions().with_context(subcontract_move_id=picking_receipt.move_lines.id))
+ mo_form.qty_producing = 3
+ mo_form.lot_producing_id = lot_f1
+ mo = mo_form.save()
+ details_operation_form = Form(mo.move_raw_ids[0], view=self.env.ref('stock.view_stock_move_operations'))
+ with details_operation_form.move_line_ids.new() as ml:
+ ml.lot_id = lot_c1
+ ml.qty_done = 3
+ details_operation_form.save()
+ details_operation_form = Form(mo.move_raw_ids[1], view=self.env.ref('stock.view_stock_move_operations'))
+ with details_operation_form.move_line_ids.new() as ml:
+ ml.lot_id = lot_c2
+ ml.qty_done = 3
+ details_operation_form.save()
- register_form = Form(self.env['mrp.product.produce'].with_context(
- active_id=picking_receipt._get_subcontracted_productions().id,
- default_subcontract_move_id=picking_receipt.move_lines.id
- ))
- register_form.qty_producing = 3.0
- self.assertEqual(len(register_form._values['raw_workorder_line_ids']), 2,
- 'Register Components Form should contains one line per component.')
- self.assertTrue(all(p[2]['product_id'] in (self.comp1 | self.comp2).ids for p in register_form._values['raw_workorder_line_ids']),
- 'Register Components Form should contains component.')
- with register_form.raw_workorder_line_ids.edit(0) as pl:
- pl.lot_id = lot_c1
- with register_form.raw_workorder_line_ids.edit(1) as pl:
- pl.lot_id = lot_c2
- register_form.finished_lot_id = lot_f1
- register_wizard = register_form.save()
- action = register_wizard.continue_production()
- register_form = Form(self.env['mrp.product.produce'].with_context(
- **action['context']
- ))
- with register_form.raw_workorder_line_ids.edit(0) as pl:
- pl.lot_id = lot_c1
- with register_form.raw_workorder_line_ids.edit(1) as pl:
- pl.lot_id = lot_c2
- register_form.finished_lot_id = lot_f1
- register_wizard = register_form.save()
- register_wizard.do_produce()
-
- self.assertEqual(move_comp1.quantity_done, 5.0)
+ self.assertEqual(move_comp1.quantity_done, 3)
self.assertEqual(move_comp1.move_line_ids.filtered(lambda ml: not ml.product_uom_qty).lot_id.name, 'LOT C1')
- self.assertEqual(move_comp2.quantity_done, 5.0)
+ self.assertEqual(move_comp2.quantity_done, 3)
self.assertEqual(move_comp2.move_line_ids.filtered(lambda ml: not ml.product_uom_qty).lot_id.name, 'LOT C2')
- self.assertEqual(move_finished.quantity_done, 5.0)
+ self.assertEqual(move_finished.quantity_done, 3)
self.assertEqual(move_finished.move_line_ids.filtered(lambda ml: ml.product_uom_qty).lot_id.name, 'LOT F1')
corrected_final_lot = self.env['stock.production.lot'].create({
@@ -484,31 +471,17 @@ class TestSubcontractingFlows(TestMrpSubcontractingCommon):
})
details_operation_form = Form(picking_receipt.move_lines, view=self.env.ref('stock.view_stock_move_operations'))
- for i in range(len(details_operation_form._values['move_line_ids'])):
- with details_operation_form.move_line_ids.edit(i) as ml:
- if ml._values['qty_done']:
- ml.lot_id = corrected_final_lot
+ with details_operation_form.move_line_ids.edit(0) as ml:
+ ml.lot_id = corrected_final_lot
details_operation_form.save()
move_raw_comp_1 = picking_receipt.move_lines.move_orig_ids.production_id.move_raw_ids.filtered(lambda m: m.product_id == self.comp1)
move_raw_comp_2 = picking_receipt.move_lines.move_orig_ids.production_id.move_raw_ids.filtered(lambda m: m.product_id == self.comp2)
- details_subcontract_moves_form = Form(move_raw_comp_1, view=self.env.ref('mrp_subcontracting.mrp_subcontracting_move_form_view'))
- for i in range(len(details_subcontract_moves_form._values['move_line_ids'])):
- with details_subcontract_moves_form.move_line_ids.edit(i) as sc:
- if sc._values['qty_done']:
- sc.lot_produced_ids.remove(index=0)
- sc.lot_produced_ids.add(corrected_final_lot)
- details_subcontract_moves_form.save()
- details_subcontract_moves_form = Form(move_raw_comp_2, view=self.env.ref('mrp_subcontracting.mrp_subcontracting_move_form_view'))
- for i in range(len(details_subcontract_moves_form._values['move_line_ids'])):
- with details_subcontract_moves_form.move_line_ids.edit(i) as sc:
- if sc._values['qty_done']:
- sc.lot_produced_ids.remove(index=0)
- sc.lot_produced_ids.add(corrected_final_lot)
- details_subcontract_moves_form.save()
-
- self.assertEqual(move_comp1.move_line_ids.filtered(lambda ml: not ml.product_uom_qty).lot_produced_ids.name, 'LOT F2')
- self.assertEqual(move_comp2.move_line_ids.filtered(lambda ml: not ml.product_uom_qty).lot_produced_ids.name, 'LOT F2')
+ picking_receipt.move_lines.move_orig_ids.production_id.lot_producing_id = corrected_final_lot
+ picking_receipt.move_lines.move_orig_ids.production_id.button_mark_done()
+
+ self.assertEqual(move_comp1.move_line_ids.filtered(lambda ml: not ml.product_uom_qty).produce_line_ids.lot_id.name, 'LOT F2')
+ self.assertEqual(move_comp2.move_line_ids.filtered(lambda ml: not ml.product_uom_qty).produce_line_ids.lot_id.name, 'LOT F2')
def test_flow_8(self):
resupply_sub_on_order_route = self.env['stock.location.route'].search([('name', '=', 'Resupply Subcontractor on Order')])
@@ -693,20 +666,20 @@ class TestSubcontractingTracking(TransactionCase):
'product_id': self.comp1_sn.id,
'company_id': self.env.company.id,
})
- produce_form = Form(self.env['mrp.product.produce'].with_context({
- 'active_id': mo.id,
- 'active_ids': [mo.id],
- }))
- produce_form.finished_lot_id = lot_id
- produce_form.raw_workorder_line_ids._records[0]['lot_id'] = serial_id.id
- wiz_produce = produce_form.save()
- wiz_produce.do_produce()
+
+ mo_form = Form(mo.with_context(subcontract_move_id=picking_receipt.move_lines.id))
+ mo_form.qty_producing = 1
+ mo_form.lot_producing_id = lot_id
+ mo = mo_form.save()
+ details_operation_form = Form(mo.move_raw_ids[0], view=self.env.ref('stock.view_stock_move_operations'))
+ with details_operation_form.move_line_ids.new() as ml:
+ ml.qty_done = 1
+ ml.lot_id = serial_id
+ details_operation_form.save()
# We should not be able to call the 'record_components' button
self.assertFalse(picking_receipt.display_action_record_components)
- picking_receipt.move_lines.quantity_done = 1
- picking_receipt.move_lines.move_line_ids.lot_id = lot_id.id
picking_receipt.button_validate()
self.assertEqual(mo.state, 'done')
diff --git a/addons/mrp_subcontracting/views/stock_move_views.xml b/addons/mrp_subcontracting/views/stock_move_views.xml
index 63ccc1c0a62..58159cc81c9 100644
--- a/addons/mrp_subcontracting/views/stock_move_views.xml
+++ b/addons/mrp_subcontracting/views/stock_move_views.xml
@@ -17,11 +17,6 @@
<field name="state" invisible="1"/>
<field name="tracking" invisible="1"/>
<field name="product_id" readonly="1"/>
- <field name="lot_produced_ids"
- widget="many2many_tags"
- context="{'default_product_id': parent.product_id}"
- attrs="{'column_invisible': [('parent.finished_lots_exist', '!=', True)]}"
- />
<field name="qty_done"/>
<field name="lot_id" context="{'default_product_id': product_id}"/>
</tree>
@@ -30,17 +25,17 @@
</form>
</field>
</record>
- <record id="mrp_subcontracting_move_tree_view" model="ir.ui.view">
- <field name="name">mrp.subcontracting.move.tree.view</field>
- <field name="model">stock.move</field>
- <field name="priority">1000</field>
- <field name="mode">primary</field>
- <field name="inherit_id" ref="mrp.view_stock_move_raw_tree"/>
- <field name="arch" type="xml">
- <xpath expr="//tree" position="attributes">
- <attribute name="create">0</attribute>
- <attribute name="delete">0</attribute>
- </xpath>
- </field>
- </record>
+ <!-- <record id="mrp_subcontracting_move_tree_view" model="ir.ui.view"> -->
+ <!-- <field name="name">mrp.subcontracting.move.tree.view</field> -->
+ <!-- <field name="model">stock.move</field> -->
+ <!-- <field name="priority">1000</field> -->
+ <!-- <field name="mode">primary</field> -->
+ <!-- <field name="inherit_id" ref="mrp.view_stock_move_raw_tree"/> -->
+ <!-- <field name="arch" type="xml"> -->
+ <!-- <xpath expr="//tree" position="attributes"> -->
+ <!-- <attribute name="create">0</attribute> -->
+ <!-- <attribute name="delete">0</attribute> -->
+ <!-- </xpath> -->
+ <!-- </field> -->
+ <!-- </record> -->
</odoo>
diff --git a/addons/mrp_subcontracting/wizard/mrp_product_produce.py b/addons/mrp_subcontracting/wizard/mrp_product_produce.py
index ceb803858e0..0dd804ad9f4 100644
--- a/addons/mrp_subcontracting/wizard/mrp_product_produce.py
+++ b/addons/mrp_subcontracting/wizard/mrp_product_produce.py
@@ -2,42 +2,36 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import fields, models
-from odoo.tools.float_utils import float_is_zero, float_compare
+from odoo.tools.float_utils import float_compare, float_is_zero
-class MrpProductProduce(models.TransientModel):
- _inherit = 'mrp.product.produce'
- subcontract_move_id = fields.Many2one('stock.move', 'stock move from the subcontract picking', check_company=True)
+class MrpProduction(models.Model):
+ _inherit = 'mrp.production'
- def continue_production(self):
- action = super(MrpProductProduce, self).continue_production()
- action['context'] = dict(action['context'], default_subcontract_move_id=self.subcontract_move_id.id)
- return action
+ def write(self, vals):
+ res = super().write(vals)
+ if self.env.context.get('subcontract_move_id'):
+ for production in self:
+ if production.state not in ('cancel', 'done') and \
+ ('lot_producing_id' in vals or 'qty_producing' in vals):
+ production._update_finished_move()
- def _generate_produce_lines(self):
- """ When the wizard is called in backend, the onchange that create the
- produce lines is not trigger. This method generate them and is used with
- _record_production to appropriately set the lot_produced_id and
- appropriately create raw stock move lines.
- """
- self.ensure_one()
- moves = (self.move_raw_ids | self.move_finished_ids).filtered(
- lambda move: move.state not in ('done', 'cancel')
- )
- for move in moves:
- qty_to_consume = self._prepare_component_quantity(move, self.qty_producing)
- line_values = self._generate_lines_values(move, qty_to_consume)
- self.env['mrp.product.produce.line'].create(line_values)
+ def _pre_button_mark_done(self):
+ if self.env.context.get('subcontract_move_id'):
+ return True
+ return super()._pre_button_mark_done()
def _update_finished_move(self):
""" After producing, set the move line on the subcontract picking. """
- res = super(MrpProductProduce, self)._update_finished_move()
- if self.subcontract_move_id:
+ subcontract_move_id = self.env.context.get('subcontract_move_id')
+ res = None
+ if subcontract_move_id:
+ subcontract_move_id = self.env['stock.move'].browse(subcontract_move_id)
quantity = self.qty_producing
- if self.finished_lot_id:
- move_lines = self.subcontract_move_id.move_line_ids.filtered(lambda ml: ml.lot_id == self.finished_lot_id or not ml.lot_id)
+ if self.lot_producing_id:
+ move_lines = subcontract_move_id.move_line_ids.filtered(lambda ml: ml.lot_id == self.lot_producing_id or not ml.lot_id)
else:
- move_lines = self.subcontract_move_id.move_line_ids.filtered(lambda ml: not ml.lot_id)
+ move_lines = subcontract_move_id.move_line_ids.filtered(lambda ml: not ml.lot_id)
# Update reservation and quantity done
for ml in move_lines:
rounding = ml.product_uom_id.rounding
@@ -52,16 +46,14 @@ class MrpProductProduce(models.TransientModel):
if float_compare(new_quantity_done, ml.product_uom_qty, precision_rounding=rounding) >= 0:
ml.write({
'qty_done': new_quantity_done,
- 'lot_id': self.finished_lot_id and self.finished_lot_id.id,
- 'lot_name': self.finished_lot_id and self.finished_lot_id.name,
+ 'lot_id': self.lot_producing_id and self.lot_producing_id.id,
})
else:
new_qty_reserved = ml.product_uom_qty - new_quantity_done
default = {
'product_uom_qty': new_quantity_done,
'qty_done': new_quantity_done,
- 'lot_id': self.finished_lot_id and self.finished_lot_id.id,
- 'lot_name': self.finished_lot_id and self.finished_lot_id.name,
+ 'lot_id': self.lot_producing_id and self.lot_producing_id.id,
}
ml.copy(default=default)
ml.with_context(bypass_reservation_update=True).write({
@@ -71,24 +63,30 @@ class MrpProductProduce(models.TransientModel):
if float_compare(quantity, 0, precision_rounding=self.product_uom_id.rounding) > 0:
self.env['stock.move.line'].create({
- 'move_id': self.subcontract_move_id.id,
- 'picking_id': self.subcontract_move_id.picking_id.id,
+ 'move_id': subcontract_move_id.id,
+ 'picking_id': subcontract_move_id.picking_id.id,
'product_id': self.product_id.id,
- 'location_id': self.subcontract_move_id.location_id.id,
- 'location_dest_id': self.subcontract_move_id.location_dest_id.id,
+ 'location_id': subcontract_move_id.location_id.id,
+ 'location_dest_id': subcontract_move_id.location_dest_id.id,
'product_uom_qty': 0,
'product_uom_id': self.product_uom_id.id,
'qty_done': quantity,
- 'lot_id': self.finished_lot_id and self.finished_lot_id.id,
- 'lot_name': self.finished_lot_id and self.finished_lot_id.name,
+ 'lot_id': self.lot_producing_id and self.lot_producing_id.id,
})
- if not self._get_todo(self.production_id):
- ml_reserved = self.subcontract_move_id.move_line_ids.filtered(lambda ml:
+ if not self._get_todo():
+ ml_reserved = subcontract_move_id.move_line_ids.filtered(lambda ml:
float_is_zero(ml.qty_done, precision_rounding=ml.product_uom_id.rounding) and
not float_is_zero(ml.product_uom_qty, precision_rounding=ml.product_uom_id.rounding))
ml_reserved.unlink()
- for ml in self.subcontract_move_id.move_line_ids:
+ for ml in subcontract_move_id.move_line_ids:
ml.product_uom_qty = ml.qty_done
- self.subcontract_move_id._recompute_state()
+ subcontract_move_id._recompute_state()
return res
+
+ def _get_todo(self):
+ """ This method will return remaining todo quantity of production. """
+ main_product_moves = self.move_finished_ids.filtered(lambda x: x.product_id.id == self.product_id.id)
+ todo_quantity = self.product_qty - sum(main_product_moves.mapped('quantity_done'))
+ todo_quantity = todo_quantity if (todo_quantity > 0) else 0
+ return todo_quantity