Added activity creation via mail and resource guess
This commit is contained in:
parent
409d7a62a7
commit
67b9a58870
15
__init__.py
15
__init__.py
|
@ -1,16 +1,17 @@
|
||||||
# The COPYRIGHT file at the top level of this repository contains the full
|
# The COPYRIGHT file at the top level of this repository contains the full
|
||||||
# copyright notices and license terms.
|
# copyright notices and license terms.
|
||||||
from trytond.pool import Pool
|
from trytond.pool import Pool
|
||||||
from .activity import *
|
from . import activity
|
||||||
from .imap import *
|
from . import configuration
|
||||||
from .user import *
|
from . import user
|
||||||
|
|
||||||
def register():
|
def register():
|
||||||
Pool.register(
|
Pool.register(
|
||||||
Activity,
|
activity.Activity,
|
||||||
IMAPServer,
|
activity.Cron,
|
||||||
User,
|
user.User,
|
||||||
|
configuration.Configuration,
|
||||||
module='electronic_mail_activity', type_='model')
|
module='electronic_mail_activity', type_='model')
|
||||||
Pool.register(
|
Pool.register(
|
||||||
ActivityReplyMail,
|
activity.ActivityReplyMail,
|
||||||
module='electronic_mail_activity', type_='wizard')
|
module='electronic_mail_activity', type_='wizard')
|
||||||
|
|
244
activity.py
244
activity.py
|
@ -4,6 +4,7 @@ from trytond.pool import Pool, PoolMeta
|
||||||
from trytond.model import fields, ModelView
|
from trytond.model import fields, ModelView
|
||||||
from trytond.transaction import Transaction
|
from trytond.transaction import Transaction
|
||||||
from trytond.wizard import Wizard, StateAction
|
from trytond.wizard import Wizard, StateAction
|
||||||
|
from trytond.pyson import Eval, Bool
|
||||||
from email.utils import parseaddr, formataddr, formatdate, make_msgid
|
from email.utils import parseaddr, formataddr, formatdate, make_msgid
|
||||||
from email import encoders, message_from_bytes
|
from email import encoders, message_from_bytes
|
||||||
from email.mime.multipart import MIMEMultipart
|
from email.mime.multipart import MIMEMultipart
|
||||||
|
@ -26,6 +27,16 @@ except ImportError:
|
||||||
__all__ = ['Activity', 'ActivityReplyMail']
|
__all__ = ['Activity', 'ActivityReplyMail']
|
||||||
|
|
||||||
|
|
||||||
|
class Cron(metaclass=PoolMeta):
|
||||||
|
__name__ = 'ir.cron'
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def __setup__(cls):
|
||||||
|
super().__setup__()
|
||||||
|
cls.method.selection.extend([
|
||||||
|
('activity.activity|create_activity', "Create Activity")])
|
||||||
|
|
||||||
|
|
||||||
class Activity(metaclass=PoolMeta):
|
class Activity(metaclass=PoolMeta):
|
||||||
__name__ = 'activity.activity'
|
__name__ = 'activity.activity'
|
||||||
|
|
||||||
|
@ -40,12 +51,17 @@ class Activity(metaclass=PoolMeta):
|
||||||
def __setup__(cls):
|
def __setup__(cls):
|
||||||
super(Activity, cls).__setup__()
|
super(Activity, cls).__setup__()
|
||||||
cls._buttons.update({
|
cls._buttons.update({
|
||||||
'new': {
|
'new': {
|
||||||
'icon': 'tryton-email',
|
'icon': 'tryton-email',
|
||||||
},
|
},
|
||||||
'reply': {
|
'reply': {
|
||||||
'icon': 'tryton-forward'
|
'icon': 'tryton-forward',
|
||||||
},
|
},
|
||||||
|
'guess': {
|
||||||
|
'icon': 'tryton-forward',
|
||||||
|
'invisible': Bool(Eval('resource', -1)),
|
||||||
|
'depends': ['resource'],
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -58,6 +74,10 @@ class Activity(metaclass=PoolMeta):
|
||||||
and self.related_activity.mail and
|
and self.related_activity.mail and
|
||||||
self.related_activity.mail.message_id or "")
|
self.related_activity.mail.message_id or "")
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _get_origin(cls):
|
||||||
|
return super()._get_origin() + ['electronic.mail']
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def reference(self):
|
def reference(self):
|
||||||
result = ""
|
result = ""
|
||||||
|
@ -95,6 +115,17 @@ class Activity(metaclass=PoolMeta):
|
||||||
def reply(cls, activities):
|
def reply(cls, activities):
|
||||||
cls.check_activity_user_info()
|
cls.check_activity_user_info()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@ModelView.button
|
||||||
|
def guess(cls, activities):
|
||||||
|
activities = cls.browse(sorted(activities, key=lambda x: x.id))
|
||||||
|
for activity in activities:
|
||||||
|
activity = cls(activity)
|
||||||
|
activity.guess_resource()
|
||||||
|
# Each activity is saved because in this list there
|
||||||
|
# could be a resource of another of the same list
|
||||||
|
activity.save()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def check_activity_user_info(cls):
|
def check_activity_user_info(cls):
|
||||||
"Check if user have deffined the a server and a mailbox"
|
"Check if user have deffined the a server and a mailbox"
|
||||||
|
@ -265,158 +296,59 @@ class Activity(metaclass=PoolMeta):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create_activity(cls, received_mails):
|
def create_activity(cls):
|
||||||
IMAPServer = Pool().get('imap.server')
|
pool = Pool()
|
||||||
CompanyEmployee = Pool().get('company.employee')
|
ModelData = pool.get('ir.model.data')
|
||||||
|
Employee = pool.get('company.employee')
|
||||||
|
ElectronicMail = pool.get('electronic.mail')
|
||||||
|
Mailbox = pool.get('electronic.mail.mailbox')
|
||||||
|
Activity = pool.get('activity.activity')
|
||||||
|
ActivityType = pool.get('activity.type')
|
||||||
|
ActivityConfiguration = pool.get('activity.configuration')
|
||||||
|
mails = ElectronicMail.search([
|
||||||
|
('mailbox', '=', ActivityConfiguration(0).pending_mailbox)
|
||||||
|
], order=[('date', 'ASC'), ('id', 'ASC')])
|
||||||
|
activity_type = ActivityType(ModelData.get_id('activity',
|
||||||
|
'incoming_email_type'))
|
||||||
|
employee = ActivityConfiguration(0).employee
|
||||||
|
processed_mailbox = ActivityConfiguration(0).processed_mailbox
|
||||||
|
activities = []
|
||||||
|
for mail in mails:
|
||||||
|
activity = Activity()
|
||||||
|
activity.subject = mail.subject
|
||||||
|
activity.activity_type = activity_type
|
||||||
|
activity.employee = employee
|
||||||
|
activity.dtstart = mail.date
|
||||||
|
activity.description = html2text(mail.body_plain).replace('\r', '')
|
||||||
|
activity.mail = mail
|
||||||
|
activity.state = 'planned'
|
||||||
|
activity.resource = None
|
||||||
|
activity.origin = mail
|
||||||
|
activities.append(activity)
|
||||||
|
mail.mailbox = processed_mailbox
|
||||||
|
cls.save(activities)
|
||||||
|
ElectronicMail.save(mails)
|
||||||
|
cls.guess(activities)
|
||||||
|
|
||||||
|
def get_previous_activity(self):
|
||||||
ElectronicMail = Pool().get('electronic.mail')
|
ElectronicMail = Pool().get('electronic.mail')
|
||||||
Attachment = Pool().get('ir.attachment')
|
if not isinstance(self.origin, ElectronicMail):
|
||||||
ActivityType = Pool().get('activity.type')
|
return
|
||||||
|
parent = self.origin.parent
|
||||||
|
if not parent:
|
||||||
|
return
|
||||||
|
activities = self.search([
|
||||||
|
('origin', '=', parent)
|
||||||
|
], limit=1)
|
||||||
|
if activities:
|
||||||
|
return activities[0]
|
||||||
|
|
||||||
values = []
|
def guess_resource(self):
|
||||||
attachs = {}
|
previous_activity = self.get_previous_activity()
|
||||||
for server_id, mails in list(received_mails.items()):
|
if previous_activity:
|
||||||
servers = IMAPServer.browse([server_id])
|
if previous_activity.resource:
|
||||||
server = servers and servers[0] or None
|
self.resource = previous_activity.resource
|
||||||
for mail in mails:
|
self.party = previous_activity.resource.party
|
||||||
# Control if the mail recevied is send by us, searching if
|
|
||||||
# there are any activity with that mail attached
|
|
||||||
activity_exist = cls.search([
|
|
||||||
('mail', '=', mail.id)
|
|
||||||
])
|
|
||||||
if activity_exist:
|
|
||||||
continue
|
|
||||||
# Take the possible employee, if not the default.
|
|
||||||
deliveredtos = mail.deliveredto and [mail.deliveredto] or []
|
|
||||||
deliveredtos.extend([m[1] for m in mail.all_to])
|
|
||||||
deliveredtos.extend([m[1] for m in mail.all_cc])
|
|
||||||
deliveredtos = ElectronicMail.validate_emails(deliveredtos)
|
|
||||||
contact = None
|
|
||||||
if deliveredtos:
|
|
||||||
employees = CompanyEmployee.search([])
|
|
||||||
parties = [p.party.id for p in employees]
|
|
||||||
contacts = []
|
|
||||||
for deliveredto in deliveredtos:
|
|
||||||
cm = cls.get_contact_mechanism(deliveredto, parties)
|
|
||||||
if cm:
|
|
||||||
contacts.append(cm)
|
|
||||||
contact = contacts and contacts[0] or None
|
|
||||||
employee = None
|
|
||||||
if contact:
|
|
||||||
emails_employee = [c.value
|
|
||||||
for c in contact.party.contact_mechanisms
|
|
||||||
if c.type == 'email']
|
|
||||||
employee = CompanyEmployee.search([
|
|
||||||
('party', '=', contact.party.id)
|
|
||||||
])
|
|
||||||
if not employee:
|
|
||||||
employee = server and server.employee or None
|
|
||||||
emails_employee = (server and server.employee and
|
|
||||||
[server.employee.party.email] or [])
|
|
||||||
else:
|
|
||||||
employee = employee[0]
|
|
||||||
|
|
||||||
# Search for the parties with that mails, to attach in the
|
|
||||||
# contacts and main contact
|
|
||||||
mail_from = ElectronicMail.validate_emails(
|
|
||||||
parseaddr(mail.from_.replace(',', ' '))[1])
|
|
||||||
contact = cls.get_contact_mechanism(mail_from)
|
|
||||||
main_contact = contact and contact.party or False
|
|
||||||
|
|
||||||
email_to = []
|
|
||||||
for to in mail.all_to:
|
|
||||||
if to[1] not in emails_employee:
|
|
||||||
email_to.append(to[1])
|
|
||||||
email_cc = email_to + [m[1] for m in mail.all_cc]
|
|
||||||
emails_cc = ElectronicMail.validate_emails(email_cc)
|
|
||||||
contacts = []
|
|
||||||
for email_cc in emails_cc:
|
|
||||||
contact = cls.get_contact_mechanism(email_cc)
|
|
||||||
if contact:
|
|
||||||
contacts.append(contact.party.id)
|
|
||||||
|
|
||||||
# Search for the possible activity referenced to add in the
|
|
||||||
# same resource.
|
|
||||||
referenced_mail = []
|
|
||||||
if mail.in_reply_to:
|
|
||||||
referenced_mail = ElectronicMail.search([
|
|
||||||
('message_id', '=', mail.in_reply_to)
|
|
||||||
])
|
|
||||||
if not referenced_mail and mail.reference:
|
|
||||||
referenced_mail = ElectronicMail.search([
|
|
||||||
('message_id', 'in', mail.reference)
|
|
||||||
])
|
|
||||||
|
|
||||||
# Fill the fields, in case the activity don't have enought
|
|
||||||
# information
|
|
||||||
resource = None
|
|
||||||
party = (main_contact and
|
|
||||||
[r.to for r in main_contact.relations] or [])
|
|
||||||
party = party and party[0] or None
|
|
||||||
if referenced_mail:
|
|
||||||
# Search if the activity have resource to use for activity
|
|
||||||
# that create now.
|
|
||||||
referenced_mails = [r.id for r in referenced_mail]
|
|
||||||
activities = cls.search([
|
|
||||||
('mail', 'in', referenced_mails)
|
|
||||||
])
|
|
||||||
if activities:
|
|
||||||
resource = activities[0].resource
|
|
||||||
party = resource and resource.party or party
|
|
||||||
|
|
||||||
# TODO: Search for a better default.
|
|
||||||
# By the moment search the first activity type with the 0 in
|
|
||||||
# sequence
|
|
||||||
activity_types = ActivityType.search([
|
|
||||||
('sequence', '=', 0)
|
|
||||||
])
|
|
||||||
activity_type = activity_types and activity_types[0] or None
|
|
||||||
|
|
||||||
# Create the activity
|
|
||||||
base_values = {
|
|
||||||
'subject': mail.subject or "NONE",
|
|
||||||
'activity_type': activity_type,
|
|
||||||
'employee': employee.id,
|
|
||||||
'dtstart': datetime.datetime.now(),
|
|
||||||
'description': (mail.body_plain
|
|
||||||
or html2text(mail.body_html)),
|
|
||||||
'mail': mail.id,
|
|
||||||
'state': 'planned',
|
|
||||||
'resource': None,
|
|
||||||
}
|
|
||||||
values = base_values.copy()
|
|
||||||
if resource:
|
|
||||||
values['resource'] = str(resource)
|
|
||||||
if party:
|
|
||||||
values['party'] = party.id
|
|
||||||
if main_contact:
|
|
||||||
values['main_contact'] = main_contact.id
|
|
||||||
if contacts:
|
|
||||||
values['contacts'] = [('add', contacts)]
|
|
||||||
try:
|
|
||||||
activity = cls.create([values])
|
|
||||||
except:
|
|
||||||
activity = cls.create([base_values])
|
|
||||||
|
|
||||||
# Add all the possible attachments from the mil to the activity
|
|
||||||
msg = message_from_bytes(mail.mail_file)
|
|
||||||
attachs = ElectronicMail.get_attachments(msg)
|
|
||||||
if attachs:
|
|
||||||
values = []
|
|
||||||
for attach in attachs:
|
|
||||||
values.append({
|
|
||||||
'name': attach.get('filename', mail.subject),
|
|
||||||
'type': 'data',
|
|
||||||
'data': attach.get('data'),
|
|
||||||
'resource': str(activity[0])
|
|
||||||
})
|
|
||||||
try:
|
|
||||||
Attachment.create(values)
|
|
||||||
except Exception as e:
|
|
||||||
logging.getLogger('Activity Mail').info(
|
|
||||||
'The mail (%s) has attachments but they are not '
|
|
||||||
'possible to attach to the activity (%s).\n\n%s' %
|
|
||||||
(mail.id, activity.id, e))
|
|
||||||
return mails
|
|
||||||
|
|
||||||
|
|
||||||
class ActivityReplyMail(Wizard, metaclass=PoolMeta):
|
class ActivityReplyMail(Wizard, metaclass=PoolMeta):
|
||||||
|
|
17
activity.xml
17
activity.xml
|
@ -3,6 +3,13 @@
|
||||||
copyright notices and license terms. -->
|
copyright notices and license terms. -->
|
||||||
<tryton>
|
<tryton>
|
||||||
<data>
|
<data>
|
||||||
|
<record model="ir.cron" id="cron_create_activity">
|
||||||
|
<field name="method">activity.activity|create_activity</field>
|
||||||
|
<field name="active" eval="True"/>
|
||||||
|
<field name="interval_number" eval="1"/>
|
||||||
|
<field name="interval_type">days</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
<record model="ir.action.wizard" id="wizard_replymail">
|
<record model="ir.action.wizard" id="wizard_replymail">
|
||||||
<field name="name">Reply Mail</field>
|
<field name="name">Reply Mail</field>
|
||||||
<field name="wiz_name">activity.activity.replymail</field>
|
<field name="wiz_name">activity.activity.replymail</field>
|
||||||
|
@ -42,5 +49,15 @@
|
||||||
<field name="group" ref="electronic_mail.group_email_user"/>
|
<field name="group" ref="electronic_mail.group_email_user"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.model.button" id="electronic_mail_guess_button">
|
||||||
|
<field name="name">guess</field>
|
||||||
|
<field name="string">Guess Resource</field>
|
||||||
|
<field name="model" search="[('model', '=', 'activity.activity')]"/>
|
||||||
|
</record>
|
||||||
|
<record model="ir.model.button-res.group"
|
||||||
|
id="activity_guess_button_group">
|
||||||
|
<field name="button" ref="electronic_mail_guess_button"/>
|
||||||
|
<field name="group" ref="electronic_mail.group_email_user"/>
|
||||||
|
</record>
|
||||||
</data>
|
</data>
|
||||||
</tryton>
|
</tryton>
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
from trytond.pool import Pool, PoolMeta
|
||||||
|
from trytond.model import fields, ModelView
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = ['Configuration']
|
||||||
|
|
||||||
|
|
||||||
|
class Configuration(metaclass=PoolMeta):
|
||||||
|
'Activity Configuration'
|
||||||
|
__name__ = 'activity.configuration'
|
||||||
|
|
||||||
|
employee = fields.Many2One('company.employee', 'Employee', required=True)
|
||||||
|
pending_mailbox = fields.Many2One('electronic.mail.mailbox', 'Pending Mailbox',
|
||||||
|
required=True)
|
||||||
|
processed_mailbox = fields.Many2One('electronic.mail.mailbox', 'Processed Mailbox',
|
||||||
|
required=True)
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--The COPYRIGHT file at the top level of this repository
|
||||||
|
contains the full copyright notices and license terms. -->
|
||||||
|
<tryton>
|
||||||
|
<data>
|
||||||
|
<record model="ir.ui.view" id="activity_configuration_view_form">
|
||||||
|
<field name="model">activity.configuration</field>
|
||||||
|
<field name="inherit" ref="activity.activity_configuration_view_form"/>
|
||||||
|
<field name="name">configuration_form</field>
|
||||||
|
</record>
|
||||||
|
</data>
|
||||||
|
</tryton>
|
30
imap.py
30
imap.py
|
@ -1,30 +0,0 @@
|
||||||
# The COPYRIGHT file at the top level of this repository contains the full
|
|
||||||
# copyright notices and license terms.
|
|
||||||
from trytond.pool import Pool, PoolMeta
|
|
||||||
from trytond.model import fields
|
|
||||||
|
|
||||||
__all__ = ['IMAPServer']
|
|
||||||
|
|
||||||
|
|
||||||
class IMAPServer(metaclass=PoolMeta):
|
|
||||||
__name__ = 'imap.server'
|
|
||||||
|
|
||||||
employee = fields.Many2One('company.employee', 'Default Employee')
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def fetch_mails(cls, servers):
|
|
||||||
Activity = Pool().get('activity.activity')
|
|
||||||
activity_servers = []
|
|
||||||
other_servers = []
|
|
||||||
for server in servers:
|
|
||||||
if server.model and server.model.model == 'activity.activity':
|
|
||||||
activity_servers.append(server)
|
|
||||||
else:
|
|
||||||
other_servers.append(server)
|
|
||||||
mails = {}
|
|
||||||
if activity_servers:
|
|
||||||
mails.update(super(IMAPServer, cls).fetch_mails(activity_servers))
|
|
||||||
Activity.create_activity(mails)
|
|
||||||
if other_servers:
|
|
||||||
mails.update(super(IMAPServer, cls).fetch_mails(other_servers))
|
|
||||||
return mails
|
|
12
imap.xml
12
imap.xml
|
@ -1,12 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
<!-- The COPYRIGHT file at the top level of this repository contains the full
|
|
||||||
copyright notices and license terms. -->
|
|
||||||
<tryton>
|
|
||||||
<data>
|
|
||||||
<record model="ir.ui.view" id="imap_server_view_form">
|
|
||||||
<field name="model">imap.server</field>
|
|
||||||
<field name="inherit" ref="imap.imap_server_view_form"/>
|
|
||||||
<field name="name">imap_server_form</field>
|
|
||||||
</record>
|
|
||||||
</data>
|
|
||||||
</tryton>
|
|
20
locale/ca.po
20
locale/ca.po
|
@ -14,6 +14,14 @@ msgctxt "field:activity.activity,related_activity:"
|
||||||
msgid "Related activity"
|
msgid "Related activity"
|
||||||
msgstr "Activitat relacionada"
|
msgstr "Activitat relacionada"
|
||||||
|
|
||||||
|
msgctxt "field:activity.configuration,pending_mailbox:"
|
||||||
|
msgid "Pending Mailbox"
|
||||||
|
msgstr "Bústia de correu Pendents"
|
||||||
|
|
||||||
|
msgctxt "field:activity.configuration,processed_mailbox:"
|
||||||
|
msgid "Processed Mailbox"
|
||||||
|
msgstr "Bústia de correu Processats"
|
||||||
|
|
||||||
msgctxt "field:imap.server,employee:"
|
msgctxt "field:imap.server,employee:"
|
||||||
msgid "Default Employee"
|
msgid "Default Employee"
|
||||||
msgstr "Empleat per defecte"
|
msgstr "Empleat per defecte"
|
||||||
|
@ -26,6 +34,10 @@ msgctxt "field:res.user,mailbox:"
|
||||||
msgid "Mailbox"
|
msgid "Mailbox"
|
||||||
msgstr "Bústia de correu"
|
msgstr "Bústia de correu"
|
||||||
|
|
||||||
|
msgctxt "field:res.user,signature_html:"
|
||||||
|
msgid "Signature"
|
||||||
|
msgstr "Signatura"
|
||||||
|
|
||||||
msgctxt "field:res.user,smtp_server:"
|
msgctxt "field:res.user,smtp_server:"
|
||||||
msgid "SMTP Server"
|
msgid "SMTP Server"
|
||||||
msgstr "Servidor SMTP"
|
msgstr "Servidor SMTP"
|
||||||
|
@ -63,6 +75,10 @@ msgctxt "model:ir.message,text:no_valid_mail"
|
||||||
msgid "The \"%(mail)s\" of the party \"%(party)s\" it is not correct."
|
msgid "The \"%(mail)s\" of the party \"%(party)s\" it is not correct."
|
||||||
msgstr "El \"%(mail)s\" del tercer \"%(party)s\" no es correcte."
|
msgstr "El \"%(mail)s\" del tercer \"%(party)s\" no es correcte."
|
||||||
|
|
||||||
|
msgctxt "model:ir.model.button,string:electronic_mail_guess_button"
|
||||||
|
msgid "Guess Resource"
|
||||||
|
msgstr "Troba recurs"
|
||||||
|
|
||||||
msgctxt "model:ir.model.button,string:electronic_mail_new_button"
|
msgctxt "model:ir.model.button,string:electronic_mail_new_button"
|
||||||
msgid "Send Mail"
|
msgid "Send Mail"
|
||||||
msgstr "Envia correu"
|
msgstr "Envia correu"
|
||||||
|
@ -71,6 +87,10 @@ msgctxt "model:ir.model.button,string:electronic_mail_reply_button"
|
||||||
msgid "Reply Mail"
|
msgid "Reply Mail"
|
||||||
msgstr "Respon correu"
|
msgstr "Respon correu"
|
||||||
|
|
||||||
|
msgctxt "selection:ir.cron,method:"
|
||||||
|
msgid "Create Activity"
|
||||||
|
msgstr "Crear Activitat"
|
||||||
|
|
||||||
msgctxt "view:activity.activity:"
|
msgctxt "view:activity.activity:"
|
||||||
msgid "Reply Mail"
|
msgid "Reply Mail"
|
||||||
msgstr "Respon correu"
|
msgstr "Respon correu"
|
||||||
|
|
20
locale/es.po
20
locale/es.po
|
@ -14,6 +14,14 @@ msgctxt "field:activity.activity,related_activity:"
|
||||||
msgid "Related activity"
|
msgid "Related activity"
|
||||||
msgstr "Actividad relacionada"
|
msgstr "Actividad relacionada"
|
||||||
|
|
||||||
|
msgctxt "field:activity.configuration,pending_mailbox:"
|
||||||
|
msgid "Pending Mailbox"
|
||||||
|
msgstr "Buzón Pendientes"
|
||||||
|
|
||||||
|
msgctxt "field:activity.configuration,processed_mailbox:"
|
||||||
|
msgid "Processed Mailbox"
|
||||||
|
msgstr "Buzón Procesados"
|
||||||
|
|
||||||
msgctxt "field:imap.server,employee:"
|
msgctxt "field:imap.server,employee:"
|
||||||
msgid "Default Employee"
|
msgid "Default Employee"
|
||||||
msgstr "Empleado por defecto"
|
msgstr "Empleado por defecto"
|
||||||
|
@ -26,6 +34,10 @@ msgctxt "field:res.user,mailbox:"
|
||||||
msgid "Mailbox"
|
msgid "Mailbox"
|
||||||
msgstr "Buzón de correo"
|
msgstr "Buzón de correo"
|
||||||
|
|
||||||
|
msgctxt "field:res.user,signature_html:"
|
||||||
|
msgid "Signature"
|
||||||
|
msgstr "Firma"
|
||||||
|
|
||||||
msgctxt "field:res.user,smtp_server:"
|
msgctxt "field:res.user,smtp_server:"
|
||||||
msgid "SMTP Server"
|
msgid "SMTP Server"
|
||||||
msgstr "Servidor SMTP"
|
msgstr "Servidor SMTP"
|
||||||
|
@ -65,6 +77,10 @@ msgctxt "model:ir.message,text:no_valid_mail"
|
||||||
msgid "The \"%(mail)s\" of the party \"%(party)s\" it is not correct."
|
msgid "The \"%(mail)s\" of the party \"%(party)s\" it is not correct."
|
||||||
msgstr "El \"%(mail)s\" del tercero \"%(party)s\" no es correcto."
|
msgstr "El \"%(mail)s\" del tercero \"%(party)s\" no es correcto."
|
||||||
|
|
||||||
|
msgctxt "model:ir.model.button,string:electronic_mail_guess_button"
|
||||||
|
msgid "Guess Resource"
|
||||||
|
msgstr "Encuentra el Recurso"
|
||||||
|
|
||||||
msgctxt "model:ir.model.button,string:electronic_mail_new_button"
|
msgctxt "model:ir.model.button,string:electronic_mail_new_button"
|
||||||
msgid "Send Mail"
|
msgid "Send Mail"
|
||||||
msgstr "Envio correo"
|
msgstr "Envio correo"
|
||||||
|
@ -73,6 +89,10 @@ msgctxt "model:ir.model.button,string:electronic_mail_reply_button"
|
||||||
msgid "Reply Mail"
|
msgid "Reply Mail"
|
||||||
msgstr "Responder correo"
|
msgstr "Responder correo"
|
||||||
|
|
||||||
|
msgctxt "selection:ir.cron,method:"
|
||||||
|
msgid "Create Activity"
|
||||||
|
msgstr "Crear Actividad"
|
||||||
|
|
||||||
msgctxt "view:activity.activity:"
|
msgctxt "view:activity.activity:"
|
||||||
msgid "Reply Mail"
|
msgid "Reply Mail"
|
||||||
msgstr "Responder correo"
|
msgstr "Responder correo"
|
||||||
|
|
|
@ -2,11 +2,10 @@
|
||||||
version=5.5.0
|
version=5.5.0
|
||||||
depends:
|
depends:
|
||||||
electronic_mail
|
electronic_mail
|
||||||
electronic_mail_model
|
|
||||||
electronic_mail_wizard
|
electronic_mail_wizard
|
||||||
activity_contact
|
activity_contact
|
||||||
xml:
|
xml:
|
||||||
activity.xml
|
activity.xml
|
||||||
imap.xml
|
|
||||||
user.xml
|
user.xml
|
||||||
message.xml
|
message.xml
|
||||||
|
configuration.xml
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
<!-- The COPYRIGHT file at the top level of this repository contains the full
|
<!-- The COPYRIGHT file at the top level of this repository contains the full
|
||||||
copyright notices and license terms. -->
|
copyright notices and license terms. -->
|
||||||
<data>
|
<data>
|
||||||
|
<xpath expr="/form/group[@id='buttons']/button[@name='activity_split']" position="after">
|
||||||
|
<button name="guess"/>
|
||||||
|
</xpath>
|
||||||
<xpath expr="/form/label[@name='state']" position="replace" />
|
<xpath expr="/form/label[@name='state']" position="replace" />
|
||||||
<xpath expr="/form/field[@name='state']" position="replace">
|
<xpath expr="/form/field[@name='state']" position="replace">
|
||||||
<group id="state" colspan="4" col="6">
|
<group id="state" colspan="4" col="6">
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
<xpath expr="/tree/field[@name='state']" position="after">
|
<xpath expr="/tree/field[@name='state']" position="after">
|
||||||
<button name="new"/>
|
<button name="new"/>
|
||||||
<button name="reply"/>
|
<button name="reply"/>
|
||||||
|
<button name="guess"/>
|
||||||
<field name="have_mail" tree_invisible="1"/>
|
<field name="have_mail" tree_invisible="1"/>
|
||||||
</xpath>
|
</xpath>
|
||||||
</data>
|
</data>
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--The COPYRIGHT file at the top level of this repository
|
||||||
|
contains the full copyright notices and license terms. -->
|
||||||
|
<data>
|
||||||
|
<xpath expr="/form" position="inside">
|
||||||
|
<label name="employee"/>
|
||||||
|
<field name="employee"/>
|
||||||
|
<label name="pending_mailbox"/>
|
||||||
|
<field name="pending_mailbox"/>
|
||||||
|
<label name="processed_mailbox"/>
|
||||||
|
<field name="processed_mailbox"/>
|
||||||
|
</xpath>
|
||||||
|
</data>
|
|
@ -1,9 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
<!-- The COPYRIGHT file at the top level of this repository contains the full
|
|
||||||
copyright notices and license terms. -->
|
|
||||||
<data>
|
|
||||||
<xpath expr="/form/field[@name='model']" position="after">
|
|
||||||
<label name="employee"/>
|
|
||||||
<field name="employee"/>
|
|
||||||
</xpath>
|
|
||||||
</data>
|
|
Loading…
Reference in New Issue