lims: Typification: add lower and upper limit allowed

This commit is contained in:
Adrián Bernardi 2020-04-17 21:46:31 -03:00
parent 9a077ac237
commit c685ef14dd
14 changed files with 165 additions and 35 deletions

View File

@ -57,6 +57,10 @@ class Typification(ModelSQL, ModelView):
digits=(16, Eval('limit_digits', 2)), depends=['limit_digits'])
quantification_limit = fields.Float('Quantification limit',
digits=(16, Eval('limit_digits', 2)), depends=['limit_digits'])
lower_limit = fields.Float('Lower limit allowed',
digits=(16, Eval('limit_digits', 2)), depends=['limit_digits'])
upper_limit = fields.Float('Upper limit allowed',
digits=(16, Eval('limit_digits', 2)), depends=['limit_digits'])
limit_digits = fields.Integer('Limit digits')
check_result_limits = fields.Boolean(
'Validate limits directly on the result')
@ -274,9 +278,12 @@ class Typification(ModelSQL, ModelView):
t.check_default()
def check_limits(self):
if (self.lower_limit and self.upper_limit and
self.upper_limit <= self.lower_limit):
raise UserError(gettext('lims.msg_invalid_limits_allowed'))
if (self.detection_limit and
self.quantification_limit <= self.detection_limit):
raise UserError(gettext('lims.msg_limits'))
raise UserError(gettext('lims.msg_invalid_limits'))
def check_default(self):
if self.by_default:
@ -412,8 +419,8 @@ class Typification(ModelSQL, ModelView):
cls.delete_typification_calculated(typifications)
fields_check = ('detection_limit', 'quantification_limit',
'initial_concentration', 'final_concentration', 'start_uom',
'end_uom', 'calc_decimals')
'lower_limit', 'upper_limit', 'initial_concentration',
'final_concentration', 'start_uom', 'end_uom', 'calc_decimals')
for field in fields_check:
if field in vals:
cls.update_laboratory_notebook(typifications)
@ -423,6 +430,9 @@ class Typification(ModelSQL, ModelView):
def update_laboratory_notebook(cls, typifications):
NotebookLine = Pool().get('lims.notebook.line')
def _str_value(val=None):
return str(val) if val is not None else None
for typification in typifications:
if not typification.valid:
continue
@ -439,16 +449,20 @@ class Typification(ModelSQL, ModelView):
])
if notebook_lines:
NotebookLine.write(notebook_lines, {
'detection_limit': str(
'detection_limit': _str_value(
typification.detection_limit),
'quantification_limit': str(
'quantification_limit': _str_value(
typification.quantification_limit),
'initial_concentration': str(
typification.initial_concentration or ''),
'final_concentration': str(
typification.final_concentration or ''),
'initial_unit': typification.start_uom,
'final_unit': typification.end_uom,
'lower_limit': _str_value(typification.lower_limit),
'upper_limit': _str_value(typification.upper_limit),
'initial_concentration': _str_value(
typification.initial_concentration),
'final_concentration': _str_value(
typification.final_concentration),
'initial_unit': (typification.start_uom and
typification.start_uom.id or None),
'final_unit': (typification.end_uom and
typification.end_uom.id or None),
'decimals': typification.calc_decimals,
})

View File

@ -864,12 +864,15 @@ class EntryDetailAnalysis(ModelSQL, ModelView):
Notebook = pool.get('lims.notebook')
Company = pool.get('company.company')
def _str_value(val=None):
return str(val) if val is not None else None
lines_create = []
for detail in details:
cursor.execute('SELECT default_repetitions, '
'initial_concentration, final_concentration, start_uom, '
'end_uom, detection_limit, quantification_limit, '
'calc_decimals, report '
'lower_limit, upper_limit, calc_decimals, report '
'FROM "' + Typification._table + '" '
'WHERE product_type = %s '
'AND matrix = %s '
@ -883,14 +886,16 @@ class EntryDetailAnalysis(ModelSQL, ModelView):
else None)
if typification:
repetitions = typification[0]
initial_concentration = str(typification[1] or '')
final_concentration = str(typification[2] or '')
initial_unit = typification[3]
final_unit = typification[4]
detection_limit = str(typification[5])
quantification_limit = str(typification[6])
decimals = typification[7]
report = typification[8]
initial_concentration = _str_value(typification[1])
final_concentration = _str_value(typification[2])
initial_unit = typification[3] or None
final_unit = typification[4] or None
detection_limit = _str_value(typification[5])
quantification_limit = _str_value(typification[6])
lower_limit = _str_value(typification[7])
upper_limit = _str_value(typification[8])
decimals = typification[9]
report = typification[10]
else:
repetitions = 0
initial_concentration = None
@ -899,6 +904,8 @@ class EntryDetailAnalysis(ModelSQL, ModelView):
final_unit = None
detection_limit = None
quantification_limit = None
lower_limit = None
upper_limit = None
decimals = 2
report = False
@ -942,6 +949,8 @@ class EntryDetailAnalysis(ModelSQL, ModelView):
'final_unit': final_unit,
'detection_limit': detection_limit,
'quantification_limit': quantification_limit,
'lower_limit': lower_limit,
'upper_limit': upper_limit,
'decimals': decimals,
'report': report,
'results_estimated_waiting': results_estimated_waiting,

View File

@ -2819,6 +2819,10 @@ msgctxt "field:lims.notebook.line,literal_result:"
msgid "Literal result"
msgstr "Resultado textual"
msgctxt "field:lims.notebook.line,lower_limit:"
msgid "Lower limit allowed"
msgstr "Límite inferior permitido"
msgctxt "field:lims.notebook.line,matrix:"
msgid "Matrix"
msgstr "Matriz"
@ -2919,6 +2923,10 @@ msgctxt "field:lims.notebook.line,rm_correction_formula:"
msgid "RM Correction Formula"
msgstr "Fórmula Corrección RM"
msgctxt "field:lims.notebook.line,sample:"
msgid "Sample"
msgstr "Muestra"
msgctxt "field:lims.notebook.line,service:"
msgid "Service"
msgstr "Servicio"
@ -2935,6 +2943,10 @@ msgctxt "field:lims.notebook.line,uncertainty:"
msgid "Uncertainty"
msgstr "Incertidumbre"
msgctxt "field:lims.notebook.line,upper_limit:"
msgid "Upper limit allowed"
msgstr "Límite superior permitido"
msgctxt "field:lims.notebook.line,urgent:"
msgid "Urgent"
msgstr "Urgente"
@ -3083,6 +3095,10 @@ msgctxt "field:lims.notebook.line.all_fields,literal_result:"
msgid "Literal result"
msgstr "Resultado textual"
msgctxt "field:lims.notebook.line.all_fields,lower_limit:"
msgid "Lower limit allowed"
msgstr "Límite inferior permitido"
msgctxt "field:lims.notebook.line.all_fields,matrix:"
msgid "Matrix"
msgstr "Matriz"
@ -3175,6 +3191,10 @@ msgctxt "field:lims.notebook.line.all_fields,uncertainty:"
msgid "Uncertainty"
msgstr "Incertidumbre"
msgctxt "field:lims.notebook.line.all_fields,upper_limit:"
msgid "Upper limit allowed"
msgstr "Límite superior permitido"
msgctxt "field:lims.notebook.line.all_fields,urgent:"
msgid "Urgent"
msgstr "Urgente"
@ -5406,6 +5426,10 @@ msgctxt "field:lims.typification,limit_digits:"
msgid "Limit digits"
msgstr "Dígitos de límite"
msgctxt "field:lims.typification,lower_limit:"
msgid "Lower limit allowed"
msgstr "Límite inferior permitido"
msgctxt "field:lims.typification,matrix:"
msgid "Matrix"
msgstr "Matriz"
@ -5450,6 +5474,10 @@ msgctxt "field:lims.typification,technical_scope_versions:"
msgid "Technical scope versions"
msgstr "Versiones de alcance técnico"
msgctxt "field:lims.typification,upper_limit:"
msgid "Upper limit allowed"
msgstr "Límite superior permitido"
msgctxt "field:lims.typification,valid:"
msgid "Active"
msgstr "Activo"
@ -6787,6 +6815,10 @@ msgctxt "model:ir.message,text:msg_english_report"
msgid "Do not forget to load the translations into English"
msgstr "No olvide cargar las traducciones al Inglés"
msgctxt "model:ir.message,text:msg_error_limits_allowed"
msgid "The value of line \"%(line)s\" is outside the allowed limits"
msgstr "El valor de la línea \"%(line)s\" está fuera de los límites permitidos"
msgctxt "model:ir.message,text:msg_extra_period"
msgid "Found an extra period in a number at character %(index)s"
msgstr "Encontrada una segunda coma en un número en el caracter %(index)s"
@ -6811,6 +6843,15 @@ msgctxt "model:ir.message,text:msg_fraction_type_code_unique_id"
msgid "Fraction type code must be unique"
msgstr "El código del tipo de fracción debe ser único"
msgctxt "model:ir.message,text:msg_invalid_limits"
msgid "Quantification limit must be greater than Detection limit"
msgstr "El Límite de cuantificación debe ser mayor que el Límite de detección"
msgctxt "model:ir.message,text:msg_invalid_limits_allowed"
msgid "Upper limit allowed must be greater than Lower limit allowed"
msgstr ""
"El Límite superior permitido debe ser mayor que el Límite inferior permitido"
msgctxt "model:ir.message,text:msg_invalid_start_date"
msgid "The start date must be after \"%(date)s\""
msgstr "La fecha de inicio debe ser posterior a «%(date)s»"
@ -6827,10 +6868,6 @@ msgctxt "model:ir.message,text:msg_lcl"
msgid "LCL (M-3D)"
msgstr "LIC (M-3D)"
msgctxt "model:ir.message,text:msg_limits"
msgid "Quantification limit must be greater than Detection limit"
msgstr "El Límite de cuantificación debe ser mayor que el Límite de detección"
msgctxt "model:ir.message,text:msg_line_end_date"
msgid "The end date cannot be lower than start date"
msgstr "La fecha de finalización no puede ser menor que la fecha de inicio"

View File

@ -1,7 +1,10 @@
<?xml version="1.0"?>
<tryton>
<data grouped="1">
<record model="ir.message" id="msg_limits">
<record model="ir.message" id="msg_invalid_limits_allowed">
<field name="text">Upper limit allowed must be greater than Lower limit allowed</field>
</record>
<record model="ir.message" id="msg_invalid_limits">
<field name="text">Quantification limit must be greater than Detection limit</field>
</record>
<record model="ir.message" id="msg_default_typification">
@ -10,6 +13,9 @@
<record model="ir.message" id="msg_not_default_typification">
<field name="text">This typification should be the default</field>
</record>
<record model="ir.message" id="msg_error_limits_allowed">
<field name="text">The value of line "%(line)s" is outside the allowed limits</field>
</record>
<record model="ir.message" id="msg_description_uniq">
<field name="text">Analysis description must be unique</field>
</record>

View File

@ -332,6 +332,10 @@ class NotebookLine(ModelSQL, ModelView):
states={'readonly': Bool(Eval('accepted'))}, depends=['accepted'])
quantification_limit = fields.Char('Quantification limit',
states={'readonly': Bool(Eval('accepted'))}, depends=['accepted'])
lower_limit = fields.Char('Lower limit allowed',
states={'readonly': Bool(Eval('accepted'))}, depends=['accepted'])
upper_limit = fields.Char('Upper limit allowed',
states={'readonly': Bool(Eval('accepted'))}, depends=['accepted'])
check_result_limits = fields.Function(fields.Boolean(
'Validate limits directly on the result'), 'get_typification_field')
chromatogram = fields.Char('Chromatogram')
@ -375,6 +379,8 @@ class NotebookLine(ModelSQL, ModelView):
fraction_type = fields.Function(fields.Many2One('lims.fraction.type',
'Fraction type'), 'get_fraction_field',
searcher='search_fraction_field')
sample = fields.Function(fields.Many2One('lims.sample', 'Sample'),
'get_fraction_field', searcher='search_fraction_field')
party = fields.Function(fields.Many2One('party.party', 'Party'),
'get_fraction_field', searcher='search_fraction_field')
product_type = fields.Function(fields.Many2One('lims.product.type',
@ -988,6 +994,8 @@ class NotebookLineAllFields(ModelSQL, ModelView):
converted_result = fields.Char('Converted result', readonly=True)
detection_limit = fields.Char('Detection limit', readonly=True)
quantification_limit = fields.Char('Quantification limit', readonly=True)
lower_limit = fields.Char('Lower limit allowed', readonly=True)
upper_limit = fields.Char('Upper limit allowed', readonly=True)
chromatogram = fields.Char('Chromatogram', readonly=True)
professionals = fields.Function(fields.One2Many(
'lims.notebook.line.professional', None,
@ -1091,6 +1099,8 @@ class NotebookLineAllFields(ModelSQL, ModelView):
line.converted_result,
line.detection_limit,
line.quantification_limit,
line.lower_limit,
line.upper_limit,
line.dilution_factor,
line.chromatogram,
line.comments,
@ -1552,6 +1562,11 @@ class NotebookLimitsValidation(Wizard):
except (TypeError, ValueError):
continue
ll = (notebook_line.lower_limit and
float(notebook_line.lower_limit) or None)
ul = (notebook_line.upper_limit and
float(notebook_line.upper_limit) or None)
if (notebook_line.result and (
notebook_line.check_result_limits or
not notebook_line.converted_result)):
@ -1561,6 +1576,9 @@ class NotebookLimitsValidation(Wizard):
value = float(notebook_line.result)
except ValueError:
continue
if (ll and value < ll) or (ul and value > ul):
raise UserError(gettext('lims.msg_error_limits_allowed',
line=notebook_line.rec_name))
if dl < value and value < ql:
notebook_line.result = str(ql)
notebook_line.result_modifier = 'low'
@ -1589,6 +1607,9 @@ class NotebookLimitsValidation(Wizard):
value = float(notebook_line.converted_result)
except ValueError:
continue
if (ll and value < ll) or (ul and value > ul):
raise UserError(gettext('lims.msg_error_limits_allowed',
line=notebook_line.rec_name))
if dl < value and value < ql:
notebook_line.converted_result = str(ql)
notebook_line.converted_result_modifier = 'low'
@ -3900,6 +3921,8 @@ class NotebookLineRepeatAnalysis(Wizard):
defaults['final_unit'] = None
defaults['detection_limit'] = None
defaults['quantification_limit'] = None
defaults['lower_limit'] = None
defaults['upper_limit'] = None
else:
defaults['final_concentration'] = (
nline_to_repeat.final_concentration)
@ -3910,6 +3933,8 @@ class NotebookLineRepeatAnalysis(Wizard):
defaults['detection_limit'] = nline_to_repeat.detection_limit
defaults['quantification_limit'] = (
nline_to_repeat.quantification_limit)
defaults['lower_limit'] = nline_to_repeat.lower_limit
defaults['upper_limit'] = nline_to_repeat.upper_limit
to_create.append(defaults)
details_to_update.append(detail_id)

View File

@ -1993,6 +1993,8 @@ class AddFractionControl(Wizard):
nline.final_unit else None),
'detection_limit': nline.detection_limit,
'quantification_limit': nline.quantification_limit,
'lower_limit': nline.lower_limit,
'upper_limit': nline.upper_limit,
'decimals': nline.decimals,
'report': nline.report,
'concentration_level': (nline.concentration_level.id if
@ -2424,6 +2426,8 @@ class AddFractionRMBMZ(Wizard):
'final_unit': None,
'detection_limit': None,
'quantification_limit': None,
'lower_limit': None,
'upper_limit': None,
}
if config.rm_start_uom:
defaults['initial_unit'] = config.rm_start_uom.id
@ -2600,6 +2604,8 @@ class AddFractionRMBMZ(Wizard):
'final_unit': None,
'detection_limit': None,
'quantification_limit': None,
'lower_limit': None,
'upper_limit': None,
}
if config.rm_start_uom:
defaults['initial_unit'] = config.rm_start_uom.id
@ -2662,6 +2668,8 @@ class AddFractionRMBMZ(Wizard):
nline.final_unit else None),
'detection_limit': nline.detection_limit,
'quantification_limit': nline.quantification_limit,
'lower_limit': nline.lower_limit,
'upper_limit': nline.upper_limit,
'decimals': nline.decimals,
'report': nline.report,
'concentration_level': (nline.concentration_level.id if
@ -3454,6 +3462,8 @@ class AddFractionMRT(Wizard):
nline.final_unit else None),
'detection_limit': nline.detection_limit,
'quantification_limit': nline.quantification_limit,
'lower_limit': nline.lower_limit,
'upper_limit': nline.upper_limit,
'decimals': nline.decimals,
'report': nline.report,
'concentration_level': (nline.concentration_level.id if

View File

@ -45,6 +45,10 @@
<field name="detection_limit"/>
<label name="quantification_limit"/>
<field name="quantification_limit"/>
<label name="lower_limit"/>
<field name="lower_limit"/>
<label name="upper_limit"/>
<field name="upper_limit"/>
<label name="dilution_factor"/>
<field name="dilution_factor"/>
<label name="chromatogram"/>

View File

@ -29,6 +29,8 @@
<field name="converted_result"/>
<field name="detection_limit"/>
<field name="quantification_limit"/>
<field name="lower_limit"/>
<field name="upper_limit"/>
<field name="dilution_factor"/>
<field name="chromatogram"/>
<field name="comments"/>

View File

@ -49,6 +49,10 @@
<field name="detection_limit"/>
<label name="quantification_limit"/>
<field name="quantification_limit"/>
<label name="lower_limit"/>
<field name="lower_limit"/>
<label name="upper_limit"/>
<field name="upper_limit"/>
<group col="2" colspan="2" id="check_result_limits">
<label name="check_result_limits"/>
<field name="check_result_limits"/>

View File

@ -25,6 +25,8 @@
<field name="converted_result"/>
<field name="detection_limit"/>
<field name="quantification_limit"/>
<field name="lower_limit"/>
<field name="upper_limit"/>
<field name="check_result_limits"/>
<field name="dilution_factor"/>
<field name="chromatogram"/>

View File

@ -16,6 +16,10 @@
<field name="detection_limit"/>
<label name="quantification_limit"/>
<field name="quantification_limit"/>
<label name="lower_limit"/>
<field name="lower_limit"/>
<label name="upper_limit"/>
<field name="upper_limit"/>
<label name="initial_concentration"/>
<field name="initial_concentration"/>
<label name="start_uom"/>

View File

@ -6,6 +6,8 @@
<field name="method_view"/>
<field name="detection_limit"/>
<field name="quantification_limit"/>
<field name="lower_limit"/>
<field name="upper_limit"/>
<field name="initial_concentration"/>
<field name="start_uom"/>
<field name="final_concentration"/>

View File

@ -438,6 +438,8 @@ class AddControl(Wizard):
'final_unit': None,
'detection_limit': None,
'quantification_limit': None,
'lower_limit': None,
'upper_limit': None,
}
if config.rm_start_uom:
defaults['initial_unit'] = config.rm_start_uom.id
@ -663,6 +665,8 @@ class RepeatAnalysis(Wizard):
nline_to_repeat.final_unit else None),
'detection_limit': nline_to_repeat.detection_limit,
'quantification_limit': nline_to_repeat.quantification_limit,
'lower_limit': nline_to_repeat.lower_limit,
'upper_limit': nline_to_repeat.upper_limit,
'start_date': date,
}
to_create.append(defaults)

