[9.0][ADD] quality_control_issue

This commit is contained in:
lreficent
2017-05-25 13:30:24 +02:00
committed by Jordi Ballester Alomar
parent 06d828f436
commit 508fe0a28b
19 changed files with 1074 additions and 0 deletions

View File

@@ -0,0 +1,69 @@
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
=====================
Quality Control Issue
=====================
WIP
This module extends the functionality of quality Control to allow you to
report and manage quality control issues.
Usage
=====
To use this module, you need to:
#. Go to *Quality Control > Issues > QC Issues*.
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
:target: https://runbot.odoo-community.org/runbot/129/9.0
Known issues / Roadmap
======================
Todo:
-----
* Add Dispositions: RMA, scrap, rework...
* reference to PO, MO, QC...
* Link to Problem tracking...
Bug Tracker
===========
Bugs are tracked on `GitHub Issues
<https://github.com/OCA/manufacture/issues>`_. In case of trouble, please
check there if your issue has already been reported. If you spotted it first,
help us smash it by providing detailed and welcomed feedback.
Credits
=======
Images
------
* Odoo Community Association: `Icon <https://github.com/OCA/maintainer-tools/blob/master/template/module/static/description/icon.svg>`_.
Contributors
------------
* Lois Rilo <lois.rilo@eficent.com>
Maintainer
----------
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
This module is maintained by the OCA.
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
To contribute to this module, please visit https://odoo-community.org.

View File

@@ -0,0 +1,5 @@
# -*- 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 models

View File

@@ -0,0 +1,25 @@
# -*- 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).
{
"name": "Quality Control Issue",
"summary": "Allow to manage and report Quality Control Issues.",
"version": "9.0.1.0.0",
"category": "Quality Control",
"website": "https://odoo-community.org/",
"author": "Eficent , Odoo Community Association (OCA)",
"license": "AGPL-3",
"application": False,
"installable": True,
"depends": ["quality_control", "quality_control_team", "stock"],
"data": [
"security/ir.model.access.csv",
"security/quality_control_issue_security.xml",
"data/qc_issue_sequence.xml",
"data/qc_stage_data.xml",
"views/qc_issue_view.xml",
"views/qc_problem_view.xml",
"views/qc_problem_group_view.xml",
"views/qc_team_dashboard_view.xml",
],
}

View File

@@ -0,0 +1,15 @@
<?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_qc_issue" model="ir.sequence">
<field name="name">QC Issues</field>
<field name="code">qc.issue</field>
<field name="prefix">QCI/%(range_year)s/</field>
<field name="padding">5</field>
<field name="company_id" eval="False"/>
</record>
</odoo>

View File

@@ -0,0 +1,23 @@
<?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>
<data noupdate="0">
<record model="qc.stage" id="qc_stage_new">
<field name="name">New</field>
<field name="sequence">1</field>
<field name="fold">False</field>
</record>
</data>
<data noupdate="0">
<record model="qc.stage" id="qc_stage_done">
<field name="name">Done</field>
<field name="sequence">100</field>
<field name="fold">True</field>
</record>
</data>
</odoo>

View File

@@ -0,0 +1,9 @@
# -*- 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 qc_issue
from . import qc_problem
from . import qc_problem_group
from . import qc_stage
from . import qc_issue_stage

View File

