Update to 5.2

This commit is contained in:
Sebastián Marró 2019-07-23 18:27:33 -03:00
parent 82df43a145
commit 8d566322e0
57 changed files with 1001 additions and 1066 deletions

View File

@ -38,6 +38,7 @@ def register():
configuration.ConfigurationProductCategory,
configuration.LabWorkYear,
configuration.LabWorkYearSequence,
configuration.Cron,
configuration.ModelDoc,
configuration.Model,
laboratory.LaboratoryProfessional,

View File

@ -13,6 +13,8 @@ from trytond.wizard import Wizard, StateTransition, StateView, StateAction, \
from trytond.pool import Pool
from trytond.transaction import Transaction
from trytond.pyson import PYSONEncoder, Eval, Equal, Bool, Not, Or, And
from trytond.exceptions import UserError
from trytond.i18n import gettext
__all__ = ['ProductType', 'Matrix', 'ObjectiveDescription', 'Formula',
'FormulaVariable', 'Analysis', 'Typification', 'TypificationAditional',
@ -109,14 +111,6 @@ class Typification(ModelSQL, ModelView):
Unique(t, t.product_type, t.matrix, t.analysis, t.method),
'This typification already exists'),
]
cls._error_messages.update({
'limits': ('Quantification limit must be greater than'
' Detection limit'),
'default_typification': ('There is already a default typification'
' for this combination of product type, matrix and analysis'),
'not_default_typification': ('This typification should be the'
' default'),
})
@staticmethod
def default_limit_digits():
@ -270,7 +264,7 @@ class Typification(ModelSQL, ModelView):
def check_limits(self):
if (self.detection_limit and
self.quantification_limit <= self.detection_limit):
self.raise_user_error('limits')
raise UserError(gettext('lims.lims.msg_limits'))
def check_default(self):
if self.by_default:
@ -283,7 +277,7 @@ class Typification(ModelSQL, ModelView):
('id', '!=', self.id),
])
if typifications:
self.raise_user_error('default_typification')
raise UserError(gettext('lims.lims.msg_default_typification'))
else:
if self.valid:
typifications = self.search([
@ -294,7 +288,8 @@ class Typification(ModelSQL, ModelView):
('id', '!=', self.id),
])
if not typifications:
self.raise_user_error('not_default_typification')
raise UserError(
gettext('lims.msg_not_default_typification'))
@classmethod
def create(cls, vlist):
@ -897,20 +892,6 @@ class Analysis(Workflow, ModelSQL, ModelView):
('code_uniq', Unique(t, t.code),
'Analysis code must be unique'),
]
cls._error_messages.update({
'description_uniq': 'Analysis description must be unique',
'not_laboratory': 'Must define a Laboratory',
'set_laboratories': ('A Set can be assigned to a single'
' laboratory'),
'analysis_laboratory': ('The "%(analysis)s" analysis is not'
' defined in laboratory "%(laboratory)s"'),
'not_laboratory_change': ('You can not change the laboratory'
' because the analysis is included in a set/group with this'
' laboratory'),
'end_date': 'The leaving date cannot be lower than entry date',
'end_date_wrong': ('End date should not be greater than the '
'current date'),
})
cls._transitions |= set((
('draft', 'active'),
('active', 'disabled'),
@ -1079,31 +1060,31 @@ class Analysis(Workflow, ModelSQL, ModelView):
('type', '=', type),
('end_date', '=', None),
]) > count:
cls.raise_user_error('description_uniq')
raise UserError(gettext('lims.msg_description_uniq'))
def check_set(self):
if self.type == 'set':
if self.laboratories and len(self.laboratories) > 1:
self.raise_user_error('set_laboratories')
raise UserError(gettext('lims.msg_set_laboratories'))
if self.included_analysis and not self.laboratories:
self.raise_user_error('not_laboratory')
raise UserError(gettext('lims.msg_not_laboratory'))
if self.included_analysis:
set_laboratory = self.laboratories[0].laboratory
for ia in self.included_analysis:
included_analysis_laboratories = [lab.laboratory
for lab in ia.included_analysis.laboratories]
if (set_laboratory not in included_analysis_laboratories):
self.raise_user_error('analysis_laboratory', {
'analysis': ia.included_analysis.rec_name,
'laboratory': set_laboratory.rec_name,
})
raise UserError(gettext('lims.msg_analysis_laboratory',
analysis=ia.included_analysis.rec_name,
laboratory=set_laboratory.rec_name,
))
def check_end_date(self):
if self.end_date:
if not self.start_date or self.end_date < self.start_date:
self.raise_user_error('end_date')
raise UserError(gettext('lims.msg_end_date'))
if not self.start_date or self.end_date > datetime.now().date():
self.raise_user_error('end_date_wrong')
raise UserError(gettext('lims.msg_end_date_wrong'))
@classmethod
def write(cls, *args):
@ -1131,7 +1112,8 @@ class Analysis(Workflow, ModelSQL, ModelView):
('laboratory', '=', laboratory),
])
if parent:
cls.raise_user_error('not_laboratory_change')
raise UserError(
gettext('lims.msg_not_laboratory_change'))
@classmethod
@ModelView.button_action('lims.wiz_lims_relate_analysis')
@ -1529,14 +1511,6 @@ class AnalysisIncluded(ModelSQL, ModelView):
laboratory_domain = fields.Function(fields.Many2Many('lims.laboratory',
None, None, 'Laboratory domain'), 'on_change_with_laboratory_domain')
@classmethod
def __setup__(cls):
super(AnalysisIncluded, cls).__setup__()
cls._error_messages.update({
'duplicated_analysis': 'The analysis "%s" is already included',
'not_set_laboratory': 'No Laboratory loaded for the Set',
})
@classmethod
def validate(cls, included_analysis):
super(AnalysisIncluded, cls).validate(included_analysis)
@ -1559,8 +1533,8 @@ class AnalysisIncluded(ModelSQL, ModelView):
analysis_ids.extend(Analysis.get_included_analysis(
ai.included_analysis.id))
if self.included_analysis.id in analysis_ids:
self.raise_user_error('duplicated_analysis',
(self.included_analysis.rec_name,))
raise UserError(gettext('lims.msg_duplicated_analysis',
analysis=self.included_analysis.rec_name))
@fields.depends('included_analysis', 'analysis', 'laboratory',
'_parent_analysis.type', '_parent_analysis.laboratories')
@ -1606,7 +1580,6 @@ class AnalysisIncluded(ModelSQL, ModelView):
laboratories=[]):
cursor = Transaction().connection.cursor()
pool = Pool()
AnalysisIncluded = pool.get('lims.analysis.included')
Analysis = pool.get('lims.analysis')
AnalysisLaboratory = pool.get('lims.analysis-laboratory')
@ -1615,7 +1588,7 @@ class AnalysisIncluded(ModelSQL, ModelView):
if analysis_type == 'set':
if len(laboratories) != 1:
AnalysisIncluded.raise_user_error('not_set_laboratory')
raise UserError(gettext('lims.msg_not_set_laboratory'))
set_laboratory_id = laboratories[0]
not_parent_clause = ''
if analysis_id:
@ -1882,14 +1855,6 @@ class AnalysisLabMethod(ModelSQL):
method = fields.Many2One('lims.lab.method', 'Method',
ondelete='CASCADE', select=True, required=True)
@classmethod
def __setup__(cls):
super(AnalysisLabMethod, cls).__setup__()
cls._error_messages.update({
'typificated_method': ('You can not delete method "%s" because '
'is typificated'),
})
@classmethod
def delete(cls, methods):
cls.check_delete(methods)
@ -1905,8 +1870,8 @@ class AnalysisLabMethod(ModelSQL):
('valid', '=', True),
])
if typifications != 0:
cls.raise_user_error('typificated_method',
(method.method.code,))
raise UserError(gettext('lims.msg_typificated_method',
method=method.method.code))
class AnalysisDevice(ModelSQL, ModelView):
@ -1926,14 +1891,6 @@ class AnalysisDevice(ModelSQL, ModelView):
depends=['laboratory'])
by_default = fields.Boolean('By default')
@classmethod
def __setup__(cls):
super(AnalysisDevice, cls).__setup__()
cls._error_messages.update({
'default_device': ('There is already a default device for this'
' analysis on this laboratory'),
})
@staticmethod
def default_by_default():
return True
@ -1953,7 +1910,7 @@ class AnalysisDevice(ModelSQL, ModelView):
('id', '!=', self.id),
])
if devices:
self.raise_user_error('default_device')
raise UserError(gettext('lims.msg_default_device'))
@staticmethod
def default_laboratory_domain():
@ -2211,13 +2168,6 @@ class RelateAnalysis(Wizard):
])
relate = StateTransition()
@classmethod
def __setup__(cls):
super(RelateAnalysis, cls).__setup__()
cls._error_messages.update({
'not_set_laboratory': 'No Laboratory loaded for the Set',
})
def default_start(self, fields):
cursor = Transaction().connection.cursor()
pool = Pool()
@ -2229,7 +2179,7 @@ class RelateAnalysis(Wizard):
'analysis_domain': [],
}
if len(analysis.laboratories) != 1:
self.raise_user_error('not_set_laboratory')
raise UserError(gettext('lims.msg_not_set_laboratory'))
cursor.execute('SELECT DISTINCT(al.analysis) '
'FROM "' + AnalysisLaboratory._table + '" al '

View File

@ -7,6 +7,8 @@ from trytond.wizard import Wizard, StateTransition, StateView, Button
from trytond.pyson import Eval
from trytond.pool import Pool
from trytond.transaction import Transaction
from trytond.exceptions import UserError
from trytond.i18n import gettext
__all__ = ['CertificationType', 'TechnicalScope', 'TechnicalScopeVersion',
'TechnicalScopeVersionLine', 'AnalysisFamily', 'AnalysisFamilyCertificant',
@ -76,10 +78,6 @@ class TechnicalScopeVersion(ModelSQL, ModelView):
@classmethod
def __setup__(cls):
super(TechnicalScopeVersion, cls).__setup__()
cls._error_messages.update({
'active_version': ('Only one version can be active for each '
'technical scope'),
})
cls._buttons.update({
'open_typifications': {},
'add_typifications': {
@ -108,7 +106,7 @@ class TechnicalScopeVersion(ModelSQL, ModelView):
('id', '!=', self.id),
])
if versions:
self.raise_user_error('active_version')
raise UserError(gettext('lims.msg_active_version'))
@classmethod
@ModelView.button_action('lims.act_open_typifications')

View File

@ -9,12 +9,14 @@ from trytond.transaction import Transaction
from trytond.pool import Pool, PoolMeta
from trytond.modules.company.model import (
CompanyMultiValueMixin, CompanyValueMixin)
from trytond.exceptions import UserError
from trytond.i18n import gettext
__all__ = ['NotebookView', 'NotebookViewColumn', 'UserRole', 'UserRoleGroup',
'Printer', 'User', 'UserLaboratory', 'Configuration',
'ConfigurationLaboratory', 'ConfigurationSequence',
'ConfigurationProductCategory', 'LabWorkYear', 'LabWorkYearSequence',
'ModelDoc', 'Model']
'Cron', 'ModelDoc', 'Model']
sequence_names = [
'entry_sequence', 'sample_sequence', 'service_sequence',
'results_report_sequence']
@ -428,11 +430,6 @@ class LabWorkYear(ModelSQL, ModelView, CompanyMultiValueMixin):
def __setup__(cls):
super(LabWorkYear, cls).__setup__()
cls._order.insert(0, ('start_date', 'ASC'))
cls._error_messages.update({
'workyear_overlaps': ('Work year "%(first)s" and '
'"%(second)s" overlap.'),
'no_workyear_date': 'No work year defined for "%s".',
})
@classmethod
def multivalue_model(cls, field):
@ -476,10 +473,10 @@ class LabWorkYear(ModelSQL, ModelView, CompanyMultiValueMixin):
second_id = cursor.fetchone()
if second_id:
second = self.__class__(second_id[0])
self.raise_user_error('workyear_overlaps', {
'first': self.rec_name,
'second': second.rec_name,
})
raise UserError(gettext('lims.msg_workyear_overlaps',
first=self.rec_name,
second=second.rec_name,
))
@classmethod
def find(cls, date=None, exception=True):
@ -497,7 +494,8 @@ class LabWorkYear(ModelSQL, ModelView, CompanyMultiValueMixin):
if exception:
lang = Lang.get()
formatted = lang.strftime(date)
cls.raise_user_error('no_workyear_date', (formatted,))
raise UserError(gettext(
'lims.msg_no_workyear_date', date=formatted))
else:
return None
return workyears[0].id
@ -563,6 +561,22 @@ class LabWorkYearSequence(ModelSQL, CompanyValueMixin):
return None
class Cron(metaclass=PoolMeta):
__name__ = 'ir.cron'
@classmethod
def __setup__(cls):
super().__setup__()
cls.method.selection.extend([
('lims.entry|cron_acknowledgment_of_receipt',
"Lims Acknowledgment of Receipt (Samples)"),
('lims.fraction|confirm_waiting_fractions',
"Lims Confirm Waiting Entries"),
('lims.planification|process_waiting_planifications',
"Lims Process Waiting Planification"),
])
class ModelDoc(ModelSQL, ModelView):
'Model Doc'
__name__ = 'ir.model.doc'

View File

@ -13,6 +13,8 @@ from trytond.pyson import PYSONEncoder, Eval, Bool
from trytond.pool import Pool
from trytond.transaction import Transaction
from trytond.report import Report
from trytond.exceptions import UserError
from trytond.i18n import gettext
__all__ = ['RangeType', 'Range', 'ControlTendency', 'ControlTendencyDetail',
'ControlTendencyDetailRule', 'MeansDeviationsCalcStart',
@ -52,15 +54,6 @@ class RangeType(ModelSQL, ModelView):
translate=True, states={'invisible': Eval('use') != 'result_range'},
depends=['use'])
@classmethod
def __setup__(cls):
super(RangeType, cls).__setup__()
cls._error_messages.update({
'default_range_type':
'There is already a default origin'
' for this use',
})
@staticmethod
def default_by_default():
return False
@ -79,7 +72,7 @@ class RangeType(ModelSQL, ModelView):
('id', '!=', self.id),
])
if range_types:
self.raise_user_error('default_range_type')
raise UserError(gettext('lims.msg_default_range_type'))
class Range(ModelSQL, ModelView):
@ -1209,22 +1202,6 @@ class PrintControlChart(Wizard):
return 'start'
return 'end'
@classmethod
def __setup__(cls):
super(PrintControlChart, cls).__setup__()
cls._error_messages.update({
'number': 'Measurement',
'result': 'Result',
'ucl': 'UCL (M+3D)',
'uwl': 'UWL (M+2D)',
'upl': 'UPL (M+D)',
'cl': 'CL (M)',
'lpl': 'LPL (M-D)',
'lwl': 'LWL (M-2D)',
'lcl': 'LCL (M-3D)',
'cv': 'CV (%)',
})
class ControlChartReport(Report):
'Control Chart'
@ -1258,31 +1235,19 @@ class ControlChartReport(Report):
@classmethod
def _get_objects(cls, tendency):
pool = Pool()
PrintControlChart = pool.get('lims.control_chart.print',
type='wizard')
objects = {
'number': {'name': PrintControlChart.raise_user_error('number',
raise_exception=False), 'order': 1, 'recs': {}},
'result': {'name': PrintControlChart.raise_user_error('result',
raise_exception=False), 'order': 2, 'recs': {}},
'ucl': {'name': PrintControlChart.raise_user_error('ucl',
raise_exception=False), 'order': 3, 'recs': {}},
'uwl': {'name': PrintControlChart.raise_user_error('uwl',
raise_exception=False), 'order': 4, 'recs': {}},
'upl': {'name': PrintControlChart.raise_user_error('upl',
raise_exception=False), 'order': 5, 'recs': {}},
'cl': {'name': PrintControlChart.raise_user_error('cl',
raise_exception=False), 'order': 6, 'recs': {}},
'lpl': {'name': PrintControlChart.raise_user_error('lpl',
raise_exception=False), 'order': 7, 'recs': {}},
'lwl': {'name': PrintControlChart.raise_user_error('lwl',
raise_exception=False), 'order': 8, 'recs': {}},
'lcl': {'name': PrintControlChart.raise_user_error('lcl',
raise_exception=False), 'order': 9, 'recs': {}},
'cv': {'name': PrintControlChart.raise_user_error('cv',
raise_exception=False), 'order': 10, 'recs': {}},
'number': {
'name': gettext('lims.msg_number'), 'order': 1, 'recs': {}},
'result': {
'name': gettext('lims.msg_result'), 'order': 2, 'recs': {}},
'ucl': {'name': gettext('lims.msg_ucl'), 'order': 3, 'recs': {}},
'uwl': {'name': gettext('lims.msg_uwl'), 'order': 4, 'recs': {}},
'upl': {'name': gettext('lims.msg_upl'), 'order': 5, 'recs': {}},
'cl': {'name': gettext('lims.msg_cl'), 'order': 6, 'recs': {}},
'lpl': {'name': gettext('lims.msg_lpl'), 'order': 7, 'recs': {}},
'lwl': {'name': gettext('lims.msg_lwl'), 'order': 8, 'recs': {}},
'lcl': {'name': gettext('lims.msg_lcl'), 'order': 9, 'recs': {}},
'cv': {'name': gettext('lims.msg_cv'), 'order': 10, 'recs': {}},
}
count = 1
for detail in tendency.details:
@ -1303,9 +1268,6 @@ class ControlChartReport(Report):
def _get_plot(cls, columns, records):
if not CAN_PLOT:
return None
pool = Pool()
PrintControlChart = pool.get('lims.control_chart.print',
type='wizard')
index = columns
cols = []
@ -1317,44 +1279,28 @@ class ControlChartReport(Report):
df = df.reindex_axis(cols, axis=1)
try:
ax = df[[
PrintControlChart.raise_user_error('ucl',
raise_exception=False),
ax = df[[gettext('lims.msg_ucl'),
]].plot(kind='line', color='red', rot=45, fontsize=7,
figsize=(10, 7.5), linestyle='-')
ax = df[[
PrintControlChart.raise_user_error('uwl',
raise_exception=False),
ax = df[[gettext('lims.msg_uwl'),
]].plot(kind='line', color='orange', rot=45, fontsize=7,
figsize=(10, 7.5), linestyle='-', ax=ax)
ax = df[[
PrintControlChart.raise_user_error('upl',
raise_exception=False),
ax = df[[gettext('lims.msg_upl'),
]].plot(kind='line', color='yellow', rot=45, fontsize=7,
figsize=(10, 7.5), linestyle='--', ax=ax)
ax = df[[
PrintControlChart.raise_user_error('cl',
raise_exception=False),
ax = df[[gettext('lims.msg_cl'),
]].plot(kind='line', color='green', rot=45, fontsize=7,
figsize=(10, 7.5), linestyle='-', ax=ax)
ax = df[[
PrintControlChart.raise_user_error('lpl',
raise_exception=False),
ax = df[[gettext('lims.msg_lpl'),
]].plot(kind='line', color='yellow', rot=45, fontsize=7,
figsize=(10, 7.5), linestyle='--', ax=ax)
ax = df[[
PrintControlChart.raise_user_error('lwl',
raise_exception=False),
ax = df[[gettext('lims.msg_lwl'),
]].plot(kind='line', color='orange', rot=45, fontsize=7,
figsize=(10, 7.5), linestyle='-', ax=ax)
ax = df[[
PrintControlChart.raise_user_error('lcl',
raise_exception=False),
ax = df[[gettext('lims.msg_lcl'),
]].plot(kind='line', color='red', rot=45, fontsize=7,
figsize=(10, 7.5), linestyle='-', ax=ax)
ax = df[[
PrintControlChart.raise_user_error('result',
raise_exception=False),
ax = df[[gettext('lims.msg_result'),
]].plot(kind='line', color='blue', rot=45, fontsize=7,
figsize=(10, 7.5), marker='o', linestyle='-', ax=ax)

View File

@ -4,6 +4,8 @@
# the full copyright notices and license terms.
from trytond.model import ModelView, ModelSQL, fields
from trytond.exceptions import UserError
from trytond.i18n import gettext
__all__ = ['Department', 'UserDepartment']
@ -27,14 +29,6 @@ class UserDepartment(ModelSQL, ModelView):
required=True)
default = fields.Boolean('By default')
@classmethod
def __setup__(cls):
super(UserDepartment, cls).__setup__()
cls._error_messages.update({
'default_department': ('There is already a default department'
' for this user'),
})
@staticmethod
def default_default():
return False
@ -53,4 +47,4 @@ class UserDepartment(ModelSQL, ModelView):
('id', '!=', self.id),
])
if user_departments:
self.raise_user_error('default_department')
raise UserError(gettext('lims.msg_default_department'))

View File

@ -17,6 +17,8 @@ from trytond.tools import get_smtp_server
from trytond.config import config
from trytond.report import Report
from trytond.rpc import RPC
from trytond.exceptions import UserError, UserWarning
from trytond.i18n import gettext
__all__ = ['Entry', 'EntryInvoiceContact', 'EntryReportContact',
'EntryAcknowledgmentContact', 'EntrySuspensionReason',
@ -141,19 +143,6 @@ class Entry(Workflow, ModelSQL, ModelView):
'invisible': ~Eval('state').in_(['draft']),
},
})
cls._error_messages.update({
'no_entry_sequence': ('There is no entry sequence for '
'the work year "%s".'),
'delete_entry': ('You can not delete entry "%s" because '
'it is not in draft state'),
'not_fraction': ('You can not confirm entry "%s" because '
'has not fractions'),
'missing_entry_contacts': ('Missing contacts in entry "%s"'),
'enac_acredited': ('The analysis marked with * are not '
'covered by the Accreditation.'),
'english_report': ('Do not forget to load the translations '
'into English'),
})
@staticmethod
def default_date():
@ -382,8 +371,8 @@ class Entry(Workflow, ModelSQL, ModelView):
workyear = LabWorkYear(workyear_id)
sequence = workyear.get_sequence('entry')
if not sequence:
cls.raise_user_error('no_entry_sequence',
(workyear.rec_name,))
raise UserError(gettext('lims.msg_no_entry_sequence',
work_year=workyear.rec_name))
vlist = [x.copy() for x in vlist]
for values in vlist:
@ -487,12 +476,16 @@ class Entry(Workflow, ModelSQL, ModelView):
if (not self.invoice_contacts or
not self.report_contacts or
not self.acknowledgment_contacts):
self.raise_user_error('missing_entry_contacts', (self.rec_name,))
raise UserError(gettext(
'lims.msg_missing_entry_contacts', entry=self.rec_name))
def warn_english_report(self):
Warning = Pool().get('res.user.warning')
if self.english_report:
self.raise_user_warning('lims_english_report@%s' %
self.number, 'english_report')
key = 'lims_english_report@%s' % self.number
if Warning.check(key):
raise UserWarning(gettext('lims.english_report'))
def print_report(self):
if self.ack_report_cache:
@ -608,14 +601,16 @@ class Entry(Workflow, ModelSQL, ModelView):
Company = Pool().get('company.company')
companies = Company.search([])
if self.party.id not in [c.party.id for c in companies]:
self.raise_user_error('not_fraction', (self.rec_name,))
raise UserError(gettext(
'lims.msg_not_fraction', entry=self.rec_name))
Fraction.confirm(fractions)
@classmethod
def check_delete(cls, entries):
for entry in entries:
if entry.state != 'draft':
cls.raise_user_error('delete_entry', (entry.rec_name,))
raise UserError(gettext(
'lims.msg_delete_entry', entry=entry.rec_name))
@classmethod
def delete(cls, entries):
@ -702,11 +697,6 @@ class EntrySuspensionReason(ModelSQL, ModelView):
('code_uniq', Unique(t, t.code),
'Suspension reason code must be unique'),
]
cls._error_messages.update({
'default_suspension_reason':
'There is already a default '
'suspension reason',
})
@staticmethod
def default_by_default():
@ -742,7 +732,7 @@ class EntrySuspensionReason(ModelSQL, ModelView):
('id', '!=', self.id),
])
if reasons:
self.raise_user_error('default_suspension_reason')
raise UserError(gettext('lims.msg_default_suspension_reason'))
class EntryDetailAnalysis(ModelSQL, ModelView):
@ -801,10 +791,6 @@ class EntryDetailAnalysis(ModelSQL, ModelView):
def __setup__(cls):
super(EntryDetailAnalysis, cls).__setup__()
cls._order.insert(0, ('service', 'DESC'))
cls._error_messages.update({
'delete_detail': ('You can not delete the analysis detail because '
'its fraction is confirmed'),
})
@classmethod
def copy(cls, details, default=None):
@ -819,7 +805,7 @@ class EntryDetailAnalysis(ModelSQL, ModelView):
def check_delete(cls, details):
for detail in details:
if detail.fraction and detail.fraction.confirmed:
cls.raise_user_error('delete_detail')
raise UserError(gettext('lims.msg_delete_detail'))
@classmethod
def delete(cls, details):
@ -835,7 +821,6 @@ class EntryDetailAnalysis(ModelSQL, ModelView):
Method = pool.get('lims.lab.method')
WaitingTime = pool.get('lims.lab.method.results_waiting')
AnalysisLaboratory = pool.get('lims.analysis-laboratory')
Fraction = pool.get('lims.fraction')
Notebook = pool.get('lims.notebook')
Company = pool.get('company.company')
@ -927,8 +912,8 @@ class EntryDetailAnalysis(ModelSQL, ModelView):
if not lines_create:
companies = Company.search([])
if fraction.party.id not in [c.party.id for c in companies]:
Fraction.raise_user_error('not_services',
(fraction.rec_name,))
raise UserError(gettext(
'lims.msg_not_services', fraction=fraction.rec_name))
with Transaction().set_user(0):
notebook = Notebook.search([
@ -1455,8 +1440,8 @@ class AcknowledgmentOfReceipt(Report):
for v in s_methods.values():
if v['enac']:
v['enac_label'] = (Entry.raise_user_error(
'enac_acredited', raise_exception=False))
v['enac_label'] = gettext(
'lims.msg_enac_acredited')
else:
v['enac_label'] = ''
sorted_analysis = sorted(v['analysis'],

View File

@ -286,29 +286,15 @@
<!-- Cron -->
<record model="ir.cron" id="cron_lims_acknowledgment_of_receipt">
<field name="name">Lims Acknowledgment of Receipt (Samples)</field>
<field name="request_user" ref="res.user_admin"/>
<field name="user" ref="user_acknowledgment_of_receipt"/>
<field name="active" eval="True"/>
<field name="interval_number" eval="20"/>
<field name="interval_type">minutes</field>
<field name="number_calls" eval="-1"/>
<field name="repeat_missed" eval="False"/>
<field name="model">lims.entry</field>
<field name="function">cron_acknowledgment_of_receipt</field>
<field name="method">lims.entry|cron_acknowledgment_of_receipt</field>
</record>
<record model="ir.cron" id="cron_lims_confirm_waiting_entries">
<field name="name">Lims Confirm Waiting Entries</field>
<field name="request_user" ref="res.user_admin"/>
<field name="user" ref="user_entry_confirm"/>
<field name="active" eval="True"/>
<field name="interval_number" eval="1"/>
<field name="interval_type">minutes</field>
<field name="number_calls" eval="-1"/>
<field name="repeat_missed" eval="False"/>
<field name="model">lims.fraction</field>
<field name="function">confirm_waiting_fractions</field>
<field name="method">lims.fraction|confirm_waiting_fractions</field>
</record>
<!-- Wizard Forward Acknowledgment of Samples Receipt -->

View File

@ -4,6 +4,8 @@
# the full copyright notices and license terms.
from trytond.model import Model
from trytond.exceptions import UserError
from trytond.i18n import gettext
__all__ = ['FormulaParser']
@ -11,24 +13,6 @@ __all__ = ['FormulaParser']
class FormulaParser(Model):
'Formula Parser'
@classmethod
def __setup__(cls):
super(FormulaParser, cls).__setup__()
cls._error_messages.update({
'variable_redefine': 'Cannot redefine the value of "%s"',
'unexpected_character': ('Unexpected character found: "%s"'
' at index %s'),
'division_zero': 'Division by 0 (occured at index %s)',
'closing_parenthesis': ('No closing parenthesis found at'
' character %s'),
'unrecognized_variable': 'Unrecognized variable: "%s"',
'extra_period': ('Found an extra period in a number at'
' character %s'),
'unexpected_end': 'Unexpected end found',
'number_expected': ('Expecting to find a number at character'
' %s but instead there is a "%s"'),
})
def __init__(self, string, vars={}, id=None, **kwargs):
self.string = string
self.index = 0
@ -38,7 +22,8 @@ class FormulaParser(Model):
}
for var in list(vars.keys()):
if self.vars.get(var) is not None:
self.raise_user_error('variable_redefine', (var,))
raise UserError(gettext(
'lims.msg_variable_redefine', variable=var))
self.vars[var] = vars[var]
super(FormulaParser, self).__init__(id, **kwargs)
@ -46,8 +31,8 @@ class FormulaParser(Model):
value = self.parseExpression()
self.skipWhitespace()
if self.hasNext():
self.raise_user_error('unexpected_character',
(self.peek(), str(self.index)))
raise UserError(gettext('lims.msg_unexpected_character',
character=self.peek(), index=str(self.index)))
return value
def peek(self):
@ -90,11 +75,12 @@ class FormulaParser(Model):
self.index += 1
values.append(self.parsePower())
elif char == '/':
#div_index = self.index
# div_index = self.index
self.index += 1
denominator = self.parsePower()
if denominator == 0:
#self.raise_user_error('division_zero', (str(div_index),))
# raise UserError(gettext(
# 'lims.msg_division_zero', index=str(div_index)))
return 0.0
values.append(1.0 / denominator)
else:
@ -127,8 +113,8 @@ class FormulaParser(Model):
value = self.parseExpression()
self.skipWhitespace()
if self.peek() != ')':
self.raise_user_error('closing_parenthesis',
(str(self.index),))
raise UserError(gettext(
'lims.msg_closing_parenthesis', index=str(self.index)))
self.index += 1
return value
else:
@ -164,7 +150,8 @@ class FormulaParser(Model):
value = self.vars.get(var, None)
if value is None:
self.raise_user_error('unrecognized_variable', (var,))
raise UserError(gettext(
'lims.msg_unrecognized_variable', variable=var))
if value == '':
return float(0)
try:
@ -183,7 +170,8 @@ class FormulaParser(Model):
char = self.peek()
if char == '.':
if decimal_found:
self.raise_user_error('extra_period', (str(self.index),))
raise UserError(gettext(
'lims.msg_extra_period', index=str(self.index)))
decimal_found = True
strValue += '.'
elif char in '0123456789':
@ -194,9 +182,9 @@ class FormulaParser(Model):
if len(strValue) == 0:
if char == '':
self.raise_user_error('unexpected_end')
raise UserError(gettext('lims.msg_unexpected_end'))
else:
self.raise_user_error('number_expected',
(str(self.index), char))
raise UserError(gettext('lims.msg_number_expected',
index=str(self.index), character=char))
return float(strValue)

View File

@ -6,6 +6,8 @@ from trytond.model import ModelView, ModelSQL, fields, Unique
from trytond.pool import Pool
from trytond.transaction import Transaction
from trytond.pyson import Eval, Bool
from trytond.exceptions import UserError
from trytond.i18n import gettext
__all__ = ['LaboratoryProfessional', 'Laboratory', 'LaboratoryCVCorrection',
'LabMethod', 'LabMethodWaitingTime', 'LabDeviceType', 'LabDevice',
@ -360,14 +362,6 @@ class LabDeviceLaboratory(ModelSQL, ModelView):
required=True)
physically_here = fields.Boolean('Physically here')
@classmethod
def __setup__(cls):
super(LabDeviceLaboratory, cls).__setup__()
cls._error_messages.update({
'physically_elsewhere': ('This Device is physically in another'
' Laboratory'),
})
@staticmethod
def default_physically_here():
return True
@ -386,4 +380,4 @@ class LabDeviceLaboratory(ModelSQL, ModelView):
('id', '!=', self.id),
])
if laboratories:
self.raise_user_error('physically_elsewhere')
raise UserError(gettext('lims.msg_physically_elsewhere'))

407
lims/message.xml Normal file
View File

@ -0,0 +1,407 @@
<?xml version="1.0"?>
<tryton>
<data group="1">
<record model="ir.message" id="msg_limits">
<field name="text">Quantification limit must be greater than Detection limit</field>
</record>
<record model="ir.message" id="msg_default_typification">
<field name="text">There is already a default typification for this combination of product type, matrix and analysis</field>
</record>
<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_description_uniq">
<field name="text">Analysis description must be unique</field>
</record>
<record model="ir.message" id="msg_not_laboratory">
<field name="text">Must define a Laboratory</field>
</record>
<record model="ir.message" id="msg_set_laboratories">
<field name="text">A Set can be assigned to a single laboratory</field>
</record>
<record model="ir.message" id="msg_analysis_laboratory">
<field name="text">The "%(analysis)s" analysis is not defined in laboratory "%(laboratory)s"</field>
</record>
<record model="ir.message" id="msg_not_laboratory_change">
<field name="text">You can not change the laboratory because the analysis is included in a set/group with this laboratory</field>
</record>
<record model="ir.message" id="msg_end_date">
<field name="text">The leaving date cannot be lower than entry date</field>
</record>
<record model="ir.message" id="msg_end_date_wrong">
<field name="text">End date should not be greater than the current date</field>
</record>
<record model="ir.message" id="msg_duplicated_analysis">
<field name="text">The analysis "%(analysis)s" is already included</field>
</record>
<record model="ir.message" id="msg_not_set_laboratory">
<field name="text">No Laboratory loaded for the Set</field>
</record>
<record model="ir.message" id="msg_typificated_method">
<field name="text">You can not delete method "%(method)s" because is typificated</field>
</record>
<record model="ir.message" id="msg_default_device">
<field name="text">There is already a default device for this analysis on this laboratory</field>
</record>
<record model="ir.message" id="msg_active_version">
<field name="text">Only one version can be active for each technical scope</field>
</record>
<record model="ir.message" id="msg_workyear_overlaps">
<field name="text">Work year "%(first)s" and "%(second)s" overlap.</field>
</record>
<record model="ir.message" id="msg_no_workyear_date">
<field name="text">No work year defined for "%(date)s".</field>
</record>
<record model="ir.message" id="msg_default_range_type">
<field name="text">There is already a default origin for this use</field>
</record>
<record model="ir.message" id="msg_number">
<field name="text">Measurement</field>
</record>
<record model="ir.message" id="msg_result">
<field name="text">Result</field>
</record>
<record model="ir.message" id="msg_ucl">
<field name="text">UCL (M+3D)</field>
</record>
<record model="ir.message" id="msg_uwl">
<field name="text">UWL (M+2D)</field>
</record>
<record model="ir.message" id="msg_upl">
<field name="text">UPL (M+D)</field>
</record>
<record model="ir.message" id="msg_cl">
<field name="text">CL (M)</field>
</record>
<record model="ir.message" id="msg_lpl">
<field name="text">LPL (M-D)</field>
</record>
<record model="ir.message" id="msg_lwl">
<field name="text">LWL (M-2D)</field>
</record>
<record model="ir.message" id="msg_lcl">
<field name="text">LCL (M-3D)</field>
</record>
<record model="ir.message" id="msg_cv">
<field name="text">CV (%)</field>
</record>
<record model="ir.message" id="msg_default_department">
<field name="text">There is already a default department for this user</field>
</record>
<record model="ir.message" id="msg_no_entry_sequence">
<field name="text">There is no entry sequence for the work year "%(work_year)s".</field>
</record>
<record model="ir.message" id="msg_delete_entry">
<field name="text">You can not delete entry "%(entry)s" because it is not in draft state</field>
</record>
<record model="ir.message" id="msg_not_fraction">
<field name="text">You can not confirm entry "%(entry)s" because has not fractions</field>
</record>
<record model="ir.message" id="msg_missing_entry_contacts">
<field name="text">Missing contacts in entry "%(entry)s"</field>
</record>
<record model="ir.message" id="msg_enac_acredited">
<field name="text">The analysis marked with * are not covered by the Accreditation.</field>
</record>
<record model="ir.message" id="msg_english_report">
<field name="text">Do not forget to load the translations into English</field>
</record>
<record model="ir.message" id="msg_default_suspension_reason">
<field name="text">There is already a default suspension reason</field>
</record>
<record model="ir.message" id="msg_delete_detail">
<field name="text">You can not delete the analysis detail because its fraction is confirmed</field>
</record>
<record model="ir.message" id="msg_variable_redefine">
<field name="text">Cannot redefine the value of "%(variable)s"</field>
</record>
<record model="ir.message" id="msg_unexpected_character">
<field name="text">Unexpected character found: "%(character)s" at index %(index)s</field>
</record>
<record model="ir.message" id="msg_division_zero">
<field name="text">Division by 0 (occured at index %(index)s)</field>
</record>
<record model="ir.message" id="msg_closing_parenthesis">
<field name="text">No closing parenthesis found at character %(index)s</field>
</record>
<record model="ir.message" id="msg_unrecognized_variable">
<field name="text">Unrecognized variable: "%(variable)s"</field>
</record>
<record model="ir.message" id="msg_extra_period">
<field name="text">Found an extra period in a number at character %(index)s</field>
</record>
<record model="ir.message" id="msg_unexpected_end">
<field name="text">Unexpected end found</field>
</record>
<record model="ir.message" id="msg_number_expected">
<field name="text">Expecting to find a number at character %(index)s but instead there is a "%(character)s"</field>
</record>
<record model="ir.message" id="msg_physically_elsewhere">
<field name="text">This Device is physically in another Laboratory</field>
</record>
<record model="ir.message" id="msg_line_end_date">
<field name="text">The end date cannot be lower than start date</field>
</record>
<record model="ir.message" id="msg_accepted">
<field name="text">The analysis "%(analysis)s" is already accepted</field>
</record>
<record model="ir.message" id="msg_not_accepted_1">
<field name="text">The analysis is not reported</field>
</record>
<record model="ir.message" id="msg_not_accepted_2">
<field name="text">The analysis is annulled</field>
</record>
<record model="ir.message" id="msg_not_accepted_3">
<field name="text">The analysis has not End date</field>
</record>
<record model="ir.message" id="msg_not_accepted_4">
<field name="text">The analysis has not Result / Converted result</field>
</record>
<record model="ir.message" id="msg_not_accepted_5">
<field name="text">The Converted result modifier is invalid</field>
</record>
<record model="ir.message" id="msg_not_accepted_6">
<field name="text">The Result modifier is invalid</field>
</record>
<record model="ir.message" id="msg_not_accepted_7">
<field name="text">The Converted result / Converted result modifier is invalid</field>
</record>
<record model="ir.message" id="msg_accepted_1">
<field name="text">The analysis is already reported (%(report)s)</field>
</record>
<record model="ir.message" id="msg_ok">
<field name="text">OK</field>
</record>
<record model="ir.message" id="msg_ok*">
<field name="text">OK*</field>
</record>
<record model="ir.message" id="msg_out">
<field name="text">Out of Range</field>
</record>
<record model="ir.message" id="msg_acceptable">
<field name="text">Acceptable / Factor: %(factor)s - CV: %(cv)s</field>
</record>
<record model="ir.message" id="msg_unacceptable">
<field name="text">Unacceptable / Factor: %(factor)s - CV: %(cv)s</field>
</record>
<record model="ir.message" id="msg_invoice_address">
<field name="text">There is already a address with invoice type</field>
</record>
<record model="ir.message" id="msg_not_start_date">
<field name="text">The planification must have a start date</field>
</record>
<record model="ir.message" id="msg_invalid_start_date">
<field name="text">The start date must be after "%(date)s"</field>
</record>
<record model="ir.message" id="msg_no_technician">
<field name="text">The following fractions have not a responsible technician: %(fractions)s</field>
</record>
<record model="ir.message" id="msg_waiting_process">
<field name="text">Planification "%(planification)s" is still waiting for processing</field>
</record>
<record model="ir.message" id="msg_delete_planification">
<field name="text">You can not delete planification "%(planification)s" because it is not in draft or pre-planned state</field>
</record>
<record model="ir.message" id="msg_copy_planification">
<field name="text">You can not copy planifications</field>
</record>
<record model="ir.message" id="msg_no_entry_control">
<field name="text">There is no default entry control for this work year</field>
</record>
<record model="ir.message" id="msg_no_con_fraction_type">
<field name="text">There is no Control fraction type configured</field>
</record>
<record model="ir.message" id="msg_no_concentration_level">
<field name="text">Missing concentration level for this control type</field>
</record>
<record model="ir.message" id="msg_no_rm_fraction_type">
<field name="text">There is no RM fraction type configured</field>
</record>
<record model="ir.message" id="msg_no_bmz_fraction_type">
<field name="text">There is no BMZ fraction type configured</field>
</record>
<record model="ir.message" id="msg_no_rm_default_configuration">
<field name="text">Missing default configuration for RM fraction type</field>
</record>
<record model="ir.message" id="msg_no_bmz_default_configuration">
<field name="text">Missing default configuration for BMZ fraction type</field>
</record>
<record model="ir.message" id="msg_not_typified">
<field name="text">The analysis "%(analysis)s" is not typified for product type "%(product_type)s" and matrix "%(matrix)s"</field>
</record>
<record model="ir.message" id="msg_no_bre_fraction_type">
<field name="text">There is no BRE fraction type configured</field>
</record>
<record model="ir.message" id="msg_no_bre_default_configuration">
<field name="text">Missing default configuration for BRE fraction type</field>
</record>
<record model="ir.message" id="msg_no_mrt_fraction_type">
<field name="text">There is no MRT fraction type configured</field>
</record>
<record model="ir.message" id="msg_no_mrt_default_configuration">
<field name="text">Missing default configuration for MRT fraction type</field>
</record>
<record model="ir.message" id="msg_no_coi_fraction_type">
<field name="text">There is no COI fraction type configured</field>
</record>
<record model="ir.message" id="msg_no_mrc_fraction_type">
<field name="text">There is no MRC fraction type configured</field>
</record>
<record model="ir.message" id="msg_no_sla_fraction_type">
<field name="text">There is no SLA fraction type configured</field>
</record>
<record model="ir.message" id="msg_no_coi_default_configuration">
<field name="text">Missing default configuration for COI fraction type</field>
</record>
<record model="ir.message" id="msg_no_mrc_default_configuration">
<field name="text">Missing default configuration for MRC fraction type</field>
</record>
<record model="ir.message" id="msg_no_sla_default_configuration">
<field name="text">Missing default configuration for SLA fraction type</field>
</record>
<record model="ir.message" id="msg_no_sequence">
<field name="text">There is no results report sequence for the work year "%(work_year)s".</field>
</record>
<record model="ir.message" id="msg_missing_module">
<field name="text">Missing PyPDF2 module</field>
</record>
<record model="ir.message" id="msg_empty_report">
<field name="text">The report has not details to print</field>
</record>
<record model="ir.message" id="msg_delete_detail_not_draft">
<field name="text">You can not delete a detail that is not in draft state</field>
</record>
<record model="ir.message" id="msg_multiple_reports">
<field name="text">Please, select only one report to print</field>
</record>
<record model="ir.message" id="msg_annulled_report">
<field name="text">This report is annulled</field>
</record>
<record model="ir.message" id="msg_replace_number">
<field name="text">Supplants the Results Report N° %(report)s</field>
</record>
<record model="ir.message" id="msg_quantification_limit">
<field name="text">&lt; LoQ = %(loq)s</field>
</record>
<record model="ir.message" id="msg_detection_limit">
<field name="text">(LoD = %(detection_limit)s %(initial_unit)s)</field>
</record>
<record model="ir.message" id="msg_detection_limit_2">
<field name="text">(LoD = %(detection_limit)s)</field>
</record>
<record model="ir.message" id="msg_uncertainty">
<field name="text">(U± %(res)s %(initial_unit)s)</field>
</record>
<record model="ir.message" id="msg_obs_uncert">
<field name="text">U = Uncertainty</field>
</record>
<record model="ir.message" id="msg_neg">
<field name="text">Negative</field>
</record>
<record model="ir.message" id="msg_pos">
<field name="text">Positive</field>
</record>
<record model="ir.message" id="msg_nd">
<field name="text">Not detected</field>
</record>
<record model="ir.message" id="msg_pre">
<field name="text">Presence</field>
</record>
<record model="ir.message" id="msg_abs">
<field name="text">Absence</field>
</record>
<record model="ir.message" id="msg_enac_all_acredited">
<field name="text">Uncertainty for the analysis covered by the Accreditation is available.</field>
</record>
<record model="ir.message" id="msg_concentration_label_1">
<field name="text">(Expressed at the concentration of the received sample)</field>
</record>
<record model="ir.message" id="msg_concentration_label_2">
<field name="text">(Expressed at %(concentration)s° Brix)</field>
</record>
<record model="ir.message" id="msg_concentration_label_3">
<field name="text">(Expressed at %(concentration)s)</field>
</record>
<record model="ir.message" id="msg_final_unit_label_1">
<field name="text">Expressed at %(concentration)s %% Alcohol</field>
</record>
<record model="ir.message" id="msg_final_unit_label_2">
<field name="text">Expressed at %(concentration)s</field>
</record>
<record model="ir.message" id="msg_final_unit_label_3">
<field name="text">Expressed at %(concentration)s Bx</field>
</record>
<record model="ir.message" id="msg_final_unit_label_4">
<field name="text">Expressed at dry matter</field>
</record>
<record model="ir.message" id="msg_obs_ql">
<field name="text">LoQ= Limit of Quantitation. If the Detection Limit is reported, Result &lt;LoQ indicates that the detected value is between LoD (Limit of Detection) and LoQ (Limit of Quantitation).</field>
</record>
<record model="ir.message" id="msg_obs_dl">
<field name="text">LoD= Limit of Detection.</field>
</record>
<record model="ir.message" id="msg_caa_min">
<field name="text">min: %(min)s</field>
</record>
<record model="ir.message" id="msg_caa_max">
<field name="text">max: %(max)s</field>
</record>
<record model="ir.message" id="msg_obs_rm_c_f">
<field name="text">Elements results are reported without recovery correction.</field>
</record>
<record model="ir.message" id="msg_data_not_specified">
<field name="text">NOT SPECIFIED BY THE CLIENT</field>
</record>
<record model="ir.message" id="msg_not_done">
<field name="text">Not done by the company</field>
</record>
<record model="ir.message" id="msg_no_service_sequence">
<field name="text">There is no service sequence for the work year "%(work_year)s".</field>
</record>
<record model="ir.message" id="msg_delete_service">
<field name="text">You can not delete service "%(service)s" because its fraction is confirmed</field>
</record>
<record model="ir.message" id="msg_duplicated_analysis_service">
<field name="text">The analysis "%(analysis)s" is assigned more than once to the fraction "%(fraction)s"</field>
</record>
<record model="ir.message" id="msg_missing_fraction_product">
<field name="text">Missing "Fraction product" on Lims configuration</field>
</record>
<record model="ir.message" id="msg_delete_fraction">
<field name="text">You can not delete fraction "%(fraction)s" because it is confirmed</field>
</record>
<record model="ir.message" id="msg_not_services">
<field name="text">You can not confirm fraction "%(fraction)s" because has not services</field>
</record>
<record model="ir.message" id="msg_not_divided">
<field name="text">You can not confirm fraction because is not yet divided</field>
</record>
<record model="ir.message" id="msg_no_sample_sequence">
<field name="text">There is no sample sequence for the work year "%(work_year)s".</field>
</record>
<record model="ir.message" id="msg_duplicated_label">
<field name="text">The label "%(label)s" is already present in another sample</field>
</record>
<record model="ir.message" id="msg_delete_sample">
<field name="text">You can not delete sample "%(sample)s" because its entry is not in draft state</field>
</record>
<record model="ir.message" id="msg_counter_sample_date">
<field name="text">Reverse counter sample storage to enter the service </field>
</record>
<record model="ir.message" id="msg_reference">
<field name="text">Countersamples Storage</field>
</record>
<record model="ir.message" id="msg_reference_reversion">
<field name="text">Countersamples Storage Reversion</field>
</record>
<record model="ir.message" id="msg_reference_discharge">
<field name="text">Countersamples Discharge</field>
</record>
<record model="ir.message" id="msg_reference_fractions_discharge">
<field name="text">Fractions Discharge</field>
</record>
<record model="ir.message" id="msg_reference_fractions_discharge_reversion">
<field name="text">Fractions Discharge Reversion</field>
</record>
</data>
</tryton>

View File

@ -13,6 +13,8 @@ from trytond.pool import Pool
from trytond.pyson import PYSONEncoder, Eval, Bool, Not, Or
from trytond.transaction import Transaction
from trytond.report import Report
from trytond.exceptions import UserError
from trytond.i18n import gettext
from .formula_parser import FormulaParser
from .results_report import get_print_date
@ -227,7 +229,8 @@ class Notebook(ModelSQL, ModelView):
domain = ('current_location', 'in', [l.id for l in locations])
all_notebooks = cls.search([])
current_locations = iter(cls.get_current_location(all_notebooks).items())
current_locations = iter(
cls.get_current_location(all_notebooks).items())
processed_lines = [{
'fraction': fraction,
@ -401,21 +404,6 @@ class NotebookLine(ModelSQL, ModelView):
super(NotebookLine, cls).__setup__()
cls._order.insert(0, ('analysis_order', 'ASC'))
cls._order.insert(1, ('repetition', 'ASC'))
cls._error_messages.update({
'end_date': 'The end date cannot be lower than start date',
'end_date_wrong': ('End date should not be greater than the '
'current date'),
'accepted': 'The analysis "%s" is already accepted',
'not_accepted_1': 'The analysis is not reported',
'not_accepted_2': 'The analysis is annulled',
'not_accepted_3': 'The analysis has not End date',
'not_accepted_4': 'The analysis has not Result / Converted result',
'not_accepted_5': 'The Converted result modifier is invalid',
'not_accepted_6': 'The Result modifier is invalid',
'not_accepted_7': ('The Converted result / Converted result '
'modifier is invalid'),
'accepted_1': 'The analysis is already reported (%s)',
})
@staticmethod
def default_repetition():
@ -532,9 +520,9 @@ class NotebookLine(ModelSQL, ModelView):
def check_end_date(self):
if self.end_date:
if not self.start_date or self.end_date < self.start_date:
self.raise_user_error('end_date')
raise UserError(gettext('lims.msg_line_end_date'))
if not self.start_date or self.end_date > datetime.now().date():
self.raise_user_error('end_date_wrong')
raise UserError(gettext('lims.msg_end_date_wrong'))
def check_accepted(self):
if self.accepted:
@ -545,7 +533,8 @@ class NotebookLine(ModelSQL, ModelView):
('id', '!=', self.id),
])
if accepted_lines:
self.raise_user_error('accepted', (self.analysis.rec_name,))
raise UserError(gettext(
'lims.msg_accepted', analysis=self.analysis.rec_name))
@classmethod
def get_analysis_order(cls, notebook_lines, name):
@ -721,16 +710,13 @@ class NotebookLine(ModelSQL, ModelView):
if self.accepted:
if not self.report:
self.accepted = False
self.not_accepted_message = self.raise_user_error(
'not_accepted_1', raise_exception=False)
self.not_accepted_message = gettext('lims.msg_not_accepted_1')
elif self.annulled:
self.accepted = False
self.not_accepted_message = self.raise_user_error(
'not_accepted_2', raise_exception=False)
self.not_accepted_message = gettext('lims.msg_not_accepted_2')
elif not self.end_date:
self.accepted = False
self.not_accepted_message = self.raise_user_error(
'not_accepted_3', raise_exception=False)
self.not_accepted_message = gettext('lims.msg_not_accepted_3')
elif not (self.result or self.converted_result or
self.literal_result or
self.result_modifier in
@ -738,27 +724,26 @@ class NotebookLine(ModelSQL, ModelView):
self.converted_result_modifier in
('nd', 'pos', 'neg', 'ni', 'abs', 'pre')):
self.accepted = False
self.not_accepted_message = self.raise_user_error(
'not_accepted_4', raise_exception=False)
self.not_accepted_message = gettext('lims.msg_not_accepted_4')
else:
if (self.converted_result and self.converted_result_modifier
not in ('ni', 'eq', 'low')):
self.accepted = False
self.not_accepted_message = self.raise_user_error(
'not_accepted_5', raise_exception=False)
self.not_accepted_message = gettext(
'lims.msg_not_accepted_5')
elif (self.result and self.result_modifier
not in ('ni', 'eq', 'low')):
self.accepted = False
self.not_accepted_message = self.raise_user_error(
'not_accepted_6', raise_exception=False)
self.not_accepted_message = gettext(
'lims.msg_not_accepted_6')
elif (self.result_modifier == 'ni' and
not self.literal_result and
(not self.converted_result_modifier or
not self.converted_result) and
self.converted_result_modifier != 'nd'):
self.accepted = False
self.not_accepted_message = self.raise_user_error(
'not_accepted_7', raise_exception=False)
self.not_accepted_message = gettext(
'lims.msg_not_accepted_7')
else:
self.acceptance_date = datetime.now()
else:
@ -771,9 +756,8 @@ class NotebookLine(ModelSQL, ModelView):
if report_lines:
self.accepted = True
report_detail = report_lines[0].report_version_detail
self.not_accepted_message = self.raise_user_error('accepted_1',
(report_detail.report_version.results_report.number,),
raise_exception=False)
self.not_accepted_message = gettext('lims.msg_accepted_1',
report=report_detail.report_version.results_report.number)
else:
self.acceptance_date = None
@ -4083,15 +4067,6 @@ class NotebookResultsVerification(Wizard):
])
ok = StateTransition()
@classmethod
def __setup__(cls):
super(NotebookResultsVerification, cls).__setup__()
cls._error_messages.update({
'ok': 'OK',
'ok*': 'OK*',
'out': 'Out of Range',
})
def default_start(self, fields):
RangeType = Pool().get('lims.range.type')
@ -4266,12 +4241,9 @@ class NotebookResultsVerification(Wizard):
verifications = {}
with Transaction().set_context(language=lang.code):
verifications['ok'] = self.raise_user_error('ok',
raise_exception=False)
verifications['ok*'] = self.raise_user_error('ok*',
raise_exception=False)
verifications['out'] = self.raise_user_error('out',
raise_exception=False)
verifications['ok'] = gettext('lims.msg_ok')
verifications['ok*'] = gettext('lims.msg_ok*')
verifications['out'] = gettext('lims.msg_out')
return verifications
@ -4490,14 +4462,6 @@ class NotebookPrecisionControl(Wizard):
])
ok = StateTransition()
@classmethod
def __setup__(cls):
super(NotebookPrecisionControl, cls).__setup__()
cls._error_messages.update({
'acceptable': 'Acceptable / Factor: %s - CV: %s',
'unacceptable': 'Unacceptable / Factor: %s - CV: %s',
})
def transition_check(self):
Notebook = Pool().get('lims.notebook')
@ -4589,11 +4553,11 @@ class NotebookPrecisionControl(Wizard):
error = abs(rep_0 - rep_1) / average * 100
if error < (cv * self.start.factor):
res = self.raise_user_error('acceptable', (
self.start.factor, cv), raise_exception=False)
res = gettext(
'lims.msg_acceptable', factor=self.start.factor, cv=cv)
else:
res = self.raise_user_error('unacceptable', (
self.start.factor, cv), raise_exception=False)
res = gettext(
'lims.msg_unacceptable', factor=self.start.factor, cv=cv)
notebook_line.verification = res
lines_to_save.append(notebook_line)
if lines_to_save:

View File

@ -79,13 +79,6 @@ class Address(metaclass=PoolMeta):
states={'readonly': ~Bool(Eval('invoice_contact'))},
depends=['invoice_contact'])
@classmethod
def __setup__(cls):
super(Address, cls).__setup__()
cls._error_messages.update({
'invoice_address': 'There is already a address with invoice type',
})
@fields.depends('report_contact')
def on_change_report_contact(self):
if not self.report_contact:

View File

@ -13,6 +13,8 @@ from trytond.report import Report
from trytond.pool import Pool
from trytond.transaction import Transaction
from trytond.pyson import PYSONEncoder, Eval, Equal, Bool, Not, Or
from trytond.exceptions import UserError
from trytond.i18n import gettext
from .results_report import get_print_date
__all__ = ['Planification', 'PlanificationTechnician',
@ -152,17 +154,6 @@ class Planification(Workflow, ModelSQL, ModelView):
'readonly': (Eval('state') != 'preplanned'),
},
})
cls._error_messages.update({
'not_start_date': 'The planification must have a start date',
'invalid_start_date': 'The start date must be after "%s"',
'no_technician': ('The following fractions have not a responsible '
'technician:%s'),
'waiting_process': ('Planification "%s" is still waiting for '
'processing'),
'delete_planification': ('You can not delete planification "%s" '
'because it is not in draft or pre-planned state'),
'copy_planification': ('You can not copy planifications'),
})
@staticmethod
def default_state():
@ -262,8 +253,8 @@ class Planification(Workflow, ModelSQL, ModelView):
def check_delete(cls, planifications):
for planification in planifications:
if planification.state not in ['draft', 'preplanned']:
cls.raise_user_error('delete_planification',
(planification.rec_name,))
raise UserError(gettext('lims.msg_delete_planification',
planification=planification.rec_name))
@classmethod
def delete(cls, planifications):
@ -272,7 +263,7 @@ class Planification(Workflow, ModelSQL, ModelView):
@classmethod
def copy(cls, planifications, default=None):
cls.raise_user_error('copy_planification')
raise UserError(gettext('lims.msg_copy_planification'))
@classmethod
@ModelView.button_action('lims.wiz_lims_add_analysis')
@ -305,11 +296,11 @@ class Planification(Workflow, ModelSQL, ModelView):
def check_start_date(self):
if not self.start_date:
self.raise_user_error('not_start_date')
raise UserError(gettext('lims.msg_not_start_date'))
for detail in self.details:
if detail.fraction.sample.date2 > self.start_date:
self.raise_user_error('invalid_start_date',
(detail.fraction.sample.date2,))
raise UserError(gettext('lims.msg_invalid_start_date',
date=detail.fraction.sample.date2))
def check_technicians(self):
fractions = {}
@ -322,9 +313,10 @@ class Planification(Workflow, ModelSQL, ModelView):
fractions[key] = '%s (%s)' % (detail.fraction.rec_name,
service_detail.notebook_line.method.code)
if fractions:
sorted_fractions = sorted(list(fractions.values()), key=lambda x: x)
self.raise_user_error('no_technician',
('\n' + '\n'.join(sorted_fractions) + '\n',))
sorted_fractions = sorted(
list(fractions.values()), key=lambda x: x)
raise UserError(gettext('lims.msg_no_technician',
fractions='\n' + '\n'.join(sorted_fractions) + '\n'))
@classmethod
def process_waiting_planifications(cls):
@ -412,8 +404,8 @@ class Planification(Workflow, ModelSQL, ModelView):
for planification in planifications:
# Check if is still waiting for confirmation
if planification.waiting_process:
cls.raise_user_error('waiting_process',
(planification.code,))
raise UserError(gettext('lims.msg_waiting_process',
planification=planification.code))
if process_background:
planification.waiting_process = True
planification.save()
@ -1740,8 +1732,8 @@ class AddFractionControlStart(ModelView):
if self.original_fraction:
label += self.original_fraction.label
if self.concentration_level:
label += (' (' +
self.concentration_level.description + ')')
label += (' (' +
self.concentration_level.description + ')')
label += ' ' + str(Date.today())
return label
@ -1757,18 +1749,6 @@ class AddFractionControl(Wizard):
])
add = StateTransition()
@classmethod
def __setup__(cls):
super(AddFractionControl, cls).__setup__()
cls._error_messages.update({
'no_entry_control': ('There is no default entry control for this '
'work year'),
'no_con_fraction_type': ('There is no Control fraction type '
'configured'),
'no_concentration_level': ('Missing concentration level '
'for this control type'),
})
def default_start(self, fields):
Config = Pool().get('lims.configuration')
config = Config(1)
@ -1804,16 +1784,16 @@ class AddFractionControl(Wizard):
config = Config(1)
fraction_type = config.con_fraction_type
if not fraction_type:
self.raise_user_error('no_con_fraction_type')
raise UserError(gettext('lims.msg_no_con_fraction_type'))
if (fraction_type.control_charts and not
self.start.concentration_level):
self.raise_user_error('no_concentration_level')
raise UserError(gettext('lims.msg_no_concentration_level'))
workyear_id = LabWorkYear.find()
workyear = LabWorkYear(workyear_id)
if not workyear.default_entry_control:
self.raise_user_error('no_entry_control')
raise UserError(gettext('lims.msg_no_entry_control'))
entry = Entry(workyear.default_entry_control.id)
original_fraction = self.start.original_fraction
@ -2238,26 +2218,6 @@ class AddFractionRMBMZ(Wizard):
])
add = StateTransition()
@classmethod
def __setup__(cls):
super(AddFractionRMBMZ, cls).__setup__()
cls._error_messages.update({
'no_entry_control': ('There is no default entry control for this '
'work year'),
'no_rm_fraction_type': ('There is no RM fraction type '
'configured'),
'no_bmz_fraction_type': ('There is no BMZ fraction type '
'configured'),
'no_rm_default_configuration': ('Missing default configuration '
'for RM fraction type'),
'no_bmz_default_configuration': ('Missing default configuration '
'for BMZ fraction type'),
'no_concentration_level': ('Missing concentration level '
'for this control type'),
'not_typified': ('The analysis "%(analysis)s" is not typified '
'for product type "%(product_type)s" and matrix "%(matrix)s"'),
})
def default_start(self, fields):
defaults = {
'planification': Transaction().context['active_id'],
@ -2294,21 +2254,21 @@ class AddFractionRMBMZ(Wizard):
config = Config(1)
if self.start.type == 'rm':
if not config.rm_fraction_type:
self.raise_user_error('no_rm_fraction_type')
raise UserError(gettext('lims.msg_no_rm_fraction_type'))
fraction_type = config.rm_fraction_type
elif self.start.type == 'bmz':
if not config.bmz_fraction_type:
self.raise_user_error('no_bmz_fraction_type')
raise UserError(gettext('lims.msg_no_bmz_fraction_type'))
fraction_type = config.bmz_fraction_type
if (fraction_type.control_charts and not
self.start.concentration_level):
self.raise_user_error('no_concentration_level')
raise UserError(gettext('lims.msg_no_concentration_level'))
workyear_id = LabWorkYear.find()
workyear = LabWorkYear(workyear_id)
if not workyear.default_entry_control:
self.raise_user_error('no_entry_control')
raise UserError(gettext('lims.msg_no_entry_control'))
entry = Entry(workyear.default_entry_control.id)
original_fraction = self.start.reference_fraction
@ -2463,27 +2423,29 @@ class AddFractionRMBMZ(Wizard):
config = Config(1)
if self.start.type == 'rm':
if not config.rm_fraction_type:
self.raise_user_error('no_rm_fraction_type')
raise UserError(gettext('lims.msg_no_rm_fraction_type'))
fraction_type = config.rm_fraction_type
if (not fraction_type.default_package_type or
not fraction_type.default_fraction_state):
self.raise_user_error('no_rm_default_configuration')
raise UserError(gettext(
'lims.msg_no_rm_default_configuration'))
elif self.start.type == 'bmz':
if not config.bmz_fraction_type:
self.raise_user_error('no_bmz_fraction_type')
raise UserError(gettext('lims.msg_no_bmz_fraction_type'))
fraction_type = config.bmz_fraction_type
if (not fraction_type.default_package_type or
not fraction_type.default_fraction_state):
self.raise_user_error('no_bmz_default_configuration')
raise UserError(gettext(
'lims.msg_no_bmz_default_configuration'))
if (fraction_type.control_charts and not
self.start.concentration_level):
self.raise_user_error('no_concentration_level')
raise UserError(gettext('lims.msg_no_concentration_level'))
workyear_id = LabWorkYear.find()
workyear = LabWorkYear(workyear_id)
if not workyear.default_entry_control:
self.raise_user_error('no_entry_control')
raise UserError(gettext('lims.msg_no_entry_control'))
laboratory = self.start.planification.laboratory
entry = Entry(workyear.default_entry_control.id)
@ -2534,11 +2496,11 @@ class AddFractionRMBMZ(Wizard):
for p_analysis in self.start.planification.analysis:
if not Analysis.is_typified(p_analysis,
new_sample.product_type, new_sample.matrix):
self.raise_user_error('not_typified', {
'analysis': p_analysis.rec_name,
'product_type': new_sample.product_type.rec_name,
'matrix': new_sample.matrix.rec_name,
})
raise UserError(gettext('lims.msg_not_typified',
analysis=p_analysis.rec_name,
product_type=new_sample.product_type.rec_name,
matrix=new_sample.matrix.rec_name,
))
laboratory_id = (laboratory.id if p_analysis.type != 'group'
else None)
method_id = None
@ -2604,21 +2566,6 @@ class AddFractionRMBMZ(Wizard):
return new_fraction
def _get_obj_description(self, sample):
cursor = Transaction().connection.cursor()
ObjectiveDescription = Pool().get('lims.objective_description')
if not sample.product_type or not sample.matrix:
return None
cursor.execute('SELECT id '
'FROM "' + ObjectiveDescription._table + '" '
'WHERE product_type = %s '
'AND matrix = %s',
(sample.product_type.id, sample.matrix.id))
res = cursor.fetchone()
return res and res[0] or None
def generate_repetition(self, notebook_lines, repetitions):
pool = Pool()
Analysis = pool.get('lims.analysis')
@ -2879,22 +2826,6 @@ class AddFractionBRE(Wizard):
])
add = StateTransition()
@classmethod
def __setup__(cls):
super(AddFractionBRE, cls).__setup__()
cls._error_messages.update({
'no_entry_control': ('There is no default entry control for this '
'work year'),
'no_bre_fraction_type': ('There is no BRE fraction type '
'configured'),
'no_bre_default_configuration': ('Missing default configuration '
'for BRE fraction type'),
'no_concentration_level': ('Missing concentration level '
'for this control type'),
'not_typified': ('The analysis "%(analysis)s" is not typified '
'for product type "%(product_type)s" and matrix "%(matrix)s"'),
})
def default_start(self, fields):
Config = Pool().get('lims.configuration')
config = Config(1)
@ -2928,20 +2859,20 @@ class AddFractionBRE(Wizard):
config = Config(1)
if not config.bre_fraction_type:
self.raise_user_error('no_bre_fraction_type')
raise UserError(gettext('lims.msg_no_bre_fraction_type'))
fraction_type = config.bre_fraction_type
if (not fraction_type.default_package_type or
not fraction_type.default_fraction_state):
self.raise_user_error('no_bre_default_configuration')
raise UserError(gettext('lims.msg_no_bre_default_configuration'))
if (fraction_type.control_charts and not
self.start.concentration_level):
self.raise_user_error('no_concentration_level')
raise UserError(gettext('lims.msg_no_concentration_level'))
workyear_id = LabWorkYear.find()
workyear = LabWorkYear(workyear_id)
if not workyear.default_entry_control:
self.raise_user_error('no_entry_control')
raise UserError(gettext('lims.msg_no_entry_control'))
laboratory = self.start.planification.laboratory
entry = Entry(workyear.default_entry_control.id)
@ -2991,11 +2922,11 @@ class AddFractionBRE(Wizard):
for p_analysis in self.start.planification.analysis:
if not Analysis.is_typified(p_analysis,
new_sample.product_type, new_sample.matrix):
self.raise_user_error('not_typified', {
'analysis': p_analysis.rec_name,
'product_type': new_sample.product_type.rec_name,
'matrix': new_sample.matrix.rec_name,
})
raise UserError(gettext('lims.msg_not_typified',
analysis=p_analysis.rec_name,
product_type=new_sample.product_type.rec_name,
matrix=new_sample.matrix.rec_name,
))
laboratory_id = (laboratory.id if p_analysis.type != 'group'
else None)
method_id = None
@ -3252,22 +3183,6 @@ class AddFractionMRT(Wizard):
])
add = StateTransition()
@classmethod
def __setup__(cls):
super(AddFractionMRT, cls).__setup__()
cls._error_messages.update({
'no_entry_control': ('There is no default entry control for this '
'work year'),
'no_mrt_fraction_type': ('There is no MRT fraction type '
'configured'),
'no_mrt_default_configuration': ('Missing default configuration '
'for MRT fraction type'),
'no_concentration_level': ('Missing concentration level '
'for this control type'),
'not_typified': ('The analysis "%(analysis)s" is not typified '
'for product type "%(product_type)s" and matrix "%(matrix)s"'),
})
def default_start(self, fields):
Config = Pool().get('lims.configuration')
config = Config(1)
@ -3301,20 +3216,20 @@ class AddFractionMRT(Wizard):
config = Config(1)
if not config.mrt_fraction_type:
self.raise_user_error('no_mrt_fraction_type')
raise UserError(gettext('lims.msg_no_mrt_fraction_type'))
fraction_type = config.mrt_fraction_type
if (not fraction_type.default_package_type or
not fraction_type.default_fraction_state):
self.raise_user_error('no_mrt_default_configuration')
raise UserError(gettext('lims.msg_no_mrt_default_configuration'))
if (fraction_type.control_charts and not
self.start.concentration_level):
self.raise_user_error('no_concentration_level')
raise UserError(gettext('lims.msg_no_concentration_level'))
workyear_id = LabWorkYear.find()
workyear = LabWorkYear(workyear_id)
if not workyear.default_entry_control:
self.raise_user_error('no_entry_control')
raise UserError(gettext('lims.msg_no_entry_control'))
laboratory = self.start.planification.laboratory
entry = Entry(workyear.default_entry_control.id)
@ -3359,11 +3274,11 @@ class AddFractionMRT(Wizard):
for p_analysis in self.start.planification.analysis:
if not Analysis.is_typified(p_analysis,
new_sample.product_type, new_sample.matrix):
self.raise_user_error('not_typified', {
'analysis': p_analysis.rec_name,
'product_type': new_sample.product_type.rec_name,
'matrix': new_sample.matrix.rec_name,
})
raise UserError(gettext('lims.msg_not_typified',
analysis=p_analysis.rec_name,
product_type=new_sample.product_type.rec_name,
matrix=new_sample.matrix.rec_name,
))
laboratory_id = (laboratory.id if p_analysis.type != 'group'
else None)
method_id = None
@ -4542,28 +4457,6 @@ class CreateFractionControl(Wizard):
create_ = StateTransition()
open_ = StateAction('lims.act_lims_sample_list')
@classmethod
def __setup__(cls):
super(CreateFractionControl, cls).__setup__()
cls._error_messages.update({
'no_entry_control': ('There is no default entry control for this '
'work year'),
'no_coi_fraction_type': ('There is no COI fraction type '
'configured'),
'no_mrc_fraction_type': ('There is no MRC fraction type '
'configured'),
'no_sla_fraction_type': ('There is no SLA fraction type '
'configured'),
'no_coi_default_configuration': ('Missing default configuration '
'for COI fraction type'),
'no_mrc_default_configuration': ('Missing default configuration '
'for MRC fraction type'),
'no_sla_default_configuration': ('Missing default configuration '
'for SLA fraction type'),
'no_concentration_level': ('Missing concentration level '
'for this control type'),
})
def default_start(self, fields):
defaults = {
'laboratory': Transaction().context.get('laboratory', None),
@ -4589,34 +4482,37 @@ class CreateFractionControl(Wizard):
config = Config(1)
if self.start.type == 'coi':
if not config.coi_fraction_type:
self.raise_user_error('no_coi_fraction_type')
raise UserError(gettext('lims.msg_no_coi_fraction_type'))
fraction_type = config.coi_fraction_type
if (not fraction_type.default_package_type or
not fraction_type.default_fraction_state):
self.raise_user_error('no_coi_default_configuration')
raise UserError(gettext(
'lims.msg_no_coi_default_configuration'))
elif self.start.type == 'mrc':
if not config.mrc_fraction_type:
self.raise_user_error('no_mrc_fraction_type')
raise UserError(gettext('lims.msg_no_mrc_fraction_type'))
fraction_type = config.mrc_fraction_type
if (not fraction_type.default_package_type or
not fraction_type.default_fraction_state):
self.raise_user_error('no_mrc_default_configuration')
raise UserError(gettext(
'lims.msg_no_mrc_default_configuration'))
elif self.start.type == 'sla':
if not config.sla_fraction_type:
self.raise_user_error('no_sla_fraction_type')
raise UserError(gettext('lims.msg_no_sla_fraction_type'))
fraction_type = config.sla_fraction_type
if (not fraction_type.default_package_type or
not fraction_type.default_fraction_state):
self.raise_user_error('no_sla_default_configuration')
raise UserError(gettext(
'lims.msg_no_sla_default_configuration'))
if (fraction_type.control_charts and not
self.start.concentration_level):
self.raise_user_error('no_concentration_level')
raise UserError(gettext('lims.msg_no_concentration_level'))
workyear_id = LabWorkYear.find()
workyear = LabWorkYear(workyear_id)
if not workyear.default_entry_control:
self.raise_user_error('no_entry_control')
raise UserError(gettext('lims.msg_no_entry_control'))
laboratory = self.start.laboratory
entry = Entry(workyear.default_entry_control.id)
@ -5964,7 +5860,8 @@ class PlanificationWorksheetMethodReport(Report):
for k1 in objects.keys():
for k2 in objects[k1]['professionals'].keys():
objects[k1]['professionals'][k2]['methods'] = {}
fractions = list(objects[k1]['professionals'][k2]['lines'].values())
fractions = list(
objects[k1]['professionals'][k2]['lines'].values())
for fraction in fractions:
m_key = ()
m_names = []
@ -6150,8 +6047,9 @@ class PlanificationWorksheetReport(Report):
'analysis'].keys():
objects[k1]['professionals'][k2]['analysis'][k3][
'methods'] = {}
fractions = list(objects[k1]['professionals'][k2]['analysis'][
k3]['lines'].values())
fractions = list(
objects[k1]['professionals'][k2]['analysis'][
k3]['lines'].values())
for fraction in fractions:
m_key = ()
m_names = []

