trytond-quality_control/quality.py

475 lines
16 KiB
Python

# The COPYRIGHT file at the top level of this repository contains the full
# copyright notices and license terms. """
import datetime
from trytond.model import Workflow, ModelView, ModelSQL, fields
from trytond.pyson import Eval, Bool, Equal, Not, Or
from trytond.transaction import Transaction
from trytond.pool import Pool, PoolMeta
__all__ = ['Proof', 'ProofMethod', 'QualitativeValue', 'Template',
'QualitativeTemplateLine', 'QuantitativeTemplateLine', 'QualityTest',
'QuantitativeTestLine', 'QualitativeTestLine']
__metaclass__ = PoolMeta
_PROOF_TYPES = [
('qualitative', 'Qualitative'),
('quantitative', 'Quantitative')
]
_TEST_STATE = [
('draft', 'Draft'),
('confirmed', 'Confirmed'),
('successful', 'Successful'),
('failed', 'Failed'),
]
_STATES = {
'readonly': Eval('state') != 'draft',
}
class Proof(ModelSQL, ModelView):
'Quality Proof'
__name__ = 'quality.proof'
name = fields.Char('Name', required=True, translate=True,
select=True)
active = fields.Boolean('Active', select=True)
company = fields.Many2One('company.company', 'Company', required=True,
select=True)
type = fields.Selection(_PROOF_TYPES, 'Type', required=True)
methods = fields.One2Many('quality.proof.method', 'proof', 'Methods',
required=True)
@staticmethod
def default_active():
""" Return default value 'True' for active field """
return True
@staticmethod
def default_company():
""" Return default company value, context setted for company field """
return Transaction().context.get('company')
class ProofMethod(ModelSQL, ModelView):
'Quality Proof Method'
__name__ = 'quality.proof.method'
name = fields.Char('Name', required=True, translate=True,
select=True)
active = fields.Boolean('Active', select=True)
company = fields.Many2One('company.company', 'Company', required=True,
select=True)
proof = fields.Many2One('quality.proof', 'Proof', required=True)
proof_type = fields.Function(fields.Selection(_PROOF_TYPES, 'Proof Type',
on_change_with=['proof']), 'on_change_with_proof_type')
possible_values = fields.One2Many('quality.qualitative.value', 'method',
'Possible Values',
states={
'readonly': Equal(Eval('proof_type'), 'quantitative'),
'required': Equal(Eval('proof_type'), 'qualitative'),
}, depends=['proof', 'proof_type'])
def on_change_with_proof_type(self, name=None):
return self.proof and self.proof.type
@staticmethod
def default_active():
return True
@staticmethod
def default_company():
return Transaction().context.get('company')
class QualitativeValue(ModelSQL, ModelView):
'Quality Value'
__name__ = 'quality.qualitative.value'
name = fields.Char('Name', required=True, translate=True,
select=True)
active = fields.Boolean('Active', select=True)
method = fields.Many2One('quality.proof.method', 'Method', required=True)
@staticmethod
def default_active():
return True
class Template(ModelSQL, ModelView):
'Quality Template'
__name__ = 'quality.template'
name = fields.Char('Name', required=True, translate=True,
select=True)
active = fields.Boolean('Active', select=True)
company = fields.Many2One('company.company', 'Company', required=True,
select=True)
document = fields.Reference('Document', selection='get_model',
required=True)
internal_description = fields.Text('Internal Description')
external_description = fields.Text('External Description')
quantitative_lines = fields.One2Many('quality.quantitative.template.line',
'template', 'Quantitative Lines')
qualitative_lines = fields.One2Many('quality.qualitative.template.line',
'template', 'Qualitative Lines')
test = fields.One2Many('quality.test', 'template', 'Quality Test')
@classmethod
def get_model(cls):
pool = Pool()
ConfigLine = pool.get('quality.configuration.line')
lines = ConfigLine.search([])
res = [(None, '')]
for line in lines:
res.append((line.document.model, line.document.name))
return res
@staticmethod
def default_active():
return True
@staticmethod
def default_company():
return Transaction().context.get('company')
class QualitativeTemplateLine(ModelSQL, ModelView):
'Quality Qualitative Template Line'
__name__ = 'quality.qualitative.template.line'
template = fields.Many2One('quality.template', 'Template',
ondelete='CASCADE', select=True, required=True)
name = fields.Char('Name', required=True, translate=True, select=True)
active = fields.Boolean('Active', select=True)
proof = fields.Many2One('quality.proof', 'Proof', required=True)
method = fields.Many2One('quality.proof.method', 'Method', required=True,
domain=[('proof', '=', Eval('proof'))], depends=['proof'])
valid_value = fields.Many2One('quality.qualitative.value', 'Valid Value',
required=True, domain=[('method', '=', Eval('method'))],
depends=['method'])
internal_description = fields.Text('Internal Description')
external_description = fields.Text('External Description')
@staticmethod
def default_active():
""" Return default value 'True' for active field """
return True
class QuantitativeTemplateLine(ModelSQL, ModelView):
'Quality Quantitative Template Line'
__name__ = 'quality.quantitative.template.line'
template = fields.Many2One('quality.template', 'Template',
ondelete='CASCADE', select=True, required=True)
name = fields.Char('Name', required=True, translate=True, select=True)
active = fields.Boolean('Active', select=True)
proof = fields.Many2One('quality.proof', 'Proof', required=True)
method = fields.Many2One('quality.proof.method', 'Method', required=True,
domain=[('proof', '=', Eval('proof'))], depends=['proof'])
internal_description = fields.Text('Internal Description')
external_description = fields.Text('External Description')
min_value = fields.Float('Min Value', digits=(16, Eval('unit_digits', 2)),
required=True, depends=['unit_digits'])
max_value = fields.Float('Max Value', digits=(16, Eval('unit_digits', 2)),
required=True, depends=['unit_digits'])
unit = fields.Many2One('product.uom', 'Unit', required=True)
unit_digits = fields.Function(fields.Integer('Unit Digits',
on_change_with=['unit']), 'on_change_with_unit_digits')
@staticmethod
def default_active():
return True
def on_change_with_unit_digits(self, name=None):
if not self.unit:
return 2
return self.unit.digits
class QualityTest(Workflow, ModelSQL, ModelView):
'Quality Test'
__name__ = 'quality.test'
_rec_name = 'number'
number = fields.Char('Number', readonly=True, select=True,
states={'required': Not(Equal(Eval('state'), 'draft'))})
active = fields.Boolean('Active', select=True)
company = fields.Many2One('company.company', 'Company', required=True,
select=True)
document = fields.Reference('Document', selection='get_model',
required=True)
test_date = fields.DateTime('Date')
internal_description = fields.Text('Internal Description')
external_description = fields.Text('External Description')
quantitative_lines = fields.One2Many('quality.quantitative.test.line',
'test', 'Quantitative Lines', states=_STATES, depends=['state'])
qualitative_lines = fields.One2Many('quality.qualitative.test.line',
'test', 'Qualitative Lines', states=_STATES, depends=['state'])
template = fields.Many2One('quality.template', 'Template')
success = fields.Function(fields.Boolean('Success'), 'get_success')
state = fields.Selection(_TEST_STATE, 'State',
readonly=True, required=True)
@classmethod
def get_model(cls):
pool = Pool()
ConfigLines = pool.get('quality.configuration.line')
lines = ConfigLines.search([])
res = [(None, '')]
for line in lines:
res.append((line.document.model, line.document.name))
return res
def get_success(self, name):
for line in self.quantitative_lines:
if not line.success:
return False
for line in self.qualitative_lines:
if not line.success:
return False
return True
@classmethod
def __setup__(cls):
super(QualityTest, cls).__setup__()
cls._transitions |= set((
('draft', 'confirmed'),
('confirmed', 'draft'),
('confirmed', 'successful'),
('confirmed', 'failed'),
('successful', 'draft'),
('failed', 'draft'),
))
cls._buttons.update({
'confirmed': {
'invisible': (Eval('state') != 'draft'),
},
'manager_validate': {
'invisible': (Eval('state') != 'confirmed'),
},
'draft': {
'invisible': (Eval('state') == 'draft'),
},
'set_template': {
'readonly': Or(Not(Equal(Eval('state'), 'draft')),
Not(Bool(Eval('template')))),
},
})
@staticmethod
def default_test_date():
return datetime.datetime.now()
@staticmethod
def default_state():
return 'draft'
@staticmethod
def default_active():
return True
@staticmethod
def default_company():
return Transaction().context.get('company')
@classmethod
@ModelView.button
@Workflow.transition('draft')
def draft(cls, tests):
pass
@classmethod
@ModelView.button
@Workflow.transition('confirmed')
def confirmed(cls, tests):
cls.set_number(tests)
@classmethod
@Workflow.transition('successful')
def successful(cls, tests):
pass
@classmethod
@Workflow.transition('failed')
def failed(cls, tests):
pass
@classmethod
@ModelView.button
def manager_validate(cls, tests):
for test in tests:
if test.success:
cls.successful(tests)
else:
cls.failed(tests)
@classmethod
def set_number(cls, tests):
pool = Pool()
ConfigLine = pool.get('quality.configuration.line')
Model = pool.get('ir.model')
Sequence = pool.get('ir.sequence')
for test in tests:
doc = str(test.document).split(',')[0]
model, = Model.search([('model', '=', doc)])
config, = ConfigLine.search([('document', '=', model.id)])
sequence = config.quality_sequence
test.number = Sequence.get_id(sequence.id)
test.save()
def set_template_vals(self):
pool = Pool()
QualitativeLine = pool.get('quality.qualitative.test.line')
QuantitativeLine = pool.get('quality.quantitative.test.line')
ql_lines = []
for ql in self.template.qualitative_lines:
line = QualitativeLine()
line.set_template_line_vals(ql)
ql_lines.append(line)
self.qualitative_lines = ql_lines
qt_lines = []
for qt in self.template.quantitative_lines:
line = QuantitativeLine()
line.set_template_line_vals(qt)
qt_lines.append(line)
self.quantitative_lines = qt_lines
@classmethod
@ModelView.button
def set_template(cls, tests):
for test in tests:
test.set_template_vals()
test.save()
class QualitativeTestLine(ModelSQL, ModelView):
'Quality Qualitative Line'
__name__ = 'quality.qualitative.test.line'
test = fields.Many2One('quality.test', 'Test',
ondelete='CASCADE', select=True)
test_state = fields.Function(fields.Selection(_TEST_STATE, 'Test State'),
'get_test_state')
template_line = fields.Many2One('quality.qualitative.template.line',
'Template Line')
name = fields.Char('Name', required=True, translate=True, select=True)
proof = fields.Many2One('quality.proof', 'Proof',
states={
'readonly': Bool(Eval('template_line')),
}, required=True, depends=['template_line'])
method = fields.Many2One('quality.proof.method', 'Method',
states={
'readonly': Bool(Eval('template_line')),
}, required=True, depends=['template_line'])
internal_description = fields.Text('Internal Description')
external_description = fields.Text('External Description')
test_value = fields.Many2One('quality.qualitative.value', 'Test Value',
states={
'readonly': Bool(Eval('template_line')),
}, required=True, depends=['template_line'])
value = fields.Many2One('quality.qualitative.value', 'Value')
success = fields.Function(fields.Boolean('Success'), 'get_success')
def on_change_with_unit_digits(self, name=None):
if not self.unit:
return 2
return self.unit.digits
def get_success(self, name=None):
if self.value == self.test_value:
return True
return False
def test_state(self):
return self.test.state
def set_template_line_vals(self, template_line):
self.name = template_line.name
self.proof = template_line.proof
self.method = template_line.method
self.internal_description = template_line.internal_description
self.external_description = template_line.external_description
self.test_value = template_line.valid_value
class QuantitativeTestLine(ModelSQL, ModelView):
'Quality Quantitative Line'
__name__ = 'quality.quantitative.test.line'
test = fields.Many2One('quality.test', 'Test',
ondelete='CASCADE', select=True, required=True)
test_state = fields.Function(fields.Selection(_TEST_STATE, 'Test State'),
'get_test_state')
template_line = fields.Many2One('quality.quantitative.template.line',
'Template Line')
name = fields.Char('Name', required=True, translate=True, select=True)
proof = fields.Many2One('quality.proof', 'Proof', required=True)
method = fields.Many2One('quality.proof.method', 'Method', required=True)
internal_description = fields.Text('Internal Description')
external_description = fields.Text('External Description')
min_value = fields.Float('Min Value', digits=(16, Eval('unit_digits', 2)),
states = {
'readonly': Bool(Eval('template_line')),
}, required=True, depends=['template_line', 'unit_digits'])
max_value = fields.Float('Max Value', digits=(16, Eval('unit_digits', 2)),
states = {
'readonly': Bool(Eval('template_line')),
}, required=True, depends=['unit_digits'])
unit_range = fields.Many2One('product.uom', 'Unit Range',
states={
'readonly': Bool(Eval('template_line')),
}, required=True)
unit_digits = fields.Function(fields.Integer('Unit Digits',
on_change_with=['unit']), 'on_change_with_unit_digits')
value = fields.Float('Value', digits=(16, Eval('unit_digits', 2)),
depends=['unit_digits', 'test_state'])
unit = fields.Many2One('product.uom', 'Unit',
states={
'required': Bool(Eval('value')),
})
success = fields.Function(fields.Boolean('Success'), 'get_success')
@classmethod
def get_success(self, lines, name):
res = {}
pool = Pool()
Uom = pool.get('product.uom')
for line in lines:
res[line.id] = False
value = line.value
value = Uom.compute_qty(line.unit, value, line.unit_range)
if value >= line.min_value and value <= line.max_value:
res[line.id] = True
return res
@classmethod
def get_test_state(self, lines, name):
res = {}
for line in lines:
res[line.id] = line.test.state
return res
def on_change_with_unit_digits(self, name=None):
if not self.unit:
return 2
return self.unit.digits
def set_template_line_vals(self, template_line):
self.name = template_line.name
self.proof = template_line.proof
self.method = template_line.method
self.internal_description = template_line.internal_description
self.external_description = template_line.external_description
self.min_value = template_line.min_value
self.max_value = template_line.max_value
self.unit_range = template_line.unit