@@ -0,0 +1,173 @@
# -*- 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 api, fields, models
import openerp.addons.decimal_precision as dp
class QualityControlIssue(models.Model):
_name = "qc.issue"
_description = "Quality Control Issue"
_inherit = "mail.thread"
@api.model
def create(self, vals):
vals['name'] = self.env['ir.sequence'].next_by_code(
'qc.issue') or ''
return super(QualityControlIssue, self).create(vals)
@api.one
def _get_uom(self):
self.product_uom = self.product_id.product_tmpl_id.uom_id
def _get_default_stage_id(self):
""" Gives default stage_id """
team_id = self.env['qc.team']._get_default_qc_team_id(
user_id=self.env.uid)
return self.issue_stage_find([], team_id, [('fold', '=', False)])
@api.multi
def _read_group_stage_ids(self, domain, read_group_order=None,
access_rights_uid=None):
access_rights_uid = access_rights_uid or self._uid
stage_obj = self.env['qc.issue.stage']
search_domain = []
qc_team_id = self.env.context.get('default_qc_team_id') or False
if qc_team_id:
search_domain += ['|', ('id', 'in', self.ids)]
search_domain += ['|', ('qc_team_id', '=', qc_team_id)]
search_domain += [('qc_team_id', '=', False)]
else:
search_domain += ['|', ('id', 'in', self.ids)]
search_domain += [('qc_team_id', '=', False)]
# perform search
stage_ids = stage_obj._search(search_domain,
access_rights_uid=access_rights_uid)
result = [stage.name_get()[0] for stage in
stage_obj.browse(stage_ids)]
# restore order of the search
result.sort(
lambda x, y: cmp(stage_ids.index(x[0]), stage_ids.index(y[0])))
fold = {}
for stage in stage_obj.browse(stage_ids):
fold[stage.id] = stage.fold or False
return result, fold
name = fields.Char(readonly=True)
state = fields.Selection(
selection=[("new", "New"),
("progress", "In Progress"),
("done", "Done"),
("cancel", "Cancel")], default="new",
track_visibility='onchange')
product_id = fields.Many2one(
comodel_name="product.product", string="Product",
readonly=True, states={"new": [("readonly", False)]},
required=True)
product_tracking = fields.Selection(related="product_id.tracking")
product_qty = fields.Float(
string="Product Quantity", required=True, default=1.0,
readonly=True, states={"new": [("readonly", False)]},
digits_compute=dp.get_precision("Product Unit of Measure"))
product_uom = fields.Many2one(
comodel_name="product.uom", string="Product Unit of Measure",
required=True, default=_get_uom,
readonly=True, states={"new": [("readonly", False)]},)
lot_id = fields.Many2one(
comodel_name="stock.production.lot", string="Lot/Serial Number",
readonly=True, states={"new": [("readonly", False)]},)
location_id = fields.Many2one(
comodel_name="stock.location", string="Location",
readonly=True, states={"new": [("readonly", False)]},)
inspector_id = fields.Many2one(
comodel_name="res.users", string="Inspector",
track_visibility="onchange",
readonly=True, states={"new": [("readonly", False)]},
default=lambda self: self.env.user, required=True)
responsible_id = fields.Many2one(
comodel_name="res.users", string="Assigned to",
track_visibility="onchange",
states={"done": [("readonly", True)]},)
description = fields.Text(
states={"done": [("readonly", True)]},)
qc_problem_ids = fields.Many2many(
comodel_name="qc.problem", string="Problems",
relation="qc_issue_problem_rel", column1="qc_issue_id",
column2="qc_problem_id",
states={"done": [("readonly", True)]},)
color = fields.Integer(string='Color Index')
stage_id = fields.Many2one(
comodel_name="qc.issue.stage", string='Stage',
track_visibility='onchange',
select=True, default=_get_default_stage_id,
domain="['|', ('qc_team_id', '=', False), "
"('qc_team_id', '=', qc_team_id)]")
qc_team_id = fields.Many2one(
comodel_name='qc.team', string='QC Team',
default=lambda self: self.env[
'qc.team'].sudo()._get_default_qc_team_id(user_id=self.env.uid),
index=True, track_visibility='onchange')
company_id = fields.Many2one(
comodel_name='res.company', string='Company', required=True,
default=lambda self: self.env.user.company_id)
_group_by_full = {
'stage_id': _read_group_stage_ids
}
def issue_stage_find(self, cases, team_id, domain=None, order='sequence'):
""" Override of the base.stage method
Parameter of the stage search taken from the problem:
- team_id: if set, stages must belong to this team or
be a default stage; if not set, stages must be default
stages
"""
team_ids = set()
if team_id:
team_ids.add(team_id)
for problem in cases:
if problem.team_id:
team_ids.add(problem.team_id.id)
search_domain = []
if team_ids:
search_domain += [('|')] * (len(team_ids) - 1)
for team_id in team_ids:
search_domain.append(('qc_team_id', '=', team_id.id))
search_domain += list(domain)
# perform search, return the first found
stage_ids = self.env['qc.issue.stage'].search(
search_domain, order=order, limit=1)
if stage_ids:
return stage_ids[0]
return False
@api.multi
def action_confirm(self):
self.write({'state': 'progress'})
@api.multi
def action_done(self):
self.write({'state': 'done'})
@api.multi
def action_cancel(self):
self.write({'state': 'cancel'})
@api.onchange('product_id')
def _onchange_product_id(self):
self.product_uom = self.product_id.product_tmpl_id.uom_id
if self.lot_id.product_id != self.product_id:
self.lot_id = False
if self.product_id:
return {'domain': {
'lot_id': [('product_id', '=', self.product_id.id)]}}
return {'domain': {'lot_id': []}}
@api.onchange("lot_id")
def _onchange_lot_id(self):
product = self.lot_id.product_id
if product:
self.product_id = product
self.product_uom = product.product_tmpl_id.uom_id

View File

