diff --git a/addons/account/account.py b/addons/account/account.py index acf27c42392..8c7f058acc6 100644 --- a/addons/account/account.py +++ b/addons/account/account.py @@ -1150,6 +1150,29 @@ class account_move(osv.osv): _description = "Account Entry" _order = 'id desc' + def account_move_prepare(self, cr, uid, journal_id, date=False, ref='', company_id=False, context=None): + ''' + Prepares and returns a dictionary of values, ready to be passed to create() based on the parameters received. + ''' + if not date: + date = fields.date.today() + period_obj = self.pool.get('account.period') + if not company_id: + user = self.pool.get('res.users').browse(cr, uid, uid, context=context) + company_id = user.company_id.id + if context is None: + context = {} + #put the company in context to find the good period + ctx = context.copy() + ctx.update({'company_id': company_id}) + return { + 'journal_id': journal_id, + 'date': date, + 'period_id': period_obj.find(cr, uid, date, context=ctx)[0], + 'ref': ref, + 'company_id': company_id, + } + def name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=80): """ Returns a list of tupples containing id, name, as internally it is called {def name_get} @@ -1850,6 +1873,13 @@ class account_tax(osv.osv): return result in the context Ex: result=round(price_unit*0.21,4) """ + def copy_data(self, cr, uid, id, default=None, context=None): + if default is None: + default = {} + name = self.read(cr, uid, id, ['name'], context=context)['name'] + default = default.copy() + default.update({'name': name + _(' (Copy)')}) + return super(account_tax, self).copy_data(cr, uid, id, default=default, context=context) def get_precision_tax(): def change_digit_tax(cr): diff --git a/addons/account/account_invoice.py b/addons/account/account_invoice.py index dbe17d1c60a..d771bc59506 100644 --- a/addons/account/account_invoice.py +++ b/addons/account/account_invoice.py @@ -22,6 +22,7 @@ import time from lxml import etree import openerp.addons.decimal_precision as dp +import openerp.exceptions from openerp import pooler from openerp.osv import fields, osv, orm @@ -302,16 +303,7 @@ class account_invoice(osv.osv): ('number_uniq', 'unique(number, company_id, journal_id, type)', 'Invoice Number must be unique per Company!'), ] - def _find_partner(self, inv): - ''' - Find the partner for which the accounting entries will be created - ''' - #if the chosen partner is not a company and has a parent company, use the parent for the journal entries - #because you want to invoice 'Agrolait, accounting department' but the journal items are for 'Agrolait' - part = inv.partner_id - if part.parent_id and not part.is_company: - part = part.parent_id - return part + def fields_view_get(self, cr, uid, view_id=None, view_type=False, context=None, toolbar=False, submenu=False): @@ -981,7 +973,7 @@ class account_invoice(osv.osv): date = inv.date_invoice or time.strftime('%Y-%m-%d') - part = self._find_partner(inv) + part = self.pool.get("res.partner")._find_accounting_partner(inv.partner_id) line = map(lambda x:(0,0,self.line_get_convert(cr, uid, x, part.id, date, context=ctx)),iml) @@ -1753,6 +1745,16 @@ class res_partner(osv.osv): 'invoice_ids': fields.one2many('account.invoice.line', 'partner_id', 'Invoices', readonly=True), } + def _find_accounting_partner(self, part): + ''' + Find the partner for which the accounting entries will be created + ''' + #if the chosen partner is not a company and has a parent company, use the parent for the journal entries + #because you want to invoice 'Agrolait, accounting department' but the journal items are for 'Agrolait' + if part.parent_id and not part.is_company: + part = part.parent_id + return part + def copy(self, cr, uid, id, default=None, context=None): default = default or {} default.update({'invoice_ids' : []}) diff --git a/addons/account/account_invoice_view.xml b/addons/account/account_invoice_view.xml index a37474db0af..8c0854bd6c6 100644 --- a/addons/account/account_invoice_view.xml +++ b/addons/account/account_invoice_view.xml @@ -145,8 +145,7 @@
@@ -1206,6 +1206,8 @@ + + @@ -1256,7 +1258,7 @@
@@ -2258,7 +2260,7 @@
diff --git a/addons/account/partner_view.xml b/addons/account/partner_view.xml index 8623bd03922..1267e20165b 100644 --- a/addons/account/partner_view.xml +++ b/addons/account/partner_view.xml @@ -95,6 +95,7 @@ + diff --git a/addons/account/project/project_view.xml b/addons/account/project/project_view.xml index 62c8fb37075..aa567d2fc79 100644 --- a/addons/account/project/project_view.xml +++ b/addons/account/project/project_view.xml @@ -131,6 +131,7 @@ + @@ -169,6 +170,7 @@ + @@ -176,7 +178,6 @@ - diff --git a/addons/account/report/account_financial_report.py b/addons/account/report/account_financial_report.py index d94955a764a..864c4bbc7d1 100644 --- a/addons/account/report/account_financial_report.py +++ b/addons/account/report/account_financial_report.py @@ -65,7 +65,7 @@ class report_account_common(report_sxw.rml_parse, common_report_header): vals['debit'] = report.debit vals['credit'] = report.credit if data['form']['enable_filter']: - vals['balance_cmp'] = self.pool.get('account.financial.report').browse(self.cr, self.uid, report.id, context=data['form']['comparison_context']).balance + vals['balance_cmp'] = self.pool.get('account.financial.report').browse(self.cr, self.uid, report.id, context=data['form']['comparison_context']).balance * report.sign or 0.0 lines.append(vals) account_ids = [] if report.display_detail == 'no_detail': @@ -97,7 +97,7 @@ class report_account_common(report_sxw.rml_parse, common_report_header): if not currency_obj.is_zero(self.cr, self.uid, account.company_id.currency_id, vals['balance']): flag = True if data['form']['enable_filter']: - vals['balance_cmp'] = account_obj.browse(self.cr, self.uid, account.id, context=data['form']['comparison_context']).balance + vals['balance_cmp'] = account_obj.browse(self.cr, self.uid, account.id, context=data['form']['comparison_context']).balance * report.sign or 0.0 if not currency_obj.is_zero(self.cr, self.uid, account.company_id.currency_id, vals['balance_cmp']): flag = True if flag: diff --git a/addons/account_analytic_analysis/account_analytic_analysis.py b/addons/account_analytic_analysis/account_analytic_analysis.py index 0a56c80766b..fe47b5d293b 100644 --- a/addons/account_analytic_analysis/account_analytic_analysis.py +++ b/addons/account_analytic_analysis/account_analytic_analysis.py @@ -714,6 +714,17 @@ class account_analytic_account(osv.osv): self.write(cr, uid, [contract.id], {'recurring_next_date': new_date.strftime('%Y-%m-%d')}, context=context) return True + def onchange_invoice_on_timesheets(self, cr, uid, ids, invoice_on_timesheets, context=None): + if not invoice_on_timesheets: + return {} + result = {'value': {'use_timesheets': True}} + try: + to_invoice = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'hr_timesheet_invoice', 'timesheet_invoice_factor1') + result['value']['to_invoice'] = to_invoice[1] + except ValueError: + pass + return result + class account_analytic_account_summary_user(osv.osv): _name = "account_analytic_analysis.summary.user" _description = "Hours Summary by User" diff --git a/addons/account_analytic_analysis/account_analytic_analysis_cron.xml b/addons/account_analytic_analysis/account_analytic_analysis_cron.xml index 14ca1fd2135..970ab275ef9 100644 --- a/addons/account_analytic_analysis/account_analytic_analysis_cron.xml +++ b/addons/account_analytic_analysis/account_analytic_analysis_cron.xml @@ -55,6 +55,19 @@ Hello ${object.name}, ${account_table(ctx["data"]["future"].iteritems())} % endif +

