summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Vanhoren <niv@openerp.com>2010-12-08 18:03:50 +0100
committerOlivier Dony <odo@openerp.com>2010-12-08 18:03:50 +0100
commit2c3cee033d3c2cc9100d315dadb145525d0f808e (patch)
tree653d9da03ff1e56f57734602de63dcd820803055
parentcfa513123a98ea098bcdb042f4a0fe590a4a5bff (diff)
parent402236d40dae999660007dec4e4954d36f0426f7 (diff)
[MERGE] refactor maintenance.contract into publisher_warranty.contract + add system logs scheduler
bzr revid: odo@openerp.com-20101208170350-p8tek7dk7wdtnzvb
-rw-r--r--.bzrignore3
-rw-r--r--bin/addons/base/__init__.py2
-rw-r--r--bin/addons/base/__openerp__.py3
-rw-r--r--bin/addons/base/ir/__init__.py1
-rw-r--r--bin/addons/base/ir/ir_config_parameter.py101
-rw-r--r--bin/addons/base/ir/ir_cron.py3
-rw-r--r--bin/addons/base/maintenance/maintenance.py206
-rw-r--r--bin/addons/base/maintenance/maintenance_security.xml6
-rw-r--r--bin/addons/base/maintenance/maintenance_view.xml131
-rw-r--r--bin/addons/base/publisher_warranty/__init__.py (renamed from bin/addons/base/maintenance/__init__.py)2
-rw-r--r--bin/addons/base/publisher_warranty/publisher_warranty.py323
-rw-r--r--bin/addons/base/publisher_warranty/publisher_warranty_data.xml20
-rw-r--r--bin/addons/base/publisher_warranty/publisher_warranty_view.xml146
-rw-r--r--bin/addons/base/res/res_log.py13
-rw-r--r--bin/addons/base/res/res_log_view.xml2
-rw-r--r--bin/addons/base/security/ir.model.access.csv5
-rw-r--r--bin/tools/config.py24
-rw-r--r--bin/tools/maintenance.py69
18 files changed, 627 insertions, 433 deletions
diff --git a/.bzrignore b/.bzrignore
index 5581ee20f94..f67a6e2c6b6 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -18,3 +18,6 @@ bin/python2.6
build/
bin/yolk
bin/pil*.py
+.project
+.pydevproject
+.settings
diff --git a/bin/addons/base/__init__.py b/bin/addons/base/__init__.py
index bf315934c6d..fe483c40602 100644
--- a/bin/addons/base/__init__.py
+++ b/bin/addons/base/__init__.py
@@ -22,7 +22,7 @@
import ir
import module
import res
-import maintenance
+import publisher_warranty
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/bin/addons/base/__openerp__.py b/bin/addons/base/__openerp__.py
index d57a8878199..eefaf9f4442 100644
--- a/bin/addons/base/__openerp__.py
+++ b/bin/addons/base/__openerp__.py
@@ -71,11 +71,12 @@
'res/ir_property_view.xml',
'security/base_security.xml',
- 'maintenance/maintenance_view.xml',
+ 'publisher_warranty/publisher_warranty_view.xml',
'security/ir.model.access.csv',
'res/res_widget_view.xml',
'res/res_widget_data.xml',
+ 'publisher_warranty/publisher_warranty_data.xml',
],
'demo_xml': [
'base_demo.xml',
diff --git a/bin/addons/base/ir/__init__.py b/bin/addons/base/ir/__init__.py
index 145a167fdc2..9b4eb96df5f 100644
--- a/bin/addons/base/ir/__init__.py
+++ b/bin/addons/base/ir/__init__.py
@@ -34,6 +34,7 @@ import ir_exports
import workflow
import ir_rule
import wizard
+import ir_config_parameter
import osv_memory_autovacuum
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/bin/addons/base/ir/ir_config_parameter.py b/bin/addons/base/ir/ir_config_parameter.py
new file mode 100644
index 00000000000..b1688b9a669
--- /dev/null
+++ b/bin/addons/base/ir/ir_config_parameter.py
@@ -0,0 +1,101 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+"""
+A module to store some configuration parameters relative to a whole database.
+"""
+
+from osv import osv,fields
+import uuid
+import datetime
+from tools import misc
+
+"""
+A dictionary holding some configuration parameters to be initialized when the database is created.
+"""
+_default_parameters = {
+ "database.uuid": lambda: str(uuid.uuid1()),
+ "database.create_date": lambda: datetime.datetime.now().strftime(misc.DEFAULT_SERVER_DATETIME_FORMAT),
+}
+
+class ir_config_parameter(osv.osv):
+ """ An osv to old configuration parameters for a given database.
+
+ To be short, it's just a global dictionary of strings stored in a table. """
+
+ _name = 'ir.config_parameter'
+
+ _columns = {
+ # The key of the configuration parameter.
+ 'key': fields.char('Key', size=256, required=True, select=1),
+ # The value of the configuration parameter.
+ 'value': fields.text('Value', required=True),
+ }
+
+ _sql_constraints = [
+ ('key_uniq', 'unique (key)', 'Key must be unique.')
+ ]
+
+ def init(self, cr):
+ """
+ Initializes the parameters listed in _default_parameters.
+ """
+ for key, func in _default_parameters.iteritems():
+ ids = self.search(cr, 1, [('key','=',key)])
+ if not ids:
+ self.set_param(cr, 1, key, func())
+
+ def get_param(self, cr, uid, key, context=None):
+ """ Get the value of a parameter.
+
+ @param key: The key of the parameter.
+ @type key: string
+ @return: The value of the parameter, False if it does not exist.
+ @rtype: string
+ """
+ ids = self.search(cr, uid, [('key','=',key)], context=context)
+ if not ids:
+ return False
+ param = self.browse(cr, uid, ids[0], context=context)
+ value = param.value
+ return value
+
+ def set_param(self, cr, uid, key, value, context=None):
+ """ Set the value of a parameter.
+
+ @param key: The key of the parameter.
+ @type key: string
+ @param value: The value of the parameter.
+ @type value: string
+ @return: Return the previous value of the parameter of False if it did
+ not existed.
+ @rtype: string
+ """
+ ids = self.search(cr, uid, [('key','=',key)], context=context)
+ if ids:
+ param = self.browse(cr, uid, ids[0], context=context)
+ old = param.value
+ self.write(cr, uid, ids, {'value': value}, context=context)
+ return old
+ else:
+ self.create(cr, uid, {'key': key, 'value': value}, context=context)
+ return False
+
+ir_config_parameter()
diff --git a/bin/addons/base/ir/ir_cron.py b/bin/addons/base/ir/ir_cron.py
index 7e5a73b4aba..391833d2fbe 100644
--- a/bin/addons/base/ir/ir_cron.py
+++ b/bin/addons/base/ir/ir_cron.py
@@ -144,7 +144,8 @@ class ir_cron(osv.osv, netsvc.Agent):
def restart(self, dbname):
self.cancel(dbname)
- self._poolJobs(dbname)
+ # Reschedule cron processing job asap, but not in the current thread
+ self.setAlarm(self._poolJobs, time.time(), dbname, dbname)
def create(self, cr, uid, vals, context=None):
res = super(ir_cron, self).create(cr, uid, vals, context=context)
diff --git a/bin/addons/base/maintenance/maintenance.py b/bin/addons/base/maintenance/maintenance.py
deleted file mode 100644
index 389d915512f..00000000000
--- a/bin/addons/base/maintenance/maintenance.py
+++ /dev/null
@@ -1,206 +0,0 @@
-# -*- coding: utf-8 -*-
-##############################################################################
-#
-# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-##############################################################################
-
-from osv import osv, fields
-import pooler
-import time
-import netsvc
-
-from tools.misc import debug
-from tools.misc import ustr
-from tools.translate import _
-import tools.maintenance as tm
-
-class maintenance_contract_module(osv.osv):
- _name ="maintenance.contract.module"
- _description = "maintenance contract modules"
- _columns = {
- 'name' : fields.char('Name', size=128, required=True),
- 'version': fields.char('Version', size=64,),
- }
-
-maintenance_contract_module()
-
-class maintenance_contract(osv.osv):
- _name = "maintenance.contract"
- _description = "Maintenance Contract"
-
- def _get_valid_contracts(self, cr, uid):
- return [contract for contract in self.browse(cr, uid, self.search(cr, uid, [])) if contract.state == 'valid']
-
- def status(self, cr, uid):
- covered_modules, uncovered_modules = set(), set()
-
- status = 'none'
- for contract in self._get_valid_contracts(cr, uid):
- covered_modules.update([m.name for m in contract.module_ids])
-
- if covered_modules:
- modobj = self.pool.get('ir.module.module')
- modids = modobj.search(cr, uid, [('state', '=', 'installed')])
- uncovered_modules = set(m.name for m in modobj.browse(cr, uid, modids)) - covered_modules
- status = ['full', 'partial'][len(uncovered_modules) > 0]
-
- return {
- 'status': status,
- 'uncovered_modules': list(uncovered_modules),
- }
-
- def send(self, cr, uid, tb, explanations, remarks=None):
- status = self.status(cr, uid)
- if status['status'] != 'full':
- raise osv.except_osv(_('Error'), _("Your can't submit bug reports due to uncovered modules: %s") % (', '.join(status['uncovered_modules']),))
-
- dbmsg = _('This error occurs on database %s') % (cr.dbname,)
- if not remarks:
- remarks = dbmsg
- else:
- remarks += '\n\n-----\n' + dbmsg
-
- valid_contracts = self._get_valid_contracts(cr, uid)
-
- crm_case_id = None
- rc = None
- try:
- for contract in valid_contracts:
- rc = tm.remote_contract(contract.name, contract.password)
- if rc.id:
- break
- rc = None
-
- if not rc:
- raise osv.except_osv(_('Error'), _('Unable to find a valid contract'))
-
- origin = 'client'
- crm_case_id = rc.submit(rc.id, tb, explanations, remarks or '', origin)
-
- except tm.RemoteContractException, rce:
- netsvc.Logger().notifyChannel('maintenance', netsvc.LOG_INFO, rce)
- except osv.except_osv:
- raise
- except:
- pass
-
- cid = rc and rc.name or valid_contracts[0].name
- try:
- # as backup, put it also in another database...
- import urllib
- args = urllib.urlencode({
- 'contract_id': cid,
- 'crm_case_id': crm_case_id or 0,
- 'explanation': explanations,
- 'remark': remarks or '',
- 'tb': tb,
- })
- uo = urllib.urlopen('http://www.openerp.com/scripts/maintenance.php', args)
- submit_result = uo.read()
- debug(submit_result)
- uo.close()
- except:
- if not crm_case_id:
- # TODO schedule a retry (ir.cron)
- return False
- return True
-
- def _valid_get(self, cr, uid, ids, field_name, arg, context=None):
- res = {}
- for contract in self.browse(cr, uid, ids, context=context):
- res[contract.id] = ("unvalid", "valid")[contract.date_stop >= time.strftime('%Y-%m-%d')]
- return res
-
- _columns = {
- 'name' : fields.char('Contract ID', size=256, required=True, readonly=True),
- 'password' : fields.char('Password', size=64, invisible=True, required=True, readonly=True),
- 'date_start' : fields.date('Starting Date', readonly=True),
- 'date_stop' : fields.date('Ending Date', readonly=True),
- 'module_ids' : fields.many2many('maintenance.contract.module', 'maintenance_contract_module_rel', 'contract_id', 'module_id', 'Covered Modules', readonly=True),
- 'state' : fields.function(_valid_get, method=True, string="State", type="selection", selection=[('valid', 'Valid'),('unvalid', 'Unvalid')], readonly=True),
- 'kind' : fields.selection([('full', 'Full'),('partial', 'Partial')], 'Kind', required=True, readonly=True),
- }
- _defaults = {
- 'password' : lambda obj,cr,uid,context={} : '',
- }
- _sql_constraints = [
- ('uniq_name', 'unique(name)', "Your maintenance contract is already subscribed in the system !")
- ]
-
-maintenance_contract()
-
-
-class maintenance_contract_wizard(osv.osv_memory):
- _name = 'maintenance.contract.wizard'
-
- _columns = {
- 'name' : fields.char('Contract ID', size=256, required=True ),
- 'password' : fields.char('Password', size=64, required=True),
- 'state' : fields.selection([('draft', 'Draft'),('validated', 'Validated'),('unvalidated', 'Unvalidated')], 'States'),
- }
-
- _defaults = {
- 'state' : lambda *a: 'draft',
- }
-
- def action_validate(self, cr, uid, ids, context=None):
- if not ids:
- return False
-
- module_proxy = self.pool.get('ir.module.module')
- module_ids = module_proxy.search(cr, uid, [('state', '=', 'installed')])
- modules = module_proxy.read(cr, uid, module_ids, ['name', 'installed_version'])
-
- contract = self.read(cr, uid, ids, ['name', 'password'])[0]
-
- try:
- contract_info = tm.remote_contract(contract['name'], contract['password'], modules)
- except tm.RemoteContractException, rce:
- raise osv.except_osv(_('Error'), ustr(rce))
-
- is_ok = contract_info['status'] in ('partial', 'full')
- if is_ok:
- module_ids = []
- if contract_info['modules_with_contract']:
- for name, version in contract_info['modules_with_contract']:
- contract_module = self.pool.get('maintenance.contract.module')
- res = contract_module.search(cr, uid, [('name', '=', name),('version', '=', version)])
- if not res:
- id = contract_module.create(cr, uid, { 'name' : name, 'version' : version } )
- else:
- id = res[0]
- module_ids.append(id)
-
- self.pool.get('maintenance.contract').create(
- cr,
- uid, {
- 'name' : contract['name'],
- 'password' : contract['password'],
- 'date_start' : contract_info['date_from'],
- 'date_stop' : contract_info['date_to'],
- 'kind' : contract_info['status'],
- 'module_ids' : [(6,0,module_ids)],
- }
- )
-
- return self.write(cr, uid, ids, {'state' : ('unvalidated', 'validated')[is_ok] }, context=context)
-
-maintenance_contract_wizard()
-
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
-
diff --git a/bin/addons/base/maintenance/maintenance_security.xml b/bin/addons/base/maintenance/maintenance_security.xml
deleted file mode 100644
index 04b7d6dc2cf..00000000000
--- a/bin/addons/base/maintenance/maintenance_security.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<openerp>
-<data noupdate="0">
-
-</data>
-</openerp>
diff --git a/bin/addons/base/maintenance/maintenance_view.xml b/bin/addons/base/maintenance/maintenance_view.xml
deleted file mode 100644
index 836344a52df..00000000000
--- a/bin/addons/base/maintenance/maintenance_view.xml
+++ /dev/null
@@ -1,131 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<openerp>
- <data>
-
- <record id="maintenance_contract_tree_view" model="ir.ui.view">
- <field name="name">maintenance.contract.tree</field>
- <field name="model">maintenance.contract</field>
- <field name="type">tree</field>
- <field name="arch" type="xml">
- <tree string="Maintenance Contract">
- <field name="name"/>
- <field name="date_start"/>
- <field name="date_stop"/>
- <field name="state" />
- </tree>
- </field>
- </record>
-
- <record id="maintenance_contract_form_view" model="ir.ui.view">
- <field name="name">maintenance.contract.form</field>
- <field name="model">maintenance.contract</field>
- <field name="type">form</field>
- <field name="arch" type="xml">
- <form string="Maintenance Contract">
- <group col="6" colspan="4">
- <field name="name"/>
- <field name="date_start"/>
- <field name="date_stop"/>
- </group>
- <separator string="Covered Modules" colspan="4"/>
- <field name="module_ids" nolabel="1" colspan="4">
- <tree string="Covered Modules">
- <field name="name" />
- <field name="version" />
- </tree>
- </field>
- <field name="state" colspan="4"/>
- </form>
- </field>
- </record>
-
- <record id="maintenance_contract_search_view" model="ir.ui.view">
- <field name="name">maintenance.contract.search</field>
- <field name="model">maintenance.contract</field>
- <field name="type">search</field>
- <field name="arch" type="xml">
- <search string="Maintenance Contract">
- <field name="name"/>
- <field name="date_start"/>
- <field name="date_stop"/>
- </search>
- </field>
- </record>
-
- <record id="maintenance_contract_view_calendar" model="ir.ui.view">
- <field name="name">maintenance.contract.calendar</field>
- <field name="model">maintenance.contract</field>
- <field name="type">calendar</field>
- <field name="arch" type="xml">
- <calendar string="Maintenance Contract" date_start="date_start" color="state">
- <field name="name"/>
- <field name="state"/>
- </calendar>
- </field>
- </record>
-
- <record id="action_maintenance_contract_form" model="ir.actions.act_window">
- <field name="name">Maintenance Contracts</field>
- <field name="type">ir.actions.act_window</field>
- <field name="res_model">maintenance.contract</field>
- <field name="view_type">form</field>
- <field name="view_mode">tree,form,calendar</field>
- <field name="search_view_id" ref="maintenance_contract_search_view"/>
- </record>
-
- <menuitem
- name="Maintenance"
- id="maintenance"
- parent="base.menu_administration" groups="base.group_extended"/>
-
- <menuitem
- action="action_maintenance_contract_form"
- id="menu_maintenance_contract"
- parent="maintenance"/>
-
- <record id="maintenance_contract_add_wizard" model="ir.ui.view">
- <field name="name">maintenance.contract.add.wizard</field>
- <field name="model">maintenance.contract.wizard</field>
- <field name="type">form</field>
- <field name="arch" type="xml">
- <form string="Add Maintenance Contract" col="2">
- <group col="1">
- <separator string="Add Maintenance Contract" />
- <group states="draft">
- <field name="name" width="250" />
- <newline />
- <field name="password" password="True" />
- <field name="state" invisible="1" />
- </group>
- <group states="validated">
- <label string="Maintenance contract added !"/>
- </group>
- <group states="unvalidated">
- <label string="Could you check your contract information ?" />
- </group>
- </group>
- <group colspan="4">
- <button type="object" string="_Cancel" icon="gtk-cancel" special="cancel" states="draft"/>
- <button type="object" string="_Validate" icon="gtk-apply" name="action_validate" states="draft"/>
- <button type="object" string="_Close" icon="gtk-close" special="cancel" states="validated,unvalidated"/>
- </group>
- </form>
- </field>
- </record>
-
- <record id="action_maintenance_contract_add_wizard" model="ir.actions.act_window">
- <field name="name">Add Maintenance Contract</field>
- <field name="type">ir.actions.act_window</field>
- <field name="res_model">maintenance.contract.wizard</field>
- <field name="view_type">form</field>
- <field name="view_mode">form</field>
- <field name="target">new</field>
- </record>
-
- <menuitem
- action="action_maintenance_contract_add_wizard"
- id="menu_maintenance_contract_add"
- parent="maintenance" />
-
- </data>
-</openerp>
diff --git a/bin/addons/base/maintenance/__init__.py b/bin/addons/base/publisher_warranty/__init__.py
index 329c61301d9..6b60ddf3ca1 100644
--- a/bin/addons/base/maintenance/__init__.py
+++ b/bin/addons/base/publisher_warranty/__init__.py
@@ -19,7 +19,7 @@
#
##############################################################################
-import maintenance
+import publisher_warranty
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/bin/addons/base/publisher_warranty/publisher_warranty.py b/bin/addons/base/publisher_warranty/publisher_warranty.py
new file mode 100644
index 00000000000..34c2329b227
--- /dev/null
+++ b/bin/addons/base/publisher_warranty/publisher_warranty.py
@@ -0,0 +1,323 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 OpenERP S.A. (<http://www.openerp.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+"""
+Module to handle publisher warranty contracts as well as notifications from
+OpenERP.
+"""
+
+import datetime
+import logging
+import sys
+import urllib
+import urllib2
+
+import pooler
+import release
+from osv import osv, fields
+from tools.translate import _
+from tools.safe_eval import safe_eval
+from tools.config import config
+from tools import misc
+
+_logger = logging.getLogger(__name__)
+
+"""
+Time interval that will be used to determine up to which date we will
+check the logs to see if a message we just received was already logged.
+@type: datetime.timedelta
+"""
+_PREVIOUS_LOG_CHECK = datetime.timedelta(days=365)
+
+class publisher_warranty_contract(osv.osv):
+ """
+ Osv representing a publisher warranty contract.
+ """
+ _name = "publisher_warranty.contract"
+
+ def _get_valid_contracts(self, cr, uid):
+ """
+ Return the list of the valid contracts encoded in the system.
+
+ @return: A list of contracts
+ @rtype: list of publisher_warranty.contract browse records
+ """
+ return [contract for contract in self.browse(cr, uid, self.search(cr, uid, []))
+ if contract.state == 'valid']
+
+ def status(self, cr, uid):
+ """ Method called by the client to check availability of publisher warranty contract. """
+
+ contracts = self._get_valid_contracts(cr, uid)
+ return {
+ 'status': "full" if contracts else "none" ,
+ 'uncovered_modules': list(),
+ }
+
+ def send(self, cr, uid, tb, explanations, remarks=None):
+ """ Method called by the client to send a problem to the publisher warranty server. """
+
+ if not remarks:
+ remarks = ""
+
+ valid_contracts = self._get_valid_contracts(cr, uid)
+ valid_contract = valid_contracts[0]
+
+ try:
+ origin = 'client'
+ dbuuid = self.pool.get('ir.config_parameter').get_param(cr, uid, 'database.uuid')
+ db_create_date = self.pool.get('ir.config_parameter').get_param(cr, uid, 'database.create_date')
+
+ msg = {'contract_name': valid_contract.name,
+ 'tb': tb,
+ 'explanations': explanations,
+ 'remarks': remarks,
+ 'origin': origin,
+ 'dbname': cr.dbname,
+ 'dbuuid': dbuuid,
+ 'db_create_date': db_create_date}
+
+
+ add_arg = {"timeout":30} if sys.version_info >= (2,6) else {}
+ uo = urllib2.urlopen(config.get("publisher_warranty_url"),
+ urllib.urlencode({'arg0': msg, "action": "send",}),**add_arg)
+ try:
+ submit_result = uo.read()
+ finally:
+ uo.close()
+
+ result = safe_eval(submit_result)
+
+ crm_case_id = result
+
+ if not crm_case_id:
+ return False
+
+ except osv.except_osv:
+ raise
+ except Exception:
+ _logger.warning("Error sending problem report", exc_info=1)
+ raise osv.except_osv("Connection error", "An error occured during the connection " +
+ "with the publisher warranty server.")
+
+ return True
+
+ def check_validity(self, cr, uid, ids, context=None):
+ """
+ Check the validity of a publisher warranty contract. This method just call get_logs() but checks
+ some more things, so it can be called from a user interface.
+ """
+ contract_id = ids[0]
+ contract = self.browse(cr, uid, contract_id)
+ state = contract.state
+ validated = state != "unvalidated"
+
+ self.get_logs(cr, uid, ids, cron_mode=False, context=context)
+
+ contract = self.browse(cr, uid, contract_id)
+ validated2 = contract.state != "unvalidated"
+ if not validated and not validated2:
+ raise osv.except_osv(_("Contract validation error"),
+ _("Please check your publisher warranty contract name and validity."))
+
+ def get_logs(self, cr, uid, ids, cron_mode=True, context=None):
+ """
+ Send a message to OpenERP's publisher warranty server to check the validity of
+ the contracts, get notifications, etc...
+
+ @param cron_mode: If true, catch all exceptions (appropriate for usage in a cron).
+ @type cron_mode: boolean
+ """
+ try:
+ try:
+ result = get_sys_logs(cr, uid)
+ except Exception:
+ if cron_mode: # we don't want to see any stack trace in cron
+ return False
+ _logger.debug("Exception while sending a get logs messages", exc_info=1)
+ raise osv.except_osv(_("Error"), _("Error during communication with the publisher warranty server."))
+
+ contracts = result["contracts"]
+ for contract in contracts:
+ c_id = self.search(cr, uid, [("name","=",contract)])[0]
+ date_from = contracts[contract][0]
+ date_to = contracts[contract][1]
+ state = contracts[contract][2]
+ self.write(cr, uid, c_id, {
+ "date_start": date_from,
+ "date_stop": date_to,
+ "state": state,
+ })
+
+ limit_date = (datetime.datetime.now() - _PREVIOUS_LOG_CHECK).strftime(misc.DEFAULT_SERVER_DATETIME_FORMAT)
+ for message in result["messages"]:
+ ids = self.pool.get("res.log").search(cr, uid, [("res_model", "=", "publisher_warranty.contract"),
+ ("create_date", ">=", limit_date),
+ ("name", "=", message)])
+ if ids:
+ continue
+ self.pool.get('res.log').create(cr, uid,
+ {
+ 'name': message,
+ 'res_model': "publisher_warranty.contract",
+ "read": True,
+ "user_id": False,
+ },
+ context=context
+ )
+ except Exception:
+ if cron_mode:
+ return False # we don't want to see any stack trace in cron
+ else:
+ raise
+ return True
+
+ def get_last_user_messages(self, cr, uid, limit, context=None):
+ """
+ Get the messages to be written in the web client.
+ @return: A list of html messages with ids, can be False or empty.
+ @rtype: list of tuples(int,string)
+ """
+ ids = self.pool.get('res.log').search(cr, uid, [("res_model", "=", "publisher_warranty.contract")]
+ , order="create_date desc", limit=limit)
+ if not ids:
+ return []
+ messages = [(x.id, x.name) for x in self.pool.get('res.log').browse(cr, uid, ids)]
+
+ return messages
+
+ def del_user_message(self, cr, uid, id, context=None):
+ """
+ Delete a message.
+ """
+ self.pool.get('res.log').unlink(cr, uid, [id])
+
+ return True
+
+ _columns = {
+ 'name' : fields.char('Serial Key', size=384, required=True),
+ 'date_start' : fields.date('Starting Date', readonly=True),
+ 'date_stop' : fields.date('Ending Date', readonly=True),
+ 'state' : fields.selection([('unvalidated', 'Unvalidated'), ('valid', 'Valid')
+ , ('terminated', 'Terminated'), ('canceled', 'Canceled')], string="State", readonly=True),
+ 'kind' : fields.char('Kind', size=64, readonly=True),
+ }
+
+ _defaults = {
+ 'state': 'unvalidated',
+ }
+
+ _sql_constraints = [
+ ('uniq_name', 'unique(name)', "Your publisher warranty contract is already subscribed in the system !")
+ ]
+
+publisher_warranty_contract()
+
+class maintenance_contract(osv.osv_memory):
+ """ Old osv we only keep for compatibility with the clients. """
+
+ _name = "maintenance.contract"
+
+ def status(self, cr, uid):
+ return self.pool.get("publisher_warranty.contract").status(cr, uid)
+
+ def send(self, cr, uid, tb, explanations, remarks=None):
+ return self.pool.get("publisher_warranty.contract").send(cr, uid, tb, explanations, remarks)
+
+maintenance_contract()
+
+class publisher_warranty_contract_wizard(osv.osv_memory):
+ """
+ A wizard osv to help people entering a publisher warranty contract.
+ """
+ _name = 'publisher_warranty.contract.wizard'
+ _inherit = "ir.wizard.screen"
+
+ _columns = {
+ 'name' : fields.char('Serial Key', size=256, required=True ),
+ 'state' : fields.selection([("draft", "Draft"), ("finished", "Finished")])
+ }
+
+ _defaults = {
+ "state": "draft",
+ }
+
+ def action_validate(self, cr, uid, ids, context=None):
+ if not ids:
+ return False
+
+ wiz = self.browse(cr, uid, ids[0])
+ c_name = wiz.name
+
+ contract_osv = self.pool.get("publisher_warranty.contract")
+ contracts = contract_osv.search(cr, uid, [("name","=",c_name)])
+ if contracts:
+ raise osv.except_osv(_("Error"), _("That contract is already registered in the system."))
+
+ contract_id = contract_osv.create(cr, uid, {
+ "name": c_name,
+ "state": "unvalidated",
+ })
+
+ contract_osv.check_validity(cr, uid, [contract_id])
+
+ self.write(cr, uid, ids, {"state": "finished"})
+
+ return True
+
+
+publisher_warranty_contract_wizard()
+
+def get_sys_logs(cr, uid):
+ """
+ Utility method to send a publisher warranty get logs messages.
+ """
+ pool = pooler.get_pool(cr.dbname)
+
+ dbuuid = pool.get('ir.config_parameter').get_param(cr, uid, 'database.uuid')
+ db_create_date = pool.get('ir.config_parameter').get_param(cr, uid, 'database.create_date')
+ nbr_users = pool.get("res.users").search(cr, uid, [], count=True)
+ contractosv = pool.get('publisher_warranty.contract')
+ contracts = contractosv.browse(cr, uid, contractosv.search(cr, uid, []))
+ user = pool.get("res.users").browse(cr, uid, uid)
+ msg = {
+ "dbuuid": dbuuid,
+ "nbr_users": nbr_users,
+ "dbname": cr.dbname,
+ "db_create_date": db_create_date,
+ "version": release.version,
+ "contracts": [c.name for c in contracts],
+ "language": user.context_lang,
+ }
+
+ add_arg = {"timeout":30} if sys.version_info >= (2,6) else {}
+ uo = urllib2.urlopen(config.get("publisher_warranty_url"),
+ urllib.urlencode({'arg0': msg, "action": "update",}), **add_arg)
+ try:
+ submit_result = uo.read()
+ finally:
+ uo.close()
+
+ result = safe_eval(submit_result)
+
+ return result
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+
diff --git a/bin/addons/base/publisher_warranty/publisher_warranty_data.xml b/bin/addons/base/publisher_warranty/publisher_warranty_data.xml
new file mode 100644
index 00000000000..68594e5d88f
--- /dev/null
+++ b/bin/addons/base/publisher_warranty/publisher_warranty_data.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<openerp>
+ <data>
+
+ <record id="ir_cron_ping_scheduler" model="ir.cron">
+ <field name="name">Update System Logs</field>
+ <field eval="True" name="active" />
+ <field name="user_id" ref="base.user_root" />
+ <field name="interval_number">1</field>
+ <field name="interval_type">weeks</field>
+ <field name="numbercall">-1</field>
+ <field eval="False" name="doall" />
+ <field eval="'publisher_warranty.contract'" name="model" />
+ <field eval="'get_logs'" name="function" />
+ <field eval="'(None,)'" name="args" />
+ <field name="priority">1000</field>
+ </record>
+
+ </data>
+</openerp> \ No newline at end of file
diff --git a/bin/addons/base/publisher_warranty/publisher_warranty_view.xml b/bin/addons/base/publisher_warranty/publisher_warranty_view.xml
new file mode 100644
index 00000000000..2eb03715537
--- /dev/null
+++ b/bin/addons/base/publisher_warranty/publisher_warranty_view.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data>
+
+ <record id="publisher_warranty_contract_tree_view" model="ir.ui.view">
+ <field name="name">publisher_warranty.contract.tree</field>
+ <field name="model">publisher_warranty.contract</field>
+ <field name="type">tree</field>
+ <field name="arch" type="xml">
+ <tree string="Publisher Warranty Contracts">
+ <field name="name"/>
+ <field name="date_start"/>
+ <field name="date_stop"/>
+ <field name="state" />
+ </tree>
+ </field>
+ </record>
+
+ <record id="publisher_warranty_contract_form_view" model="ir.ui.view">
+ <field name="name">publisher_warranty.contract.form</field>
+ <field name="model">publisher_warranty.contract</field>
+ <field name="type">form</field>
+ <field name="arch" type="xml">
+ <form string="Publisher Warranty Contract">
+ <group col="2" colspan="4">
+ <group col="2">
+ <field name="name"/>
+ </group>
+ <group col="2">
+ <field name="date_start"/>
+ <field name="date_stop"/>
+ </group>
+ <group col="2">
+ <field name="state"/>
+ <field name="kind"/>
+ </group>
+ <group col="2">
+ <button name="check_validity" string="Validate" type="object"
+ attrs="{'invisible':[('state','in',['valid', 'terminated', 'canceled'])]}"/>
+ <button name="check_validity" string="Refresh Validation Dates" type="object"
+ attrs="{'invisible':[('state','in',['unvalidated'])]}"/>
+ </group>
+ </group>
+ </form>
+ </field>
+ </record>
+
+ <record id="publisher_warranty_contract_search_view" model="ir.ui.view">
+ <field name="name">publisher_warranty.contract.search</field>
+ <field name="model">publisher_warranty.contract</field>
+ <field name="type">search</field>
+ <field name="arch" type="xml">
+ <search string="Publisher Warranty Contract">
+ <field name="name"/>
+ <field name="date_start"/>
+ <field name="date_stop"/>
+ </search>
+ </field>
+ </record>
+
+ <record id="publisher_warranty_contract_view_calendar" model="ir.ui.view">
+ <field name="name">publisher_warranty.contract.calendar</field>
+ <field name="model">publisher_warranty.contract</field>
+ <field name="type">calendar</field>
+ <field name="arch" type="xml">
+ <calendar string="Maintenance Contract" date_start="date_start" color="state">
+ <field name="name"/>
+ <field name="state"/>
+ </calendar>
+ </field>
+ </record>
+
+ <record id="action_publisher_warranty_contract_form" model="ir.actions.act_window">
+ <field name="name">Contracts</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">publisher_warranty.contract</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">tree,form,calendar</field>
+ <field name="search_view_id" ref="publisher_warranty_contract_search_view"/>
+ </record>
+
+ <menuitem name="Publisher Warranty" id="publisher_warranty"
+ parent="base.menu_administration" groups="base.group_extended"/>
+
+ <menuitem action="action_publisher_warranty_contract_form" id="menu_publisher_warranty_contract"
+ parent="publisher_warranty" sequence="2"/>
+
+
+ <record id="publisher_warranty_contract_add_wizard" model="ir.ui.view">
+ <field name="name">publisher_warranty.contract.add.wizard</field>
+ <field name="model">publisher_warranty.contract.wizard</field>
+ <field name="type">form</field>
+ <field name="arch" type="xml">
+ <form string="Register a Contract">
+ <group col="8">
+ <group colspan="3" col="1">
+ <field name="config_logo" widget="image" width="220" height="130" nolabel="1" colspan="1"/>
+ <newline/>
+ <label width="220" string="This wizard helps you register a publisher warranty contract in your OpenERP system. After the contract has been registered, you will be able to send issues directly to OpenERP."/>
+ <label width="220"/>
+ <label width="220" string=""/>
+ <field name="state" invisible="1"/>
+ </group>
+ <separator orientation="vertical" rowspan="5"/>
+ <group colspan="4">
+ <separator string="Register a Contract" colspan="4"/>
+ <group states="draft" col="4">
+ <label string="Please enter the serial key provided in your contract document:" colspan="4"/>
+ <field name="name" colspan="4"/>
+ </group>
+ <group states="finished" col="4">
+ <label string="Publisher warranty contract successfully registered!" colspan="4"/>
+ </group>
+ </group>
+ <group colspan="8" col="8" states="draft">
+ <separator string="" colspan="8"/>
+ <label colspan="6" width="220"/>
+ <button special="cancel" string="Cancel" icon="gtk-cancel"/>
+ <button name="action_validate" string="Register" type="object" icon="gtk-apply"/>
+ </group>
+ <group colspan="8" col="8" states="finished">
+ <separator string="" colspan="8"/>
+ <label colspan="6" width="220"/>
+ <button special="cancel" string="Close" icon="gtk-ok"/>
+ </group>
+ </group>
+ </form>
+ </field>
+ </record>
+
+ <record id="action_publisher_warranty_contract_add_wizard" model="ir.actions.act_window">
+ <field name="name">Register a Contract</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">publisher_warranty.contract.wizard</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">form</field>
+ <field name="target">new</field>
+ </record>
+
+ <menuitem
+ action="action_publisher_warranty_contract_add_wizard"
+ id="menu_publisher_warranty_contract_add"
+ parent="publisher_warranty" sequence="1"/>
+
+ </data>
+</openerp>
diff --git a/bin/addons/base/res/res_log.py b/bin/addons/base/res/res_log.py
index 0862a686aa8..26e1eaeed69 100644
--- a/bin/addons/base/res/res_log.py
+++ b/bin/addons/base/res/res_log.py
@@ -20,24 +20,23 @@
##############################################################################
from osv import fields, osv
-import tools
class res_log(osv.osv):
_name = 'res.log'
_columns = {
- 'name': fields.char('Message', size=128, help='The logging message.', required=True),
- 'user_id': fields.many2one('res.users','User', required=True),
- 'res_model': fields.char('Object', size=128),
+ 'name': fields.char('Message', size=250, help='The logging message.', required=True, select=1),
+ 'user_id': fields.many2one('res.users','User'),
+ 'res_model': fields.char('Object', size=128, select=1),
'context': fields.char('Context', size=250),
'res_id': fields.integer('Object ID'),
'secondary': fields.boolean('Secondary Log', help='Do not display this log if it belongs to the same object the user is working on'),
- 'create_date': fields.datetime('Created Date', readonly=True),
- 'read': fields.boolean('Read', help="If this log item has been read, get() should not send it to the client")
+ 'create_date': fields.datetime('Creation Date', readonly=True, select=1),
+ 'read': fields.boolean('Read', help="If this log item has been read, get() should not send it to the client"),
}
_defaults = {
'user_id': lambda self,cr,uid,ctx: uid,
'context': "{}",
- 'read': False
+ 'read': False,
}
_order='create_date desc'
diff --git a/bin/addons/base/res/res_log_view.xml b/bin/addons/base/res/res_log_view.xml
index 4fc137eb26b..86d1e0d06cb 100644
--- a/bin/addons/base/res/res_log_view.xml
+++ b/bin/addons/base/res/res_log_view.xml
@@ -11,6 +11,8 @@
<filter icon="terp-stock_align_left_24" string="Unread" domain="[('read','&lt;&gt;',True)]" name="unread"/>
<separator orientation="vertical"/>
<filter icon="terp-stock_align_left_24" string="My Logs" domain="[('user_id','=',uid)]" name="my"/>
+ <filter icon="terp-stock_align_left_24" string="System Logs"
+ domain="[('res_model','=','publisher_warranty.contract')]" name="sys"/>
<separator orientation="vertical"/>
<field name="name"/>
<field name="user_id"/>
diff --git a/bin/addons/base/security/ir.model.access.csv b/bin/addons/base/security/ir.model.access.csv
index 62eb8ffe2b1..b83d858d4e8 100644
--- a/bin/addons/base/security/ir.model.access.csv
+++ b/bin/addons/base/security/ir.model.access.csv
@@ -112,8 +112,8 @@
"access_res_payterm_group_system","res_payterm_group_system","model_res_payterm","group_system",1,1,1,1
"access_res_bank_group_partner_manager","res_bank_group_partner_manager","model_res_bank","group_partner_manager",1,1,1,1
"access_res_bank_user","res_bank user","model_res_bank","group_user",1,0,0,0
-"access_maintenance_group_user","maintenance_contract group_user","model_maintenance_contract","group_system",1,1,1,1
-"access_maintenance_contract_module","maintenance.contract.module","model_maintenance_contract_module","group_system",1,1,1,1
+"access_publisher_warranty_group_user","publisher_warranty_contract group_user","model_publisher_warranty_contract","group_system",1,1,1,1
+"access_publisher_warranty_all","publisher_warranty_contract all","model_publisher_warranty_contract",,1,0,0,0
"access_multi_company_default user","multi_company_default all","model_multi_company_default",,1,0,0,0
"access_multi_company_default manager","multi_company_default Manager","model_multi_company_default","group_erp_manager",1,1,1,1
"access_ir_filter all","ir_filters all","model_ir_filters",,1,0,0,0
@@ -123,3 +123,4 @@
"access_res_widget","res.widget","model_res_widget","group_erp_manager",1,1,1,1
"access_res_widget_user","res.widget.user","model_res_widget",,1,0,0,0
"access_res_log_all","res.log","model_res_log",,1,1,1,1
+"access_ir_config_parameter","ir_config_parameter","model_ir_config_parameter",,1,0,0,0
diff --git a/bin/tools/config.py b/bin/tools/config.py
index f98cdbab1b9..0fe2664c2a9 100644
--- a/bin/tools/config.py
+++ b/bin/tools/config.py
@@ -31,8 +31,8 @@ def check_ssl():
try:
from OpenSSL import SSL
import socket
-
- return hasattr(socket, 'ssl')
+
+ return hasattr(socket, 'ssl') and hasattr(SSL, "Connection")
except:
return False
@@ -91,7 +91,10 @@ class configmanager(object):
'static_http_url_prefix': None,
'secure_cert_file': 'server.cert',
'secure_pkey_file': 'server.pkey',
+ 'publisher_warranty_url': 'http://services.openerp.com/publisher-warranty',
}
+
+ self.blacklist_for_save = set(["publisher_warranty_url"])
self.misc = {}
self.config_file = fname
@@ -224,7 +227,7 @@ class configmanager(object):
parser.add_option_group(security)
def parse_config(self):
- (opt, args) = self.parser.parse_args()
+ opt = self.parser.parse_args()[0]
def die(cond, msg):
if cond:
@@ -317,7 +320,7 @@ class configmanager(object):
# If an explicit TZ was provided in the config, make sure it is known
try:
import pytz
- tz = pytz.timezone(self.options['timezone'])
+ pytz.timezone(self.options['timezone'])
except pytz.UnknownTimeZoneError:
die(True, "The specified timezone (%s) is invalid" % self.options['timezone'])
except:
@@ -374,7 +377,10 @@ class configmanager(object):
fp.close()
if is_win32:
- import _winreg
+ try:
+ import _winreg
+ except ImportError:
+ _winreg = None
x=_winreg.ConnectRegistry(None,_winreg.HKEY_LOCAL_MACHINE)
y = _winreg.OpenKey(x, r"SYSTEM\CurrentControlSet\Control\Session Manager\Environment", 0,_winreg.KEY_ALL_ACCESS)
_winreg.SetValueEx(y,"PGPASSFILE", 0, _winreg.REG_EXPAND_SZ, filename )
@@ -436,16 +442,18 @@ class configmanager(object):
p = ConfigParser.ConfigParser()
loglevelnames = dict(zip(self._LOGLEVELS.values(), self._LOGLEVELS.keys()))
p.add_section('options')
- for opt in self.options.keys():
+ for opt in sorted(self.options.keys()):
if opt in ('version', 'language', 'translate_out', 'translate_in', 'init', 'update'):
continue
+ if opt in self.blacklist_for_save:
+ continue
if opt in ('log_level', 'assert_exit_level'):
p.set('options', opt, loglevelnames.get(self.options[opt], self.options[opt]))
else:
p.set('options', opt, self.options[opt])
- for sec in self.misc.keys():
- for opt in self.misc[sec].keys():
+ for sec in sorted(self.misc.keys()):
+ for opt in sorted(self.misc[sec].keys()):
p.set(sec,opt,self.misc[sec][opt])
# try to create the directories and write the file
diff --git a/bin/tools/maintenance.py b/bin/tools/maintenance.py
deleted file mode 100644
index 83cf5e3b8bd..00000000000
--- a/bin/tools/maintenance.py
+++ /dev/null
@@ -1,69 +0,0 @@
-# -*- coding: utf-8 -*-
-##############################################################################
-#
-# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-##############################################################################
-
-import xmlrpclib
-
-class RemoteContractException(Exception): pass
-
-class remote_contract(object):
- def __init__(self, contract_id, contract_password, modules=None):
- self.__server = 'http://tiny.my.odoo.com:8069/xmlrpc/'
- self.__db = "tiny_belgium"
- self.__password = "maintenance"
- self.__login = "maintenance"
-
- rpc = xmlrpclib.ServerProxy(self.__server + 'common')
- try:
- self.__userid = rpc.login(self.__db, self.__login, self.__password)
- except:
- raise RemoteContractException("Unable to contact the migration server")
-
- if not self.__userid:
- raise RemoteContractException("Unable to contact the migration server")
-
- self.__rpc = xmlrpclib.ServerProxy(self.__server + 'object')
-
-
- contract = {
- 'name': contract_id,
- 'password': contract_password,
- }
- if modules is None:
- modules = []
-
- info = self.check_contract(modules, contract)
- for n in info:
- setattr(self, n, info[n])
-
- self.name = contract_id
- self.contract_id = self.name
- self.password = contract_password
-
- def __getattr__(self, fun):
- def remote_call(*args, **kwargs):
- return self.__rpc.execute(self.__db, self.__userid, self.__password, 'maintenance.maintenance', fun, *args, **kwargs)
- return remote_call
-
- def __getitem__(self, item):
- return getattr(self, item)
-
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
-