Files
odoo_source/addons/mrp/models/stock_rule.py
T
Arnold Moyaux c5b3f41fbd [IMP] mrp: new procurement group for MTO manufacture product
The purpose is to split up the supply chain in different group.
Currently if a user create a SO with a MTO manufacture product
that use MTO/buy components.
SO cancellation will:
- Cancel all the pickings including pickings between MO and suppliers.
- Log an activity on the MO but not cancel it.

We prefer cancel all transfers between SO and MO when the SO is cancel.
Cancel all the transfers between MO and suppliers when the MO is cancel.

Create a new procurement group when the _run_manufacture method is call
allows to achieve this behavior.
2018-08-13 15:38:34 +02:00

91 lines
4.7 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from dateutil.relativedelta import relativedelta
from odoo import api, fields, models, _
from odoo.exceptions import UserError
class StockRule(models.Model):
_inherit = 'stock.rule'
action = fields.Selection(selection_add=[('manufacture', 'Manufacture')])
def _get_message_dict(self):
message_dict = super(StockRule, self)._get_message_dict()
source, destination, operation = self._get_message_values()
manufacture_message = _('When products are needed in <b>%s</b>, <br/> a manufacturing order is created to fulfill the need.') % (destination)
if self.location_src_id:
manufacture_message += _(' <br/><br/> The components will be taken from <b>%s</b>.') % (source)
message_dict.update({
'manufacture': manufacture_message
})
return message_dict
@api.onchange('action')
def _onchange_action_operation(self):
domain = {'picking_type_id': []}
if self.action == 'manufacture':
domain = {'picking_type_id': [('code', '=', 'mrp_operation')]}
return {'domain': domain}
@api.multi
def _run_manufacture(self, product_id, product_qty, product_uom, location_id, name, origin, values):
Production = self.env['mrp.production']
ProductionSudo = Production.sudo().with_context(force_company=values['company_id'].id)
bom = self._get_matching_bom(product_id, values)
if not bom:
msg = _('There is no Bill of Material found for the product %s. Please define a Bill of Material for this product.') % (product_id.display_name,)
raise UserError(msg)
# create the MO as SUPERUSER because the current user may not have the rights to do it (mto product launched by a sale for example)
production = ProductionSudo.create(self._prepare_mo_vals(product_id, product_qty, product_uom, location_id, name, origin, values, bom))
origin_production = values.get('move_dest_ids') and values['move_dest_ids'][0].raw_material_production_id or False
orderpoint = values.get('orderpoint_id')
if orderpoint:
production.message_post_with_view('mail.message_origin_link',
values={'self': production, 'origin': orderpoint},
subtype_id=self.env.ref('mail.mt_note').id)
if origin_production:
production.message_post_with_view('mail.message_origin_link',
values={'self': production, 'origin': origin_production},
subtype_id=self.env.ref('mail.mt_note').id)
return True
@api.multi
def _get_matching_bom(self, product_id, values):
if values.get('bom_id', False):
return values['bom_id']
return self.env['mrp.bom'].with_context(
company_id=values['company_id'].id, force_company=values['company_id'].id
)._bom_find(product=product_id, picking_type=self.picking_type_id) # TDE FIXME: context bullshit
def _prepare_mo_vals(self, product_id, product_qty, product_uom, location_id, name, origin, values, bom):
return {
'origin': origin,
'product_id': product_id.id,
'product_qty': product_qty,
'product_uom_id': product_uom.id,
'location_src_id': self.location_src_id.id or self.picking_type_id.default_location_src_id.id or location_id.id,
'location_dest_id': location_id.id,
'bom_id': bom.id,
'date_planned_start': fields.Datetime.to_string(self._get_date_planned(product_id, values)),
'date_planned_finished': values['date_planned'],
'procurement_group_id': False,
'propagate': self.propagate,
'picking_type_id': self.picking_type_id.id or values['warehouse_id'].manu_type_id.id,
'company_id': values['company_id'].id,
'move_dest_ids': values.get('move_dest_ids') and [(4, x.id) for x in values['move_dest_ids']] or False,
}
def _get_date_planned(self, product_id, values):
format_date_planned = fields.Datetime.from_string(values['date_planned'])
date_planned = format_date_planned - relativedelta(days=product_id.produce_delay or 0.0)
date_planned = date_planned - relativedelta(days=values['company_id'].manufacturing_lead)
return date_planned
def _push_prepare_move_copy_values(self, move_to_copy, new_date):
new_move_vals = super(StockRule, self)._push_prepare_move_copy_values(move_to_copy, new_date)
new_move_vals['production_id'] = False
return new_move_vals