@@ -0,0 +1,41 @@
# -*- 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 api, fields, models
AVAILABLE_PRIORITIES = [
('0', 'Normal'),
('1', 'Low'),
('2', 'High'),
('3', 'Very High'),
]
class QualityControlIssueStage(models.Model):
_name = "qc.issue.stage"
_rec_name = 'name'
_order = "sequence, name, id"
@api.model
def default_get(self, fields):
""" Hack : when going from the kanban view, creating a stage with a
qc team in context should not create a stage for the current team only.
"""
ctx = dict(self.env.context)
if ctx.get('default_qc_team_id') and not ctx.get('some_context'):
ctx.pop('default_qc_team_id')
return super(QualityControlIssueStage,
self.with_context(ctx)).default_get(fields)
name = fields.Char('Stage Name', required=True)
sequence = fields.Integer(
string='Sequence', help="Used to order stages. Lower is better.",
default=1)
qc_team_id = fields.Many2one(
comodel_name='qc.team', string='Quality Control Team',
ondelete='set null')
fold = fields.Boolean(
string='Folded in Pipeline', default=False,
help='This stage is folded in the kanban view when there are no '
'records in that stage to display.')

View File

@@ -0,0 +1,113 @@
# -*- 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 api, fields, models
AVAILABLE_PRIORITIES = [
('0', 'Normal'),
('1', 'Low'),
('2', 'High'),
('3', 'Very High'),
]
class QcProblem(models.Model):
_name = "qc.problem"
_description = "Quality Control Problem Tracking"
_inherit = "mail.thread"
def _get_default_stage_id(self):
""" Gives default stage_id """
team_id = self.env['qc.team']._get_default_qc_team_id(
user_id=self.env.uid)
return self.stage_find([], team_id, [('fold', '=', False)])
@api.multi
def _read_group_stage_ids(self, domain, read_group_order=None,
access_rights_uid=None):
access_rights_uid = access_rights_uid or self._uid
stage_obj = self.env['qc.stage']
search_domain = []
qc_team_id = self.env.context.get('default_qc_team_id') or False
if qc_team_id:
search_domain += ['|', ('id', 'in', self.ids)]
search_domain += ['|', ('qc_team_id', '=', qc_team_id)]
search_domain += [('qc_team_id', '=', False)]
else:
search_domain += ['|', ('id', 'in', self.ids)]
search_domain += [('qc_team_id', '=', False)]
# perform search
stage_ids = stage_obj._search(search_domain,
access_rights_uid=access_rights_uid)
result = [stage.name_get()[0] for stage in
stage_obj.browse(stage_ids)]
# restore order of the search
result.sort(
lambda x, y: cmp(stage_ids.index(x[0]), stage_ids.index(y[0])))
fold = {}
for stage in stage_obj.browse(stage_ids):
fold[stage.id] = stage.fold or False
return result, fold
@api.one
@api.depends('issue_ids')
def _compute_count(self):
self.issue_count = len(self.issue_ids)
name = fields.Char()
notes = fields.Text()
issue_ids = fields.Many2many(
comodel_name="qc.issue", string="QC Issues",
relation="qc_issue_problem_rel", column1="qc_problem_id",
column2="qc_issue_id")
problem_group_id = fields.Many2one(
comodel_name="qc.problem.group", string="Problem Group")
issue_count = fields.Integer(
string="Issues", compute=_compute_count, store=True)
color = fields.Integer(string='Color Index')
priority = fields.Selection(
selection=AVAILABLE_PRIORITIES, string='Rating', index=True)
stage_id = fields.Many2one(
comodel_name="qc.stage", string='Stage', track_visibility='onchange',
select=True, default=_get_default_stage_id,
domain="['|', ('qc_team_id', '=', False), "
"('qc_team_id', '=', qc_team_id)]")
qc_team_id = fields.Many2one(
comodel_name='qc.team', string='QC Team',
default=lambda self: self.env[
'qc.team'].sudo()._get_default_qc_team_id(user_id=self.env.uid),
index=True, track_visibility='onchange')
company_id = fields.Many2one(
comodel_name='res.company', string='Company', required=True,
default=lambda self: self.env.user.company_id)
_group_by_full = {
'stage_id': _read_group_stage_ids
}
def stage_find(self, cases, team_id, domain=None, order='sequence'):
""" Override of the base.stage method
Parameter of the stage search taken from the problem:
- team_id: if set, stages must belong to this team or
be a default stage; if not set, stages must be default
stages
"""
team_ids = set()
if team_id:
team_ids.add(team_id)
for problem in cases:
if problem.team_id:
team_ids.add(problem.team_id.id)
search_domain = []
if team_ids:
search_domain += [('|')] * (len(team_ids) - 1)
for team_id in team_ids:
search_domain.append(('qc_team_id', '=', team_id.id))
search_domain += list(domain)
# perform search, return the first found
stage_ids = self.env['qc.stage'].search(
search_domain, order=order, limit=1)
if stage_ids:
return stage_ids[0]
return False

