diff --git a/oca_dependencies.txt b/oca_dependencies.txt index e9e2f94a5..862337b72 100644 --- a/oca_dependencies.txt +++ b/oca_dependencies.txt @@ -2,3 +2,4 @@ # Add a repository url and branch if you need a forked version product-attribute stock-logistics-warehouse +stock-logistics-workflow diff --git a/quality_control_issue/README.rst b/quality_control_issue/README.rst index f17a29a5a..8581832f7 100644 --- a/quality_control_issue/README.rst +++ b/quality_control_issue/README.rst @@ -6,17 +6,59 @@ Quality Control Issue ===================== -WIP - This module extends the functionality of quality Control to allow you to report and manage quality control issues. +Configuration +============= + +To configure this module in order to take advantage of the kanban views you +need to create the stages for *issues* and *problems*. To **create** stages in +any kanban view click on *Add New Column*. Then you can **reorder** the stages +just dragging them. + +In created stages you can **configure** them clicking on the gear button that +appears at the right of the stage name and clicking on *Edit*. Note the +following behaviors: + +* You can set a *Quality Control Team*. + + - Stages with no team set will be shared by all teams. + - Stages with a team associated will be only available for that specific + team. + +* In Issue Stages you can also relate a *QC State* to the stage. + + - When you move to a different stage an issue with *QC state* defined the + state of the issue will also change according to it. + - The other way around, if you change the state, the system will look for + an appropriate stage and if existing the issue will be move to that stage. + - If you change the *QC team* of an issue, the system will get the default + stage for that team and apply it to the issue. + Usage ===== -To use this module, you need to: +To use Quality Control Issues, you need to: -#. Go to *Quality Control > Issues > QC Issues*. +#. Go to *Quality Control > Issues > QC Issues* or to *Quality Control > + Dashboard* and click on *Issues* in any of your teams. +#. Click on create to report an issue. +#. Select the product and quantity for the issue. Optionally you can specify + a location and relate the issue to some *Problem*. + +To manage your Quality Control Problems, you have to: + +#. Go to *Quality Control > Problem Tracking > Problems* or to *Quality + Control > Dashboard* and click on *Problems* in any of your teams. + +Issue Dispositions: +------------------- + +You can perform the following actions in quality control issues 'in progress': + +* Scrap: Click on *Scrap Products* button. +* Create RMA: Install `rma_quality_control_issue` and see instructions there. .. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas :alt: Try me on Runbot @@ -28,9 +70,7 @@ Known issues / Roadmap Todo: ----- -* Add Dispositions: RMA, scrap, rework... -* reference to PO, MO, QC... -* Link to Problem tracking... +* Add more dispositions: repair, refurbish... Bug Tracker =========== @@ -52,6 +92,7 @@ Contributors ------------ * Lois Rilo +* Jordi Ballester Alomar Maintainer ---------- diff --git a/quality_control_issue/__openerp__.py b/quality_control_issue/__openerp__.py index 823c85570..881a129d3 100644 --- a/quality_control_issue/__openerp__.py +++ b/quality_control_issue/__openerp__.py @@ -11,7 +11,12 @@ "license": "AGPL-3", "application": False, "installable": True, - "depends": ["quality_control", "quality_control_team", "stock"], + "depends": [ + "quality_control", + "quality_control_team", + "stock", + "stock_scrap", + ], "data": [ "security/ir.model.access.csv", "security/quality_control_issue_security.xml", @@ -21,5 +26,6 @@ "views/qc_problem_view.xml", "views/qc_problem_group_view.xml", "views/qc_team_dashboard_view.xml", + "views/stock_scrap_view.xml", ], } diff --git a/quality_control_issue/models/__init__.py b/quality_control_issue/models/__init__.py index 8eef5efd4..64bcb241b 100644 --- a/quality_control_issue/models/__init__.py +++ b/quality_control_issue/models/__init__.py @@ -1,6 +1,8 @@ # -*- coding: utf-8 -*- # Copyright 2017 Eficent Business and IT Consulting Services S.L. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import stock_scrap from . import qc_stage from . import qc_problem from . import qc_problem_group diff --git a/quality_control_issue/models/qc_issue.py b/quality_control_issue/models/qc_issue.py index a7d5d7aae..19dfeb3e3 100644 --- a/quality_control_issue/models/qc_issue.py +++ b/quality_control_issue/models/qc_issue.py @@ -2,7 +2,8 @@ # Copyright 2017 Eficent Business and IT Consulting Services S.L. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from openerp import api, fields, models +from openerp import api, fields, models, _ +from openerp.exceptions import UserError import openerp.addons.decimal_precision as dp @@ -11,6 +12,12 @@ class QualityControlIssue(models.Model): _description = "Quality Control Issue" _inherit = "mail.thread" + @api.multi + def _compute_stock_scrap_qty(self): + for rec in self: + rec.stock_scrap_qty = sum( + self.stock_scrap_ids.mapped('scrap_qty')) + @api.model def create(self, vals): vals['name'] = self.env['ir.sequence'].next_by_code( @@ -61,7 +68,7 @@ class QualityControlIssue(models.Model): ("progress", "In Progress"), ("done", "Done"), ("cancel", "Cancel")], default="new", - track_visibility='onchange') + track_visibility='onchange', readonly=True) product_id = fields.Many2one( comodel_name="product.product", string="Product", readonly=True, states={"new": [("readonly", False)]}, required=True) @@ -111,6 +118,10 @@ class QualityControlIssue(models.Model): company_id = fields.Many2one( comodel_name='res.company', string='Company', required=True, default=lambda self: self.env.user.company_id) + stock_scrap_ids = fields.One2many( + comodel_name='stock.scrap', string='Scraps', + inverse_name='qc_issue_id') + stock_scrap_qty = fields.Integer(compute=_compute_stock_scrap_qty) _group_by_full = { 'stage_id': _read_group_stage_ids @@ -131,18 +142,47 @@ class QualityControlIssue(models.Model): team_ids.add(issue.team_id.id) search_domain = [] if team_ids: - search_domain += [('|')] * (len(team_ids) - 1) + search_domain += [('|')] * (len(team_ids)) + search_domain.append(('qc_team_id', '=', False)) for team_id in team_ids: search_domain.append(('qc_team_id', '=', team_id)) + else: + search_domain.append(('qc_team_id', '=', False)) search_domain += list(domain) # perform search, return the first found stage = self.env['qc.issue.stage'].search( search_domain, order=order, limit=1) return stage + @api.multi + def write(self, vals): + stage_obj = self.env['qc.issue.stage'] + state = vals.get('state') + if state: + if len(self.mapped('qc_team_id')) > 1: + raise UserError(_( + "Every issue must have the same QC team to perform this " + "action.")) + team = self[0].qc_team_id + stage = self.issue_stage_find([], team, [('state', '=', state)]) + if stage: + vals.update({'stage_id': stage.id}) + return super(QualityControlIssue, self).write(vals) + team_id = vals.get('qc_team_id') + if team_id is not None: + team = self.env['qc.team'].browse(team_id) + stage = self.issue_stage_find([], team, [('fold', '=', False)]) + if stage: + vals.update({'stage_id': stage.id}) + stage_id = vals.get('stage_id') + if stage_id: + state = stage_obj.browse(stage_id).state + if state: + vals.update({'state': state}) + return super(QualityControlIssue, self).write(vals) + @api.multi def action_confirm(self): - self._check_required_fields() self.write({'state': 'progress'}) @api.multi @@ -170,7 +210,38 @@ class QualityControlIssue(models.Model): self.product_id = product self.product_uom = product.product_tmpl_id.uom_id - @api.onchange("stage_id") - def _onchange_stage_id(self): - if self.stage_id.state: - self.state = self.stage_id.state + @api.multi + def scrap_products(self): + self.ensure_one() + return { + 'name': _('Scrap'), + 'view_type': 'form', + 'view_mode': 'form', + 'res_model': 'stock.scrap', + 'view_id': self.env.ref('stock_scrap.stock_scrap_form_view2').id, + 'type': 'ir.actions.act_window', + 'context': { + 'default_qc_issue_id': self.id, + 'default_location_id': self.location_id.id, + 'default_product_id': self.product_id.id, + 'default_scrap_qty': self.product_qty, + 'default_product_uom_id': self.product_uom.id, + 'default_lot_id': self.lot_id.id, + }, + 'target': 'new', + } + + @api.multi + def action_view_stock_scrap(self): + action = self.env.ref('stock_scrap.action_stock_scrap') + result = action.read()[0] + lines = self.stock_scrap_ids + # choose the view_mode accordingly + if len(lines) != 1: + result['domain'] = "[('id', 'in', " + \ + str(lines.ids) + ")]" + elif len(lines) == 1: + res = self.env.ref('stock_scrap.stock_scrap_form_view', False) + result['views'] = [(res and res.id or False, 'form')] + result['res_id'] = lines.id + return result diff --git a/quality_control_issue/models/qc_issue_stage.py b/quality_control_issue/models/qc_issue_stage.py index 4a652ff18..387e1ff17 100644 --- a/quality_control_issue/models/qc_issue_stage.py +++ b/quality_control_issue/models/qc_issue_stage.py @@ -40,5 +40,5 @@ class QualityControlIssueStage(models.Model): help='This stage is folded in the kanban view when there are no ' 'records in that stage to display.') state = fields.Selection( - string="QC Status", + string="QC State", selection=lambda self: self.env['qc.issue']._fields['state'].selection) diff --git a/quality_control_issue/models/qc_problem.py b/quality_control_issue/models/qc_problem.py index 72b9881f4..465f6b377 100644 --- a/quality_control_issue/models/qc_problem.py +++ b/quality_control_issue/models/qc_problem.py @@ -101,9 +101,12 @@ class QcProblem(models.Model): team_ids.add(problem.team_id.id) search_domain = [] if team_ids: - search_domain += [('|')] * (len(team_ids) - 1) + search_domain += [('|')] * (len(team_ids)) + search_domain.append(('qc_team_id', '=', False)) for team_id in team_ids: search_domain.append(('qc_team_id', '=', team_id)) + else: + search_domain.append(('qc_team_id', '=', False)) search_domain += list(domain) # perform search, return the first found stage = self.env['qc.stage'].search( diff --git a/quality_control_issue/models/stock_scrap.py b/quality_control_issue/models/stock_scrap.py new file mode 100644 index 000000000..dd83a67e6 --- /dev/null +++ b/quality_control_issue/models/stock_scrap.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 Eficent Business and IT Consulting Services S.L. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from openerp import fields, models + + +class QualityControlIssueStage(models.Model): + _inherit = "stock.scrap" + + qc_issue_id = fields.Many2one( + comodel_name="qc.issue", string="Quality Control Issue") diff --git a/quality_control_issue/views/qc_issue_view.xml b/quality_control_issue/views/qc_issue_view.xml index 1dffb686b..d10884178 100644 --- a/quality_control_issue/views/qc_issue_view.xml +++ b/quality_control_issue/views/qc_issue_view.xml @@ -29,7 +29,10 @@ string="Confirm" class="oe_highlight" />