diff --git a/README.md b/README.md
index a33e4c89e48..9e77856701a 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,5 @@
+
+
Odoo
----
diff --git a/addons/account/account_invoice.py b/addons/account/account_invoice.py
index 9d4654c9eee..eb43830f8f6 100644
--- a/addons/account/account_invoice.py
+++ b/addons/account/account_invoice.py
@@ -1546,7 +1546,7 @@ class account_invoice_line(osv.osv):
context = dict(context)
context.update({'company_id': company_id})
warning = {}
- res = self.product_id_change(cr, uid, ids, product, uom, qty, name, type, partner_id, fposition_id, price_unit, currency_id, context=context)
+ res = self.product_id_change(cr, uid, ids, product, uom, qty, name, type, partner_id, fposition_id, price_unit, currency_id, context=context, company_id=company_id)
if not uom:
res['value']['price_unit'] = 0.0
if product and uom:
diff --git a/addons/account_analytic_default/account_analytic_default.py b/addons/account_analytic_default/account_analytic_default.py
index ac8698ae342..e0e8f7292ef 100644
--- a/addons/account_analytic_default/account_analytic_default.py
+++ b/addons/account_analytic_default/account_analytic_default.py
@@ -39,7 +39,7 @@ class account_analytic_default(osv.osv):
'date_stop': fields.date('End Date', help="Default end date for this Analytic Account."),
}
- def account_get(self, cr, uid, product_id=None, partner_id=None, user_id=None, date=None, context=None):
+ def account_get(self, cr, uid, product_id=None, partner_id=None, user_id=None, date=None, company_id=None, context=None):
domain = []
if product_id:
domain += ['|', ('product_id', '=', product_id)]
@@ -47,6 +47,9 @@ class account_analytic_default(osv.osv):
if partner_id:
domain += ['|', ('partner_id', '=', partner_id)]
domain += [('partner_id', '=', False)]
+ if company_id:
+ domain += ['|', ('company_id', '=', company_id)]
+ domain += [('company_id', '=', False)]
if user_id:
domain += ['|',('user_id', '=', user_id)]
domain += [('user_id','=', False)]
@@ -59,6 +62,7 @@ class account_analytic_default(osv.osv):
index = 0
if rec.product_id: index += 1
if rec.partner_id: index += 1
+ if rec.company_id: index += 1
if rec.user_id: index += 1
if rec.date_start: index += 1
if rec.date_stop: index += 1
@@ -74,7 +78,7 @@ class account_invoice_line(osv.osv):
def product_id_change(self, cr, uid, ids, product, uom_id, qty=0, name='', type='out_invoice', partner_id=False, fposition_id=False, price_unit=False, currency_id=False, context=None, company_id=None):
res_prod = super(account_invoice_line, self).product_id_change(cr, uid, ids, product, uom_id, qty, name, type, partner_id, fposition_id, price_unit, currency_id=currency_id, context=context, company_id=company_id)
- rec = self.pool.get('account.analytic.default').account_get(cr, uid, product, partner_id, uid, time.strftime('%Y-%m-%d'), context=context)
+ rec = self.pool.get('account.analytic.default').account_get(cr, uid, product, partner_id, uid, time.strftime('%Y-%m-%d'), company_id=company_id, context=context)
if rec:
res_prod['value'].update({'account_analytic_id': rec.analytic_id.id})
else:
@@ -88,7 +92,7 @@ class stock_picking(osv.osv):
def _get_account_analytic_invoice(self, cursor, user, picking, move_line):
partner_id = picking.partner_id and picking.partner_id.id or False
- rec = self.pool.get('account.analytic.default').account_get(cursor, user, move_line.product_id.id, partner_id , user, time.strftime('%Y-%m-%d'), context={})
+ rec = self.pool.get('account.analytic.default').account_get(cursor, user, move_line.product_id.id, partner_id, user, time.strftime('%Y-%m-%d'))
if rec:
return rec.analytic_id.id
diff --git a/addons/account_analytic_plans/account_analytic_plans.py b/addons/account_analytic_plans/account_analytic_plans.py
index 23a309c1dda..aa9844105e6 100644
--- a/addons/account_analytic_plans/account_analytic_plans.py
+++ b/addons/account_analytic_plans/account_analytic_plans.py
@@ -81,7 +81,7 @@ class account_analytic_plan_line(osv.osv):
_order = "sequence, id"
_columns = {
'plan_id': fields.many2one('account.analytic.plan','Analytic Plan',required=True),
- 'name': fields.char('Plan Name', size=64, required=True, select=True),
+ 'name': fields.char('Axis Name', size=64, required=True, select=True),
'sequence': fields.integer('Sequence'),
'root_analytic_id': fields.many2one('account.analytic.account', 'Root Account', help="Root account of this plan.", required=False),
'min_required': fields.float('Minimum Allowed (%)'),
diff --git a/addons/hr/hr.py b/addons/hr/hr.py
index 5bb172eb082..85366adfe3b 100644
--- a/addons/hr/hr.py
+++ b/addons/hr/hr.py
@@ -349,10 +349,12 @@ class hr_employee(osv.osv):
else:
return super(hr_employee, self).get_suggested_thread(cr, uid, removed_suggested_threads, context)
- def _message_get_auto_subscribe_fields(self, cr, uid, updated_fields, auto_follow_fields=['user_id'], context=None):
+ def _message_get_auto_subscribe_fields(self, cr, uid, updated_fields, auto_follow_fields=None, context=None):
""" Overwrite of the original method to always follow user_id field,
even when not track_visibility so that a user will follow it's employee
"""
+ if auto_follow_fields is None:
+ auto_follow_fields = ['user_id']
user_field_lst = []
for name, column_info in self._all_columns.items():
if name in auto_follow_fields and name in updated_fields and column_info.column._obj == 'res.users':
diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py
index 55a566880b8..dc2b98fdc93 100644
--- a/addons/mail/mail_thread.py
+++ b/addons/mail/mail_thread.py
@@ -1699,7 +1699,7 @@ class mail_thread(osv.AbstractModel):
], context=context)
return fol_obj.unlink(cr, SUPERUSER_ID, fol_ids, context=context)
- def _message_get_auto_subscribe_fields(self, cr, uid, updated_fields, auto_follow_fields=['user_id'], context=None):
+ def _message_get_auto_subscribe_fields(self, cr, uid, updated_fields, auto_follow_fields=None, context=None):
""" Returns the list of relational fields linking to res.users that should
trigger an auto subscribe. The default list checks for the fields
- called 'user_id'
@@ -1710,6 +1710,8 @@ class mail_thread(osv.AbstractModel):
Override this method if a custom behavior is needed about fields
that automatically subscribe users.
"""
+ if auto_follow_fields is None:
+ auto_follow_fields = ['user_id']
user_field_lst = []
for name, column_info in self._all_columns.items():
if name in auto_follow_fields and name in updated_fields and getattr(column_info.column, 'track_visibility', False) and column_info.column._obj == 'res.users':
diff --git a/addons/project/project.py b/addons/project/project.py
index d98b9b03e94..a9c487be244 100644
--- a/addons/project/project.py
+++ b/addons/project/project.py
@@ -782,6 +782,7 @@ class task(osv.osv):
'project.task': (lambda self, cr, uid, ids, c={}: ids, ['work_ids', 'remaining_hours', 'planned_hours'], 10),
'project.task.work': (_get_task, ['hours'], 10),
}),
+ 'reviewer_id': fields.many2one('res.users', 'Reviewer', select=True, track_visibility='onchange'),
'user_id': fields.many2one('res.users', 'Assigned to', select=True, track_visibility='onchange'),
'delegated_user_id': fields.related('child_ids', 'user_id', type='many2one', relation='res.users', string='Delegated To'),
'partner_id': fields.many2one('res.partner', 'Customer'),
@@ -801,6 +802,7 @@ class task(osv.osv):
'progress': 0,
'sequence': 10,
'active': True,
+ 'reviewer_id': lambda obj, cr, uid, ctx=None: uid,
'user_id': lambda obj, cr, uid, ctx=None: uid,
'company_id': lambda self, cr, uid, ctx=None: self.pool.get('res.company')._company_default_get(cr, uid, 'project.task', context=ctx),
'partner_id': lambda self, cr, uid, ctx=None: self._get_default_partner(cr, uid, context=ctx),
@@ -1090,6 +1092,11 @@ class task(osv.osv):
# Mail gateway
# ---------------------------------------------------
+ def _message_get_auto_subscribe_fields(self, cr, uid, updated_fields, auto_follow_fields=None, context=None):
+ if auto_follow_fields is None:
+ auto_follow_fields = ['user_id', 'reviewer_id']
+ return super(task, self)._message_get_auto_subscribe_fields(cr, uid, updated_fields, auto_follow_fields, context=context)
+
def message_get_reply_to(self, cr, uid, ids, context=None):
""" Override to get the reply_to of the parent project. """
return [task.project_id.message_get_reply_to()[0] if task.project_id else False
diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml
index fc6ffe647bb..9bbd078ac68 100644
--- a/addons/project/project_view.xml
+++ b/addons/project/project_view.xml
@@ -29,9 +29,11 @@
help="Show only tasks having a deadline"/>
+
+
@@ -389,6 +391,9 @@
+
diff --git a/addons/website/static/src/js/website.editor.newpage.js b/addons/website/static/src/js/website.editor.newpage.js
index 5fa5df7a750..eba3784a42f 100644
--- a/addons/website/static/src/js/website.editor.newpage.js
+++ b/addons/website/static/src/js/website.editor.newpage.js
@@ -47,7 +47,7 @@
}
}).then(function (val, field, $dialog) {
if (val) {
- var url = '/website/add/' + encodeURI(val);
+ var url = '/website/add/' + encodeURIComponent(val);
if ($dialog.find('input[type="checkbox"]').is(':checked')) url +="?add_menu=1";
document.location = url;
}
diff --git a/openerp/addons/base/ir/ir_model_view.xml b/openerp/addons/base/ir/ir_model_view.xml
index ea5cf0f479f..c5266587a21 100644
--- a/openerp/addons/base/ir/ir_model_view.xml
+++ b/openerp/addons/base/ir/ir_model_view.xml
@@ -214,6 +214,13 @@
string="Readonly"
domain="[('readonly', '=', True)]"/>
+
+
+
diff --git a/openerp/modules/graph.py b/openerp/modules/graph.py
index 74f4e0db9ce..76a9f046dc6 100644
--- a/openerp/modules/graph.py
+++ b/openerp/modules/graph.py
@@ -3,7 +3,7 @@
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL ().
-# Copyright (C) 2010-2011 OpenERP s.a. ().
+# Copyright (C) 2010-2014 OpenERP s.a. ().
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@@ -149,7 +149,14 @@ class Graph(dict):
level += 1
-class Singleton(object):
+class Node(object):
+ """ One module in the modules dependency graph.
+
+ Node acts as a per-module singleton. A node is constructed via
+ Graph.add_module() or Graph.add_modules(). Some of its fields are from
+ ir_module_module (setted by Graph.update_from_db()).
+
+ """
def __new__(cls, name, graph, info):
if name in graph:
inst = graph[name]
@@ -160,22 +167,13 @@ class Singleton(object):
graph[name] = inst
return inst
-
-class Node(Singleton):
- """ One module in the modules dependency graph.
-
- Node acts as a per-module singleton. A node is constructed via
- Graph.add_module() or Graph.add_modules(). Some of its fields are from
- ir_module_module (setted by Graph.update_from_db()).
-
- """
-
def __init__(self, name, graph, info):
self.graph = graph
if not hasattr(self, 'children'):
self.children = []
if not hasattr(self, 'depth'):
self.depth = 0
+ self.info = info or {}
def add_child(self, name, info):
node = Node(name, self.graph, info)
@@ -189,7 +187,7 @@ class Node(Singleton):
return node
def __setattr__(self, name, value):
- super(Singleton, self).__setattr__(name, value)
+ super(Node, self).__setattr__(name, value)
if name in ('init', 'update', 'demo'):
tools.config[name][self.name] = 1
for child in self.children:
diff --git a/openerp/modules/loading.py b/openerp/modules/loading.py
index 2b507acc0bb..2b9fca6fca9 100644
--- a/openerp/modules/loading.py
+++ b/openerp/modules/loading.py
@@ -148,6 +148,13 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, skip_modules=
migrations.migrate_module(package, 'pre')
load_openerp_module(package.name)
+ new_install = package.installed_version is None
+ if new_install:
+ py_module = sys.modules['openerp.addons.%s' % (module_name,)]
+ pre_init = package.info.get('pre_init_hook')
+ if pre_init:
+ getattr(py_module, pre_init)(cr)
+
models = registry.load(cr, package)
loaded_modules.append(package.name)
@@ -181,6 +188,11 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, skip_modules=
migrations.migrate_module(package, 'post')
+ if new_install:
+ post_init = package.info.get('post_init_hook')
+ if post_init:
+ getattr(py_module, post_init)(cr, registry)
+
registry._init_modules.add(package.name)
# validate all the views at a whole
registry['ir.ui.view']._validate_module_views(cr, SUPERUSER_ID, module_name)
@@ -401,10 +413,17 @@ def load_modules(db, force_demo=False, status=None, update_module=False):
if update_module:
# Remove records referenced from ir_model_data for modules to be
# removed (and removed the references from ir_model_data).
- cr.execute("SELECT id FROM ir_module_module WHERE state=%s", ('to remove',))
- mod_ids_to_remove = [x[0] for x in cr.fetchall()]
- if mod_ids_to_remove:
- registry['ir.module.module'].module_uninstall(cr, SUPERUSER_ID, mod_ids_to_remove)
+ cr.execute("SELECT name, id FROM ir_module_module WHERE state=%s", ('to remove',))
+ modules_to_remove = dict(cr.fetchall())
+ if modules_to_remove:
+ pkgs = reversed([p for p in graph if p.name in modules_to_remove])
+ for pkg in pkgs:
+ uninstall_hook = pkg.info.get('uninstall_hook')
+ if uninstall_hook:
+ py_module = sys.modules['openerp.addons.%s' % (pkg.name,)]
+ getattr(py_module, uninstall_hook)(cr, registry)
+
+ registry['ir.module.module'].module_uninstall(cr, SUPERUSER_ID, modules_to_remove.values())
# Recursive reload, should only happen once, because there should be no
# modules to remove next time
cr.commit()