[ADD] Added module with pre-commit changes only.

This commit is contained in:
Chandresh Thakkar
2020-04-03 16:51:57 +05:30
parent 2a00e31fd3
commit 6c2f6fe827
17 changed files with 885 additions and 647 deletions

View File

@@ -7,11 +7,10 @@
"planification.",
"version": "12.0.1.0.0",
"development_status": "Mature",
"maintainers": ['lreficent'],
"maintainers": ["lreficent"],
"category": "Manufacturing",
"website": "https://github.com/OCA/manufacture",
"author": "Eficent,"
"Odoo Community Association (OCA)",
"author": "Eficent," "Odoo Community Association (OCA)",
"license": "AGPL-3",
"application": False,
"installable": True,

View File

@@ -1,9 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2017 Eficent Business and IT Consulting Services S.L.
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo noupdate="1">
<record id="seq_mrp_production_request" model="ir.sequence">
<field name="name">Manufacturing Request</field>
<field name="code">mrp.production.request</field>
@@ -11,5 +9,4 @@
<field name="padding">5</field>
<field name="company_id" eval="False" />
</record>
</odoo>

View File

@@ -9,7 +9,10 @@ class MrpProduction(models.Model):
mrp_production_request_id = fields.Many2one(
comodel_name="mrp.production.request",
string="Manufacturing Request", copy=False, readonly=True)
string="Manufacturing Request",
copy=False,
readonly=True,
)
def _generate_finished_moves(self):
"""`move_dest_ids` is a One2many fields in mrp.production, thus we
@@ -21,7 +24,7 @@ class MrpProduction(models.Model):
move = super()._generate_finished_moves()
request = self.mrp_production_request_id
if request and request.move_dest_ids:
move.write({
'move_dest_ids': [(4, x.id) for x in request.move_dest_ids],
})
move.write(
{"move_dest_ids": [(4, x.id) for x in request.move_dest_ids],}
)
return move

View File

@@ -1,10 +1,11 @@
# Copyright 2017-19 Eficent Business and IT Consulting Services S.L.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models, _
import odoo.addons.decimal_precision as dp
from odoo import _, api, fields, models
from odoo.exceptions import UserError
import odoo.addons.decimal_precision as dp
class MrpProductionRequest(models.Model):
_name = "mrp.production.request"
@@ -14,153 +15,239 @@ class MrpProductionRequest(models.Model):
@api.model
def _company_get(self):
company_id = self.env['res.company']._company_default_get()
return self.env['res.company'].browse(company_id.id)
company_id = self.env["res.company"]._company_default_get()
return self.env["res.company"].browse(company_id.id)
@api.model
def _get_default_requested_by(self):
return self.env.user
name = fields.Char(
default="/", required=True,
readonly=True, states={'draft': [('readonly', False)]})
default="/",
required=True,
readonly=True,
states={"draft": [("readonly", False)]},
)
origin = fields.Char(
string='Source Document',
readonly=True, states={'draft': [('readonly', False)]})
string="Source Document", readonly=True, states={"draft": [("readonly", False)]}
)
requested_by = fields.Many2one(
comodel_name='res.users', string='Requested by',
comodel_name="res.users",
string="Requested by",
default=lambda self: self._get_default_requested_by(),
required=True, track_visibility='onchange',
readonly=True, states={'draft': [('readonly', False)]})
required=True,
track_visibility="onchange",
readonly=True,
states={"draft": [("readonly", False)]},
)
assigned_to = fields.Many2one(
comodel_name='res.users', string='Approver',
track_visibility='onchange',
readonly=True, states={'draft': [('readonly', False)]},
domain=lambda self: [('groups_id', 'in', self.env.ref(
'mrp_production_request.'
'group_mrp_production_request_manager').id)])
description = fields.Text('Description')
comodel_name="res.users",
string="Approver",
track_visibility="onchange",
readonly=True,
states={"draft": [("readonly", False)]},
domain=lambda self: [
(
"groups_id",
"in",
self.env.ref(
"mrp_production_request." "group_mrp_production_request_manager"
).id,
)
],
)
description = fields.Text("Description")
date_planned_start = fields.Datetime(
'Deadline Start', copy=False, default=fields.Datetime.now,
index=True, required=True,
states={'confirmed': [('readonly', False)]}, oldname="date_planned")
date_planned_finished = fields.Datetime(
'Deadline End', copy=False, default=fields.Datetime.now,
"Deadline Start",
copy=False,
default=fields.Datetime.now,
index=True,
states={'confirmed': [('readonly', False)]})
required=True,
states={"confirmed": [("readonly", False)]},
oldname="date_planned",
)
date_planned_finished = fields.Datetime(
"Deadline End",
copy=False,
default=fields.Datetime.now,
index=True,
states={"confirmed": [("readonly", False)]},
)
company_id = fields.Many2one(
comodel_name='res.company', string='Company',
required=True, default=lambda self: self._company_get())
comodel_name="res.company",
string="Company",
required=True,
default=lambda self: self._company_get(),
)
mrp_production_ids = fields.One2many(
comodel_name="mrp.production", string="Manufacturing Orders",
inverse_name="mrp_production_request_id", readonly=True)
comodel_name="mrp.production",
string="Manufacturing Orders",
inverse_name="mrp_production_request_id",
readonly=True,
)
mrp_production_count = fields.Integer(
compute="_compute_mrp_production_count",
string="MO's Count",
compute="_compute_mrp_production_count", string="MO's Count",
)
state = fields.Selection(
selection=[("draft", "Draft"),
selection=[
("draft", "Draft"),
("to_approve", "To Be Approved"),
("approved", "Approved"),
("done", "Done"),
("cancel", "Cancelled")],
index=True, track_visibility='onchange',
required=True, copy=False, default='draft')
procurement_group_id = fields.Many2one(
string='Procurement Group',
comodel_name='procurement.group',
copy=False)
propagate = fields.Boolean(
'Propagate cancel and split',
help='If checked, when the previous move of the move '
'(which was generated by a next procurement) is cancelled '
'or split, the move generated by this move will too')
product_id = fields.Many2one(
comodel_name="product.product", string="Product", required=True,
domain=[('type', 'in', ['product', 'consu'])],
("cancel", "Cancelled"),
],
index=True,
track_visibility="onchange",
readonly=True, states={'draft': [('readonly', False)]})
required=True,
copy=False,
default="draft",
)
procurement_group_id = fields.Many2one(
string="Procurement Group", comodel_name="procurement.group", copy=False
)
propagate = fields.Boolean(
"Propagate cancel and split",
help="If checked, when the previous move of the move "
"(which was generated by a next procurement) is cancelled "
"or split, the move generated by this move will too",
)
product_id = fields.Many2one(
comodel_name="product.product",
string="Product",
required=True,
domain=[("type", "in", ["product", "consu"])],
track_visibility="onchange",
readonly=True,
states={"draft": [("readonly", False)]},
)
product_tmpl_id = fields.Many2one(
comodel_name='product.template', string='Product Template',
related='product_id.product_tmpl_id')
comodel_name="product.template",
string="Product Template",
related="product_id.product_tmpl_id",
)
product_qty = fields.Float(
string="Required Quantity", required=True, track_visibility='onchange',
digits=dp.get_precision('Product Unit of Measure'), default=1.0,
readonly=True, states={'draft': [('readonly', False)]})
string="Required Quantity",
required=True,
track_visibility="onchange",
digits=dp.get_precision("Product Unit of Measure"),
default=1.0,
readonly=True,
states={"draft": [("readonly", False)]},
)
product_uom_id = fields.Many2one(
comodel_name='uom.uom', string='Unit of Measure',
readonly=True, states={'draft': [('readonly', False)]},
domain="[('category_id', '=', category_uom_id)]")
comodel_name="uom.uom",
string="Unit of Measure",
readonly=True,
states={"draft": [("readonly", False)]},
domain="[('category_id', '=', category_uom_id)]",
)
category_uom_id = fields.Many2one(related="product_uom_id.category_id")
manufactured_qty = fields.Float(
string="Quantity in Manufacturing Orders",
compute="_compute_manufactured_qty", store=True, readonly=True,
digits=dp.get_precision('Product Unit of Measure'),
help="Sum of the quantities in Manufacturing Orders (in any state).")
done_qty = fields.Float(
string="Quantity Done", store=True, readonly=True,
compute="_compute_manufactured_qty",
digits=dp.get_precision('Product Unit of Measure'),
help="Sum of the quantities in all done Manufacturing Orders.")
store=True,
readonly=True,
digits=dp.get_precision("Product Unit of Measure"),
help="Sum of the quantities in Manufacturing Orders (in any state).",
)
done_qty = fields.Float(
string="Quantity Done",
store=True,
readonly=True,
compute="_compute_manufactured_qty",
digits=dp.get_precision("Product Unit of Measure"),
help="Sum of the quantities in all done Manufacturing Orders.",
)
pending_qty = fields.Float(
string="Pending Quantity", compute="_compute_manufactured_qty",
store=True, digits=dp.get_precision('Product Unit of Measure'),
string="Pending Quantity",
compute="_compute_manufactured_qty",
store=True,
digits=dp.get_precision("Product Unit of Measure"),
readonly=True,
help="Quantity pending to add to Manufacturing Orders "
"to fulfill the Manufacturing Request requirement.")
"to fulfill the Manufacturing Request requirement.",
)
bom_id = fields.Many2one(
comodel_name="mrp.bom", string="Bill of Materials", required=True,
readonly=True, states={'draft': [('readonly', False)]})
comodel_name="mrp.bom",
string="Bill of Materials",
required=True,
readonly=True,
states={"draft": [("readonly", False)]},
)
routing_id = fields.Many2one(
comodel_name='mrp.routing', string='Routing',
on_delete='setnull', readonly=True,
states={'draft': [('readonly', False)]},
comodel_name="mrp.routing",
string="Routing",
on_delete="setnull",
readonly=True,
states={"draft": [("readonly", False)]},
help="The list of operations (list of work centers) to produce "
"the finished product. The routing is mainly used to compute "
"work center costs during operations and to plan future loads "
"on work centers based on production plannification.")
"on work centers based on production plannification.",
)
location_src_id = fields.Many2one(
comodel_name='stock.location', string='Raw Materials Location',
default=lambda self: self.env['stock.location'].browse(
self.env['mrp.production']._get_default_location_src_id()),
required=True, readonly=True, states={'draft': [('readonly', False)]})
comodel_name="stock.location",
string="Raw Materials Location",
default=lambda self: self.env["stock.location"].browse(
self.env["mrp.production"]._get_default_location_src_id()
),
required=True,
readonly=True,
states={"draft": [("readonly", False)]},
)
location_dest_id = fields.Many2one(
comodel_name='stock.location', string='Finished Products Location',
default=lambda self: self.env['stock.location'].browse(
self.env['mrp.production']._get_default_location_dest_id()),
required=True, readonly=True, states={'draft': [('readonly', False)]})
comodel_name="stock.location",
string="Finished Products Location",
default=lambda self: self.env["stock.location"].browse(
self.env["mrp.production"]._get_default_location_dest_id()
),
required=True,
readonly=True,
states={"draft": [("readonly", False)]},
)
picking_type_id = fields.Many2one(
comodel_name='stock.picking.type', string='Picking Type',
default=lambda self: self.env['stock.picking.type'].browse(
self.env['mrp.production']._get_default_picking_type()),
required=True, readonly=True, states={'draft': [('readonly', False)]})
comodel_name="stock.picking.type",
string="Picking Type",
default=lambda self: self.env["stock.picking.type"].browse(
self.env["mrp.production"]._get_default_picking_type()
),
required=True,
readonly=True,
states={"draft": [("readonly", False)]},
)
move_dest_ids = fields.One2many(
comodel_name='stock.move',
inverse_name='created_mrp_production_request_id',
string="Stock Movements of Produced Goods")
comodel_name="stock.move",
inverse_name="created_mrp_production_request_id",
string="Stock Movements of Produced Goods",
)
orderpoint_id = fields.Many2one(
comodel_name='stock.warehouse.orderpoint',
string='Orderpoint')
comodel_name="stock.warehouse.orderpoint", string="Orderpoint"
)
_sql_constraints = [
('name_uniq', 'unique(name, company_id)',
'Reference must be unique per Company!'),
(
"name_uniq",
"unique(name, company_id)",
"Reference must be unique per Company!",
),
]
@api.model
def _get_mo_valid_states(self):
return ['planned', 'confirmed', 'progress', 'done']
return ["planned", "confirmed", "progress", "done"]
@api.multi
@api.depends('mrp_production_ids', 'mrp_production_ids.state', 'state')
@api.depends("mrp_production_ids", "mrp_production_ids.state", "state")
def _compute_manufactured_qty(self):
valid_states = self._get_mo_valid_states()
for req in self:
done_mo = req.mrp_production_ids.filtered(
lambda mo: mo.state in 'done').mapped('product_qty')
lambda mo: mo.state in "done"
).mapped("product_qty")
req.done_qty = sum(done_mo)
valid_mo = req.mrp_production_ids.filtered(
lambda mo: mo.state in valid_states).mapped('product_qty')
lambda mo: mo.state in valid_states
).mapped("product_qty")
req.manufactured_qty = sum(valid_mo)
req.pending_qty = max(req.product_qty - req.manufactured_qty, 0.0)
@@ -169,25 +256,29 @@ class MrpProductionRequest(models.Model):
for rec in self:
rec.mrp_production_count = len(rec.mrp_production_ids)
@api.onchange('product_id')
@api.onchange("product_id")
def _onchange_product_id(self):
self.product_uom_id = self.product_id.uom_id
self.bom_id = self.env['mrp.bom']._bom_find(
product=self.product_id, company_id=self.company_id.id,
picking_type=self.picking_type_id)
self.bom_id = self.env["mrp.bom"]._bom_find(
product=self.product_id,
company_id=self.company_id.id,
picking_type=self.picking_type_id,
)
@api.multi
def _subscribe_assigned_user(self, vals):
self.ensure_one()
if vals.get('assigned_to'):
if vals.get("assigned_to"):
self.message_subscribe(
partner_ids=self.assigned_to.mapped('partner_id').ids)
partner_ids=self.assigned_to.mapped("partner_id").ids
)
@api.model
def _create_sequence(self, vals):
if not vals.get('name') or vals.get('name') == '/':
vals['name'] = self.env['ir.sequence'].next_by_code(
'mrp.production.request') or '/'
if not vals.get("name") or vals.get("name") == "/":
vals["name"] = (
self.env["ir.sequence"].next_by_code("mrp.production.request") or "/"
)
return vals
@api.model
@@ -208,59 +299,70 @@ class MrpProductionRequest(models.Model):
@api.multi
def button_to_approve(self):
self.write({'state': 'to_approve'})
self.write({"state": "to_approve"})
return True
@api.multi
def button_approved(self):
self.write({'state': 'approved'})
self.write({"state": "approved"})
return True
@api.multi
def button_done(self):
self.write({'state': 'done'})
self.write({"state": "done"})
return True
@api.multi
def _check_reset_allowed(self):
if any([s in self._get_mo_valid_states() for s in self.mapped(
'mrp_production_ids.state')]):
if any(
[
s in self._get_mo_valid_states()
for s in self.mapped("mrp_production_ids.state")
]
):
raise UserError(
_("You cannot reset a manufacturing request if the related "
"manufacturing orders are not cancelled."))
_(
"You cannot reset a manufacturing request if the related "
"manufacturing orders are not cancelled."
)
)
@api.multi
def button_draft(self):
self._check_reset_allowed()
self.write({'state': 'draft'})
self.write({"state": "draft"})
return True
@api.multi
def _check_cancel_allowed(self):
if any([s == 'done' for s in self.mapped('state')]):
if any([s == "done" for s in self.mapped("state")]):
raise UserError(
_('You cannot reject a manufacturing request related to '
'done procurement orders.'))
_(
"You cannot reject a manufacturing request related to "
"done procurement orders."
)
)
@api.multi
def button_cancel(self):
self._check_cancel_allowed()
self.write({'state': 'cancel'})
self.mapped('move_dest_ids').filtered(
lambda r: r.state != 'cancel')._action_cancel()
self.write({"state": "cancel"})
self.mapped("move_dest_ids").filtered(
lambda r: r.state != "cancel"
)._action_cancel()
return True
@api.multi
def action_view_mrp_productions(self):
action = self.env.ref('mrp.mrp_production_action')
action = self.env.ref("mrp.mrp_production_action")
result = action.read()[0]
result['context'] = {}
mos = self.mapped('mrp_production_ids')
result["context"] = {}
mos = self.mapped("mrp_production_ids")
# choose the view_mode accordingly
if len(mos) != 1:
result['domain'] = [('id', 'in', mos.ids)]
result["domain"] = [("id", "in", mos.ids)]
elif len(mos) == 1:
form = self.env.ref('mrp.mrp_production_form_view', False)
result['views'] = [(form and form.id or False, 'form')]
result['res_id'] = mos[0].id
form = self.env.ref("mrp.mrp_production_form_view", False)
result["views"] = [(form and form.id or False, "form")]
result["res_id"] = mos[0].id
return result

View File

@@ -8,7 +8,7 @@ class ProductTemplate(models.Model):
_inherit = "product.template"
mrp_production_request = fields.Boolean(
string='Manufacturing Request',
string="Manufacturing Request",
help="Check this box to generate manufacturing request instead of "
"generating manufacturing orders from procurement.",
)

View File

@@ -8,15 +8,13 @@ class StockMove(models.Model):
_inherit = "stock.move"
created_mrp_production_request_id = fields.Many2one(
comodel_name='mrp.production.request',
string='Created Production Request',
comodel_name="mrp.production.request", string="Created Production Request",
)
@api.model
def create(self, vals):
if 'production_id' in vals:
production = self.env['mrp.production'].browse(
vals['production_id'])
if "production_id" in vals:
production = self.env["mrp.production"].browse(vals["production_id"])
if production.mrp_production_request_id:
vals['propagate'] = False
vals["propagate"] = False
return super().create(vals)

View File

@@ -1,7 +1,7 @@
# Copyright 2018-19 Eficent Business and IT Consulting Services S.L.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, models, _
from odoo import _, api, models
from odoo.exceptions import UserError
@@ -10,74 +10,96 @@ class StockRule(models.Model):
@api.multi
def _prepare_mrp_production_request(
self, product_id, product_qty, product_uom, location_id, name,
origin, values, bom):
self,
product_id,
product_qty,
product_uom,
location_id,
name,
origin,
values,
bom,
):
self.ensure_one()
data = self._prepare_mo_vals(
product_id, product_qty, product_uom, location_id, name,
origin, values, bom)
data['state'] = 'to_approve'
orderpoint = values.get('orderpoint_id')
product_id, product_qty, product_uom, location_id, name, origin, values, bom
)
data["state"] = "to_approve"
orderpoint = values.get("orderpoint_id")
if orderpoint:
data['orderpoint_id'] = orderpoint.id
procurement_group = values.get('group_id')
data["orderpoint_id"] = orderpoint.id
procurement_group = values.get("group_id")
if procurement_group:
data['procurement_group_id'] = procurement_group.id
data["procurement_group_id"] = procurement_group.id
return data
@api.multi
def _need_production_request(self, product_id):
return self.action == 'manufacture' \
and product_id.mrp_production_request
return self.action == "manufacture" and product_id.mrp_production_request
@api.multi
def _run_production_request(self, product_id, product_qty, product_uom,
location_id, name, origin, values):
def _run_production_request(
self, product_id, product_qty, product_uom, location_id, name, origin, values
):
"""Trying to handle this as much similar as possible to Odoo
production orders. See `_run_manufacture` in Odoo standard."""
request_obj = self.env['mrp.production.request']
request_obj = self.env["mrp.production.request"]
request_obj_sudo = request_obj.sudo().with_context(
force_company=values['company_id'].id)
force_company=values["company_id"].id
)
bom = self._get_matching_bom(product_id, values)
if not bom:
raise UserError(_(
'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(
_(
"There is no Bill of Material found for the product %s. "
"Please define a Bill of Material for this product."
)
% (product_id.display_name,)
)
# create the MR as SUPERUSER because the current user may not
# have the rights to do it (mto product launched by a sale for example)
request = request_obj_sudo.create(
self._prepare_mrp_production_request(
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')
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:
request.message_post_with_view(
'mail.message_origin_link',
values={'self': request,
'origin': orderpoint},
subtype_id=self.env.ref('mail.mt_note').id,
"mail.message_origin_link",
values={"self": request, "origin": orderpoint},
subtype_id=self.env.ref("mail.mt_note").id,
)
if origin_production:
request.message_post_with_view(
'mail.message_origin_link',
values={'self': request,
'origin': origin_production},
subtype_id=self.env.ref('mail.mt_note').id,
"mail.message_origin_link",
values={"self": request, "origin": origin_production},
subtype_id=self.env.ref("mail.mt_note").id,
)
return True
@api.multi
def _run_manufacture(self, product_id, product_qty, product_uom,
location_id, name, origin, values):
def _run_manufacture(
self, product_id, product_qty, product_uom, location_id, name, origin, values
):
if self._need_production_request(product_id):
return self._run_production_request(
product_id, product_qty, product_uom,
location_id, name, origin, values)
product_id, product_qty, product_uom, location_id, name, origin, values
)
return super()._run_manufacture(
product_id, product_qty, product_uom, location_id, name,
origin, values)
product_id, product_qty, product_uom, location_id, name, origin, values
)

View File

@@ -9,11 +9,14 @@ class Orderpoint(models.Model):
def _quantity_in_progress(self):
res = super()._quantity_in_progress()
mrp_requests = self.env['mrp.production.request'].search([
('state', 'not in', ('done', 'cancel')),
('orderpoint_id', 'in', self.ids),
])
mrp_requests = self.env["mrp.production.request"].search(
[
("state", "not in", ("done", "cancel")),
("orderpoint_id", "in", self.ids),
]
)
for rec in mrp_requests:
res[rec.orderpoint_id.id] += rec.product_uom_id._compute_quantity(
rec.pending_qty, rec.orderpoint_id.product_uom, round=False)
rec.pending_qty, rec.orderpoint_id.product_uom, round=False
)
return res

View File

@@ -2,32 +2,31 @@
<!-- Copyright 2017 Eficent Business and IT Consulting Services S.L.
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl-3.0) -->
<odoo>
<data noupdate="0">
<record model="ir.module.category" id="module_category_mrp_production_request">
<field name="name">Manufacturing Request</field>
<field name="parent_id" ref="base.module_category_manufacturing" />
<field name="sequence">20</field>
</record>
<record id="group_mrp_production_request_user" model="res.groups">
<field name="name">User</field>
<field name="implied_ids" eval="[(4, ref('base.group_user'))]" />
<field name="category_id" ref="module_category_mrp_production_request" />
</record>
<record id="group_mrp_production_request_manager" model="res.groups">
<field name="name">Manager</field>
<field name="implied_ids"
eval="[(4, ref('mrp_production_request.group_mrp_production_request_user'))]"/>
<field name="users" eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"/>
<field
name="implied_ids"
eval="[(4, ref('mrp_production_request.group_mrp_production_request_user'))]"
/>
<field
name="users"
eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"
/>
<field name="category_id" ref="module_category_mrp_production_request" />
</record>
</data>
<data noupdate="0">
<record model="ir.rule" id="mrp_production_request_comp_rule">
<field name="name">Manufacturing Request multi-company</field>
<field name="model_id" ref="model_mrp_production_request" />
@@ -35,11 +34,13 @@
<field name="domain_force">['|',('company_id','=',False),
('company_id','child_of',[user.company_id.id])]</field>
</record>
<record id="mrp_production_request_followers_rule" model="ir.rule">
<field name="name">Follow Manufacturing Request</field>
<field name="model_id" ref="model_mrp_production_request" />
<field name="groups" eval="[(6,0, [ref('group_mrp_production_request_user')])]"/>
<field
name="groups"
eval="[(6,0, [ref('group_mrp_production_request_user')])]"
/>
<field name="perm_read" eval="True" />
<field name="perm_write" eval="False" />
<field name="perm_create" eval="False" />
@@ -47,27 +48,30 @@
<field name="domain_force">['|',('requested_by','=',user.id),
('message_partner_ids', 'in', [user.partner_id.id])]</field>
</record>
<record id="mrp_production_request_rule" model="ir.rule">
<field name="name">Manufacturing Request User</field>
<field name="model_id" ref="model_mrp_production_request" />
<field name="groups" eval="[(6,0, [ref('group_mrp_production_request_user')])]"/>
<field
name="groups"
eval="[(6,0, [ref('group_mrp_production_request_user')])]"
/>
<field name="perm_read" eval="True" />
<field name="perm_write" eval="True" />
<field name="perm_create" eval="True" />
<field name="perm_unlink" eval="True" />
<field name="domain_force">[('requested_by','=',user.id)]</field>
</record>
<record id="mpr_production_request_line_manager_rule" model="ir.rule">
<field name="name">Manufacturing Request Line Manager</field>
<field name="model_id" ref="model_mrp_production_request" />
<field name="groups" eval="[(6,0, [ref('group_mrp_production_request_manager')])]"/>
<field
name="groups"
eval="[(6,0, [ref('group_mrp_production_request_manager')])]"
/>
<field name="perm_read" eval="True" />
<field name="perm_write" eval="True" />
<field name="perm_create" eval="True" />
<field name="perm_unlink" eval="True" />
</record>
</data>
</odoo>

View File

@@ -1,101 +1,119 @@
# Copyright 2017-18 Eficent Business and IT Consulting Services S.L.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo.tests.common import TransactionCase
from odoo import fields
from odoo.exceptions import UserError
from odoo.tests.common import TransactionCase
class TestMrpProductionRequest(TransactionCase):
def setUp(self, *args, **kwargs):
super().setUp(*args, **kwargs)
self.production_model = self.env['mrp.production']
self.request_model = self.env['mrp.production.request']
self.wiz_model = self.env['mrp.production.request.create.mo']
self.bom_model = self.env['mrp.bom']
self.group_model = self.env['procurement.group']
self.product_model = self.env['product.product']
self.bom_model = self.env['mrp.bom']
self.boml_model = self.env['mrp.bom.line']
self.production_model = self.env["mrp.production"]
self.request_model = self.env["mrp.production.request"]
self.wiz_model = self.env["mrp.production.request.create.mo"]
self.bom_model = self.env["mrp.bom"]
self.group_model = self.env["procurement.group"]
self.product_model = self.env["product.product"]
self.bom_model = self.env["mrp.bom"]
self.boml_model = self.env["mrp.bom.line"]
self.warehouse = self.env.ref('stock.warehouse0')
self.stock_loc = self.env.ref('stock.stock_location_stock')
route_manuf = self.env.ref('mrp.route_warehouse0_manufacture')
self.warehouse = self.env.ref("stock.warehouse0")
self.stock_loc = self.env.ref("stock.stock_location_stock")
route_manuf = self.env.ref("mrp.route_warehouse0_manufacture")
# Prepare Products:
self.product = self.env.ref('product.product_product_3')
self.product = self.env.ref("product.product_product_3")
self.product.mrp_production_request = True
self.product.route_ids = [(4, route_manuf.id, 0)]
self.product_no_bom = self.product_model.create({
'name': 'Test Product without BoM',
'mrp_production_request': True,
'route_ids': [(6, 0, route_manuf.ids)],
})
self.product_orderpoint = self.product_model.create({
'name': 'Test Product for orderpoint',
'mrp_production_request': True,
'route_ids': [(6, 0, route_manuf.ids)],
})
product_component = self.product_model.create({
'name': 'Test component',
'mrp_production_request': True,
'route_ids': [(6, 0, route_manuf.ids)],
})
self.product_no_bom = self.product_model.create(
{
"name": "Test Product without BoM",
"mrp_production_request": True,
"route_ids": [(6, 0, route_manuf.ids)],
}
)
self.product_orderpoint = self.product_model.create(
{
"name": "Test Product for orderpoint",
"mrp_production_request": True,
"route_ids": [(6, 0, route_manuf.ids)],
}
)
product_component = self.product_model.create(
{
"name": "Test component",
"mrp_production_request": True,
"route_ids": [(6, 0, route_manuf.ids)],
}
)
# Create Bill of Materials:
self.test_bom_1 = self.bom_model.create({
'product_id': self.product_orderpoint.id,
'product_tmpl_id': self.product_orderpoint.product_tmpl_id.id,
'product_uom_id': self.product_orderpoint.uom_id.id,
'product_qty': 1.0,
'type': 'normal',
})
self.boml_model.create({
'bom_id': self.test_bom_1.id,
'product_id': product_component.id,
'product_qty': 1.0,
})
self.test_bom_1 = self.bom_model.create(
{
"product_id": self.product_orderpoint.id,
"product_tmpl_id": self.product_orderpoint.product_tmpl_id.id,
"product_uom_id": self.product_orderpoint.uom_id.id,
"product_qty": 1.0,
"type": "normal",
}
)
self.boml_model.create(
{
"bom_id": self.test_bom_1.id,
"product_id": product_component.id,
"product_qty": 1.0,
}
)
# Create Orderpoint:
self.orderpoint = self.env['stock.warehouse.orderpoint'].create({
'warehouse_id': self.warehouse.id,
'location_id': self.warehouse.lot_stock_id.id,
'product_id': self.product_orderpoint.id,
'product_min_qty': 10.0,
'product_max_qty': 50.0,
'product_uom': self.product_orderpoint.uom_id.id,
})
self.orderpoint = self.env["stock.warehouse.orderpoint"].create(
{
"warehouse_id": self.warehouse.id,
"location_id": self.warehouse.lot_stock_id.id,
"product_id": self.product_orderpoint.id,
"product_min_qty": 10.0,
"product_max_qty": 50.0,
"product_uom": self.product_orderpoint.uom_id.id,
}
)
# Create Procurement Group:
self.test_group = self.group_model.create({
'name': 'TEST',
})
self.test_group = self.group_model.create({"name": "TEST",})
# Create User:
self.test_user = self.env['res.users'].create({
'name': 'John',
'login': 'test',
})
self.test_user = self.env["res.users"].create(
{"name": "John", "login": "test",}
)
def procure(self, group, product, qty=4.0,):
def procure(
self, group, product, qty=4.0,
):
values = {
'date_planned': fields.Datetime.now(),
'group_id': group,
"date_planned": fields.Datetime.now(),
"group_id": group,
}
self.group_model.run(
product, qty, product.uom_id, self.stock_loc,
group.name, group.name, values,
product,
qty,
product.uom_id,
self.stock_loc,
group.name,
group.name,
values,
)
return True
def test_01_manufacture_request(self):
"""Tests manufacture request workflow."""
self.procure(self.test_group, self.product)
request = self.request_model.search([
('product_id', '=', self.product.id),
('procurement_group_id', '=', self.test_group.id),
])
request = self.request_model.search(
[
("product_id", "=", self.product.id),
("procurement_group_id", "=", self.test_group.id),
]
)
self.assertEqual(len(request), 1)
request.button_to_approve()
request.button_draft()
@@ -103,13 +121,14 @@ class TestMrpProductionRequest(TransactionCase):
request.button_approved()
self.assertEqual(request.pending_qty, 4.0)
wiz = self.wiz_model.with_context(
active_ids=request.ids,
active_model="mrp.production.request").create({})
active_ids=request.ids, active_model="mrp.production.request"
).create({})
wiz.compute_product_line_ids()
wiz.mo_qty = 4.0
wiz.create_mo()
mo = self.production_model.search([
('mrp_production_request_id', '=', request.id)])
mo = self.production_model.search(
[("mrp_production_request_id", "=", request.id)]
)
self.assertTrue(mo, "No MO created.")
self.assertEqual(request.pending_qty, 0.0)
request.button_done()
@@ -117,39 +136,42 @@ class TestMrpProductionRequest(TransactionCase):
def test_02_assignation(self):
"""Tests assignation of manufacturing requests."""
randon_bom_id = self.bom_model.search([], limit=1).id
request = self.request_model.create({
'assigned_to': self.test_user.id,
'product_id': self.product.id,
'product_qty': 5.0,
'bom_id': randon_bom_id,
})
request = self.request_model.create(
{
"assigned_to": self.test_user.id,
"product_id": self.product.id,
"product_qty": 5.0,
"bom_id": randon_bom_id,
}
)
request._onchange_product_id()
self.assertEqual(
request.bom_id.product_tmpl_id, self.product.product_tmpl_id,
"Wrong Bill of Materials.")
request.write({
'assigned_to': self.uid,
})
self.assertTrue(request.message_follower_ids,
"Followers not added correctly.")
request.bom_id.product_tmpl_id,
self.product.product_tmpl_id,
"Wrong Bill of Materials.",
)
request.write(
{"assigned_to": self.uid,}
)
self.assertTrue(request.message_follower_ids, "Followers not added correctly.")
def test_03_substract_qty_from_orderpoint(self):
"""Quantity in Manufacturing Requests should be considered by
orderpoints."""
request = self.request_model.search([
('product_id', '=', self.product_orderpoint.id),
])
request = self.request_model.search(
[("product_id", "=", self.product_orderpoint.id),]
)
self.assertFalse(request)
self.env['procurement.group'].run_scheduler()
request = self.request_model.search([
('product_id', '=', self.product_orderpoint.id),
])
self.env["procurement.group"].run_scheduler()
request = self.request_model.search(
[("product_id", "=", self.product_orderpoint.id),]
)
self.assertEqual(len(request), 1)
# Running again the scheduler should not generate a new MR.
self.env['procurement.group'].run_scheduler()
request = self.request_model.search([
('product_id', '=', self.product_orderpoint.id),
])
self.env["procurement.group"].run_scheduler()
request = self.request_model.search(
[("product_id", "=", self.product_orderpoint.id),]
)
self.assertEqual(len(request), 1)
def test_04_raise_errors(self):

View File

@@ -2,60 +2,94 @@
<!-- Copyright 2017-18 Eficent Business and IT Consulting Services S.L.
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl-3.0) -->
<odoo>
<record model="ir.ui.view" id="view_mrp_production_request_form">
<field name="name">mrp.production.request.form</field>
<field name="model">mrp.production.request</field>
<field name="arch" type="xml">
<form string="Manufacturing Request">
<header>
<button name="button_draft"
<button
name="button_draft"
states="to_approve,approved,cancel,done"
string="Reset"
type="object"
groups="mrp_production_request.group_mrp_production_request_manager"/>
<button name="button_to_approve" states="draft"
string="Request approval" type="object"
class="oe_highlight"/>
<button name="button_approved" states="to_approve"
string="Approve" type="object" class="oe_highlight"
groups="mrp_production_request.group_mrp_production_request_manager"/>
<button name="%(mrp_production_request_create_mo_action)d"
groups="mrp_production_request.group_mrp_production_request_manager"
/>
<button
name="button_to_approve"
states="draft"
string="Request approval"
type="object"
class="oe_highlight"
/>
<button
name="button_approved"
states="to_approve"
string="Approve"
type="object"
class="oe_highlight"
groups="mrp_production_request.group_mrp_production_request_manager"
/>
<button
name="%(mrp_production_request_create_mo_action)d"
states="approved"
string="Create Manufacturing Order" type="action"/>
<button name="button_done" states="approved"
string="Done" type="object" class="oe_highlight"
groups="mrp_production_request.group_mrp_production_request_manager"/>
<button name="button_cancel" states="to_approve,approved"
string="Reject" type="object"
groups="mrp_production_request.group_mrp_production_request_manager"/>
<field name="state" widget="statusbar"
statusbar_visible="draft,approved,done"/>
string="Create Manufacturing Order"
type="action"
/>
<button
name="button_done"
states="approved"
string="Done"
type="object"
class="oe_highlight"
groups="mrp_production_request.group_mrp_production_request_manager"
/>
<button
name="button_cancel"
states="to_approve,approved"
string="Reject"
type="object"
groups="mrp_production_request.group_mrp_production_request_manager"
/>
<field
name="state"
widget="statusbar"
statusbar_visible="draft,approved,done"
/>
</header>
<sheet>
<div class="oe_button_box" name="button_box">
<button type="object" name="action_view_mrp_productions"
<button
type="object"
name="action_view_mrp_productions"
class="oe_stat_button"
icon="fa-wrench"
attrs="{'invisible': [('mrp_production_count', '=', 0)]}">
<field name="mrp_production_count" widget="statinfo"
string="MOs"/>
attrs="{'invisible': [('mrp_production_count', '=', 0)]}"
>
<field
name="mrp_production_count"
widget="statinfo"
string="MOs"
/>
</button>
</div>
<label for="name" string="Manufacturing Request" />
<h1>
<field name="name" />
</h1>
<group name="request">
<group>
<field name="product_id"
domain="[('bom_ids','!=',False),('bom_ids.type','!=','phantom')]"/>
<field
name="product_id"
domain="[('bom_ids','!=',False),('bom_ids.type','!=','phantom')]"
/>
<field name="product_tmpl_id" invisible="1" />
<field name="bom_id"
<field
name="bom_id"
domain="['&amp;', '|', ('product_id','=',product_id),
'&amp;', ('product_tmpl_id.product_variant_ids','=',product_id),
('product_id','=',False), ('type', '=', 'normal')]"/>
('product_id','=',False), ('type', '=', 'normal')]"
/>
</group>
<group>
<field name="product_qty" />
@@ -86,7 +120,6 @@
<field name="location_src_id" />
<field name="location_dest_id" />
<field name="picking_type_id" />
</group>
<group>
<field name="origin" />
@@ -103,28 +136,32 @@
</form>
</field>
</record>
<record model="ir.ui.view" id="view_mrp_production_request_tree">
<field name="name">mrp.production.request.tree</field>
<field name="model">mrp.production.request</field>
<field name="arch" type="xml">
<tree decoration-info="state in ('draft','to_approve')"
<tree
decoration-info="state in ('draft','to_approve')"
decoration-muted="state in ('cancel')"
string="Manufacturing Requests">
string="Manufacturing Requests"
>
<field name="name" />
<field name="product_id" />
<field name="requested_by" />
<field name="assigned_to" />
<field name="product_qty" />
<field name="pending_qty" />
<field name="company_id" groups="base.group_multi_company" widget="selection"/>
<field
name="company_id"
groups="base.group_multi_company"
widget="selection"
/>
<field name="origin" />
<field name="date_planned_start" />
<field name="state" />
</tree>
</field>
</record>
<record id="view_mrp_production_request_search" model="ir.ui.view">
<field name="name">mrp.production.request.search</field>
<field name="model">mrp.production.request</field>
@@ -140,62 +177,98 @@
<field name="state" />
<field name="pending_qty" invisible="1" />
<!--Filters:-->
<filter name="unassigned" string="Unassigned"
<filter
name="unassigned"
string="Unassigned"
domain="[('assigned_to','=', False)]"
help="Unassigned Request"/>
<filter name="assigned_to_me"
help="Unassigned Request"
/>
<filter
name="assigned_to_me"
domain="[('assigned_to','=', uid)]"
string="Assigned to me"/>
<filter name="requested_by_me"
string="Assigned to me"
/>
<filter
name="requested_by_me"
domain="[('requested_by','=', uid)]"
string="My requests" help="Requested by me"/>
string="My requests"
help="Requested by me"
/>
<separator />
<filter name="pending"
<filter
name="pending"
domain="[('pending_qty','!=', 0.0)]"
string="Pending Qty"
help="Request with pending quantity"/>
help="Request with pending quantity"
/>
<separator />
<filter name="todo" string="To Do"
<filter
name="todo"
string="To Do"
domain="[('state','in',('draft', 'to_approve','approved'))]"
help="Manufacturing Requests not done or cancelled."/>
help="Manufacturing Requests not done or cancelled."
/>
<separator />
<filter name="state_draft" string="Draft"
<filter
name="state_draft"
string="Draft"
domain="[('state','=','draft')]"
help="Request is to be approved"/>
<filter name="state_to_approve" string="To Approve"
help="Request is to be approved"
/>
<filter
name="state_to_approve"
string="To Approve"
domain="[('state','=','to_approve')]"
help="Request is to be approved"/>
<filter name="state_approved" string="Approved"
help="Request is to be approved"
/>
<filter
name="state_approved"
string="Approved"
domain="[('state','=','approved')]"
help="Request is approved"/>
<filter name="state_cancel" string="Cancelled"
help="Request is approved"
/>
<filter
name="state_cancel"
string="Cancelled"
domain="[('state','=','cancel')]"
help="Request is cancelled"/>
<filter name="state_done" string="Done"
help="Request is cancelled"
/>
<filter
name="state_done"
string="Done"
domain="[('state','=','done')]"
help="Request is done"/>
help="Request is done"
/>
<separator />
<filter name="message_needaction"
<filter
name="message_needaction"
string="Unread Messages"
domain="[('message_needaction','=',True)]"/>
domain="[('message_needaction','=',True)]"
/>
<!--Group by:-->
<filter name="requested_by_group_by"
string="Requested by" icon="terp-personal"
<filter
name="requested_by_group_by"
string="Requested by"
icon="terp-personal"
domain="[]"
context="{'group_by':'requested_by'}"/>
<filter name="assign_to_group_by"
string="Assigned to" icon="terp-personal"
context="{'group_by':'requested_by'}"
/>
<filter
name="assign_to_group_by"
string="Assigned to"
icon="terp-personal"
domain="[]"
context="{'group_by':'assigned_to'}"/>
<filter name="origin_group_by"
context="{'group_by':'assigned_to'}"
/>
<filter
name="origin_group_by"
string="Source"
domain="[]"
context="{'group_by':'origin'}"/>
context="{'group_by':'origin'}"
/>
</search>
</field>
</record>
<record model="ir.actions.act_window" id="mrp_production_request_action">
<field name="name">Manufacturing Requests</field>
<field name="type">ir.actions.act_window</field>
@@ -206,28 +279,25 @@
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to start a new manufacturing request process.
</p><p>
</p>
<p>
A Manufacturing Request is an instruction to production to produce
a certain quantity of a given product.
</p>
</field>
</record>
<menuitem
id="menu_mrp_production_request_act"
sequence="10"
parent="mrp.menu_mrp_manufacturing"
action="mrp_production_request_action"
/>
<!--Sever actions-->
<record id="action_server_mrp_production_request_refresh"
model="ir.actions.server">
<record id="action_server_mrp_production_request_refresh" model="ir.actions.server">
<field name="name">Refresh Quantities</field>
<field name="model_id" ref="model_mrp_production_request" />
<field name="binding_model_id" ref="model_mrp_production_request" />
<field name="state">code</field>
<field name="code">records._compute_manufactured_qty()</field>
</record>
</odoo>

View File

@@ -2,17 +2,14 @@
<!-- Copyright 2017 Eficent Business and IT Consulting Services S.L.
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl-3.0) -->
<odoo>
<record id="mrp_production_form_view" model="ir.ui.view">
<field name="name">mrp.production.form - mrp_production_request</field>
<field name="model">mrp.production</field>
<field name="inherit_id"
ref="mrp.mrp_production_form_view"/>
<field name="inherit_id" ref="mrp.mrp_production_form_view" />
<field name="arch" type="xml">
<field name="availability" position="after">
<field name="mrp_production_request_id" />
</field>
</field>
</record>
</odoo>

View File

@@ -2,17 +2,14 @@
<!-- Copyright 2017 Eficent Business and IT Consulting Services S.L.
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl-3.0) -->
<odoo>
<record model="ir.ui.view" id="view_template_property_form">
<field name="name">product.template.form - mrp_production_request</field>
<field name="model">product.template</field>
<field name="inherit_id"
ref="stock.view_template_property_form"/>
<field name="inherit_id" ref="stock.view_template_property_form" />
<field name="arch" type="xml">
<field name="route_ids" position="after">
<field name="mrp_production_request" />
</field>
</field>
</record>
</odoo>

View File

@@ -1,10 +1,11 @@
# Copyright 2017-19 Eficent Business and IT Consulting Services S.L.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models, _
import odoo.addons.decimal_precision as dp
from odoo import _, api, fields, models
from odoo.exceptions import UserError
import odoo.addons.decimal_precision as dp
class MrpProductionRequestCreateMo(models.TransientModel):
_name = "mrp.production.request.create.mo"
@@ -16,14 +17,16 @@ class MrpProductionRequestCreateMo(models.TransientModel):
res = self._prepare_lines()
product_lines = res[1]
for line in product_lines:
self.env['mrp.production.request.create.mo.line'].create(
self._prepare_product_line(line))
self.env["mrp.production.request.create.mo.line"].create(
self._prepare_product_line(line)
)
self._get_mo_qty()
# The wizard must be reloaded in order to show the new product lines
action = self.env.ref(
'mrp_production_request.mrp_production_request_create_mo_action')
"mrp_production_request.mrp_production_request_create_mo_action"
)
res = action.read()[0]
res['res_id'] = self.id
res["res_id"] = self.id
return res
def _prepare_lines(self):
@@ -32,70 +35,71 @@ class MrpProductionRequestCreateMo(models.TransientModel):
:return: boms_done, lines_done
"""
bom_point = self.bom_id
factor = self.mrp_production_request_id.product_uom_id.\
_compute_quantity(self.pending_qty, bom_point.product_uom_id)
factor = self.mrp_production_request_id.product_uom_id._compute_quantity(
self.pending_qty, bom_point.product_uom_id
)
return bom_point.explode(
self.mrp_production_request_id.product_id,
factor / bom_point.product_qty)
self.mrp_production_request_id.product_id, factor / bom_point.product_qty
)
@api.multi
def _get_mo_qty(self):
"""Propose a qty to create a MO available to produce."""
for rec in self:
bottle_neck = min(rec.product_line_ids.mapped(
'bottle_neck_factor'))
bottle_neck = min(rec.product_line_ids.mapped("bottle_neck_factor"))
bottle_neck = max(min(1, bottle_neck), 0)
rec.mo_qty = rec.pending_qty * bottle_neck
mrp_production_request_id = fields.Many2one(
comodel_name="mrp.production.request", readonly=True)
bom_id = fields.Many2one(
related='mrp_production_request_id.bom_id', readonly=True)
comodel_name="mrp.production.request", readonly=True
)
bom_id = fields.Many2one(related="mrp_production_request_id.bom_id", readonly=True)
mo_qty = fields.Float(
string="Quantity",
digits=dp.get_precision("Product Unit of Measure"))
string="Quantity", digits=dp.get_precision("Product Unit of Measure")
)
pending_qty = fields.Float(
related="mrp_production_request_id.pending_qty",
digits=dp.get_precision("Product Unit of Measure"))
product_uom_id = fields.Many2one(
related="mrp_production_request_id.product_uom_id")
digits=dp.get_precision("Product Unit of Measure"),
)
product_uom_id = fields.Many2one(related="mrp_production_request_id.product_uom_id")
product_line_ids = fields.One2many(
comodel_name="mrp.production.request.create.mo.line",
string="Products needed",
inverse_name="mrp_production_request_create_mo_id", readonly=True)
date_planned_start = fields.Datetime(
string="Deadline Start",
required=True,
)
date_planned_finished = fields.Datetime(
string="Deadline End",
required=True,
inverse_name="mrp_production_request_create_mo_id",
readonly=True,
)
date_planned_start = fields.Datetime(string="Deadline Start", required=True,)
date_planned_finished = fields.Datetime(string="Deadline End", required=True,)
@api.model
def default_get(self, fields):
rec = super().default_get(fields)
active_ids = self._context.get('active_ids')
active_model = self._context.get('active_model')
active_ids = self._context.get("active_ids")
active_model = self._context.get("active_model")
if not active_ids:
raise UserError(_(
raise UserError(
_(
"Programming error: wizard action executed without "
"active_ids in context."))
"active_ids in context."
)
)
request = self.env[active_model].browse(active_ids)
rec.update({
'mrp_production_request_id': active_ids[0],
'date_planned_start': request[0].date_planned_start,
'date_planned_finished': request[0].date_planned_finished,
})
rec.update(
{
"mrp_production_request_id": active_ids[0],
"date_planned_start": request[0].date_planned_start,
"date_planned_finished": request[0].date_planned_finished,
}
)
return rec
def _prepare_product_line(self, pl):
return {
'product_id': pl[0].product_id.id,
'product_qty': pl[1]['qty'],
'product_uom_id': pl[0].product_uom_id.id,
'mrp_production_request_create_mo_id': self.id,
'location_id': self.mrp_production_request_id.location_src_id.id,
"product_id": pl[0].product_id.id,
"product_qty": pl[1]["qty"],
"product_uom_id": pl[0].product_uom_id.id,
"mrp_production_request_create_mo_id": self.id,
"location_id": self.mrp_production_request_id.location_src_id.id,
}
@api.multi
@@ -103,35 +107,34 @@ class MrpProductionRequestCreateMo(models.TransientModel):
self.ensure_one()
request_id = self.mrp_production_request_id
return {
'product_id': request_id.product_id.id,
'bom_id': request_id.bom_id.id,
'product_qty': self.mo_qty,
'product_uom_id': self.product_uom_id.id,
'mrp_production_request_id': self.mrp_production_request_id.id,
'origin': request_id.origin,
'location_src_id': request_id.location_src_id.id,
'location_dest_id': request_id.location_dest_id.id,
'picking_type_id': request_id.picking_type_id.id,
'routing_id': request_id.routing_id.id,
'date_planned_start': self.date_planned_start,
'date_planned_finished': self.date_planned_finished,
'procurement_group_id': request_id.procurement_group_id.id,
'propagate': request_id.propagate,
'company_id': request_id.company_id.id,
"product_id": request_id.product_id.id,
"bom_id": request_id.bom_id.id,
"product_qty": self.mo_qty,
"product_uom_id": self.product_uom_id.id,
"mrp_production_request_id": self.mrp_production_request_id.id,
"origin": request_id.origin,
"location_src_id": request_id.location_src_id.id,
"location_dest_id": request_id.location_dest_id.id,
"picking_type_id": request_id.picking_type_id.id,
"routing_id": request_id.routing_id.id,
"date_planned_start": self.date_planned_start,
"date_planned_finished": self.date_planned_finished,
"procurement_group_id": request_id.procurement_group_id.id,
"propagate": request_id.propagate,
"company_id": request_id.company_id.id,
}
@api.multi
def create_mo(self):
self.ensure_one()
vals = self._prepare_manufacturing_order()
mo = self.env['mrp.production'].create(vals)
mo = self.env["mrp.production"].create(vals)
# Open resulting MO:
action = self.env.ref('mrp.mrp_production_action').read()[0]
res = self.env.ref('mrp.mrp_production_form_view')
action.update({
'res_id': mo and mo.id,
'views': [(res and res.id or False, 'form')],
})
action = self.env.ref("mrp.mrp_production_action").read()[0]
res = self.env.ref("mrp.mrp_production_form_view")
action.update(
{"res_id": mo and mo.id, "views": [(res and res.id or False, "form")],}
)
return action
@@ -143,11 +146,13 @@ class MrpProductionRequestCreateMoLine(models.TransientModel):
def _compute_available_qty(self):
for rec in self:
product_available = rec.product_id.with_context(
location=rec.location_id.id).\
_compute_product_available_not_res_dict()[
rec.product_id.id]['qty_available_not_res']
location=rec.location_id.id
)._compute_product_available_not_res_dict()[rec.product_id.id][
"qty_available_not_res"
]
res = rec.product_id.product_tmpl_id.uom_id._compute_quantity(
product_available, rec.product_uom_id)
product_available, rec.product_uom_id
)
rec.available_qty = res
@api.multi
@@ -157,19 +162,23 @@ class MrpProductionRequestCreateMoLine(models.TransientModel):
rec.bottle_neck_factor = rec.available_qty / rec.product_qty
product_id = fields.Many2one(
comodel_name='product.product', string='Product', required=True)
comodel_name="product.product", string="Product", required=True
)
product_qty = fields.Float(
string='Quantity Required', required=True,
digits=dp.get_precision('Product Unit of Measure'))
string="Quantity Required",
required=True,
digits=dp.get_precision("Product Unit of Measure"),
)
product_uom_id = fields.Many2one(
comodel_name='uom.uom', string='UoM', required=True)
comodel_name="uom.uom", string="UoM", required=True
)
mrp_production_request_create_mo_id = fields.Many2one(
comodel_name='mrp.production.request.create.mo')
comodel_name="mrp.production.request.create.mo"
)
available_qty = fields.Float(
string='Quantity Available', compute='_compute_available_qty',
digits=dp.get_precision('Product Unit of Measure'))
bottle_neck_factor = fields.Float(
compute='_compute_bottle_neck_factor')
location_id = fields.Many2one(
comodel_name='stock.location',
required=True)
string="Quantity Available",
compute="_compute_available_qty",
digits=dp.get_precision("Product Unit of Measure"),
)
bottle_neck_factor = fields.Float(compute="_compute_bottle_neck_factor")
location_id = fields.Many2one(comodel_name="stock.location", required=True)

