From 5b2852e44286719be48483cc253539d8446b3667 Mon Sep 17 00:00:00 2001 From: Christophe Chauvet Date: Mon, 7 Dec 2009 11:37:06 +0100 Subject: [PATCH 001/157] [IMP] Disallow connection to PostgreSQL with postgres user himself (security flaws) bzr revid: christophe.chauvet@syleam.fr-20091207103706-vp3sc1gydbjtqmzg --- bin/openerp-server.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/bin/openerp-server.py b/bin/openerp-server.py index 33b5fef9aeb..2d445070011 100755 --- a/bin/openerp-server.py +++ b/bin/openerp-server.py @@ -70,6 +70,12 @@ logger = netsvc.Logger() #----------------------------------------------------------------------- import tools +# Check if the connection to PostgreSQL don't use postgres user +if tools.config['db_user'] == 'postgres': + sys.stderr.write("Attempted to connected database with postgres user." \ + " This is a security flaws, aborting.\n") + sys.exit(1) + logger.notifyChannel("server", netsvc.LOG_INFO, "version - %s" % release.version ) for name, value in [('addons_path', tools.config['addons_path']), ('database hostname', tools.config['db_host'] or 'localhost'), From 9bd2e38eafdf37e87bc9327e4d01363361c44f31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Valyi?= Date: Mon, 1 Mar 2010 00:55:24 -0300 Subject: [PATCH 002/157] [REF] removed mx.DateTime unused import as well as 2 other unused imports (!!) bzr revid: rvalyi@gmail.com-20100301035524-4nejbvju86c1wwvb --- addons/hr/hr.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/addons/hr/hr.py b/addons/hr/hr.py index 475185aa10e..a4a36d0e052 100755 --- a/addons/hr/hr.py +++ b/addons/hr/hr.py @@ -19,10 +19,6 @@ # ############################################################################## -from mx import DateTime -import time -import math - from osv import fields, osv from tools.translate import _ From b04e0c64d1d48c4219774912d3b03c87637f49dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Valyi?= Date: Mon, 1 Mar 2010 01:00:47 -0300 Subject: [PATCH 003/157] [REF] [account] removed unused mx.DateTime imports bzr revid: rvalyi@gmail.com-20100301040047-3p41ik9rzhq5luoz --- addons/account/report/general_ledger.py | 1 - addons/account/report/general_ledger_landscape.py | 1 - 2 files changed, 2 deletions(-) diff --git a/addons/account/report/general_ledger.py b/addons/account/report/general_ledger.py index 43c298866ed..b06aa1198fc 100644 --- a/addons/account/report/general_ledger.py +++ b/addons/account/report/general_ledger.py @@ -25,7 +25,6 @@ # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. import time -from mx.DateTime import * from report import report_sxw import xml import rml_parse diff --git a/addons/account/report/general_ledger_landscape.py b/addons/account/report/general_ledger_landscape.py index dcb4e47fbdd..c888994622b 100644 --- a/addons/account/report/general_ledger_landscape.py +++ b/addons/account/report/general_ledger_landscape.py @@ -27,7 +27,6 @@ ############################################################################## import time -from mx.DateTime import * from report import report_sxw import xml import rml_parse From a421e021ed7aa289c217dbb7cb14202b6c0dd43d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Valyi?= Date: Mon, 1 Mar 2010 01:09:24 -0300 Subject: [PATCH 004/157] [REF] [account] removed unused mx.DateTime imports bzr revid: rvalyi@gmail.com-20100301040924-b8wxwhmvopxas6v7 --- addons/account/invoice.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/addons/account/invoice.py b/addons/account/invoice.py index 96f3a0afb40..ae9428f19db 100644 --- a/addons/account/invoice.py +++ b/addons/account/invoice.py @@ -24,8 +24,6 @@ import netsvc from osv import fields, osv import ir import pooler -import mx.DateTime -from mx.DateTime import RelativeDateTime from tools import config from tools.translate import _ From b8d17ac8044fe2cfca00530d61966960525102c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Valyi?= Date: Mon, 1 Mar 2010 01:36:05 -0300 Subject: [PATCH 005/157] [REF] [account] replaced mx.DateTime usage by pure Python datime and dateutil bzr revid: rvalyi@gmail.com-20100301043605-35lca2eqgk774jgh --- addons/account/account.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/addons/account/account.py b/addons/account/account.py index 516c185b652..8134c6d0c30 100644 --- a/addons/account/account.py +++ b/addons/account/account.py @@ -27,8 +27,8 @@ from osv import fields, osv from tools.misc import currency from tools.translate import _ import pooler -import mx.DateTime -from mx.DateTime import RelativeDateTime, now, DateTime, localtime +from datetime import datetime +from dateutil.relativedelta import relativedelta from tools import config @@ -60,11 +60,11 @@ class account_payment_term(osv.osv): elif line.value == 'balance': amt = round(amount, int(config['price_accuracy'])) if amt: - next_date = mx.DateTime.strptime(date_ref, '%Y-%m-%d') + RelativeDateTime(days=line.days) + next_date = datetime.strptime(date_ref, '%y-%m-%d') + relativedelta(days=line.days) if line.days2 < 0: - next_date += RelativeDateTime(day=line.days2) + next_date += relativedelta(day=line.days2) if line.days2 > 0: - next_date += RelativeDateTime(day=line.days2, months=1) + next_date += relativedelta(day=line.days2, months=1) result.append( (next_date.strftime('%Y-%m-%d'), amt) ) amount -= amt return result @@ -582,12 +582,12 @@ class account_fiscalyear(osv.osv): def create_period(self,cr, uid, ids, context={}, interval=1): for fy in self.browse(cr, uid, ids, context): - ds = mx.DateTime.strptime(fy.date_start, '%Y-%m-%d') + ds = datetime.strptime(fy.date_start, '%Y-%m-%d') while ds.strftime('%Y-%m-%d')fy.date_stop: - de=mx.DateTime.strptime(fy.date_stop, '%Y-%m-%d') + de = datetime.strptime(fy.date_stop, '%Y-%m-%d') self.pool.get('account.period').create(cr, uid, { 'name': ds.strftime('%m/%Y'), @@ -596,7 +596,7 @@ class account_fiscalyear(osv.osv): 'date_stop': de.strftime('%Y-%m-%d'), 'fiscalyear_id': fy.id, }) - ds = ds + RelativeDateTime(months=interval) + ds = ds + relativedelta(months=interval) return True def find(self, cr, uid, dt=None, exception=True, context={}): @@ -1720,11 +1720,11 @@ class account_subscription(osv.osv): 'subscription_id': sub.id, }) if sub.period_type=='day': - ds = (mx.DateTime.strptime(ds, '%Y-%m-%d') + RelativeDateTime(days=sub.period_nbr)).strftime('%Y-%m-%d') + ds = (datetime.strptime(ds, '%Y-%m-%d') + relativedelta(days=sub.period_nbr)).strftime('%Y-%m-%d') if sub.period_type=='month': - ds = (mx.DateTime.strptime(ds, '%Y-%m-%d') + RelativeDateTime(months=sub.period_nbr)).strftime('%Y-%m-%d') + ds = (datetime.strptime(ds, '%Y-%m-%d') + relativedelta(months=sub.period_nbr)).strftime('%Y-%m-%d') if sub.period_type=='year': - ds = (mx.DateTime.strptime(ds, '%Y-%m-%d') + RelativeDateTime(years=sub.period_nbr)).strftime('%Y-%m-%d') + ds = (datetime.strptime(ds, '%Y-%m-%d') + relativedelta(years=sub.period_nbr)).strftime('%Y-%m-%d') self.write(cr, uid, ids, {'state':'running'}) return True account_subscription() From bb84484882f15ca7ea2b452d61505d1914c68be2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Valyi?= Date: Mon, 1 Mar 2010 01:53:16 -0300 Subject: [PATCH 006/157] [REF] [account] further mx.DateTime cleanup bzr revid: rvalyi@gmail.com-20100301045316-mw67ahn1epe4lknq --- addons/account/account_move_line.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/addons/account/account_move_line.py b/addons/account/account_move_line.py index 8355cf6be3c..ba44f413410 100644 --- a/addons/account/account_move_line.py +++ b/addons/account/account_move_line.py @@ -24,8 +24,7 @@ import netsvc from osv import fields, osv from tools.translate import _ -import mx.DateTime -from mx.DateTime import RelativeDateTime, now, DateTime, localtime +from datetime import now import tools From fca1d230e4a87630b05cd704e0e077b8342b4b85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Valyi?= Date: Mon, 1 Mar 2010 01:54:48 -0300 Subject: [PATCH 007/157] [REF] [account] removed unused mx.DateTime imports bzr revid: rvalyi@gmail.com-20100301045448-6c7j5ck2gtkc6u09 --- addons/account/account_bank_statement.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/addons/account/account_bank_statement.py b/addons/account/account_bank_statement.py index 01c1eb7fa37..e0a316ae2a1 100644 --- a/addons/account/account_bank_statement.py +++ b/addons/account/account_bank_statement.py @@ -26,10 +26,6 @@ from osv import fields, osv from tools.misc import currency from tools.translate import _ -import mx.DateTime -from mx.DateTime import RelativeDateTime, now, DateTime, localtime - - class account_bank_statement(osv.osv): def _default_journal_id(self, cr, uid, context={}): if context.get('journal_id', False): From 45edbf48b9626834469adc91f28d3e6bc12169c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Valyi?= Date: Mon, 1 Mar 2010 02:05:14 -0300 Subject: [PATCH 008/157] [REF] [stock] removed mx.DateTime from stock module bzr revid: rvalyi@gmail.com-20100301050514-0dq2xgpypxw52hbj --- addons/stock/report/product_stock.py | 7 ++++--- addons/stock/report/stock_graph.py | 1 - addons/stock/stock.py | 10 ++++++---- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/addons/stock/report/product_stock.py b/addons/stock/report/product_stock.py index 49c1daef8ed..f9a61a8989a 100644 --- a/addons/stock/report/product_stock.py +++ b/addons/stock/report/product_stock.py @@ -19,7 +19,8 @@ # ############################################################################## -from mx import DateTime +from datetime import datetime +from dateutil.relativedelta import relativedelta import osv import time @@ -76,7 +77,7 @@ class report_stock(report_int): "group by date_planned,product_id",(('confirmed','assigned','waiting'),loc_ids ,product_ids,)) for (qty, dt, prod_id) in cr.fetchall(): if dt<=dt_from: - dt= (DateTime.now() + DateTime.RelativeDateTime(days=1)).strftime('%Y-%m-%d') + dt= (datetime.now() + relativedelta(days=1)).strftime('%Y-%m-%d') else: dt = dt[:10] products.setdefault(prod_id, []) @@ -91,7 +92,7 @@ class report_stock(report_int): for (qty, dt, prod_id) in cr.fetchall(): if dt<=dt_from: - dt= (DateTime.now() + DateTime.RelativeDateTime(days=1)).strftime('%Y-%m-%d') + dt= (datetime.now() + relativedelta(days=1)).strftime('%Y-%m-%d') else: dt = dt[:10] products.setdefault(prod_id, []) diff --git a/addons/stock/report/stock_graph.py b/addons/stock/report/stock_graph.py index 0fdf88da7ce..d20baa08d58 100644 --- a/addons/stock/report/stock_graph.py +++ b/addons/stock/report/stock_graph.py @@ -18,7 +18,6 @@ # along with this program. If not, see . # ############################################################################## -from mx.DateTime import * from pychart import * import pychart.legend import time diff --git a/addons/stock/stock.py b/addons/stock/stock.py index 240bc9762ce..6cf6d5901c3 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -19,7 +19,9 @@ # ############################################################################## -from mx import DateTime +from datetime import datetime +from dateutil.relativedelta import relativedelta + from osv import fields, osv from tools import config from tools.translate import _ @@ -1169,8 +1171,8 @@ class stock_move(osv.osv): if dest: if dest[1] == 'transparent': self.write(cr, uid, [m.id], { - 'date_planned': (DateTime.strptime(m.date_planned, '%Y-%m-%d %H:%M:%S') + \ - DateTime.RelativeDateTime(days=dest[2] or 0)).strftime('%Y-%m-%d'), + 'date_planned': (datetime.strptime(m.date_planned, '%Y-%m-%d %H:%M:%S') + \ + relativedelta(days=dest[2] or 0)).strftime('%Y-%m-%d'), 'location_dest_id': dest[0].id}) else: result.setdefault(m.picking_id, []) @@ -1206,7 +1208,7 @@ class stock_move(osv.osv): 'picking_id': pickid, 'state': 'waiting', 'move_history_ids': [], - 'date_planned': (DateTime.strptime(move.date_planned, '%Y-%m-%d %H:%M:%S') + DateTime.RelativeDateTime(days=delay or 0)).strftime('%Y-%m-%d'), + 'date_planned': (datetime.strptime(move.date_planned, '%Y-%m-%d %H:%M:%S') + relativedelta(days=delay or 0)).strftime('%Y-%m-%d'), 'move_history_ids2': []} ) self.pool.get('stock.move').write(cr, uid, [move.id], { From caef744e048f8b6562282bce6f9549de751c42a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Valyi?= Date: Mon, 1 Mar 2010 02:09:11 -0300 Subject: [PATCH 009/157] [REF] [sale] removed mx.DateTime usage from sale module bzr revid: rvalyi@gmail.com-20100301050911-sqnifbigc455bylm --- addons/sale/sale.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/addons/sale/sale.py b/addons/sale/sale.py index a9d0935fc76..f3997e6334d 100644 --- a/addons/sale/sale.py +++ b/addons/sale/sale.py @@ -22,7 +22,8 @@ import time import netsvc from osv import fields, osv -from mx import DateTime +from datetime import datetime, now +from dateutil.relativedelta import relativedelta from tools import config from tools.translate import _ @@ -581,8 +582,8 @@ class sale_order(osv.osv): picking_id = False for line in order.order_line: proc_id = False - date_planned = DateTime.now() + DateTime.DateTimeDeltaFromDays(line.delay or 0.0) - date_planned = (date_planned - DateTime.DateTimeDeltaFromDays(company.security_lead)).strftime('%Y-%m-%d %H:%M:%S') + date_planned = datetime.now() + relativedelta(days=line.delay or 0.0) + date_planned = (date_planned - relativedelta(company.security_lead)).strftime('%Y-%m-%d %H:%M:%S') if line.state == 'done': continue if line.product_id and line.product_id.product_tmpl_id.type in ('product', 'consu'): From 325ba204715bb1e8e2a729d45ccbe7f0df3a132d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Valyi?= Date: Mon, 1 Mar 2010 02:13:20 -0300 Subject: [PATCH 010/157] [REF] [purchase] removed mx.DateTime usage from purchase module bzr revid: rvalyi@gmail.com-20100301051320-j20t2m079zh49rrx --- addons/purchase/purchase.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index 1d7745a82f7..581c055db7c 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -25,7 +25,8 @@ import time import netsvc import ir -from mx import DateTime +from datetime import datetime +from dateutil.relativedelta import relativedelta import pooler from tools import config from tools.translate import _ @@ -518,7 +519,7 @@ class purchase_order_line(osv.osv): 'uom': uom, 'date': date_order, })[pricelist] - dt = (DateTime.now() + DateTime.RelativeDateTime(days=seller_delay or 0.0)).strftime('%Y-%m-%d %H:%M:%S') + dt = (datetime.now() + relativedelta(days=seller_delay or 0.0)).strftime('%Y-%m-%d %H:%M:%S') prod_name = self.pool.get('product.product').name_get(cr, uid, [prod.id])[0][1] From 42f1ff14d1a9c10b183a35e250042e1f481e4300 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Valyi?= Date: Mon, 1 Mar 2010 02:16:51 -0300 Subject: [PATCH 011/157] [REF] fixed datetime now() method call in account and sale modules bzr revid: rvalyi@gmail.com-20100301051651-2gdc7tn8ljyi5vz9 --- addons/account/account.py | 2 +- addons/account/account_move_line.py | 4 ++-- addons/sale/sale.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/addons/account/account.py b/addons/account/account.py index 8134c6d0c30..7fbab48d436 100644 --- a/addons/account/account.py +++ b/addons/account/account.py @@ -48,7 +48,7 @@ class account_payment_term(osv.osv): def compute(self, cr, uid, id, value, date_ref=False, context={}): if not date_ref: - date_ref = now().strftime('%Y-%m-%d') + date_ref = datetime.now().strftime('%Y-%m-%d') pt = self.browse(cr, uid, id, context) amount = value result = [] diff --git a/addons/account/account_move_line.py b/addons/account/account_move_line.py index ba44f413410..15c2c93b8fb 100644 --- a/addons/account/account_move_line.py +++ b/addons/account/account_move_line.py @@ -24,7 +24,7 @@ import netsvc from osv import fields, osv from tools.translate import _ -from datetime import now +from datetime import datetime import tools @@ -484,7 +484,7 @@ class account_move_line(osv.osv): if not partner_id: return {'value':val} if not date: - date = now().strftime('%Y-%m-%d') + date = datetime.now().strftime('%Y-%m-%d') part = self.pool.get('res.partner').browse(cr, uid, partner_id) if part.property_payment_term and part.property_payment_term.line_ids: diff --git a/addons/sale/sale.py b/addons/sale/sale.py index f3997e6334d..60e5b39a183 100644 --- a/addons/sale/sale.py +++ b/addons/sale/sale.py @@ -22,7 +22,7 @@ import time import netsvc from osv import fields, osv -from datetime import datetime, now +from datetime import datetime from dateutil.relativedelta import relativedelta from tools import config from tools.translate import _ From 858db998cab6f020dcc87d6901eea1f5944d6ed1 Mon Sep 17 00:00:00 2001 From: Julien Thewys Date: Thu, 4 Mar 2010 10:44:58 +0100 Subject: [PATCH 012/157] [IMP] yaml test: init bzr revid: jth@openerp.com-20100304094458-rypj37e94wo2oedi --- bin/addons/__init__.py | 2 + bin/netsvc.py | 12 +- bin/tools/__init__.py | 1 + bin/tools/yaml_test.py | 406 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 418 insertions(+), 3 deletions(-) create mode 100644 bin/tools/yaml_test.py diff --git a/bin/addons/__init__.py b/bin/addons/__init__.py index 2910b9fe7c1..ebf0c2fcd05 100644 --- a/bin/addons/__init__.py +++ b/bin/addons/__init__.py @@ -644,6 +644,8 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, **kwargs): new_query = ' '.join(query.split()) if new_query: cr.execute(new_query) + elif ext == '.yaml': + tools.convert_yaml_import(cr, m, fp, idref, mode=mode, **kwargs) else: tools.convert_xml_import(cr, m, fp, idref, mode=mode, **kwargs) fp.close() diff --git a/bin/netsvc.py b/bin/netsvc.py index d8548db5d6a..eae53826a74 100644 --- a/bin/netsvc.py +++ b/bin/netsvc.py @@ -127,6 +127,7 @@ class ExportService(object): LOG_NOTSET = 'notset' LOG_DEBUG_RPC = 'debug_rpc' LOG_DEBUG = 'debug' +LOG_TEST = 'test' LOG_INFO = 'info' LOG_WARNING = 'warn' LOG_ERROR = 'error' @@ -135,6 +136,9 @@ LOG_CRITICAL = 'critical' logging.DEBUG_RPC = logging.DEBUG - 2 logging.addLevelName(logging.DEBUG_RPC, 'DEBUG_RPC') +logging.TEST = logging.INFO - 5 +logging.addLevelName(logging.TEST, 'TEST') + def init_logger(): import os from tools.translate import resetlocale @@ -195,6 +199,7 @@ def init_logger(): 'DEBUG_RPC': ('blue', 'white'), 'DEBUG': ('blue', 'default'), 'INFO': ('green', 'default'), + 'TEST': ('white', 'blue'), 'WARNING': ('yellow', 'default'), 'ERROR': ('red', 'default'), 'CRITICAL': ('white', 'red'), @@ -220,9 +225,10 @@ class Logger(object): log = logging.getLogger(tools.ustr(name)) - if level == LOG_DEBUG_RPC and not hasattr(log, level): - fct = lambda msg, *args, **kwargs: log.log(logging.DEBUG_RPC, msg, *args, **kwargs) - setattr(log, LOG_DEBUG_RPC, fct) + if level in [LOG_DEBUG_RPC, LOG_TEST] and not hasattr(log, level): + fct = lambda msg, *args, **kwargs: log.log(getattr(logging, level.upper()), msg, *args, **kwargs) + setattr(log, level, fct) + level_method = getattr(log, level) diff --git a/bin/tools/__init__.py b/bin/tools/__init__.py index 9b7bb84a57f..78c77edf394 100644 --- a/bin/tools/__init__.py +++ b/bin/tools/__init__.py @@ -24,6 +24,7 @@ import win32 from config import * from misc import * from convert import * +from yaml_test import * from translate import * from graph import graph from amount_to_text import * diff --git a/bin/tools/yaml_test.py b/bin/tools/yaml_test.py new file mode 100644 index 00000000000..52ce059a5fd --- /dev/null +++ b/bin/tools/yaml_test.py @@ -0,0 +1,406 @@ +# -*- encoding: utf-8 -*- +import types +import yaml +import time # used to eval time.strftime expressions +import logging + +import pooler +import netsvc + +from config import config + +logger_channel = 'tests' + +class YamlImportException(Exception): + pass + +class YamlImportAbortion(Exception): + pass + +class YamlTag(object): + """Superclass for constructors of custom tags defined in yaml file.""" + + def __init__(self, **kwargs): + self.__dict__.update(kwargs) + def __getitem__(self, key): + return getattr(self, key) + def __getattr__(self, attr): + return None + def __repr__(self): + return "<%s %s>" % (self.__class__.__name__, sorted(self.__dict__.items())) + +class Assert(YamlTag): + def __init__(self, model, id, severity=netsvc.LOG_ERROR, string="NONAME", **kwargs): + self.model = model + self.id = id + self.severity = severity + self.string = string + super(Assert, self).__init__(**kwargs) + +class Record(YamlTag): + def __init__(self, model, id, **kwargs): + self.model = model + self.id = id + super(Record, self).__init__(**kwargs) + +class Python(YamlTag): + def __init__(self, model, severity=netsvc.LOG_ERROR, name="NONAME", **kwargs): + self.model= model + self.severity = severity + self.name = name + super(Python, self).__init__(**kwargs) + +class Workflow(YamlTag): + def __init__(self, model, action, **kwargs): + self.model = model + self.action = action + super(Workflow, self).__init__(**kwargs) + +class Context(YamlTag): + def __init__(self, **kwargs): + super(Context, self).__init__(**kwargs) + +class Eval(YamlTag): + def __init__(self, expression): + self.expression = expression + super(Eval, self).__init__() + +class Ref(YamlTag): + def __init__(self, xmlid): + self.xmlid = xmlid + super(Ref, self).__init__() + +def assert_constructor(loader, node): + kwargs = loader.construct_mapping(node) + return Assert(**kwargs) + +def record_constructor(loader, node): + kwargs = loader.construct_mapping(node) + return Record(**kwargs) + +def python_constructor(loader, node): + kwargs = loader.construct_mapping(node) + return Python(**kwargs) + +def workflow_constructor(loader, node): + kwargs = loader.construct_mapping(node) + return Workflow(**kwargs) + +def context_constructor(loader, node): + kwargs = loader.construct_mapping(node) + return Context(**kwargs) + +def eval_constructor(loader, node): + expression = loader.construct_scalar(node) + return Eval(expression) + +def ref_constructor(loader, node): + xmlid = loader.construct_scalar(node) + return Ref(xmlid) + +yaml.add_constructor(u"!assert", assert_constructor) +yaml.add_constructor(u"!record", record_constructor) +yaml.add_constructor(u"!python", python_constructor) +yaml.add_constructor(u"!workflow", workflow_constructor) +yaml.add_constructor(u"!context", context_constructor) +yaml.add_constructor(u"!eval", eval_constructor) +yaml.add_constructor(u"!ref", ref_constructor) + +def _is_yaml_mapping(node, tag_constructor): + value = isinstance(node, types.DictionaryType) \ + and len(node.keys()) == 1 \ + and isinstance(node.keys()[0], tag_constructor) + return value + +def is_comment(node): + return isinstance(node, types.StringTypes) + +def is_assert(node): + return _is_yaml_mapping(node, Assert) + +def is_record(node): + return _is_yaml_mapping(node, Record) + +def is_python(node): + return _is_yaml_mapping(node, Python) + +def is_workflow(node): + return isinstance(node, Workflow) \ + or _is_yaml_mapping(node, Workflow) + +def is_context(node): + return isinstance(node, Context) + +def is_eval(node): + return isinstance(node, Eval) + +def is_ref(node): + return isinstance(node, Ref) + + +class TestReport(object): + def __init__(self): + self._report = {} + + def record(self, success, severity): + """Records the result of an assertion for the failed/success count. + Returns success.""" + + if severity in self._report: + self._report[severity][success] += 1 + else: + self._report[severity] = {success: 1, not success: 0} + return success + + def __str__(self): + res = [] + res.append('\nAssertions report:\nLevel\tsuccess\tfailed') + success = failure = 0 + for severity in self._report: + res.append("%s\t%s\t%s" % (severity, self._report[severity][True], self._report[severity][False])) + success += self._report[severity][True] + failure += self._report[severity][False] + res.append("total\t%s\t%s" % (success, failure)) + res.append("end of report (%s assertion(s) checked)" % success + failure) + return "\n".join(res) + + +class YamlInterpreter(object): + def __init__(self, cr, module, id_map, mode, filename, noupdate=False): + self.cr = cr + self.module = module + self.id_map = id_map + self.mode = mode + self.filename = filename + self.assert_report = TestReport() + self.noupdate = noupdate + self.logger = netsvc.Logger() + self.pool = pooler.get_pool(cr.dbname) + self.uid = 1 + self.context = {} + + def _ref(self): + return lambda xml_id: self.get_id(xml_id) + + def get_model(self, model_name): + model = self.pool.get(model_name) + assert model, "The model %s does not exist." % (model_name,) + return model + + def validate_xml_id(self, xml_id): + id = xml_id + if '.' in xml_id: + module, id = xml_id.split('.', 1) + assert '.' not in id, "The ID reference '%s' must contains maximum one dot.\n" \ + "It is used to refer to other modules ID, in the form: module.record_id" \ + % (xml_id,) + if module != self.module: + module_count = self.pool.get('ir.module.module').search_count(self.cr, self.uid, \ + ['&', ('name', '=', module), ('state', 'in', ['installed'])]) + assert module_count == 1, """The ID "%s" refers to an uninstalled module""" % (xml_id,) + if len(id) > 64: # TODO where does 64 come from (DB is 128)? should be a constant or loaded form DB + self.logger.notifyChannel(logger_channel, netsvc.LOG_ERROR, 'id: %s is to long (max: 64)' % (id,)) + + def get_id(self, xml_id): + if isinstance(xml_id, types.IntType): + id = xml_id + elif xml_id in self.id_map: + id = self.id_map[xml_id] + else: + if '.' in xml_id: + module, xml_id = xml_id.split('.', 1) + else: + module = self.module + ir_id = self.pool.get('ir.model.data')._get_id(self.cr, self.uid, module, xml_id) + obj = self.pool.get('ir.model.data').read(self.cr, self.uid, ir_id, ['res_id']) + id = int(obj['res_id']) + self.id_map[xml_id] = id + return id + + def process_comment(self, node): + return node + + def _log_assert_failure(self, severity, msg, *args): + self.assert_report.record(False, severity) + self.logger.notifyChannel(logger_channel, severity, msg % (args)) + if getattr(logging, severity.upper()) >= config['assert_exit_level']: + raise YamlImportAbortion('Severe assertion failure (%s), aborting.' % (severity,)) + return + + def _get_assertion_id(self, assertion): + if assertion.id: + ids = [self.get_id(assertion.id)] + elif assertion.search: + q = eval(assertion.search, {'ref': self._ref}) + ids = self.pool.get(assertion.model).search(self.cr, self.uid, q, context=assertion.context) + if not ids: + raise YamlImportException('Nothing to assert: you must give either an id or a search criteria.') + return ids + + def process_assert(self, node): + assertion, expressions = node.items()[0] + + model = self.get_model(assertion.model) + ids = self._get_assertion_id(assertion) + if assertion.count and len(ids) != assertion.count: + msg = 'assertion "%s" failed!\n' \ + ' Incorrect search count:\n' \ + ' expected count: %d\n' \ + ' obtained count: %d\n' + args = (assertion.string, assertion.count, len(ids)) + self._log_assert_failure(assertion.severity, msg, *args) + else: + test_context = {'ref': self._ref, '_ref': self._ref} # added '_ref' so that record['ref'] is possible + for id in ids: + record = model.browse(self.cr, self.uid, id, assertion.context) + for test in expressions.get('test', ''): + success = eval(test, test_context, record) + if not success: + msg = 'Assertion "%s" FAILED\ntest: %s\n' + args = (assertion.string, test) + self._log_assert_failure(assertion.severity, msg, *args) + return + else: # all tests were successful for this assertion tag (no break) + self.assert_report.record(True, assertion.severity) + + def process_record(self, node): + record, fields = node.items()[0] + + self.validate_xml_id(record.id) + model = self.get_model(record.model) + record_dict = self._create_record(model, fields) + id = self.pool.get('ir.model.data')._update(self.cr, self.uid, record.model, \ + self.module, record_dict, record.id, mode=self.mode) + self.id_map[record.id] = int(id) + if config.get('import_partial', False): + self.cr.commit() + + def _create_record(self, model, fields): + record_dict = {} + for field_name, expression in fields.items(): + field_value = self._eval_field(model, field_name, expression) + record_dict[field_name] = field_value + return record_dict + + def _eval_field(self, model, field_name, expression): + column = model._columns[field_name] + if column._type == "many2one": + value = self.get_id(expression) + elif column._type == "one2many": + other_model = self.get_model(column._obj) + value = [(0, 0, self._create_record(other_model, fields)) for fields in expression] + elif column._type == "many2many": + ids = [self.get_id(xml_id) for xml_id in expression] + value= [(6, 0, ids)] + else: # scalar field + if isinstance(expression, Eval): + value = eval(expression.expression) + else: + value = expression + # raise YamlImportException('Unsupported column "%s" or value %s:%s' % (field_name, type(expression), expression)) + return value + + def process_context(self, node): + self.context = node.__dict__ + if 'uid' in node.__dict__: + self.uid = self.get_id(node.__dict__['uid']) + + def process_python(self, node): + def log(msg): + self.logger.notifyChannel(logger_channel, netsvc.LOG_TEST, msg) + python, statements = node.items()[0] + model = self.get_model(python.model) + statements = statements.replace("\r\n", "\n").replace("\n", ";") + code_context = {'self': model, 'cr': self.cr, 'uid': self.uid, 'log': log, 'context': self.context} + try: + code = compile(statements, self.filename, 'exec') + eval(code, code_context) + except Exception, e: + raise YamlImportException(e) + # TODO log success/failure + + def process_workflow(self, node): + workflow, values = node.items()[0] + model = self.get_model(workflow.model) + if workflow.ref: + id = self.get_id(workflow.ref) + else: + if not values: + raise YamlImportException('You must define a child node if you do not give a ref.') + if not len(values) == 1: + raise YamlImportException('Only one child node is accepted (%d given).' % len(values)) + value = values[0] + if not 'model' in value and not 'eval' in value: + raise YamlImportException('You must provide a model and an expression to evaluate for the workflow.') + value_model = self.get_model(value['model']) + local_context = {'ref': self._ref, '_ref': self._ref} + local_context['obj'] = lambda x: value_model.browse(self.cr, self.uid, x, context=self.context) + local_context.update(self.id_map) + id = eval(value['eval'], local_context) + + if workflow.uid is not None: + uid = workflow.uid + else: + uid = self.uid + wf_service = netsvc.LocalService("workflow") + wf_service.trg_validate(uid, model, id, workflow.action, self.cr) + + def process(self, yaml_string): + """Processes a Yaml string. Custom tags are interpreted by 'process_' instance methods.""" + + is_preceded_by_comment = False + for node in yaml.load(yaml_string): + is_preceded_by_comment = self._log(node, is_preceded_by_comment) + try: + self._process_node(node) + except YamlImportException, e: + self.logger.notifyChannel(logger_channel, netsvc.LOG_ERROR, e) + except YamlImportAbortion, e: + self.logger.notifyChannel(logger_channel, netsvc.LOG_ERROR, e) + return + + def _process_node(self, node): + if is_comment(node): + self.process_comment(node) + elif is_assert(node): + self.process_assert(node) + elif is_record(node): + self.process_record(node) + elif is_python(node): + self.process_python(node) + elif is_context(node): + self.process_context(node) + elif is_workflow(node): + if isinstance(node, types.DictionaryType): + self.process_workflow(node) + else: + self.process_workflow({node: []}) + else: + raise YamlImportException("Can not process YAML block: %s" % node) + + def _log(self, node, is_preceded_by_comment): + if is_comment(node): + is_preceded_by_comment = True + self.logger.notifyChannel(logger_channel, netsvc.LOG_TEST, node) + elif not is_preceded_by_comment: + if isinstance(node, types.DictionaryType): + k, v = node.items()[0] + msg = "Creating %s\n with %s" % (k, v) + self.logger.notifyChannel(logger_channel, netsvc.LOG_TEST, msg) + else: + self.logger.notifyChannel(logger_channel, netsvc.LOG_TEST, node) + else: + is_preceded_by_comment = False + return is_preceded_by_comment + +def yaml_import(cr, module, yamlfile, idref=None, mode='init', noupdate=False, report=None): + if idref is None: + idref = {} + yaml_string = yamlfile.read() + yaml_interpreter = YamlInterpreter(cr, module, idref, mode, filename=yamlfile.name, noupdate=noupdate) + yaml_interpreter.process(yaml_string) + +# keeps convention of convert.py +convert_yaml_import = yaml_import + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: From 52185a68e951a1e59525b20c7eff4d58a6111225 Mon Sep 17 00:00:00 2001 From: Julien Thewys Date: Thu, 4 Mar 2010 11:03:55 +0100 Subject: [PATCH 013/157] [FIX] YAML files have '.yml' extension, not '.yaml' bzr revid: jth@openerp.com-20100304100355-ay8z40i4rxriwaz4 --- bin/addons/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/addons/__init__.py b/bin/addons/__init__.py index ebf0c2fcd05..8137a7fecbb 100644 --- a/bin/addons/__init__.py +++ b/bin/addons/__init__.py @@ -644,7 +644,7 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, **kwargs): new_query = ' '.join(query.split()) if new_query: cr.execute(new_query) - elif ext == '.yaml': + elif ext == '.yml': tools.convert_yaml_import(cr, m, fp, idref, mode=mode, **kwargs) else: tools.convert_xml_import(cr, m, fp, idref, mode=mode, **kwargs) From 6d1a50b1ebe21b1760bf6cf9eb20044d5bebf57a Mon Sep 17 00:00:00 2001 From: Julien Thewys Date: Thu, 4 Mar 2010 16:41:59 +0100 Subject: [PATCH 014/157] [IMP] Record python block success in assertion report. bzr revid: jth@openerp.com-20100304154159-jlxcylq12qbezpoh --- bin/tools/yaml_test.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/bin/tools/yaml_test.py b/bin/tools/yaml_test.py index 52ce059a5fd..b91e457791e 100644 --- a/bin/tools/yaml_test.py +++ b/bin/tools/yaml_test.py @@ -315,9 +315,15 @@ class YamlInterpreter(object): try: code = compile(statements, self.filename, 'exec') eval(code, code_context) + except AssertionError, e: + msg = 'Assertion "%s" FAILED in Python code.' + args = (python.name,) + self._log_assert_failure(python.severity, msg, *args) + return except Exception, e: - raise YamlImportException(e) - # TODO log success/failure + raise YamlImportAbortion(e) + else: + self.assert_report.record(True, python.severity) def process_workflow(self, node): workflow, values = node.items()[0] From a974840afd4ce934150f277fa0f74b035e2f9c93 Mon Sep 17 00:00:00 2001 From: "sbh (Open ERP)" Date: Fri, 5 Mar 2010 11:03:51 +0530 Subject: [PATCH 015/157] [IMP] report_crm: set the default view tree in report bzr revid: sbh@tinyerp.com-20100305053351-0f3jb70roram90fo --- addons/report_crm/report_crm_claim_view.xml | 8 ++++---- addons/report_crm/report_crm_fundraising_view.xml | 8 ++++---- addons/report_crm/report_crm_lead_view.xml | 7 +++---- addons/report_crm/report_crm_opportunity_view.xml | 7 +++---- addons/report_crm/report_crm_phonecall_view.xml | 8 ++++---- 5 files changed, 18 insertions(+), 20 deletions(-) diff --git a/addons/report_crm/report_crm_claim_view.xml b/addons/report_crm/report_crm_claim_view.xml index 8232d72792b..1766eabb94f 100644 --- a/addons/report_crm/report_crm_claim_view.xml +++ b/addons/report_crm/report_crm_claim_view.xml @@ -66,21 +66,21 @@ Claims report.crm.claim form - graph,tree - + tree,graph + - + tree - + graph diff --git a/addons/report_crm/report_crm_fundraising_view.xml b/addons/report_crm/report_crm_fundraising_view.xml index 1bdba2fb4a4..dc188ef9956 100644 --- a/addons/report_crm/report_crm_fundraising_view.xml +++ b/addons/report_crm/report_crm_fundraising_view.xml @@ -69,21 +69,21 @@ Fundraising report.crm.fundraising form - graph,tree - + tree,graph + - + tree - + graph diff --git a/addons/report_crm/report_crm_lead_view.xml b/addons/report_crm/report_crm_lead_view.xml index 027238cc279..d5f4e63fd16 100644 --- a/addons/report_crm/report_crm_lead_view.xml +++ b/addons/report_crm/report_crm_lead_view.xml @@ -66,21 +66,20 @@ Leads report.crm.lead form - graph,tree - + tree,graph - + tree - + graph diff --git a/addons/report_crm/report_crm_opportunity_view.xml b/addons/report_crm/report_crm_opportunity_view.xml index b4f149d3cfe..f093d07940d 100644 --- a/addons/report_crm/report_crm_opportunity_view.xml +++ b/addons/report_crm/report_crm_opportunity_view.xml @@ -71,18 +71,17 @@ Opportunities report.crm.opportunity form - graph,tree - + tree,graph - + tree - + graph diff --git a/addons/report_crm/report_crm_phonecall_view.xml b/addons/report_crm/report_crm_phonecall_view.xml index b89570192ef..672f6fe101d 100644 --- a/addons/report_crm/report_crm_phonecall_view.xml +++ b/addons/report_crm/report_crm_phonecall_view.xml @@ -64,20 +64,20 @@ Phone Calls report.crm.phonecall form - graph,tree - + tree,graph + - + tree - + graph From 990552c684cfc7103da4e5e47d82f8df76448ffd Mon Sep 17 00:00:00 2001 From: "sbh (Open ERP)" Date: Fri, 5 Mar 2010 13:00:14 +0530 Subject: [PATCH 016/157] [IMP]report_crm: improve the view and set default in group by and filter bzr revid: sbh@tinyerp.com-20100305073014-vm9x4mjs9cfa2fes --- addons/report_crm/report_crm_opportunity.py | 6 ++++-- .../report_crm_opportunity_view.xml | 9 ++++++--- addons/report_crm/report_crm_view.xml | 19 +++++++------------ 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/addons/report_crm/report_crm_opportunity.py b/addons/report_crm/report_crm_opportunity.py index 1adfbf4baed..8ff49af0e71 100644 --- a/addons/report_crm/report_crm_opportunity.py +++ b/addons/report_crm/report_crm_opportunity.py @@ -12,7 +12,8 @@ class report_crm_opportunity(osv.osv): 'amount_revenue_prob': fields.float('Est. Rev*Prob.', readonly=True), 'delay_close': fields.char('Delay to close', size=20, readonly=True), 'categ_id': fields.many2one('crm.case.categ', 'Category', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.opportunity')]"), - 'stage_id':fields.many2one('crm.case.stage', 'Stage', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.opportunity')]", readonly=True), + 'stage_id':fields.many2one('crm.case.stage', 'Stage', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.opportunity')]", readonly=True), + 'partner_id': fields.many2one('res.partner', 'Partner'), } def init(self, cr): tools.drop_view_if_exists(cr, 'report_crm_opportunity') @@ -27,6 +28,7 @@ class report_crm_opportunity(osv.osv): c.section_id, c.categ_id, c.stage_id, + c.partner_id, count(*) as nbr, 0 as avg_answers, 0.0 as perc_done, @@ -37,7 +39,7 @@ class report_crm_opportunity(osv.osv): to_char(avg(date_closed-c.create_date), 'DD"d" HH24:MI:SS') as delay_close from crm_opportunity c - group by to_char(c.create_date, 'YYYY'), to_char(c.create_date, 'MM'), c.state, c.user_id,c.section_id,c.stage_id,c.categ_id + group by to_char(c.create_date, 'YYYY'), to_char(c.create_date, 'MM'), c.state, c.user_id,c.section_id,c.stage_id,c.categ_id,c.partner_id )""") report_crm_opportunity() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/report_crm/report_crm_opportunity_view.xml b/addons/report_crm/report_crm_opportunity_view.xml index f093d07940d..bd5e14edae6 100644 --- a/addons/report_crm/report_crm_opportunity_view.xml +++ b/addons/report_crm/report_crm_opportunity_view.xml @@ -13,14 +13,15 @@ + + - + + - - @@ -63,6 +64,8 @@ + + diff --git a/addons/report_crm/report_crm_view.xml b/addons/report_crm/report_crm_view.xml index b69ee89548b..8b88c7ef524 100644 --- a/addons/report_crm/report_crm_view.xml +++ b/addons/report_crm/report_crm_view.xml @@ -53,8 +53,8 @@ - - + + @@ -67,24 +67,19 @@ domain="[('section_id.user_id','=',uid)]" help="My section"/> - - - + - + + + + - - - From f9906e76dee6272793249c600c8a753f5d2cb21f Mon Sep 17 00:00:00 2001 From: Fabien Pinckaers Date: Fri, 5 Mar 2010 09:07:30 +0100 Subject: [PATCH 017/157] [IMP] crm views bzr revid: fp@tinyerp.com-20100305080730-rm54yomvsnrb6myc --- addons/crm/crm_meeting_view.xml | 41 ++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/addons/crm/crm_meeting_view.xml b/addons/crm/crm_meeting_view.xml index 561f3b3a63b..a1f1cef502e 100644 --- a/addons/crm/crm_meeting_view.xml +++ b/addons/crm/crm_meeting_view.xml @@ -90,25 +90,28 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + From c872a4a4460b1031d474d4bb80cf496d5bbe4be8 Mon Sep 17 00:00:00 2001 From: "sbh (Open ERP)" Date: Fri, 5 Mar 2010 13:49:49 +0530 Subject: [PATCH 018/157] [IMP] report_crm: Add the partner_id and section_id in all view bzr revid: sbh@tinyerp.com-20100305081949-pd9032ukqas9oa1h --- addons/report_crm/report_crm_claim.py | 6 ++++-- addons/report_crm/report_crm_claim_view.xml | 5 +++-- addons/report_crm/report_crm_fundraising.py | 4 +++- addons/report_crm/report_crm_fundraising_view.xml | 5 +++-- addons/report_crm/report_crm_lead.py | 4 +++- addons/report_crm/report_crm_lead_view.xml | 5 +++-- addons/report_crm/report_crm_opportunity_view.xml | 2 +- addons/report_crm/report_crm_phonecall.py | 4 +++- addons/report_crm/report_crm_phonecall_view.xml | 5 +++-- 9 files changed, 26 insertions(+), 14 deletions(-) diff --git a/addons/report_crm/report_crm_claim.py b/addons/report_crm/report_crm_claim.py index e78f2c8aa51..7f171849462 100644 --- a/addons/report_crm/report_crm_claim.py +++ b/addons/report_crm/report_crm_claim.py @@ -8,7 +8,8 @@ class report_crm_claim(osv.osv): _columns = { 'delay_close': fields.char('Delay to close', size=20, readonly=True), 'stage_id': fields.many2one ('crm.case.stage', 'Stage', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.claim')]", readonly=True), - 'categ_id': fields.many2one('crm.case.categ', 'Category', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.claim')]"), + 'categ_id': fields.many2one('crm.case.categ', 'Category', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.claim')]"), + 'partner_id': fields.many2one('res.partner', 'Partner'), } def init(self, cr): tools.drop_view_if_exists(cr, 'report_crm_claim') @@ -22,6 +23,7 @@ class report_crm_claim(osv.osv): c.user_id, c.stage_id, c.section_id, + c.partner_id, c.categ_id, count(*) as nbr, 0 as avg_answers, @@ -30,7 +32,7 @@ class report_crm_claim(osv.osv): to_char(avg(date_closed-c.create_date), 'DD"d" HH24:MI:SS') as delay_close from crm_claim c - group by to_char(c.create_date, 'YYYY'), to_char(c.create_date, 'MM'), c.state, c.user_id,c.section_id, c.stage_id,c.categ_id + group by to_char(c.create_date, 'YYYY'), to_char(c.create_date, 'MM'), c.state, c.user_id,c.section_id, c.stage_id,c.categ_id,c.partner_id )""") report_crm_claim() diff --git a/addons/report_crm/report_crm_claim_view.xml b/addons/report_crm/report_crm_claim_view.xml index 1766eabb94f..9186ff49865 100644 --- a/addons/report_crm/report_crm_claim_view.xml +++ b/addons/report_crm/report_crm_claim_view.xml @@ -10,12 +10,13 @@ + + + - - diff --git a/addons/report_crm/report_crm_fundraising.py b/addons/report_crm/report_crm_fundraising.py index 397a50896bc..bd136e28162 100644 --- a/addons/report_crm/report_crm_fundraising.py +++ b/addons/report_crm/report_crm_fundraising.py @@ -11,6 +11,7 @@ class report_crm_fundraising(osv.osv): 'amount_revenue': fields.float('Est.Revenue', readonly=True), 'amount_revenue_prob': fields.float('Est. Rev*Prob.', readonly=True), 'delay_close': fields.char('Delay to close', size=20, readonly=True), + 'partner_id': fields.many2one('res.partner', 'Partner'), } def init(self, cr): tools.drop_view_if_exists(cr, 'report_crm_fundraising') @@ -24,6 +25,7 @@ class report_crm_fundraising(osv.osv): c.user_id, c.section_id, c.categ_id, + c.partner_id, count(*) as nbr, 0 as avg_answers, 0.0 as perc_done, @@ -34,7 +36,7 @@ class report_crm_fundraising(osv.osv): to_char(avg(date_closed-c.create_date), 'DD"d" HH24:MI:SS') as delay_close from crm_fundraising c - group by to_char(c.create_date, 'YYYY'), to_char(c.create_date, 'MM'), c.state, c.user_id,c.section_id,c.categ_id + group by to_char(c.create_date, 'YYYY'), to_char(c.create_date, 'MM'), c.state, c.user_id,c.section_id,c.categ_id,c.partner_id )""") report_crm_fundraising() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/report_crm/report_crm_fundraising_view.xml b/addons/report_crm/report_crm_fundraising_view.xml index dc188ef9956..509adf7e530 100644 --- a/addons/report_crm/report_crm_fundraising_view.xml +++ b/addons/report_crm/report_crm_fundraising_view.xml @@ -13,14 +13,15 @@ + + + - - diff --git a/addons/report_crm/report_crm_lead.py b/addons/report_crm/report_crm_lead.py index 2f170bd1825..0f42c0803ef 100644 --- a/addons/report_crm/report_crm_lead.py +++ b/addons/report_crm/report_crm_lead.py @@ -9,6 +9,7 @@ class report_crm_lead(osv.osv): 'delay_close': fields.char('Delay to close', size=20, readonly=True), 'categ_id': fields.many2one('crm.case.categ', 'Category', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.lead')]"), 'stage_id': fields.many2one ('crm.case.stage', 'Stage', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.lead')]", readonly=True), + 'partner_id': fields.many2one('res.partner', 'Partner'), } def init(self, cr): tools.drop_view_if_exists(cr, 'report_crm_lead') @@ -23,6 +24,7 @@ class report_crm_lead(osv.osv): c.stage_id, c.section_id, c.categ_id, + c.partner_id, count(*) as nbr, 0 as avg_answers, 0.0 as perc_done, @@ -30,7 +32,7 @@ class report_crm_lead(osv.osv): to_char(avg(date_closed-c.create_date), 'DD"d" HH24:MI:SS') as delay_close from crm_lead c - group by to_char(c.create_date, 'YYYY'), to_char(c.create_date, 'MM'), c.state, c.user_id,c.section_id,c.stage_id,categ_id + group by to_char(c.create_date, 'YYYY'), to_char(c.create_date, 'MM'), c.state, c.user_id,c.section_id,c.stage_id,categ_id,c.partner_id )""") report_crm_lead() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/report_crm/report_crm_lead_view.xml b/addons/report_crm/report_crm_lead_view.xml index d5f4e63fd16..b5491dffd80 100644 --- a/addons/report_crm/report_crm_lead_view.xml +++ b/addons/report_crm/report_crm_lead_view.xml @@ -13,11 +13,12 @@ + + + - - diff --git a/addons/report_crm/report_crm_opportunity_view.xml b/addons/report_crm/report_crm_opportunity_view.xml index bd5e14edae6..3deb335ffd3 100644 --- a/addons/report_crm/report_crm_opportunity_view.xml +++ b/addons/report_crm/report_crm_opportunity_view.xml @@ -15,12 +15,12 @@ + - diff --git a/addons/report_crm/report_crm_phonecall.py b/addons/report_crm/report_crm_phonecall.py index e693179a258..129fd977356 100644 --- a/addons/report_crm/report_crm_phonecall.py +++ b/addons/report_crm/report_crm_phonecall.py @@ -9,6 +9,7 @@ class report_crm_phonecall(osv.osv): _columns = { 'delay_close': fields.char('Delay to close', size=20, readonly=True), 'categ_id': fields.many2one('crm.case.categ', 'Category', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.phonecall')]"), + } def init(self, cr): tools.drop_view_if_exists(cr, 'report_crm_phonecall') @@ -22,6 +23,7 @@ class report_crm_phonecall(osv.osv): c.user_id, c.section_id, c.categ_id, + c.partner_id, count(*) as nbr, 0 as avg_answers, 0.0 as perc_done, @@ -29,7 +31,7 @@ class report_crm_phonecall(osv.osv): to_char(avg(date_closed-c.create_date), 'DD"d" HH24:MI:SS') as delay_close from crm_phonecall c - group by to_char(c.create_date, 'YYYY'), to_char(c.create_date, 'MM'), c.state, c.user_id,c.section_id, c.categ_id + group by to_char(c.create_date, 'YYYY'), to_char(c.create_date, 'MM'), c.state, c.user_id,c.section_id, c.categ_id,c.partner_id )""") report_crm_phonecall() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/report_crm/report_crm_phonecall_view.xml b/addons/report_crm/report_crm_phonecall_view.xml index 672f6fe101d..8b6e87f54a5 100644 --- a/addons/report_crm/report_crm_phonecall_view.xml +++ b/addons/report_crm/report_crm_phonecall_view.xml @@ -13,11 +13,12 @@ + + + - - From a93473787e0fe1a3aaecab5224e961ecb8516688 Mon Sep 17 00:00:00 2001 From: Julien Thewys Date: Fri, 5 Mar 2010 10:12:18 +0100 Subject: [PATCH 019/157] [IMP] Added more syntax. bzr revid: jth@openerp.com-20100305091218-p3t878j0z02q7rwd --- bin/tools/yaml_test.py | 284 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 279 insertions(+), 5 deletions(-) diff --git a/bin/tools/yaml_test.py b/bin/tools/yaml_test.py index b91e457791e..5cee9b92d5e 100644 --- a/bin/tools/yaml_test.py +++ b/bin/tools/yaml_test.py @@ -50,16 +50,45 @@ class Python(YamlTag): self.name = name super(Python, self).__init__(**kwargs) +class Menuitem(YamlTag): + def __init__(self, id, name, **kwargs): + self.id = id + self.name = name + super(Menuitem, self).__init__(**kwargs) + class Workflow(YamlTag): def __init__(self, model, action, **kwargs): self.model = model self.action = action super(Workflow, self).__init__(**kwargs) +class ActWindow(YamlTag): + def __init__(self, model, action, **kwargs): + self.model = model + self.action = action + super(Workflow, self).__init__(**kwargs) + +class Function(YamlTag): + def __init__(self, model, name, **kwargs): + self.model = model + self.name = name + super(Function, self).__init__(**kwargs) + +class Delete(YamlTag): + def __init__(self, model, id, search, **kwargs): + self.model = model + self.id = id + self.search = search + super(Delete, self).__init__(**kwargs) + class Context(YamlTag): def __init__(self, **kwargs): super(Context, self).__init__(**kwargs) +class Url(YamlTag): + def __init__(self, **kwargs): + super(Url, self).__init__(**kwargs) + class Eval(YamlTag): def __init__(self, expression): self.expression = expression @@ -82,14 +111,34 @@ def python_constructor(loader, node): kwargs = loader.construct_mapping(node) return Python(**kwargs) +def menuitem_constructor(loader, node): + kwargs = loader.construct_mapping(node) + return Menuitem(**kwargs) + def workflow_constructor(loader, node): kwargs = loader.construct_mapping(node) return Workflow(**kwargs) +def act_window_constructor(loader, node): + kwargs = loader.construct_mapping(node) + return ActWindow(**kwargs) + +def function_constructor(loader, node): + kwargs = loader.construct_mapping(node) + return Function(**kwargs) + +def delete_constructor(loader, node): + kwargs = loader.construct_mapping(node) + return Delete(**kwargs) + def context_constructor(loader, node): kwargs = loader.construct_mapping(node) return Context(**kwargs) +def url_constructor(loader, node): + kwargs = loader.construct_mapping(node) + return Url(**kwargs) + def eval_constructor(loader, node): expression = loader.construct_scalar(node) return Eval(expression) @@ -101,8 +150,13 @@ def ref_constructor(loader, node): yaml.add_constructor(u"!assert", assert_constructor) yaml.add_constructor(u"!record", record_constructor) yaml.add_constructor(u"!python", python_constructor) +yaml.add_constructor(u"!menuitem", menuitem_constructor) yaml.add_constructor(u"!workflow", workflow_constructor) +yaml.add_constructor(u"!act_window", act_window_constructor) +yaml.add_constructor(u"!function", function_constructor) yaml.add_constructor(u"!context", context_constructor) +yaml.add_constructor(u"!delete", delete_constructor) +yaml.add_constructor(u"!url", url_constructor) yaml.add_constructor(u"!eval", eval_constructor) yaml.add_constructor(u"!ref", ref_constructor) @@ -124,13 +178,29 @@ def is_record(node): def is_python(node): return _is_yaml_mapping(node, Python) +def is_menuitem(node): + return isinstance(node, Menuitem) \ + or _is_yaml_mapping(node, Menuitem) + +def is_function(node): + return isinstance(node, Function) \ + or _is_yaml_mapping(node, Function) + def is_workflow(node): - return isinstance(node, Workflow) \ - or _is_yaml_mapping(node, Workflow) + return isinstance(node, Workflow) + +def is_act_window(node): + return isinstance(node, ActWindow) + +def is_delete(node): + return isinstance(node, Delete) def is_context(node): return isinstance(node, Context) +def is_url(node): + return isinstance(node, Url) + def is_eval(node): return isinstance(node, Eval) @@ -154,7 +224,7 @@ class TestReport(object): def __str__(self): res = [] - res.append('\nAssertions report:\nLevel\tsuccess\tfailed') + res.append('\nAssertions report:\nLevel\tsuccess\tfailure') success = failure = 0 for severity in self._report: res.append("%s\t%s\t%s" % (severity, self._report[severity][True], self._report[severity][False])) @@ -217,6 +287,12 @@ class YamlInterpreter(object): self.id_map[xml_id] = id return id + def get_context(self, node, locals_dict): + context = self.context.copy() + if node.context: + context.update(eval(node.context, locals_dict)) + return context + def process_comment(self, node): return node @@ -336,8 +412,8 @@ class YamlInterpreter(object): if not len(values) == 1: raise YamlImportException('Only one child node is accepted (%d given).' % len(values)) value = values[0] - if not 'model' in value and not 'eval' in value: - raise YamlImportException('You must provide a model and an expression to evaluate for the workflow.') + if not 'model' in value and (not 'eval' in value or not 'search' in value): + raise YamlImportException('You must provide a "model" and an "eval" or "search" to evaluate.') value_model = self.get_model(value['model']) local_context = {'ref': self._ref, '_ref': self._ref} local_context['obj'] = lambda x: value_model.browse(self.cr, self.uid, x, context=self.context) @@ -350,7 +426,192 @@ class YamlInterpreter(object): uid = self.uid wf_service = netsvc.LocalService("workflow") wf_service.trg_validate(uid, model, id, workflow.action, self.cr) + + def process_function(self, node): + if self.mode != 'init': + return + function, values = node.items()[0] + local_context = {'ref': self._ref, '_ref': self._ref} + context = self.get_context(node, local_context) + args = [] + if function.eval: + args = eval(function.eval, local_context) + for value in values: + if not 'model' in value and (not 'eval' in value or not 'search' in value): + raise YamlImportException('You must provide a "model" and an "eval" or "search" to evaluate.') + value_model = self.get_model(value['model']) + local_context = {'ref': self._ref, '_ref': self._ref} + local_context['obj'] = lambda x: value_model.browse(self.cr, self.uid, x, context=context) + local_context.update(self.id_map) + id = eval(value['eval'], local_context) + if id != None: + args.append(id) + model = self.get_model(function.model) + method = function.name + getattr(model, method)(self.cr, self.uid, *args) + def _set_group_values(self, node, values): + if node.groups: + group_names = node.groups.split(',') + groups_value = [] + for group in group_names: + if group.startswith('-'): + group_id = self.get_id(group[1:]) + groups_value.append((3, group_id)) + else: + group_id = self.get_id(group) + groups_value.append((4, group_id)) + values['groups_id'] = groups_value + + def process_menuitem(self, node): + self.validate_xml_id(node.id) + + if not node.parent: + parent_id = False + self.cr.execute('select id from ir_ui_menu where parent_id is null and name=%s', (node.name,)) + res = self.cr.fetchone() + values = {'parent_id': parent_id, 'name': node.name} + else: + parent_id = self.get_id(node.parent) + values = {'parent_id': parent_id} + if node.name: + values['name'] = node.name + try: + res = [ self.get_id(node.id) ] + except: # which exception ? + res = None + + if node.action: + action_type = node.type or 'act_window' + icons = { + "act_window": 'STOCK_NEW', + "report.xml": 'STOCK_PASTE', + "wizard": 'STOCK_EXECUTE', + "url": 'STOCK_JUMP_TO', + } + values['icon'] = icons.get(action_type, 'STOCK_NEW') + if action_type == 'act_window': + action_id = self.get_id(node.action) + self.cr.execute('select view_type,view_mode,name,view_id,target from ir_act_window where id=%s', (action_id,)) + ir_act_window_result = self.cr.fetchone() + assert ir_act_window_result, "No window action defined for this id %s !\n" \ + "Verify that this is a window action or add a type argument." % (node.action,) + action_type, action_mode, action_name, view_id, target = ir_act_window_result + if view_id: + self.cr.execute('SELECT type FROM ir_ui_view WHERE id=%s', (view_id,)) + # TODO guess why action_mode is ir_act_window.view_mode above and ir_ui_view.type here + action_mode = self.cr.fetchone() + self.cr.execute('SELECT view_mode FROM ir_act_window_view WHERE act_window_id=%s ORDER BY sequence LIMIT 1', (action_id,)) + if self.cr.rowcount: + action_mode = self.cr.fetchone() + if action_type == 'tree': + values['icon'] = 'STOCK_INDENT' + elif action_mode and action_mode.startswith('tree'): + values['icon'] = 'STOCK_JUSTIFY_FILL' + elif action_mode and action_mode.startswith('graph'): + values['icon'] = 'terp-graph' + elif action_mode and action_mode.startswith('calendar'): + values['icon'] = 'terp-calendar' + if target == 'new': + values['icon'] = 'STOCK_EXECUTE' + if not values.get('name', False): + values['name'] = action_name + elif action_type == 'wizard': + action_id = self.get_id(node.action) + self.cr.execute('select name from ir_act_wizard where id=%s', (action_id,)) + ir_act_wizard_result = self.cr.fetchone() + if (not values.get('name', False)) and ir_act_wizard_result: + values['name'] = ir_act_wizard_result[0] + else: + raise YamlImportException("Unsupported type '%s' in menuitem tag." % action_type) + if node.sequence: + values['sequence'] = node.sequence + if node.icon: + values['icon'] = node.icon + + self._set_group_values(node, values) + + pid = self.pool.get('ir.model.data')._update(self.cr, self.uid, \ + 'ir.ui.menu', self.module, values, node.id, mode=self.mode, \ + res_id=res and res[0] or False) + + if node.id and parent_id: + self.id_map[node.id] = int(parent_id) + + if node.action and pid: + action_type = node.type or 'act_window' + action_id = self.get_id(node.action) + action = "ir.actions.%s,%d" % (action_type, action_id) + self.pool.get('ir.model.data').ir_set(self.cr, self.uid, 'action', \ + 'tree_but_open', 'Menuitem', [('ir.ui.menu', int(parent_id))], action, True, True, xml_id=node.id) + + def process_act_window(self, node): + self.validate_xml_id(node.id) + view_id = False + if node.view: + view_id = self.get_id(node.view) + context = eval(node.context, {'ref': self._ref, '_ref': self._ref}) + + values = { + 'name': node.name, + 'type': type or 'ir.actions.act_window', + 'view_id': view_id, + 'domain': node.domain, + 'context': context, + 'res_model': node.res_model, + 'src_model': node.src_model, + 'view_type': node.view_type or 'form', + 'view_mode': node.view_mode or 'tree,form', + 'usage': node.usage, + 'limit': node.limit, + 'auto_refresh': node.auto_refresh, + } + + self._set_group_values(node, values) + + if node.target: + values['target'] = node.target + id = self.pool.get('ir.model.data')._update(self.cr, self.uid, \ + 'ir.actions.act_window', self.module, values, node.id, mode=self.mode) + self.id_map[node.id] = int(id) + + if node.src_model: + keyword = 'client_action_relate' + value = 'ir.actions.act_window,%s' % id + replace = node.replace or True + self.pool.get('ir.model.data').ir_set(self.cr, self.uid, 'action', \ + keyword, node.id, [node.src_model], value, replace=replace, isobject=True, xml_id=node.id) + # TODO add remove ir.model.data + + def process_delete(self, node): + ids = [] + if len(node.search): + ids = self.pool.get(node.model).search(self.cr, self.uid, eval(node.search)) + if len(node.id): + try: + ids.append(self.get_id(node.id)) + except: + pass + if len(ids): + self.pool.get(node.model).unlink(self.cr, self.uid, ids) + self.pool.get('ir.model.data')._unlink(self.cr, self.uid, node.model, ids, direct=True) + + def process_url(self, node): + self.validate_xml_id(node.id) + + res = {'name': node.name, 'url': node.url, 'target': node.target} + + id = self.pool.get('ir.model.data')._update(self.cr, self.uid, \ + "ir.actions.url", self.module, res, node.id, mode=self.mode) + self.id_map[node.id] = int(id) + # ir_set + if (not node.menu or eval(node.menu)) and id: + keyword = node.keyword or 'client_action_multi' + value = 'ir.actions.url,%s' % id + replace = node.replace or True + self.pool.get('ir.model.data').ir_set(self.cr, self.uid, \ + 'action', keyword, node.url, ["ir.actions.url"], value, replace=replace, isobject=True, xml_id=node.id) + def process(self, yaml_string): """Processes a Yaml string. Custom tags are interpreted by 'process_' instance methods.""" @@ -374,13 +635,26 @@ class YamlInterpreter(object): self.process_record(node) elif is_python(node): self.process_python(node) + elif is_menuitem(node): + self.process_menuitem(node) + elif is_delete(node): + self.process_delete(node) + elif is_url(node): + self.process_url(node) elif is_context(node): self.process_context(node) + elif is_act_window(node): + self.process_act_window(node) elif is_workflow(node): if isinstance(node, types.DictionaryType): self.process_workflow(node) else: self.process_workflow({node: []}) + elif is_function(node): + if isinstance(node, types.DictionaryType): + self.process_function(node) + else: + self.process_function({node: []}) else: raise YamlImportException("Can not process YAML block: %s" % node) From 110771a391c5367aac3182438a41019aa9bec18c Mon Sep 17 00:00:00 2001 From: "sbh (Open ERP)" Date: Fri, 5 Mar 2010 14:50:14 +0530 Subject: [PATCH 020/157] [IMP] crm,report_crm: Fix the probelm probability aand add the company_id in all report bzr revid: sbh@tinyerp.com-20100305092014-id3njiugtdj2hb0a --- addons/crm/crm.py | 7 ++++--- addons/report_crm/report_crm_claim.py | 6 ++++-- addons/report_crm/report_crm_claim_view.xml | 1 + addons/report_crm/report_crm_fundraising.py | 4 +++- addons/report_crm/report_crm_fundraising_view.xml | 3 ++- addons/report_crm/report_crm_lead.py | 6 ++++-- addons/report_crm/report_crm_lead_view.xml | 1 + addons/report_crm/report_crm_opportunity.py | 6 ++++-- addons/report_crm/report_crm_opportunity_view.xml | 5 +++-- addons/report_crm/report_crm_phonecall.py | 5 +++-- addons/report_crm/report_crm_phonecall_view.xml | 1 + 11 files changed, 30 insertions(+), 15 deletions(-) diff --git a/addons/crm/crm.py b/addons/crm/crm.py index 7765f61ec32..33b75802e49 100644 --- a/addons/crm/crm.py +++ b/addons/crm/crm.py @@ -296,8 +296,8 @@ class crm_case(osv.osv): if section in s: st = case.stage_id.id or False if st in s[section]: - self.write(cr, uid, [case.id], {'stage_id': s[section][st]}) - + stage_value = self.pool.get('crm.case.stage').read(cr, uid,s[section][st] , ['probability'], context) + self.write(cr, uid, [case.id], {'stage_id': s[section][st],'probability':stage_value['probability']}) return True def get_stage_dict(self, cr, uid, ids, context={}): @@ -319,7 +319,8 @@ class crm_case(osv.osv): st = case.stage_id.id or False s[section] = dict([(v, k) for (k, v) in s[section].iteritems()]) if st in s[section]: - self.write(cr, uid, [case.id], {'stage_id': s[section][st]}) + stage_value = self.pool.get('crm.case.stage').read(cr, uid,s[section][st] ,['probability'], context) + self.write(cr, uid, [case.id], {'stage_id': s[section][st],'probability':stage_value['probability']}) return True diff --git a/addons/report_crm/report_crm_claim.py b/addons/report_crm/report_crm_claim.py index 7f171849462..f82444fb79b 100644 --- a/addons/report_crm/report_crm_claim.py +++ b/addons/report_crm/report_crm_claim.py @@ -9,7 +9,8 @@ class report_crm_claim(osv.osv): 'delay_close': fields.char('Delay to close', size=20, readonly=True), 'stage_id': fields.many2one ('crm.case.stage', 'Stage', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.claim')]", readonly=True), 'categ_id': fields.many2one('crm.case.categ', 'Category', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.claim')]"), - 'partner_id': fields.many2one('res.partner', 'Partner'), + 'partner_id': fields.many2one('res.partner', 'Partner'), + 'company_id': fields.many2one('res.company','Company'), } def init(self, cr): tools.drop_view_if_exists(cr, 'report_crm_claim') @@ -24,6 +25,7 @@ class report_crm_claim(osv.osv): c.stage_id, c.section_id, c.partner_id, + c.company_id, c.categ_id, count(*) as nbr, 0 as avg_answers, @@ -32,7 +34,7 @@ class report_crm_claim(osv.osv): to_char(avg(date_closed-c.create_date), 'DD"d" HH24:MI:SS') as delay_close from crm_claim c - group by to_char(c.create_date, 'YYYY'), to_char(c.create_date, 'MM'), c.state, c.user_id,c.section_id, c.stage_id,c.categ_id,c.partner_id + group by to_char(c.create_date, 'YYYY'), to_char(c.create_date, 'MM'), c.state, c.user_id,c.section_id, c.stage_id,c.categ_id,c.partner_id,c.company_id )""") report_crm_claim() diff --git a/addons/report_crm/report_crm_claim_view.xml b/addons/report_crm/report_crm_claim_view.xml index 9186ff49865..99a715be840 100644 --- a/addons/report_crm/report_crm_claim_view.xml +++ b/addons/report_crm/report_crm_claim_view.xml @@ -12,6 +12,7 @@ + diff --git a/addons/report_crm/report_crm_fundraising.py b/addons/report_crm/report_crm_fundraising.py index bd136e28162..70497a71c31 100644 --- a/addons/report_crm/report_crm_fundraising.py +++ b/addons/report_crm/report_crm_fundraising.py @@ -12,6 +12,7 @@ class report_crm_fundraising(osv.osv): 'amount_revenue_prob': fields.float('Est. Rev*Prob.', readonly=True), 'delay_close': fields.char('Delay to close', size=20, readonly=True), 'partner_id': fields.many2one('res.partner', 'Partner'), + 'company_id': fields.many2one('res.company','Company'), } def init(self, cr): tools.drop_view_if_exists(cr, 'report_crm_fundraising') @@ -25,6 +26,7 @@ class report_crm_fundraising(osv.osv): c.user_id, c.section_id, c.categ_id, + c.company_id, c.partner_id, count(*) as nbr, 0 as avg_answers, @@ -36,7 +38,7 @@ class report_crm_fundraising(osv.osv): to_char(avg(date_closed-c.create_date), 'DD"d" HH24:MI:SS') as delay_close from crm_fundraising c - group by to_char(c.create_date, 'YYYY'), to_char(c.create_date, 'MM'), c.state, c.user_id,c.section_id,c.categ_id,c.partner_id + group by to_char(c.create_date, 'YYYY'), to_char(c.create_date, 'MM'), c.state, c.user_id,c.section_id,c.categ_id,c.partner_id,c.company_id )""") report_crm_fundraising() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/report_crm/report_crm_fundraising_view.xml b/addons/report_crm/report_crm_fundraising_view.xml index 509adf7e530..0861cd58a2b 100644 --- a/addons/report_crm/report_crm_fundraising_view.xml +++ b/addons/report_crm/report_crm_fundraising_view.xml @@ -15,9 +15,10 @@ + - + diff --git a/addons/report_crm/report_crm_lead.py b/addons/report_crm/report_crm_lead.py index 0f42c0803ef..0a233ce9b51 100644 --- a/addons/report_crm/report_crm_lead.py +++ b/addons/report_crm/report_crm_lead.py @@ -9,7 +9,8 @@ class report_crm_lead(osv.osv): 'delay_close': fields.char('Delay to close', size=20, readonly=True), 'categ_id': fields.many2one('crm.case.categ', 'Category', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.lead')]"), 'stage_id': fields.many2one ('crm.case.stage', 'Stage', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.lead')]", readonly=True), - 'partner_id': fields.many2one('res.partner', 'Partner'), + 'partner_id': fields.many2one('res.partner', 'Partner'), + 'company_id': fields.many2one('res.company','Company'), } def init(self, cr): tools.drop_view_if_exists(cr, 'report_crm_lead') @@ -22,6 +23,7 @@ class report_crm_lead(osv.osv): c.state, c.user_id, c.stage_id, + c.company_id, c.section_id, c.categ_id, c.partner_id, @@ -32,7 +34,7 @@ class report_crm_lead(osv.osv): to_char(avg(date_closed-c.create_date), 'DD"d" HH24:MI:SS') as delay_close from crm_lead c - group by to_char(c.create_date, 'YYYY'), to_char(c.create_date, 'MM'), c.state, c.user_id,c.section_id,c.stage_id,categ_id,c.partner_id + group by to_char(c.create_date, 'YYYY'), to_char(c.create_date, 'MM'), c.state, c.user_id,c.section_id,c.stage_id,categ_id,c.partner_id,c.company_id )""") report_crm_lead() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/report_crm/report_crm_lead_view.xml b/addons/report_crm/report_crm_lead_view.xml index b5491dffd80..fd7e56a0317 100644 --- a/addons/report_crm/report_crm_lead_view.xml +++ b/addons/report_crm/report_crm_lead_view.xml @@ -15,6 +15,7 @@ + diff --git a/addons/report_crm/report_crm_opportunity.py b/addons/report_crm/report_crm_opportunity.py index 8ff49af0e71..a261fd91f24 100644 --- a/addons/report_crm/report_crm_opportunity.py +++ b/addons/report_crm/report_crm_opportunity.py @@ -14,6 +14,7 @@ class report_crm_opportunity(osv.osv): 'categ_id': fields.many2one('crm.case.categ', 'Category', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.opportunity')]"), 'stage_id':fields.many2one('crm.case.stage', 'Stage', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.opportunity')]", readonly=True), 'partner_id': fields.many2one('res.partner', 'Partner'), + 'company_id': fields.many2one('res.company', 'Company',readonly=True), } def init(self, cr): tools.drop_view_if_exists(cr, 'report_crm_opportunity') @@ -29,17 +30,18 @@ class report_crm_opportunity(osv.osv): c.categ_id, c.stage_id, c.partner_id, + c.company_id, count(*) as nbr, 0 as avg_answers, 0.0 as perc_done, 0.0 as perc_cancel, sum(planned_revenue) as amount_revenue, - sum(planned_revenue*probability)::decimal(16,2) as amount_revenue_prob, + sum((planned_revenue*probability)/100.0)::decimal(16,2) as amount_revenue_prob, avg(probability)::decimal(16,2) as probability, to_char(avg(date_closed-c.create_date), 'DD"d" HH24:MI:SS') as delay_close from crm_opportunity c - group by to_char(c.create_date, 'YYYY'), to_char(c.create_date, 'MM'), c.state, c.user_id,c.section_id,c.stage_id,c.categ_id,c.partner_id + group by to_char(c.create_date, 'YYYY'), to_char(c.create_date, 'MM'), c.state, c.user_id,c.section_id,c.stage_id,c.categ_id,c.partner_id,company_id )""") report_crm_opportunity() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/report_crm/report_crm_opportunity_view.xml b/addons/report_crm/report_crm_opportunity_view.xml index 3deb335ffd3..8dfe91c4031 100644 --- a/addons/report_crm/report_crm_opportunity_view.xml +++ b/addons/report_crm/report_crm_opportunity_view.xml @@ -15,9 +15,10 @@ + - + @@ -64,8 +65,8 @@ + - diff --git a/addons/report_crm/report_crm_phonecall.py b/addons/report_crm/report_crm_phonecall.py index 129fd977356..77ce3c17f94 100644 --- a/addons/report_crm/report_crm_phonecall.py +++ b/addons/report_crm/report_crm_phonecall.py @@ -9,7 +9,7 @@ class report_crm_phonecall(osv.osv): _columns = { 'delay_close': fields.char('Delay to close', size=20, readonly=True), 'categ_id': fields.many2one('crm.case.categ', 'Category', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.phonecall')]"), - + 'company_id': fields.many2one('res.company','Company'), } def init(self, cr): tools.drop_view_if_exists(cr, 'report_crm_phonecall') @@ -24,6 +24,7 @@ class report_crm_phonecall(osv.osv): c.section_id, c.categ_id, c.partner_id, + c.company_id, count(*) as nbr, 0 as avg_answers, 0.0 as perc_done, @@ -31,7 +32,7 @@ class report_crm_phonecall(osv.osv): to_char(avg(date_closed-c.create_date), 'DD"d" HH24:MI:SS') as delay_close from crm_phonecall c - group by to_char(c.create_date, 'YYYY'), to_char(c.create_date, 'MM'), c.state, c.user_id,c.section_id, c.categ_id,c.partner_id + group by to_char(c.create_date, 'YYYY'), to_char(c.create_date, 'MM'), c.state, c.user_id,c.section_id, c.categ_id,c.partner_id,c.company_id )""") report_crm_phonecall() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/report_crm/report_crm_phonecall_view.xml b/addons/report_crm/report_crm_phonecall_view.xml index 8b6e87f54a5..71889fb994c 100644 --- a/addons/report_crm/report_crm_phonecall_view.xml +++ b/addons/report_crm/report_crm_phonecall_view.xml @@ -15,6 +15,7 @@ + From 33a87c8dea87caf6284cfbe409f1240884d245e5 Mon Sep 17 00:00:00 2001 From: "rpa (Open ERP)" Date: Fri, 5 Mar 2010 14:51:22 +0530 Subject: [PATCH 021/157] [FIX]: base_calendar: Fixed problem of editing recurrent event+ exporting attendee without email bzr revid: rpa@openerp.co.in-20100305092122-d6ujxcrmpk2ctyle --- addons/base_calendar/base_calendar.py | 18 +++++++++++------- addons/caldav/caldav.py | 5 ++++- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/addons/base_calendar/base_calendar.py b/addons/base_calendar/base_calendar.py index 5c8aa460da0..18b27820766 100644 --- a/addons/base_calendar/base_calendar.py +++ b/addons/base_calendar/base_calendar.py @@ -811,18 +811,18 @@ rule or repeating pattern for anexception to a recurrence set"), 'interval': lambda *x: 1, } - def modify_this(self, cr, uid, ids, defaults, context=None, *args): + def modify_this(self, cr, uid, ids, defaults, real_date, context=None, *args): ids = map(lambda x: base_calendar_id2real_id(x), ids) datas = self.read(cr, uid, ids[0], context=context) defaults.update({ 'recurrent_uid': base_calendar_id2real_id(datas['id']), - 'recurrent_id': defaults.get('date'), + 'recurrent_id': defaults.get('date') or real_date, 'rrule_type': 'none', 'rrule': '' }) exdate = datas['exdate'] and datas['exdate'].split(',') or [] - if defaults.get('date'): - exdate.append(defaults.get('date')) + if real_date and defaults.get('date'): + exdate.append(real_date) self.write(cr, uid, ids, {'exdate': ','.join(exdate)}, context=context) new_id = self.copy(cr, uid, ids[0], default=defaults, context=context) return new_id @@ -986,9 +986,13 @@ rule or repeating pattern for anexception to a recurrence set"), new_ids = [] for id in select: if len(str(id).split('-')) > 1: - data = self.read(cr, uid, id, ['date', 'date_deadline']) - self.modify_this(cr, uid, [id], vals, context) - continue + data = self.read(cr, uid, id, ['date', 'date_deadline', 'rrule', 'duration']) + if data.get('rrule'): + real_date = data.get('date') + data.update(vals) + new_id = self.modify_this(cr, uid, [id], data, real_date, context) + context.update({'active_id': new_id,'active_ids': [new_id]}) + continue id = base_calendar_id2real_id(id) if not id in new_ids: new_ids.append(id) diff --git a/addons/caldav/caldav.py b/addons/caldav/caldav.py index 3afcc28dd40..ce7bbe62e24 100644 --- a/addons/caldav/caldav.py +++ b/addons/caldav/caldav.py @@ -804,7 +804,10 @@ class Attendee(CalDAV, osv.osv_memory): cn_val = [str(attendee[a_val['field']])] if cn_val: attendee_add.params['CN'] = cn_val - attendee_add.value = 'MAILTO:' + attendee['email'] + if not attendee['email']: + raise osv.except_osv(_('Error !'), _('Attendee must have an Email Id')) + elif attendee['email']: + attendee_add.value = 'MAILTO:' + attendee['email'] return vevent Attendee() From 6c3969b38914af23dd72be7edf0efee4596c5290 Mon Sep 17 00:00:00 2001 From: "sbh (Open ERP)" Date: Fri, 5 Mar 2010 15:01:42 +0530 Subject: [PATCH 022/157] [IMP] report_crm: set readonly on some field bzr revid: sbh@tinyerp.com-20100305093142-lh7migddq6dnzj30 --- addons/report_crm/report_crm.py | 4 +++- addons/report_crm/report_crm_claim.py | 6 +++--- addons/report_crm/report_crm_lead.py | 6 +++--- addons/report_crm/report_crm_opportunity.py | 4 ++-- addons/report_crm/report_crm_phonecall.py | 3 ++- addons/report_crm/report_crm_view.xml | 3 +++ 6 files changed, 16 insertions(+), 10 deletions(-) diff --git a/addons/report_crm/report_crm.py b/addons/report_crm/report_crm.py index da9ba2e9ba3..91ad7269351 100644 --- a/addons/report_crm/report_crm.py +++ b/addons/report_crm/report_crm.py @@ -74,6 +74,7 @@ class report_crm_case(osv.osv): 'perc_cancel': fields.function(_get_data,string='%Cancel', method=True,type="float"), 'month':fields.selection([('01','January'), ('02','February'), ('03','March'), ('04','April'), ('05','May'), ('06','June'), ('07','July'), ('08','August'), ('09','September'), ('10','October'), ('11','November'), ('12','December')],'Month',readonly=True), + 'company_id': fields.many2one('res.company','Company',readonly=True), } _order = 'name desc, user_id' def init(self, cr): @@ -87,10 +88,11 @@ class report_crm_case(osv.osv): c.state, c.user_id, c.section_id, + c.company_id, count(*) as nbr from crm_case c - group by to_char(c.create_date, 'YYYY'), to_char(c.create_date, 'MM'), c.state, c.user_id,c.section_id + group by to_char(c.create_date, 'YYYY'), to_char(c.create_date, 'MM'), c.state, c.user_id,c.section_id,c.company_id )""") report_crm_case() diff --git a/addons/report_crm/report_crm_claim.py b/addons/report_crm/report_crm_claim.py index f82444fb79b..5ec1cf05849 100644 --- a/addons/report_crm/report_crm_claim.py +++ b/addons/report_crm/report_crm_claim.py @@ -8,9 +8,9 @@ class report_crm_claim(osv.osv): _columns = { 'delay_close': fields.char('Delay to close', size=20, readonly=True), 'stage_id': fields.many2one ('crm.case.stage', 'Stage', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.claim')]", readonly=True), - 'categ_id': fields.many2one('crm.case.categ', 'Category', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.claim')]"), - 'partner_id': fields.many2one('res.partner', 'Partner'), - 'company_id': fields.many2one('res.company','Company'), + 'categ_id': fields.many2one('crm.case.categ', 'Category', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.claim')]",readonly=True), + 'partner_id': fields.many2one('res.partner', 'Partner',readonly=True), + 'company_id': fields.many2one('res.company','Company',readonly=True), } def init(self, cr): tools.drop_view_if_exists(cr, 'report_crm_claim') diff --git a/addons/report_crm/report_crm_lead.py b/addons/report_crm/report_crm_lead.py index 0a233ce9b51..e9c79ed772d 100644 --- a/addons/report_crm/report_crm_lead.py +++ b/addons/report_crm/report_crm_lead.py @@ -7,10 +7,10 @@ class report_crm_lead(osv.osv): _inherit = "report.crm.case" _columns = { 'delay_close': fields.char('Delay to close', size=20, readonly=True), - 'categ_id': fields.many2one('crm.case.categ', 'Category', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.lead')]"), + 'categ_id': fields.many2one('crm.case.categ', 'Category', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.lead')]" ,readonly=True), 'stage_id': fields.many2one ('crm.case.stage', 'Stage', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.lead')]", readonly=True), - 'partner_id': fields.many2one('res.partner', 'Partner'), - 'company_id': fields.many2one('res.company','Company'), + 'partner_id': fields.many2one('res.partner', 'Partner' ,readonly=True), + 'company_id': fields.many2one('res.company','Company',readonly=True), } def init(self, cr): tools.drop_view_if_exists(cr, 'report_crm_lead') diff --git a/addons/report_crm/report_crm_opportunity.py b/addons/report_crm/report_crm_opportunity.py index a261fd91f24..2ded021a71e 100644 --- a/addons/report_crm/report_crm_opportunity.py +++ b/addons/report_crm/report_crm_opportunity.py @@ -11,9 +11,9 @@ class report_crm_opportunity(osv.osv): 'amount_revenue': fields.float('Est.Revenue', readonly=True), 'amount_revenue_prob': fields.float('Est. Rev*Prob.', readonly=True), 'delay_close': fields.char('Delay to close', size=20, readonly=True), - 'categ_id': fields.many2one('crm.case.categ', 'Category', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.opportunity')]"), + 'categ_id': fields.many2one('crm.case.categ', 'Category', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.opportunity')]", readonly=True), 'stage_id':fields.many2one('crm.case.stage', 'Stage', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.opportunity')]", readonly=True), - 'partner_id': fields.many2one('res.partner', 'Partner'), + 'partner_id': fields.many2one('res.partner', 'Partner',readonly=True), 'company_id': fields.many2one('res.company', 'Company',readonly=True), } def init(self, cr): diff --git a/addons/report_crm/report_crm_phonecall.py b/addons/report_crm/report_crm_phonecall.py index 77ce3c17f94..f89af4b1d15 100644 --- a/addons/report_crm/report_crm_phonecall.py +++ b/addons/report_crm/report_crm_phonecall.py @@ -9,7 +9,8 @@ class report_crm_phonecall(osv.osv): _columns = { 'delay_close': fields.char('Delay to close', size=20, readonly=True), 'categ_id': fields.many2one('crm.case.categ', 'Category', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.phonecall')]"), - 'company_id': fields.many2one('res.company','Company'), + 'partner_id': fields.many2one('res.partner', 'Partner' ,readonly=True), + 'company_id': fields.many2one('res.company','Company',readonly=True), } def init(self, cr): tools.drop_view_if_exists(cr, 'report_crm_phonecall') diff --git a/addons/report_crm/report_crm_view.xml b/addons/report_crm/report_crm_view.xml index 8b88c7ef524..2e52d59b87c 100644 --- a/addons/report_crm/report_crm_view.xml +++ b/addons/report_crm/report_crm_view.xml @@ -11,6 +11,7 @@ + @@ -72,6 +73,7 @@ + @@ -79,6 +81,7 @@ + From 434c1fb2cacbe323338e631d13d1cbc9fec6bf4a Mon Sep 17 00:00:00 2001 From: Julien Thewys Date: Fri, 5 Mar 2010 10:37:22 +0100 Subject: [PATCH 023/157] [IMP] Added ir_set. [FIX] ActWindow __init__ bzr revid: jth@openerp.com-20100305093722-s62ly3eabzn5mup5 --- bin/tools/yaml_test.py | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/bin/tools/yaml_test.py b/bin/tools/yaml_test.py index 5cee9b92d5e..442370ab5dc 100644 --- a/bin/tools/yaml_test.py +++ b/bin/tools/yaml_test.py @@ -66,7 +66,7 @@ class ActWindow(YamlTag): def __init__(self, model, action, **kwargs): self.model = model self.action = action - super(Workflow, self).__init__(**kwargs) + super(ActWindow, self).__init__(**kwargs) class Function(YamlTag): def __init__(self, model, name, **kwargs): @@ -94,10 +94,9 @@ class Eval(YamlTag): self.expression = expression super(Eval, self).__init__() -class Ref(YamlTag): - def __init__(self, xmlid): - self.xmlid = xmlid - super(Ref, self).__init__() +class IrSet(YamlTag): + def __init__(self): + super(IrSet, self).__init__() def assert_constructor(loader, node): kwargs = loader.construct_mapping(node) @@ -143,9 +142,9 @@ def eval_constructor(loader, node): expression = loader.construct_scalar(node) return Eval(expression) -def ref_constructor(loader, node): - xmlid = loader.construct_scalar(node) - return Ref(xmlid) +def ir_set_constructor(loader, node): + kwargs = loader.construct_mapping(node) + return IrSet(**kwargs) yaml.add_constructor(u"!assert", assert_constructor) yaml.add_constructor(u"!record", record_constructor) @@ -158,7 +157,7 @@ yaml.add_constructor(u"!context", context_constructor) yaml.add_constructor(u"!delete", delete_constructor) yaml.add_constructor(u"!url", url_constructor) yaml.add_constructor(u"!eval", eval_constructor) -yaml.add_constructor(u"!ref", ref_constructor) +yaml.add_constructor(u"!ir_set", ir_set_constructor) def _is_yaml_mapping(node, tag_constructor): value = isinstance(node, types.DictionaryType) \ @@ -204,8 +203,8 @@ def is_url(node): def is_eval(node): return isinstance(node, Eval) -def is_ref(node): - return isinstance(node, Ref) +def is_ir_set(node): + return _is_yaml_mapping(node, IrSet) class TestReport(object): @@ -611,6 +610,21 @@ class YamlInterpreter(object): replace = node.replace or True self.pool.get('ir.model.data').ir_set(self.cr, self.uid, \ 'action', keyword, node.url, ["ir.actions.url"], value, replace=replace, isobject=True, xml_id=node.id) + + def process_ir_set(self, node): + if not self.mode == 'init': + return False + _, fields = node.items()[0] + res = {} + for fieldname, expression in fields.items(): + if isinstance(expression, Eval): + value = eval(expression.expression, {'ref': self._ref, '_ref': self._ref}) + else: + value = expression + res[fieldname] = value + self.pool.get('ir.model.data').ir_set(self.cr, self.uid, res['key'], res['key2'], \ + res['name'], res['models'], res['value'], replace=res.get('replace',True), \ + isobject=res.get('isobject', False), meta=res.get('meta',None)) def process(self, yaml_string): """Processes a Yaml string. Custom tags are interpreted by 'process_' instance methods.""" @@ -643,6 +657,8 @@ class YamlInterpreter(object): self.process_url(node) elif is_context(node): self.process_context(node) + elif is_ir_set(node): + self.process_ir_set(node) elif is_act_window(node): self.process_act_window(node) elif is_workflow(node): From f3cd7c3a9751436d6b7b5b828fbf6e1719bafa78 Mon Sep 17 00:00:00 2001 From: "rpa (Open ERP)" Date: Fri, 5 Mar 2010 15:33:09 +0530 Subject: [PATCH 024/157] [IMP]: crm(Opportunity): Added domain for Current Opportunity in schedule a meeting wizard bzr revid: rpa@openerp.co.in-20100305100309-xy1we9khjuy5tcqx --- addons/crm/wizard/crm_opportunity_wizard.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/addons/crm/wizard/crm_opportunity_wizard.py b/addons/crm/wizard/crm_opportunity_wizard.py index d7ec0b72cb6..e2636027c92 100644 --- a/addons/crm/wizard/crm_opportunity_wizard.py +++ b/addons/crm/wizard/crm_opportunity_wizard.py @@ -154,16 +154,20 @@ class opportunity2meeting(wizard.interface): partner_id = opportunity.partner_id and opportunity.partner_id.id or False name = opportunity.name email = opportunity.email_from - section_id = opportunity.section_id and opportunity.section_id.id or False + section_id = opportunity.section_id and opportunity.section_id.id or False return { 'name': _('Meetings'), - 'domain' : "[('user_id','=',%s)]"%(uid), - 'context': {'default_partner_id': partner_id, 'default_section_id': section_id, 'default_email_from': email, 'default_state':'open', 'default_name':name}, + 'domain' : "[('user_id','=',%s), ('opportunity_id', '=', %s)]"%(uid, data['id']), + 'context': {'default_partner_id': partner_id, + 'default_opportunity_id': data['id'], + 'default_section_id': section_id, + 'default_email_from': email, + 'default_state':'open', 'default_name':name}, 'view_type': 'form', - 'view_mode': 'calendar,form,tree', + 'view_mode': 'tree,form,calendar', 'res_model': 'crm.meeting', 'view_id': False, - 'views': [(id1,'calendar'),(id2,'form'),(id3,'tree')], + 'views': [(id3, 'tree'), (id2, 'form'), (id1, 'calendar')], 'type': 'ir.actions.act_window', 'search_view_id': id['res_id'] } From cf770834143a7425671dada9f5af3c69732ef5a5 Mon Sep 17 00:00:00 2001 From: Julien Thewys Date: Fri, 5 Mar 2010 11:05:37 +0100 Subject: [PATCH 025/157] [FIX] fixed missing isnoupdate and get_context bzr revid: jth@openerp.com-20100305100537-jqia7equynfbue4o --- bin/tools/yaml_test.py | 46 +++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/bin/tools/yaml_test.py b/bin/tools/yaml_test.py index 442370ab5dc..d284824e1c1 100644 --- a/bin/tools/yaml_test.py +++ b/bin/tools/yaml_test.py @@ -291,6 +291,9 @@ class YamlInterpreter(object): if node.context: context.update(eval(node.context, locals_dict)) return context + + def isnoupdate(self, node): + return self.noupdate or node.noupdate or False def process_comment(self, node): return node @@ -315,6 +318,8 @@ class YamlInterpreter(object): def process_assert(self, node): assertion, expressions = node.items()[0] + if self.isnoupdate(assertion) and self.mode != 'init': + return model = self.get_model(assertion.model) ids = self._get_assertion_id(assertion) if assertion.count and len(ids) != assertion.count: @@ -325,11 +330,12 @@ class YamlInterpreter(object): args = (assertion.string, assertion.count, len(ids)) self._log_assert_failure(assertion.severity, msg, *args) else: - test_context = {'ref': self._ref, '_ref': self._ref} # added '_ref' so that record['ref'] is possible + local_context = {'ref': self._ref, '_ref': self._ref} # added '_ref' so that record['ref'] is possible + context = self.get_context(assertion, local_context) for id in ids: - record = model.browse(self.cr, self.uid, id, assertion.context) + record = model.browse(self.cr, self.uid, id, context) for test in expressions.get('test', ''): - success = eval(test, test_context, record) + success = eval(test, local_context, record) if not success: msg = 'Assertion "%s" FAILED\ntest: %s\n' args = (assertion.string, test) @@ -342,13 +348,14 @@ class YamlInterpreter(object): record, fields = node.items()[0] self.validate_xml_id(record.id) - model = self.get_model(record.model) - record_dict = self._create_record(model, fields) - id = self.pool.get('ir.model.data')._update(self.cr, self.uid, record.model, \ - self.module, record_dict, record.id, mode=self.mode) - self.id_map[record.id] = int(id) - if config.get('import_partial', False): - self.cr.commit() + if self.isnoupdate(record) and self.mode != 'init': + model = self.get_model(record.model) + record_dict = self._create_record(model, fields) + id = self.pool.get('ir.model.data')._update(self.cr, self.uid, record.model, \ + self.module, record_dict, record.id, noupdate=self.isnoupdate(node), mode=self.mode) + self.id_map[record.id] = int(id) + if config.get('import_partial', False): + self.cr.commit() def _create_record(self, model, fields): record_dict = {} @@ -402,6 +409,8 @@ class YamlInterpreter(object): def process_workflow(self, node): workflow, values = node.items()[0] + if self.isnoupdate(workflow) and self.mode != 'init': + return model = self.get_model(workflow.model) if workflow.ref: id = self.get_id(workflow.ref) @@ -427,11 +436,11 @@ class YamlInterpreter(object): wf_service.trg_validate(uid, model, id, workflow.action, self.cr) def process_function(self, node): - if self.mode != 'init': - return function, values = node.items()[0] + if self.isnoupdate(function) and self.mode != 'init': + return local_context = {'ref': self._ref, '_ref': self._ref} - context = self.get_context(node, local_context) + context = self.get_context(function, local_context) args = [] if function.eval: args = eval(function.eval, local_context) @@ -532,7 +541,7 @@ class YamlInterpreter(object): pid = self.pool.get('ir.model.data')._update(self.cr, self.uid, \ 'ir.ui.menu', self.module, values, node.id, mode=self.mode, \ - res_id=res and res[0] or False) + noupdate=self.isnoupdate(node), res_id=res and res[0] or False) if node.id and parent_id: self.id_map[node.id] = int(parent_id) @@ -578,8 +587,8 @@ class YamlInterpreter(object): keyword = 'client_action_relate' value = 'ir.actions.act_window,%s' % id replace = node.replace or True - self.pool.get('ir.model.data').ir_set(self.cr, self.uid, 'action', \ - keyword, node.id, [node.src_model], value, replace=replace, isobject=True, xml_id=node.id) + self.pool.get('ir.model.data').ir_set(self.cr, self.uid, 'action', keyword, \ + node.id, [node.src_model], value, replace=replace, noupdate=self.isnoupdate(node), isobject=True, xml_id=node.id) # TODO add remove ir.model.data def process_delete(self, node): @@ -608,8 +617,9 @@ class YamlInterpreter(object): keyword = node.keyword or 'client_action_multi' value = 'ir.actions.url,%s' % id replace = node.replace or True - self.pool.get('ir.model.data').ir_set(self.cr, self.uid, \ - 'action', keyword, node.url, ["ir.actions.url"], value, replace=replace, isobject=True, xml_id=node.id) + self.pool.get('ir.model.data').ir_set(self.cr, self.uid, 'action', \ + keyword, node.url, ["ir.actions.url"], value, replace=replace, \ + noupdate=self.isnoupdate(node), isobject=True, xml_id=node.id) def process_ir_set(self, node): if not self.mode == 'init': From 48e7f8370a2f0024fb2356bf3bd52275df9922be Mon Sep 17 00:00:00 2001 From: "uco (OpenERP)" Date: Fri, 5 Mar 2010 15:38:13 +0530 Subject: [PATCH 026/157] [ADD]: Added access rules for remaining objects in account, hr, mail_gateway, mrp, stock, project, base_calendar and resource modules. bzr revid: uco@tinyerp.co.in-20100305100813-2wsyownr15sk335s --- addons/account/security/ir.model.access.csv | 1 + addons/account_voucher/__terp__.py | 1 + .../base_calendar/security/ir.model.access.csv | 2 ++ addons/hr/security/ir.model.access.csv | 2 ++ addons/mail_gateway/security/ir.model.access.csv | 3 +++ addons/mrp/mrp.py | 2 +- addons/mrp/security/ir.model.access.csv | 2 ++ addons/project/security/ir.model.access.csv | 2 ++ addons/resource/__terp__.py | 2 +- addons/resource/security/ir.model.access.csv | 8 ++++---- addons/stock/security/ir.model.access.csv | 7 +++++++ addons/stock/stock_wizard.py | 16 ++++++++-------- addons/stock/stock_wizard_view.xml | 4 ++-- 13 files changed, 36 insertions(+), 16 deletions(-) diff --git a/addons/account/security/ir.model.access.csv b/addons/account/security/ir.model.access.csv index 4cf67851760..271a4efe0ab 100644 --- a/addons/account/security/ir.model.access.csv +++ b/addons/account/security/ir.model.access.csv @@ -87,3 +87,4 @@ "access_account_fiscal_position_account_template","account.fiscal.position.account.template","model_account_fiscal_position_account_template","account.group_account_manager",1,1,1,1 "access_account_sequence_fiscal_year","account.sequence.fiscalyear","model_account_sequence_fiscalyear","account.group_account_user",1,1,1,1 "access_account_sequence_fiscal_year_user","account.sequence.fiscalyear user","model_account_sequence_fiscalyear","base.group_user",1,0,0,0 +"access_account_installer","account.installer","model_account_installer","base.group_user",1,0,0,0 diff --git a/addons/account_voucher/__terp__.py b/addons/account_voucher/__terp__.py index 242cc5fb391..20bf2c579ff 100755 --- a/addons/account_voucher/__terp__.py +++ b/addons/account_voucher/__terp__.py @@ -39,6 +39,7 @@ ], "update_xml" : [ + "security/account_security.xml", "voucher_sequence.xml", "account_report.xml", "voucher_view.xml", diff --git a/addons/base_calendar/security/ir.model.access.csv b/addons/base_calendar/security/ir.model.access.csv index 8a720533140..2851e392e0b 100644 --- a/addons/base_calendar/security/ir.model.access.csv +++ b/addons/base_calendar/security/ir.model.access.csv @@ -3,3 +3,5 @@ "access_calendar_alarm","calendar.alarm","model_calendar_alarm",,1,1,1,1 "access_res_alarm","res.alarm","model_res_alarm",,1,1,1,1 "access_calendar_event_all","calendar.event","model_calendar_event",,1,1,1,1 +"access_calendar_todo","calendar.todo","model_calendar_todo",,1,1,1,1 +"access_base_calendar_invite_attendee","base_calendar.invite.attendee","model_base_calendar_invite_attendee",,1,1,1,1 diff --git a/addons/hr/security/ir.model.access.csv b/addons/hr/security/ir.model.access.csv index cd1a18d246b..3853a6e8e38 100644 --- a/addons/hr/security/ir.model.access.csv +++ b/addons/hr/security/ir.model.access.csv @@ -5,3 +5,5 @@ "access_hr_employee_category_manager","hr.employee.category.manager","model_hr_employee_category","hr.group_hr_manager",1,1,1,1 "access_hr_department_manager","hr.department.manager","model_hr_department","hr.group_hr_manager",1,1,1,1 "access_hr_employee_marital_status","hr.employee.marital.status","model_hr_employee_marital_status","hr.group_hr_user",1,1,1,1 +"access_hr_job","hr.job","model_hr_job","hr.group_hr_user",1,0,0,0 +"access_hr_installer","hr.installer","model_hr_installer","hr.group_hr_user",1,0,0,0 \ No newline at end of file diff --git a/addons/mail_gateway/security/ir.model.access.csv b/addons/mail_gateway/security/ir.model.access.csv index 996147308f6..864db00acb0 100644 --- a/addons/mail_gateway/security/ir.model.access.csv +++ b/addons/mail_gateway/security/ir.model.access.csv @@ -1,4 +1,7 @@ "id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" +"access_mail_gateway_server","mail.gateway.server","model_mail_gateway_server","base.group_user",1,0,0,0 +"access_mail_gateway","mail.gateway","model_mail_gateway","base.group_user",1,0,0,0 +"access_mail_gateway_history","mail.gateway.history","model_mail_gateway_history","base.group_user",1,0,0,0 diff --git a/addons/mrp/mrp.py b/addons/mrp/mrp.py index 5bb5d8a59c4..40fd2e46525 100644 --- a/addons/mrp/mrp.py +++ b/addons/mrp/mrp.py @@ -1422,7 +1422,7 @@ StockPicking() class spilt_in_production_lot(osv.osv_memory): - _inherit = "stock.move.spilt" + _inherit = "stock.move.split" def split(self, cr, uid, ids, move_ids, context=None): production_obj = self.pool.get('mrp.production') move_obj = self.pool.get('stock.move') diff --git a/addons/mrp/security/ir.model.access.csv b/addons/mrp/security/ir.model.access.csv index f3cae96266c..cdc658ff7c0 100644 --- a/addons/mrp/security/ir.model.access.csv +++ b/addons/mrp/security/ir.model.access.csv @@ -30,3 +30,5 @@ "access_hr_timesheet_group_mrp_worker","resource.calendar mrp_worker","resource.model_resource_calendar","mrp.group_mrp_user",1,0,0,0 "access_mrp_procurement_stock_worker","mrp.procurement stock_worker","model_mrp_procurement","stock.group_stock_user",1,1,1,1 "access_mrp_production_stock_worker","mrp.production stock_worker","model_mrp_production","stock.group_stock_user",1,0,0,0 +"access_mrp_installer","mrp.installer","model_mrp_installer","mrp.group_mrp_user",1,0,0,0 +"access_mrp_product_produce","mrp.product.produce","model_mrp_product_produce","mrp.group_mrp_user",1,0,0,0 diff --git a/addons/project/security/ir.model.access.csv b/addons/project/security/ir.model.access.csv index efeda2170a5..b5877b688b7 100644 --- a/addons/project/security/ir.model.access.csv +++ b/addons/project/security/ir.model.access.csv @@ -11,3 +11,5 @@ "access_project_task_work_manager","project.task.work.manager","model_project_task_work","project.group_project_manager",1,1,1,1 "access_config_compute_remaining","project.config.compute.remaining","model_config_compute_remaining","project.group_project_user",1,1,1,1 "access_config_compute_remaining_manager","project.config.compute.remaining.manager","model_config_compute_remaining","project.group_project_manager",1,1,1,1 +"access_project_message","project.message","model_project_message","project.group_project_user",1,0,0,0 +"access_project_installer","project.installer","model_project_installer","project.group_project_user",1,0,0,0 \ No newline at end of file diff --git a/addons/resource/__terp__.py b/addons/resource/__terp__.py index 7c924574cf1..fb2a0f5899c 100755 --- a/addons/resource/__terp__.py +++ b/addons/resource/__terp__.py @@ -37,7 +37,7 @@ 'init_xml': [], 'update_xml': [ #'security/resource_security.xml', -# 'security/ir.model.access.csv', + 'security/ir.model.access.csv', 'resource_view.xml', ], 'demo_xml': ['resource_demo.xml' diff --git a/addons/resource/security/ir.model.access.csv b/addons/resource/security/ir.model.access.csv index 0874bf97235..796d29dcb94 100644 --- a/addons/resource/security/ir.model.access.csv +++ b/addons/resource/security/ir.model.access.csv @@ -1,5 +1,5 @@ "id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" -"access_hr_timesheet_group","resource.calendar","model_resource_calendar","hr.group_hr_user",1,0,0,0 -"access_hr_timesheet","hr.timesheet","model_hr_timesheet","hr.group_hr_user",1,1,1,1 -"access_hr_timesheet_manager","hr.timesheet manager","model_hr_timesheet","hr.group_hr_manager",1,1,1,1 -"access_hr_timesheet_group_manager","hr.timesheet.group.manager","model_hr_timesheet_group","hr.group_hr_manager",1,1,1,1 +"access_resource_calendar","resource.calendar","model_resource_calendar","base.group_user",1,0,0,0 +"access_resource_calendar_week","resource.calendar.week","model_resource_calendar_week","base.group_user",1,0,0,0 +"access_resource_resource","resource.resource","model_resource_resource","base.group_user",1,0,0,0 +"access_resource_calendar_leaves","resource.calendar.leaves","model_resource_calendar_leaves","base.group_user",1,0,0,0 \ No newline at end of file diff --git a/addons/stock/security/ir.model.access.csv b/addons/stock/security/ir.model.access.csv index 25a455e771f..eea058ebde1 100644 --- a/addons/stock/security/ir.model.access.csv +++ b/addons/stock/security/ir.model.access.csv @@ -16,3 +16,10 @@ "access_stock_location_product_manager","stock.location product manager","model_stock_location","product.group_product_manager",1,0,0,0 "access_stock_lines_date","report.stock.lines.date all","model_report_stock_lines_date",,1,0,0,0 "access_stock_report_tracklots","stock.report.tracklots","model_stock_report_tracklots","stock.group_stock_user",1,1,1,1 +"access_report_products_to_received_planned","report.products.to.received.planned","model_report_products_to_received_planned","stock.group_stock_user",1,0,0,0 +"access_report_delivery_products_planned","report.delivery.products.planned","model_report_delivery_products_planned","stock.group_stock_user",1,0,0,0 +"access_stock_move_track","stock.move.track","model_stock_move_track","stock.group_stock_user",1,0,0,0 +"access_stock_move_consume","stock.move.consume","model_stock_move_consume","stock.group_stock_user",1,0,0,0 +"access_stock_move_scrap","stock.move.scrap","model_stock_move_scrap","stock.group_stock_user",1,0,0,0 +"access_stock_move_split","stock.move.split","model_stock_move_split","stock.group_stock_user",1,0,0,0 +"access_stock_move_split_lines","stock.move.split.lines","model_stock_move_split_lines","stock.group_stock_user",1,0,0,0 \ No newline at end of file diff --git a/addons/stock/stock_wizard.py b/addons/stock/stock_wizard.py index c813b8583b6..548375db199 100644 --- a/addons/stock/stock_wizard.py +++ b/addons/stock/stock_wizard.py @@ -110,13 +110,13 @@ class stock_move_scrap(osv.osv_memory): stock_move_scrap() -class spilt_in_production_lot(osv.osv_memory): - _name = "stock.move.spilt" +class split_in_production_lot(osv.osv_memory): + _name = "stock.move.split" _description = "Split in Production lots" _columns = { 'product_id': fields.many2one('product.product', 'Product', required=True, select=True), - 'line_ids': fields.one2many('stock.move.spilt.lines', 'lot_id', 'Lots Number') + 'line_ids': fields.one2many('stock.move.split.lines', 'lot_id', 'Lots Number') } def _get_product_id(self, cr, uid, context): @@ -185,17 +185,17 @@ class spilt_in_production_lot(osv.osv_memory): return new_move -spilt_in_production_lot() +split_in_production_lot() -class stock_move_spilt_lines(osv.osv_memory): - _name = "stock.move.spilt.lines" +class stock_move_split_lines(osv.osv_memory): + _name = "stock.move.split.lines" _description = "Split lines" _columns = { 'name': fields.char('Tracking serial', size=64), 'quantity': fields.integer('Quantity'), 'use_exist' : fields.boolean('Use Exist'), - 'lot_id': fields.many2one('stock.move.spilt', 'Lot'), + 'lot_id': fields.many2one('stock.move.split', 'Lot'), 'action': fields.selection([('split','Split'),('keepinone','Keep in one lot')],'Action'), } _defaults = { @@ -203,4 +203,4 @@ class stock_move_spilt_lines(osv.osv_memory): 'action' : lambda *x: 'split', } -stock_move_spilt_lines() +stock_move_split_lines() diff --git a/addons/stock/stock_wizard_view.xml b/addons/stock/stock_wizard_view.xml index 72200beaee8..55fc8a6d8a7 100644 --- a/addons/stock/stock_wizard_view.xml +++ b/addons/stock/stock_wizard_view.xml @@ -100,7 +100,7 @@ Split in lots - stock.move.spilt + stock.move.split form
@@ -131,7 +131,7 @@ Split in lots ir.actions.act_window - stock.move.spilt + stock.move.split form form new From 23ef56589e6e88fbd55c11920e149f10abd52a12 Mon Sep 17 00:00:00 2001 From: "rpa (Open ERP)" Date: Fri, 5 Mar 2010 15:47:26 +0530 Subject: [PATCH 027/157] [IMP]: crm(claim): Improved filter + put buttons in list view bzr revid: rpa@openerp.co.in-20100305101726-12bnj0b8ytr2ujlz --- addons/crm/crm_claims_view.xml | 20 ++++++++++++++++---- addons/crm/crm_fund_view.xml | 4 +++- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/addons/crm/crm_claims_view.xml b/addons/crm/crm_claims_view.xml index e0fd5d90c80..ae6635bdbcb 100644 --- a/addons/crm/crm_claims_view.xml +++ b/addons/crm/crm_claims_view.xml @@ -43,6 +43,11 @@ + + + + + + + + + + +
+ + OpenERP + + + + Tiny + +
+ +
+ - From f549ded71494795863d28f0aecaed8572efb77f1 Mon Sep 17 00:00:00 2001 From: "mra (Open ERP)" Date: Mon, 8 Mar 2010 17:23:48 +0530 Subject: [PATCH 091/157] [FIX] event: registration tree view date field replace by create_date lp bug: https://launchpad.net/bugs/534279 fixed bzr revid: mra@tinyerp.com-20100308115348-7j6gr3887rg8mk2c --- addons/event/event_view.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/event/event_view.xml b/addons/event/event_view.xml index 274d9f8c2e4..aaf16a0ad9c 100644 --- a/addons/event/event_view.xml +++ b/addons/event/event_view.xml @@ -162,7 +162,7 @@ - + From b5056e2c9f4494c95fdcd680674d2084231b0f38 Mon Sep 17 00:00:00 2001 From: "uco (OpenERP)" Date: Mon, 8 Mar 2010 18:04:34 +0530 Subject: [PATCH 092/157] [FIX] multi_company: Fixed the problem of demo data. bzr revid: uco@tinyerp.co.in-20100308123434-fjhgd3jiqacfedbx --- addons/multi_company/multi_company_demo.xml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/addons/multi_company/multi_company_demo.xml b/addons/multi_company/multi_company_demo.xml index 7f18b7edd86..b7ddeca9d5c 100644 --- a/addons/multi_company/multi_company_demo.xml +++ b/addons/multi_company/multi_company_demo.xml @@ -24,30 +24,36 @@ OpenERP Corp. + + OpenERP Editor + OpenERP US + OpenERP BE - OpenERP IN +
+ OpenERP IN + Odoo From fec4b1a0c7cf436a469ef4d73ad1a982ed17d01c Mon Sep 17 00:00:00 2001 From: "uco (OpenERP)" Date: Mon, 8 Mar 2010 18:06:27 +0530 Subject: [PATCH 093/157] [FIX] document_ics: Fixed the problem of demo data. bzr revid: uco@tinyerp.co.in-20100308123627-wpt0lxa13o86o3p3 --- addons/document_ics/document_demo.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/document_ics/document_demo.xml b/addons/document_ics/document_demo.xml index b21842214b1..a4c892340de 100644 --- a/addons/document_ics/document_demo.xml +++ b/addons/document_ics/document_demo.xml @@ -23,7 +23,7 @@ dtstart - + From b63ea698607bb152227ed85c6afeff9dcf263f8e Mon Sep 17 00:00:00 2001 From: "uco (OpenERP)" Date: Mon, 8 Mar 2010 18:09:27 +0530 Subject: [PATCH 094/157] [FIX] l10n_ch: Fixed name of fields in 'res.partner.bank' object. bzr revid: uco@tinyerp.co.in-20100308123927-idhwyd79x83e7z59 --- addons/l10n_ch/bank.py | 4 ++-- addons/l10n_ch/bank_view.xml | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/addons/l10n_ch/bank.py b/addons/l10n_ch/bank.py index 280057a558b..5b8603ded96 100755 --- a/addons/l10n_ch/bank.py +++ b/addons/l10n_ch/bank.py @@ -48,8 +48,8 @@ class bvr_checkbox(osv.osv): """ Add function to generate function """ _inherit = "res.partner.bank" _columns = { - 'printBank' : fields.boolean('Print Bank on BVR'), - 'printAccount' : fields.boolean('Print Account Number on BVR'), + 'print_Bank' : fields.boolean('Print Bank on BVR'), + 'print_Account' : fields.boolean('Print Account Number on BVR'), } bvr_checkbox() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/l10n_ch/bank_view.xml b/addons/l10n_ch/bank_view.xml index 35593c2688c..aeb37ac15cb 100755 --- a/addons/l10n_ch/bank_view.xml +++ b/addons/l10n_ch/bank_view.xml @@ -32,8 +32,8 @@ - - + + @@ -45,8 +45,8 @@ - - + +
From 491069f3df858a92f6aef68dac146d5e5fb54fee Mon Sep 17 00:00:00 2001 From: "uco (OpenERP)" Date: Mon, 8 Mar 2010 18:15:46 +0530 Subject: [PATCH 095/157] [FIX] board_crm_configuration: Changed object names which were in report_crm. Removed dependancy of report_crm. bzr revid: uco@tinyerp.co.in-20100308124546-jqm1u0wnz8iv1ole --- addons/board_crm_configuration/__terp__.py | 2 +- .../board_crm_statistical_view.xml | 20 +++++++++---------- .../board_crm_view.xml | 8 ++++---- addons/crm/crm.py | 2 +- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/addons/board_crm_configuration/__terp__.py b/addons/board_crm_configuration/__terp__.py index 3c303ee2d1c..09bd6e25bc1 100644 --- a/addons/board_crm_configuration/__terp__.py +++ b/addons/board_crm_configuration/__terp__.py @@ -34,7 +34,7 @@ This module implements a dashboard for CRM that includes: * Jobs Tracking (graph) """, 'author': 'Tiny', - 'depends': ['board', 'crm', 'report_crm'], + 'depends': ['board', 'crm'], 'update_xml': ['board_crm_statistical_view.xml', 'board_crm_view.xml'], 'demo_xml': ['board_crm_demo.xml'], 'installable': True, diff --git a/addons/board_crm_configuration/board_crm_statistical_view.xml b/addons/board_crm_configuration/board_crm_statistical_view.xml index 8dbe05735f0..d6dd5b6d65b 100644 --- a/addons/board_crm_configuration/board_crm_statistical_view.xml +++ b/addons/board_crm_configuration/board_crm_statistical_view.xml @@ -6,7 +6,7 @@ --> Leads By Stage - Graph - report.crm.lead.section.stage + crm.lead.report graph @@ -18,11 +18,11 @@ - report.crm.opportunity.categ.graph - report.crm.opportunity.categ + crm.opportunity.report.graph + crm.opportunity.report graph - + @@ -32,14 +32,14 @@ - report.crm.lead.section.stage + crm.lead.report form graph,tree,form @@ -47,8 +47,8 @@ diff --git a/addons/board_crm_configuration/board_crm_view.xml b/addons/board_crm_configuration/board_crm_view.xml index 586a3c64baa..b111aabc2b2 100644 --- a/addons/board_crm_configuration/board_crm_view.xml +++ b/addons/board_crm_configuration/board_crm_view.xml @@ -6,8 +6,8 @@ - crm.opportunity.user.graph1 - report.crm.opportunity.user + crm.opportunity.report.graph1 + crm.opportunity.report graph @@ -41,7 +41,7 @@ id="act_my_cases"/> - report.crm.lead.section.stage + crm.lead.report form graph,tree,form @@ -49,7 +49,7 @@ - report.crm.opportunity.user + crm.opportunity.report form graph,tree,form diff --git a/addons/crm/crm.py b/addons/crm/crm.py index 1a0ba8ad950..a7b2c79759f 100644 --- a/addons/crm/crm.py +++ b/addons/crm/crm.py @@ -280,7 +280,7 @@ class crm_case(osv.osv): 'section_id': _get_section, 'company_id': lambda s,cr,uid,c: s.pool.get('res.company')._company_default_get(cr, uid, 'crm.case', context=c), } - _order = 'date_deadline desc, date desc,id desc' + _order = 'date_deadline desc, id desc' def unlink(self, cr, uid, ids, context={}): for case in self.browse(cr, uid, ids, context): From 7f584d927db64c3f6a64093335eb5967b06f2ee2 Mon Sep 17 00:00:00 2001 From: "uco (OpenERP)" Date: Mon, 8 Mar 2010 18:23:13 +0530 Subject: [PATCH 096/157] [FIX] board_sale: Removed dependancy of report_crm and report_sale modules. bzr revid: uco@tinyerp.co.in-20100308125313-6bkvgzc4ib1rd0q6 --- addons/board_sale/__terp__.py | 2 +- addons/board_sale/board_sale_view.xml | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/addons/board_sale/__terp__.py b/addons/board_sale/__terp__.py index 4a08eed8d96..bf4e572d031 100644 --- a/addons/board_sale/__terp__.py +++ b/addons/board_sale/__terp__.py @@ -33,7 +33,7 @@ This module implements a dashboard for salesman that includes: * Graph of cases of the month """, 'author': 'Tiny', - 'depends': ['board', 'sale', 'report_crm', 'report_sale'], + 'depends': ['board', 'sale'], 'update_xml': ['board_sale_view.xml'], 'demo_xml': ['board_sale_demo.xml'], 'installable': True, diff --git a/addons/board_sale/board_sale_view.xml b/addons/board_sale/board_sale_view.xml index 496f189bf89..509bcb5428b 100644 --- a/addons/board_sale/board_sale_view.xml +++ b/addons/board_sale/board_sale_view.xml @@ -33,15 +33,11 @@ - - - - From 3bf452c0ddd52ef8ed37ba334ea36980be04ca98 Mon Sep 17 00:00:00 2001 From: "uco (OpenERP)" Date: Mon, 8 Mar 2010 18:52:36 +0530 Subject: [PATCH 097/157] [FIX] l10n_ch: Fixed names of fields. bzr revid: uco@tinyerp.co.in-20100308132236-agdiluh32u22pxlj --- addons/l10n_ch/bank.py | 4 ++-- addons/l10n_ch/bank_view.xml | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/addons/l10n_ch/bank.py b/addons/l10n_ch/bank.py index 5b8603ded96..18aac869b77 100755 --- a/addons/l10n_ch/bank.py +++ b/addons/l10n_ch/bank.py @@ -48,8 +48,8 @@ class bvr_checkbox(osv.osv): """ Add function to generate function """ _inherit = "res.partner.bank" _columns = { - 'print_Bank' : fields.boolean('Print Bank on BVR'), - 'print_Account' : fields.boolean('Print Account Number on BVR'), + 'print_bank' : fields.boolean('Print Bank on BVR'), + 'print_account' : fields.boolean('Print Account Number on BVR'), } bvr_checkbox() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/l10n_ch/bank_view.xml b/addons/l10n_ch/bank_view.xml index aeb37ac15cb..6da45b45f0c 100755 --- a/addons/l10n_ch/bank_view.xml +++ b/addons/l10n_ch/bank_view.xml @@ -32,8 +32,8 @@ - - + + @@ -45,8 +45,8 @@ - - + + From 264b7e4322c644c21e4e7a856aae158b0328a96f Mon Sep 17 00:00:00 2001 From: "uco (OpenERP)" Date: Mon, 8 Mar 2010 19:02:44 +0530 Subject: [PATCH 098/157] [ADD] hr_contract: Added security rules for hr_contract. bzr revid: uco@tinyerp.co.in-20100308133244-h1jt52bb9juj47n1 --- addons/hr_contract/security/ir.model.access.csv | 2 ++ 1 file changed, 2 insertions(+) diff --git a/addons/hr_contract/security/ir.model.access.csv b/addons/hr_contract/security/ir.model.access.csv index 29290f16067..ab6179c530f 100644 --- a/addons/hr_contract/security/ir.model.access.csv +++ b/addons/hr_contract/security/ir.model.access.csv @@ -8,3 +8,5 @@ "access_hr_contract_user","hr.contract user","model_hr_contract","hr.group_hr_user",1,0,0,0 "access_hr_contract","hr.contract","model_hr_contract","group_hr_contract",1,1,1,1 "access_hr_employee_contract","hr.employee contract","hr.model_hr_employee","group_hr_contract",1,0,0,0 +"access_hr_contract_type_user","hr.contract.type user","model_hr_contract_type","hr.group_hr_user",1,0,0,0 +"access_hr_contract_type","hr.contract.type","model_hr_contract_type","group_hr_contract",1,1,1,1 From dee4267f0d056b10b0d31fb84f5e92f3bdad98e3 Mon Sep 17 00:00:00 2001 From: "uco (OpenERP)" Date: Mon, 8 Mar 2010 19:03:48 +0530 Subject: [PATCH 099/157] [REF] multi_company: Changed demo data for currency field. bzr revid: uco@tinyerp.co.in-20100308133348-l652716g09z3aa0v --- addons/multi_company/multi_company_demo.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/multi_company/multi_company_demo.xml b/addons/multi_company/multi_company_demo.xml index b7ddeca9d5c..592e63d5ed2 100644 --- a/addons/multi_company/multi_company_demo.xml +++ b/addons/multi_company/multi_company_demo.xml @@ -35,7 +35,7 @@ - + OpenERP US @@ -47,7 +47,7 @@ - + OpenERP IN From 4c72b9114eedfb655748e927d26f7a362d2be661 Mon Sep 17 00:00:00 2001 From: "uco (OpenERP)" Date: Mon, 8 Mar 2010 19:08:28 +0530 Subject: [PATCH 100/157] [ADD] l10n_be: Added security file for the module. bzr revid: uco@tinyerp.co.in-20100308133828-xgoy0ltaubjcnvd3 --- addons/l10n_be/__terp__.py | 2 +- addons/l10n_be/security/ir.model.access.csv | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 addons/l10n_be/security/ir.model.access.csv diff --git a/addons/l10n_be/__terp__.py b/addons/l10n_be/__terp__.py index 84e3354a332..43d5a189247 100644 --- a/addons/l10n_be/__terp__.py +++ b/addons/l10n_be/__terp__.py @@ -52,7 +52,7 @@ 'l10n_be_wizard.xml', 'l10n_be_sequence.xml', 'fiscal_templates.xml', - #'security/ir.model.access.csv' + 'security/ir.model.access.csv' ], 'demo_xml': [ 'account.report.report.csv' diff --git a/addons/l10n_be/security/ir.model.access.csv b/addons/l10n_be/security/ir.model.access.csv new file mode 100644 index 00000000000..daadf3d4b22 --- /dev/null +++ b/addons/l10n_be/security/ir.model.access.csv @@ -0,0 +1,2 @@ +"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" +"access_vat_listing_clients","vat.listing.clients","model_vat_listing_clients",,1,1,1,1 From 5d38506ee034a1753a541e6f17ae17c0723478e6 Mon Sep 17 00:00:00 2001 From: "uco (OpenERP)" Date: Mon, 8 Mar 2010 19:09:23 +0530 Subject: [PATCH 101/157] [FIX] crm: Removed 'date' field form report view. bzr revid: uco@tinyerp.co.in-20100308133923-rbcxy4dp3mt4vy2z --- addons/crm/report/crm_report_view.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/addons/crm/report/crm_report_view.xml b/addons/crm/report/crm_report_view.xml index 6ecdcfb755a..7427fe64588 100644 --- a/addons/crm/report/crm_report_view.xml +++ b/addons/crm/report/crm_report_view.xml @@ -124,7 +124,6 @@ - @@ -139,7 +138,6 @@ tree - From 66fc981930aaaff12f3021ed9911ff9deb5ce9fe Mon Sep 17 00:00:00 2001 From: "uco (OpenERP)" Date: Mon, 8 Mar 2010 19:15:12 +0530 Subject: [PATCH 102/157] [ADD] thunderbird: Added security file for the module. bzr revid: uco@tinyerp.co.in-20100308134512-b69ngzpcc2qmk4nh --- addons/thunderbird/__terp__.py | 2 +- addons/thunderbird/security/ir.model.access.csv | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 addons/thunderbird/security/ir.model.access.csv diff --git a/addons/thunderbird/__terp__.py b/addons/thunderbird/__terp__.py index 3447b0377c2..8ebe6b80b10 100644 --- a/addons/thunderbird/__terp__.py +++ b/addons/thunderbird/__terp__.py @@ -55,7 +55,7 @@ "category" : "Generic Modules/Thunderbird interface", "init_xml" : [], "demo_xml" : [], - "update_xml" : [], + "update_xml" : ['security/ir.model.access.csv'], "active": False, "installable": True } diff --git a/addons/thunderbird/security/ir.model.access.csv b/addons/thunderbird/security/ir.model.access.csv new file mode 100644 index 00000000000..fdd310a0679 --- /dev/null +++ b/addons/thunderbird/security/ir.model.access.csv @@ -0,0 +1,3 @@ +"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" +"access_tinythunderbird_partner","tinythunderbird.partner","model_tinythunderbird_partner",,1,1,1,1 + From 012aa376031cac9778b8a1791b726130693f78cf Mon Sep 17 00:00:00 2001 From: "rpa (Open ERP)" Date: Mon, 8 Mar 2010 19:19:55 +0530 Subject: [PATCH 103/157] [IMP]: crm(mailgate): Improvement in mailgateway code according to new changes in crm bzr revid: rpa@tinyerp.com-20100308134955-ja9d2o97mrcupeid --- .../openerp_mailgate/openerp_mailgate.py | 120 ++++++++---------- 1 file changed, 56 insertions(+), 64 deletions(-) diff --git a/addons/crm/scripts/openerp_mailgate/openerp_mailgate.py b/addons/crm/scripts/openerp_mailgate/openerp_mailgate.py index 0e4fd4347bd..85f5d24279d 100755 --- a/addons/crm/scripts/openerp_mailgate/openerp_mailgate.py +++ b/addons/crm/scripts/openerp_mailgate/openerp_mailgate.py @@ -29,24 +29,17 @@ import os import binascii import time, socket -email_re = re.compile(r""" - ([a-zA-Z][\w\.-]*[a-zA-Z0-9] # username part - @ # mandatory @ sign - [a-zA-Z0-9][\w\.-]* # domain must start with a letter ... Ged> why do we include a 0-9 then? - \. - [a-z]{2,3} # TLD - ) - """, re.VERBOSE) +email_re = re.compile(r"[a-zA-Z][\w\.-]*[a-zA-Z0-9]@[a-zA-Z0-9][\w\.-]*\.[a-z]{2,3}", re.VERBOSE) case_re = re.compile(r"\[([0-9]+)\]", re.UNICODE) command_re = re.compile("^Set-([a-z]+) *: *(.+)$", re.I + re.UNICODE) reference_re = re.compile("<.*-tinycrm-(\\d+)@(.*)>", re.UNICODE) priorities = { - '1': '1 (Highest)', - '2': '2 (High)', - '3': '3 (Normal)', - '4': '4 (Low)', - '5': '5 (Lowest)', + '1': '1 (Highest)', + '2': '2 (High)', + '3': '3 (Normal)', + '4': '4 (Low)', + '5': '5 (Lowest)', } def html2plaintext(html, body_id=None, encoding='utf-8'): @@ -88,18 +81,18 @@ def html2plaintext(html, body_id=None, encoding='utf-8'): html = html.replace(d['tag'], '%s [%s]' % (d['title'], i)) url_index.append(d['url']) - html = html.replace('','*').replace('','*') - html = html.replace('','*').replace('','*') - html = html.replace('