View File

@@ -0,0 +1,17 @@
# -*- 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 QcProblemGroup(models.Model):
_name = "qc.problem.group"
_description = "Quality Control Problem Tracking Groups"
name = fields.Char()
problem_ids = fields.One2many(
comodel_name="qc.problem", inverse_name="problem_group_id")
company_id = fields.Many2one(
comodel_name='res.company', string='Company', required=True,
default=lambda self: self.env.user.company_id)

View File

@@ -0,0 +1,41 @@
# -*- 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 api, fields, models
AVAILABLE_PRIORITIES = [
('0', 'Normal'),
('1', 'Low'),
('2', 'High'),
('3', 'Very High'),
]
class QualityControlStage(models.Model):
_name = "qc.stage"
_rec_name = 'name'
_order = "sequence, name, id"
@api.model
def default_get(self, fields):
""" Hack : when going from the kanban view, creating a stage with a
qc team in context should not create a stage for the current team only.
"""
ctx = dict(self.env.context)
if ctx.get('default_qc_team_id') and not ctx.get('some_context'):
ctx.pop('default_qc_team_id')
return super(QualityControlStage,
self.with_context(ctx)).default_get(fields)
name = fields.Char('Stage Name', required=True)
sequence = fields.Integer(
string='Sequence', help="Used to order stages. Lower is better.",
default=1)
qc_team_id = fields.Many2one(
comodel_name='qc.team', string='Quality Control Team',
ondelete='set null')
fold = fields.Boolean(
string='Folded in Pipeline', default=False,
help='This stage is folded in the kanban view when there are no '
'records in that stage to display.')

View File

@@ -0,0 +1,11 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_user_qc_issue,qc.issue.user,quality_control_issue.model_qc_issue,quality_control.group_quality_control_user,1,1,1,0
access_manager_qc_issue,qc.issue.manager,quality_control_issue.model_qc_issue,quality_control.group_quality_control_manager,1,1,1,1
access_user_qc_problem_group,qc.problem.group.user,quality_control_issue.model_qc_problem_group,quality_control.group_quality_control_user,1,0,0,0
access_manager_qc_problem_group,qc.problem.group.manager,quality_control_issue.model_qc_problem_group,quality_control.group_quality_control_manager,1,1,1,1
access_user_qc_problem,qc.problem.user,quality_control_issue.model_qc_problem,quality_control.group_quality_control_user,1,1,1,0
access_manager_qc_team,qc.problem.manager,quality_control_issue.model_qc_problem,quality_control.group_quality_control_manager,1,1,1,1
access_user_qc_stage,qc.stage.user,quality_control_issue.model_qc_stage,quality_control.group_quality_control_user,1,0,0,0
access_manager_qc_stage,qc.stage.manager,quality_control_issue.model_qc_stage,quality_control.group_quality_control_manager,1,1,1,1
access_user_qc_issue_stage,qc.issue.stage.user,quality_control_issue.model_qc_issue_stage,quality_control.group_quality_control_user,1,0,0,0
access_manager_qc_issue_stage,qc.issue.stage.manager,quality_control_issue.model_qc_issue_stage,quality_control.group_quality_control_manager,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_user_qc_issue qc.issue.user quality_control_issue.model_qc_issue quality_control.group_quality_control_user 1 1 1 0
3 access_manager_qc_issue qc.issue.manager quality_control_issue.model_qc_issue quality_control.group_quality_control_manager 1 1 1 1
4 access_user_qc_problem_group qc.problem.group.user quality_control_issue.model_qc_problem_group quality_control.group_quality_control_user 1 0 0 0
5 access_manager_qc_problem_group qc.problem.group.manager quality_control_issue.model_qc_problem_group quality_control.group_quality_control_manager 1 1 1 1
6 access_user_qc_problem qc.problem.user quality_control_issue.model_qc_problem quality_control.group_quality_control_user 1 1 1 0
7 access_manager_qc_team qc.problem.manager quality_control_issue.model_qc_problem quality_control.group_quality_control_manager 1 1 1 1
8 access_user_qc_stage qc.stage.user quality_control_issue.model_qc_stage quality_control.group_quality_control_user 1 0 0 0
9 access_manager_qc_stage qc.stage.manager quality_control_issue.model_qc_stage quality_control.group_quality_control_manager 1 1 1 1
10 access_user_qc_issue_stage qc.issue.stage.user quality_control_issue.model_qc_issue_stage quality_control.group_quality_control_user 1 0 0 0
11 access_manager_qc_issue_stage qc.issue.stage.manager quality_control_issue.model_qc_issue_stage quality_control.group_quality_control_manager 1 1 1 1

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record model="ir.rule" id="qc_issue_mc_rule">
<field name="name">qc.issue multi-company</field>
<field name="model_id" search="[('model','=','qc.issue')]"
model="ir.model"/>
<field name="global" eval="True"/>
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
</record>
<record model="ir.rule" id="qc_problem_mc_rule">
<field name="name">qc.issue multi-company</field>
<field name="model_id" search="[('model','=','qc.problem')]"
model="ir.model"/>
<field name="global" eval="True"/>
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
</record>
</data>
</odoo>

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