View File

@ -285,6 +285,9 @@ class EntryDetailAnalysis(metaclass=PoolMeta):
Notebook = pool.get('lims.notebook')
Company = pool.get('company.company')
def _str_value(val=None):
return str(val) if val is not None else None
lines_create = []
template_id = None
@ -294,7 +297,7 @@ class EntryDetailAnalysis(metaclass=PoolMeta):
query = 'SELECT default_repetitions, ' \
'initial_concentration, final_concentration, start_uom, ' \
'end_uom, detection_limit, quantification_limit, ' \
'calc_decimals, report, id ' \
'lower_limit, upper_limit, calc_decimals, report, id ' \
'FROM "' + Typification._table + '" ' \
'WHERE product_type = %s ' \
'AND matrix = %s ' \
@ -316,14 +319,16 @@ class EntryDetailAnalysis(metaclass=PoolMeta):
else None)
if typification:
repetitions = typification[0]
initial_concentration = str(typification[1] or '')
final_concentration = str(typification[2] or '')
initial_unit = typification[3]
final_unit = typification[4]
detection_limit = str(typification[5])
quantification_limit = str(typification[6])
decimals = typification[7]
report = typification[8]
initial_concentration = _str_value(typification[1])
final_concentration = _str_value(typification[2])
initial_unit = typification[3] or None
final_unit = typification[4] or None
detection_limit = _str_value(typification[5])
quantification_limit = _str_value(typification[6])
lower_limit = _str_value(typification[7])
upper_limit = _str_value(typification[8])
decimals = typification[9]
report = typification[10]
else:
repetitions = 0
initial_concentration = None
@ -332,6 +337,8 @@ class EntryDetailAnalysis(metaclass=PoolMeta):
final_unit = None
detection_limit = None
quantification_limit = None
lower_limit = None
upper_limit = None
decimals = 2
report = False
@ -380,7 +387,7 @@ class EntryDetailAnalysis(metaclass=PoolMeta):
'department': department,
}
if template_id:
quality_typification = Typification(typification[9])
quality_typification = Typification(typification[11])
notebook_line['typification'] = quality_typification.id
notebook_line['test_value'] = \
quality_typification.valid_value.id \