View File

@ -302,16 +302,9 @@
<!-- Cron -->
<record model="ir.cron" id="cron_lims_process_waiting_planifications">
<field name="name">Lims Process Waiting Planifications</field>
<field name="request_user" ref="res.user_admin"/>
<field name="user" ref="user_planification_process"/>
<field name="active" eval="True"/>
<field name="interval_number" eval="1"/>
<field name="interval_type">minutes</field>
<field name="number_calls" eval="-1"/>
<field name="repeat_missed" eval="False"/>
<field name="model">lims.planification</field>
<field name="function">process_waiting_planifications</field>
<field name="method">lims.planification|process_waiting_planifications</field>
</record>
<!-- Sequence -->

View File

@ -2,7 +2,7 @@
# This file is part of lims module for Tryton.
# The COPYRIGHT file at the top level of this repository contains
# the full copyright notices and license terms.
from io import StringIO, BytesIO
from io import BytesIO
from datetime import datetime
from PyPDF2 import PdfFileMerger
from trytond.model import ModelView, ModelSQL, fields
@ -13,6 +13,8 @@ from trytond.pyson import PYSONEncoder, Eval, Equal, Bool, Not, And, Or, If
from trytond.transaction import Transaction
from trytond.report import Report
from trytond.rpc import RPC
from trytond.exceptions import UserError
from trytond.i18n import gettext
__all__ = ['ResultsReport', 'ResultsReportVersion',
'ResultsReportVersionDetail', 'ResultsReportVersionDetailLine',
@ -76,12 +78,6 @@ class ResultsReport(ModelSQL, ModelView):
def __setup__(cls):
super(ResultsReport, cls).__setup__()
cls._order.insert(0, ('number', 'DESC'))
cls._error_messages.update({
'no_sequence': ('There is no results report sequence for '
'the work year "%s".'),
'missing_module': 'Missing PyPDF2 module',
'empty_report': 'The report has not details to print',
})
@staticmethod
def default_report_grouper():
@ -97,8 +93,8 @@ class ResultsReport(ModelSQL, ModelView):
workyear = LabWorkYear(workyear_id)
sequence = workyear.get_sequence('results_report')
if not sequence:
cls.raise_user_error('no_sequence',
(workyear.rec_name,))
raise UserError(gettext('lims.msg_no_sequence',
work_year=workyear.rec_name))
vlist = [x.copy() for x in vlist]
for values in vlist:
@ -369,48 +365,6 @@ class ResultsReportVersionDetail(ModelSQL, ModelView):
)),
},
})
cls._error_messages.update({
'delete_detail': ('You can not delete a detail that is not in '
'draft state'),
'multiple_reports': 'Please, select only one report to print',
'annulled_report': 'This report is annulled',
'empty_report': 'The report has not lines to print',
'replace_number': 'Supplants the Results Report N° %s',
'quantification_limit': '< LoQ = %s',
'detection_limit': '(LoD = %s %s)',
'detection_limit_2': '(LoD = %s)',
'uncertainty': '(U± %s %s)',
'obs_uncert': 'U = Uncertainty.',
'neg': 'Negative',
'pos': 'Positive',
'nd': 'Not detected',
'pre': 'Presence',
'abs': 'Absence',
'enac_all_acredited': ('Uncertainty for the analysis covered '
'by the Accreditation is available.'),
'enac_acredited': ('The analysis marked with * are not '
'covered by the Accreditation. Uncertainty for the '
'analysis covered by the Accreditation is available.'),
'concentration_label_1': ('(Expressed at the concentration of '
'the received sample)'),
'concentration_label_2': '(Expressed at %s° Brix)',
'concentration_label_3': '(Expressed at %s)',
'final_unit_label_1': 'Expressed at %s %% Alcohol',
'final_unit_label_2': 'Expressed at %s',
'final_unit_label_3': 'Expressed at %s Bx',
'final_unit_label_4': 'Expressed at dry matter',
'obs_ql': ('LoQ= Limit of Quantitation. If the Detection '
'Limit is reported, Result <LoQ '
'indicates that the detected value is between LoD '
'(Limit of Detection) and LoQ (Limit of Quantitation).'),
'obs_dl': 'LoD= Limit of Detection.',
'caa_min': 'min: %s',
'caa_max': 'max: %s',
'obs_rm_c_f': ('Elements results are reported without recovery '
'correction.'),
'data_not_specified': 'NOT SPECIFIED BY THE CLIENT',
'not_done': 'Not done by the company',
})
@staticmethod
def default_report_type_forced():
@ -810,7 +764,7 @@ class ResultsReportVersionDetail(ModelSQL, ModelView):
def check_delete(cls, details):
for detail in details:
if detail.state != 'draft':
cls.raise_user_error('delete_detail')
raise UserError(gettext('lims.msg_delete_detail_not_draft'))
@classmethod
def get_fraction_comments(cls, details, name):
@ -1989,7 +1943,7 @@ class PrintResultsReport(Wizard):
(format_field, '=', 'pdf'),
])
if not details:
ResultsReport.raise_user_error('empty_report')
raise UserError(gettext('lims.msg_empty_report'))
if results_report.english_report:
results_report.report_format_eng = 'pdf'
@ -2201,11 +2155,11 @@ class ResultReport(Report):
def execute(cls, ids, data):
ResultsReport = Pool().get('lims.results_report.version.detail')
if len(ids) > 1:
ResultsReport.raise_user_error('multiple_reports')
raise UserError(gettext('lims.msg_multiple_reports'))
results_report = ResultsReport(ids[0])
if results_report.state == 'annulled':
ResultsReport.raise_user_error('annulled_report')
raise UserError(gettext('lims.msg_annulled_report'))
if data is None:
data = {}
@ -2279,8 +2233,7 @@ class ResultReport(Report):
prev_number = "%s-%s" % (report.report_version.number,
int(report.number) - 1)
report_context['replace_number'] = (
ResultsReport.raise_user_error('replace_number',
(prev_number,), raise_exception=False))
gettext('lims.msg_replace_number', report=prev_number))
report_context['print_date'] = get_print_date()
report_context['party'] = (
report.report_version.results_report.party.rec_name)
@ -2347,7 +2300,7 @@ class ResultReport(Report):
('report_version_detail.valid', '=', True)],
], order=[('report_version_detail', 'ASC')])
if not notebook_lines:
ResultsReport.raise_user_error('empty_report')
raise UserError(gettext('lims.msg_empty_report'))
with Transaction().set_context(language=lang_code):
reference_sample = Sample(
@ -2393,8 +2346,7 @@ class ResultReport(Report):
if sample.package_state else ''),
'producer': (sample.producer.rec_name
if sample.producer else
ResultsReport.raise_user_error('data_not_specified',
raise_exception=False)),
gettext('lims.msg_data_not_specified')),
'obj_description': (sample.obj_description.description
if sample.obj_description else
sample.obj_description_manual),
@ -2426,9 +2378,8 @@ class ResultReport(Report):
cls.format_date(sample.sampling_datetime.date(),
report_context['user'].language))
else:
fractions[key]['water_sampling_date'] = (
ResultsReport.raise_user_error('not_done',
raise_exception=False))
fractions[key]['water_sampling_date'] = gettext(
'not_done')
record = {
'order': t_line.analysis.order or 9999,
@ -2541,8 +2492,7 @@ class ResultReport(Report):
with Transaction().set_context(language=lang_code):
report_context['sample_producer'] = (
reference_sample.producer.rec_name if reference_sample.producer
else ResultsReport.raise_user_error('data_not_specified',
raise_exception=False))
else gettext('lims.msg_data_not_specified'))
report_context['sample_obj_description'] = (
reference_sample.obj_description.description
if reference_sample.obj_description
@ -2599,9 +2549,8 @@ class ResultReport(Report):
cls.format_date(reference_sample.sampling_datetime.date(),
report_context['user'].language))
else:
report_context['water_sampling_date'] = (
ResultsReport.raise_user_error('not_done',
raise_exception=False))
report_context['water_sampling_date'] = gettext(
'lims.msg_not_done')
report_context['tas_project'] = 'True' if tas_project else 'False'
report_context['stp_project'] = 'True' if stp_project else 'False'
@ -2646,14 +2595,14 @@ class ResultReport(Report):
fraction['concentrations'][conc]['label'] = ''
elif conc_is_numeric and numeric_conc < 100:
fraction['concentrations'][conc]['label'] = (
ResultsReport.raise_user_error(
'concentration_label_2', (conc,),
raise_exception=False))
gettext(
'concentration_label_2', concentration=conc
))
else:
fraction['concentrations'][conc]['label'] = (
ResultsReport.raise_user_error(
'concentration_label_3', (conc,),
raise_exception=False))
gettext(
'concentration_label_3', concentration=conc
))
show_unit_label = False
for line in sorted_lines:
@ -2664,29 +2613,27 @@ class ResultReport(Report):
if dry_matter:
fraction['concentrations'][conc][
'unit_label'] = (
ResultsReport.raise_user_error(
'final_unit_label_4',
raise_exception=False))
gettext('lims.msg_final_unit_label_4'))
else:
if conc_is_numeric:
if alcohol:
fraction['concentrations'][conc][
'unit_label'] = (
ResultsReport.raise_user_error(
'final_unit_label_1', (conc,),
raise_exception=False))
gettext(
'final_unit_label_1',
concentration=conc))
else:
fraction['concentrations'][conc][
'unit_label'] = (
ResultsReport.raise_user_error(
'final_unit_label_3', (conc,),
raise_exception=False))
gettext(
'final_unit_label_3',
concentration=conc))
else:
fraction['concentrations'][conc][
'unit_label'] = (
ResultsReport.raise_user_error(
'final_unit_label_2', (conc,),
raise_exception=False))
gettext(
'final_unit_label_2',
concentration=conc))
report_context['fractions'] = sorted_fractions
@ -2703,12 +2650,10 @@ class ResultReport(Report):
with Transaction().set_context(language=lang_code):
if enac_all_acredited:
report_context['enac_label'] = (
ResultsReport.raise_user_error(
'enac_all_acredited', raise_exception=False))
gettext('lims.msg_enac_all_acredited'))
else:
report_context['enac_label'] = (
ResultsReport.raise_user_error(
'enac_acredited', raise_exception=False))
report_context['enac_label'] = gettext(
'lims.msg_enac_acredited')
else:
report_context['enac_label'] = ''
@ -2735,23 +2680,17 @@ class ResultReport(Report):
with Transaction().set_context(language=lang_code):
if report_context['comments']:
report_context['comments'] += '\n'
report_context['comments'] += (
ResultsReport.raise_user_error('obs_ql',
raise_exception=False))
report_context['comments'] += gettext('lims.msg_obs_ql')
if obs_dl and report_context['report_section']:
with Transaction().set_context(language=lang_code):
if report_context['comments']:
report_context['comments'] += '\n'
report_context['comments'] += (
ResultsReport.raise_user_error('obs_dl',
raise_exception=False))
report_context['comments'] += gettext('lims.msg_obs_dl')
if obs_uncert:
with Transaction().set_context(language=lang_code):
if report_context['comments']:
report_context['comments'] += '\n'
report_context['comments'] += (
ResultsReport.raise_user_error('obs_uncert',
raise_exception=False))
report_context['comments'] += gettext('lims.msg_obs_uncert')
if obs_result_range and range_type.resultrange_comments:
if report_context['comments']:
report_context['comments'] += '\n'
@ -2760,9 +2699,7 @@ class ResultReport(Report):
with Transaction().set_context(language=lang_code):
if report_context['comments']:
report_context['comments'] += '\n'
report_context['comments'] += (
ResultsReport.raise_user_error('obs_rm_c_f',
raise_exception=False))
report_context['comments'] += gettext('lims.msg_obs_rm_c_f')
report_context['annulment_reason'] = ''
if report.number != '1':
@ -2812,9 +2749,6 @@ class ResultReport(Report):
@classmethod
def get_result(cls, report_section, notebook_line, obs_ql, language):
pool = Pool()
ResultsReport = pool.get('lims.results_report.version.detail')
literal_result = notebook_line.literal_result
result = notebook_line.result
decimals = notebook_line.decimals
@ -2835,27 +2769,20 @@ class ResultReport(Report):
if result_modifier == 'eq':
res = res
elif result_modifier == 'low':
res = ResultsReport.raise_user_error(
'quantification_limit', (res,),
raise_exception=False)
res = gettext('lims.msg_quantification_limit', loq=res)
obs_ql = True
elif result_modifier == 'nd':
res = ResultsReport.raise_user_error('nd',
raise_exception=False)
res = gettext('lims.msg_nd')
elif result_modifier == 'ni':
res = ''
elif result_modifier == 'pos':
res = ResultsReport.raise_user_error('pos',
raise_exception=False)
res = gettext('lims.msg_pos')
elif result_modifier == 'neg':
res = ResultsReport.raise_user_error('neg',
raise_exception=False)
res = gettext('lims.msg_neg')
elif result_modifier == 'pre':
res = ResultsReport.raise_user_error('pre',
raise_exception=False)
res = gettext('lims.msg_pre')
elif result_modifier == 'abs':
res = ResultsReport.raise_user_error('abs',
raise_exception=False)
res = gettext('lims.msg_abs')
else:
res = result_modifier
elif report_section == 'mi':
@ -2873,28 +2800,20 @@ class ResultReport(Report):
elif result_modifier == 'low':
res = '< %s' % res
elif result_modifier == 'nd':
res = ResultsReport.raise_user_error('nd',
raise_exception=False)
res = gettext('lims.msg_nd')
elif result_modifier == 'pos':
res = ResultsReport.raise_user_error('pos',
raise_exception=False)
res = gettext('lims.msg_pos')
elif result_modifier == 'neg':
res = ResultsReport.raise_user_error('neg',
raise_exception=False)
res = gettext('lims.msg_neg')
elif result_modifier == 'pre':
res = ResultsReport.raise_user_error('pre',
raise_exception=False)
res = gettext('lims.msg_pre')
elif result_modifier == 'abs':
res = ResultsReport.raise_user_error('abs',
raise_exception=False)
res = gettext('lims.msg_abs')
return res, obs_ql
@classmethod
def get_converted_result(cls, report_section, report_result_type,
notebook_line, obs_ql, language):
pool = Pool()
ResultsReport = pool.get('lims.results_report.version.detail')
if (report_section in ('for', 'mi', 'rp') or
report_result_type not in ('both', 'both_range')):
return '', obs_ql
@ -2909,38 +2828,29 @@ class ResultReport(Report):
res = ''
if analysis != '0001' and not literal_result:
if converted_result_modifier == 'neg':
res = ResultsReport.raise_user_error('neg',
raise_exception=False)
res = gettext('lims.msg_neg')
elif converted_result_modifier == 'pos':
res = ResultsReport.raise_user_error('pos',
raise_exception=False)
res = gettext('lims.msg_pos')
elif converted_result_modifier == 'pre':
res = ResultsReport.raise_user_error('pre',
raise_exception=False)
res = gettext('lims.msg_pre')
elif converted_result_modifier == 'abs':
res = ResultsReport.raise_user_error('abs',
raise_exception=False)
res = gettext('lims.msg_abs')
elif converted_result_modifier == 'nd':
res = ResultsReport.raise_user_error('nd',
raise_exception=False)
res = gettext('lims.msg_nd')
else:
if converted_result and converted_result_modifier != 'ni':
res = round(float(converted_result), decimals)
if decimals == 0:
res = int(res)
if converted_result_modifier == 'low':
res = ResultsReport.raise_user_error(
'quantification_limit', (res,),
raise_exception=False)
res = gettext(
'quantification_limit', loq=res)
obs_ql = True
return res, obs_ql
@classmethod
def get_initial_unit(cls, report_section, report_result_type,
notebook_line, obs_dl, obs_uncert, language):
pool = Pool()
ResultsReport = pool.get('lims.results_report.version.detail')
if not notebook_line.initial_unit:
return '', obs_dl, obs_uncert
@ -2960,9 +2870,8 @@ class ResultReport(Report):
res = round(float(uncertainty), decimals)
if decimals == 0:
res = int(res)
res = ResultsReport.raise_user_error(
'uncertainty', (res, ''),
raise_exception=False)
res = gettext(
'lims.msg_uncertainty', res=res, initial_unit='')
obs_uncert = True
else:
res = initial_unit
@ -2978,9 +2887,9 @@ class ResultReport(Report):
'0', '0.0')):
res = initial_unit
else:
res = ResultsReport.raise_user_error(
'detection_limit', (detection_limit,
initial_unit), raise_exception=False)
res = gettext('lims.msg_detection_limit',
detection_limit=detection_limit,
initial_unit=initial_unit)
obs_dl = True
else:
if (not converted_result and uncertainty and
@ -2988,18 +2897,14 @@ class ResultReport(Report):
res = round(float(uncertainty), decimals)
if decimals == 0:
res = int(res)
res = ResultsReport.raise_user_error(
'uncertainty', (res, initial_unit),
raise_exception=False)
res = gettext('lims.msg_uncertainty',
res=res, initial_unit=initial_unit)
obs_uncert = True
return res, obs_dl, obs_uncert
@classmethod
def get_final_unit(cls, report_section, report_result_type,
notebook_line, obs_dl, obs_uncert, language):
pool = Pool()
ResultsReport = pool.get('lims.results_report.version.detail')
if (report_section in ('for', 'mi', 'rp') or
report_result_type not in ('both', 'both_range')):
return '', obs_dl, obs_uncert
@ -3026,9 +2931,9 @@ class ResultReport(Report):
'0', '0.0')):
res = final_unit
else:
res = ResultsReport.raise_user_error(
'detection_limit', (detection_limit,
final_unit), raise_exception=False)
res = gettext('lims.msg_detection_limit',
detection_limit=detection_limit,
final_unit=final_unit)
obs_dl = True
else:
if not converted_result:
@ -3038,17 +2943,14 @@ class ResultReport(Report):
res = round(float(uncertainty), decimals)
if decimals == 0:
res = int(res)
res = ResultsReport.raise_user_error(
'uncertainty', (res, final_unit),
raise_exception=False)
res = gettext('lims.msg_uncertainty',
res=res, final_unit=final_unit)
obs_uncert = True
return res, obs_dl, obs_uncert
@classmethod
def get_detection_limit(cls, report_section, report_result_type,
report_type, notebook_line, language):
ResultsReport = Pool().get('lims.results_report.version.detail')
detection_limit = notebook_line.detection_limit
literal_result = notebook_line.literal_result
result_modifier = notebook_line.result_modifier
@ -3057,9 +2959,8 @@ class ResultReport(Report):
res = ''
if report_type == 'polisample' and result_modifier == 'nd':
with Transaction().set_context(language=language):
res = ResultsReport.raise_user_error(
'detection_limit_2', (detection_limit),
raise_exception=False)
res = gettext('lims.msg_detection_limit_2',
detection_limit=detection_limit)
else:
if (not detection_limit or detection_limit in ('0', '0.0') or
literal_result):
@ -3073,7 +2974,6 @@ class ResultReport(Report):
report_section):
pool = Pool()
Range = pool.get('lims.range')
ResultsReport = pool.get('lims.results_report.version.detail')
with Transaction().set_context(language=language):
ranges = Range.search([
@ -3101,8 +3001,7 @@ class ResultReport(Report):
res1 = str(round(range_.min, 2))
else:
res1 = str(int(range_.min))
res = ResultsReport.raise_user_error('caa_min',
(res1,), raise_exception=False)
res = gettext('lims.msg_caa_min', min=res1)
if range_.max:
if res:
@ -3115,8 +3014,7 @@ class ResultReport(Report):
else:
res1 = str(int(range_.max))
res += ResultsReport.raise_user_error('caa_max',
(res1,), raise_exception=False)
res += gettext('lims.msg_caa_max', max=res1)
return res
@ -3128,11 +3026,11 @@ class ResultReportTranscription(ResultReport):
def execute(cls, ids, data):
ResultsReport = Pool().get('lims.results_report.version.detail')
if len(ids) > 1:
ResultsReport.raise_user_error('multiple_reports')
raise UserError(gettext('lims.msg_multiple_reports'))
results_report = ResultsReport(ids[0])
if results_report.state == 'annulled':
ResultsReport.raise_user_error('annulled_report')
raise UserError(gettext('lims.msg_annulled_report'))
if data is None:
data = {}

View File

@ -14,6 +14,8 @@ from trytond.pool import Pool
from trytond.pyson import PYSONEncoder, Eval, Equal, Bool, Not, Or
from trytond.transaction import Transaction
from trytond.report import Report
from trytond.exceptions import UserError
from trytond.i18n import gettext
__all__ = ['Zone', 'Variety', 'MatrixVariety', 'PackagingIntegrity',
'PackagingType', 'FractionType', 'SampleProducer', 'Service',
@ -362,14 +364,6 @@ class Service(ModelSQL, ModelView):
def __setup__(cls):
super(Service, cls).__setup__()
cls._order.insert(0, ('number', 'DESC'))
cls._error_messages.update({
'no_service_sequence': ('There is no service sequence for '
'the work year "%s".'),
'delete_service': ('You can not delete service "%s" because '
'its fraction is confirmed'),
'duplicated_analysis': ('The analysis "%(analysis)s" is assigned '
'more than once to the fraction "%(fraction)s"'),
})
@staticmethod
def default_urgent():
@ -411,10 +405,11 @@ class Service(ModelSQL, ModelView):
for a_id in new_analysis_ids:
if a_id in analysis_ids:
analysis = Analysis(a_id)
self.raise_user_error('duplicated_analysis', {
'analysis': analysis.rec_name,
'fraction': self.fraction.rec_name,
})
raise UserError(gettext(
'lims.msg_duplicated_analysis_service',
analysis=analysis.rec_name,
fraction=self.fraction.rec_name,
))
@classmethod
def create(cls, vlist):
@ -427,8 +422,8 @@ class Service(ModelSQL, ModelView):
workyear = LabWorkYear(workyear_id)
sequence = workyear.get_sequence('service')
if not sequence:
cls.raise_user_error('no_service_sequence',
(workyear.rec_name,))
raise UserError(gettext('lims.msg_no_service_sequence',
work_year=workyear.rec_name))
vlist = [x.copy() for x in vlist]
for values in vlist:
@ -489,7 +484,8 @@ class Service(ModelSQL, ModelView):
def check_delete(cls, services):
for service in services:
if service.fraction and service.fraction.confirmed:
cls.raise_user_error('delete_service', (service.rec_name,))
raise UserError(gettext(
'lims.msg_delete_service', service=service.rec_name))
@staticmethod
def update_analysis_detail(services):
@ -1318,18 +1314,6 @@ class Fraction(ModelSQL, ModelView):
Bool(Eval('services'))),
},
})
cls._error_messages.update({
'missing_fraction_product': ('Missing "Fraction product" '
'on Lims configuration'),
'delete_fraction': ('You can not delete fraction "%s" because '
'it is confirmed'),
'duplicated_analysis': ('The analysis "%s" is assigned more'
' than once'),
'not_services': ('You can not confirm fraction "%s" because '
'has not services'),
'not_divided': ('You can not confirm fraction because '
'is not yet divided'),
})
@staticmethod
def default_packages_quantity():
@ -1419,7 +1403,8 @@ class Fraction(ModelSQL, ModelView):
def check_delete(cls, fractions):
for fraction in fractions:
if fraction.confirmed:
cls.raise_user_error('delete_fraction', (fraction.rec_name,))
raise UserError(gettext(
'lims.msg_delete_fraction', fraction=fraction.rec_name))
@classmethod
def delete(cls, fractions):
@ -1782,7 +1767,7 @@ class Fraction(ModelSQL, ModelView):
('service', '=', service.id),
('report_grouper', '!=', 0),
]) == 0):
cls.raise_user_error('not_divided')
raise UserError(gettext('lims.msg_not_divided'))
@classmethod
@ModelView.button
@ -1855,7 +1840,7 @@ class Fraction(ModelSQL, ModelView):
if config_.fraction_product:
product = config_.fraction_product
else:
self.raise_user_error('missing_fraction_product')
raise UserError(gettext('lims.msg_missing_fraction_product'))
today = Date.today()
company = User(Transaction().user).company
if self.sample.entry.party.customer_location:
@ -1921,9 +1906,9 @@ class Fraction(ModelSQL, ModelView):
if a_id in analysis_ids:
analysis = Analysis(a_id)
self.duplicated_analysis_message = (
self.raise_user_error('duplicated_analysis',
(analysis.rec_name,),
raise_exception=False))
gettext(
'lims.msg_duplicated_analysis_fraction',
analysis=analysis.rec_name))
return
analysis_ids.extend(new_analysis_ids)
@ -2321,14 +2306,6 @@ class Sample(ModelSQL, ModelView):
def __setup__(cls):
super(Sample, cls).__setup__()
cls._order.insert(0, ('number', 'DESC'))
cls._error_messages.update({
'no_sample_sequence': ('There is no sample sequence for '
'the work year "%s".'),
'duplicated_label': ('The label "%s" is already present in '
'another sample'),
'delete_sample': ('You can not delete sample "%s" because '
'its entry is not in draft state'),
})
@staticmethod
def default_date():
@ -2410,8 +2387,8 @@ class Sample(ModelSQL, ModelView):
workyear = LabWorkYear(workyear_id)
sequence = workyear.get_sequence('sample')
if not sequence:
cls.raise_user_error('no_sample_sequence',
(workyear.rec_name,))
raise UserError(gettext('lims.msg_no_sample_sequence',
work_year=workyear.rec_name))
vlist = [x.copy() for x in vlist]
for values in vlist:
@ -2423,6 +2400,7 @@ class Sample(ModelSQL, ModelView):
def warn_duplicated_label(self):
return # deactivated
Warning = Pool().get('res.user.warning')
if self.label:
duplicated = self.search([
('entry', '=', self.entry.id),
@ -2430,8 +2408,10 @@ class Sample(ModelSQL, ModelView):
('id', '!=', self.id),
])
if duplicated:
self.raise_user_warning('lims_sample_label@%s' %
self.number, 'duplicated_label', self.label)
key = 'lims_sample_label@%s' % self.number
if Warning.check(key):
raise UserWarning(gettext(
'lims.duplicated_label', label=self.label))
@classmethod
def write(cls, *args):
@ -2584,7 +2564,8 @@ class Sample(ModelSQL, ModelView):
def check_delete(cls, samples):
for sample in samples:
if sample.entry and sample.entry.state != 'draft':
cls.raise_user_error('delete_sample', (sample.rec_name,))
raise UserError(
gettext('lims.msg_delete_sample', sample=sample.rec_name))
@classmethod
def delete(cls, samples):
@ -2855,14 +2836,6 @@ class ManageServices(Wizard):
])
ok = StateTransition()
@classmethod
def __setup__(cls):
super(ManageServices, cls).__setup__()
cls._error_messages.update({
'counter_sample_date':
'Reverse counter sample storage to enter the service ',
})
def default_start(self, fields):
Fraction = Pool().get('lims.fraction')
@ -2895,7 +2868,7 @@ class ManageServices(Wizard):
if fraction.countersample_date is None:
return 'start'
else:
self.raise_user_error('counter_sample_date')
raise UserError(gettext('lims.msg_counter_sample_date'))
return 'end'
def transition_ok(self):
@ -3249,13 +3222,6 @@ class CountersampleStorage(Wizard):
storage = StateTransition()
open = StateAction('stock.act_shipment_internal_form')
@classmethod
def __setup__(cls):
super(CountersampleStorage, cls).__setup__()
cls._error_messages.update({
'reference': 'Countersamples Storage',
})
def default_start(self, fields):
res = {}
for field in ('report_date_from', 'report_date_to',
@ -3443,8 +3409,7 @@ class CountersampleStorage(Wizard):
with Transaction().set_user(0, set_context=True):
shipment = ShipmentInternal()
shipment.reference = CountersampleStorage.raise_user_error(
'reference', raise_exception=False)
shipment.reference = gettext('lims.msg_reference')
shipment.planned_date = planned_date
shipment.planned_start_date = planned_date
shipment.company = company
@ -3456,7 +3421,6 @@ class CountersampleStorage(Wizard):
def _get_stock_moves(self, fractions):
pool = Pool()
Config = pool.get('lims.configuration')
Fraction = pool.get('lims.fraction')
User = pool.get('res.user')
Move = pool.get('stock.move')
@ -3464,7 +3428,7 @@ class CountersampleStorage(Wizard):
if config_.fraction_product:
product = config_.fraction_product
else:
Fraction.raise_user_error('missing_fraction_product')
raise UserError(gettext('lims.msg_missing_fraction_product'))
company = User(Transaction().user).company
from_location = self.start.location_origin
@ -3569,13 +3533,6 @@ class CountersampleStorageRevert(Wizard):
revert = StateTransition()
open = StateAction('stock.act_shipment_internal_form')
@classmethod
def __setup__(cls):
super(CountersampleStorageRevert, cls).__setup__()
cls._error_messages.update({
'reference': 'Countersamples Storage Reversion',
})
def default_start(self, fields):
res = {}
for field in ('date_from', 'date_to'):
@ -3651,8 +3608,7 @@ class CountersampleStorageRevert(Wizard):
with Transaction().set_user(0, set_context=True):
shipment = ShipmentInternal()
shipment.reference = CountersampleStorageRevert.raise_user_error(
'reference', raise_exception=False)
shipment.reference = gettext('lims.msg_reference_reversion')
shipment.planned_date = today
shipment.planned_start_date = today
shipment.company = company
@ -3664,7 +3620,6 @@ class CountersampleStorageRevert(Wizard):
def _get_stock_moves(self, fractions):
pool = Pool()
Config = pool.get('lims.configuration')
Fraction = pool.get('lims.fraction')
User = pool.get('res.user')
Date = pool.get('ir.date')
Move = pool.get('stock.move')
@ -3673,7 +3628,7 @@ class CountersampleStorageRevert(Wizard):
if config_.fraction_product:
product = config_.fraction_product
else:
Fraction.raise_user_error('missing_fraction_product')
raise UserError(gettext('lims.msg_missing_fraction_product'))
company = User(Transaction().user).company
from_location = self.start.location_origin
@ -3764,13 +3719,6 @@ class CountersampleDischarge(Wizard):
discharge = StateTransition()
open = StateAction('stock.act_shipment_internal_form')
@classmethod
def __setup__(cls):
super(CountersampleDischarge, cls).__setup__()
cls._error_messages.update({
'reference': 'Countersamples Discharge',
})
def default_start(self, fields):
res = {}
for field in ('expiry_date_from', 'expiry_date_to',
@ -3848,8 +3796,7 @@ class CountersampleDischarge(Wizard):
with Transaction().set_user(0, set_context=True):
shipment = ShipmentInternal()
shipment.reference = CountersampleDischarge.raise_user_error(
'reference', raise_exception=False)
shipment.reference = gettext('lims.msg_reference_discharge')
shipment.planned_date = planned_date
shipment.planned_start_date = planned_date
shipment.company = company
@ -3861,7 +3808,6 @@ class CountersampleDischarge(Wizard):
def _get_stock_moves(self, fractions):
pool = Pool()
Config = pool.get('lims.configuration')
Fraction = pool.get('lims.fraction')
User = pool.get('res.user')
Move = pool.get('stock.move')
@ -3869,7 +3815,7 @@ class CountersampleDischarge(Wizard):
if config_.fraction_product:
product = config_.fraction_product
else:
Fraction.raise_user_error('missing_fraction_product')
raise UserError(gettext('lims.msg_missing_fraction_product'))
company = User(Transaction().user).company
from_location = self.start.location_origin
@ -3959,13 +3905,6 @@ class FractionDischarge(Wizard):
discharge = StateTransition()
open = StateAction('stock.act_shipment_internal_form')
@classmethod
def __setup__(cls):
super(FractionDischarge, cls).__setup__()
cls._error_messages.update({
'reference': 'Fractions Discharge',
})
def default_start(self, fields):
res = {}
for field in ('date_from', 'date_to'):
@ -4049,8 +3988,7 @@ class FractionDischarge(Wizard):
with Transaction().set_user(0, set_context=True):
shipment = ShipmentInternal()
shipment.reference = FractionDischarge.raise_user_error(
'reference', raise_exception=False)
shipment.reference = gettext('lims.msg_reference_fractions_discharge')
shipment.planned_date = planned_date
shipment.planned_start_date = planned_date
shipment.company = company
@ -4062,7 +4000,6 @@ class FractionDischarge(Wizard):
def _get_stock_moves(self, fractions):
pool = Pool()
Config = pool.get('lims.configuration')
Fraction = pool.get('lims.fraction')
User = pool.get('res.user')
Move = pool.get('stock.move')
@ -4070,7 +4007,7 @@ class FractionDischarge(Wizard):
if config_.fraction_product:
product = config_.fraction_product
else:
Fraction.raise_user_error('missing_fraction_product')
raise UserError(gettext('lims.msg_missing_fraction_product'))
company = User(Transaction().user).company
from_location = self.start.location_origin
@ -4158,13 +4095,6 @@ class FractionDischargeRevert(Wizard):
revert = StateTransition()
open = StateAction('stock.act_shipment_internal_form')
@classmethod
def __setup__(cls):
super(FractionDischargeRevert, cls).__setup__()
cls._error_messages.update({
'reference': 'Fractions Discharge Reversion',
})
def default_start(self, fields):
res = {}
for field in ('date_from', 'date_to'):
@ -4238,8 +4168,7 @@ class FractionDischargeRevert(Wizard):
with Transaction().set_user(0, set_context=True):
shipment = ShipmentInternal()
shipment.reference = FractionDischargeRevert.raise_user_error(
'reference', raise_exception=False)
shipment.reference = gettext('lims.msg_reference')
shipment.planned_date = today
shipment.planned_start_date = today
shipment.company = company
@ -4251,7 +4180,6 @@ class FractionDischargeRevert(Wizard):
def _get_stock_moves(self, fractions):
pool = Pool()
Config = pool.get('lims.configuration')
Fraction = pool.get('lims.fraction')
User = pool.get('res.user')
Date = pool.get('ir.date')
Move = pool.get('stock.move')
@ -4260,7 +4188,7 @@ class FractionDischargeRevert(Wizard):
if config_.fraction_product:
product = config_.fraction_product
else:
Fraction.raise_user_error('missing_fraction_product')
raise UserError(gettext('lims.msg_missing_fraction_product'))
company = User(Transaction().user).company
from_location = self.start.location_origin

View File

@ -1,5 +1,5 @@
[tryton]
version=5.0.0
version=5.2.0
depends:
carrier
party_relationship
@ -21,3 +21,4 @@ xml:
fraction.xml
stock.xml
party.xml
message.xml

View File

@ -178,30 +178,6 @@ this repository contains the full copyright notices and license terms. -->
<field name="group" ref="group_lims_control"/>
</record>
<!-- Users -->
<record model="res.user" id="user_acknowledgment_of_receipt">
<field name="login">user_cron_acknowledgment_of_receipt</field>
<field name="name">Cron Lims Acknowledgment Of Receipt</field>
<field name="signature"></field>
<field name="active" eval="False"/>
</record>
<record model="res.user-res.group" id="user_acknowledgment_of_receipt_group_entry">
<field name="user" ref="user_acknowledgment_of_receipt"/>
<field name="group" ref="group_lims_entry"/>
</record>
<record model="res.user" id="user_entry_confirm">
<field name="login">user_cron_entry_confirm</field>
<field name="name">Cron Lims Entry Confirm</field>
<field name="signature"></field>
<field name="active" eval="False"/>
</record>
<record model="res.user-res.group" id="user_entry_confirm_group_entry">
<field name="user" ref="user_entry_confirm"/>
<field name="group" ref="group_lims_entry"/>
</record>
<!-- Groups -->
<record model="res.group" id="group_lims_blind_sample_readonly">
@ -226,19 +202,6 @@ this repository contains the full copyright notices and license terms. -->
<field name="group" ref="group_lims_planification"/>
</record>
<!-- Users -->
<record model="res.user" id="user_planification_process">
<field name="login">user_cron_planification_process</field>
<field name="name">Cron Lims Planification Process</field>
<field name="signature"></field>
<field name="active" eval="False"/>
</record>
<record model="res.user-res.group" id="user_planification_process_group_planification">
<field name="user" ref="user_planification_process"/>
<field name="group" ref="group_lims_planification"/>
</record>
<menuitem parent="res.menu_res" action="act_lims_user_role_list"
id="lims_user_role_menu" sequence="5"/>

View File

@ -13,6 +13,7 @@ from . import lims
def register():
Pool.register(
configuration.Configuration,
configuration.Cron,
party.Party,
party.Address,
invoice.InvoiceContact,

View File

@ -6,7 +6,7 @@
from trytond.model import fields
from trytond.pool import PoolMeta
__all__ = ['Configuration']
__all__ = ['Configuration', 'Cron']
class Configuration(metaclass=PoolMeta):
@ -15,3 +15,14 @@ class Configuration(metaclass=PoolMeta):
mail_send_invoice_subject = fields.Char('Email subject of Invoice report',
help="In the text will be added suffix with the invoice report number")
mail_send_invoice_body = fields.Text('Email body of Invoice report')
class Cron(metaclass=PoolMeta):
__name__ = 'ir.cron'
@classmethod
def __setup__(cls):
super().__setup__()
cls.method.selection.extend([
('account.invoice|cron_send_invoice', "Cron Send Of Invoice"),
])

View File

@ -17,6 +17,8 @@ from trytond.pyson import Eval, Bool, Or
from trytond.transaction import Transaction
from trytond.tools import get_smtp_server
from trytond.config import config
from trytond.exceptions import UserError
from trytond.i18n import gettext
__all__ = ['Invoice', 'InvoiceContact', 'InvoiceLine', 'CreditInvoice',
'PopulateInvoiceContactsStart', 'PopulateInvoiceContacts', 'SendOfInvoice']
@ -50,9 +52,6 @@ class Invoice(metaclass=PoolMeta):
super(Invoice, cls).__setup__()
cls._check_modify_exclude.extend(['sent', 'sent_date',
'invoice_contacts', 'no_send_invoice'])
cls._error_messages.update({
'not_invoice_contacts': 'Invoice Contacts field must have a value',
})
@classmethod
def view_attributes(cls):
@ -90,7 +89,8 @@ class Invoice(metaclass=PoolMeta):
if invoice.type == 'out':
if (not invoice.no_send_invoice and not
invoice.invoice_contacts):
cls.raise_user_error('not_invoice_contacts')
raise UserError(gettext(
'lims_account_invoice.msg_not_invoice_contacts'))
@classmethod
def cron_send_invoice(cls):
@ -273,10 +273,6 @@ class InvoiceLine(metaclass=PoolMeta):
def __setup__(cls):
super(InvoiceLine, cls).__setup__()
cls.origin.states['readonly'] = True
cls._error_messages.update({
'delete_service_invoice': ('You can not delete an invoice line '
'related to a service ("%s")'),
})
@classmethod
def delete(cls, lines):
@ -289,8 +285,9 @@ class InvoiceLine(metaclass=PoolMeta):
for line in lines:
if (line.origin and line.origin.__name__ == 'lims.service' and not
line.economic_offer):
cls.raise_user_error('delete_service_invoice',
(line.origin.rec_name,))
raise UserError(
gettext('lims_account_invoice.msg_delete_service_invoice',
service=line.origin.rec_name))
@classmethod
def get_fraction_field(cls, lines, names):

View File

@ -69,32 +69,12 @@
<field name="group" ref="group_lims_account_invoice"/>
</record>
<!-- Users -->
<record model="res.user" id="user_send_invoice">
<field name="login">user_cron_send_invoice</field>
<field name="name">Cron Send Of Invoice</field>
<field name="signature"></field>
<field name="active" eval="False"/>
</record>
<record model="res.user-res.group" id="user_send_invoice_group_lims_account_invoice">
<field name="user" ref="user_send_invoice"/>
<field name="group" ref="group_lims_account_invoice"/>
</record>
<!-- Cron Send Of Invoice -->
<record model="ir.cron" id="cron_account_invoice_send_invoice">
<field name="name">Send Invoice</field>
<field name="request_user" ref="res.user_admin"/>
<field name="user" ref="user_send_invoice"/>
<field name="active" eval="True"/>
<field name="interval_number" eval="1"/>
<field name="interval_type">days</field>
<field name="number_calls" eval="-1"/>
<field name="repeat_missed" eval="False"/>
<field name="model">account.invoice</field>
<field name="function">cron_send_invoice</field>
<field name="method">account.invoice|cron_send_invoice</field>
</record>
<record model="ir.action.wizard" id="wiz_send_invoice">

View File

@ -7,6 +7,8 @@ from decimal import Decimal
from trytond.model import fields
from trytond.pool import Pool, PoolMeta
from trytond.transaction import Transaction
from trytond.exceptions import UserError
from trytond.i18n import gettext
__all__ = ['FractionType', 'Entry', 'Fraction', 'Service', 'ManageServices']
@ -67,16 +69,6 @@ class Fraction(metaclass=PoolMeta):
class Service(metaclass=PoolMeta):
__name__ = 'lims.service'
@classmethod
def __setup__(cls):
super(Service, cls).__setup__()
cls._error_messages.update({
'missing_account_revenue': ('Analysis product \"%(product)s\" in '
'Service "%(service)s" misses an "account revenue".'),
'delete_service_invoice': ('You can not delete a service '
'related to an invoice'),
})
@classmethod
def create(cls, vlist):
services = super(Service, cls).create(vlist)
@ -108,10 +100,10 @@ class Service(metaclass=PoolMeta):
return
account_revenue = product.account_revenue_used
if not account_revenue:
self.raise_user_error('missing_account_revenue', {
'product': self.analysis.product.rec_name,
'service': self.rec_name,
})
raise UserError(
gettext('lims_account_invoice.msg_missing_account_revenue',
product=self.analysis.product.rec_name,
service=self.rec_name))
party = self.entry.invoice_party
taxes = []
@ -167,7 +159,8 @@ class Service(metaclass=PoolMeta):
if lines_to_delete:
for line in lines_to_delete:
if line.invoice:
cls.raise_user_error('delete_service_invoice')
raise UserError(gettext(
'lims_account_invoice.msg_delete_service_invoice'))
with Transaction().set_context(_check_access=False,
delete_service=True):
InvoiceLine.delete(lines_to_delete)

View File

@ -0,0 +1,14 @@
<?xml version="1.0"?>
<tryton>
<data group="1">
<record model="ir.message" id="msg_not_invoice_contacts">
<field name="text">Invoice Contacts field must have a value</field>
</record>
<record model="ir.message" id="msg_delete_service_invoice">
<field name="text">You can not delete an invoice line related to a service ("%(service)s")</field>
</record>
<record model="ir.message" id="msg_missing_account_revenue">
<field name="text">Analysis product \"%(product)s\" in Service "%(service)s" misses an "account revenue".</field>
</record>
</data>
</tryton>

View File

@ -5,6 +5,8 @@
from trytond.model import fields
from trytond.pool import PoolMeta
from trytond.exceptions import UserError
from trytond.i18n import gettext
__all__ = ['Party', 'Address']
@ -40,4 +42,5 @@ class Address(metaclass=PoolMeta):
('id', '!=', self.id),
])
if addresses:
self.raise_user_error('invoice_address')
raise UserError(
gettext('lims_account_invoice.msg_invoice_address'))

View File

@ -1,5 +1,5 @@
[tryton]
version=5.0.0
version=5.2.0
depends:
lims
account_invoice
@ -9,3 +9,4 @@ xml:
invoice.xml
lims.xml
stock.xml
message.xml

View File

@ -1,5 +1,5 @@
[tryton]
version=5.0.0
version=5.2.0
depends:
lims
analytic_account

View File

@ -11,6 +11,7 @@ from . import digital_sign
def register():
Pool.register(
configuration.Configuration,
configuration.Cron,
lims.ResultsReportVersionDetail,
lims.ResultsReport,
digital_sign.DigitalSignStart,

View File

@ -6,7 +6,7 @@
from trytond.model import fields
from trytond.pool import PoolMeta
__all__ = ['Configuration']
__all__ = ['Configuration', 'Cron']
class Configuration(metaclass=PoolMeta):
@ -18,3 +18,15 @@ class Configuration(metaclass=PoolMeta):
mail_ack_report_body = fields.Text('Email body of Acknowledgment of'
' results report',
help='<SAMPLES> will be replaced by the list of sample\'s labels')
class Cron(metaclass=PoolMeta):
__name__ = 'ir.cron'
@classmethod
def __setup__(cls):
super().__setup__()
cls.method.selection.extend([
('lims.results_repor|cron_digital_signs',
"Cron Lims Digital Sign"),
])

View File

@ -12,32 +12,12 @@
<field name="group" ref="group_lims_digital_sign"/>
</record>
<!-- Users -->
<record model="res.user" id="user_digital_sign">
<field name="login">user_cron_digital_sign</field>
<field name="name">Cron Lims Digital Sign</field>
<field name="signature"></field>
<field name="active" eval="False"/>
</record>
<record model="res.user-res.group" id="user_digital_sign_group_digital_sign">
<field name="user" ref="user_digital_sign"/>
<field name="group" ref="group_lims_digital_sign"/>
</record>
<!-- Cron -->
<record model="ir.cron" id="cron_lims_digital_sign_results_reports">
<field name="name">Lims Digital Sign Results Reports</field>
<field name="request_user" ref="res.user_admin"/>
<field name="user" ref="user_digital_sign"/>
<field name="active" eval="True"/>
<field name="interval_number" eval="1"/>
<field name="interval_type">days</field>
<field name="number_calls" eval="-1"/>
<field name="repeat_missed" eval="False"/>
<field name="model">lims.results_report</field>
<field name="function">cron_digital_signs</field>
<field name="method">lims.results_repor|cron_digital_signs</field>
</record>
<!-- Wizard Digital Sign -->

View File

@ -16,6 +16,7 @@ from trytond.pool import Pool, PoolMeta
from trytond.transaction import Transaction
from trytond.tools import get_smtp_server
from trytond.config import config as tconfig
from trytond.i18n import gettext
from .tokenclient import GetToken
__all__ = ['ResultsReportVersionDetail', 'ResultsReport',
@ -61,13 +62,6 @@ class ResultsReport(metaclass=PoolMeta):
sent = fields.Boolean('Sent', readonly=True)
sent_date = fields.DateTime('Sent date', readonly=True)
@classmethod
def __setup__(cls):
super(ResultsReport, cls).__setup__()
cls._error_messages.update({
'polisample': 'Polisample',
})
@classmethod
def _get_modified_fields(cls):
fields = super(ResultsReport, cls)._get_modified_fields()
@ -263,8 +257,7 @@ class ResultsReport(metaclass=PoolMeta):
if len(sample_list) == 1:
label = '%s' % sample_list[0]
else:
label = self.raise_user_error('polisample',
raise_exception=False)
label = gettext('lims_digital_sign.msg_polisample')
subject = str('%s %s (%s)' % (
config.mail_ack_report_subject,
self.number, label)).strip()

View File

@ -0,0 +1,8 @@
<?xml version="1.0"?>
<tryton>
<data group="1">
<record model="ir.message" id="msg_polisample">
<field name="text">Polisample</field>
</record>
</data>
</tryton>

View File

@ -1,7 +1,8 @@
[tryton]
version=5.0.0
version=5.2.0
depends:
lims
xml:
digital_sign.xml
configuration.xml
message.xml

View File

@ -0,0 +1,32 @@
<?xml version="1.0"?>
<tryton>
<data group="1">
<record model="ir.message" id="msg_not_module">
<field name="text">No module for importer type "%(module)s"</field>
</record>
<record model="ir.message" id="msg_not_implemented">
<field name="text">The function "%(function)s" is not implemented for this importer</field>
</record>
<record model="ir.message" id="msg_invalid_alias">
<field name="text">Invalid symbol "%(symbol)s" in formula "%(name)s".</field>
</record>
<record model="ir.message" id="msg_invalid_store">
<field name="text">Formula "%(formula)s" cannot be stored because type is not set.</field>
</record>
<record model="ir.message" id="msg_end_date">
<field name="text">End date cannot be empty</field>
</record>
<record model="ir.message" id="msg_end_date_start_date">
<field name="text">End date cannot be lower than Start date</field>
</record>
<record model="ir.message" id="msg_inj_date_start_date">
<field name="text">Injection date cannot be lower than Start date</field>
</record>
<record model="ir.message" id="msg_inj_date_end_date">
<field name="text">Injection date cannot be upper than End date</field>
</record>
<record model="ir.message" id="msg_professionals">
<field name="text">Professional(s) with code %(code)s not identified</field>
</record>
</data>
</tryton>

View File

@ -2,10 +2,7 @@
# This file is part of lims_instrument module for Tryton.
# The COPYRIGHT file at the top level of this repository contains
# the full copyright notices and license terms.
try:
import io as StringIO
except ImportError:
import io
import io
import traceback
import xlrd
from xlutils.copy import copy
@ -15,6 +12,8 @@ from trytond.model import ModelView, ModelSQL, fields, Unique
from trytond.wizard import Wizard, StateView, StateTransition, Button
from trytond.pool import Pool, PoolMeta
from trytond.transaction import Transaction
from trytond.exceptions import UserError
from trytond.i18n import gettext
__all__ = ['NotebookLine', 'ResultsImport', 'NotebookLoadResultsFileStart',
@ -60,11 +59,6 @@ class ResultsImport(ModelSQL, ModelView):
('name_uniq', Unique(t, t.name),
'The results importer name must be unique'),
]
cls._error_messages.update({
'not_module': 'No module for importer type "%s"',
'not_implemented': ('The function "%s" is not implemented for'
' this importer'),
})
@fields.depends('name')
def on_change_with_description(self, name=None):
@ -75,12 +69,12 @@ class ResultsImport(ModelSQL, ModelView):
try:
description = self.controller.getControllerName()
except AttributeError:
self.raise_user_error('not_implemented',
('getControllerName',))
raise UserError(gettext('lims_instrument.msg_not_implemented',
function='getControllerName'))
return description
def loadController(self):
self.raise_user_error('not_module', (self.name,))
raise UserError(gettext('lims_instrument.msg_not_module', module=self.name))
def getInputFile(self):
return self._infile
@ -95,7 +89,7 @@ class ResultsImport(ModelSQL, ModelView):
return self.controller.parse(self, infile)
except AttributeError:
traceback.print_exc()
self.raise_user_error('not_implemented', ('parse',))
raise UserError(gettext('lims_instrument.msg_not_implemented', function='parse'))
def exportResults(self):
'''
@ -298,19 +292,6 @@ class NotebookLoadResultsFile(Wizard):
Button('Done', 'end', 'tryton-close', default=True),
])
@classmethod
def __setup__(cls):
super(NotebookLoadResultsFile, cls).__setup__()
cls._error_messages.update({
'end_date': 'End date cannot be empty',
'end_date_start_date': 'End date cannot be lower than Start date',
'inj_date_start_date': ('Injection date cannot be lower than '
'Start date'),
'inj_date_end_date': ('Injection date cannot be upper than '
'End date'),
'professionals': 'Professional(s) with code %s not identified',
})
def transition_collect(self):
cursor = Transaction().connection.cursor()
pool = Pool()
@ -488,23 +469,19 @@ class NotebookLoadResultsFile(Wizard):
if line.imported_result != '-1000.0':
if not line.imported_end_date:
prevent_line = True
outcome = self.raise_user_error('end_date',
raise_exception=False)
outcome = gettext('lims_instrument.msg_end_date')
elif (line.imported_end_date and line.start_date and
line.start_date > line.imported_end_date):
prevent_line = True
outcome = self.raise_user_error('end_date_start_date',
raise_exception=False)
outcome = gettext('lims_instrument.msg_end_date_start_date')
elif (line.imported_inj_date and line.start_date and
line.start_date > line.imported_inj_date):
prevent_line = True
outcome = self.raise_user_error('inj_date_start_date',
raise_exception=False)
outcome = gettext('lims_instrument.msg_inj_date_start_date')
elif (line.imported_end_date and line.imported_inj_date and
line.imported_inj_date > line.imported_end_date):
prevent_line = True
outcome = self.raise_user_error('inj_date_end_date',
raise_exception=False)
outcome = gettext('lims_instrument.msg_inj_date_end_date')
else:
line.result = line.imported_result
line.end_date = line.imported_end_date
@ -543,9 +520,8 @@ class NotebookLoadResultsFile(Wizard):
outcome = msg
else:
prevent_line = True
outcome = self.raise_user_error('professionals',
(str(line.imported_professionals),),
raise_exception=False)
outcome = gettext('lims_instrument.msg_professionals',
code=str(line.imported_professionals))
if prevent_line:
warnings = True

View File

@ -1,6 +1,7 @@
[tryton]
version=5.0.0
version=5.2.0
depends:
lims
xml:
resultsimport.xml
resultsimport.xml
message.xml

View File

@ -1,5 +1,5 @@
[tryton]
version=5.0.0
version=5.2.0
depends:
lims_instrument

View File

@ -1,5 +1,5 @@
[tryton]
version=5.0.0
version=5.2.0
depends:
lims_instrument

View File

@ -1,5 +1,5 @@
[tryton]
version=5.0.0
version=5.2.0
depends:
lims_instrument

View File

@ -0,0 +1,11 @@
<?xml version="1.0"?>
<tryton>
<data group="1">
<record model="ir.message" id="msg_quantity_multiple_required">
<field name="text">Quantity multiple of output bom required.</field>
</record>
<record model="ir.message" id="msg_invalid_product_uom_category">
<field name="text">The UoM\'s Category of each Product should be the same as the UoM\'s Category of Family/Equivalent.</field>
</record>
</data>
</tryton>

View File

@ -9,6 +9,8 @@ from trytond.pyson import Eval, Bool
from trytond.pool import PoolMeta, Pool
from trytond.transaction import Transaction
from trytond.report import Report
from trytond.exceptions import UserError
from trytond.i18n import gettext
__all__ = ['BOM', 'Production', 'FamilyEquivalentReport']
@ -50,14 +52,6 @@ class Production(metaclass=PoolMeta):
'on_change_with_salable_product')
comments = fields.Text('Comments')
@classmethod
def __setup__(cls):
super(Production, cls).__setup__()
cls._error_messages.update({
'quantity_multiple_required': ('Quantity multiple of output bom '
'required.'),
})
@fields.depends('product')
def on_change_with_salable_product(self, name=None):
if self.product:
@ -96,7 +90,8 @@ class Production(metaclass=PoolMeta):
for output in self.bom.outputs:
quantity += output.quantity
if not (self.quantity % quantity == 0):
self.raise_user_error('quantity_multiple_required')
raise UserError(
gettext('lims_production.msg_quantity_multiple_required'))
outputs = []

View File

@ -12,6 +12,8 @@ from trytond.transaction import Transaction
from trytond.pool import PoolMeta, Pool
from trytond.wizard import Wizard, StateAction
from trytond.modules.product import price_digits
from trytond.exceptions import UserError
from trytond.i18n import gettext
__all__ = ['PurityDegree', 'Brand', 'FamilyEquivalent', 'Template', 'Product',
'LotCategory', 'Lot', 'Move', 'ShipmentIn', 'MoveProductionRelated']
@ -46,15 +48,6 @@ class FamilyEquivalent(ModelSQL, ModelView):
products = fields.One2Many('product.template', 'family_equivalent',
'Products', readonly=True)
@classmethod
def __setup__(cls):
super(FamilyEquivalent, cls).__setup__()
cls._error_messages.update({
'invalid_product_uom_category': ('The UoM\'s Category '
'of each Product should be the same as the UoM\'s '
'Category of Family/Equivalent.'),
})
@classmethod
def validate(cls, family_equivalents):
super(FamilyEquivalent, cls).validate(family_equivalents)
@ -66,7 +59,8 @@ class FamilyEquivalent(ModelSQL, ModelView):
main_category = self.uom.category
for product in self.products:
if main_category != product.default_uom.category:
self.raise_user_error('invalid_product_uom_category')
raise UserError(gettext(
'lims_production.msg_invalid_product_uom_category'))
@classmethod
def copy(cls, family_equivalents, default=None):

View File

@ -1,5 +1,5 @@
[tryton]
version=5.0.0
version=5.2.0
depends:
lims
production
@ -9,4 +9,5 @@ depends:
xml:
stock.xml
production.xml
configuration.xml
configuration.xml
message.xml

View File

@ -1,5 +1,5 @@
[tryton]
version=5.0.0
version=5.2.0
depends:
lims
xml:

View File

@ -1,5 +1,5 @@
[tryton]
version=5.0.0
version=5.2.0
depends:
lims_project
xml:

View File

@ -0,0 +1,26 @@
<?xml version="1.0"?>
<tryton>
<data group="1">
<record model="ir.message" id="msg_no_project_study_plan_sequence">
<field name="text">There is no sequence for Study plan Projects for the work year "%(work_year)s".</field>
</record>
<record model="ir.message" id="msg_not_glp">
<field name="text">Please, select a "Study plan" Project to print this report</field>
</record>
<record model="ir.message" id="msg_not_analytical_phase">
<field name="text">Please, select a "Analytical Phase Project" to print this report</field>
</record>
<record model="ir.message" id="msg_not_study_plan">
<field name="text">Please, select a "Study Plan Phase Project" to print this report</field>
</record>
<record model="ir.message" id="msg_existing_role_study_director">
<field name="text">There is already a Study director for this project</field>
</record>
<record model="ir.message" id="msg_existing_role_facility_director">
<field name="text">There is already a Facility director for this project</field>
</record>
<record model="ir.message" id="msg_existing_role_quality_unit">
<field name="text">There is already a Quality unit for this project</field>
</record>
</data>
</tryton>

View File

@ -11,6 +11,8 @@ from trytond.transaction import Transaction
from trytond.wizard import Wizard, StateTransition, StateView, StateAction, \
Button
from trytond.report import Report
from trytond.exceptions import UserError
from trytond.i18n import gettext
__all__ = ['Project', 'Entry', 'ProjectReferenceElement',
'ProjectSolventAndReagent', 'ProjectSampleInCustody',
@ -226,16 +228,6 @@ class Project(metaclass=PoolMeta):
'invisible': (Eval('stp_state') != 'finalized'),
},
})
cls._error_messages.update({
'no_project_study_plan_sequence': ('There is no sequence for '
'Study plan Projects for the work year "%s".'),
'not_glp': ('Please, select a "Study plan" Project to print this '
'report'),
'not_analytical_phase': ('Please, select a "Analytical Phase '
'Project" to print this report'),
'not_study_plan': ('Please, select a "Study Plan Phase '
'Project" to print this report'),
})
@classmethod
def view_attributes(cls):
@ -254,8 +246,9 @@ class Project(metaclass=PoolMeta):
workyear = LabWorkYear(workyear_id)
sequence = workyear.get_sequence('project_study_plan')
if not sequence:
cls.raise_user_error('no_project_study_plan_sequence',
(workyear.rec_name,))
raise UserError(gettext(
'lims_project_study_plan.msg_no_project_study_plan_sequence',
work_year=workyear.rec_name))
vlist = [x.copy() for x in vlist]
for values in vlist:
@ -297,7 +290,8 @@ class Project(metaclass=PoolMeta):
if line.device.id not in devices:
devices[line.device.id] = line.device.rec_name
if devices:
stp_test_system = '\n'.join([d for d in list(devices.values())])
stp_test_system = '\n'.join(
[d for d in list(devices.values())])
self.stp_test_system = stp_test_system
@ModelView.button_change('stp_test_method')
@ -315,7 +309,8 @@ class Project(metaclass=PoolMeta):
if line.method.id not in methods:
methods[line.method.id] = line.method.rec_name
if methods:
stp_test_method = '\n'.join([m for m in list(methods.values())])
stp_test_method = '\n'.join(
[m for m in list(methods.values())])
self.stp_test_method = stp_test_method
@classmethod
@ -413,18 +408,6 @@ class ProjectLaboratoryProfessional(ModelSQL, ModelView):
role_other = fields.Boolean('Other')
approval_date = fields.Date('Approval date')
@classmethod
def __setup__(cls):
super(ProjectLaboratoryProfessional, cls).__setup__()
cls._error_messages.update({
'existing_role_study_director': ('There is already a '
'Study director for this project'),
'existing_role_facility_director': ('There is already a '
'Facility director for this project'),
'existing_role_quality_unit': ('There is already a '
'Quality unit for this project'),
})
@classmethod
def validate(cls, professionals):
super(ProjectLaboratoryProfessional, cls).validate(professionals)
@ -441,7 +424,8 @@ class ProjectLaboratoryProfessional(ModelSQL, ModelView):
('id', '!=', self.id),
])
if existing_roles:
self.raise_user_error('existing_' + field)
raise UserError(gettext(
'lims_project_study_plan.msg_existing_' + field))
@fields.depends('role_study_director', 'role_facility_director',
'role_quality_unit', 'role_other')
@ -970,11 +954,11 @@ class ProjectGLPReport01(Report):
def execute(cls, ids, data):
Project = Pool().get('lims.project')
if len(ids) > 1:
Project.raise_user_error('not_glp')
raise UserError(gettext('lims_project_study_plan.msg_not_glp'))
project = Project(ids[0])
if project.type != 'study_plan':
Project.raise_user_error('not_glp')
raise UserError(gettext('lims_project_study_plan.msg_not_glp'))
return super(ProjectGLPReport01, cls).execute(ids, data)
@ -1033,11 +1017,11 @@ class ProjectGLPReport02(Report):
def execute(cls, ids, data):
Project = Pool().get('lims.project')
if len(ids) > 1:
Project.raise_user_error('not_glp')
raise UserError(gettext('lims_project_study_plan.msg_not_glp'))
project = Project(ids[0])
if project.type != 'study_plan':
Project.raise_user_error('not_glp')
raise UserError(gettext('lims_project_study_plan.msg_not_glp'))
return super(ProjectGLPReport02, cls).execute(ids, data)
@ -1135,7 +1119,7 @@ class ProjectGLPReport03(Report):
project = Project(data['id'])
if project.type != 'study_plan':
Project.raise_user_error('not_glp')
raise UserError(gettext('lims_project_study_plan.msg_not_glp'))
return super(ProjectGLPReport03, cls).execute(ids, data)
@ -1192,11 +1176,11 @@ class ProjectGLPReport04(Report):
def execute(cls, ids, data):
Project = Pool().get('lims.project')
if len(ids) > 1:
Project.raise_user_error('not_glp')
raise UserError(gettext('lims_project_study_plan.msg_not_glp'))
project = Project(ids[0])
if project.type != 'study_plan':
Project.raise_user_error('not_glp')
raise UserError(gettext('lims_project_study_plan.msg_not_glp'))
return super(ProjectGLPReport04, cls).execute(ids, data)
@ -1299,7 +1283,7 @@ class ProjectGLPReport05(Report):
project = Project(data['id'])
if project.type != 'study_plan':
Project.raise_user_error('not_glp')
raise UserError(gettext('lims_project_study_plan.msg_not_glp'))
return super(ProjectGLPReport05, cls).execute(ids, data)
@ -1354,11 +1338,11 @@ class ProjectGLPReport06(Report):
def execute(cls, ids, data):
Project = Pool().get('lims.project')
if len(ids) > 1:
Project.raise_user_error('not_glp')
raise UserError(gettext('lims_project_study_plan.msg_not_glp'))
project = Project(ids[0])
if project.type != 'study_plan':
Project.raise_user_error('not_glp')
raise UserError(gettext('lims_project_study_plan.msg_not_glp'))
return super(ProjectGLPReport06, cls).execute(ids, data)
@ -1411,11 +1395,11 @@ class ProjectGLPReport07(Report):
def execute(cls, ids, data):
Project = Pool().get('lims.project')
if len(ids) > 1:
Project.raise_user_error('not_glp')
raise UserError(gettext('lims_project_study_plan.msg_not_glp'))
project = Project(ids[0])
if project.type != 'study_plan':
Project.raise_user_error('not_glp')
raise UserError(gettext('lims_project_study_plan.msg_not_glp'))
return super(ProjectGLPReport07, cls).execute(ids, data)
@ -1476,11 +1460,11 @@ class ProjectGLPReport08(Report):
def execute(cls, ids, data):
Project = Pool().get('lims.project')
if len(ids) > 1:
Project.raise_user_error('not_glp')
raise UserError(gettext('lims_project_study_plan.msg_not_glp'))
project = Project(ids[0])
if project.type != 'study_plan':
Project.raise_user_error('not_glp')
raise UserError(gettext('lims_project_study_plan.msg_not_glp'))
return super(ProjectGLPReport08, cls).execute(ids, data)
@ -1538,11 +1522,11 @@ class ProjectGLPReport09(Report):
def execute(cls, ids, data):
Project = Pool().get('lims.project')
if len(ids) > 1:
Project.raise_user_error('not_glp')
raise UserError(gettext('lims_project_study_plan.msg_not_glp'))
project = Project(ids[0])
if project.type != 'study_plan':
Project.raise_user_error('not_glp')
raise UserError(gettext('lims_project_study_plan.msg_not_glp'))
return super(ProjectGLPReport09, cls).execute(ids, data)
@ -1608,7 +1592,7 @@ class ProjectGLPReport09(Report):
re = None
analysis = None
if report_id[1] == 'eq':
re = report_id[2]
re = report_id[2]
else:
if report_id[1] == 'low':
re = '< ' + report_id[2]
@ -1754,11 +1738,11 @@ class ProjectGLPReport11(Report):
def execute(cls, ids, data):
Project = Pool().get('lims.project')
if len(ids) > 1:
Project.raise_user_error('not_glp')
raise UserError(gettext('lims_project_study_plan.msg_not_glp'))
project = Project(ids[0])
if project.type != 'study_plan':
Project.raise_user_error('not_glp')
raise UserError(gettext('lims_project_study_plan.msg_not_glp'))
return super(ProjectGLPReport11, cls).execute(ids, data)
@ -1913,11 +1897,11 @@ class ProjectGLPReportStudyPlan(Report):
def execute(cls, ids, data):
Project = Pool().get('lims.project')
if len(ids) > 1:
Project.raise_user_error('not_glp')
raise UserError(gettext('lims_project_study_plan.msg_not_glp'))
project = Project(ids[0])
if project.type != 'study_plan':
Project.raise_user_error('not_glp')
raise UserError(gettext('lims_project_study_plan.msg_not_glp'))
return super(ProjectGLPReportStudyPlan, cls).execute(ids, data)
@ -2007,14 +1991,15 @@ class ProjectGLPReportFinalRP(Report):
def execute(cls, ids, data):
Project = Pool().get('lims.project')
if len(ids) > 1:
Project.raise_user_error('not_glp')
raise UserError(gettext('lims_project_study_plan.msg_not_glp'))
project = Project(ids[0])
if project.type != 'study_plan':
Project.raise_user_error('not_glp')
raise UserError(gettext('lims_project_study_plan.msg_not_glp'))
else:
if project.stp_phase != 'study_plan':
Project.raise_user_error('not_study_plan')
raise UserError(gettext(
'lims_project_study_plan.msg_not_study_plan'))
return super(ProjectGLPReportFinalRP, cls).execute(ids, data)
@classmethod
@ -2248,14 +2233,15 @@ class ProjectGLPReportFinalFOR(Report):
def execute(cls, ids, data):
Project = Pool().get('lims.project')
if len(ids) > 1:
Project.raise_user_error('not_glp')
raise UserError(gettext('lims_project_study_plan.msg_not_glp'))
project = Project(ids[0])
if project.type != 'study_plan':
Project.raise_user_error('not_glp')
raise UserError(gettext('lims_project_study_plan.msg_not_glp'))
else:
if project.stp_phase != 'study_plan':
Project.raise_user_error('not_study_plan')
raise UserError(gettext(
'lims_project_study_plan.msg_not_study_plan'))
return super(ProjectGLPReportFinalFOR, cls).execute(ids, data)
@classmethod
@ -2494,14 +2480,15 @@ class ProjectGLPReportAnalyticalPhase(Report):
def execute(cls, ids, data):
Project = Pool().get('lims.project')
if len(ids) > 1:
Project.raise_user_error('not_glp')
raise UserError(gettext('lims_project_study_plan.msg_not_glp'))
project = Project(ids[0])
if project.type != 'study_plan':
Project.raise_user_error('not_glp')
raise UserError(gettext('lims_project_study_plan.msg_not_glp'))
else:
if project.stp_phase != 'analytical_phase':
Project.raise_user_error('not_analytical_phase')
raise UserError(gettext(
'lims_project_study_plan.msg_not_analytical_phase'))
return super(ProjectGLPReportAnalyticalPhase,
cls).execute(ids, data)
@ -2736,11 +2723,11 @@ class ProjectGLPReport13(Report):
def execute(cls, ids, data):
Project = Pool().get('lims.project')
if len(ids) > 1:
Project.raise_user_error('not_glp')
raise UserError(gettext('lims_project_study_plan.msg_not_glp'))
project = Project(ids[0])
if project.type != 'study_plan':
Project.raise_user_error('not_glp')
raise UserError(gettext('lims_project_study_plan.msg_not_glp'))
return super(ProjectGLPReport13, cls).execute(ids, data)

View File

@ -1,8 +1,9 @@
[tryton]
version=5.0.0
version=5.2.0
depends:
lims_project
lims_production
xml:
project.xml
configuration.xml
message.xml

View File

@ -0,0 +1,8 @@
<?xml version="1.0"?>
<tryton>
<data group="1">
<record model="ir.message" id="msg_no_project_tas_sequence">
<field name="text">There is no sequence for TAS Projects for the work year "%(work_year)s".</field>
</record>
</data>
</tryton>

View File

@ -6,6 +6,8 @@
from trytond.model import ModelView, ModelSQL, fields, Unique
from trytond.pool import Pool, PoolMeta
from trytond.pyson import Eval, Equal, Bool, Not
from trytond.exceptions import UserError
from trytond.i18n import gettext
__all__ = ['TasType', 'Project', 'Entry']
@ -44,10 +46,6 @@ class Project(metaclass=PoolMeta):
cls.type.selection.append(project_type)
cls.client.states = STATES
cls.client.depends = DEPENDS
cls._error_messages.update({
'no_project_tas_sequence': ('There is no sequence for '
'TAS Projects for the work year "%s".'),
})
@classmethod
def view_attributes(cls):
@ -115,8 +113,9 @@ class Project(metaclass=PoolMeta):
workyear = LabWorkYear(workyear_id)
sequence = workyear.get_sequence('project_tas')
if not sequence:
cls.raise_user_error('no_project_tas_sequence',
(workyear.rec_name,))
raise UserError(gettext(
'lims_project_tas.msg_no_project_tas_sequence',
work_year=workyear.rec_name))
vlist = [x.copy() for x in vlist]
for values in vlist:

View File

@ -1,5 +1,5 @@
[tryton]
version=5.0.0
version=5.2.0
depends:
lims_project
extras_depend:
@ -8,3 +8,4 @@ xml:
project.xml
invoice.xml
configuration.xml
message.xml

View File

@ -0,0 +1,8 @@
<?xml version="1.0"?>
<tryton>
<data group="1">
<record model="ir.message" id="msg_not_water">
<field name="text">Please, select a "Water sampling" Project to print this report</field>
</record>
</data>
</tryton>

View File

@ -8,6 +8,8 @@ from trytond.pool import Pool, PoolMeta
from trytond.pyson import Eval, Equal, Bool, Not
from trytond.transaction import Transaction
from trytond.report import Report
from trytond.exceptions import UserError
from trytond.i18n import gettext
__all__ = ['Project', 'Entry', 'Sample', 'CreateSampleStart', 'CreateSample']
@ -29,10 +31,6 @@ class Project(metaclass=PoolMeta):
project_type = PROJECT_TYPE
if project_type not in cls.type.selection:
cls.type.selection.append(project_type)
cls._error_messages.update({
'not_water': ('Please, select a "Water sampling" Project to print '
'this report'),
})
@classmethod
def view_attributes(cls):
@ -140,7 +138,7 @@ class ProjectWaterSampling(Report):
project = Project(data['id'])
if project.type != 'water':
Project.raise_user_error('not_water')
raise UserError(gettext('lims_project_water.msg_not_water'))
return super(ProjectWaterSampling, cls).execute(ids, data)

View File

@ -1,7 +1,8 @@
[tryton]
version=5.0.0
version=5.2.0
depends:
lims_project
xml:
project.xml
message.xml

View File

@ -1,5 +1,5 @@
[tryton]
version=5.0.0
version=5.2.0
depends:
lims
sale

View File

@ -35,12 +35,12 @@ def get_require_version(name):
return require
version = '5.0.0'
version = '5.2.0'
major_version, minor_version, _ = version.split('.', 2)
major_version = int(major_version)
minor_version = int(minor_version)
requires = ['pytz', 'xlrd', 'xlutils', 'PyPDF2']
requires = ['pytz', 'xlrd', 'xlutils', 'PyPDF2', 'unidecode']
packages = []
package_dir = {}
package_data = {}