@@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="svg2"
version="1.1"
inkscape:version="0.91 r"
width="256"
height="256"
viewBox="0 0 256 256"
sodipodi:docname="icon.svg"
inkscape:export-filename="icon.png"
inkscape:export-xdpi="45"
inkscape:export-ydpi="45">
<metadata
id="metadata8">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs6" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1855"
inkscape:window-height="1056"
id="namedview4"
showgrid="false"
showguides="false"
inkscape:zoom="2.6074563"
inkscape:cx="97.374622"
inkscape:cy="132.02575"
inkscape:window-x="65"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<path
style="fill:#3b4552;fill-opacity:1;stroke:none;stroke-width:1.93276381"
d="m 211.33966,96.067802 c 0,5.992928 7.91763,11.579358 6.74724,17.584548 -1.17039,6.00519 -11.48804,8.10481 -13.8219,13.58637 -2.33386,5.48156 3.54667,14.45202 0.2853,19.35834 -3.26137,4.90632 -13.42612,3.16349 -17.72981,7.43515 -4.30369,4.27166 -2.84179,14.82951 -7.85007,18.16415 -5.00827,3.33464 -14.16074,-2.55764 -19.80601,-0.26061 -5.64527,2.29703 -8.12649,12.89205 -13.9027,13.97052 -5.77621,1.07847 -11.48439,-7.0737 -17.64561,-7.0737 -6.16121,0 -12.25109,7.92446 -18.34832,6.62698 -6.09723,-1.29748 -7.59194,-10.41046 -12.762714,-12.66396 -5.170777,-2.2535 -13.376422,2.91752 -18.36,-0.36786 -4.983578,-3.28538 -5.262182,-14.36977 -9.53734,-18.79261 -4.275158,-4.42285 -12.851882,-1.69906 -16.45127,-7.12771 -3.599388,-5.42865 1.214828,-13.41741 -0.770599,-19.03959 -1.985426,-5.62218 -11.704615,-8.69661 -12.692518,-13.74392 -0.987903,-5.04731 7.500299,-12.47926 7.500299,-18.614887 0,-6.135628 -8.588091,-11.321696 -7.392633,-17.238661 C 39.996464,71.953386 50.643513,69.536 52.904546,64.153032 55.165579,58.770064 48.868664,50.58811 52.15073,45.63683 c 3.282066,-4.951281 13.747588,-4.272318 18.076133,-8.582161 4.328545,-4.309842 2.720858,-13.899039 7.694198,-17.198646 4.97334,-3.299607 13.104622,1.205446 18.503316,-1.022051 5.398693,-2.227496 7.894433,-11.1597399 13.714143,-12.3387556 5.81971,-1.1790158 12.1411,6.0407876 18.24461,6.0407876 6.10351,-1e-6 11.68483,-7.3111077 17.42643,-6.2026403 5.7416,1.1084674 8.13974,10.5614813 13.80595,12.8572833 5.6662,2.295802 14.94429,-2.23592 19.8907,1.108078 4.94641,3.343998 2.48246,11.892283 6.64749,15.99066 4.16503,4.098377 14.62827,3.666275 18.01677,8.682357 3.3885,5.016082 -2.02844,13.500558 0.32346,19.125397 2.3519,5.62484 12.47407,8.60159 13.61721,14.510953 1.14314,5.909363 -6.77148,11.466779 -6.77148,17.45971 z"
id="circle3368"
inkscape:connector-curvature="0"
sodipodi:nodetypes="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" />
<circle
r="63.531616"
cy="96.067802"
cx="128.38313"
id="circle3346"
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.34354317" />
<circle
style="fill:#2b78c2;fill-opacity:1;stroke:none;stroke-width:1.09952056"
id="path3342"
cx="128.38313"
cy="96.067802"
r="51.992611" />
<path
style="fill:#2b78c2;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
d="m 83.989904,184.28259 8.053826,-1.24642 c 9.05399,16.12754 16.49528,14.24662 24.0656,13.80656 l -10.83431,53.1169 -14.190079,-13.51892 -18.984019,4.79394 z"
id="path3338"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc" />
<path
sodipodi:nodetypes="ccccccc"
inkscape:connector-curvature="0"
id="path3340"
d="m 171.81497,184.37847 -8.05383,-1.24642 c -9.05399,16.12754 -16.49528,14.24662 -24.0656,13.80656 l 10.83431,53.1169 14.19008,-13.51892 18.98402,4.79394 z"
style="fill:#2b78c2;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
inkscape:transform-center-x="-0.016606677"
inkscape:transform-center-y="-4.1513637"
d="m 147.10763,127.15966 -18.87851,-10.66672 -19.29578,10.61355 c -2.14644,1.18064 -5.60088,-1.48065 -5.11608,-3.87048 l 4.26518,-21.02547 -15.410855,-14.46528 c -1.952657,-1.832846 -1.388891,-6.342484 1.848072,-6.713162 l 20.920483,-2.395688 9.61304,-20.440593 c 0.75725,-1.610169 4.6613,-2.921345 5.96156,-0.04186 l 9.11939,20.195236 22.68645,2.860817 c 3.08062,0.388473 2.79381,4.411669 1.38356,5.705416 l -16.16599,14.830394 4.28375,22.429 c 0.38417,2.01144 -2.29024,4.63697 -5.21427,2.98484 z"
id="path3350"
inkscape:connector-curvature="0"
sodipodi:nodetypes="scsscsscsscsscss" />
</svg>

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@@ -0,0 +1,175 @@
<?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>
<record id="qc_issue_tree" model="ir.ui.view">
<field name="name">qc.issue.tree</field>
<field name="model">qc.issue</field>
<field name="arch" type="xml">
<tree string="Issues">
<field name="name"/>
<field name="inspector_id"/>
<field name="product_id"/>
<field name="responsible_id"/>
<field name="state"/>
</tree>
</field>
</record>
<record id="qc_issue_form" model="ir.ui.view">
<field name="name">qc.issue.form</field>
<field name="model">qc.issue</field>
<field name="arch" type="xml">
<form>
<header>
<button name="action_confirm"
type="object" states="new"
string="Confirm" class="oe_highlight" />
<button name="action_done"
type="object" states="progress"
string="Set to Done" class="oe_highlight" />
<button name="action_cancel"
type="object" states="new,progress"
string="Cancel"/>
<field name="stage_id" widget="statusbar" clickable="True"
options="{'fold_field': 'fold'}"
domain="['|', ('qc_team_id', '=', qc_team_id), ('qc_team_id', '=', False)]"/>
</header>
<sheet>
<div class="oe_button_box" name="button_box">
<!--To be inhereted by other modules.-->
</div>
<div class="oe_title">
<label string="Quality Control Issue"/>
<h1>
<field name="name"/>
</h1>
</div>
<group name="top">
<group>
<field name="inspector_id"/>
<field name="responsible_id"/>
<field name="company_id"
groups="base.group_multi_company"/>
<field name="qc_team_id" widget="selection"/>
<field name="state"/>
</group>
<group>
<field name="lot_id"
groups="stock.group_production_lot"
attrs="{'required': [('product_tracking', 'in', ('serial', 'lot'))]}"/>
<field name="product_id"/>
<field name="product_tracking" invisible="1"/>
<field name="product_qty"
attrs="{'invisible': [('product_tracking', '=', 'serial')]}"/>
<field name="product_uom"
groups="product.group_uom"
attrs="{'invisible': [('product_tracking', '=', 'serial')]}"/>
<field name="location_id"/>
</group>
</group>
<group name="bottom">
<field name="qc_problem_ids" widget="many2many_tags"/>
<field name="description"/>
</group>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers" />
<field name="message_ids" widget="mail_thread" />
</div>
</form>
</field>
</record>
<record id="qc_issue_kanban_view" model="ir.ui.view">
<field name="name">qc.issue.kanban</field>
<field name="model">qc.issue</field>
<field name="arch" type="xml">
<kanban class="o_kanban_small_column" default_group_by="stage_id">
<field name="stage_id"/>
<field name="color"/>
<templates>
<t t-name="kanban-box">
<div t-attf-class="#{kanban_color(record.color.raw_value)} oe_kanban_global_click">
<div class="o_dropdown_kanban dropdown">
<a class="dropdown-toggle btn" data-toggle="dropdown" href="#" >
<span class="fa fa-bars fa-lg"/>
</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
<t t-if="widget.editable"><li><a type="edit">Edit</a></li></t>
<t t-if="widget.deletable"><li><a type="delete">Delete</a></li></t>
<li><ul class="oe_kanban_colorpicker" data-field="color"/></li>
</ul>
</div>
<div class="oe_kanban_content">
<div>
<strong><field name="name"/></strong>
</div>
Product: <field name="product_id"/><br></br>
Qty: <field name="product_qty"/> <field name="product_uom"/><br></br>
Location: <field name="location_id"/>
<t t-if="record.qc_problem_ids"><br></br>
Problems:
<t t-foreach="record.qc_problem_ids.raw_value" t-as="rec">
<t t-esc="rec"/>;
</t></t>
<div class="o_kanban_footer">
<!--To be inhereted.-->
</div>
</div>
<div class="oe_clear"></div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<record model="ir.ui.view" id="qc_issue_search">
<field name="name">qc.issue.serch</field>
<field name="model">qc.issue</field>
<field name="arch" type="xml">
<search>
<field name="qc_team_id"/>
<field name="stage_id"/>
<field name="product_id"/>
<field name="location_id"/>
<filter string="My inspections"
domain="[('inspector_id', '=', uid)]"/>
<group expand="0" string="Group By...">
<filter string="Stage" domain="[]"
context="{'group_by':'stage_id'}"/>
<filter string="Problem Group" domain="[]"
context="{'group_by': 'problem_group_id'}"/>
<filter string="Product" domain="[]"
context="{'group_by': 'product_id'}"/>
<filter string="Location" domain="[]"
context="{'group_by': 'location_id'}"/>
<filter string="Company" context="{'group_by':'company_id'}"
groups="base.group_multi_company"/>
</group>
</search>
</field>
</record>
<record id="qc_issue_action" model="ir.actions.act_window">
<field name="name">QC Issues</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">qc.issue</field>
<field name="view_type">form</field>
<field name="view_mode">kanban,tree,form</field>
</record>
<menuitem id="menu_qc_issue"
parent="quality_control.qc_menu"
sequence="50" name="Issues"/>
<menuitem id="menu_qc_issue_child"
parent="quality_control_issue.menu_qc_issue"
action="qc_issue_action"
sequence="20" name="Issues"/>
</odoo>

