mirror of
https://github.com/OCA/manufacture.git
synced 2025-01-28 16:37:15 +02:00
[ADD] Added module with pre-commit changes only.
This commit is contained in:
@@ -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"),
|
||||
("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'])],
|
||||
selection=[
|
||||
("draft", "Draft"),
|
||||
("to_approve", "To Be Approved"),
|
||||
("approved", "Approved"),
|
||||
("done", "Done"),
|
||||
("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.")
|
||||
"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.",
|
||||
)
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user