Compare commits
2 Commits
15aab43072
...
29d020aa96
Author | SHA1 | Date |
---|---|---|
Adrián Bernardi | 29d020aa96 | |
Adrián Bernardi | 7a52f2a87d |
|
@ -40,6 +40,7 @@ def register():
|
|||
configuration.LabWorkYearHoliday,
|
||||
configuration.Cron,
|
||||
configuration.Sequence,
|
||||
configuration.SmtpServer,
|
||||
laboratory.LaboratoryProfessional,
|
||||
laboratory.Laboratory,
|
||||
laboratory.LabMethod,
|
||||
|
|
|
@ -5,8 +5,11 @@
|
|||
from datetime import datetime
|
||||
from dateutil import rrule
|
||||
from sql import Null
|
||||
import logging
|
||||
import smtplib
|
||||
|
||||
from trytond.model import ModelSingleton, ModelView, ModelSQL, fields, Index
|
||||
from trytond.model import ModelSingleton, ModelView, ModelSQL, Workflow, \
|
||||
fields, Index
|
||||
from trytond.pyson import Eval, Id
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.pool import Pool, PoolMeta
|
||||
|
@ -15,6 +18,8 @@ from trytond.modules.company.model import (
|
|||
from trytond.exceptions import UserError
|
||||
from trytond.i18n import gettext
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
sequence_names = [
|
||||
'entry_sequence', 'sample_sequence', 'service_sequence',
|
||||
'results_report_sequence']
|
||||
|
@ -201,6 +206,9 @@ class Configuration(ModelSingleton, ModelSQL, ModelView,
|
|||
mail_ack_body = fields.Text('Email body of Acknowledgment of Samples'
|
||||
' Receipt')
|
||||
mail_ack_hide_recipients = fields.Boolean('Hide recipients')
|
||||
mail_ack_smtp = fields.Many2One('lims.smtp.server', 'SMTP for '
|
||||
'Acknowledgment of Samples Receipt',
|
||||
domain=[('state', '=', 'done')])
|
||||
microbiology_laboratories = fields.Many2Many(
|
||||
'lims.configuration-laboratory', 'configuration',
|
||||
'laboratory', 'Microbiology Laboratories')
|
||||
|
@ -280,6 +288,9 @@ class Configuration(ModelSingleton, ModelSQL, ModelView,
|
|||
mail_referral_subject = fields.Char('Email subject of Referral of Samples',
|
||||
help="A suffix with the referral number will be added to the text")
|
||||
mail_referral_body = fields.Text('Email body of Referral of Samples')
|
||||
mail_referral_smtp = fields.Many2One('lims.smtp.server', 'SMTP for '
|
||||
'Referral of Samples',
|
||||
domain=[('state', '=', 'done')])
|
||||
sample_fast_copy = fields.Boolean('Fast Sample Creation (Experimental)')
|
||||
|
||||
@staticmethod
|
||||
|
@ -692,3 +703,134 @@ class Sequence(metaclass=PoolMeta):
|
|||
date = Date.today()
|
||||
res['year2'] = date.strftime('%y')
|
||||
return res
|
||||
|
||||
|
||||
class SmtpServer(Workflow, ModelSQL, ModelView):
|
||||
'SMTP Server'
|
||||
__name__ = 'lims.smtp.server'
|
||||
|
||||
_states = {'readonly': (Eval('state') != 'draft')}
|
||||
|
||||
name = fields.Char('Name', required=True)
|
||||
smtp_server = fields.Char('Server', required=True, states=_states)
|
||||
smtp_port = fields.Integer('Port', required=True, states=_states)
|
||||
smtp_timeout = fields.Integer('Timeout', required=True, states=_states,
|
||||
help='Time in seconds')
|
||||
smtp_ssl = fields.Boolean('SSL', states=_states)
|
||||
smtp_tls = fields.Boolean('TLS', states=_states)
|
||||
smtp_user = fields.Char('User', states=_states)
|
||||
smtp_password = fields.Char('Password', strip=False, states=_states)
|
||||
smtp_email = fields.Char('Email', required=True, states=_states,
|
||||
help='Default From and Reply Email')
|
||||
state = fields.Selection([
|
||||
('draft', 'Draft'),
|
||||
('done', 'Done'),
|
||||
], 'State', readonly=True, required=True)
|
||||
|
||||
del _states
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
super().__setup__()
|
||||
cls._transitions |= set((
|
||||
('draft', 'done'),
|
||||
('done', 'draft'),
|
||||
))
|
||||
cls._buttons.update({
|
||||
'test_smtp_server': {},
|
||||
'draft': {
|
||||
'invisible': Eval('state') == 'draft',
|
||||
'depends': ['state'],
|
||||
},
|
||||
'done': {
|
||||
'invisible': Eval('state') == 'done',
|
||||
'depends': ['state'],
|
||||
},
|
||||
})
|
||||
|
||||
@staticmethod
|
||||
def default_smtp_timeout():
|
||||
return 60
|
||||
|
||||
@staticmethod
|
||||
def default_smtp_ssl():
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def default_smtp_port():
|
||||
return 465
|
||||
|
||||
@staticmethod
|
||||
def default_state():
|
||||
return 'draft'
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
@Workflow.transition('draft')
|
||||
def draft(cls, servers):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
@Workflow.transition('done')
|
||||
def done(cls, servers):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
def test_smtp_server(cls, servers):
|
||||
for server in servers:
|
||||
try:
|
||||
server.get_smtp_server()
|
||||
except Exception as message:
|
||||
logger.error('Exception getting SMTP Server: %s', message)
|
||||
raise UserError(gettext('lims.smtp_test_failed',
|
||||
error=message))
|
||||
raise UserError(gettext('lims.smtp_test_successful'))
|
||||
|
||||
def get_smtp_server(self):
|
||||
"""
|
||||
Instanciate, configure and return a SMTP or SMTP_SSL instance from
|
||||
smtplib.
|
||||
:return: A SMTP instance. The quit() method must be call when all
|
||||
the calls to sendmail() have been made.
|
||||
"""
|
||||
if self.smtp_ssl:
|
||||
smtp_server = smtplib.SMTP_SSL(self.smtp_server, self.smtp_port,
|
||||
timeout=self.smtp_timeout)
|
||||
else:
|
||||
smtp_server = smtplib.SMTP(self.smtp_server, self.smtp_port,
|
||||
timeout=self.smtp_timeout)
|
||||
|
||||
if self.smtp_tls:
|
||||
smtp_server.starttls()
|
||||
|
||||
if self.smtp_user and self.smtp_password:
|
||||
smtp_server.login(self.smtp_user, self.smtp_password)
|
||||
|
||||
return smtp_server
|
||||
|
||||
def send_mail(self, from_addr, to_addrs, msg):
|
||||
success = False
|
||||
server = None
|
||||
try:
|
||||
smtp_server = self.get_smtp_server()
|
||||
smtp_server.sendmail(from_addr, to_addrs, msg)
|
||||
smtp_server.quit()
|
||||
success = True
|
||||
except smtplib.SMTPException as error:
|
||||
logger.error('SMTPException: %s', error)
|
||||
if server is not None:
|
||||
server.quit()
|
||||
raise UserError(gettext('lims.smtp_exception', error=error))
|
||||
except smtplib.socket.error as error:
|
||||
logger.error('socket.error: %s', error)
|
||||
if server is not None:
|
||||
server.quit()
|
||||
raise UserError(gettext('lims.smtp_server_error', error=error))
|
||||
except smtplib.SMTPRecipientsRefused as error:
|
||||
logger.error('socket.error: %s', error)
|
||||
if server is not None:
|
||||
server.quit()
|
||||
raise UserError(gettext('lims.smtp_server_error', error=error))
|
||||
return success
|
||||
|
|
|
@ -219,5 +219,68 @@
|
|||
<field name="name">sequence_form</field>
|
||||
</record>
|
||||
|
||||
<!-- SMTP Servers -->
|
||||
|
||||
<record model="ir.ui.view" id="smtp_server_view_form">
|
||||
<field name="model">lims.smtp.server</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">smtp_server_form</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="smtp_server_view_list">
|
||||
<field name="model">lims.smtp.server</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">smtp_server_list</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_smtp_server">
|
||||
<field name="name">SMTP Servers</field>
|
||||
<field name="res_model">lims.smtp.server</field>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_smtp_server_view_list">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="smtp_server_view_list"/>
|
||||
<field name="act_window" ref="act_smtp_server"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_smtp_server_view_form">
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="view" ref="smtp_server_view_form"/>
|
||||
<field name="act_window" ref="act_smtp_server"/>
|
||||
</record>
|
||||
|
||||
<menuitem action="act_smtp_server" id="act_smtp_server_menu"
|
||||
parent="lims_config_base" sequence="40"/>
|
||||
|
||||
<record model="ir.model.button" id="smtp_server_test_smtp_server_button">
|
||||
<field name="name">test_smtp_server</field>
|
||||
<field name="string">Test Connection</field>
|
||||
<field name="model" search="[('model', '=', 'lims.smtp.server')]"/>
|
||||
</record>
|
||||
<record model="ir.model.button" id="smtp_server_draft_button">
|
||||
<field name="name">draft</field>
|
||||
<field name="string">Draft</field>
|
||||
<field name="model" search="[('model', '=', 'lims.smtp.server')]"/>
|
||||
</record>
|
||||
<record model="ir.model.button" id="smtp_server_done_button">
|
||||
<field name="name">done</field>
|
||||
<field name="string">Confirm</field>
|
||||
<field name="model" search="[('model', '=', 'lims.smtp.server')]"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_smtp_server">
|
||||
<field name="model" search="[('model', '=', 'lims.smtp.server')]"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_smtp_server_group_smtp_server">
|
||||
<field name="model" search="[('model', '=', 'lims.smtp.server')]"/>
|
||||
<field name="group" ref="group_lims_smtp_server"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
<field name="perm_create" eval="True"/>
|
||||
<field name="perm_delete" eval="True"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</tryton>
|
||||
|
|
|
@ -662,19 +662,21 @@ class Entry(Workflow, ModelSQL, ModelView):
|
|||
if not self.ack_report_cache:
|
||||
return
|
||||
|
||||
from_addr = tconfig.get('email', 'from')
|
||||
config_ = Config(1)
|
||||
smtp_server = config_.mail_ack_smtp
|
||||
from_addr = (smtp_server and smtp_server.smtp_email or
|
||||
tconfig.get('email', 'from'))
|
||||
to_addrs = [c.contact.email for c in self.acknowledgment_contacts]
|
||||
if not (from_addr and to_addrs):
|
||||
return
|
||||
|
||||
config = Config(1)
|
||||
hide_recipients = config.mail_ack_hide_recipients
|
||||
|
||||
hide_recipients = config_.mail_ack_hide_recipients
|
||||
subject, body = self.subject_body()
|
||||
attachment_data = self.attachment()
|
||||
|
||||
msg = self.create_msg(from_addr, to_addrs, subject,
|
||||
body, hide_recipients, attachment_data)
|
||||
return self.send_msg(from_addr, to_addrs, msg)
|
||||
return self.send_msg(smtp_server, from_addr, to_addrs, msg)
|
||||
|
||||
def subject_body(self):
|
||||
pool = Pool()
|
||||
|
@ -734,17 +736,20 @@ class Entry(Workflow, ModelSQL, ModelView):
|
|||
msg.attach(attachment)
|
||||
return msg
|
||||
|
||||
def send_msg(self, from_addr, to_addrs, msg):
|
||||
def send_msg(self, smtp_server, from_addr, to_addrs, msg):
|
||||
to_addrs = list(set(to_addrs))
|
||||
success = False
|
||||
server = None
|
||||
try:
|
||||
server = get_smtp_server()
|
||||
if smtp_server:
|
||||
server = smtp_server.get_smtp_server()
|
||||
else:
|
||||
server = get_smtp_server()
|
||||
server.sendmail(from_addr, to_addrs, msg.as_string())
|
||||
server.quit()
|
||||
success = True
|
||||
except Exception as e:
|
||||
logger.error('Unable to deliver mail for entry %s' % (self.number))
|
||||
logger.error('Unable to deliver mail for entry %s' % self.number)
|
||||
logger.error(str(e))
|
||||
if server is not None:
|
||||
server.quit()
|
||||
|
|
|
@ -447,6 +447,10 @@ msgctxt "field:lims.configuration,mail_ack_hide_recipients:"
|
|||
msgid "Hide recipients"
|
||||
msgstr "Ocultar destinatarios"
|
||||
|
||||
msgctxt "field:lims.configuration,mail_ack_smtp:"
|
||||
msgid "SMTP for Acknowledgment of Samples Receipt"
|
||||
msgstr "SMTP para Acuse de recibo de muestras"
|
||||
|
||||
msgctxt "field:lims.configuration,mail_ack_subject:"
|
||||
msgid "Email subject of Acknowledgment of Samples Receipt"
|
||||
msgstr "Asunto del correo de Acuse de recibo de muestras"
|
||||
|
@ -455,6 +459,10 @@ msgctxt "field:lims.configuration,mail_referral_body:"
|
|||
msgid "Email body of Referral of Samples"
|
||||
msgstr "Cuerpo del correo de Derivación de muestras"
|
||||
|
||||
msgctxt "field:lims.configuration,mail_referral_smtp:"
|
||||
msgid "SMTP for Referral of Samples"
|
||||
msgstr "SMTP para Derivación de muestras"
|
||||
|
||||
msgctxt "field:lims.configuration,mail_referral_subject:"
|
||||
msgid "Email subject of Referral of Samples"
|
||||
msgstr "Asunto del correo de Derivación de muestras"
|
||||
|
@ -6315,6 +6323,46 @@ msgctxt "field:lims.service.additional_origin,service:"
|
|||
msgid "Service"
|
||||
msgstr "Servicio"
|
||||
|
||||
msgctxt "field:lims.smtp.server,name:"
|
||||
msgid "Name"
|
||||
msgstr "Nombre"
|
||||
|
||||
msgctxt "field:lims.smtp.server,smtp_email:"
|
||||
msgid "Email"
|
||||
msgstr "Correo electrónico"
|
||||
|
||||
msgctxt "field:lims.smtp.server,smtp_password:"
|
||||
msgid "Password"
|
||||
msgstr "Contraseña"
|
||||
|
||||
msgctxt "field:lims.smtp.server,smtp_port:"
|
||||
msgid "Port"
|
||||
msgstr "Puerto"
|
||||
|
||||
msgctxt "field:lims.smtp.server,smtp_server:"
|
||||
msgid "Server"
|
||||
msgstr "Servidor"
|
||||
|
||||
msgctxt "field:lims.smtp.server,smtp_ssl:"
|
||||
msgid "SSL"
|
||||
msgstr "SSL"
|
||||
|
||||
msgctxt "field:lims.smtp.server,smtp_timeout:"
|
||||
msgid "Timeout"
|
||||
msgstr "Timeout"
|
||||
|
||||
msgctxt "field:lims.smtp.server,smtp_tls:"
|
||||
msgid "TLS"
|
||||
msgstr "TLS"
|
||||
|
||||
msgctxt "field:lims.smtp.server,smtp_user:"
|
||||
msgid "User"
|
||||
msgstr "Usuario"
|
||||
|
||||
msgctxt "field:lims.smtp.server,state:"
|
||||
msgid "State"
|
||||
msgstr "Estado"
|
||||
|
||||
msgctxt "field:lims.technical.scope,certification_type:"
|
||||
msgid "Certification type"
|
||||
msgstr "Tipo de certificación"
|
||||
|
@ -7273,6 +7321,14 @@ msgstr ""
|
|||
"Para las condiciones \"En\" y \"No en\", utilice una lista de valores "
|
||||
"separados por comas (Ej.: AB, CD, 12, 34)"
|
||||
|
||||
msgctxt "help:lims.smtp.server,smtp_email:"
|
||||
msgid "Default From and Reply Email"
|
||||
msgstr "Correo electrónico predeterminado para remitente y respuesta"
|
||||
|
||||
msgctxt "help:lims.smtp.server,smtp_timeout:"
|
||||
msgid "Time in seconds"
|
||||
msgstr "Tiempo en segundos"
|
||||
|
||||
msgctxt "help:lims.trend.chart,active:"
|
||||
msgid "Check to include in future use"
|
||||
msgstr "Marcar para usar en el futuro."
|
||||
|
@ -7641,6 +7697,10 @@ msgctxt "model:ir.action,name:act_service_referred_pending_result_list"
|
|||
msgid "Referred Services Pending Result"
|
||||
msgstr "Servicios derivados pendientes de resultado"
|
||||
|
||||
msgctxt "model:ir.action,name:act_smtp_server"
|
||||
msgid "SMTP Servers"
|
||||
msgstr "Servidores SMTP"
|
||||
|
||||
msgctxt "model:ir.action,name:act_trend_chart_data"
|
||||
msgid "Trend Chart"
|
||||
msgstr "Gráfico de tendencia"
|
||||
|
@ -9169,6 +9229,30 @@ msgctxt "model:ir.message,text:msg_zone_code_unique_id"
|
|||
msgid "Zone code must be unique"
|
||||
msgstr "El código de la zona debe ser único"
|
||||
|
||||
msgctxt "model:ir.message,text:smtp_exception"
|
||||
msgid ""
|
||||
"SMTP Server exception (Email not sent):\n"
|
||||
"%(error)s"
|
||||
msgstr ""
|
||||
"Excepción de Servidor SMTP (Correo no enviado):\n"
|
||||
"%(error)s"
|
||||
|
||||
msgctxt "model:ir.message,text:smtp_server_error"
|
||||
msgid "Error: could not connect to server. (Email not sent)"
|
||||
msgstr "Error: no se pudo conectar al servidor. (Correo no enviado)"
|
||||
|
||||
msgctxt "model:ir.message,text:smtp_test_failed"
|
||||
msgid ""
|
||||
"SMTP test connection failed:\n"
|
||||
"%(error)s"
|
||||
msgstr ""
|
||||
"La conexión SMTP de prueba falló:\n"
|
||||
"%(error)s"
|
||||
|
||||
msgctxt "model:ir.message,text:smtp_test_successful"
|
||||
msgid "SMTP test connection was successful"
|
||||
msgstr "La conexión SMTP de prueba fue exitosa"
|
||||
|
||||
msgctxt "model:ir.model.button,confirm:entry_confirm_button"
|
||||
msgid "Are you sure you want to confirm the entry?"
|
||||
msgstr "¿Está seguro que desea confirmar el ingreso?"
|
||||
|
@ -9185,6 +9269,18 @@ msgctxt "model:ir.model.button,string:means_deviations_calc_select_all_button"
|
|||
msgid "Select All"
|
||||
msgstr "Seleccionar todo"
|
||||
|
||||
msgctxt "model:ir.model.button,string:smtp_server_done_button"
|
||||
msgid "Confirm"
|
||||
msgstr "Confirmar"
|
||||
|
||||
msgctxt "model:ir.model.button,string:smtp_server_draft_button"
|
||||
msgid "Draft"
|
||||
msgstr "Borrador"
|
||||
|
||||
msgctxt "model:ir.model.button,string:smtp_server_test_smtp_server_button"
|
||||
msgid "Test Connection"
|
||||
msgstr "Probar conexión"
|
||||
|
||||
msgctxt "model:ir.rule.group,name:rule_group_analysis_device"
|
||||
msgid "User in laboratory"
|
||||
msgstr ""
|
||||
|
@ -9273,6 +9369,10 @@ msgctxt "model:ir.ui.menu,name:"
|
|||
msgid "Laboratory Notebook"
|
||||
msgstr "Cuaderno de laboratorio"
|
||||
|
||||
msgctxt "model:ir.ui.menu,name:act_smtp_server_menu"
|
||||
msgid "SMTP Servers"
|
||||
msgstr "Servidores SMTP"
|
||||
|
||||
msgctxt "model:ir.ui.menu,name:company_department_menu"
|
||||
msgid "Departments"
|
||||
msgstr "Departamentos"
|
||||
|
@ -10662,6 +10762,10 @@ msgctxt "model:lims.service.additional_origin,name:"
|
|||
msgid "Service Origin"
|
||||
msgstr "Origen de Servicio adicional"
|
||||
|
||||
msgctxt "model:lims.smtp.server,name:"
|
||||
msgid "SMTP Server"
|
||||
msgstr "Servidor SMTP"
|
||||
|
||||
msgctxt "model:lims.technical.scope,name:"
|
||||
msgid "Technical Scope"
|
||||
msgstr "Alcance técnico"
|
||||
|
@ -10898,6 +11002,10 @@ msgctxt "model:res.group,name:group_lims_planification_readonly"
|
|||
msgid "Lims Planification Read Only"
|
||||
msgstr "Lims Planificación Sólo lectura"
|
||||
|
||||
msgctxt "model:res.group,name:group_lims_smtp_server"
|
||||
msgid "Lims SMTP Server"
|
||||
msgstr "Lims Servidor SMTP"
|
||||
|
||||
msgctxt "model:res.group,name:group_lims_trend_chart"
|
||||
msgid "Lims Trend Charts"
|
||||
msgstr "Lims Gráficos de tendencia"
|
||||
|
@ -13945,6 +14053,14 @@ msgctxt "selection:lims.service,analysis_type:"
|
|||
msgid "Set"
|
||||
msgstr "Set"
|
||||
|
||||
msgctxt "selection:lims.smtp.server,state:"
|
||||
msgid "Done"
|
||||
msgstr "Confirmado"
|
||||
|
||||
msgctxt "selection:lims.smtp.server,state:"
|
||||
msgid "Draft"
|
||||
msgstr "Borrador"
|
||||
|
||||
msgctxt "selection:lims.trend.chart,filter:"
|
||||
msgid "Any Sample"
|
||||
msgstr "Cualquier muestra"
|
||||
|
@ -15312,6 +15428,10 @@ msgctxt "view:lims.service:"
|
|||
msgid "Time"
|
||||
msgstr "Hora"
|
||||
|
||||
msgctxt "view:lims.smtp.server:"
|
||||
msgid "Server"
|
||||
msgstr "Servidor"
|
||||
|
||||
msgctxt "view:lims.technical.scope.version.line:"
|
||||
msgid "Technical Scope Version Line"
|
||||
msgstr "Línea de versión de alcance técnico"
|
||||
|
|
|
@ -589,5 +589,19 @@ Rule 4: 1 value above or below the mean +/- 3 deviations.</field>
|
|||
<record model="ir.message" id="msg_invalid_email">
|
||||
<field name="text">Invalid email address</field>
|
||||
</record>
|
||||
<record model="ir.message" id="smtp_test_successful">
|
||||
<field name="text">SMTP test connection was successful</field>
|
||||
</record>
|
||||
<record model="ir.message" id="smtp_test_failed">
|
||||
<field name="text">SMTP test connection failed:
|
||||
%(error)s</field>
|
||||
</record>
|
||||
<record model="ir.message" id="smtp_exception">
|
||||
<field name="text">SMTP Server exception (Email not sent):
|
||||
%(error)s</field>
|
||||
</record>
|
||||
<record model="ir.message" id="smtp_server_error">
|
||||
<field name="text">Error: could not connect to server. (Email not sent)</field>
|
||||
</record>
|
||||
</data>
|
||||
</tryton>
|
||||
|
|
|
@ -6328,7 +6328,7 @@ class OpenNotebookLines(Wizard):
|
|||
|
||||
action['name'] = \
|
||||
'%s - %s - %s - %s - %s' % (notebook.fraction.number,
|
||||
notebook.party.name, notebook.product_type.description,
|
||||
notebook.party.code, notebook.product_type.description,
|
||||
notebook.matrix.description, notebook.label)
|
||||
return action, {}
|
||||
|
||||
|
|
|
@ -7732,9 +7732,12 @@ class Referral(ModelSQL, ModelView):
|
|||
|
||||
@classmethod
|
||||
def send_email_laboratory(cls, referrals):
|
||||
Warning = Pool().get('res.user.warning')
|
||||
pool = Pool()
|
||||
Warning = pool.get('res.user.warning')
|
||||
|
||||
from_addr = tconfig.get('email', 'from')
|
||||
smtp_server = None
|
||||
from_addr = (smtp_server and smtp_server.smtp_email or
|
||||
tconfig.get('email', 'from'))
|
||||
if not from_addr:
|
||||
logger.error("Missing configuration to send emails")
|
||||
return
|
||||
|
@ -7751,9 +7754,11 @@ class Referral(ModelSQL, ModelView):
|
|||
|
||||
subject, body = referral._get_mail_subject_body()
|
||||
attachment_data = referral._get_mail_attachment()
|
||||
|
||||
msg = cls.create_msg(from_addr, to_addrs, subject,
|
||||
body, attachment_data)
|
||||
cls.send_msg(from_addr, to_addrs, msg, referral.number)
|
||||
cls.send_msg(smtp_server, from_addr, to_addrs, msg,
|
||||
referral.number)
|
||||
|
||||
def _get_mail_recipients(self):
|
||||
pool = Pool()
|
||||
|
@ -7821,17 +7826,23 @@ class Referral(ModelSQL, ModelView):
|
|||
return msg
|
||||
|
||||
@staticmethod
|
||||
def send_msg(from_addr, to_addrs, msg, referral_number):
|
||||
def send_msg(smtp_server, from_addr, to_addrs, msg, referral_number):
|
||||
to_addrs = list(set(to_addrs))
|
||||
success = False
|
||||
server = None
|
||||
try:
|
||||
server = get_smtp_server()
|
||||
if smtp_server:
|
||||
server = smtp_server.get_smtp_server()
|
||||
else:
|
||||
server = get_smtp_server()
|
||||
server.sendmail(from_addr, to_addrs, msg.as_string())
|
||||
server.quit()
|
||||
success = True
|
||||
except Exception:
|
||||
logger.error(
|
||||
"Unable to deliver mail for referral '%s'" % (referral_number))
|
||||
"Unable to deliver mail for referral '%s'" % referral_number)
|
||||
if server is not None:
|
||||
server.quit()
|
||||
return success
|
||||
|
||||
|
||||
|
|
|
@ -203,6 +203,14 @@
|
|||
<field name="group" ref="group_lims_planification"/>
|
||||
</record>
|
||||
|
||||
<record model="res.group" id="group_lims_smtp_server">
|
||||
<field name="name">Lims SMTP Server</field>
|
||||
</record>
|
||||
<record model="res.user-res.group" id="user_admin_group_lims_smtp_server">
|
||||
<field name="user" ref="res.user_admin"/>
|
||||
<field name="group" ref="group_lims_smtp_server"/>
|
||||
</record>
|
||||
|
||||
<!-- Icons -->
|
||||
|
||||
<record model="ir.ui.icon" id="laboratory_icon">
|
||||
|
|
|
@ -69,6 +69,8 @@
|
|||
</page>
|
||||
<page string="Mail Acknowledgment of Samples Receipt"
|
||||
id="mail_ack_samples">
|
||||
<label name="mail_ack_smtp"/>
|
||||
<field name="mail_ack_smtp"/>
|
||||
<label name="mail_ack_hide_recipients"/>
|
||||
<field name="mail_ack_hide_recipients"/>
|
||||
<separator string="Email body of Acknowledgment of Samples Receipt"
|
||||
|
@ -77,6 +79,8 @@
|
|||
<field name="mail_ack_body" colspan="4"/>
|
||||
</page>
|
||||
<page string="Mail Referral of Samples" id="mail_referral" col="6">
|
||||
<label name="mail_referral_smtp"/>
|
||||
<field name="mail_referral_smtp"/>
|
||||
<separator string="Email subject of Referral of Samples"
|
||||
colspan="4" id="mail_referral_subject"/>
|
||||
<field name="mail_referral_subject" colspan="4"/>
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0"?>
|
||||
<form col="4">
|
||||
<label name="name"/>
|
||||
<field name="name"/>
|
||||
<notebook colspan="4">
|
||||
<page id="server" string="Server">
|
||||
<label name="smtp_server"/>
|
||||
<field name="smtp_server"/>
|
||||
<group id="smtp_header" col="4" colspan="2">
|
||||
<label name="smtp_port"/>
|
||||
<field name="smtp_port"/>
|
||||
<label name="smtp_timeout"/>
|
||||
<field name="smtp_timeout"/>
|
||||
</group>
|
||||
<label name="smtp_ssl"/>
|
||||
<field name="smtp_ssl"/>
|
||||
<label name="smtp_tls"/>
|
||||
<field name="smtp_tls"/>
|
||||
<label name="smtp_user"/>
|
||||
<field name="smtp_user"/>
|
||||
<label name="smtp_password"/>
|
||||
<field name="smtp_password" widget="password"/>
|
||||
<label name="smtp_email"/>
|
||||
<field name="smtp_email"/>
|
||||
<group id="server_buttons" col="6" colspan="6">
|
||||
<label name="state"/>
|
||||
<field name="state"/>
|
||||
<button name="draft" icon="tryton-clear"/>
|
||||
<button name="done" icon="tryton-forward"/>
|
||||
<button name="test_smtp_server" icon="tryton-ok"/>
|
||||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
</form>
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0"?>
|
||||
<tree>
|
||||
<field name="name"/>
|
||||
<field name="smtp_server"/>
|
||||
<field name="smtp_user"/>
|
||||
<field name="state"/>
|
||||
</tree>
|
|
@ -13,6 +13,9 @@ 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')
|
||||
mail_send_invoice_smtp = fields.Many2One('lims.smtp.server', 'SMTP for '
|
||||
'Invoice report',
|
||||
domain=[('state', '=', 'done')])
|
||||
|
||||
|
||||
class Cron(metaclass=PoolMeta):
|
||||
|
|
|
@ -18,7 +18,7 @@ from trytond.pool import Pool, PoolMeta
|
|||
from trytond.pyson import Eval, Bool, Or, If
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.tools import get_smtp_server
|
||||
from trytond.config import config
|
||||
from trytond.config import config as tconfig
|
||||
from trytond.exceptions import UserError
|
||||
from trytond.i18n import gettext
|
||||
|
||||
|
@ -114,10 +114,16 @@ class Invoice(metaclass=PoolMeta):
|
|||
tt)
|
||||
|
||||
def mail_send_invoice(self):
|
||||
pool = Pool()
|
||||
Config = pool.get('lims.configuration')
|
||||
|
||||
if not self.invoice_report_cache:
|
||||
return
|
||||
|
||||
from_addr = config.get('email', 'from')
|
||||
config_ = Config(1)
|
||||
smtp_server = config_.mail_send_invoice_smtp
|
||||
from_addr = (smtp_server and smtp_server.smtp_email or
|
||||
tconfig.get('email', 'from'))
|
||||
to_addrs = [c.contact.email for c in self.invoice_contacts]
|
||||
if not (from_addr and to_addrs):
|
||||
logger.warn('mail_send_invoice():Factura %s:Envio omitido '
|
||||
|
@ -128,9 +134,10 @@ class Invoice(metaclass=PoolMeta):
|
|||
|
||||
subject, body = self.subject_body()
|
||||
attachments_data = self.attachment()
|
||||
|
||||
msg = self.create_msg(from_addr, to_addrs, subject,
|
||||
body, attachments_data)
|
||||
return self.send_msg(from_addr, to_addrs, msg)
|
||||
return self.send_msg(smtp_server, from_addr, to_addrs, msg)
|
||||
|
||||
def subject_body(self):
|
||||
pool = Pool()
|
||||
|
@ -138,7 +145,7 @@ class Invoice(metaclass=PoolMeta):
|
|||
User = pool.get('res.user')
|
||||
Lang = pool.get('ir.lang')
|
||||
|
||||
config = Config(1)
|
||||
config_ = Config(1)
|
||||
|
||||
lang = User(Transaction().user).language
|
||||
if not lang:
|
||||
|
@ -147,9 +154,9 @@ class Invoice(metaclass=PoolMeta):
|
|||
], limit=1)
|
||||
|
||||
with Transaction().set_context(language=lang.code):
|
||||
subject = str('%s %s' % (config.mail_send_invoice_subject,
|
||||
subject = str('%s %s' % (config_.mail_send_invoice_subject,
|
||||
self.number)).strip()
|
||||
body = str(config.mail_send_invoice_body)
|
||||
body = str(config_.mail_send_invoice_body)
|
||||
|
||||
return subject, body
|
||||
|
||||
|
@ -204,16 +211,23 @@ class Invoice(metaclass=PoolMeta):
|
|||
msg.attach(attachment)
|
||||
return msg
|
||||
|
||||
def send_msg(self, from_addr, to_addrs, msg):
|
||||
def send_msg(self, smtp_server, from_addr, to_addrs, msg):
|
||||
to_addrs = list(set(to_addrs))
|
||||
success = False
|
||||
server = None
|
||||
try:
|
||||
server = get_smtp_server()
|
||||
if smtp_server:
|
||||
server = smtp_server.get_smtp_server()
|
||||
else:
|
||||
server = get_smtp_server()
|
||||
server.sendmail(from_addr, to_addrs, msg.as_string())
|
||||
server.quit()
|
||||
success = True
|
||||
except Exception:
|
||||
except Exception as e:
|
||||
logger.error('Unable to deliver mail for invoice %s', self.number)
|
||||
logger.error(str(e))
|
||||
if server is not None:
|
||||
server.quit()
|
||||
return success
|
||||
|
||||
|
||||
|
|
|
@ -54,6 +54,10 @@ msgctxt "field:lims.configuration,mail_send_invoice_body:"
|
|||
msgid "Email body of Invoice report"
|
||||
msgstr "Cuerpo del correo de Informe de factura"
|
||||
|
||||
msgctxt "field:lims.configuration,mail_send_invoice_smtp:"
|
||||
msgid "SMTP for Invoice report"
|
||||
msgstr "SMTP para Informe de factura"
|
||||
|
||||
msgctxt "field:lims.configuration,mail_send_invoice_subject:"
|
||||
msgid "Email subject of Invoice report"
|
||||
msgstr "Asunto del correo de Informe de factura"
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
<data>
|
||||
<xpath expr="/form/notebook/page[@id='general']" position="after">
|
||||
<page string="Mail Invoice Report" id="mail_send_invoice_report">
|
||||
<label name="mail_send_invoice_smtp"/>
|
||||
<field name="mail_send_invoice_smtp"/>
|
||||
<separator string="Email subject of Invoice report"
|
||||
colspan="4" id="mail_send_invoice_subject"/>
|
||||
<field name="mail_send_invoice_subject" colspan="4"/>
|
||||
|
|
|
@ -412,7 +412,9 @@ class AdministrativeTask(Workflow, ModelSQL, ModelView):
|
|||
|
||||
@classmethod
|
||||
def send_email_responsible(cls, tasks):
|
||||
from_addr = tconfig.get('email', 'from')
|
||||
smtp_server = None
|
||||
from_addr = (smtp_server and smtp_server.smtp_email or
|
||||
tconfig.get('email', 'from'))
|
||||
if not from_addr:
|
||||
logger.error("Missing configuration to send emails")
|
||||
return
|
||||
|
@ -429,12 +431,15 @@ class AdministrativeTask(Workflow, ModelSQL, ModelView):
|
|||
continue
|
||||
|
||||
subject, body = task._get_mail_subject_body()
|
||||
|
||||
msg = cls._create_msg(from_addr, to_addrs, subject, body)
|
||||
cls._send_msg(from_addr, to_addrs, msg, task.number)
|
||||
cls._send_msg(smtp_server, from_addr, to_addrs, msg, task.number)
|
||||
|
||||
@classmethod
|
||||
def send_email_update(cls, tasks):
|
||||
from_addr = tconfig.get('email', 'from')
|
||||
smtp_server = None
|
||||
from_addr = (smtp_server and smtp_server.smtp_email or
|
||||
tconfig.get('email', 'from'))
|
||||
if not from_addr:
|
||||
logger.error("Missing configuration to send emails")
|
||||
return
|
||||
|
@ -453,8 +458,9 @@ class AdministrativeTask(Workflow, ModelSQL, ModelView):
|
|||
continue
|
||||
|
||||
subject, body = task._get_mail_subject_body(True)
|
||||
|
||||
msg = cls._create_msg(from_addr, to_addrs, subject, body)
|
||||
cls._send_msg(from_addr, to_addrs, msg, task.number)
|
||||
cls._send_msg(smtp_server, from_addr, to_addrs, msg, task.number)
|
||||
|
||||
def _get_mail_subject_body(self, update=False):
|
||||
pool = Pool()
|
||||
|
@ -526,17 +532,23 @@ class AdministrativeTask(Workflow, ModelSQL, ModelView):
|
|||
return msg
|
||||
|
||||
@staticmethod
|
||||
def _send_msg(from_addr, to_addrs, msg, task_number):
|
||||
def _send_msg(smtp_server, from_addr, to_addrs, msg, task_number):
|
||||
to_addrs = list(set(to_addrs))
|
||||
success = False
|
||||
server = None
|
||||
try:
|
||||
server = get_smtp_server()
|
||||
if smtp_server:
|
||||
server = smtp_server.get_smtp_server()
|
||||
else:
|
||||
server = get_smtp_server()
|
||||
server.sendmail(from_addr, to_addrs, msg.as_string())
|
||||
server.quit()
|
||||
success = True
|
||||
except Exception:
|
||||
logger.error(
|
||||
"Unable to deliver email for task '%s'" % (task_number))
|
||||
"Unable to deliver email for task '%s'" % task_number)
|
||||
if server is not None:
|
||||
server.quit()
|
||||
return success
|
||||
|
||||
@classmethod
|
||||
|
|
|
@ -20,6 +20,9 @@ class Configuration(metaclass=PoolMeta):
|
|||
' results report',
|
||||
help='<SAMPLES> will be replaced by the list of sample\'s labels')
|
||||
mail_ack_report_hide_recipients = fields.Boolean('Hide recipients')
|
||||
mail_ack_report_smtp = fields.Many2One('lims.smtp.server', 'SMTP for '
|
||||
'Acknowledgment of results report',
|
||||
domain=[('state', '=', 'done')])
|
||||
result_report_format = fields.Many2One('lims.result_report.format',
|
||||
'Default Results Report Name Format')
|
||||
|
||||
|
|
|
@ -14,6 +14,10 @@ msgctxt "field:lims.configuration,mail_ack_report_hide_recipients:"
|
|||
msgid "Hide recipients"
|
||||
msgstr "Ocultar destinatarios"
|
||||
|
||||
msgctxt "field:lims.configuration,mail_ack_report_smtp:"
|
||||
msgid "SMTP for Acknowledgment of results report"
|
||||
msgstr "SMTP para Acuse de informe de resultados"
|
||||
|
||||
msgctxt "field:lims.configuration,mail_ack_report_subject:"
|
||||
msgid "Email subject of Acknowledgment of results report"
|
||||
msgstr "Asunto del correo de Acuse de informe de resultados"
|
||||
|
|
|
@ -483,16 +483,18 @@ class SendResultsReport(Wizard):
|
|||
ResultsReport = pool.get('lims.results_report')
|
||||
Lang = pool.get('ir.lang')
|
||||
|
||||
from_addr = tconfig.get('email', 'from')
|
||||
config_ = Config(1)
|
||||
smtp_server = config_.mail_ack_report_smtp
|
||||
from_addr = (smtp_server and smtp_server.smtp_email or
|
||||
tconfig.get('email', 'from'))
|
||||
if not from_addr:
|
||||
logger.warning('Send Results Report: FAILED')
|
||||
self.failed.reports_not_ready = []
|
||||
self.failed.reports_not_sent = []
|
||||
return 'failed'
|
||||
|
||||
config = Config(1)
|
||||
hide_recipients = config.mail_ack_report_hide_recipients
|
||||
email_qa = config.email_qa
|
||||
hide_recipients = config_.mail_ack_report_hide_recipients
|
||||
email_qa = config_.email_qa
|
||||
|
||||
context = Transaction().context
|
||||
model = context.get('active_model', None)
|
||||
|
@ -606,7 +608,7 @@ class SendResultsReport(Wizard):
|
|||
|
||||
msg = self._create_msg(from_addr, to_addrs, subject,
|
||||
body, hide_recipients, group['attachments_data'])
|
||||
sent = self._send_msg(from_addr, to_addrs, msg)
|
||||
sent = self._send_msg(smtp_server, from_addr, to_addrs, msg)
|
||||
if not sent:
|
||||
reports_not_sent.extend(group['reports_ready'])
|
||||
logger.warning('Send Results Report: Not sent')
|
||||
|
@ -635,12 +637,12 @@ class SendResultsReport(Wizard):
|
|||
Config = pool.get('lims.configuration')
|
||||
ResultsReport = pool.get('lims.results_report')
|
||||
|
||||
config = Config(1)
|
||||
config_ = Config(1)
|
||||
|
||||
res = {}
|
||||
results_reports = ResultsReport.browse(report_ids)
|
||||
|
||||
if not config.mail_ack_report_grouping:
|
||||
if not config_.mail_ack_report_grouping:
|
||||
for report in results_reports:
|
||||
if (report.invoice_party and
|
||||
hasattr(report.invoice_party,
|
||||
|
@ -654,7 +656,7 @@ class SendResultsReport(Wizard):
|
|||
}
|
||||
return res
|
||||
|
||||
if config.mail_ack_report_grouping == 'party':
|
||||
if config_.mail_ack_report_grouping == 'party':
|
||||
for report in results_reports:
|
||||
if (report.invoice_party and
|
||||
hasattr(report.invoice_party,
|
||||
|
@ -704,7 +706,7 @@ class SendResultsReport(Wizard):
|
|||
User = pool.get('res.user')
|
||||
Lang = pool.get('ir.lang')
|
||||
|
||||
config = Config(1)
|
||||
config_ = Config(1)
|
||||
|
||||
lang = User(Transaction().user).language
|
||||
if not lang:
|
||||
|
@ -720,9 +722,9 @@ class SendResultsReport(Wizard):
|
|||
else:
|
||||
label = gettext('lims_email.msg_polisample')
|
||||
subject = str('%s %s (%s)' % (
|
||||
config.mail_ack_report_subject,
|
||||
config_.mail_ack_report_subject,
|
||||
report_list, label)).strip()
|
||||
body = str(config.mail_ack_report_body)
|
||||
body = str(config_.mail_ack_report_body)
|
||||
|
||||
body = body.replace('<SAMPLES>', '\n'.join(sample_list))
|
||||
body = body.replace('<SAMPLES>', '\n'.join(sample_list))
|
||||
|
@ -770,12 +772,15 @@ class SendResultsReport(Wizard):
|
|||
msg.attach(attachment)
|
||||
return msg
|
||||
|
||||
def _send_msg(self, from_addr, to_addrs, msg):
|
||||
def _send_msg(self, smtp_server, from_addr, to_addrs, msg):
|
||||
to_addrs = list(set(to_addrs))
|
||||
success = False
|
||||
server = None
|
||||
try:
|
||||
server = get_smtp_server()
|
||||
if smtp_server:
|
||||
server = smtp_server.get_smtp_server()
|
||||
else:
|
||||
server = get_smtp_server()
|
||||
server.sendmail(from_addr, to_addrs, msg.as_string())
|
||||
server.quit()
|
||||
success = True
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
<field name="result_report_format"/>
|
||||
<label name="mail_ack_report_grouping"/>
|
||||
<field name="mail_ack_report_grouping"/>
|
||||
<label name="mail_ack_report_smtp"/>
|
||||
<field name="mail_ack_report_smtp"/>
|
||||
<label name="mail_ack_report_hide_recipients"/>
|
||||
<field name="mail_ack_report_hide_recipients"/>
|
||||
<separator string="Email subject of Acknowledgment of results report"
|
||||
|
|
|
@ -16,7 +16,7 @@ from trytond.wizard import Wizard, StateView, StateTransition, Button
|
|||
from trytond.pool import PoolMeta, Pool
|
||||
from trytond.pyson import Eval, Bool
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.config import config
|
||||
from trytond.config import config as tconfig
|
||||
from trytond.tools import get_smtp_server
|
||||
from trytond.exceptions import UserError, UserWarning
|
||||
from trytond.i18n import gettext
|
||||
|
@ -291,7 +291,9 @@ class Sale(metaclass=PoolMeta):
|
|||
|
||||
@classmethod
|
||||
def send_email_party(cls, sales):
|
||||
from_addr = config.get('email', 'from')
|
||||
smtp_server = None
|
||||
from_addr = (smtp_server and smtp_server.smtp_email or
|
||||
tconfig.get('email', 'from'))
|
||||
if not from_addr:
|
||||
logger.error("Missing configuration to send emails")
|
||||
return
|
||||
|
@ -302,21 +304,22 @@ class Sale(metaclass=PoolMeta):
|
|||
logger.error("Missing address for '%s' to send email",
|
||||
sale.party.rec_name)
|
||||
continue
|
||||
reply_to = sale.create_uid.email
|
||||
|
||||
reply_to = sale.create_uid.email
|
||||
subject, body = sale._get_subject_body()
|
||||
attachment_data = sale._get_attachment()
|
||||
|
||||
msg = cls.create_msg(from_addr, to_addr, reply_to, subject,
|
||||
body, attachment_data)
|
||||
cls.send_msg(from_addr, to_addr, msg, sale.number)
|
||||
cls.send_msg(smtp_server, from_addr, to_addr, msg, sale.number)
|
||||
|
||||
def _get_subject_body(self):
|
||||
pool = Pool()
|
||||
Config = pool.get('sale.configuration')
|
||||
|
||||
config = Config(1)
|
||||
subject = str(config.email_quotation_subject)
|
||||
body = str(config.email_quotation_body)
|
||||
config_ = Config(1)
|
||||
subject = str(config_.email_quotation_subject)
|
||||
body = str(config_.email_quotation_body)
|
||||
return subject, body
|
||||
|
||||
def _get_attachment(self):
|
||||
|
@ -359,16 +362,22 @@ class Sale(metaclass=PoolMeta):
|
|||
return msg
|
||||
|
||||
@staticmethod
|
||||
def send_msg(from_addr, to_addr, msg, task_number):
|
||||
def send_msg(smtp_server, from_addr, to_addr, msg, task_number):
|
||||
success = False
|
||||
server = None
|
||||
try:
|
||||
server = get_smtp_server()
|
||||
if smtp_server:
|
||||
server = smtp_server.get_smtp_server()
|
||||
else:
|
||||
server = get_smtp_server()
|
||||
server.sendmail(from_addr, [to_addr], msg.as_string())
|
||||
server.quit()
|
||||
success = True
|
||||
except Exception:
|
||||
logger.error(
|
||||
"Unable to deliver email for task '%s'" % (task_number))
|
||||
"Unable to deliver email for task '%s'" % task_number)
|
||||
if server is not None:
|
||||
server.quit()
|
||||
return success
|
||||
|
||||
def create_invoice(self):
|
||||
|
|
Loading…
Reference in New Issue