[ADD] new module quality_control_plan

This commit is contained in:
Stefano Consolaro
2020-02-16 19:16:58 +01:00
parent 84c27df0c8
commit d648fd98c6
32 changed files with 2240 additions and 1 deletions

View File

@@ -0,0 +1,3 @@
from . import mgmtsystem_nonconformity_inspection, partner_quality, \
qc_inspection_plan, qc_plan, qc_trigger, stock_picking_inspection

View File

@@ -0,0 +1,17 @@
# Copyright 2019 Marcelo Frare (Ass. PNLUG - Gruppo Odoo <http://odoo.pnlug.it>)
# Copyright 2019 Stefano Consolaro (Ass. PNLUG - Gruppo Odoo <http://odoo.pnlug.it>)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models
class MgmtsystemMgmInspection(models.Model):
"""
Extends nonconformity adding related inspection
"""
_inherit = ['mgmtsystem.nonconformity']
# new field
# inspection reference
inspection_id = fields.Many2one('qc.inspection', 'Inspection')

View File

@@ -0,0 +1,21 @@
# Copyright 2019 Marcelo Frare (Ass. PNLUG - Gruppo Odoo <http://odoo.pnlug.it>)
# Copyright 2019 Stefano Consolaro (Ass. PNLUG - Gruppo Odoo <http://odoo.pnlug.it>)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models
class MgmtsystemMgmPartner(models.Model):
"""
Extends partner with quality control triggers
"""
_inherit = ['res.partner']
# new fields
# trigger to activate inspection
qc_triggers = fields.One2many(
comodel_name="qc.trigger.partner_line",
inverse_name="partner",
string="Quality control triggers"
)

View File

@@ -0,0 +1,29 @@
# Copyright 2019 Marcelo Frare (Ass. PNLUG - Gruppo Odoo <http://odoo.pnlug.it>)
# Copyright 2019 Stefano Consolaro (Ass. PNLUG - Gruppo Odoo <http://odoo.pnlug.it>)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models
class QcProduct(models.Model):
"""
Extends product model with a field to store quality control plan assigned
"""
_inherit = ['qc.trigger.product_template_line']
# new filed
# product's control plan
plan_id = fields.Many2one('qc.plan', 'Plan')
class QcCategory(models.Model):
"""
Extends product category model with a field to store quality control plan assigned
"""
_inherit = ['qc.trigger.product_category_line']
# new filed
# sets product category's control plan
plan_id = fields.Many2one('qc.plan', 'Plan')

View File

