diff --git a/CHANGELOG b/CHANGELOG
index 18f8c97802..688fdf9039 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,5 @@
+* Remove request
+
Version 2.8.0 - 2013-04-22
* Bug fixes (see mercurial logs for details)
* Allow to search on target of Reference field
diff --git a/etc/trytond.conf b/etc/trytond.conf
index aea2683979..6208dd5e33 100644
--- a/etc/trytond.conf
+++ b/etc/trytond.conf
@@ -58,6 +58,7 @@ jsonrpc = localhost:8000
#smtp_tls = False
#smtp_password = False
#smtp_user = False
+#smtp_default_from_email = False
# Configure the path to store attachments and sqlite database
#data_path = /var/lib/trytond
diff --git a/trytond/config.py b/trytond/config.py
index 4f4d5a6980..58c27ee484 100644
--- a/trytond/config.py
+++ b/trytond/config.py
@@ -12,6 +12,8 @@ except ImportError:
import os
import ConfigParser
import time
+import getpass
+import socket
def get_hostname(netloc):
@@ -69,6 +71,8 @@ class ConfigManager(object):
'smtp_tls': False,
'smtp_user': False,
'smtp_password': False,
+ 'smtp_default_from_email': '%s@%s' % (
+ getpass.getuser(), socket.getfqdn()),
'data_path': '/var/lib/trytond',
'multi_server': False,
'session_timeout': 600,
diff --git a/trytond/ir/cron.py b/trytond/ir/cron.py
index 320b9c1d1e..48b2004b0f 100644
--- a/trytond/ir/cron.py
+++ b/trytond/ir/cron.py
@@ -6,12 +6,14 @@ from dateutil.relativedelta import relativedelta
import traceback
import sys
import logging
+from email.mime.text import MIMEText
from ..model import ModelView, ModelSQL, fields
-from ..tools import safe_eval
+from ..tools import safe_eval, get_smtp_server
from ..transaction import Transaction
from ..pool import Pool
from ..backend import TableHandler
+from ..config import CONFIG
__all__ = [
'Cron',
@@ -60,10 +62,10 @@ class Cron(ModelSQL, ModelView):
def __setup__(cls):
super(Cron, cls).__setup__()
cls._error_messages.update({
- 'request_title': 'Scheduled action failed',
- 'request_body': "The following action failed to execute "
- "properly: \"%s\"\n Traceback: \n\n%s\n"
- })
+ 'request_title': 'Scheduled action failed',
+ 'request_body': ("The following action failed to execute "
+ "properly: \"%s\"\n%s\n Traceback: \n\n%s\n")
+ })
@classmethod
def __register__(cls, module_name):
@@ -120,29 +122,33 @@ class Cron(ModelSQL, ModelView):
return _INTERVALTYPES[cron.interval_type](cron.interval_number)
@classmethod
- def _get_request_values(cls, cron):
+ def send_error_message(cls, cron):
tb_s = ''.join(traceback.format_exception(*sys.exc_info()))
tb_s = tb_s.decode('utf-8', 'ignore')
- name = cls.raise_user_error('request_title',
+ subject = cls.raise_user_error('request_title',
raise_exception=False)
- body = cls.raise_user_error('request_body', (cron.name, tb_s),
+ body = cls.raise_user_error('request_body',
+ (cron.name, cron.__url__, tb_s),
raise_exception=False)
- values = {
- 'name': name,
- 'priority': '2',
- 'act_from': cron.user.id,
- 'act_to': cron.request_user.id,
- 'body': body,
- 'date_sent': datetime.datetime.now(),
- 'references': [
- ('create', [{
- 'reference': '%s,%s' % (cls.__name__, cron.id),
- }]),
- ],
- 'state': 'waiting',
- 'trigger_date': datetime.datetime.now(),
- }
- return values
+
+ from_addr = CONFIG['smtp_default_from_email']
+ to_addr = cron.request_user.email
+
+ msg = MIMEText(body)
+ msg['To'] = to_addr
+ msg['From'] = from_addr
+ msg['Subject'] = subject
+ logger = logging.getLogger(__name__)
+ if not to_addr:
+ logger.error(msg.as_string())
+ else:
+ try:
+ server = get_smtp_server()
+ server.sendmail(from_addr, to_addr, msg.as_string())
+ server.quit()
+ except Exception, exception:
+ logger.error('Unable to deliver email (%s):\n %s'
+ % (exception, msg.as_string()))
@classmethod
def _callback(cls, cron):
@@ -156,15 +162,12 @@ class Cron(ModelSQL, ModelView):
except Exception:
Transaction().cursor.rollback()
- Request = pool.get('res.request')
req_user = cron.request_user
language = (req_user.language.code if req_user.language
else Config.get_language())
with contextlib.nested(Transaction().set_user(cron.user.id),
Transaction().set_context(language=language)):
- values = cls._get_request_values(cron)
- Request.create([values])
- Transaction().cursor.commit()
+ cls.send_error_message(cron)
@classmethod
def run(cls, db_name):
diff --git a/trytond/protocols/dispatcher.py b/trytond/protocols/dispatcher.py
index e00f0b0069..899146a7fa 100644
--- a/trytond/protocols/dispatcher.py
+++ b/trytond/protocols/dispatcher.py
@@ -183,17 +183,16 @@ def dispatch(host, port, protocol, database_name, user, session, object_type,
database_name) + tb_s)
transaction.cursor.rollback()
raise
- if not (object_name == 'res.request' and method == 'request_get'):
- with Transaction().start(database_name, 0) as transaction:
- pool = Pool(database_name)
- Session = pool.get('ir.session')
- try:
- Session.reset(session)
- except DatabaseOperationalError:
- # Silently fail when reseting session
- transaction.cursor.rollback()
- else:
- transaction.cursor.commit()
+ with Transaction().start(database_name, 0) as transaction:
+ pool = Pool(database_name)
+ Session = pool.get('ir.session')
+ try:
+ Session.reset(session)
+ except DatabaseOperationalError:
+ # Silently fail when reseting session
+ transaction.cursor.rollback()
+ else:
+ transaction.cursor.commit()
Cache.resets(database_name)
return result
diff --git a/trytond/res/__init__.py b/trytond/res/__init__.py
index 396cd3a9a4..481f45ab49 100644
--- a/trytond/res/__init__.py
+++ b/trytond/res/__init__.py
@@ -3,7 +3,6 @@
from ..pool import Pool
from .group import *
from .user import *
-from .request import *
from .ir import *
@@ -17,10 +16,6 @@ def register():
UserGroup,
Warning_,
UserConfigStart,
- Request,
- RequestLink,
- RequestHistory,
- RequestReference,
UIMenuGroup,
ActionGroup,
ModelFieldGroup,
diff --git a/trytond/res/ir.xml b/trytond/res/ir.xml
index dd99cc253a..9c52d980b4 100644
--- a/trytond/res/ir.xml
+++ b/trytond/res/ir.xml
@@ -746,11 +746,6 @@ this repository contains the full copyright notices and license terms. -->
-
- Scheduler
- ir.cron
-
-
ir.sequence.type
diff --git a/trytond/res/request.py b/trytond/res/request.py
deleted file mode 100644
index 4151b504fd..0000000000
--- a/trytond/res/request.py
+++ /dev/null
@@ -1,266 +0,0 @@
-#This file is part of Tryton. The COPYRIGHT file at the top level of
-#this repository contains the full copyright notices and license terms.
-import datetime
-from ..model import ModelView, ModelSQL, fields
-from ..pyson import Eval, If
-from ..transaction import Transaction
-from ..pool import Pool
-from ..rpc import RPC
-
-__all__ = [
- 'Request', 'RequestLink', 'RequestHistory', 'RequestReference',
- ]
-
-_STATES = [
- ('draft', 'Draft'),
- ('waiting', 'Waiting'),
- ('chatting', 'Chatting'),
- ('closed', 'Closed'),
-]
-
-_PRIORITIES = [
- ('0', 'Low'),
- ('1', 'Normal'),
- ('2', 'High'),
-]
-
-_READONLY = If(Eval('state').in_(['waiting', 'closed']),
- True,
- If(Eval('state') == 'chatting',
- Eval('act_from') != Eval('_user'),
- False))
-_DEPENDS = ['state', 'act_from']
-
-
-class Request(ModelSQL, ModelView):
- "Request"
- __name__ = 'res.request'
- name = fields.Char('Subject', states={
- 'readonly': _READONLY,
- }, required=True, depends=_DEPENDS)
- active = fields.Boolean('Active')
- priority = fields.Selection(_PRIORITIES, 'Priority', states={
- 'readonly': _READONLY,
- }, required=True, order_field='priority', depends=_DEPENDS)
- act_from = fields.Many2One('res.user', 'From', required=True,
- readonly=True)
- act_to = fields.Many2One('res.user', 'To', required=True,
- domain=[('active', '=', True)],
- states={
- 'readonly': _READONLY,
- }, depends=_DEPENDS)
- body = fields.Text('Body', states={
- 'readonly': _READONLY,
- }, depends=_DEPENDS)
- date_sent = fields.DateTime('Date', readonly=True)
- trigger_date = fields.DateTime('Trigger Date', states={
- 'readonly': _READONLY,
- }, depends=_DEPENDS)
- references = fields.One2Many('res.request.reference', 'request',
- 'References', states={
- 'readonly': If(Eval('state') == 'closed',
- True,
- Eval('act_from', 0) != Eval('_user', 0)),
- }, depends=['state', 'act_from'])
- number_references = fields.Function(fields.Integer('Number of References',
- on_change_with=['references']), 'on_change_with_number_references')
- state = fields.Selection(_STATES, 'State', required=True, readonly=True)
- history = fields.One2Many('res.request.history', 'request',
- 'History', readonly=True)
-
- @classmethod
- def __setup__(cls):
- super(Request, cls).__setup__()
- cls.__rpc__.update({
- 'request_get': RPC(),
- })
- cls._order.insert(0, ('priority', 'DESC'))
- cls._order.insert(1, ('trigger_date', 'DESC'))
- cls._order.insert(2, ('create_date', 'DESC'))
- cls._buttons.update({
- 'send': {
- 'invisible': ~Eval('state').in_(['draft', 'chatting']),
- 'readonly': Eval('act_from') != Eval('_user'),
- },
- 'reply': {
- 'invisible': Eval('state') != 'waiting',
- 'readonly': Eval('act_to') != Eval('_user'),
- },
- 'close': {
- 'invisible': ~Eval('state').in_(['waiting', 'draft',
- 'chatting']),
- },
- })
-
- @staticmethod
- def default_act_from():
- return int(Transaction().user)
-
- @staticmethod
- def default_state():
- return 'draft'
-
- @staticmethod
- def default_active():
- return True
-
- @staticmethod
- def default_priority():
- return '1'
-
- def on_change_with_number_references(self, name=None):
- return len(self.references or '')
-
- @classmethod
- @ModelView.button
- def send(cls, requests):
- pool = Pool()
- RequestHistory = pool.get('res.request.history')
- to_create = []
- for request in requests:
- values = {
- 'request': request.id,
- 'act_from': request.act_from.id,
- 'act_to': request.act_to.id,
- 'body': request.body,
- 'state': request.state,
- 'subject': request.name,
- 'number_references': request.number_references,
- 'priority': request.priority,
- }
- if values['body'] and len(values['body']) > 128:
- values['name'] = values['body'][:125] + '...'
- else:
- values['name'] = values['body'] or '/'
- to_create.append(values)
- if to_create:
- RequestHistory.create(to_create)
- cls.write(requests, {
- 'state': 'waiting',
- 'date_sent': datetime.datetime.now(),
- })
-
- @classmethod
- @ModelView.button
- def reply(cls, requests):
- user = Transaction().user
- for request in requests:
- cls.write([request], {
- 'state': 'chatting',
- 'act_from': user,
- 'act_to': request.act_from.id,
- 'trigger_date': None,
- 'body': '',
- })
-
- @classmethod
- @ModelView.button
- def close(cls, requests):
- cls.write(requests, {'state': 'closed', 'active': False})
-
- @classmethod
- def request_get(cls):
- user = Transaction().user
- requests = cls.search([
- ('act_to', '=', user),
- ['OR',
- ('trigger_date', '<=', datetime.datetime.now()),
- ('trigger_date', '=', None),
- ],
- ('active', '=', True),
- ])
- requests2 = cls.search([
- ('act_from', '=', user),
- ('act_to', '!=', user),
- ('state', '!=', 'draft'),
- ('active', '=', True),
- ])
- return ([r.id for r in requests], [r.id for r in requests2])
-
-
-class RequestLink(ModelSQL, ModelView):
- "Request link"
- __name__ = 'res.request.link'
- name = fields.Char('Name', required=True, translate=True)
- model = fields.Selection('models_get', 'Model', required=True)
- priority = fields.Integer('Priority', required=True)
-
- @classmethod
- def __setup__(cls):
- super(RequestLink, cls).__setup__()
- cls._order.insert(0, ('priority', 'ASC'))
-
- @staticmethod
- def default_priority():
- return 5
-
- @staticmethod
- def models_get():
- pool = Pool()
- Model = pool.get('ir.model')
- models = Model.search([])
- res = []
- for model in models:
- res.append((model.model, model.name))
- return res
-
-
-class RequestHistory(ModelSQL, ModelView):
- "Request history"
- __name__ = 'res.request.history'
- name = fields.Char('Summary', required=True, readonly=True)
- request = fields.Many2One('res.request', 'Request', required=True,
- ondelete='CASCADE', select=True, readonly=True)
- act_from = fields.Many2One('res.user', 'From', required=True,
- readonly=True)
- act_to = fields.Many2One('res.user', 'To', required=True, readonly=True)
- body = fields.Text('Body', readonly=True)
- date_sent = fields.DateTime('Date sent', required=True, readonly=True)
- state = fields.Selection(_STATES, 'State', required=True, readonly=True)
- subject = fields.Char('Subject', required=True, readonly=True)
- number_references = fields.Integer('References', readonly=True)
- priority = fields.Selection(_PRIORITIES, 'Priority', required=True,
- readonly=True)
-
- @classmethod
- def __setup__(cls):
- super(RequestHistory, cls).__setup__()
- cls._order.insert(0, ('date_sent', 'DESC'))
-
- @staticmethod
- def default_name():
- return 'No Name'
-
- @staticmethod
- def default_act_from():
- return int(Transaction().user)
-
- @staticmethod
- def default_act_to():
- return int(Transaction().user)
-
- @staticmethod
- def default_date_sent():
- return datetime.datetime.now()
-
- @staticmethod
- def write(records, vals):
- pass
-
-
-class RequestReference(ModelSQL, ModelView):
- "Request Reference"
- __name__ = 'res.request.reference'
- _rec_name = 'reference'
-
- request = fields.Many2One('res.request', 'Request', required=True,
- ondelete="CASCADE", select=True)
- reference = fields.Reference('Reference', selection='links_get',
- required=True)
-
- @staticmethod
- def links_get():
- pool = Pool()
- RequestLink = pool.get('res.request.link')
- request_links = RequestLink.search([])
- return [(x.model, x.name) for x in request_links]
diff --git a/trytond/res/request.xml b/trytond/res/request.xml
deleted file mode 100644
index 649796ce5f..0000000000
--- a/trytond/res/request.xml
+++ /dev/null
@@ -1,94 +0,0 @@
-
-
-
-
-
- res.request
- tree
- request_list
-
-
- res.request
- form
- request_form
-
-
- Requests
- res.request
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- res.request.link
- form
- request_link_form
-
-
- res.request.link
- tree
- request_link_list
-
-
- Request Links
- res.request.link
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- res.request.history
- tree
- request_history_list
-
-
- res.request.history
- form
- request_history_form
-
-
-
- res.request.reference
- tree
- request_reference_list
-
-
- res.request.reference
- form
- request_reference_form
-
-
-
diff --git a/trytond/res/tryton.cfg b/trytond/res/tryton.cfg
index d46848b4b0..b59766d33b 100644
--- a/trytond/res/tryton.cfg
+++ b/trytond/res/tryton.cfg
@@ -5,5 +5,4 @@ xml:
res.xml
group.xml
user.xml
- request.xml
ir.xml
diff --git a/trytond/res/view/request_form.xml b/trytond/res/view/request_form.xml
deleted file mode 100644
index a4225012f1..0000000000
--- a/trytond/res/view/request_form.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
-
diff --git a/trytond/res/view/request_history_form.xml b/trytond/res/view/request_history_form.xml
deleted file mode 100644
index 9f1d9a3c34..0000000000
--- a/trytond/res/view/request_history_form.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
diff --git a/trytond/res/view/request_history_list.xml b/trytond/res/view/request_history_list.xml
deleted file mode 100644
index f2362bac79..0000000000
--- a/trytond/res/view/request_history_list.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
-
-
-
-
-
diff --git a/trytond/res/view/request_link_form.xml b/trytond/res/view/request_link_form.xml
deleted file mode 100644
index 5af2853b59..0000000000
--- a/trytond/res/view/request_link_form.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
diff --git a/trytond/res/view/request_link_list.xml b/trytond/res/view/request_link_list.xml
deleted file mode 100644
index ba1f8f5eaf..0000000000
--- a/trytond/res/view/request_link_list.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
diff --git a/trytond/res/view/request_list.xml b/trytond/res/view/request_list.xml
deleted file mode 100644
index 2e6eebb038..0000000000
--- a/trytond/res/view/request_list.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/trytond/res/view/request_reference_form.xml b/trytond/res/view/request_reference_form.xml
deleted file mode 100644
index 9d2f65a6f9..0000000000
--- a/trytond/res/view/request_reference_form.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
diff --git a/trytond/res/view/request_reference_list.xml b/trytond/res/view/request_reference_list.xml
deleted file mode 100644
index 8a60996523..0000000000
--- a/trytond/res/view/request_reference_list.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-