View File

@@ -0,0 +1,48 @@
<?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>
<record id="qc_problem_group_tree" model="ir.ui.view">
<field name="name">qc.problem.group.tree</field>
<field name="model">qc.problem.group</field>
<field name="arch" type="xml">
<tree string="Problem Groups">
<field name="name"/>
</tree>
</field>
</record>
<record id="qc_problem_group_form" model="ir.ui.view">
<field name="name">qc.problem.group.form</field>
<field name="model">qc.problem.group</field>
<field name="arch" type="xml">
<form>
<sheet>
<group>
<field name="name"/>
</group>
<notebook>
<page name="problems" string="Problems">
<field name="problem_ids"/>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<record id="qc_problem_group_action" model="ir.actions.act_window">
<field name="name">Problem groups</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">qc.problem.group</field>
<field name="view_type">form</field>
</record>
<menuitem id="menu_qc_problem_group"
parent="quality_control_issue.menu_qc_problem_tracking"
action="qc_problem_group_action"
sequence="60" name="Problem Groups"/>
</odoo>

View File

@@ -0,0 +1,136 @@
<?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>
<record id="qc_problem_tree" model="ir.ui.view">
<field name="name">qc.problem.tree</field>
<field name="model">qc.problem</field>
<field name="arch" type="xml">
<tree string="Problem Tracking">
<field name="name"/>
<field name="problem_group_id"/>
<field name="issue_count"/>
</tree>
</field>
</record>
<record id="qc_problem_form" model="ir.ui.view">
<field name="name">qc.problem.form</field>
<field name="model">qc.problem</field>
<field name="arch" type="xml">
<form>
<header>
<field name="stage_id" widget="statusbar" clickable="True"
options="{'fold_field': 'fold'}"
domain="['|', ('qc_team_id', '=', qc_team_id), ('qc_team_id', '=', False)]"/>
<!--attrs="{'invisible': [('active', '=', False)]}"/>-->
</header>
<sheet>
<group>
<group>
<field name="name"/>
<field name="problem_group_id"/>
<field name="notes"/>
</group>
<group>
<field name="qc_team_id" widget="selection"/>
<field name="company_id"
groups="base.group_multi_company"/>
</group>
</group>
<notebook>
<page name="qc_issues" string="QC Issues">
<field name="issue_ids"/>
</page>
</notebook>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers" />
<field name="message_ids" widget="mail_thread" />
</div>
</form>
</field>
</record>
<record model="ir.ui.view" id="qc_problem_kanban_view">
<field name="name">qc.problem.kanban</field>
<field name="model">qc.problem</field>
<field name="arch" type="xml">
<kanban class="o_kanban_small_column" default_group_by="stage_id">
<field name="stage_id"/>
<!--<field name="stage_id" options='{"group_by_tooltip": {"requirements": "Description", "legend_priority": "Use of stars"}}'/>-->
<field name="color"/>
<field name="priority"/>
<templates>
<t t-name="kanban-box">
<div t-attf-class="#{kanban_color(record.color.raw_value)} oe_kanban_global_click">
<div class="o_dropdown_kanban dropdown">
<a class="dropdown-toggle btn" data-toggle="dropdown" href="#" >
<span class="fa fa-bars fa-lg"/>
</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
<t t-if="widget.editable"><li><a type="edit">Edit</a></li></t>
<t t-if="widget.deletable"><li><a type="delete">Delete</a></li></t>
<li><ul class="oe_kanban_colorpicker" data-field="color"/></li>
</ul>
</div>
<div class="oe_kanban_content">
<div>
<strong><field name="name"/></strong>
</div>
<field name="problem_group_id"/><br></br>
<field name="issue_count"/> issues
<div class="o_kanban_footer">
<field name="priority" widget="priority" groups="base.group_user"/>
</div>
</div>
<div class="oe_clear"></div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<record model="ir.ui.view" id="qc_problem_search">
<field name="name">qc.problem.serch</field>
<field name="model">qc.problem</field>
<field name="arch" type="xml">
<search>
<field name="qc_team_id"/>
<field name="stage_id"/>
<field name="problem_group_id"/>
<group expand="0" string="Group By...">
<filter string="Stage" domain="[]"
context="{'group_by':'stage_id'}"/>
<filter string="Problem Group" domain="[]"
context="{'group_by': 'problem_group_id'}"/>
<filter string="Company" context="{'group_by':'company_id'}"
groups="base.group_multi_company"/>
</group>
</search>
</field>
</record>
<record id="qc_problem_action" model="ir.actions.act_window">
<field name="name">Problem Tracking</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">qc.problem</field>
<field name="view_type">form</field>
<field name="view_mode">kanban,tree,form</field>
</record>
<menuitem id="menu_qc_problem_tracking"
parent="quality_control.qc_menu"
sequence="60" name="Problem Tracking"/>
<menuitem id="menu_qc_problem"
parent="quality_control_issue.menu_qc_problem_tracking"
action="qc_problem_action"
sequence="20" name="Problems"/>
</odoo>