@@ -0,0 +1,211 @@
# Copyright 2019 Marcelo Frare (Ass. PNLUG - Gruppo Odoo <http://odoo.pnlug.it>)
# Copyright 2019 Stefano Consolaro (Ass. PNLUG - Gruppo Odoo <http://odoo.pnlug.it>)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models, api, _
class QcInspection(models.Model):
"""
Extends inspection with:
- plan control
- nonconformity relations
- method to fill inspection with control plan data
- method create nonconformity from inspection
"""
_inherit = ['qc.inspection']
# new fields
# the control plan to be used
plan_id = fields.Many2one('qc.plan', 'Control Plan')
# quantity to be checked
qty_checked = fields.Float('Quantity checked')
# nonconformity reference
inspection_ids = fields.One2many('mgmtsystem.nonconformity',
'inspection_id',
'Nonconformity'
)
@api.model
def create(self, values):
"""
Extends inspection method by integrating logic to determine the control plan
to be used and the calculation of the quantity to be checked
"""
# calls original method
new_record = super(QcInspection, self).create(values)
# gets product of the inspection
product_id = new_record.product_id
# gets partner from picking if exists
if new_record.picking_id:
partner_id = self.env['stock.picking'
].search([('id', '=', new_record.picking_id.id)],
limit=1
).partner_id.id
else:
partner_id = False
# temporary presetted solutions
solution_art_prt = '' # plan for product (article) and partner
solution_cat_prt = '' # plan for product category and partner
solution_art = '' # plan for product (article)
solution_cat = '' # plan for product category
solution_prt = '' # plan for partner
# tries to get plan for product and partner
solution_art_prt = self.env['qc.trigger.product_template_line'
].search([('product_template',
'=',
product_id.product_tmpl_id.id),
('partners', '!=', False),
('partners', '=', partner_id)
],
limit=1
)
if (len(solution_art_prt)
== 0):
# tries to gets plan for category and partner
solution_cat_prt = self.env['qc.trigger.product_category_line'
].search([('product_category',
'=',
product_id.categ_id.id),
('partners', '!=', False),
('partners', '=', partner_id)
],
limit=1
)
if (len(solution_art_prt)
+ len(solution_cat_prt)
== 0):
# tries to get plan for product
solution_art = self.env['qc.trigger.product_template_line'
].search([('product_template',
'=',
product_id.product_tmpl_id.id
),
('partners', '=', False)
],
limit=1
)
if (len(solution_art_prt)
+ len(solution_cat_prt)
+ len(solution_art)
== 0):
# tries to get plan for category
solution_cat = self.env['qc.trigger.product_category_line'
].search([('product_category',
'=',
product_id.categ_id.id
),
('partners', '=', False)
],
limit=1
)
if (len(solution_art_prt)
+ len(solution_cat_prt)
+ len(solution_art)
+ len(solution_cat)
== 0):
# tries to get plan for partner
solution_prt = self.env['qc.trigger.partner_line'
].search([('partner', '=', partner_id)
],
limit=1
)
# gets the plan from the first positive try
if len(solution_art_prt):
plan_id = solution_art_prt.plan_id
elif len(solution_cat_prt):
plan_id = solution_cat_prt.plan_id
elif len(solution_art):
plan_id = solution_art.plan_id
elif len(solution_cat):
plan_id = solution_cat.plan_id
elif len(solution_prt):
plan_id = solution_prt.plan_id
else:
new_record.qty_checked = '1'
new_record.plan_id = ''
return new_record
if plan_id:
# assigns plan to be used
new_record.plan_id = plan_id
if new_record.plan_id.free_pass:
# for free pass doesn't check product
new_record.qty_checked = 0
else:
# gets check informations from levels
qty_related = self.env['qc.level'
].search([('plan_id', '=', plan_id.id),
('qty_received', '<', new_record.qty)
],
limit=1,
order='qty_received desc'
)
# assigns qty to check
if qty_related:
if qty_related.chk_type == 'percent':
# as percent of qty to check
new_record.qty_checked = int(new_record.qty
* qty_related.qty_checked
/ 100
)
else:
# as absolute value
new_record.qty_checked = qty_related.qty_checked
# verifies if enough pcs to check
if new_record.qty_checked > new_record.qty:
new_record.qty_checked = new_record.qty
# checks and fix absolute minimum value lower to 1
if new_record.qty_checked < 1:
new_record.qty_checked = 1
return new_record
@api.multi
def create_nonconformity(self, **kwargs):
"""
Opens nonconformity form view prefilled with inspection data
"""
# gets partner if exists
if self.picking_id.partner_id.id:
partner = self.picking_id.partner_id.id
else:
partner = False
tmp_form_name = "mgmtsystem_nonconformity.view_mgmtsystem_nonconformity_form"
return {
# opens nonconformity form view
'name' : _('Create Nonconformity on not compliant Inspection'),
'view_type' : 'form',
'view_mode' : 'form',
'res_model' : 'mgmtsystem.nonconformity',
'view_id' : self.env.ref(tmp_form_name).id,
'type' : 'ir.actions.act_window',
# fills fields with inspection data
'context': {
'default_name' : _('Inspection not compliant'),
'default_product_id' : self.product_id.id,
'default_partner_id' : partner,
'default_qty_checked' : self.qty_checked,
'default_inspection_id' : self.id
},
'target': 'new'
}

View File

@@ -0,0 +1,86 @@
# Copyright 2019 Marcelo Frare (Ass. PNLUG - Gruppo Odoo <http://odoo.pnlug.it>)
# Copyright 2019 Stefano Consolaro (Ass. PNLUG - Gruppo Odoo <http://odoo.pnlug.it>)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models, api, _
from odoo.exceptions import ValidationError
class QcPlan(models.Model):
"""
Manages quality control plans
"""
# model
_name = 'qc.plan'
_description = 'Quality Control Plan'
_inherit = ['mail.thread']
# fields
# alphanumeric identification code
name = fields.Char('Name', required=True)
# description of plan calculation
description = fields.Char('Description')
# free pass option
free_pass = fields.Boolean('Free pass')
# control levels of the plan
plan_ids = fields.One2many('qc.level', 'plan_id', 'Plan')
@api.onchange('free_pass')
def on_change_free_pass(self):
"""
Checks if there is only one free pass plan
Sets the last changed to false if another one exists
"""
if self.free_pass:
free_p = self.env['qc.plan'].search([('free_pass', '=', True)])[0]
if free_p:
self.free_pass = False
raise ValidationError(_("A free pass plan already exists: %s.")
% free_p.name)
@api.model
def create(self, vals):
"""
Avoids multiple free pass plans
"""
if vals['free_pass']:
if self.env['qc.plan'].search([('free_pass', '=', True)]):
return False
return super(QcPlan, self).create(vals)
class QcLevel(models.Model):
"""
Manages the lelevs for a control plan
"""
# model
_name = 'qc.level'
_description = 'Quality Control Plan Levels'
# fields
# plan reference
plan_id = fields.Many2one('qc.plan', 'Plan', required=True)
# minimum ingoing quantity
qty_received = fields.Float('Quantity to inspect',
help='Minimum received quantity reference'
)
# quantity value to check
qty_checked = fields.Float(
'Quantity checked',
help='Quantity to check if the received goods is higher than the reference'
)
# chek value type: absolute or percent of ingoing quantity
chk_type = fields.Selection([('absolute', 'Absolute value'),
('percent', 'Percent'),
],
'Measure',
default='absolute',
help='Indicate how to use quantity checked value'
)
# defines record name to display in form view
_rec_name = 'id'

