From 9d3512c3126c6cc98c7fe212e4bb48564fce5a10 Mon Sep 17 00:00:00 2001 From: "uco (OpenERP)" Date: Fri, 5 Mar 2010 19:45:00 +0530 Subject: [PATCH 01/52] [ADD]: Added remaining object in security file. bzr revid: uco@tinyerp.co.in-20100305141500-akzd0p22yhvzxkaw --- addons/crm/security/ir.model.access.csv | 2 ++ 1 file changed, 2 insertions(+) diff --git a/addons/crm/security/ir.model.access.csv b/addons/crm/security/ir.model.access.csv index e6c961a4c35..c3888951d4c 100644 --- a/addons/crm/security/ir.model.access.csv +++ b/addons/crm/security/ir.model.access.csv @@ -31,3 +31,5 @@ "access_crm_lead_report_user","crm.lead.report","model_crm_lead_report","crm.group_crm_user",1,0,0,0 "access_crm_phonecall_report_user","crm.phonecall.report","model_crm_phonecall_report","crm.group_crm_user",1,0,0,0 "access_crm_opportunity_report_user","crm.opportunity.report","model_crm_opportunity_report","crm.group_crm_user",1,0,0,0 +"access_report_crm_case_service_dashboard","report.crm.case.service.dashboard","model_report_crm_case_service_dashboard","crm.group_crm_user",1,0,0,0 + From a17092ba94b1be75c76e1cc691674c8809b213c1 Mon Sep 17 00:00:00 2001 From: Julien Thewys Date: Sun, 7 Mar 2010 17:49:07 +0100 Subject: [PATCH 02/52] [REF] Renamed file and moved import statement. bzr revid: jth@openerp.com-20100307164907-t1cevokp7u1zz2tx --- bin/tools/__init__.py | 1 - bin/tools/convert.py | 1 + bin/tools/{yaml_test.py => yaml_import.py} | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename bin/tools/{yaml_test.py => yaml_import.py} (99%) diff --git a/bin/tools/__init__.py b/bin/tools/__init__.py index 78c77edf394..9b7bb84a57f 100644 --- a/bin/tools/__init__.py +++ b/bin/tools/__init__.py @@ -24,7 +24,6 @@ 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/convert.py b/bin/tools/convert.py index db3edf380f7..2e16237f50a 100644 --- a/bin/tools/convert.py +++ b/bin/tools/convert.py @@ -37,6 +37,7 @@ import netsvc import osv import pooler from config import config +from yaml_import import convert_yaml_import class ConvertError(Exception): def __init__(self, doc, orig_excpt): diff --git a/bin/tools/yaml_test.py b/bin/tools/yaml_import.py similarity index 99% rename from bin/tools/yaml_test.py rename to bin/tools/yaml_import.py index b4d23376c7a..8602afd58cb 100644 --- a/bin/tools/yaml_test.py +++ b/bin/tools/yaml_import.py @@ -368,7 +368,7 @@ class YamlInterpreter(object): 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.module, record_dict, record.id, noupdate=self.isnoupdate(record), mode=self.mode) self.id_map[record.id] = int(id) if config.get('import_partial', False): self.cr.commit() From f9e6517ee6ec96cdf467f9198261dfc25d730d2e Mon Sep 17 00:00:00 2001 From: Julien Thewys Date: Sun, 7 Mar 2010 22:18:33 +0100 Subject: [PATCH 03/52] [REF] Uses logging.getLogger instead of the to be deprecated netsvc.Logger . bzr revid: jth@openerp.com-20100307211833-j4b6x8pcbirs0sxk --- bin/tools/yaml_import.py | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/bin/tools/yaml_import.py b/bin/tools/yaml_import.py index 8602afd58cb..2c334c9cd3c 100644 --- a/bin/tools/yaml_import.py +++ b/bin/tools/yaml_import.py @@ -31,7 +31,7 @@ class YamlTag(object): 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): + def __init__(self, model, id, severity=logging.ERROR, string="NONAME", **kwargs): self.model = model self.id = id self.severity = severity @@ -45,7 +45,7 @@ class Record(YamlTag): super(Record, self).__init__(**kwargs) class Python(YamlTag): - def __init__(self, model, severity=netsvc.LOG_ERROR, name="NONAME", **kwargs): + def __init__(self, model, severity=logging.ERROR, name="NONAME", **kwargs): self.model= model self.severity = severity self.name = name @@ -259,7 +259,7 @@ class YamlInterpreter(object): self.filename = filename self.assert_report = TestReport() self.noupdate = noupdate - self.logger = netsvc.Logger() + self.logger = logging.getLogger(logger_channel) self.pool = pooler.get_pool(cr.dbname) self.uid = 1 self.context = {} @@ -284,7 +284,7 @@ class YamlInterpreter(object): ['&', ('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,)) + self.logger.log(logging.ERROR, 'id: %s is to long (max: 64)', id) def get_id(self, xml_id): if isinstance(xml_id, types.IntType): @@ -316,8 +316,8 @@ class YamlInterpreter(object): 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']: + self.logger.log(severity, msg, *args) + if severity >= config['assert_exit_level']: raise YamlImportAbortion('Severe assertion failure (%s), aborting.' % (severity,)) return @@ -404,8 +404,8 @@ class YamlInterpreter(object): 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) + def log(msg, *args): + self.logger.log(logging.TEST, msg, *args) python, statements = node.items()[0] model = self.get_model(python.model) statements = statements.replace("\r\n", "\n") @@ -414,9 +414,7 @@ class YamlInterpreter(object): 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) + self._log_assert_failure(python.severity, 'Assertion "%s" FAILED in Python code.', python.name) return except Exception, e: raise YamlImportAbortion(e) @@ -693,9 +691,9 @@ class YamlInterpreter(object): try: self._process_node(node) except YamlImportException, e: - self.logger.notifyChannel(logger_channel, netsvc.LOG_ERROR, e) + self.logger.log(logging.ERROR, e) except YamlImportAbortion, e: - self.logger.notifyChannel(logger_channel, netsvc.LOG_ERROR, e) + self.logger.log(logging.ERROR, e) return def _process_node(self, node): @@ -737,14 +735,14 @@ class YamlInterpreter(object): 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) + self.logger.log(logging.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) + msg = "Creating %s\n with %s" + args = node.items()[0] + self.logger.log(logging.TEST, msg, *args) else: - self.logger.notifyChannel(logger_channel, netsvc.LOG_TEST, node) + self.logger.log(logging.TEST, node) else: is_preceded_by_comment = False return is_preceded_by_comment From e5f3ead146ae9fd9acbfacb79d41010b3ab19718 Mon Sep 17 00:00:00 2001 From: "rpa (Open ERP)" Date: Mon, 8 Mar 2010 10:53:33 +0530 Subject: [PATCH 04/52] [FIX]: base_calendar: Fixed some minor problems for delegation bzr revid: rpa@openerp.co.in-20100308052333-tvn2nvxnc1a3bby6 --- addons/base_calendar/base_calendar.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/addons/base_calendar/base_calendar.py b/addons/base_calendar/base_calendar.py index 18b27820766..8bdfd4019d6 100644 --- a/addons/base_calendar/base_calendar.py +++ b/addons/base_calendar/base_calendar.py @@ -226,7 +226,9 @@ class invite_attendee_wizard(osv.osv_memory): if type == 'internal': user_obj = self.pool.get('res.users') - for user_id in datas.get('user_ids', []): + if not datas.get('user_ids'): + raise osv.except_osv(_('Error!'), ("Please select any User")) + for user_id in datas.get('user_ids'): user = user_obj.browse(cr, uid, user_id) vals.update({'user_id': user_id, 'email': user.address_id.email}) @@ -251,10 +253,6 @@ class invite_attendee_wizard(osv.osv_memory): 'parent_ids' : [(4, att.id)], 'ref': att.ref }) - att_id = att_obj.create(cr, uid, vals) - if model_field: - obj.write(cr, uid, res_obj.id, {model_field: [(4, att_id)]}) - if datas.get('send_mail'): if not mail_to: name = map(lambda x: x[1], filter(lambda x: type==x[0], \ @@ -263,7 +261,9 @@ class invite_attendee_wizard(osv.osv_memory): Address to send mail") % (name[0])) att_obj._send_mail(cr, uid, [att_id], mail_to, \ email_from=tools.config.get('email_from', False)) - + att_id = att_obj.create(cr, uid, vals) + if model_field: + obj.write(cr, uid, res_obj.id, {model_field: [(4, att_id)]}) return {} @@ -313,12 +313,14 @@ class calendar_attendee(osv.osv): if name == 'delegated_to': todata = [] for parent in attdata.parent_ids: - todata.append('MAILTO:' + parent.email) + if parent.email: + todata.append('MAILTO:' + parent.email) result[id][name] = ', '.join(todata) if name == 'delegated_from': fromdata = [] for child in attdata.child_ids: - fromdata.append('MAILTO:' + child.email) + if child.email: + fromdata.append('MAILTO:' + child.email) result[id][name] = ', '.join(fromdata) if name == 'event_date': if attdata.ref: From 1f8c9782862debe499fc96dddf74b07ad2c13ce1 Mon Sep 17 00:00:00 2001 From: "sbh (Open ERP)" Date: Mon, 8 Mar 2010 11:30:48 +0530 Subject: [PATCH 05/52] [Add] add wizard of crm_phonecall2phonecall bzr revid: sbh@tinyerp.com-20100308060048-a5qqd4zf3qwdfvek --- addons/crm/__terp__.py | 4 +- addons/crm/wizard/__init__.py | 1 + addons/crm/wizard/crm_phonecall2phonecall.py | 73 +++++++++++++++++++ addons/crm/wizard/crm_phonecall2phonecall.xml | 33 +++++++++ 4 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 addons/crm/wizard/crm_phonecall2phonecall.py create mode 100644 addons/crm/wizard/crm_phonecall2phonecall.xml diff --git a/addons/crm/__terp__.py b/addons/crm/__terp__.py index 994f11f3212..7a248005578 100644 --- a/addons/crm/__terp__.py +++ b/addons/crm/__terp__.py @@ -61,8 +61,10 @@ between mails and Open ERP.""", ], 'update_xml': [ + 'wizard/crm_phonecall2phonecall.xml', 'crm_wizard.xml', - 'crm_view.xml', + 'crm_view.xml', + 'crm_action_rule_view.xml', 'crm_lead_wizard.xml', 'crm_lead_view.xml', diff --git a/addons/crm/wizard/__init__.py b/addons/crm/wizard/__init__.py index 62be2041d98..73c4596a145 100644 --- a/addons/crm/wizard/__init__.py +++ b/addons/crm/wizard/__init__.py @@ -26,6 +26,7 @@ import crm_phonecall_wizard import wizard_crm_send_email import wizard_crm_new_send_email import wizard_history_event +import crm_phonecall2phonecall # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/crm/wizard/crm_phonecall2phonecall.py b/addons/crm/wizard/crm_phonecall2phonecall.py new file mode 100644 index 00000000000..81f11d2f95b --- /dev/null +++ b/addons/crm/wizard/crm_phonecall2phonecall.py @@ -0,0 +1,73 @@ +# -*- encoding: utf-8 -*- +############################################################################################ +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved +# Copyright (C) 2008-2009 AJM Technologies S.A. (. +# +############################################################################################ +############################################################################################ + +from osv import osv, fields +import netsvc +import time +import tools +import mx.DateTime +from tools import config +from tools.translate import _ +import tools + +class crm_phonecall2phonecall(osv.osv_memory): + _name = 'crm.phonecall2phonecall' + _description = 'Phonecall To Phonecall' + + def action_cancel(self, cr, uid, ids, context=None): + return {'type':'ir.actions.act_window_close'} + + def action_apply(self, cr, uid, ids, context=None): + this = self.browse(cr, uid, ids)[0] + + record_id = context and context.get('record_id', False) or False + print ">>>>>>>>>>",record_id + values={} + values['name']=this.name + values['user_id']=this.user_id and this.user_id.id + values['category_id']=this.category_id and this.category_id.id + values['section_id']=this.section_id and this.section_id.id or False, + values['description']=this.notes + phonecall_proxy = self.pool.get('crm.phonecall') + phonecall_id = phonecall_proxy.create(cr, uid, values, context=context) + value = { + 'name': _('Phone Call'), + 'view_type': 'form', + 'view_mode': 'form', + 'res_model': 'crm.phonecall', + 'view_id': False, + 'type': 'ir.actions.act_window', + 'res_id': phonecall_id + } + return value + + _columns = { + 'name' : fields.char('Name', size=64, required=True, select=1), + 'user_id' : fields.many2one('res.users',"Assign To"), + 'deadline': fields.datetime('Deadline', readonly=True), + 'category_id' : fields.many2one('crm.case.categ','Category',domain="[('object_id.model', '=', ''crm.phonecall')]"), + 'section_id':fields.many2one('crm.case.section','Section Id'), + 'notes' : fields.text('Notes'), + } +crm_phonecall2phonecall() \ No newline at end of file diff --git a/addons/crm/wizard/crm_phonecall2phonecall.xml b/addons/crm/wizard/crm_phonecall2phonecall.xml new file mode 100644 index 00000000000..ea30368243e --- /dev/null +++ b/addons/crm/wizard/crm_phonecall2phonecall.xml @@ -0,0 +1,33 @@ + + + + + crm.phonecall2phonecall.form + crm.phonecall2phonecall + form + +
+ + + + + + + + + + + + + + + + +
+ + OpenERP + + + + Tiny + +
+ +
+ - From b5056e2c9f4494c95fdcd680674d2084231b0f38 Mon Sep 17 00:00:00 2001 From: "uco (OpenERP)" Date: Mon, 8 Mar 2010 18:04:34 +0530 Subject: [PATCH 19/52] [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 20/52] [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 21/52] [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 22/52] [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 23/52] [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 24/52] [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 25/52] [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 26/52] [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 27/52] [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 28/52] [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 29/52] [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 30/52] [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 d1c37a80b646be2a38c804e1534ff52423fb8ba2 Mon Sep 17 00:00:00 2001 From: "mra (Open ERP)" Date: Tue, 9 Mar 2010 11:13:27 +0530 Subject: [PATCH 32/52] [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 33/52] [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 34/52] [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 35/52] [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 03bce49375554543318d486a6829cc7f09c16aa9 Mon Sep 17 00:00:00 2001 From: "noz@tinyerp.com" <> Date: Tue, 9 Mar 2010 15:06:01 +0530 Subject: [PATCH 36/52] [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 37/52] [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 38/52] [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 45ea2256a5703846a11f1d90841566d0ec277070 Mon Sep 17 00:00:00 2001 From: "mra (Open ERP)" Date: Tue, 9 Mar 2010 17:22:35 +0530 Subject: [PATCH 39/52] [IMP] project_long_term: merge improvements from rvo bzr revid: mra@tinyerp.com-20100309115235-qkv9c4uuskgraqrz --- addons/project_long_term/__terp__.py | 4 +- addons/project_long_term/project.py | 267 +++++++++--------- addons/project_long_term/project_demo.xml | 1 + addons/project_long_term/project_view.xml | 43 ++- ...hase_workflow.xml => project_workflow.xml} | 52 ++-- addons/project_long_term/wizard/__init__.py | 2 +- .../wizard/compute_phases_date.py | 129 +++++---- .../wizard/compute_tasks_date.py | 97 ++++--- .../wizard/project_resource.py | 81 ------ .../wizard/schedule_tasks.py | 92 +++--- .../wizard/working_calendar.py | 114 ++++++++ 11 files changed, 487 insertions(+), 395 deletions(-) rename addons/project_long_term/{project_phase_workflow.xml => project_workflow.xml} (71%) delete mode 100644 addons/project_long_term/wizard/project_resource.py create mode 100644 addons/project_long_term/wizard/working_calendar.py diff --git a/addons/project_long_term/__terp__.py b/addons/project_long_term/__terp__.py index 75c73396549..5367ff02567 100644 --- a/addons/project_long_term/__terp__.py +++ b/addons/project_long_term/__terp__.py @@ -26,7 +26,7 @@ "author" : "Tiny", "website" : "http://www.openerp.com", "category" : "Generic Modules/Projects & Services", - "depends" : ["project","resource"], + "depends" : ["project", "resource"], "description": """Long Term Project management module that track planning, scheduling, resources allocation. """, "init_xml" : [], @@ -35,7 +35,7 @@ #"security/ir.model.access.csv", "project_wizard.xml" , "project_view.xml", - "project_phase_workflow.xml" + "project_workflow.xml" ], 'installable': True, 'active': False, diff --git a/addons/project_long_term/project.py b/addons/project_long_term/project.py index 9c87f3048c2..595d3c82140 100644 --- a/addons/project_long_term/project.py +++ b/addons/project_long_term/project.py @@ -30,25 +30,21 @@ class project_phase(osv.osv): _name = "project.phase" _description = "Project Phase" - - def _check_recursion(self,cr,uid,ids): + def _check_recursion(self, cr, uid, ids): obj_self = self.browse(cr, uid, ids[0]) prev_ids = obj_self.previous_phase_ids next_ids = obj_self.next_phase_ids - #it should nither be in prev_ids nor in next_ids + # it should nither be in prev_ids nor in next_ids if (obj_self in prev_ids) or (obj_self in next_ids): return False ids = [id for id in prev_ids if id in next_ids] - - #both prev_ids and next_ids must be unique + # both prev_ids and next_ids must be unique if ids: return False - #unrelated project - + # unrelated project prev_ids = [rec.id for rec in prev_ids] next_ids = [rec.id for rec in next_ids] - - #iter prev_ids + # iter prev_ids while prev_ids: cr.execute('select distinct prv_phase_id from project_phase_rel where next_phase_id in ('+','.join(map(str, prev_ids))+')') prv_phase_ids = filter(None, map(lambda x: x[0], cr.fetchall())) @@ -58,8 +54,7 @@ class project_phase(osv.osv): if ids: return False prev_ids = prv_phase_ids - - #iter next_ids + # iter next_ids while next_ids: cr.execute('select distinct next_phase_id from project_phase_rel where prv_phase_id in ('+','.join(map(str, next_ids))+')') next_phase_ids = filter(None, map(lambda x: x[0], cr.fetchall())) @@ -72,21 +67,21 @@ class project_phase(osv.osv): return True def _check_dates(self, cr, uid, ids): - phase = self.read(cr, uid, ids[0],['date_start','date_end']) + phase = self.read(cr, uid, ids[0], ['date_start', 'date_end']) if phase['date_start'] and phase['date_end']: if phase['date_start'] > phase['date_end']: return False return True def _check_constraint_start(self, cr, uid, ids): - phase = self.read(cr, uid, ids[0],['date_start','constraint_date_start']) + phase = self.read(cr, uid, ids[0], ['date_start', 'constraint_date_start']) if phase['date_start'] and phase['constraint_date_start']: if phase['date_start'] < phase['constraint_date_start']: return False return True def _check_constraint_end(self, cr, uid, ids): - phase = self.read(cr, uid, ids[0],['date_end','constraint_date_end']) + phase = self.read(cr, uid, ids[0], ['date_end', 'constraint_date_end']) if phase['date_end'] and phase['constraint_date_end']: if phase['date_end'] > phase['constraint_date_end']: return False @@ -102,74 +97,76 @@ class project_phase(osv.osv): 'next_phase_ids': fields.many2many('project.phase', 'project_phase_rel', 'prv_phase_id', 'next_phase_id', 'Next Phases'), 'previous_phase_ids': fields.many2many('project.phase', 'project_phase_rel', 'next_phase_id', 'prv_phase_id', 'Previous Phases'), 'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of phases."), - 'duration': fields.float('Duration',required=True), - 'product_uom': fields.many2one('product.uom', 'Duration UoM',required=True, help="UoM (Unit of Measure) is the unit of measurement for Duration"), + 'duration': fields.float('Duration', required=True), + 'product_uom': fields.many2one('product.uom', 'Duration UoM', required=True, help="UoM (Unit of Measure) is the unit of measurement for Duration"), 'task_ids': fields.one2many('project.task', 'phase_id', "Project Tasks"), 'resource_ids': fields.one2many('project.resource.allocation', 'phase_id', "Project Resources"), 'responsible_id':fields.many2one('res.users', 'Responsible'), - 'state': fields.selection([('draft', 'Draft'),('open', 'In Progress'),('pending', 'Pending'), ('cancelled', 'Cancelled'), ('done', 'Done')], 'State', readonly=True, required=True, + 'state': fields.selection([('draft', 'Draft'), ('open', 'In Progress'), ('pending', 'Pending'), ('cancelled', 'Cancelled'), ('done', 'Done')], 'State', readonly=True, required=True, help='If the phase is created the state \'Draft\'.\n If the phase is started, the state becomes \'In Progress\'.\n If review is needed the phase is in \'Pending\' state.\ \n If the phase is over, the states is set to \'Done\'.') - } - _defaults = { 'responsible_id': lambda obj,cr,uid,context: uid, 'date_start': lambda *a: time.strftime('%Y-%m-%d'), 'state': lambda *a: 'draft', 'sequence': lambda *a: 10, } - _order = "name" _constraints = [ - (_check_recursion,'Error ! Loops In Phases Not Allowed',['next_phase_ids','previous_phase_ids']), + (_check_recursion,'Error ! Loops In Phases Not Allowed',['next_phase_ids', 'previous_phase_ids']), (_check_dates, 'Error! Phase start-date must be lower then Phase end-date.', ['date_start', 'date_end']), (_check_constraint_start, 'Error! Phase must start-after Constraint Start Date.', ['date_start', 'constraint_date_start']), (_check_constraint_end, 'Error! Phase must end-before Constraint End Date.', ['date_end', 'constraint_date_end']), - ] def onchange_project(self, cr, uid, ids, project): result = {} if project: - project_pool = self.pool.get('project.project') - project_id = project_pool.browse(cr, uid, project) + project_obj = self.pool.get('project.project') + project_id = project_obj.browse(cr, uid, project) if project_id.date_start: result['date_start'] = mx.DateTime.strptime(project_id.date_start, "%Y-%m-%d").strftime('%Y-%m-%d %H:%M:%S') - return {'value' : result} - return {'value' : {'date_start' : []}} + return {'value': result} + return {'value': {'date_start': []}} - def constraint_date_start(self, cr, uid, phase, date_end, context=None): - # Recursive call for all previous phases if change in date_start < older time - - resource_cal_pool = self.pool.get('resource.calendar') - uom_pool = self.pool.get('product.uom') - resource_pool = self.pool.get('resource.resource') + def _check_date_start(self, cr, uid, phase, date_end, context=None): + """ + Check And Compute date_end of phase if change in date_start < older time. + """ + resource_calendar_obj = self.pool.get('resource.calendar') + uom_obj = self.pool.get('product.uom') + resource_obj = self.pool.get('resource.resource') calendar_id = phase.project_id.resource_calendar_id.id - resource_id = resource_pool.search(cr, uid, [('user_id','=',phase.responsible_id.id)]) + resource_id = resource_obj.search(cr, uid, [('user_id', '=', phase.responsible_id.id)]) if resource_id: - calendar_id = resource_pool.browse(cr, uid, resource_id[0]).calendar_id.id - default_uom_id = uom_pool.search(cr, uid, [('name','=','Hour')])[0] - avg_hours = uom_pool._compute_qty(cr, uid, phase.product_uom.id, phase.duration, default_uom_id) - work_time = resource_cal_pool.interval_min_get(cr, uid, calendar_id or False, date_end, avg_hours or 0.0, resource_id or False) - dt_start = work_time[0][0].strftime('%Y-%m-%d %H:%M:%S') - self.write(cr, uid, [phase.id], {'date_start' : dt_start, 'date_end' : date_end.strftime('%Y-%m-%d %H:%M:%S')}) + cal_id = resource_obj.browse(cr, uid, resource_id[0]).calendar_id.id + if cal_id: + calendar_id = cal_id + default_uom_id = uom_obj.search(cr, uid, [('name', '=', 'Hour')])[0] + avg_hours = uom_obj._compute_qty(cr, uid, phase.product_uom.id, phase.duration, default_uom_id) + work_times = resource_calendar_obj.interval_min_get(cr, uid, calendar_id or False, date_end, avg_hours or 0.0, resource_id or False) + dt_start = work_times[0][0].strftime('%Y-%m-%d %H:%M:%S') + self.write(cr, uid, [phase.id], {'date_start': dt_start, 'date_end': date_end.strftime('%Y-%m-%d %H:%M:%S')}) - def constraint_date_end(self, cr, uid, phase, date_start, context=None): - # Recursive call for all next phases if change in date_end > older time - - resource_cal_pool = self.pool.get('resource.calendar') - uom_pool = self.pool.get('product.uom') - resource_pool = self.pool.get('resource.resource') + def _check_date_end(self, cr, uid, phase, date_start, context=None): + """ + Check And Compute date_end of phase if change in date_end > older time. + """ + resource_calendar_obj = self.pool.get('resource.calendar') + uom_obj = self.pool.get('product.uom') + resource_obj = self.pool.get('resource.resource') calendar_id = phase.project_id.resource_calendar_id.id - resource_id = resource_pool.search(cr, uid, [('user_id','=',phase.responsible_id.id)]) + resource_id = resource_obj.search(cr, uid, [('user_id', '=', phase.responsible_id.id)]) if resource_id: - calendar_id = resource_pool.browse(cr, uid, resource_id[0]).calendar_id.id - default_uom_id = uom_pool.search(cr, uid, [('name','=','Hour')])[0] - avg_hours = uom_pool._compute_qty(cr, uid, phase.product_uom.id, phase.duration, default_uom_id) - work_time = resource_cal_pool.interval_get(cr, uid, calendar_id or False, date_start, avg_hours or 0.0, resource_id or False) - dt_end = work_time[-1][1].strftime('%Y-%m-%d %H:%M:%S') - self.write(cr, uid, [phase.id], {'date_start' : date_start.strftime('%Y-%m-%d %H:%M:%S'), 'date_end' : dt_end}) + cal_id = resource_obj.browse(cr, uid, resource_id[0]).calendar_id.id + if cal_id: + calendar_id = cal_id + default_uom_id = uom_obj.search(cr, uid, [('name', '=', 'Hour')])[0] + avg_hours = uom_obj._compute_qty(cr, uid, phase.product_uom.id, phase.duration, default_uom_id) + work_times = resource_calendar_obj.interval_get(cr, uid, calendar_id or False, date_start, avg_hours or 0.0, resource_id or False) + dt_end = work_times[-1][1].strftime('%Y-%m-%d %H:%M:%S') + self.write(cr, uid, [phase.id], {'date_start': date_start.strftime('%Y-%m-%d %H:%M:%S'), 'date_end': dt_end}) def write(self, cr, uid, ids, vals, context=None): @@ -179,62 +176,62 @@ class project_phase(osv.osv): if context.get('scheduler',False): return super(project_phase, self).write(cr, uid, ids, vals, context=context) -# if the phase is performed by a resource then its calendar and efficiency also taken -# otherwise the project's working calendar considered + # Consider calendar and efficiency if the phase is performed by a resource + # otherwise consider the project's working calendar phase = self.browse(cr, uid, ids[0]) - resource_cal_pool = self.pool.get('resource.calendar') - resource_pool = self.pool.get('resource.resource') - uom_pool = self.pool.get('product.uom') + resource_calendar_obj = self.pool.get('resource.calendar') + resource_obj = self.pool.get('resource.resource') + uom_obj = self.pool.get('product.uom') resource_id = False calendar_id = phase.project_id.resource_calendar_id.id - resource_id = resource_pool.search(cr, uid, [('user_id','=',phase.responsible_id.id)]) + resource_id = resource_obj.search(cr, uid, [('user_id', '=', phase.responsible_id.id)]) if resource_id: - calendar_id = resource_pool.browse(cr, uid, resource_id[0]).calendar_id.id - default_uom_id = uom_pool.search(cr, uid, [('name','=','Hour')])[0] - avg_hours = uom_pool._compute_qty(cr, uid, phase.product_uom.id, phase.duration, default_uom_id) - -# write method changes the date_start and date_end -#for previous and next phases respectively based on valid condition + cal_id = resource_obj.browse(cr, uid, resource_id[0]).calendar_id.id + if cal_id: + calendar_id = cal_id + default_uom_id = uom_obj.search(cr, uid, [('name', '=', 'Hour')])[0] + avg_hours = uom_obj._compute_qty(cr, uid, phase.product_uom.id, phase.duration, default_uom_id) + # Change the date_start and date_end + # for previous and next phases respectively based on valid condition if vals.get('date_start'): if vals['date_start'] < phase.date_start: dt_start = mx.DateTime.strptime(vals['date_start'],'%Y-%m-%d %H:%M:%S') - work_times = resource_cal_pool.interval_get(cr, uid, calendar_id or False, dt_start, avg_hours or 0.0, resource_id or False) + work_times = resource_calendar_obj.interval_get(cr, uid, calendar_id or False, dt_start, avg_hours or 0.0, resource_id or False) vals['date_end'] = work_times[-1][1].strftime('%Y-%m-%d %H:%M:%S') super(project_phase, self).write(cr, uid, ids, vals, context=context) for prv_phase in phase.previous_phase_ids: - self.constraint_date_start(cr, uid, prv_phase, dt_start) - + self._check_date_start(cr, uid, prv_phase, dt_start) if vals.get('date_end'): if vals['date_end'] > phase.date_end: dt_end = mx.DateTime.strptime(vals['date_end'],'%Y-%m-%d %H:%M:%S') - work_times = resource_cal_pool.interval_min_get(cr, uid, calendar_id or False, dt_end, avg_hours or 0.0, resource_id or False) + work_times = resource_calendar_obj.interval_min_get(cr, uid, calendar_id or False, dt_end, avg_hours or 0.0, resource_id or False) vals['date_start'] = work_times[0][0].strftime('%Y-%m-%d %H:%M:%S') super(project_phase, self).write(cr, uid, ids, vals, context=context) for next_phase in phase.next_phase_ids: - self.constraint_date_end(cr, uid, next_phase, dt_end) + self._check_date_end(cr, uid, next_phase, dt_end) return super(project_phase, self).write(cr, uid, ids, vals, context=context) - def phase_draft(self, cr, uid, ids,*args): + def set_draft(self, cr, uid, ids, *args): self.write(cr, uid, ids, {'state': 'draft'}) return True - def phase_start(self, cr, uid, ids,*args): + def set_open(self, cr, uid, ids, *args): self.write(cr, uid, ids, {'state': 'open'}) return True - def phase_pending(self, cr, uid, ids,*args): + def set_pending(self, cr, uid, ids,*args): self.write(cr, uid, ids, {'state': 'pending'}) return True - def phase_cancel(self, cr, uid, ids,*args): + def set_cancel(self, cr, uid, ids, *args): self.write(cr, uid, ids, {'state': 'cancelled'}) return True - def phase_done(self, cr, uid, ids,*args): + def set_done(self, cr, uid, ids, *args): self.write(cr, uid, ids, {'state': 'done'}) return True @@ -246,7 +243,7 @@ class project_resource_allocation(osv.osv): _rec_name = 'resource_id' _columns = { 'resource_id': fields.many2one('resource.resource', 'Resource', required=True), - 'phase_id': fields.many2one('project.phase', 'Project Phase',required=True), + 'phase_id': fields.many2one('project.phase', 'Project Phase', required=True), 'useability': fields.float('Useability', help="Useability of this ressource for this project phase in percentage (=50%)"), } _defaults = { @@ -257,7 +254,7 @@ project_resource_allocation() class project(osv.osv): _inherit = "project.project" - + _description = "Project" _columns = { 'phase_ids': fields.one2many('project.phase', 'project_id', "Project Phases"), 'resource_calendar_id': fields.many2one('resource.calendar', 'Working Time', help="Timetable working hours to adjust the gantt diagram report"), @@ -267,7 +264,7 @@ project() class task(osv.osv): _inherit = "project.task" - + _description = "Task" _columns = { 'phase_id': fields.many2one('project.phase', 'Project Phase'), 'occupation_rate': fields.float('Occupation Rate', help='The occupation rate fields indicates how much of his time a user is working on a task. A 100% occupation rate means the user works full time on the tasks. The ending date of a task is computed like this: Starting Date + Duration / Occupation Rate.'), @@ -280,53 +277,58 @@ class task(osv.osv): def onchange_planned(self, cr, uid, ids, project, user_id=False, planned=0.0, effective=0.0, date_start=None, occupation_rate=0.0): result = {} if date_start: - resource_pool = self.pool.get('resource.resource') + resource_obj = self.pool.get('resource.resource') project_pool = self.pool.get('project.project') + hrs = float(planned / float(occupation_rate)) + calendar_id = project_pool.browse(cr, uid, project).resource_calendar_id.id resource_calendar = self.pool.get('resource.calendar') dt_start = mx.DateTime.strptime(date_start, '%Y-%m-%d %H:%M:%S') - resource_id = resource_pool.search(cr, uid, [('user_id','=',user_id)]) + resource_id = resource_obj.search(cr, uid, [('user_id','=',user_id)]) if resource_id: - resource_obj = resource_pool.browse(cr, uid, resource_id)[0] - hrs = planned / (float(occupation_rate) * resource_obj.time_efficiency) - calendar_id = resource_obj.calendar_id.id - else: - hrs = float(planned / float(occupation_rate)) - calendar_id = project_pool.browse(cr, uid, project).resource_calendar_id .id + resource = resource_obj.browse(cr, uid, resource_id)[0] + hrs = planned / (float(occupation_rate) * resource.time_efficiency) + if resource.calendar_id.id: + calendar_id = resource.calendar_id.id work_times = resource_calendar.interval_get(cr, uid, calendar_id or False, dt_start, hrs or 0.0, resource_id or False) result['date_end'] = work_times[-1][1].strftime('%Y-%m-%d %H:%M:%S') result['remaining_hours'] = planned - effective return {'value' : result} - def constraint_date_start(self, cr, uid, task, date_end, context=None): - # Recursive call for all previous tasks if change in date_start < older time - - resource_cal_pool = self.pool.get('resource.calendar') - resource_pool = self.pool.get('resource.resource') + def _check_date_start(self, cr, uid, task, date_end, context=None): + """ + Check And Compute date_end of task if change in date_start < older time. + """ + resource_calendar_obj = self.pool.get('resource.calendar') + resource_obj = self.pool.get('resource.resource') calendar_id = task.project_id.resource_calendar_id.id - hours = task.remaining_hours / task.occupation_rate - resource_id = resource_pool.search(cr, uid, [('user_id','=',task.user_id.id)]) + hours = task.planned_hours / task.occupation_rate + resource_id = resource_obj.search(cr, uid, [('user_id', '=', task.user_id.id)]) if resource_id: - resource_obj = resource_pool.browse(cr, uid, resource_id[0]) - calendar_id = resource_obj.calendar_id.id - hours = task.planned_hours / (float(task.occupation_rate) * resource_obj.time_efficiency) - work_time = resource_cal_pool.interval_min_get(cr, uid, calendar_id or False, date_end, hours or 0.0, resource_id or False) - dt_start = work_time[0][0].strftime('%Y-%m-%d %H:%M:%S') + resource = resource_obj.browse(cr, uid, resource_id[0]) + if resource.calendar_id.id: + calendar_id = resource.calendar_id.id + hours = task.planned_hours / (float(task.occupation_rate) * resource.time_efficiency) + work_times = resource_calendar_obj.interval_min_get(cr, uid, calendar_id or False, date_end, hours or 0.0, resource_id or False) + dt_start = work_times[0][0].strftime('%Y-%m-%d %H:%M:%S') self.write(cr, uid, [task.id], {'date_start' : dt_start,'date_end' : date_end.strftime('%Y-%m-%d %H:%M:%S')}) - def constraint_date_end(self, cr, uid, task, date_start, context=None): - # Recursive call for all next tasks if change in date_end > older time + def _check_date_end(self, cr, uid, task, date_start, context=None): + """ + Check And Compute date_end of task if change in date_end > older time. + """ - resource_cal_pool = self.pool.get('resource.calendar') - resource_pool = self.pool.get('resource.resource') + resource_calendar_obj = self.pool.get('resource.calendar') + resource_obj = self.pool.get('resource.resource') calendar_id = task.project_id.resource_calendar_id.id - hours = task.remaining_hours / task.occupation_rate - resource_id = resource_pool.search(cr,uid,[('user_id','=',task.user_id.id)]) + hours = task.planned_hours / task.occupation_rate + resource_id = resource_obj.search(cr,uid,[('user_id', '=', task.user_id.id)]) if resource_id: - resource_obj = resource_pool.browse(cr, uid, resource_id[0]) - calendar_id = resource_obj.calendar_id.id - hours = task.planned_hours / (float(task.occupation_rate) * resource_obj.time_efficiency) - work_time = resource_cal_pool.interval_get(cr, uid, calendar_id or False, date_start, hours or 0.0, resource_id or False) - dt_end = work_time[-1][1].strftime('%Y-%m-%d %H:%M:%S') + resource = resource_obj.browse(cr, uid, resource_id[0]) + if resource.calendar_id.id: + calendar_id = resource.calendar_id.id + hours = task.planned_hours / (float(task.occupation_rate) * resource.time_efficiency) + work_times = resource_calendar_obj.interval_get(cr, uid, calendar_id or False, date_start, hours or 0.0, resource_id or False) + dt_end = work_times[-1][1].strftime('%Y-%m-%d %H:%M:%S') self.write(cr, uid, [task.id], {'date_start' : date_start.strftime('%Y-%m-%d %H:%M:%S'),'date_end' : dt_end}) def write(self, cr, uid, ids, vals, context=None): @@ -337,44 +339,43 @@ class task(osv.osv): if context.get('scheduler',False): return super(task, self).write(cr, uid, ids, vals, context=context) -# if the task is performed by a resource then its calendar and efficiency also taken -# otherwise the project's working calendar considered + # Consider calendar and efficiency if the task is performed by a resource + # otherwise consider the project's working calendar task_id = ids if isinstance(ids, list): task_id = ids[0] - tasks = self.browse(cr, uid, task_id, context=context) - resource_cal_pool = self.pool.get('resource.calendar') - resource_pool = self.pool.get('resource.resource') - calendar_id = tasks.project_id.resource_calendar_id.id - hrs = tasks.remaining_hours / tasks.occupation_rate - resource_id = resource_pool.search(cr, uid, [('user_id','=',tasks.user_id.id)]) + task_rec = self.browse(cr, uid, task_id, context=context) + resource_calendar_obj = self.pool.get('resource.calendar') + resource_obj = self.pool.get('resource.resource') + calendar_id = task_rec.project_id.resource_calendar_id.id + hrs = task_rec.planned_hours / task_rec.occupation_rate + resource_id = resource_obj.search(cr, uid, [('user_id', '=', task_rec.user_id.id)]) if resource_id: - resource_obj = resource_pool.browse(cr, uid, resource_id[0]) - calendar_id = resource_obj.calendar_id.id - hrs = tasks.planned_hours / (float(tasks.occupation_rate) * resource_obj.time_efficiency) + resource = resource_obj.browse(cr, uid, resource_id[0]) + if resource.calendar_id.id: + calendar_id = resource.calendar_id.id + hrs = task_rec.planned_hours / (float(task_rec.occupation_rate) * resource.time_efficiency) -# write method changes the date_start and date_end -# for previous and next tasks respectively based on valid condition + # Change the date_start and date_end + # for previous and next tasks respectively based on valid condition if vals.get('date_start'): - if vals['date_start'] < tasks.date_start: - dt_start = mx.DateTime.strptime(vals['date_start'],'%Y-%m-%d %H:%M:%S') - work_times = resource_cal_pool.interval_get(cr, uid, calendar_id or False, dt_start, hrs or 0.0, resource_id or False) + if vals['date_start'] < task_rec.date_start: + dt_start = mx.DateTime.strptime(vals['date_start'], '%Y-%m-%d %H:%M:%S') + work_times = resource_calendar_obj.interval_get(cr, uid, calendar_id or False, dt_start, hrs or 0.0, resource_id or False) vals['date_end'] = work_times[-1][1].strftime('%Y-%m-%d %H:%M:%S') super(task, self).write(cr, uid, ids, vals, context=context) - for prv_task in tasks.parent_ids: - self.constraint_date_start(cr, uid, prv_task, dt_start) - + for prv_task in task_rec.parent_ids: + self._check_date_start(cr, uid, prv_task, dt_start) if vals.get('date_end'): - if vals['date_end'] > tasks.date_end: - dt_end = mx.DateTime.strptime(vals['date_end'],'%Y-%m-%d %H:%M:%S') - hrs = tasks.remaining_hours / tasks.occupation_rate - work_times = resource_cal_pool.interval_min_get(cr, uid, calendar_id or False, dt_end, hrs or 0.0, resource_id or False) + if vals['date_end'] > task_rec.date_end: + dt_end = mx.DateTime.strptime(vals['date_end'], '%Y-%m-%d %H:%M:%S') + work_times = resource_calendar_obj.interval_min_get(cr, uid, calendar_id or False, dt_end, hrs or 0.0, resource_id or False) vals['date_start'] = work_times[0][0].strftime('%Y-%m-%d %H:%M:%S') super(task, self).write(cr, uid, ids, vals, context=context) - for next_task in tasks.child_ids: - self.constraint_date_end(cr, uid, next_task, dt_end) + for next_task in task_rec.child_ids: + self._check_date_end(cr, uid, next_task, dt_end) return super(task, self).write(cr, uid, ids, vals, context=context) diff --git a/addons/project_long_term/project_demo.xml b/addons/project_long_term/project_demo.xml index 64dcb19c31e..24bc7ff9438 100644 --- a/addons/project_long_term/project_demo.xml +++ b/addons/project_long_term/project_demo.xml @@ -201,6 +201,7 @@ + diff --git a/addons/project_long_term/project_view.xml b/addons/project_long_term/project_view.xml index 059e0a8300a..0af1e09c422 100644 --- a/addons/project_long_term/project_view.xml +++ b/addons/project_long_term/project_view.xml @@ -1,6 +1,11 @@ + + # ------------------------------------------------------ + # Project Resource Allocation + # ------------------------------------------------------ + project.resource.allocation.form project.resource.allocation @@ -13,7 +18,7 @@ - + project.resource.allocation.list project.resource.allocation @@ -26,7 +31,11 @@
- + + # ------------------------------------------------------ + # Project Phase + # ------------------------------------------------------ + project.phase.form project.phase @@ -57,11 +66,11 @@
-