View File

@@ -0,0 +1,56 @@
<?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>
<record model="ir.actions.act_window" id="team_qc_issue_act">
<field name="name">Issues by team</field>
<field name="res_model">qc.issue</field>
<field name="view_mode">kanban,tree,form,pivot</field>
<field name="context">{
'search_default_qc_team_id': [active_id],
'default_qc_team_id': active_id,
'default_user_id': uid,
}
</field>
<field name="help" type="html">
<p>Manage Quality Control Issues through your team flow.</p>
</field>
</record>
<record model="ir.actions.act_window" id="team_qc_problem_act">
<field name="name">Problem tracking</field>
<field name="res_model">qc.problem</field>
<field name="view_mode">kanban,tree,form,pivot</field>
<field name="context">{
'search_default_qc_team_id': [active_id],
'default_qc_team_id': active_id,
'default_user_id': uid,
}
</field>
<field name="help" type="html">
<p>Track problems through your team flow.</p>
</field>
</record>
<record id="qc_team_view_kanban" model="ir.ui.view" >
<field name="name">qc.team.dashboard - quality_control_issue</field>
<field name="model">qc.team</field>
<field name="inherit_id" ref="quality_control_team.qc_team_view_kanban"/>
<field name="arch" type="xml">
<xpath expr="//div[contains(@class, 'o_kanban_primary_left')]" position="inside">
<button class="btn btn-primary" type="action"
name="%(team_qc_issue_act)d">Issues
</button>
</xpath>
<xpath expr="//div[contains(@class, 'o_kanban_primary_right')]" position="inside">
<button class="btn btn-primary" type="action"
name="%(team_qc_problem_act)d">Problems
</button>
</xpath>
</field>
</record>
</odoo>