+ You can check all contracts to be renewed using the menu: +

+
    +
  • Sales / Invoicing / Contracts to Renew
  • +
+

+ Thanks, +

+ +
+-- 
+OpenERP Automatic Email
 
]]> diff --git a/addons/account_analytic_analysis/account_analytic_analysis_view.xml b/addons/account_analytic_analysis/account_analytic_analysis_view.xml index b4746484e7c..3c477b5556f 100644 --- a/addons/account_analytic_analysis/account_analytic_analysis_view.xml +++ b/addons/account_analytic_analysis/account_analytic_analysis_view.xml @@ -130,11 +130,11 @@ -

- When invoicing on timesheet, OpenERP uses the +

+ When reinvoicing costs, OpenERP uses the pricelist of the contract which uses the price - defined on the product related to each employee to - define the customer invoice price rate. + defined on the product related (e.g timesheet + products are defined on each employee).

- + - - - - + + + + + + this.attr('data-modes', 'default'); + diff --git a/addons/base_action_rule/base_action_rule.py b/addons/base_action_rule/base_action_rule.py index a3237c1620b..62c808ed556 100644 --- a/addons/base_action_rule/base_action_rule.py +++ b/addons/base_action_rule/base_action_rule.py @@ -214,6 +214,13 @@ class base_action_rule(osv.osv): self._register_hook(cr, ids) return True + def onchange_model_id(self, cr, uid, ids, model_id, context=None): + data = {'model': False, 'filter_pre_id': False, 'filter_id': False} + if model_id: + model = self.pool.get('ir.model').browse(cr, uid, model_id, context=context) + data.update({'model': model.model}) + return {'value': data} + def _check(self, cr, uid, automatic=False, use_new_cursor=False, context=None): """ This Function is called by scheduler. """ context = context or {} diff --git a/addons/base_action_rule/base_action_rule_view.xml b/addons/base_action_rule/base_action_rule_view.xml index 25ea4048bad..4e551fa21c5 100644 --- a/addons/base_action_rule/base_action_rule_view.xml +++ b/addons/base_action_rule/base_action_rule_view.xml @@ -15,7 +15,7 @@

