2012-10-16 17:05:20 +02:00
|
|
|
# This file is part of subscription module of Tryton.
|
2012-10-25 11:26:36 +02:00
|
|
|
# The COPYRIGHT file at the top level of this repository contains the full
|
|
|
|
# copyright notices and license terms.
|
2012-10-16 17:05:20 +02:00
|
|
|
|
2012-10-25 14:10:24 +02:00
|
|
|
from datetime import datetime
|
2012-10-16 17:05:20 +02:00
|
|
|
from trytond.model import ModelView, ModelSQL, fields
|
2012-10-23 14:05:46 +02:00
|
|
|
from trytond.pool import Pool
|
2012-10-25 14:10:24 +02:00
|
|
|
from trytond.pyson import Eval, Get, Id
|
2012-10-23 14:05:46 +02:00
|
|
|
from trytond.transaction import Transaction
|
2012-10-25 14:10:24 +02:00
|
|
|
import logging
|
2012-10-16 17:05:20 +02:00
|
|
|
|
2012-10-25 11:26:36 +02:00
|
|
|
__all__ = [
|
2012-10-16 17:05:20 +02:00
|
|
|
'SubscriptionSubscription',
|
2012-10-25 11:26:36 +02:00
|
|
|
'SubscriptionLine',
|
2012-10-25 14:26:03 +02:00
|
|
|
'SubscriptionHistory',
|
2012-10-16 17:05:20 +02:00
|
|
|
]
|
|
|
|
|
2012-10-25 11:26:36 +02:00
|
|
|
STATES = {
|
|
|
|
'readonly': ~Eval('state', 'running'),
|
|
|
|
}
|
|
|
|
DEPENDS = ['state']
|
2012-10-16 17:05:20 +02:00
|
|
|
|
|
|
|
class SubscriptionSubscription(ModelSQL, ModelView):
|
2012-10-25 11:26:36 +02:00
|
|
|
'Subscription'
|
|
|
|
__name__ = 'subscription.subscription'
|
2012-10-16 17:05:20 +02:00
|
|
|
|
2012-10-23 14:05:46 +02:00
|
|
|
name = fields.Char('Name', select=True, required=True, translate=True)
|
|
|
|
user = fields.Many2One('res.user', 'User', required=True,
|
|
|
|
domain=[('active', '=', False)])
|
|
|
|
request_user = fields.Many2One(
|
|
|
|
'res.user', 'Request User', required=True,
|
2012-10-25 11:26:36 +02:00
|
|
|
help='The user who will receive requests in case of failure.')
|
|
|
|
request_group = fields.Many2One(
|
|
|
|
'res.group', 'Request Group',
|
|
|
|
help='The group who will receive requests in case of failure.')
|
2012-10-16 17:05:20 +02:00
|
|
|
active = fields.Boolean('Active', select=True,
|
2012-10-25 11:26:36 +02:00
|
|
|
help='If the active field is set to False, it will allow you to ' \
|
|
|
|
'hide the subscription without removing it.')
|
|
|
|
interval_number = fields.Integer('Interval Qty')
|
2012-10-16 17:05:20 +02:00
|
|
|
interval_type = fields.Selection([
|
|
|
|
('days', 'Days'),
|
|
|
|
('weeks', 'Weeks'),
|
|
|
|
('months', 'Months'),
|
|
|
|
], 'Interval Unit')
|
2012-10-25 11:26:36 +02:00
|
|
|
number_calls = fields.Integer('Number of documents')
|
|
|
|
next_call = fields.DateTime('First Date')
|
2012-10-16 17:05:20 +02:00
|
|
|
state = fields.Selection([
|
|
|
|
('draft','Draft'),
|
|
|
|
('running','Running'),
|
2012-10-23 14:05:46 +02:00
|
|
|
('done','Done')], 'State', readonly=True)
|
2012-10-25 11:26:36 +02:00
|
|
|
model_source = fields.Reference('Source Document',
|
|
|
|
selection='get_model', depends=['state'],
|
2012-10-23 14:05:46 +02:00
|
|
|
states={'readonly': Eval('state') == 'running'},
|
2012-10-25 11:26:36 +02:00
|
|
|
help='User can choose the source model on which he wants to ' \
|
|
|
|
'create models.')
|
|
|
|
lines = fields.One2Many('subscription.line', 'subscription', 'Lines')
|
2012-10-25 14:26:03 +02:00
|
|
|
history = fields.One2Many('subscription.history',
|
|
|
|
'subscription', 'History')
|
2012-10-16 17:05:20 +02:00
|
|
|
cron = fields.Many2One('ir.cron', 'Cron Job',
|
2012-10-25 11:26:36 +02:00
|
|
|
help='Scheduler which runs on subscription.', ondelete='CASCADE')
|
|
|
|
note = fields.Text('Notes', help='Description or Summary of Subscription.')
|
2012-10-16 17:05:20 +02:00
|
|
|
|
2012-10-23 14:05:46 +02:00
|
|
|
@classmethod
|
|
|
|
def __setup__(cls):
|
|
|
|
super(SubscriptionSubscription, cls).__setup__()
|
|
|
|
cls._buttons.update({
|
2012-10-25 11:26:36 +02:00
|
|
|
'set_process': {
|
|
|
|
'invisible': Eval('state') != 'draft',
|
|
|
|
},
|
|
|
|
'set_done': {
|
|
|
|
'invisible': Eval('state') != 'running',
|
|
|
|
},
|
|
|
|
'set_draft': {
|
|
|
|
'invisible': Eval('state') != 'done',
|
|
|
|
},
|
|
|
|
})
|
|
|
|
cls._error_messages.update({
|
|
|
|
'error': 'Error. Wrong Source Document',
|
|
|
|
'provide_another_source': 'Please provide another source ' \
|
|
|
|
'model.\nThis one does not exist!',
|
|
|
|
})
|
|
|
|
cls._sql_constraints = [
|
|
|
|
('name_unique', 'UNIQUE(name)',
|
|
|
|
'The name of the subscription must be unique!')
|
|
|
|
]
|
2012-10-23 14:05:46 +02:00
|
|
|
|
|
|
|
@staticmethod
|
2012-10-25 11:26:36 +02:00
|
|
|
def default_next_call():
|
2012-10-23 14:05:46 +02:00
|
|
|
return datetime.now()
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def default_user():
|
|
|
|
User = Pool().get('res.user')
|
|
|
|
user_ids = User.search([
|
|
|
|
('active', '=', False),
|
|
|
|
('login', '=', 'user_cron_trigger'),
|
|
|
|
])
|
|
|
|
return user_ids[0].id
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def default_request_user():
|
|
|
|
return Transaction().user
|
|
|
|
|
2012-10-16 17:05:20 +02:00
|
|
|
@staticmethod
|
|
|
|
def default_active():
|
|
|
|
return True
|
|
|
|
|
2012-10-23 14:05:46 +02:00
|
|
|
@staticmethod
|
2012-10-25 11:26:36 +02:00
|
|
|
def default_interval_number():
|
|
|
|
return 1
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def default_number_calls():
|
2012-10-23 14:05:46 +02:00
|
|
|
return 1
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def default_interval_type():
|
|
|
|
return 'months'
|
|
|
|
|
|
|
|
@staticmethod
|
2012-10-25 11:26:36 +02:00
|
|
|
def default_model_source():
|
2012-10-23 14:05:46 +02:00
|
|
|
return False
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def default_state():
|
|
|
|
return 'draft'
|
2012-10-25 11:26:36 +02:00
|
|
|
#
|
2012-10-23 14:05:46 +02:00
|
|
|
@classmethod
|
2012-10-25 11:26:36 +02:00
|
|
|
def get_model(cls):
|
2012-10-23 14:05:46 +02:00
|
|
|
cr = Transaction().cursor
|
|
|
|
cr.execute('''\
|
|
|
|
SELECT
|
|
|
|
m.model,
|
2012-10-25 11:26:36 +02:00
|
|
|
m.name
|
2012-10-23 14:05:46 +02:00
|
|
|
FROM
|
|
|
|
ir_model m
|
|
|
|
ORDER BY
|
2012-10-25 11:26:36 +02:00
|
|
|
m.name
|
2012-10-23 14:05:46 +02:00
|
|
|
''')
|
2012-10-25 11:26:36 +02:00
|
|
|
return cr.fetchall()
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
@ModelView.button
|
|
|
|
def set_process(self, subscriptions):
|
|
|
|
for subscription in subscriptions:
|
|
|
|
prova = str([subscription])
|
|
|
|
prova2 = repr
|
|
|
|
vals = {
|
|
|
|
'model': subscription.__name__,
|
|
|
|
'name': subscription.name,
|
|
|
|
'user': subscription.user.id,
|
|
|
|
'request_user': subscription.request_user.id,
|
|
|
|
'interval_number': subscription.interval_number,
|
|
|
|
'interval_type': subscription.interval_type,
|
|
|
|
'number_calls': subscription.number_calls or 1,
|
|
|
|
'next_call': subscription.next_call,
|
|
|
|
'args': str([subscription.id]),
|
|
|
|
'function': 'model_copy',
|
|
|
|
}
|
2012-10-23 14:05:46 +02:00
|
|
|
Cron = Pool().get('ir.cron')
|
2012-10-25 11:26:36 +02:00
|
|
|
domain = [
|
|
|
|
('model', '=', subscription.__name__),
|
|
|
|
('name', '=', subscription.name),
|
|
|
|
('active', '=', False),
|
|
|
|
]
|
|
|
|
cron = Cron.search([domain])
|
|
|
|
if not cron:
|
|
|
|
cron = Cron.create(vals)
|
|
|
|
else:
|
|
|
|
vals['active'] = True
|
|
|
|
Cron.write(cron, vals)
|
|
|
|
cron = cron[0]
|
|
|
|
vals = {
|
|
|
|
'cron': cron.id,
|
|
|
|
'state': 'running',
|
|
|
|
}
|
|
|
|
self.write([subscription], vals)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def model_copy(cls, subscription_id=None):
|
|
|
|
Cron = Pool().get('ir.cron')
|
2012-10-25 16:29:26 +02:00
|
|
|
History = Pool().get('subscription.history')
|
2012-10-25 11:26:36 +02:00
|
|
|
subscription = cls(subscription_id)
|
2012-10-25 14:10:24 +02:00
|
|
|
logger = logging.getLogger('subscription_subscription')
|
2012-10-25 11:26:36 +02:00
|
|
|
remaining = Cron.browse([subscription.cron.id])[0].number_calls
|
|
|
|
model_id = subscription.model_source and subscription.model_source.id \
|
|
|
|
or False
|
|
|
|
if model_id:
|
|
|
|
Model = Pool().get(subscription.model_source.__name__)
|
|
|
|
default = {'state':'draft'}
|
|
|
|
localspace = {
|
|
|
|
'self': subscription,
|
|
|
|
'pool': Pool(),
|
|
|
|
'transaction': Transaction(),
|
|
|
|
}
|
|
|
|
for line in subscription.lines:
|
2012-10-25 14:10:24 +02:00
|
|
|
with Transaction().set_context():
|
2012-10-25 11:26:36 +02:00
|
|
|
try:
|
2012-10-25 14:10:24 +02:00
|
|
|
exec line.value in localspace
|
2012-10-25 11:26:36 +02:00
|
|
|
except SyntaxError, e:
|
2012-10-25 14:10:24 +02:00
|
|
|
logger.error('Syntax Error in field %s.\n'\
|
|
|
|
'Error: %s' % (line.field.name, e))
|
|
|
|
return None
|
2012-10-25 11:26:36 +02:00
|
|
|
except NameError, e:
|
2012-10-25 14:10:24 +02:00
|
|
|
logger.error('Syntax Error in field %s.\n'\
|
|
|
|
'Error: %s' % (line.field.name, e))
|
|
|
|
return None
|
2012-10-25 11:26:36 +02:00
|
|
|
except Exception, e:
|
2012-10-25 14:10:24 +02:00
|
|
|
logger.error('Unkonwn Error in field %s.'\
|
|
|
|
'\nMessage: %s' % (line.field.name, e))
|
|
|
|
return None
|
|
|
|
default[line.field.name] = localspace['result'] \
|
2012-10-25 11:26:36 +02:00
|
|
|
if 'result' in localspace else False
|
2012-10-25 16:29:26 +02:00
|
|
|
try:
|
|
|
|
model_id = Model.copy([subscription.model_source], default)
|
|
|
|
except:
|
|
|
|
vals = {
|
|
|
|
'log': str('Error creating document %s. See logs for ' \
|
|
|
|
'more information.' % \
|
|
|
|
subscription.model_source.__name__),
|
|
|
|
'subscription': subscription,
|
|
|
|
}
|
|
|
|
else:
|
|
|
|
vals = {
|
|
|
|
'log': 'Document %s created successfully.' % \
|
|
|
|
subscription.model_source.__name__,
|
|
|
|
'subscription': subscription.id,
|
|
|
|
# 'model': (subscription.model_source.__name__, model_id),
|
|
|
|
}
|
|
|
|
History.create(vals)
|
2012-10-25 11:26:36 +02:00
|
|
|
if remaining == 1:
|
2012-10-25 16:50:08 +02:00
|
|
|
subscription.write([subscription], {'state': 'done'})
|
2012-10-25 11:26:36 +02:00
|
|
|
else:
|
|
|
|
logger.error('Document in subscription %s not found.\n' % \
|
|
|
|
subscription.name)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
@ModelView.button
|
|
|
|
def set_done(self, subscriptions):
|
|
|
|
for subscription in subscriptions:
|
|
|
|
Pool().get('ir.cron').write([subscription.cron], {'active': False})
|
|
|
|
self.write([subscription], {'state':'draft'})
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
@ModelView.button
|
|
|
|
def set_draft(self, subscriptions):
|
2012-10-25 16:50:08 +02:00
|
|
|
self.write(subscriptions, {'state':'draft'})
|
2012-10-23 14:05:46 +02:00
|
|
|
|
2012-10-16 17:05:20 +02:00
|
|
|
|
2012-10-25 11:26:36 +02:00
|
|
|
class SubscriptionLine(ModelSQL, ModelView):
|
|
|
|
'Subscription Line'
|
|
|
|
__name__ = 'subscription.line'
|
2012-10-25 14:10:24 +02:00
|
|
|
_rec_name = 'field'
|
2012-10-16 17:05:20 +02:00
|
|
|
|
|
|
|
subscription = fields.Many2One('subscription.subscription',
|
2012-10-25 11:26:36 +02:00
|
|
|
'Subscription', ondelete='CASCADE', select=True)
|
2012-10-25 14:10:24 +02:00
|
|
|
# name = fields.Many2One('ir.model.field', 'Field',
|
|
|
|
# domain=[('model', '=',
|
|
|
|
# Id(Eval('_parent_subscription', {}), 'model_source')
|
|
|
|
# )],
|
|
|
|
# select=True, required=True)
|
|
|
|
field = fields.Many2One('ir.model.field', 'Field',
|
|
|
|
# domain=[(
|
|
|
|
# 'model', '=', Eval('_parent_subscription', {}).get('model_source')
|
|
|
|
# )],
|
|
|
|
select=True, required=True)
|
2012-10-25 11:26:36 +02:00
|
|
|
value = fields.Char('Default Value', required=True,
|
|
|
|
help='Default value is considered for field when new subscription ' \
|
2012-10-25 14:10:24 +02:00
|
|
|
'is generated. You must put here a Python expression. The ' \
|
|
|
|
'available variables are:\n' \
|
|
|
|
' - self: The current subcription object.\n' \
|
|
|
|
' - pool: The store of the instances of models.\n' \
|
|
|
|
' - transaction: That contains thread-local parameters of the ' \
|
|
|
|
'database transaction.\n' \
|
|
|
|
'You must return a value into a variable called "result".\n' \
|
|
|
|
'As an example to get the current date:\n\n' \
|
2012-10-25 14:12:11 +02:00
|
|
|
'result = pool.get(\'ir.date\').today()')
|
2012-10-25 11:26:36 +02:00
|
|
|
|
|
|
|
|
2012-10-25 14:26:03 +02:00
|
|
|
class SubscriptionHistory(ModelSQL, ModelView):
|
|
|
|
"Subscription History"
|
|
|
|
__name__ = "subscription.history"
|
|
|
|
_rec_name = 'date'
|
|
|
|
|
2012-10-25 16:29:26 +02:00
|
|
|
date = fields.DateTime('Date')
|
|
|
|
subscription = fields.Many2One('subscription.subscription',
|
|
|
|
'Subscription')
|
|
|
|
log = fields.Char('Result')
|
2012-10-25 14:26:03 +02:00
|
|
|
subscription = fields.Many2One('subscription.subscription',
|
|
|
|
'Subscription', ondelete='CASCADE')
|
2012-10-25 16:29:26 +02:00
|
|
|
# document = fields.Reference('Source Document', selection=[],
|
|
|
|
# readonly=True)
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def default_date():
|
|
|
|
return datetime.now()
|
2012-10-25 14:26:03 +02:00
|
|
|
|