View File

@@ -0,0 +1,51 @@
# Copyright 2010 NaN Projectes de Programari Lliure, S.L.
# Copyright 2014 Serv. Tec. Avanzados - Pedro M. Baeza
# Copyright 2014 Oihane Crucelaegui - AvanzOSC
# Copyright 2017 Eficent Business and IT Consulting Services S.L.
# Copyright 2017 Simone Rubino - Agile Business Group
# Copyright 2019 Marcelo Frare (Ass. PNLUG - Gruppo Odoo <http://odoo.pnlug.it>)
# Copyright 2019 Stefano Consolaro (Ass. PNLUG - Gruppo Odoo <http://odoo.pnlug.it>)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models
class QcTriggerPartnerLine(models.Model):
"""
Extends quality trigger with partner control plan
"""
_inherit = "qc.trigger.line"
# model
_name = "qc.trigger.partner_line"
# new fields
# reference partner
partner = fields.Many2one(comodel_name="res.partner")
# control plan to use
plan_id = fields.Many2one('qc.plan', 'Plan', required=True)
class QcTriggerProductLine(models.Model):
"""
Extends product model with a field to store quality control plan assigned
"""
_inherit = ['qc.trigger.product_template_line']
# new filed
# product's control plan
plan_id = fields.Many2one('qc.plan', 'Plan')
class QcTriggerCategoryLine(models.Model):
"""
Extends product category model with a field to store quality control plan assigned
"""
_inherit = ['qc.trigger.product_category_line']
# new filed
# sets product category's control plan
plan_id = fields.Many2one('qc.plan', 'Plan')

View File

@@ -0,0 +1,27 @@
# Copyright 2010 NaN Projectes de Programari Lliure, S.L.
# Copyright 2014 Serv. Tec. Avanzados - Pedro M. Baeza
# Copyright 2014 Oihane Crucelaegui - AvanzOSC
# Copyright 2017 Eficent Business and IT Consulting Services S.L.
# Copyright 2017 Simone Rubino - Agile Business Group
# Copyright 2019 Marcelo Frare (Ass. PNLUG - Gruppo Odoo <http://odoo.pnlug.it>)
# Copyright 2019 Stefano Consolaro (Ass. PNLUG - Gruppo Odoo <http://odoo.pnlug.it>)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models
class QcTriggerPartnerLine(models.Model):
"""
Extend quality trigger with partner control plan
"""
_inherit = "qc.trigger.line"
# model
_name = "qc.trigger.partner_line"
# new fields
# reference partner
partner = fields.Many2one(comodel_name="res.partner")
# control plan to use
plan_id = fields.Many2one('qc.plan', 'Plan', required=True)

View File

@@ -0,0 +1,51 @@
# Copyright 2019 Marcelo Frare (Ass. PNLUG - Gruppo Odoo <http://odoo.pnlug.it>)
# Copyright 2019 Stefano Consolaro (Ass. PNLUG - Gruppo Odoo <http://odoo.pnlug.it>)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import models, api
class StockPicking(models.Model):
"""
Extend picking method
"""
_inherit = 'stock.picking'
@api.multi
def action_done(self):
"""
Extend actions on done stock move adding inspection defined on Partner
"""
# does original action and memorize result
result = super(StockPicking, self).action_done()
# gets model of the inspection
inspection_model = self.env['qc.inspection']
# for each line moved
for operation in self.move_lines:
# gets quality trigger associate to movement type
qc_trigger = self.env['qc.trigger'
].search([('picking_type_id',
'=',
self.picking_type_id.id)
])
# gets partner associate to movement
partner = (self.partner_id)
# gets trigger for movement type on partner
trigger_line = self.env['qc.trigger.partner_line'
].search([('partner', '=', partner.id),
('trigger', '=', qc_trigger.id)
],
limit=1
)
# adds new ispection
if trigger_line:
inspection_model._make_inspection(operation, trigger_line)
return result