- + diff --git a/addons/base_calendar/base_calendar_view.xml b/addons/base_calendar/base_calendar_view.xml index e3ad980dae7..92ffad4be9a 100644 --- a/addons/base_calendar/base_calendar_view.xml +++ b/addons/base_calendar/base_calendar_view.xml @@ -70,7 +70,7 @@
diff --git a/addons/base_report_designer/base_report_designer.py b/addons/base_report_designer/base_report_designer.py index 825d1d29c4c..180a534b07f 100644 --- a/addons/base_report_designer/base_report_designer.py +++ b/addons/base_report_designer/base_report_designer.py @@ -19,10 +19,11 @@ # ############################################################################## +import base64 +import openerp.modules.registry from openerp.osv import osv from openerp_sxw2rml import sxw2rml from StringIO import StringIO -import base64 from openerp import pooler from openerp import addons @@ -55,7 +56,12 @@ class report_xml(osv.osv): 'report_sxw_content': base64.decodestring(file_sxw), 'report_rml_content': str(sxw2rml(sxwval, xsl=fp.read())), }) + + # FIXME: this should be moved to an override of the ir.actions.report_xml.create() method + cr.commit() pool.get('ir.actions.report.xml').register_all(cr) + openerp.modules.registry.RegistryManager.signal_registry_change(cr.dbname) + return True def report_get(self, cr, uid, report_id, context=None): diff --git a/addons/base_report_designer/plugin/openerp_report_designer.zip b/addons/base_report_designer/plugin/openerp_report_designer.zip index 855fef319fb..7d03f45dbb4 100644 Binary files a/addons/base_report_designer/plugin/openerp_report_designer.zip and b/addons/base_report_designer/plugin/openerp_report_designer.zip differ diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/ExportToRML.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/ExportToRML.py index d92b2aec14f..d2605ce73e4 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/ExportToRML.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/ExportToRML.py @@ -92,9 +92,9 @@ class ExportToRML( unohelper.Base, XJobExecutor ): if docinfo.getUserFieldValue(2) == "": ErrorDialog("Please Save this file on server","Use Send To Server Option in OpenERP Report Menu","Error") exit(1) - filename = self.GetAFileName() - if not filename: - exit(1) + filename = self.GetAFileName() + if not filename: + exit(1) global passwd self.password = passwd try: @@ -118,7 +118,7 @@ class ExportToRML( unohelper.Base, XJobExecutor ): initPath = tempfile.gettempdir() oUcb = createUnoService("com.sun.star.ucb.SimpleFileAccess") if oUcb.exists(initPath): - oFileDialog.setDisplayDirectory('file://' + ( os.name == 'nt' and '/' or '' ) + initPath ) + oFileDialog.setDisplayDirectory('file://' + ( os.name == 'nt' and '/' or '' ) + initPath ) oFileDialog.setDefaultName(f_path ) diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Fields.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Fields.py index 3e39b528b6b..90f85e57a0d 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Fields.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Fields.py @@ -209,13 +209,13 @@ class Fields(unohelper.Base, XJobExecutor ): key.sort() myval=None if not sVar.find("/")==-1: - myval=sVar[:sVar.find("/")] + myval=sVar[:sVar.find("/")] else: myval=sVar if myval in key: if (res[myval]['type'] in ['many2one']): sObject = res[myval]['relation'] - return self.getRes(sock,res[myval]['relation'], sVar[sVar.find("/")+1:]) + return self.getRes(sock,res[myval]['relation'], sVar[sVar.find("/")+1:]) else: return sObject diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Repeatln.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Repeatln.py index 16735d40f4e..f5e0972d2dd 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Repeatln.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Repeatln.py @@ -166,33 +166,33 @@ class RepeatIn( unohelper.Base, XJobExecutor ): self.sValue= "objects" else: sItem="" - for anObject in self.aObjectList: - if anObject[:anObject.find("(")] == sObject: - sItem = anObject - self.insVariable.setText( sItem ) + for anObject in self.aObjectList: + if anObject[:anObject.find("(")] == sObject: + sItem = anObject + self.insVariable.setText( sItem ) - genTree( - sItem[sItem.find("(")+1:sItem.find(")")], - self.aListRepeatIn, - self.insField, - self.sMyHost, - 2, - ending=['one2many','many2many'], - recur=['one2many','many2many'] - ) + genTree( + sItem[sItem.find("(")+1:sItem.find(")")], + self.aListRepeatIn, + self.insField, + self.sMyHost, + 2, + ending=['one2many','many2many'], + recur=['one2many','many2many'] + ) self.sValue= self.win.getListBoxItem("lstFields",self.aListRepeatIn.index(sFields)) for var in self.aVariableList: - if var[:8] <> 'List of ': - self.model_ids = self.sock.execute(database, uid, self.password, 'ir.model' , 'search', [('model','=',var[var.find("(")+1:var.find(")")])]) + if var[:8] <> 'List of ': + self.model_ids = self.sock.execute(database, uid, self.password, 'ir.model' , 'search', [('model','=',var[var.find("(")+1:var.find(")")])]) else: - self.model_ids = self.sock.execute(database, uid, self.password, 'ir.model' , 'search', [('model','=',var[8:])]) + self.model_ids = self.sock.execute(database, uid, self.password, 'ir.model' , 'search', [('model','=',var[8:])]) fields=['name','model'] self.model_res = self.sock.execute(database, uid, self.password, 'ir.model', 'read', self.model_ids,fields) if self.model_res <> []: - if var[:8]<>'List of ': + if var[:8]<>'List of ': self.insVariable.addItem(var[:var.find("(")+1] + self.model_res[0]['name'] + ")" ,self.insVariable.getItemCount()) else: self.insVariable.addItem('List of ' + self.model_res[0]['name'] ,self.insVariable.getItemCount()) @@ -212,8 +212,8 @@ class RepeatIn( unohelper.Base, XJobExecutor ): self.win.setEditText("txtName", self.sGVariable) self.win.setEditText("txtUName",self.sGDisplayName) else: - self.win.setEditText("txtName",sMain[sMain.rfind("/")+1:]) - self.win.setEditText("txtUName","|-."+sItem[sItem.rfind("/")+1:]+".-|") + self.win.setEditText("txtName",sMain[sMain.rfind("/")+1:]) + self.win.setEditText("txtUName","|-."+sItem[sItem.rfind("/")+1:]+".-|") def cmbVariable_selected(self, oItemEvent): @@ -225,15 +225,15 @@ class RepeatIn( unohelper.Base, XJobExecutor ): self.win.removeListBoxItems("lstFields", 0, self.win.getListBoxItemCount("lstFields")) sItem=self.win.getComboBoxText("cmbVariable") for var in self.aVariableList: - if var[:8]=='List of ': - if var[:8]==sItem[:8]: + if var[:8]=='List of ': + if var[:8]==sItem[:8]: sItem = var - elif var[:var.find("(")+1] == sItem[:sItem.find("(")+1]: + elif var[:var.find("(")+1] == sItem[:sItem.find("(")+1]: sItem = var self.aListRepeatIn=[] - data = ( sItem[sItem.rfind(" ") + 1:] == docinfo.getUserFieldValue(3) ) and docinfo.getUserFieldValue(3) or sItem[sItem.find("(")+1:sItem.find(")")] - genTree( data, self.aListRepeatIn, self.insField, self.sMyHost, 2, ending=['one2many','many2many'], recur=['one2many','many2many'] ) + data = ( sItem[sItem.rfind(" ") + 1:] == docinfo.getUserFieldValue(3) ) and docinfo.getUserFieldValue(3) or sItem[sItem.find("(")+1:sItem.find(")")] + genTree( data, self.aListRepeatIn, self.insField, self.sMyHost, 2, ending=['one2many','many2many'], recur=['one2many','many2many'] ) self.win.selectListBoxItemPos("lstFields", 0, True ) diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/SendToServer.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/SendToServer.py index 86cf24edaa4..7e83910a427 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/SendToServer.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/SendToServer.py @@ -123,6 +123,7 @@ class SendtoServer(unohelper.Base, XJobExecutor): self.win.addFixedText("lblReportName", 2, 30, 50, 15, "Technical Name :") self.win.addEdit("txtReportName", -5, 25, 123, 15,report_name) self.win.addCheckBox("chkHeader", 51, 45, 70 ,15, "Corporate Header") + self.win.setCheckBoxState("chkHeader", True) self.win.addFixedText("lblResourceType", 2 , 60, 50, 15, "Select Rpt. Type :") self.win.addComboListBox("lstResourceType", -5, 58, 123, 15,True,itemListenerProc=self.lstbox_selected) self.lstResourceType = self.win.getControl( "lstResourceType" ) @@ -190,7 +191,6 @@ class SendtoServer(unohelper.Base, XJobExecutor): #sock = xmlrpclib.ServerProxy(docinfo.getUserFieldValue(0) +'/xmlrpc/object') file_type = oDoc2.getURL()[7:].split(".")[-1] - res = self.sock.execute(database, uid, self.password, 'ir.actions.report.xml', 'upload_report', int(docinfo.getUserFieldValue(2)),base64.encodestring(data),file_type,{}) params = { 'name': self.win.getEditText("txtName"), 'model': docinfo.getUserFieldValue(3), @@ -200,7 +200,12 @@ class SendtoServer(unohelper.Base, XJobExecutor): } if self.win.getListBoxSelectedItem("lstResourceType")=='OpenOffice': params['report_type']=file_type - res = self.sock.execute(database, uid, self.password, 'ir.actions.report.xml', 'write', int(docinfo.getUserFieldValue(2)), params) + self.sock.execute(database, uid, self.password, 'ir.actions.report.xml', 'write', int(docinfo.getUserFieldValue(2)), params) + + # Call upload_report as the *last* step, as it will call register_all() and cause the report service + # to be loaded - which requires all the data to be correct in the database + self.sock.execute(database, uid, self.password, 'ir.actions.report.xml', 'upload_report', int(docinfo.getUserFieldValue(2)),base64.encodestring(data),file_type,{}) + self.logobj.log_write('SendToServer',LOG_INFO, ':Report %s successfully send using %s'%(params['name'],database)) self.win.endExecute() else: diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Translation.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Translation.py index 13d02c86329..05f81a5c5b2 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Translation.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Translation.py @@ -112,43 +112,43 @@ class AddLang(unohelper.Base, XJobExecutor ): text=cursor.getText() tcur=text.createTextCursorByRange(cursor) - self.aVariableList.extend( filter( lambda obj: obj[:obj.find("(")] == "Objects", self.aObjectList ) ) + self.aVariableList.extend( filter( lambda obj: obj[:obj.find("(")] == "Objects", self.aObjectList ) ) for i in range(len(self.aItemList)): - anItem = self.aItemList[i][1] - component = self.aComponentAdd[i] + anItem = self.aItemList[i][1] + component = self.aComponentAdd[i] if component == "Document": - sLVal = anItem[anItem.find(",'") + 2:anItem.find("')")] - self.aVariableList.extend( filter( lambda obj: obj[:obj.find("(")] == sLVal, self.aObjectList ) ) + sLVal = anItem[anItem.find(",'") + 2:anItem.find("')")] + self.aVariableList.extend( filter( lambda obj: obj[:obj.find("(")] == sLVal, self.aObjectList ) ) if tcur.TextSection: getRecersiveSection(tcur.TextSection,self.aSectionList) if component in self.aSectionList: - sLVal = anItem[anItem.find(",'") + 2:anItem.find("')")] - self.aVariableList.extend( filter( lambda obj: obj[:obj.find("(")] == sLVal, self.aObjectList ) ) + sLVal = anItem[anItem.find(",'") + 2:anItem.find("')")] + self.aVariableList.extend( filter( lambda obj: obj[:obj.find("(")] == sLVal, self.aObjectList ) ) if tcur.TextTable: - if not component == "Document" and component[component.rfind(".") + 1:] == tcur.TextTable.Name: + if not component == "Document" and component[component.rfind(".") + 1:] == tcur.TextTable.Name: VariableScope(tcur,self.insVariable,self.aObjectList,self.aComponentAdd,self.aItemList,component) self.bModify=bFromModify if self.bModify==True: sItem="" - for anObject in self.aObjectList: - if anObject[:anObject.find("(")] == sVariable: - sItem = anObject - self.insVariable.setText( sItem ) - genTree(sItem[sItem.find("(")+1:sItem.find(")")],self.aListFields, self.insField,self.sMyHost,2,ending_excl=['one2many','many2one','many2many','reference'], recur=['many2one']) + for anObject in self.aObjectList: + if anObject[:anObject.find("(")] == sVariable: + sItem = anObject + self.insVariable.setText( sItem ) + genTree(sItem[sItem.find("(")+1:sItem.find(")")],self.aListFields, self.insField,self.sMyHost,2,ending_excl=['one2many','many2one','many2many','reference'], recur=['many2one']) self.sValue= self.win.getListBoxItem("lstFields",self.aListFields.index(sFields)) for var in self.aVariableList: - self.model_ids = self.sock.execute(database, uid, self.password, 'ir.model' , 'search', [('model','=',var[var.find("(")+1:var.find(")")])]) + self.model_ids = self.sock.execute(database, uid, self.password, 'ir.model' , 'search', [('model','=',var[var.find("(")+1:var.find(")")])]) fields=['name','model'] self.model_res = self.sock.execute(database, uid, self.password, 'ir.model', 'read', self.model_ids,fields) if self.model_res <> []: - self.insVariable.addItem(var[:var.find("(")+1] + self.model_res[0]['name'] + ")" ,self.insVariable.getItemCount()) + self.insVariable.addItem(var[:var.find("(")+1] + self.model_res[0]['name'] + ")" ,self.insVariable.getItemCount()) else: self.insVariable.addItem(var ,self.insVariable.getItemCount()) @@ -165,15 +165,15 @@ class AddLang(unohelper.Base, XJobExecutor ): docinfo=doc.getDocumentInfo() sItem= self.win.getComboBoxText("cmbVariable") for var in self.aVariableList: - if var[:var.find("(")+1]==sItem[:sItem.find("(")+1]: + if var[:var.find("(")+1]==sItem[:sItem.find("(")+1]: sItem = var sMain=self.aListFields[self.win.getListBoxSelectedItemPos("lstFields")] t=sMain.rfind('/lang') if t!=-1: - sObject=self.getRes(self.sock,sItem[sItem.find("(")+1:-1],sMain[1:]) + sObject=self.getRes(self.sock,sItem[sItem.find("(")+1:-1],sMain[1:]) ids = self.sock.execute(database, uid, self.password, sObject , 'search', []) res = self.sock.execute(database, uid, self.password, sObject , 'read',[ids[0]]) - self.win.setEditText("txtUName",res[0][sMain[sMain.rfind("/")+1:]]) + self.win.setEditText("txtUName",res[0][sMain[sMain.rfind("/")+1:]]) else: ErrorDialog("Please select a language.") @@ -192,13 +192,13 @@ class AddLang(unohelper.Base, XJobExecutor ): key.sort() myval=None if not sVar.find("/")==-1: - myval=sVar[:sVar.find("/")] + myval=sVar[:sVar.find("/")] else: myval=sVar if myval in key: if (res[myval]['type'] in ['many2one']): sObject = res[myval]['relation'] - return self.getRes(sock,res[myval]['relation'], sVar[sVar.find("/")+1:]) + return self.getRes(sock,res[myval]['relation'], sVar[sVar.find("/")+1:]) else: return sObject @@ -213,18 +213,18 @@ class AddLang(unohelper.Base, XJobExecutor ): self.aListFields=[] tempItem = self.win.getComboBoxText("cmbVariable") for var in self.aVariableList: - if var[:var.find("(")] == tempItem[:tempItem.find("(")]: + if var[:var.find("(")] == tempItem[:tempItem.find("(")]: sItem=var - genTree( - sItem[ sItem.find("(") + 1:sItem.find(")")], - self.aListFields, - self.insField, - self.sMyHost, - 2, - ending_excl=['one2many','many2one','many2many','reference'], - recur=['many2one'] - ) + genTree( + sItem[ sItem.find("(") + 1:sItem.find(")")], + self.aListFields, + self.insField, + self.sMyHost, + 2, + ending_excl=['one2many','many2one','many2many','reference'], + recur=['many2one'] + ) except: import traceback;traceback.print_exc() diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/functions.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/functions.py index 1b614224147..1d10f0f6a4c 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/functions.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/functions.py @@ -87,19 +87,19 @@ def genTree(object, aList, insField, host, level=3, ending=None, ending_excl=Non def VariableScope(oTcur, insVariable, aObjectList, aComponentAdd, aItemList, sTableName=""): if sTableName.find(".") != -1: - for i in range(len(aItemList)): + for i in range(len(aItemList)): if aComponentAdd[i]==sTableName: - sLVal=aItemList[i][1][aItemList[i][1].find(",'")+2:aItemList[i][1].find("')")] + sLVal=aItemList[i][1][aItemList[i][1].find(",'")+2:aItemList[i][1].find("')")] for j in range(len(aObjectList)): - if aObjectList[j][:aObjectList[j].find("(")] == sLVal: + if aObjectList[j][:aObjectList[j].find("(")] == sLVal: insVariable.append(aObjectList[j]) - VariableScope(oTcur,insVariable,aObjectList,aComponentAdd,aItemList, sTableName[:sTableName.rfind(".")]) + VariableScope(oTcur,insVariable,aObjectList,aComponentAdd,aItemList, sTableName[:sTableName.rfind(".")]) else: - for i in range(len(aItemList)): + for i in range(len(aItemList)): if aComponentAdd[i]==sTableName: - sLVal=aItemList[i][1][aItemList[i][1].find(",'")+2:aItemList[i][1].find("')")] + sLVal=aItemList[i][1][aItemList[i][1].find(",'")+2:aItemList[i][1].find("')")] for j in range(len(aObjectList)): - if aObjectList[j][:aObjectList[j].find("(")] == sLVal and sLVal!="": + if aObjectList[j][:aObjectList[j].find("(")] == sLVal and sLVal!="": insVariable.append(aObjectList[j]) def getList(aObjectList, host, count): @@ -145,8 +145,8 @@ def getRelation(sRelName, sItem, sObjName, aObjectList, host): if k == sItem: aObjectList.append(sObjName + "(" + res[k]['relation'] + ")") return 0 - if k == sItem[:sItem.find(".")]: - getRelation(res[k]['relation'], sItem[sItem.find(".")+1:], sObjName,aObjectList,host) + if k == sItem[:sItem.find(".")]: + getRelation(res[k]['relation'], sItem[sItem.find(".")+1:], sObjName,aObjectList,host) def getPath(sPath, sMain): @@ -157,13 +157,13 @@ def getPath(sPath, sMain): oPar = oParEnum.nextElement() if oPar.supportsService("com.sun.star.text.TextField.DropDown"): sItem=oPar.Items[1] - if sPath[:sPath.find(".")] == sMain: + if sPath[:sPath.find(".")] == sMain: break; else: res = re.findall('\\[\\[ *([a-zA-Z0-9_\.]+) *\\]\\]',sPath) if len(res) <> 0: - if sItem[sItem.find(",'")+2:sItem.find("')")] == sPath[:sPath.find(".")]: - sPath = sItem[sItem.find("(")+1:sItem.find(",")] + sPath[sPath.find("."):] + if sItem[sItem.find(",'")+2:sItem.find("')")] == sPath[:sPath.find(".")]: + sPath = sItem[sItem.find("(")+1:sItem.find(",")] + sPath[sPath.find("."):] getPath(sPath, sMain) return sPath diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/tools.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/tools.py index 53dc81f5bc3..8e03d853773 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/tools.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/tools.py @@ -22,21 +22,21 @@ import urllib def get_absolute_file_path(url): - url_unquoted = urllib.unquote(url) - return os.name == 'nt' and url_unquoted[1:] or url_unquoted + url_unquoted = urllib.unquote(url) + return os.name == 'nt' and url_unquoted[1:] or url_unquoted # This function reads the content of a file and return it to the caller def read_data_from_file(filename): - fp = file( filename, "rb" ) - data = fp.read() - fp.close() - return data + fp = file( filename, "rb" ) + data = fp.read() + fp.close() + return data # This function writes the content to a file def write_data_to_file(filename, data): - fp = file( filename, 'wb' ) - fp.write( data ) - fp.close() + fp = file( filename, 'wb' ) + fp.write( data ) + fp.close() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/modify.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/modify.py index b5f5a1501b9..60edbc71d96 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/modify.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/modify.py @@ -75,42 +75,42 @@ class modify(unohelper.Base, XJobExecutor ): self.sMyHost= docinfo.getUserFieldValue(0) else: ErrorDialog( - "Please insert user define field Field-1", - "Just go to File->Properties->User Define \n" - "Field-1 E.g. http://localhost:8069" - ) + "Please insert user define field Field-1", + "Just go to File->Properties->User Define \n" + "Field-1 E.g. http://localhost:8069" + ) exit(1) # Check weather Field-4 is available or not otherwise exit from application if not docinfo.getUserFieldValue(3) == "" and not docinfo.getUserFieldValue(0)=="": if self.oVC.TextField: self.oCurObj=self.oVC.TextField - item = self.oCurObj.Items[0] + item = self.oCurObj.Items[0] - kind, group1, group2 = self.getOperation(self.oCurObj.Items[1] ) + kind, group1, group2 = self.getOperation(self.oCurObj.Items[1] ) - start_group1 = group1[:group1.find(".")] - stop_group1 = group1[group1.find("."):].replace(".", "/") + start_group1 = group1[:group1.find(".")] + stop_group1 = group1[group1.find("."):].replace(".", "/") if kind == "field": - Fields( start_group1, stop_group1, item, True ) + Fields( start_group1, stop_group1, item, True ) elif kind == "expression": Expression( group1, item, True ) elif kind == "repeatIn": - RepeatIn( start_group1, group2, stop_group1, item, True ) + RepeatIn( start_group1, group2, stop_group1, item, True ) else: ErrorDialog( "Please place your cursor at beginning of field that you want to modify.","" - ) + ) else: ErrorDialog( - "Please insert user define field Field-1 or Field-4", - "Just go to File->Properties->User Define \n" - "Field-1 E.g. http://localhost:8069 \n" - "OR \n" - "Field-4 E.g. account.invoice" - ) + "Please insert user define field Field-1 or Field-4", + "Just go to File->Properties->User Define \n" + "Field-1 E.g. http://localhost:8069 \n" + "OR \n" + "Field-4 E.g. account.invoice" + ) exit(1) def getOperation(self, str): @@ -121,14 +121,14 @@ class modify(unohelper.Base, XJobExecutor ): method2 = lambda x: (u'field', x.group(1), None) method3 = lambda x: (u'expression', x.group(1), None) regexes = [ - ('\\[\\[ *repeatIn\\( *(.+)*, *\'([a-zA-Z0-9_]+)\' *\\) *\\]\\]', method1), - ('\\[\\[ *([a-zA-Z0-9_\.]+) *\\]\\]', method2), - ('\\[\\[ *(.+) *\\]\\]', method3) + ('\\[\\[ *repeatIn\\( *(.+)*, *\'([a-zA-Z0-9_]+)\' *\\) *\\]\\]', method1), + ('\\[\\[ *([a-zA-Z0-9_\.]+) *\\]\\]', method2), + ('\\[\\[ *(.+) *\\]\\]', method3) ] for (rule,method) in regexes: - res = re.match(rule, str) - if res: - return method(res) + res = re.match(rule, str) + if res: + return method(res) if __name__<>"package": modify(None) diff --git a/addons/base_report_designer/plugin/openerp_report_designer/test/test_fields.py b/addons/base_report_designer/plugin/openerp_report_designer/test/test_fields.py index c23e0e739bf..948b3733b70 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/test/test_fields.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/test/test_fields.py @@ -11,23 +11,23 @@ import time sock = xmlrpclib.ServerProxy('http://localhost:8069/xmlrpc/object') def get(object, level=3, ending=None, ending_excl=None, recur=None, root=''): - if ending is None: - ending = [] - if ending_excl is None: - ending_excl = [] - if recur is None: - recur = [] - res = sock.execute('terp', 3, 'admin', 'account.invoice', 'fields_get') - key = res.keys() - key.sort() - for k in key: - if (not ending or res[k]['type'] in ending) and ((not ending_excl) or not (res[k]['type'] in ending_excl)): - print root+'/'+k + if ending is None: + ending = [] + if ending_excl is None: + ending_excl = [] + if recur is None: + recur = [] + res = sock.execute('terp', 3, 'admin', 'account.invoice', 'fields_get') + key = res.keys() + key.sort() + for k in key: + if (not ending or res[k]['type'] in ending) and ((not ending_excl) or not (res[k]['type'] in ending_excl)): + print root+'/'+k - if res[k]['type'] in recur: - print root+'/'+k - if (res[k]['type'] in recur) and (level>0): - get(res[k]['relation'], level-1, ending, ending_excl, recur, root+'/'+k) + if res[k]['type'] in recur: + print root+'/'+k + if (res[k]['type'] in recur) and (level>0): + get(res[k]['relation'], level-1, ending, ending_excl, recur, root+'/'+k) print 'Field selection for a rields', '='*40 get('account.invoice', level=0, ending_excl=['one2many','many2one','many2many','reference'], recur=['many2one']) diff --git a/addons/board/static/src/js/dashboard.js b/addons/board/static/src/js/dashboard.js index 0a38c744738..bd9625a4fa8 100644 --- a/addons/board/static/src/js/dashboard.js +++ b/addons/board/static/src/js/dashboard.js @@ -177,8 +177,10 @@ instance.web.form.DashBoard = instance.web.form.FormWidget.extend({ view_mode = action_attrs.view_mode; // evaluate action_attrs context and domain + action_attrs.context_string = action_attrs.context; action_attrs.context = instance.web.pyeval.eval( 'context', action_attrs.context || {}); + action_attrs.domain_string = action_attrs.domain; action_attrs.domain = instance.web.pyeval.eval( 'domain', action_attrs.domain || [], action_attrs.context); if (action_attrs.context['dashboard_merge_domains_contexts'] === false) { @@ -301,9 +303,9 @@ instance.web.form.DashBoard = instance.web.form.FormWidget.extend({ instance.web.form.DashBoardLegacy = instance.web.form.DashBoard.extend({ renderElement: function() { if (this.node.tag == 'hpaned') { - this.node.attrs.style = '2-1'; + this.node.attrs.layout = '2-1'; } else if (this.node.tag == 'vpaned') { - this.node.attrs.style = '1'; + this.node.attrs.layout = '1'; } this.node.tag = 'board'; _.each(this.node.children, function(child) { diff --git a/addons/board/static/src/xml/board.xml b/addons/board/static/src/xml/board.xml index 03ede793036..9e1f15562a3 100644 --- a/addons/board/static/src/xml/board.xml +++ b/addons/board/static/src/xml/board.xml @@ -10,7 +10,7 @@ Change Layout - +
diff --git a/addons/l10n_in_hr_payroll/l10n_in_hr_payroll_view.xml b/addons/l10n_in_hr_payroll/l10n_in_hr_payroll_view.xml index 37d2f865770..51c63c730ff 100644 --- a/addons/l10n_in_hr_payroll/l10n_in_hr_payroll_view.xml +++ b/addons/l10n_in_hr_payroll/l10n_in_hr_payroll_view.xml @@ -80,7 +80,7 @@
-
- - Write to the followers of this document... - Share with my followers... -
+ +
+ + Share with my followers... +
+
+ +
+ + Send a message + or + Log a note +
+
@@ -57,10 +68,10 @@ - File + Attach a File - /web/binary/upload_attachment + /web/binary/upload_attachment @@ -106,7 +117,7 @@ template to the recipients list --> -
+
To: @@ -129,14 +140,17 @@ <<<
-
- -
@@ -190,7 +190,7 @@
diff --git a/addons/crm/crm_data.xml b/addons/crm/crm_data.xml index 3726c744b2e..613141b5818 100644 --- a/addons/crm/crm_data.xml +++ b/addons/crm/crm_data.xml @@ -80,8 +80,7 @@ basis for email recipients, name and to ease the definition of a further elaborated template. --> Opportunity - Send Emails - ${object.user_id.email or ''} - Opportunity ${object.name | h}) + ${object.name} ${object.partner_id.id} diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py index f4b27fa4d9d..6c74ead0140 100644 --- a/addons/crm/crm_lead.py +++ b/addons/crm/crm_lead.py @@ -259,7 +259,9 @@ class crm_lead(base_stage, format_address, osv.osv): 'channel_id': fields.many2one('crm.case.channel', 'Channel', help="Communication channel (mail, direct, phone, ...)"), 'contact_name': fields.char('Contact Name', size=64), 'partner_name': fields.char("Customer Name", size=64,help='The name of the future partner company that will be created while converting the lead into opportunity', select=1), - 'opt_out': fields.boolean('Opt-Out', oldname='optout', help="If opt-out is checked, this contact has refused to receive emails or unsubscribed to a campaign."), + 'opt_out': fields.boolean('Opt-Out', oldname='optout', + help="If opt-out is checked, this contact has refused to receive emails for mass mailing and marketing campaign. " + "Filter 'Available for Mass Mailing' allows users to filter the leads when performing mass mailing."), 'type':fields.selection([ ('lead','Lead'), ('opportunity','Opportunity'), ],'Type', help="Type is used to separate Leads and Opportunities"), 'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority', select=True), 'date_closed': fields.datetime('Closed', readonly=True), @@ -711,7 +713,7 @@ class crm_lead(base_stage, format_address, osv.osv): 'parent_id': parent_id, 'phone': lead.phone, 'mobile': lead.mobile, - 'email': lead.email_from and tools.email_split(lead.email_from)[0], + 'email': tools.email_split(lead.email_from) and tools.email_split(lead.email_from)[0] or False, 'fax': lead.fax, 'title': lead.title and lead.title.id or False, 'function': lead.function, @@ -930,7 +932,7 @@ class crm_lead(base_stage, format_address, osv.osv): try: compose_form_id = ir_model_data.get_object_reference(cr, uid, 'mail', 'email_compose_message_wizard_form')[1] except ValueError: - compose_form_id = False + compose_form_id = False if context is None: context = {} ctx = context.copy() @@ -961,13 +963,22 @@ class crm_lead(base_stage, format_address, osv.osv): return [lead.section_id.message_get_reply_to()[0] if lead.section_id else False for lead in self.browse(cr, uid, ids, context=context)] + def message_get_suggested_recipients(self, cr, uid, ids, context=None): + recipients = super(crm_lead, self).message_get_suggested_recipients(cr, uid, ids, context=context) + for lead in self.browse(cr, uid, ids, context=context): + if lead.partner_id: + self._message_add_suggested_recipient(cr, uid, recipients, lead, partner=lead.partner_id, reason=_('Customer')) + elif lead.email_from: + self._message_add_suggested_recipient(cr, uid, recipients, lead, email=lead.email_from, reason=_('Customer Email')) + return recipients + def message_new(self, cr, uid, msg, custom_values=None, context=None): """ Overrides mail_thread message_new that is called by the mailgateway through message_process. This override updates the document according to the email. """ - if custom_values is None: custom_values = {} - + if custom_values is None: + custom_values = {} desc = html2plaintext(msg.get('body')) if msg.get('body') else '' defaults = { 'name': msg.get('subject') or _("No Subject"), @@ -1015,9 +1026,12 @@ class crm_lead(base_stage, format_address, osv.osv): def schedule_phonecall_send_note(self, cr, uid, ids, phonecall_id, action, context=None): phonecall = self.pool.get('crm.phonecall').browse(cr, uid, [phonecall_id], context=context)[0] - if action == 'log': prefix = 'Logged' - else: prefix = 'Scheduled' - message = _("%s a call for the %s.") % (prefix, phonecall.date) + if action == 'log': + prefix = 'Logged' + else: + prefix = 'Scheduled' + suffix = ' %s' % phonecall.description + message = _("%s a call for %s.%s") % (prefix, phonecall.date, suffix) return self.message_post(cr, uid, ids, body=message, context=context) def onchange_state(self, cr, uid, ids, state_id, context=None): diff --git a/addons/crm/crm_lead_view.xml b/addons/crm/crm_lead_view.xml index 87c130547cd..91154b1ee5a 100644 --- a/addons/crm/crm_lead_view.xml +++ b/addons/crm/crm_lead_view.xml @@ -97,7 +97,7 @@ states="draft,open,pending" help="Convert to Opportunity" class="oe_highlight"/> - [[ get_employer_line(o, p).rate or '']] + [[ get_employer_line(o, p) and get_employer_line(o, p).rate or '']] - [[ get_employer_line(o,p).total or '' ]] + [[ get_employer_line(o,p) and get_employer_line(o,p).total or '' ]]