','*').replace('

','*') - html = html.replace('

','**').replace('

','**') - html = html.replace('

','**').replace('

','**') - html = html.replace('','/').replace('','/') + html = html.replace('', '*').replace('', '*') + html = html.replace('', '*').replace('', '*') + html = html.replace('

', '*').replace('

', '*') + html = html.replace('

', '**').replace('

', '**') + html = html.replace('

', '**').replace('

', '**') + html = html.replace('', '/').replace('', '/') # the only line breaks we respect is those of ending tags and # breaks - html = html.replace('\n',' ') + html = html.replace('\n', ' ') html = html.replace('
', '\n') html = html.replace('', '\n') html = html.replace('

', '\n\n') @@ -135,12 +128,14 @@ class rpc_proxy(object): return self.rpc.execute(self.dbname, self.user_id, self.passwd, *request) class email_parser(object): - def __init__(self, uid, password, section, email, email_default, dbname, host, port): + def __init__(self, uid, password, model, email, email_default, dbname, host, port): self.rpc = rpc_proxy(uid, password, host=host, port=port, dbname=dbname) try: - self.section_id = int(section) + self.model_id = int(model) + self.model = str(model) except: - self.section_id = self.rpc('crm.case.section', 'search', [('code','=',section)])[0] + self.model_id = self.rpc('ir.model', 'search', [('model', '=', model)])[0] + self.model = str(model) self.email = email self.email_default = email_default self.canal_id = False @@ -156,8 +151,8 @@ class email_parser(object): return {} adr = self.rpc('res.partner.address', 'read', adr_ids, ['partner_id']) return { - 'partner_address_id': adr[0]['id'], - 'partner_id': adr[0].get('partner_id',False) and adr[0]['partner_id'][0] or False + 'partner_address_id': adr[0]['id'], + 'partner_id': adr[0].get('partner_id', False) and adr[0]['partner_id'][0] or False } def _decode_header(self, s): @@ -168,14 +163,13 @@ class email_parser(object): def msg_new(self, msg): message = self.msg_body_get(msg) data = { - 'name': self._decode_header(msg['Subject']), - 'section_id': self.section_id, - 'email_from': self._decode_header(msg['From']), - 'email_cc': self._decode_header(msg['Cc'] or ''), - 'canal_id': self.canal_id, - 'user_id': False, - 'description': message['body'], - 'history_line': [(0, 0, {'description': message['body'], 'email': msg['From'] })], + 'name': self._decode_header(msg['Subject']), + 'email_from': self._decode_header(msg['From']), + 'email_cc': self._decode_header(msg['Cc'] or ''), + 'canal_id': self.canal_id, + 'user_id': False, + 'description': message['body'], + 'history_line': [(0, 0, {'description': message['body'], 'email': msg['From'] })], } try: data.update(self.partner_get(self._decode_header(msg['From']))) @@ -184,21 +178,21 @@ class email_parser(object): netsvc.Logger().notifyChannel('mailgate', netsvc.LOG_ERROR, "%s" % e) try: - id = self.rpc('crm.case', 'create', data) - self.rpc('crm.case','case_open', [id]) - except Exception,e: - if getattr(e,'faultCode','') and 'AccessError' in e.faultCode: + id = self.rpc(self.model, 'create', data) + self.rpc(self.model, 'case_open', [id]) + except Exception, e: + if getattr(e, 'faultCode', '') and 'AccessError' in e.faultCode: e = '\n\nThe Specified user does not have an access to the CRM case.' print e attachments = message['attachment'] for attach in attachments or []: data_attach = { - 'name': str(attach), - 'datas':binascii.b2a_base64(str(attachments[attach])), - 'datas_fname': str(attach), - 'description': 'Mail attachment', - 'res_model': 'crm.case', + 'name': str(attach), + 'datas': binascii.b2a_base64(str(attachments[attach])), + 'datas_fname': str(attach), + 'description': 'Mail attachment', + 'res_model': self.model, 'res_id': id } self.rpc('ir.attachment', 'create', data_attach) @@ -273,22 +267,22 @@ class email_parser(object): body['body'] = body_data data = { - 'description': body['body'], - 'history_line': [(0, 0, {'description': body['body'], 'email': msg['From']})], + 'description': body['body'], + 'history_line': [(0, 0, {'description': body['body'], 'email': msg['From']})], } act = 'case_pending' if 'state' in actions: - if actions['state'] in ['draft','close','cancel','open','pending']: + if actions['state'] in ['draft', 'close', 'cancel', 'open', 'pending']: act = 'case_' + actions['state'] - for k1,k2 in [('cost','planned_cost'),('revenue','planned_revenue'),('probability','probability')]: + for k1, k2 in [('cost', 'planned_cost'), ('revenue', 'planned_revenue'), ('probability', 'probability')]: try: data[k2] = float(actions[k1]) except: pass if 'priority' in actions: - if actions['priority'] in ('1','2','3','4','5'): + if actions['priority'] in ('1', '2', '3', '4', '5'): data['priority'] = actions['priority'] if 'partner' in actions: @@ -299,8 +293,8 @@ class email_parser(object): if uids: data['user_id'] = uids[0][0] - self.rpc('crm.case', act, [id]) - self.rpc('crm.case', 'write', [id], data) + self.rpc(self.model, act, [id]) + self.rpc(self.model, 'write', [id], data) return id def msg_send(self, msg, emails, priority=None): @@ -326,19 +320,19 @@ class email_parser(object): message = self.msg_body_get(msg) body = message['body'] act = 'case_open' - self.rpc('crm.case', act, [id]) + self.rpc(self.model, act, [id]) body2 = '\n'.join(map(lambda l: '> '+l, (body or '').split('\n'))) data = { - 'description':body, - 'history_line': [(0, 0, {'description': body, 'email': msg['From'][:84]})], + 'description':body, + 'history_line': [(0, 0, {'description': body, 'email': msg['From'][:84]})], } - self.rpc('crm.case', 'write', [id], data) + self.rpc(self.model, 'write', [id], data) return id def msg_test(self, msg, case_str): if not case_str: return (False, False) - emails = self.rpc('crm.case', 'emails_get', int(case_str)) + emails = self.rpc(self.model, 'emails_get', int(case_str)) return (int(case_str), emails) def parse(self, msg): @@ -363,12 +357,12 @@ class email_parser(object): msg['Subject'] = '['+str(case_id)+'] '+subject msg['Message-Id'] = '<'+str(time.time())+'-tinycrm-'+str(case_id)+'@'+socket.gethostname()+'>' - emails = self.rpc('crm.case', 'emails_get', case_id) + emails = self.rpc(self.model, 'emails_get', case_id) priority = emails[3] em = [emails[0], emails[1]] + (emails[2] or '').split(',') emails = map(self.email_get, filter(None, em)) - mm = [self._decode_header(msg['From']), self._decode_header(msg['To'])]+self._decode_header(msg.get('Cc','')).split(',') + mm = [self._decode_header(msg['From']), self._decode_header(msg['To'])]+self._decode_header(msg.get('Cc', '')).split(',') msg_mails = map(self.email_get, filter(None, mm)) emails = filter(lambda m: m and m not in msg_mails, emails) @@ -385,10 +379,9 @@ class email_parser(object): if __name__ == '__main__': import sys, optparse parser = optparse.OptionParser( - usage='usage: %prog [options]', + usage='usage: %prog [options]', version='%prog v1.0') - - group = optparse.OptionGroup(parser, "Note", + group = optparse.OptionGroup(parser, "Note", "This program parse a mail from standard input and communicate " "with the Open ERP server for case management in the CRM module.") parser.add_option_group(group) @@ -396,7 +389,7 @@ if __name__ == '__main__': parser.add_option("-u", "--user", dest="userid", help="ID of the user in Open ERP", default=1, type='int') parser.add_option("-p", "--password", dest="password", help="Password of the user in Open ERP", default='admin') parser.add_option("-e", "--email", dest="email", help="Email address used in the From field of outgoing messages") - parser.add_option("-s", "--section", dest="section", help="ID or code of the case section", default="support") + parser.add_option("-o", "--model", dest="model", help="Name or ID of crm model", default="crm.lead") parser.add_option("-m", "--default", dest="default", help="Default eMail in case of any trouble.", default=None) parser.add_option("-d", "--dbname", dest="dbname", help="Database name (default: terp)", default='terp') parser.add_option("--host", dest="host", help="Hostname of the Open ERP Server", default="localhost") @@ -404,15 +397,14 @@ if __name__ == '__main__': (options, args) = parser.parse_args() - parser = email_parser(options.userid, options.password, options.section, options.email, options.default, dbname=options.dbname, host=options.host, port=options.port) + parser = email_parser(options.userid, options.password, options.model, options.email, options.default, dbname=options.dbname, host=options.host, port=options.port) msg_txt = email.message_from_file(sys.stdin) try : parser.parse(msg_txt) - except Exception,e: - if getattr(e,'faultCode','') and 'Connection unexpectedly closed' in e.faultCode: + except Exception, e: + if getattr(e, 'faultCode', '') and 'Connection unexpectedly closed' in e.faultCode: print e # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - From a33d6ea2efdb65c1b1ee3a69d5fc7e3ea5ef6b2c Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Mon, 8 Mar 2010 17:47:50 +0100 Subject: [PATCH 105/157] [FIX] account: Remove an error bzr revid: stephane@openerp.com-20100308164750-cf2nsfy0twp91xxv --- addons/account/report/account_tax_code.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/addons/account/report/account_tax_code.py b/addons/account/report/account_tax_code.py index f406d884ec8..9a72c83fab5 100644 --- a/addons/account/report/account_tax_code.py +++ b/addons/account/report/account_tax_code.py @@ -47,8 +47,6 @@ def _record_to_report_line(record): } class account_tax_code_report(rml_parse.rml_parse): - _name = 'report.account.tax.code.entries' - def __init__(self, cr, uid, name, context): super(account_tax_code_report, self).__init__(cr, uid, name, context=context) self.localcontext.update({ From 04ef9b7795fb8f9a57e49d2e8d6f803465f7224b Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Mon, 8 Mar 2010 17:49:06 +0100 Subject: [PATCH 106/157] [REF] Use the right indentation in the xml file bzr revid: stephane@openerp.com-20100308164906-ids4171vwn3i1v90 --- .../hr_timesheet_sheet_view.xml | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml b/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml index ef1df892668..9d7b7900356 100644 --- a/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml +++ b/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml @@ -197,24 +197,24 @@ search - - - - - - - - - + + + + + + + + + - - - - - + + + +
+
From c8a24fd8622d8488ee1bcfb58280a3268f2a22ad Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Mon, 8 Mar 2010 17:56:48 +0100 Subject: [PATCH 107/157] [REF] hr_timesheet_sheet: Rewrite the domain bzr revid: stephane@openerp.com-20100308165648-24jocdsyc8ctncpe --- addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml b/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml index 9d7b7900356..17c113acd78 100644 --- a/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml +++ b/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml @@ -197,8 +197,8 @@ search - - + + From fa8a34a438eef052b9d349a3e7116306598e0163 Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Mon, 8 Mar 2010 18:20:16 +0100 Subject: [PATCH 108/157] [FIX] Layout bzr revid: stephane@openerp.com-20100308172016-4s6e67sa1vasdqgo --- addons/auction/auction.py | 2 +- addons/event/event_view.xml | 4 ++-- addons/membership/membership_view.xml | 13 +++++-------- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/addons/auction/auction.py b/addons/auction/auction.py index 2955d97b501..0ece4690d9f 100644 --- a/addons/auction/auction.py +++ b/addons/auction/auction.py @@ -63,7 +63,7 @@ class auction_dates(osv.osv): return name _columns = { - 'name': fields.char('Auction date', size=64, required=True), + 'name': fields.char('Auction Name', size=64, required=True), 'expo1': fields.date('First Exposition Day', required=True), 'expo2': fields.date('Last Exposition Day', required=True), 'auction1': fields.date('First Auction Day', required=True), diff --git a/addons/event/event_view.xml b/addons/event/event_view.xml index aaf16a0ad9c..92c08594c11 100644 --- a/addons/event/event_view.xml +++ b/addons/event/event_view.xml @@ -331,14 +331,14 @@ - Events On Registrations + Registration by Event report.event.registration form tree,graph - + diff --git a/addons/membership/membership_view.xml b/addons/membership/membership_view.xml index 2bc1ac1d48d..3e22529332f 100644 --- a/addons/membership/membership_view.xml +++ b/addons/membership/membership_view.xml @@ -97,7 +97,7 @@ - Current members + Members res.partner tree @@ -129,10 +129,10 @@ - Current members + Members res.partner [('membership_state','<>','none'),('membership_state','<>','canceled'),('membership_state','<>','old'),('membership_state','<>','waiting')] - + @@ -148,10 +148,7 @@ - + @@ -189,7 +186,7 @@ - + From 7b748f1905ac55869049e7284f4ccd5cbfbfd39d Mon Sep 17 00:00:00 2001 From: Fabien Pinckaers Date: Mon, 8 Mar 2010 19:44:23 +0100 Subject: [PATCH 109/157] [IMP] improved access rules bzr revid: fp@tinyerp.com-20100308184423-kqflx640x9fk4dwq --- addons/project/security/project_security.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/project/security/project_security.xml b/addons/project/security/project_security.xml index 75bc18922eb..7c34807517a 100644 --- a/addons/project/security/project_security.xml +++ b/addons/project/security/project_security.xml @@ -42,7 +42,7 @@ - ['|','|',('user_id','=',user.id),('project_id.members','=',user.id),('project_id.user_id','=',user.id)] + ['|','|','|',('user_id','=',False),('user_id','=',user.id),('project_id.members','=',user.id),('project_id.user_id','=',user.id)] From 3925b8388fd173219470b86e5d97562d33a8e132 Mon Sep 17 00:00:00 2001 From: Fabien Pinckaers Date: Tue, 9 Mar 2010 09:44:22 +0100 Subject: [PATCH 110/157] [IMP] removed tests in base bzr revid: fp@tinyerp.com-20100309084422-83zbkvap5smz9o7y --- bin/addons/base/res/partner/partner_view.xml | 37 ++------------------ 1 file changed, 2 insertions(+), 35 deletions(-) diff --git a/bin/addons/base/res/partner/partner_view.xml b/bin/addons/base/res/partner/partner_view.xml index 6d8e6b00b19..938ffc83d12 100644 --- a/bin/addons/base/res/partner/partner_view.xml +++ b/bin/addons/base/res/partner/partner_view.xml @@ -252,43 +252,10 @@ form
- -
- HTML Form Example -
- - - - - -
- - - - - - -
- - OpenERP - - - - Tiny - -
-
-
- - + + From 231336c878cef4cd3b8054cbea8ce187c2bf470f Mon Sep 17 00:00:00 2001 From: Julien Thewys Date: Mon, 8 Mar 2010 23:51:58 +0100 Subject: [PATCH 111/157] [FIX] Added TEST logging level to the command line options. bzr revid: jth@openerp.com-20100308225158-wkbgit6epxt3ggga --- bin/tools/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/tools/config.py b/bin/tools/config.py index 23a1666b6c6..bc4aa98b77e 100644 --- a/bin/tools/config.py +++ b/bin/tools/config.py @@ -89,7 +89,7 @@ class configmanager(object): hasSSL = check_ssl() self._LOGLEVELS = dict([(getattr(netsvc, 'LOG_%s' % x), getattr(logging, x)) - for x in ('CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG', 'DEBUG_RPC', 'NOTSET')]) + for x in ('CRITICAL', 'ERROR', 'WARNING', 'INFO', 'TEST', 'DEBUG', 'DEBUG_RPC', 'NOTSET')]) version = "%s %s" % (release.description, release.version) parser = optparse.OptionParser(version=version) From d1c37a80b646be2a38c804e1534ff52423fb8ba2 Mon Sep 17 00:00:00 2001 From: "mra (Open ERP)" Date: Tue, 9 Mar 2010 11:13:27 +0530 Subject: [PATCH 112/157] [FIX] event: Registration by events: you can create a new event since list view, but the one is not editable lp bug: https://launchpad.net/bugs/534493 fixed bzr revid: mra@tinyerp.com-20100309054327-9oynsicikp90ort7 --- addons/event/event_view.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/event/event_view.xml b/addons/event/event_view.xml index 92c08594c11..55dea914ac5 100644 --- a/addons/event/event_view.xml +++ b/addons/event/event_view.xml @@ -338,7 +338,7 @@ - + From 1e8622118905179e2a1f665dabe44d0abad15b4c Mon Sep 17 00:00:00 2001 From: "mra (Open ERP)" Date: Tue, 9 Mar 2010 12:06:03 +0530 Subject: [PATCH 113/157] [FIX] hr_timesheet_sheet: to link attendaces with timesheet (employee now attchaed with resource so change the query) bzr revid: mra@tinyerp.com-20100309063603-3sxf2efirreqoneq --- addons/hr_timesheet_sheet/hr_timesheet_sheet.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/addons/hr_timesheet_sheet/hr_timesheet_sheet.py b/addons/hr_timesheet_sheet/hr_timesheet_sheet.py index a738ee55ace..b7d395ac2e0 100644 --- a/addons/hr_timesheet_sheet/hr_timesheet_sheet.py +++ b/addons/hr_timesheet_sheet/hr_timesheet_sheet.py @@ -482,7 +482,7 @@ class hr_attendance(osv.osv): res[line_id] = False return res - def _sheet_search(self, cursor, user, obj, name, args): + def _sheet_search(self, cursor, user, obj, name, args, context={}): if not len(args): return [] sheet_obj = self.pool.get('hr_timesheet_sheet.sheet') @@ -525,9 +525,11 @@ class hr_attendance(osv.osv): LEFT JOIN (hr_attendance a \ LEFT JOIN hr_employee e \ ON (a.employee_id = e.id)) \ + LEFT JOIN resource_resource r \ + ON (e.resource_id = r.id) \ ON (s.date_to >= date_trunc(\'day\',a.name) \ AND s.date_from <= a.name \ - AND s.user_id = e.user_id) ' + \ + AND s.user_id = r.user_id) ' + \ qu1, qu2) res = cursor.fetchall() if not len(res): From 836636905c9356c7cc0b4133616b66dbe63c061c Mon Sep 17 00:00:00 2001 From: "HDA (OpenERP)" Date: Tue, 9 Mar 2010 12:58:46 +0530 Subject: [PATCH 114/157] [IMP] scrum: improved burndown chart bzr revid: hda@tinyerp.com-20100309072846-5mylm9v12z60lt7m --- addons/scrum/report/__init__.py | 1 - addons/scrum/report/sprint_burndown.py | 16 +++++++++++----- addons/scrum/scrum_report.xml | 6 +----- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/addons/scrum/report/__init__.py b/addons/scrum/report/__init__.py index 2e7bbe68cd0..6112b117959 100644 --- a/addons/scrum/report/__init__.py +++ b/addons/scrum/report/__init__.py @@ -19,7 +19,6 @@ # ############################################################################## -import task_burndown import sprint_burndown # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/scrum/report/sprint_burndown.py b/addons/scrum/report/sprint_burndown.py index 79a549ff81f..cdc837fe96b 100644 --- a/addons/scrum/report/sprint_burndown.py +++ b/addons/scrum/report/sprint_burndown.py @@ -50,9 +50,6 @@ class report_tasks(report_int): cr.execute('select id,date_start,date_stop from scrum_sprint where id=%s', (datas['id'],)) for (id,date_start,date_stop) in cr.fetchall(): - date_to_int = lambda x: int(x.ticks()) - int_to_date = lambda x: '/a60{}'+DateTime.localtime(x).strftime('%d/%m/%Y') - cr.execute('select id from project_task where product_backlog_id in(select id from scrum_product_backlog where sprint_id=%s)', (id,)) ids = map(lambda x: x[0], cr.fetchall()) @@ -71,7 +68,9 @@ class report_tasks(report_int): if (not result) or result[-1]<>res: result.append(res) return result - + + guideline__data=[(datas[0][0],max_hour), (datas[-1][0],0)] + ar = area.T(x_grid_style=line_style.gray50_dash1, x_axis=axis.X(label="Date", format=int_to_date), y_axis=axis.Y(label="Burndown Chart - Planned Hours"), @@ -80,7 +79,14 @@ class report_tasks(report_int): y_range = (0,max_hour), legend = None, size = (680,450)) - ar.add_plot(line_plot.T(data=datas)) + ar.add_plot(line_plot.T(data=guideline__data, line_style=line_style.red)) + ar.add_plot(line_plot.T(data=datas, line_style=line_style.green)) + + entr1 = pychart.legend.Entry(label="guideline", line_style=line_style.red) + entr2 = pychart.legend.Entry(label="burndownchart",line_style=line_style.green) + legend = pychart.legend.T(nr_rows=2, inter_row_sep=5) + legend.draw(ar,[entr1,entr2],canv) + ar.draw(canv) canv.close() diff --git a/addons/scrum/scrum_report.xml b/addons/scrum/scrum_report.xml index a5b3a672986..845a677c356 100644 --- a/addons/scrum/scrum_report.xml +++ b/addons/scrum/scrum_report.xml @@ -1,10 +1,6 @@ - - - - + - From 33c94dc95f8bd9283864d43a15c4c8fc4c836faf Mon Sep 17 00:00:00 2001 From: "noz@tinyerp.com" <> Date: Tue, 9 Mar 2010 13:58:27 +0530 Subject: [PATCH 115/157] [FIX] Wrong context syntax. bzr revid: noz@tinyerp.com-20100309082827-w33bvmg1dsoyzcgu --- addons/account/partner_view.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/account/partner_view.xml b/addons/account/partner_view.xml index 44cf3afde69..1b4603cd8ed 100644 --- a/addons/account/partner_view.xml +++ b/addons/account/partner_view.xml @@ -91,7 +91,7 @@ - + From f6cb964437fb0c5b9eb6bfa959caeaa503f38cf2 Mon Sep 17 00:00:00 2001 From: Julien Thewys Date: Tue, 9 Mar 2010 10:23:46 +0100 Subject: [PATCH 116/157] [IMP] Cleanup. bzr revid: jth@openerp.com-20100309092346-ehfpe1fhe26a1u0a --- bin/tools/yaml_import.py | 96 ++++++++++++++++++++++++++-------------- 1 file changed, 63 insertions(+), 33 deletions(-) diff --git a/bin/tools/yaml_import.py b/bin/tools/yaml_import.py index 8296a205830..7ebc1a39f70 100644 --- a/bin/tools/yaml_import.py +++ b/bin/tools/yaml_import.py @@ -19,8 +19,9 @@ class YamlImportAbortion(Exception): pass class YamlTag(object): - """Superclass for constructors of custom tags defined in yaml file.""" - + """ + Superclass for constructors of custom tags defined in yaml file. + """ def __init__(self, **kwargs): self.__dict__.update(kwargs) def __getitem__(self, key): @@ -45,7 +46,7 @@ class Record(YamlTag): super(Record, self).__init__(**kwargs) class Python(YamlTag): - def __init__(self, model, severity=logging.ERROR, name="NONAME", **kwargs): + def __init__(self, model, severity=logging.ERROR, name="", **kwargs): self.model= model self.severity = severity self.name = name @@ -228,9 +229,10 @@ class TestReport(object): self._report = {} def record(self, success, severity): - """Records the result of an assertion for the failed/success count. - Returns success.""" - + """ + Records the result of an assertion for the failed/success count. + Returns success. + """ if severity in self._report: self._report[severity][success] += 1 else: @@ -249,7 +251,18 @@ class TestReport(object): res.append("end of report (%s assertion(s) checked)" % success + failure) return "\n".join(res) - +class RecordDictWrapper(dict): + """ + Used to pass a record as locals in eval: + records do not strictly behave like dict, so we force them to. + """ + def __init__(self, record): + self.record = record + def __getitem__(self, key): + if key in self.record: + return self.record[key] + return dict.__getitem__(self, key) + class YamlInterpreter(object): def __init__(self, cr, module, id_map, mode, filename, noupdate=False): self.cr = cr @@ -259,10 +272,11 @@ class YamlInterpreter(object): self.filename = filename self.assert_report = TestReport() self.noupdate = noupdate - self.logger = logging.getLogger(logger_channel) + self.logger = logging.getLogger("%s.%s" % (logger_channel, self.module)) self.pool = pooler.get_pool(cr.dbname) self.uid = 1 - self.context = {} + self.context = {} # opererp context + self.eval_context = {'ref': self._ref, '_ref': self._ref} # added '_ref' so that record['ref'] is possible def _ref(self): return lambda xml_id: self.get_id(xml_id) @@ -282,11 +296,13 @@ class YamlInterpreter(object): if module != self.module: module_count = self.pool.get('ir.module.module').search_count(self.cr, self.uid, \ ['&', ('name', '=', module), ('state', 'in', ['installed'])]) - assert module_count == 1, """The ID "%s" refers to an uninstalled module""" % (xml_id,) + assert module_count == 1, 'The ID "%s" refers to an uninstalled module.' % (xml_id,) if len(id) > 64: # TODO where does 64 come from (DB is 128)? should be a constant or loaded form DB self.logger.log(logging.ERROR, 'id: %s is to long (max: 64)', id) def get_id(self, xml_id): + if not xml_id: + raise YamlImportException("The xml_id should be a non empty string.") if isinstance(xml_id, types.IntType): id = xml_id elif xml_id in self.id_map: @@ -302,10 +318,10 @@ class YamlInterpreter(object): self.id_map[xml_id] = id return id - def get_context(self, node, locals_dict): + def get_context(self, node, eval_dict): context = self.context.copy() if node.context: - context.update(eval(node.context, locals_dict)) + context.update(eval(node.context, eval_dict)) return context def isnoupdate(self, node): @@ -318,14 +334,14 @@ class YamlInterpreter(object): self.assert_report.record(False, severity) self.logger.log(severity, msg, *args) if severity >= config['assert_exit_level']: - raise YamlImportAbortion('Severe assertion failure (%s), aborting.' % (severity,)) + raise YamlImportAbortion('Severe assertion failure (%s), aborting.' % logging.getLevelName(severity)) return def _get_assertion_id(self, assertion): if assertion.id: ids = [self.get_id(assertion.id)] elif assertion.search: - q = eval(assertion.search, {'ref': self._ref}) + q = eval(assertion.search, self.eval_context) ids = self.pool.get(assertion.model).search(self.cr, self.uid, q, context=assertion.context) if not ids: raise YamlImportException('Nothing to assert: you must give either an id or a search criteria.') @@ -346,12 +362,14 @@ class YamlInterpreter(object): args = (assertion.string, assertion.count, len(ids)) self._log_assert_failure(assertion.severity, msg, *args) else: - local_context = {'ref': self._ref, '_ref': self._ref} # added '_ref' so that record['ref'] is possible - context = self.get_context(assertion, local_context) + context = self.get_context(assertion, self.eval_context) for id in ids: record = model.browse(self.cr, self.uid, id, context) for test in expressions.get('test', ''): - success = eval(test, local_context, record) + try: + success = eval(test, self.eval_context, RecordDictWrapper(record)) + except Exception, e: + raise YamlImportAbortion(e) if not success: msg = 'Assertion "%s" FAILED\ntest: %s\n' args = (assertion.string, test) @@ -367,6 +385,7 @@ class YamlInterpreter(object): if self.isnoupdate(record) and self.mode != 'init': model = self.get_model(record.model) record_dict = self._create_record(model, fields) + self.logger.debug("RECORD_DICT %s" % record_dict) id = self.pool.get('ir.model.data')._update(self.cr, self.uid, record.model, \ self.module, record_dict, record.id, noupdate=self.isnoupdate(record), mode=self.mode) self.id_map[record.id] = int(id) @@ -412,9 +431,9 @@ class YamlInterpreter(object): code_context = {'self': model, 'cr': self.cr, 'uid': self.uid, 'log': log, 'context': self.context} try: code = compile(statements, self.filename, 'exec') - eval(code, code_context) + eval(code, {'ref': self.get_id}, code_context) except AssertionError, e: - self._log_assert_failure(python.severity, 'Assertion "%s" FAILED in Python code.', python.name) + self._log_assert_failure(python.severity, 'AssertionError in Python code %s: %s', python.name, e) return except Exception, e: raise YamlImportAbortion(e) @@ -437,10 +456,9 @@ class YamlInterpreter(object): if not 'model' in value and (not 'eval' in value or not 'search' in value): raise YamlImportException('You must provide a "model" and an "eval" or "search" to evaluate.') value_model = self.get_model(value['model']) - local_context = {'ref': self._ref, '_ref': self._ref} - local_context['obj'] = lambda x: value_model.browse(self.cr, self.uid, x, context=self.context) + local_context = {'obj': lambda x: value_model.browse(self.cr, self.uid, x, context=self.context)} local_context.update(self.id_map) - id = eval(value['eval'], local_context) + id = eval(value['eval'], self.eval_context, local_context) if workflow.uid is not None: uid = workflow.uid @@ -453,19 +471,17 @@ class YamlInterpreter(object): function, values = node.items()[0] if self.isnoupdate(function) and self.mode != 'init': return - local_context = {'ref': self._ref, '_ref': self._ref} - context = self.get_context(function, local_context) + context = self.get_context(function, self.eval_context) args = [] if function.eval: - args = eval(function.eval, local_context) + args = eval(function.eval, self.eval_context) for value in values: if not 'model' in value and (not 'eval' in value or not 'search' in value): raise YamlImportException('You must provide a "model" and an "eval" or "search" to evaluate.') value_model = self.get_model(value['model']) - local_context = {'ref': self._ref, '_ref': self._ref} - local_context['obj'] = lambda x: value_model.browse(self.cr, self.uid, x, context=context) + local_context = {'obj': lambda x: value_model.browse(self.cr, self.uid, x, context=context)} local_context.update(self.id_map) - id = eval(value['eval'], local_context) + id = eval(value['eval'], self.eval_context, local_context) if id != None: args.append(id) model = self.get_model(function.model) @@ -572,7 +588,7 @@ class YamlInterpreter(object): view_id = False if node.view: view_id = self.get_id(node.view) - context = eval(node.context, {'ref': self._ref, '_ref': self._ref}) + context = eval(node.context, self.eval_context) values = { 'name': node.name, @@ -608,7 +624,7 @@ class YamlInterpreter(object): def process_delete(self, node): ids = [] if len(node.search): - ids = self.pool.get(node.model).search(self.cr, self.uid, eval(node.search)) + ids = self.pool.get(node.model).search(self.cr, self.uid, eval(node.search, self.eval_context)) if len(node.id): try: ids.append(self.get_id(node.id)) @@ -642,7 +658,7 @@ class YamlInterpreter(object): res = {} for fieldname, expression in fields.items(): if isinstance(expression, Eval): - value = eval(expression.expression, {'ref': self._ref, '_ref': self._ref}) + value = eval(expression.expression, self.eval_context) else: value = expression res[fieldname] = value @@ -681,10 +697,18 @@ class YamlInterpreter(object): replace = node.replace or True self.pool.get('ir.model.data').ir_set(self.cr, self.uid, 'action', \ keyword, values['name'], [values['model']], value, replace=replace, isobject=True, xml_id=xml_id) + + def process_none(self): + """ + Empty node or commented node should not pass silently. + """ + self._log_assert_failure(logging.WARNING, "You have an empty block in your tests.") + def process(self, yaml_string): - """Processes a Yaml string. Custom tags are interpreted by 'process_' instance methods.""" - + """ + Processes a Yaml string. Custom tags are interpreted by 'process_' instance methods. + """ is_preceded_by_comment = False for node in yaml.load(yaml_string): is_preceded_by_comment = self._log(node, is_preceded_by_comment) @@ -694,7 +718,11 @@ class YamlInterpreter(object): self.logger.log(logging.ERROR, e) except YamlImportAbortion, e: self.logger.log(logging.ERROR, e) + self.cr.rollback() return + except Exception, e: + self.cr.rollback() + raise e def _process_node(self, node): if is_comment(node): @@ -729,6 +757,8 @@ class YamlInterpreter(object): self.process_function(node) else: self.process_function({node: []}) + elif node is None: + self.process_none() else: raise YamlImportException("Can not process YAML block: %s" % node) From 03bce49375554543318d486a6829cc7f09c16aa9 Mon Sep 17 00:00:00 2001 From: "noz@tinyerp.com" <> Date: Tue, 9 Mar 2010 15:06:01 +0530 Subject: [PATCH 117/157] [FIX] Correction in context syntax. bzr revid: noz@tinyerp.com-20100309093601-bdkrn8h0dxyzvzwz --- addons/account/partner_view.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/account/partner_view.xml b/addons/account/partner_view.xml index 1b4603cd8ed..0b2291224a9 100644 --- a/addons/account/partner_view.xml +++ b/addons/account/partner_view.xml @@ -91,7 +91,7 @@ - + From 46838596d42a71299d819d6dda90a6a65ffe7830 Mon Sep 17 00:00:00 2001 From: "mra (Open ERP)" Date: Tue, 9 Mar 2010 15:41:24 +0530 Subject: [PATCH 118/157] [IMP] hr_timesheet_sheet: Add group by on timesheet (Departement and user) bzr revid: mra@tinyerp.com-20100309101124-c75o9ay48gel1bma --- addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml b/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml index 17c113acd78..c2fbccca5cd 100644 --- a/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml +++ b/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml @@ -214,6 +214,11 @@ help="My Departments Timesheet"/> + + + + + From 236aec74aff4d9992a739e6776bf871eca652816 Mon Sep 17 00:00:00 2001 From: Julien Thewys Date: Tue, 9 Mar 2010 10:41:32 +0100 Subject: [PATCH 119/157] [IMP] Completed tests. bzr revid: jth@openerp.com-20100309094132-x4ycbziga4kqflyj --- addons/account/test/price_accuracy00.yaml | 64 ---------------- addons/account/test/price_accuracy00.yml | 92 +++++++++++++++++++++++ 2 files changed, 92 insertions(+), 64 deletions(-) delete mode 100644 addons/account/test/price_accuracy00.yaml create mode 100644 addons/account/test/price_accuracy00.yml diff --git a/addons/account/test/price_accuracy00.yaml b/addons/account/test/price_accuracy00.yaml deleted file mode 100644 index a825700e4b7..00000000000 --- a/addons/account/test/price_accuracy00.yaml +++ /dev/null @@ -1,64 +0,0 @@ -- | - Tax Scenario: - In order to check that the accounting entries and tax engine works - efficiently with all kind of price accuracies we run this test scenario. -- - Given the price accuracy for the account module is configured with two - digits -- - !record {model: decimal.precision, id: product.decimal_account}: - digits: 2 -- - And we have a tax defined -- - !record {model: account.tax, id: tax196}: - name: Tax 19.6% - amount: &tax 0.196 -- - And we define an invoice with one invoice line with a tax of *tax -- - !record {model: account.invoice, id: invoice1}: &invoice - name: Precision Test - type: out_invoice - partner_id: base.xxx - address_contact_id: - address_invoice_id: - account_id: - invoice_lines: - - product_qty: &qty 11.11 - product_uom: product.product_unit - price_unit: &price 12.34 -- - When I press on the CREATE button on the invoice to open it. -- - # to be completed -- - Then I should see an account entry linked to this invoice. -- - !record {model: account.invoice, id: invoice1}: - test: bool(move_id) -- - # This is not working, find a way to do that in YAML, *qty is not - # interpreted because it's not a node. - And this account entry must have a credit equals to 163.70€ which is - equal to *qty x *price x (1 + *tax) -- - !record {model: account.invoice, id: invoice1}: - test: abs(move_id.credit - 163.70) < 0.000001 -- - And this account entry must have a credit equals to the debit -- - !record {model: account.invoice, id: invoice1}: - test: abs(move_id.debit - move_id.credit) < 0.000001 -- - Then, I change the precision of numbers to 3 digits. -- - !record {model: decimal.precision, id: product.decimal_account}: - digits: 3 -- - And I create another invoice with the same content. -- - !record {model: account.invoice, id: invoice2}: - *invoice -- - to be completed, etc. diff --git a/addons/account/test/price_accuracy00.yml b/addons/account/test/price_accuracy00.yml new file mode 100644 index 00000000000..48b5ceca35b --- /dev/null +++ b/addons/account/test/price_accuracy00.yml @@ -0,0 +1,92 @@ +- | + Tax Scenario: + In order to check that the accounting entries and tax engine works + efficiently with all kind of price accuracies we run this test scenario. +- + Given the price accuracy for the account module is configured with two + digits +- + !record {model: decimal.precision, id: product.decimal_account}: + digits: 2 +- + And we have a tax defined +- + !record {model: account.tax, id: tax196}: + name: Tax 19.6% + amount: &tax 0.196 + account_collected_id: account.a_recv + account_paid_id: account.a_recv +- + And we define an invoice with one invoice line with a tax of *tax +- + !record {model: account.invoice, id: invoice1}: &invoice + name: Precision Test + type: out_invoice + partner_id: base.res_partner_2 + address_invoice_id: base.res_partner_address_1 + account_id: account.a_recv + date_invoice: !eval time.strftime('%Y-%m-%d') + invoice_line: + - product_id: product.product_product_pc1 + quantity: &qty 11.11 + account_id: account.a_sale + uos_id: product.product_uom_unit + price_unit: &price 12.34 + name: test + invoice_line_tax_id: + - tax196 +- + When I press on the CREATE button on the invoice to open it. +- + !python {model: account.invoice}: | + self.action_move_create(cr, uid, [ref("invoice1")]) +- + Then I should see an account entry linked to this invoice. +- + !assert {model: account.invoice, id: invoice1}: + test: + - bool(move_id) +- + # This is not working, find a way to do that in YAML, *qty is not + # interpreted because it's not a node. + And this account entry must have a credit equals to 163.70€ which is + equal to *qty x *price x (1 + *tax) +- + !assert {model: account.invoice, id: invoice1}: + test: + - abs(sum(x.credit for x in move_id.line_id) - 163.97) < 0.000001 +- + And this account entry must have a credit equals to the debit +- + !assert {model: account.invoice, id: invoice1}: + test: + - abs(sum(x.credit - x.debit for x in move_id.line_id)) < 0.000001 +- + Then, I change the precision of numbers to 3 digits. +- + !record {model: decimal.precision, id: product.decimal_account}: + digits: 3 +- + And I create another invoice with the same content. +- + !record {model: account.invoice, id: invoice2}: + *invoice +- + When I press on the CREATE button on the invoice to open it. +- + !python {model: account.invoice}: | + self.action_move_create(cr, uid, [ref("invoice2")]) +- + !python {model: account.invoice}: | + invoice = self.browse(cr, uid, ref("invoice2")) + log(sum(x.credit for x in invoice.move_id.line_id)) + assert (sum(x.credit for x in invoice.move_id.line_id) - 163.968) < 0.000001, "Pas bon !!!" +- + !assert {model: account.invoice, id: invoice2}: + test: + - abs(sum(x.credit for x in move_id.line_id) - 163.968) < 0.000001 +- + !assert {model: account.invoice, id: invoice2}: + test: + - abs(sum(x.credit - x.debit for x in move_id.line_id)) < 0.000001 + From 0129ecbcf76f5a2076ddf9278fda4e23b70b175e Mon Sep 17 00:00:00 2001 From: Fabien Pinckaers Date: Tue, 9 Mar 2010 10:56:19 +0100 Subject: [PATCH 120/157] [IMP] project issue form bzr revid: fp@tinyerp.com-20100309095619-r2d676mg94jhsc1u --- addons/crm/crm.py | 3 +- addons/project_issue/project_issue.py | 28 +-- addons/project_issue/project_issue_view.xml | 188 +++++++++----------- 3 files changed, 98 insertions(+), 121 deletions(-) diff --git a/addons/crm/crm.py b/addons/crm/crm.py index 8bc6f56117d..ce318aeca4f 100644 --- a/addons/crm/crm.py +++ b/addons/crm/crm.py @@ -224,6 +224,7 @@ class crm_case(osv.osv): 'email_from': fields.char('Email', size=128, help="These people will receive email."), 'email_cc': fields.text('Watchers Emails', size=252 , help="These people will receive a copy of the future" \ " communication between partner and users by email"), + 'probability': fields.float('Probability'), 'email_last': fields.function(_email_last, method=True, string='Latest E-Mail', type='text'), 'partner_id': fields.many2one('res.partner', 'Partner'), @@ -318,7 +319,7 @@ class crm_case(osv.osv): if section in s: st = case.stage_id.id or False s[section] = dict([(v, k) for (k, v) in s[section].iteritems()]) - if st in s[section]: + if st and st in s[section]: stage_value = self.pool.get('crm.case.stage').read(cr, uid,s[section][st] ,['probability'], context) self.write(cr, uid, [case.id], {'stage_id': s[section][st],'probability':stage_value['probability']}) return True diff --git a/addons/project_issue/project_issue.py b/addons/project_issue/project_issue.py index f0441c0263c..48492f44675 100644 --- a/addons/project_issue/project_issue.py +++ b/addons/project_issue/project_issue.py @@ -29,10 +29,8 @@ from tools.translate import _ import tools from osv import fields,osv,orm from osv.orm import except_orm - from crm import crm - class project_issue(osv.osv): _name = "project.issue" _description = "Project Issue" @@ -45,30 +43,22 @@ class project_issue(osv.osv): 'ref2' : fields.reference('Reference 2', selection=crm._links_get, size=128), 'canal_id': fields.many2one('res.partner.canal', 'Channel',help="The channels represent the different communication modes available with the customer." \ " With each commercial opportunity, you can indicate the canall which is this opportunity source."), - 'planned_revenue': fields.float('Planned Revenue'), - 'planned_cost': fields.float('Planned Costs'), - 'som': fields.many2one('res.partner.som', 'State of Mind', help="The minds states allow to define a value scale which represents" \ - "the partner mentality in relation to our services.The scale has" \ - "to be created with a factor for each level from 0 (Very dissatisfied) to 10 (Extremely satisfied)."), 'categ_id': fields.many2one('crm.case.categ','Category', domain="[('object_id.model', '=', 'crm.project.bug')]"), - 'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority'), - 'type_id': fields.many2one('crm.case.resource.type', 'Bug Type', domain="[('object_id.model', '=', 'project.issue')]"), - + 'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Severity'), + 'type_id': fields.many2one('crm.case.resource.type', 'Version', domain="[('object_id.model', '=', 'project.issue')]"), 'partner_name': fields.char("Employee's Name", size=64), 'partner_mobile': fields.char('Mobile', size=32), 'partner_phone': fields.char('Phone', size=32), 'stage_id': fields.many2one ('crm.case.stage', 'Stage', domain="[('object_id.model', '=', 'project.issue')]"), 'project_id':fields.many2one('project.project', 'Project'), 'duration': fields.float('Duration'), - 'probability': fields.float('Probability (%)'), 'task_id': fields.many2one('project.task', 'Task', domain="[('project_id','=',project_id)]") } - def _get_project(self, cr, uid, context): user = self.pool.get('res.users').browse(cr,uid,uid, context=context) if user.context_project_id: return user.context_project_id - return False + return False def _convert(self, cr, uid, ids, xml_id, context=None): data_obj = self.pool.get('ir.model.data') @@ -79,7 +69,7 @@ class project_issue(osv.osv): if categ_id: self.write(cr, uid, ids, {'categ_id': categ_id}) return True - + def convert_to_feature(self, cr, uid, ids, context=None): return self._convert(cr, uid, ids, 'feature_request_categ', context=context) @@ -92,14 +82,10 @@ class project_issue(osv.osv): stage = self.pool.get('crm.case.stage').browse(cr, uid, stage_id, context) if not stage.on_change: return {'value':{}} - return {'value':{'probability':stage.probability}} + return {'value':{}} _defaults = { - 'project_id':_get_project, - 'probability':lambda *a:0.0, - 'planned_cost':lambda *a:0.0, - 'planned_revenue':lambda *a:0.0, - } - + 'project_id':_get_project, + } project_issue() diff --git a/addons/project_issue/project_issue_view.xml b/addons/project_issue/project_issue_view.xml index 305db272f4c..2a82ef783d3 100644 --- a/addons/project_issue/project_issue_view.xml +++ b/addons/project_issue/project_issue_view.xml @@ -11,22 +11,22 @@ Issue Categories crm.case.categ form - - [('object_id.model', '=', 'project.issue')] - {'object_id':'project.issue'} + + [('object_id.model', '=', 'project.issue')] + {'object_id':'project.issue'} # ------------------------------------------------------ - # Stage - # ------------------------------------------------------ - - Issue Stages - crm.case.stage - form - - [('object_id.model', '=', 'project.issue')] - {'object_id':'project.issue'} - - + # Stage + # ------------------------------------------------------ + + Issue Stages + crm.case.stage + form + + [('object_id.model', '=', 'project.issue')] + {'object_id':'project.issue'} + + Project Issue Tracker Form @@ -34,50 +34,38 @@ form - - - + + + + - - -