View File

@@ -2,20 +2,25 @@
<!-- Copyright 2017 Eficent Business and IT Consulting Services S.L.
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl-3.0) -->
<odoo>
<record id="mrp_production_request_create_mo_view" model="ir.ui.view">
<field name="name">mrp.production.request.create.mo.form</field>
<field name="model">mrp.production.request.create.mo</field>
<field name="arch" type="xml">
<form string="Select event to register">
<group name="origin" string="Manufacture Request status"
col="6">
<group name="origin" string="Manufacture Request status" col="6">
<group colspan="2">
<field name="mrp_production_request_id"
options='{"no_open": True}'/>
<field
name="mrp_production_request_id"
options='{"no_open": True}'
/>
<field name="pending_qty" />
<button name="compute_product_line_ids" type="object"
string="Compute lines" colspan="2" icon="fa-cogs"/>
<button
name="compute_product_line_ids"
type="object"
string="Compute lines"
colspan="2"
icon="fa-cogs"
/>
</group>
<group colspan="4">
<field name="product_line_ids" nolabel="1">
@@ -34,7 +39,12 @@
<label for="mo_qty" />
<div>
<field name="mo_qty" class="oe_inline" />
<field name="product_uom_id" class="oe_inline" options="{'no_open': True}" groups="uom.group_uom"/>
<field
name="product_uom_id"
class="oe_inline"
options="{'no_open': True}"
groups="uom.group_uom"
/>
</div>
</group>
<group name="date_planned">
@@ -42,20 +52,19 @@
<field name="date_planned_finished" />
</group>
</group>
<footer>
<button name="create_mo"
<button
name="create_mo"
type="object"
string="Create MO"
class="oe_highlight"/>
class="oe_highlight"
/>
or
<button special="cancel"
string="Cancel"/>
<button special="cancel" string="Cancel" />
</footer>
</form>
</field>
</record>
<record id="mrp_production_request_create_mo_action" model="ir.actions.act_window">
<field name="name">Create Manufacturing Order</field>
<field name="res_model">mrp.production.request.create.mo</field>
@@ -63,5 +72,4 @@
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
</odoo>

View File

@@ -0,0 +1 @@
../../../../mrp_production_request

View File

@@ -0,0 +1,6 @@
import setuptools
setuptools.setup(
setup_requires=['setuptools-odoo'],
odoo_addon=True,
)