From fec027e83203e6705f690469cd39101e4eba3b06 Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Tue, 15 Jan 2013 11:40:15 +0100 Subject: [PATCH 001/518] [IMP] reorder modules menus bzr revid: chs@openerp.com-20130115104015-5ytx00t0b5230aaf --- openerp/addons/base/module/module_view.xml | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/openerp/addons/base/module/module_view.xml b/openerp/addons/base/module/module_view.xml index 3a43a2591ba..3923c9de3bd 100644 --- a/openerp/addons/base/module/module_view.xml +++ b/openerp/addons/base/module/module_view.xml @@ -171,23 +171,18 @@ - - Modules ir.module.module form kanban,tree,form -

No module found!

You should try others search criteria.

- + @@ -195,20 +190,14 @@ Apps apps - - + Updates apps.updates {} - - + From 7e1a76cdd846a8c455d402fcd76d8baa58a9b2f8 Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Tue, 15 Jan 2013 11:40:47 +0100 Subject: [PATCH 002/518] [FIX] setup.py: correct windows install bzr revid: chs@openerp.com-20130115104047-6hrl825bn5pkmoo6 --- setup.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/setup.py b/setup.py index b144924d022..e4e6001d302 100755 --- a/setup.py +++ b/setup.py @@ -43,6 +43,12 @@ def data(): base = os.path.join('pytz', root[len(tzdir) + 1:]) r[base] = [os.path.join(root, f) for f in filenames] + import docutils + dudir = os.path.dirname(docutils.__file__) + for root, _, filenames in os.walk(dudir): + base = os.path.join('docutils', root[len(dudir) + 1:]) + r[base] = [os.path.join(root, f) for f in filenames if not f.endswith(('.py', '.pyc', '.pyo'))] + return r.items() def gen_manifest(): From e2639618f666605e385befb578db3f889a8c035f Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 17 Jan 2013 10:27:22 +0100 Subject: [PATCH 003/518] [DOC] remove openerpdev intersphinx, add ref to module doc bzr revid: xmo@openerp.com-20130117092722-6rfhkcu4igrgeo06 --- addons/web/doc/conf.py | 1 - addons/web/doc/module.rst | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/web/doc/conf.py b/addons/web/doc/conf.py index 54434190707..7fe38022ab1 100644 --- a/addons/web/doc/conf.py +++ b/addons/web/doc/conf.py @@ -253,6 +253,5 @@ todo_include_todos = True intersphinx_mapping = { 'python': ('http://docs.python.org/', None), 'openerpserver': ('http://doc.openerp.com/trunk/developers/server', None), - 'openerpdev': ('http://doc.openerp.com/trunk/developers', None), 'openerpcommand': ('http://doc.openerp.com/trunk/developers/command', None), } diff --git a/addons/web/doc/module.rst b/addons/web/doc/module.rst index 1bdb7c14799..8306e885f65 100644 --- a/addons/web/doc/module.rst +++ b/addons/web/doc/module.rst @@ -1,3 +1,5 @@ +.. _module: + Building an OpenERP Web module ============================== From 3574038ffdf78e8c63430ecc92a4f2d916207fda Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Thu, 17 Jan 2013 14:29:24 +0100 Subject: [PATCH 004/518] [FIX] apps: install_from_url: fix install condition + better logging bzr revid: chs@openerp.com-20130117132924-ejzbkh5przqi6hwf --- openerp/addons/base/module/module.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/openerp/addons/base/module/module.py b/openerp/addons/base/module/module.py index 9e8b68451c5..123bf4124ed 100644 --- a/openerp/addons/base/module/module.py +++ b/openerp/addons/base/module/module.py @@ -2,7 +2,7 @@ ############################################################################## # # OpenERP, Open Source Management Solution -# Copyright (C) 2004-2012 OpenERP S.A. (). +# Copyright (C) 2004-2013 OpenERP S.A. (). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -656,6 +656,7 @@ class module(osv.osv): def install_from_urls(self, cr, uid, urls, context=None): OPENERP = 'openerp' tmp = tempfile.mkdtemp() + _logger.debug('Install from url: %r', urls) try: # 1. Download & unzip missing modules for module_name, url in urls.items(): @@ -672,12 +673,13 @@ class module(osv.osv): zipfile.ZipFile(StringIO(content)).extractall(tmp) assert os.path.isdir(os.path.join(tmp, module_name)) - # 2a. Copy/Replace module source in addons path + # 2a. Copy/Replace module source in addons path for module_name, url in urls.items(): if module_name == OPENERP or not url: continue # OPENERP is special case, handled below, and no URL means local module module_path = modules.get_module_path(module_name, downloaded=True, display_warning=False) bck = backup(module_path, False) + _logger.info('Copy downloaded module `%s` to `%s`', module_name, module_path) shutil.move(os.path.join(tmp, module_name), module_path) if bck: shutil.rmtree(bck) @@ -697,15 +699,22 @@ class module(osv.osv): # then replace the server by the new "base" module server_dir = openerp.tools.config['root_path'] # XXX or dirname() bck = backup(server_dir) + _logger.info('Copy downloaded module `openerp` to `%s`', server_dir) shutil.move(os.path.join(tmp, OPENERP), server_dir) #if bck: # shutil.rmtree(bck) self.update_list(cr, uid, context=context) - ids = self.search(cr, uid, [('name', 'in', urls.keys())], context=context) - if self.search_count(cr, uid, [('id', 'in', ids), ('state', '=', 'installed')], context=context): - # if any to update + with_urls = [m for m, u in urls.items() if u] + downloaded_ids = self.search(cr, uid, [('name', 'in', with_urls)], context=context) + already_installed = self.search(cr, uid, [('id', 'in', downloaded_ids), ('state', '=', 'installed')], context=context) + + to_install_ids = self.search(cr, uid, [('name', 'in', urls.keys()), ('state', '=', 'uninstalled')], context=context) + post_install_action = self.button_immediate_install(cr, uid, to_install_ids, context=context) + + if already_installed: + # in this case, force server restart to reload python code... cr.commit() openerp.service.restart_server() return { @@ -713,7 +722,7 @@ class module(osv.osv): 'tag': 'home', 'params': {'wait': True}, } - return self.button_immediate_install(cr, uid, ids, context=context) + return post_install_action finally: shutil.rmtree(tmp) From 4857a8a020d81ebd375122fb478726103c3f2393 Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Thu, 17 Jan 2013 14:51:08 +0100 Subject: [PATCH 005/518] [FIX] module loading: call adapt_version() instead of computing it ourself bzr revid: chs@openerp.com-20130117135108-a4wt4wtbtfdwiui3 --- openerp/modules/loading.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/openerp/modules/loading.py b/openerp/modules/loading.py index fb68642f137..638a40c9fa8 100644 --- a/openerp/modules/loading.py +++ b/openerp/modules/loading.py @@ -3,7 +3,7 @@ # # OpenERP, Open Source Management Solution # Copyright (C) 2004-2009 Tiny SPRL (). -# Copyright (C) 2010-2012 OpenERP s.a. (). +# Copyright (C) 2010-2013 OpenERP s.a. (). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -36,14 +36,12 @@ import openerp.modules.graph import openerp.modules.migration import openerp.osv as osv import openerp.pooler as pooler -import openerp.release as release import openerp.tools as tools from openerp import SUPERUSER_ID -from openerp import SUPERUSER_ID from openerp.tools.translate import _ from openerp.modules.module import initialize_sys_path, \ - load_openerp_module, init_module_models + load_openerp_module, init_module_models, adapt_version _logger = logging.getLogger(__name__) @@ -213,7 +211,7 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, skip_modules= migrations.migrate_module(package, 'post') - ver = release.major_version + '.' + package.data['version'] + ver = adapt_version(package.data['version']) # Set new modules and dependencies modobj.write(cr, SUPERUSER_ID, [module_id], {'state': 'installed', 'latest_version': ver}) # Update translations for all installed languages From 66cadcdb18c9ce0f48a05cf7d13cb98ed2f171e5 Mon Sep 17 00:00:00 2001 From: Anael Closson Date: Fri, 10 May 2013 17:19:34 +0200 Subject: [PATCH 007/518] [FIX] OPW 591344 : internal reports don't show images Cleaner method, and shows images. bzr revid: acl@openerp.com-20130510151934-e2kvwiexdzp3zc12 --- openerp/report/render/rml2pdf/trml2pdf.py | 54 +++++++---------------- 1 file changed, 17 insertions(+), 37 deletions(-) diff --git a/openerp/report/render/rml2pdf/trml2pdf.py b/openerp/report/render/rml2pdf/trml2pdf.py index e8d6375c98e..153eff14b65 100644 --- a/openerp/report/render/rml2pdf/trml2pdf.py +++ b/openerp/report/render/rml2pdf/trml2pdf.py @@ -82,53 +82,33 @@ def _open_image(filename, path=None): pass raise IOError("File %s cannot be found in image path" % filename) + class NumberedCanvas(canvas.Canvas): def __init__(self, *args, **kwargs): canvas.Canvas.__init__(self, *args, **kwargs) - self._codes = [] - self._flag=False - self._pageCount=0 - self._currentPage =0 - self._pageCounter=0 - self.pages={} + self._saved_page_states = [] def showPage(self): - self._currentPage +=1 - if not self._flag: - self._pageCount += 1 - else: - self.pages.update({self._currentPage:self._pageCount}) - self._codes.append({'code': self._code, 'stack': self._codeStack}) + self._saved_page_states.append(dict(self.__dict__)) self._startPage() - self._flag=False - - def pageCount(self): - if self.pages.get(self._pageCounter,False): - self._pageNumber=0 - self._pageCounter +=1 - key=self._pageCounter - if not self.pages.get(key,False): - while not self.pages.get(key,False): - key += 1 - self.setFont("Helvetica", 8) - self.drawRightString((self._pagesize[0]-30), (self._pagesize[1]-40), - " %(this)i / %(total)i" % { - 'this': self._pageNumber+1, - 'total': self.pages.get(key,False), - } - ) def save(self): """add page info to each page (page x of y)""" - # reset page counter - self._pageNumber = 0 - for code in self._codes: - self._code = code['code'] - self._codeStack = code['stack'] - self.pageCount() + num_pages = len(self._saved_page_states) + for state in self._saved_page_states: + self.__dict__.update(state) + self.draw_page_number(num_pages) canvas.Canvas.showPage(self) -# self.restoreState() - self._doc.SaveToFile(self._filename, self) + canvas.Canvas.save(self) + + def draw_page_number(self, page_count): + self.drawRightString((self._pagesize[0]-30), (self._pagesize[1]-40), + " %(this)i / %(total)i" % { + 'this': self._pageNumber, + 'total': page_count, + } + ) + class PageCount(platypus.Flowable): def __init__(self, story_count=0): From 46e89d6dd1427ac5c7fa144f3b36e6ea1779771d Mon Sep 17 00:00:00 2001 From: Mohammed Shekha Date: Thu, 20 Jun 2013 16:16:06 +0530 Subject: [PATCH 008/518] [FIX]Fixed the issue of recurrent rule, there is no need of passing 'Z' after end_date as end_date converted to UNTIL parameter in rrule, and date given in UNTIL is not converted to any other timezone until you specifically passed timezone difference or timezone name like 20130620T121012+3:30 or 20130620T121012TZOFFSET, currently Z creates issue when recurrent rule is created with end_date, TypeError: can't compare offset-naive and offset-aware datetimes. bzr revid: msh@openerp.com-20130620104606-g3dyr1mafzo8fpgg --- addons/base_calendar/base_calendar.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/base_calendar/base_calendar.py b/addons/base_calendar/base_calendar.py index 25bfcac448c..41a142cde68 100644 --- a/addons/base_calendar/base_calendar.py +++ b/addons/base_calendar/base_calendar.py @@ -1269,7 +1269,7 @@ rule or repeating pattern of time to exclude from the recurring rule."), def get_end_date(data): if data.get('end_date'): - data['end_date_new'] = ''.join((re.compile('\d')).findall(data.get('end_date'))) + 'T235959Z' + data['end_date_new'] = ''.join((re.compile('\d')).findall(data.get('end_date'))) + 'T235959' return (data.get('end_type') == 'count' and (';COUNT=' + str(data.get('count'))) or '') +\ ((data.get('end_date_new') and data.get('end_type') == 'end_date' and (';UNTIL=' + data.get('end_date_new'))) or '') From 3276861ff6125d02e08b5c5b12b75925e056c4bc Mon Sep 17 00:00:00 2001 From: "Xavier Fernandez http://www.smile.fr" <> Date: Wed, 28 Aug 2013 17:21:17 +0200 Subject: [PATCH 009/518] [FIX] port Xavier Fernandez's fix for Bug #971412: Translations export has no fixed order lp bug: https://launchpad.net/bugs/971412 fixed bzr revid: ls@numerigraphe.com-20130828152117-e1h0yljgbn538v9o --- openerp/tools/translate.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openerp/tools/translate.py b/openerp/tools/translate.py index 41113b8ccd9..53762b87970 100644 --- a/openerp/tools/translate.py +++ b/openerp/tools/translate.py @@ -458,7 +458,8 @@ def trans_export(lang, modules, buffer, format, cr): row.setdefault('tnrs', []).append((type, name, res_id)) row.setdefault('comments', set()).update(comments) - for src, row in grouped_rows.items(): + for src in sorted(grouped_rows): + row = grouped_rows[src] if not lang: # translation template, so no translation value row['translation'] = '' From 1f3a482f4fc309262802b980e143234a56b9503d Mon Sep 17 00:00:00 2001 From: Lionel Sausin Date: Thu, 29 Aug 2013 09:50:35 +0200 Subject: [PATCH 010/518] [REF] avoid the lookup in sorted translation export as suggested by Guewen Baconnier @ Camptocamp bzr revid: ls@numerigraphe.com-20130829075035-lml81a7bbn66c8qu --- openerp/tools/translate.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openerp/tools/translate.py b/openerp/tools/translate.py index 53762b87970..6e9eb50f162 100644 --- a/openerp/tools/translate.py +++ b/openerp/tools/translate.py @@ -458,8 +458,7 @@ def trans_export(lang, modules, buffer, format, cr): row.setdefault('tnrs', []).append((type, name, res_id)) row.setdefault('comments', set()).update(comments) - for src in sorted(grouped_rows): - row = grouped_rows[src] + for src, row in sorted(grouped_rows.items()): if not lang: # translation template, so no translation value row['translation'] = '' From 0dcc62426c3689191798fbe33717eea5d4659a96 Mon Sep 17 00:00:00 2001 From: Yanina Aular Date: Fri, 15 Nov 2013 17:57:17 -0430 Subject: [PATCH 011/518] [FIX] function field with wrong type int instead of integer bzr revid: yanina.aular@vauxoo.com-20131115222717-12bplq7rnv3rorbm --- addons/project/project.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/project/project.py b/addons/project/project.py index 5bd2e604368..c7b394ad376 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -288,7 +288,8 @@ class project(osv.osv): help="The kind of document created when an email is received on this project's email alias"), 'privacy_visibility': fields.selection(_visibility_selection, 'Privacy / Visibility', required=True), 'state': fields.selection([('template', 'Template'),('draft','New'),('open','In Progress'), ('cancelled', 'Cancelled'),('pending','Pending'),('close','Closed')], 'Status', required=True,), - 'doc_count':fields.function(_get_attached_docs, string="Number of documents attached", type='int') + 'doc_count':fields.function(_get_attached_docs, string="Number of documents attached", + type='integer') } def _get_type_common(self, cr, uid, context): From 02224a3f112426c9e15a8af7cde2e7a5406d1885 Mon Sep 17 00:00:00 2001 From: "Dharti Ratani (Open ERP)" Date: Thu, 12 Dec 2013 10:55:44 +0530 Subject: [PATCH 012/518] [FIX]Added the refernce of the supplier in price_get method while creating purchase order from purchase requisition, as without supplier the price unit in PO was 0 when the pricelist item was based on Supplier Price in the product form bzr revid: dhr@tinyerp.com-20131212052544-skljxsrxea4o8efm --- addons/purchase_requisition/purchase_requisition.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/purchase_requisition/purchase_requisition.py b/addons/purchase_requisition/purchase_requisition.py index c1d80c7bf46..c31f8a69a37 100644 --- a/addons/purchase_requisition/purchase_requisition.py +++ b/addons/purchase_requisition/purchase_requisition.py @@ -109,7 +109,7 @@ class purchase_requisition(osv.osv): seller_delay = product_supplier.delay seller_qty = product_supplier.qty supplier_pricelist = supplier.property_product_pricelist_purchase or False - seller_price = pricelist.price_get(cr, uid, [supplier_pricelist.id], product.id, qty, False, {'uom': default_uom_po_id})[supplier_pricelist.id] + seller_price = pricelist.price_get(cr, uid, [supplier_pricelist.id], product.id, qty, supplier.id, {'uom': default_uom_po_id})[supplier_pricelist.id] if seller_qty: qty = max(qty,seller_qty) date_planned = self._planned_date(requisition_line.requisition_id, seller_delay) From f6349ffb7fd9c075573953be2ac0f0dc20520743 Mon Sep 17 00:00:00 2001 From: Leonardo Pistone Date: Wed, 18 Dec 2013 17:45:26 +0100 Subject: [PATCH 013/518] [merge] [fix] action should return True lp bug: https://launchpad.net/bugs/1262265 fixed bzr revid: leonardo.pistone@camptocamp.com-20131218164526-rgyo6p9hlpk28sxg --- addons/mrp_repair/mrp_repair.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/mrp_repair/mrp_repair.py b/addons/mrp_repair/mrp_repair.py index 9c0ab0e2c18..9335d395714 100644 --- a/addons/mrp_repair/mrp_repair.py +++ b/addons/mrp_repair/mrp_repair.py @@ -350,7 +350,8 @@ class mrp_repair(osv.osv): return self.write(cr,uid,ids,{'state':'cancel'}) def wkf_invoice_create(self, cr, uid, ids, *args): - return self.action_invoice_create(cr, uid, ids) + self.action_invoice_create(cr, uid, ids) + return True def action_invoice_create(self, cr, uid, ids, group=False, context=None): """ Creates invoice(s) for repair order. From 262a405b0ab1018bde19e61d38a4525582831a16 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Fri, 3 Jan 2014 14:07:03 +0100 Subject: [PATCH 014/518] Remove old FR VAT taxes 19.6% and 7.0%. Remove the FR VAT tax 5.0% that has never seen the light ! bzr revid: alexis@via.ecp.fr-20140103130703-kpf5rojc4azwq8w1 --- addons/l10n_fr/fr_fiscal_templates.xml | 79 ----- addons/l10n_fr/fr_tax.xml | 387 ------------------------- 2 files changed, 466 deletions(-) diff --git a/addons/l10n_fr/fr_fiscal_templates.xml b/addons/l10n_fr/fr_fiscal_templates.xml index bf49d15e08c..cca96422c22 100644 --- a/addons/l10n_fr/fr_fiscal_templates.xml +++ b/addons/l10n_fr/fr_fiscal_templates.xml @@ -40,11 +40,6 @@ - - - - - @@ -57,22 +52,12 @@ - - - - - - - - - - @@ -91,17 +76,6 @@ - - - - - - - - - - - @@ -124,17 +98,6 @@ - - - - - - - - - - - @@ -146,17 +109,6 @@ - - - - - - - - - - - @@ -177,11 +129,6 @@ - - - - - @@ -194,22 +141,12 @@ - - - - - - - - - - @@ -224,11 +161,6 @@ - - - - - @@ -241,23 +173,12 @@ - - - - - - - - - - - diff --git a/addons/l10n_fr/fr_tax.xml b/addons/l10n_fr/fr_tax.xml index 8633cca7141..22e1e12f03c 100644 --- a/addons/l10n_fr/fr_tax.xml +++ b/addons/l10n_fr/fr_tax.xml @@ -29,28 +29,6 @@ sale - - - - TVA collectée (vente) 19,6% - 19.6 - - percent - - - - - - - - - - - - - - sale - @@ -96,51 +74,7 @@ sale - - - TVA collectée (vente) 7,0% - 7.0 - - percent - - - - - - - - - - - - - - sale - - - - TVA collectée (vente) 5,0% - 5.0 - - percent - - - - - - - - - - - - - - sale - - - TVA collectée (vente) 5,5% 5.5 @@ -208,28 +142,6 @@ purchase - - - TVA déductible (achat) 19,6% - ACH-19.6 - - percent - - - - - - - - - - - - - - purchase - - TVA déductible (achat) 8,5% @@ -274,51 +186,7 @@ purchase - - - TVA déductible (achat) 7,0% - ACH-7.0 - - percent - - - - - - - - - - - - - - purchase - - - - TVA déductible (achat) 5,0% - ACH-5.0 - - percent - - - - - - - - - - - - - - purchase - - - TVA déductible (achat) 5,5% ACH-5.5 @@ -387,29 +255,6 @@ purchase - - - TVA déductible (achat) 19,6% TTC - ACH-19.6-TTC - - - percent - - - - - - - - - - - - - - purchase - - TVA déductible (achat) 8,5% TTC @@ -456,53 +301,7 @@ purchase - - - TVA déductible (achat) 7,0% TTC - ACH-7.0-TTC - - - percent - - - - - - - - - - - - - - purchase - - - - TVA déductible (achat) 5,0% TTC - ACH-5.0-TTC - - - percent - - - - - - - - - - - - - - purchase - - - TVA déductible (achat) 5,5% TTC ACH-5.5-TTC @@ -573,28 +372,6 @@ purchase - - - TVA déd./immobilisation (achat) 19,6% - IMMO-19.6 - - percent - - - - - - - - - - - - - - purchase - - TVA déd./immobilisation (achat) 8,5% @@ -639,51 +416,7 @@ purchase - - - TVA déd./immobilisation (achat) 7,0% - IMMO-7.0 - - percent - - - - - - - - - - - - - - purchase - - - - TVA déd./immobilisation (achat) 5,0% - IMMO-5.0 - - percent - - - - - - - - - - - - - - purchase - - - TVA déd./immobilisation (achat) 5,5% IMMO-5.5 @@ -751,28 +484,6 @@ purchase - - - TVA due s/ acq. intracommunautaire (achat) 19,6% - ACH_UE_due-19.6 - - percent - - - - - - - - - - - - - - purchase - - TVA due s/ acq. intracommunautaire (achat) 8,5% @@ -817,51 +528,7 @@ purchase - - - TVA due s/ acq. intracommunautaire (achat) 7,0% - ACH_UE_due-7.0 - - percent - - - - - - - - - - - - - - purchase - - - - TVA due s/ acq. intracommunautaire (achat) 5,0% - ACH_UE_due-5.0 - - percent - - - - - - - - - - - - - - purchase - - - TVA due s/ acq. intracommunautaire (achat) 5,5% ACH_UE_due-5.5 @@ -925,24 +592,6 @@ purchase - - - TVA déd. s/ acq. intracommunautaire (achat) 19,6% - ACH_UE_ded.-19.6 - - percent - - - - - - - - - - purchase - - TVA déd. s/ acq. intracommunautaire (achat) 8,5% @@ -979,43 +628,7 @@ purchase - - - TVA déd. s/ acq. intracommunautaire (achat) 7,0% - ACH_UE_ded.-7.0 - - percent - - - - - - - - - - purchase - - - - TVA déd. s/ acq. intracommunautaire (achat) 5,0% - ACH_UE_ded.-5.0 - - percent - - - - - - - - - - purchase - - - TVA déd. s/ acq. intracommunautaire (achat) 5,5% ACH_UE_ded.-5.5 From 6abf20906e7b5d3e319a227301fbcf1a6d4492b7 Mon Sep 17 00:00:00 2001 From: jke-openerp Date: Sat, 1 Feb 2014 21:04:13 +0100 Subject: [PATCH 015/518] [Typo] Replace t-esc in t-field for amount_untaxed in checkout of website_sale. Else display monetary does not work bzr revid: jke@openerp.com-20140201200413-zww5pcobl6vmvqe1 --- addons/website_sale/views/website_sale.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/website_sale/views/website_sale.xml b/addons/website_sale/views/website_sale.xml index ed2007e27c7..cc1220a57e7 100644 --- a/addons/website_sale/views/website_sale.xml +++ b/addons/website_sale/views/website_sale.xml @@ -832,7 +832,7 @@
Subtotal:
-
From c18d3504689228807d6703b920b43d6c4e6e6721 Mon Sep 17 00:00:00 2001 From: jke-openerp Date: Sat, 1 Feb 2014 21:47:41 +0100 Subject: [PATCH 016/518] [FIX] Fix bug where button with contenteditable does not work in cross browser. Fix : replace tag 'button' by 'a' with class 'a-submit' bzr revid: jke@openerp.com-20140201204741-ygdxaauq0m5axttg --- addons/website_sale/static/src/js/website_sale.js | 4 ++++ addons/website_sale/views/website_sale.xml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/addons/website_sale/static/src/js/website_sale.js b/addons/website_sale/static/src/js/website_sale.js index 7f6d24373f7..eedbb5a046c 100644 --- a/addons/website_sale/static/src/js/website_sale.js +++ b/addons/website_sale/static/src/js/website_sale.js @@ -60,6 +60,10 @@ $(document).ready(function () { return false; }); + $('.a-submit').on('click', function () { + $(this).closest('form').submit(); + }); + // change price when they are variants $('form.js_add_cart_json label').on('mouseup', function (ev) { ev.preventDefault(); diff --git a/addons/website_sale/views/website_sale.xml b/addons/website_sale/views/website_sale.xml index ed2007e27c7..d6c86c81e8b 100644 --- a/addons/website_sale/views/website_sale.xml +++ b/addons/website_sale/views/website_sale.xml @@ -331,7 +331,7 @@ }'/>
- + Add to Cart


From 763496be49813da85aecb518116f7ccc7f30eac2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 6 Feb 2014 10:48:31 +0100 Subject: [PATCH 017/518] [IMP] mail: added message_last_update field. This field is a datetime field, updated everytime message_post in called. This allows to build filters, search or actions based on the last message date, for reporting for example. bzr revid: tde@openerp.com-20140206094831-nvyds6nqz0v25t59 --- addons/mail/mail_thread.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index ee4dcac5414..c1006182000 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -296,6 +296,9 @@ class mail_thread(osv.AbstractModel): auto_join=True, string='Messages', help="Messages and communication history"), + 'message_last_update': fields.datetime('Last Message Date', + help='Date of the last message posted on the record. Only messages going' + 'through the message_post API are taken into account for better performances.'), 'message_unread': fields.function(_get_message_data, fnct_search=_search_message_unread, multi="_get_message_data", type='boolean', string='Unread Messages', @@ -1522,8 +1525,13 @@ class mail_thread(osv.AbstractModel): for x in ('from', 'to', 'cc'): values.pop(x, None) - # Create and auto subscribe the author + # Post the message msg_id = mail_message.create(cr, uid, values, context=context) + + # Post-process: subscribe author, update message_last_update + if model and model != 'mail.thread' and thread_id: + # done with SUPERUSER_ID, because on some models users can post only with read access, not necessarily write access + self.write(cr, SUPERUSER_ID, [thread_id], {'message_last_update': fields.datetime.now()}, context=context) message = mail_message.browse(cr, uid, msg_id, context=context) if message.author_id and thread_id and type != 'notification' and not context.get('mail_create_nosubscribe'): self.message_subscribe(cr, uid, [thread_id], [message.author_id.id], context=context) From 7d656e961b69939a1b68abae10741a4f156c60f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me?= Date: Thu, 13 Feb 2014 15:30:44 +0100 Subject: [PATCH 018/518] [ADD] crm_project_issue: link module to create lead from issues and issues from lead bzr revid: jem@openerp.com-20140213143044-p06ef9scr32ihef2 --- addons/crm_project_issue/__init__.py | 3 +++ addons/crm_project_issue/__openerp__.py | 21 +++++++++++++++ addons/crm_project_issue/crm_lead.py | 10 +++++++ addons/crm_project_issue/crm_lead_view.xml | 27 +++++++++++++++++++ addons/crm_project_issue/project_issue.py | 14 ++++++++++ .../crm_project_issue/project_issue_view.xml | 17 ++++++++++++ 6 files changed, 92 insertions(+) create mode 100644 addons/crm_project_issue/__init__.py create mode 100644 addons/crm_project_issue/__openerp__.py create mode 100644 addons/crm_project_issue/crm_lead.py create mode 100644 addons/crm_project_issue/crm_lead_view.xml create mode 100644 addons/crm_project_issue/project_issue.py create mode 100644 addons/crm_project_issue/project_issue_view.xml diff --git a/addons/crm_project_issue/__init__.py b/addons/crm_project_issue/__init__.py new file mode 100644 index 00000000000..40302ae183c --- /dev/null +++ b/addons/crm_project_issue/__init__.py @@ -0,0 +1,3 @@ + +import project_issue +import crm_lead \ No newline at end of file diff --git a/addons/crm_project_issue/__openerp__.py b/addons/crm_project_issue/__openerp__.py new file mode 100644 index 00000000000..89ef20a655e --- /dev/null +++ b/addons/crm_project_issue/__openerp__.py @@ -0,0 +1,21 @@ +{ + 'name' : 'CRM Project Issues', + 'version': '1.0', + 'summary': 'Module linker between Leads and Issues', + 'sequence': '19', + 'category': 'Project Management', + 'complexity': 'easy', + 'description': + """ +CRM Project Issues +================== + +Link module to map leads and issues + """, + 'data': [ + 'project_issue_view.xml', + 'crm_lead_view.xml', + ], + 'depends' : ['crm', 'project_issue'], + 'installable': True, +} diff --git a/addons/crm_project_issue/crm_lead.py b/addons/crm_project_issue/crm_lead.py new file mode 100644 index 00000000000..ec83af18a39 --- /dev/null +++ b/addons/crm_project_issue/crm_lead.py @@ -0,0 +1,10 @@ + +from openerp.osv import osv, fields + + +class crm_lead(osv.Model): + _inherit = 'crm.lead' + + _columns = { + 'project_issue_ids': fields.one2many('project.issue', 'lead_id', "Project Issues"), + } diff --git a/addons/crm_project_issue/crm_lead_view.xml b/addons/crm_project_issue/crm_lead_view.xml new file mode 100644 index 00000000000..0e81f16fa9f --- /dev/null +++ b/addons/crm_project_issue/crm_lead_view.xml @@ -0,0 +1,27 @@ + + + + + + lead.form + crm.lead + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/addons/crm_project_issue/project_issue.py b/addons/crm_project_issue/project_issue.py new file mode 100644 index 00000000000..9409aeb51ae --- /dev/null +++ b/addons/crm_project_issue/project_issue.py @@ -0,0 +1,14 @@ + +from openerp.osv import osv, fields + + +class project_issue(osv.Model): + _inherit = 'project.issue' + + _columns = { + 'lead_id': fields.many2one('crm.lead', ondelete='set null', string="Related lead"), + } + + _defaults = { + + } \ No newline at end of file diff --git a/addons/crm_project_issue/project_issue_view.xml b/addons/crm_project_issue/project_issue_view.xml new file mode 100644 index 00000000000..18a03b5a2c1 --- /dev/null +++ b/addons/crm_project_issue/project_issue_view.xml @@ -0,0 +1,17 @@ + + + + + + project.issue.form + project.issue + + + + + + + + + + \ No newline at end of file From 8bbb20650464b5784fd3afa0eb219ed1802e2a4f Mon Sep 17 00:00:00 2001 From: "ddm@openerp.com" <> Date: Thu, 13 Feb 2014 16:24:49 +0100 Subject: [PATCH 019/518] [IMP] save new orders only bzr revid: ddm@openerp.com-20140213152449-tarl15agw9r3teqg --- addons/point_of_sale/point_of_sale.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/addons/point_of_sale/point_of_sale.py b/addons/point_of_sale/point_of_sale.py index 30fcff2e5e6..dec4431a15c 100644 --- a/addons/point_of_sale/point_of_sale.py +++ b/addons/point_of_sale/point_of_sale.py @@ -513,13 +513,18 @@ class pos_order(osv.osv): _order = "id desc" def create_from_ui(self, cr, uid, orders, context=None): - #_logger.info("orders: %r", orders) + + # Keep only new orders + submitted_references = [o['data']['name'] for o in orders] + existing_orders = self.search_read(cr, uid, [('pos_reference', 'in', submitted_references)], context) + existing_references = set([o['pos_reference'] for o in existing_orders]) + orders_to_save = [o for o in orders if o['data']['name'] not in existing_references] + order_ids = [] - for tmp_order in orders: + for tmp_order in orders_to_save: to_invoice = tmp_order['to_invoice'] order = tmp_order['data'] - order_id = self.create(cr, uid, { 'name': order['name'], 'user_id': order['user_id'] or False, From e7f238615ca1c79700a0deacb1d1799b797a0472 Mon Sep 17 00:00:00 2001 From: "ddm@openerp.com" <> Date: Thu, 13 Feb 2014 17:38:49 +0100 Subject: [PATCH 020/518] [IMP] fetch only relevant fields when checking for dupes bzr revid: ddm@openerp.com-20140213163849-8v485vq5v4xmeocg --- addons/point_of_sale/point_of_sale.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/point_of_sale/point_of_sale.py b/addons/point_of_sale/point_of_sale.py index 9e78a29cfec..01e7a49ec8c 100644 --- a/addons/point_of_sale/point_of_sale.py +++ b/addons/point_of_sale/point_of_sale.py @@ -517,7 +517,7 @@ class pos_order(osv.osv): # Keep only new orders submitted_references = [o['data']['name'] for o in orders] - existing_orders = self.search_read(cr, uid, [('pos_reference', 'in', submitted_references)], context) + existing_orders = self.search_read(cr, uid, domain=[('pos_reference', 'in', submitted_references)], fields=['pos_reference'], context=context) existing_references = set([o['pos_reference'] for o in existing_orders]) orders_to_save = [o for o in orders if o['data']['name'] not in existing_references] From 3ea931c48637265183ce17b8cfb21c858f90a56d Mon Sep 17 00:00:00 2001 From: "ddm@openerp.com" <> Date: Fri, 14 Feb 2014 15:49:30 +0100 Subject: [PATCH 021/518] [IMP] save all orders at once (client) bzr revid: ddm@openerp.com-20140214144930-5zpn3miys1hwrdoa --- addons/point_of_sale/static/src/js/models.js | 97 ++++++++++---------- 1 file changed, 51 insertions(+), 46 deletions(-) diff --git a/addons/point_of_sale/static/src/js/models.js b/addons/point_of_sale/static/src/js/models.js index 6b54c14113d..90aa5fece05 100644 --- a/addons/point_of_sale/static/src/js/models.js +++ b/addons/point_of_sale/static/src/js/models.js @@ -421,62 +421,67 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal // it is therefore important to only call this method from inside a mutex // this method returns a deferred indicating wether the sending was successful or not // there is a timeout parameter which is set to 2 seconds by default. - _flush_order: function(order_id, options){ - var self = this; - options = options || {}; - timeout = typeof options.timeout === 'number' ? options.timeout : 7500; - - this.set('synch',{state:'connecting', pending: this.get('synch').pending}); - - var order = this.db.get_order(order_id); - order.to_invoice = options.to_invoice || false; - - if(!order){ - // flushing a non existing order always fails - return (new $.Deferred()).reject(); - } - - // we try to send the order. shadow prevents a spinner if it takes too long. (unless we are sending an invoice, - // then we want to notify the user that we are waiting on something ) - var rpc = (new instance.web.Model('pos.order')).call('create_from_ui',[[order]],undefined,{shadow: !options.to_invoice, timeout:timeout}); - - rpc.fail(function(unused,event){ - // prevent an error popup creation by the rpc failure - // we want the failure to be silent as we send the orders in the background - event.preventDefault(); - console.error('Failed to send order:',order); - }); - - rpc.done(function(){ - self.db.remove_order(order_id); - var pending = self.db.get_orders().length; - self.set('synch',{state: pending ? 'connecting' : 'connected', pending:pending}); - }); - - return rpc; + _flush_order: function( order_id, options) { + return this._flush_all_orders([this.db.get_order(order_id)], options); }, // attempts to send all the locally stored orders. As with _flush_order, it should only be // called from within a mutex. // this method returns a deferred that always succeeds when all orders have been tried to be sent, // even if none of them could actually be sent. - _flush_all_orders: function(){ + _flush_all_orders: function () { var self = this; - var orders = this.db.get_orders(); - var tried_all = new $.Deferred(); + self.set('synch', { + state: 'connecting', + pending: self.get('synch').pending + }); + return self._save_to_server(self.db.get_orders()).done(function () { + var pending = self.db.get_orders().length; + self.set('synch', { + state: pending ? 'connecting' : 'connected', + pending: pending + }); + }); + }, - function rec_flush(index){ - if(index < orders.length){ - self._flush_order(orders[index].id).always(function(){ - rec_flush(index+1); - }) - }else{ - tried_all.resolve(); - } + // send an array of orders to the server + // available options: + // - timeout: timeout for the rpc call in ms + _save_to_server: function (orders, options) { + if (!orders || !orders.length) { + var result = $.Deferred(); + result.resolve(); + return result; } - rec_flush(0); + + options = options || {}; - return tried_all; + var self = this; + var timeout = typeof options.timeout === 'number' ? options.timeout : 7500; + + // we try to send the order. shadow prevents a spinner if it takes too long. (unless we are sending an invoice, + // then we want to notify the user that we are waiting on something ) + var posOrderModel = new instance.web.Model('pos.order'); + return posOrderModel.call('create_from_ui', + [_.map(orders, function (order) { + order.to_invoice = options.to_invoice || false; + return order; + })], + undefined, + { + shadow: !options.to_invoice, + timeout: timeout + } + ).then(function () { + _.each(orders, function (order) { + self.db.remove_order(order.id); + }); + }).fail(function (unused, event){ + // prevent an error popup creation by the rpc failure + // we want the failure to be silent as we send the orders in the background + event.preventDefault(); + console.error('Failed to send orders:', orders); + }); }, scan_product: function(parsed_code){ From 0ff108c00c72742693c20cb22d251bee7d463978 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me?= Date: Mon, 17 Feb 2014 14:57:31 +0100 Subject: [PATCH 022/518] [ADD] change the link between lead and issue. Now : transfrom a lead into a issue and modify the mail thread bzr revid: jem@openerp.com-20140217135731-538vluw7i1gverjf --- addons/crm_project_issue/__init__.py | 3 +- addons/crm_project_issue/__openerp__.py | 3 +- addons/crm_project_issue/project_issue.py | 36 +++++++++--- .../crm_project_issue/project_issue_view.xml | 55 ++++++++++++++----- addons/mail/mail_thread.py | 31 +++++++++++ 5 files changed, 103 insertions(+), 25 deletions(-) diff --git a/addons/crm_project_issue/__init__.py b/addons/crm_project_issue/__init__.py index 40302ae183c..1d0a3f683ea 100644 --- a/addons/crm_project_issue/__init__.py +++ b/addons/crm_project_issue/__init__.py @@ -1,3 +1,2 @@ -import project_issue -import crm_lead \ No newline at end of file +import project_issue \ No newline at end of file diff --git a/addons/crm_project_issue/__openerp__.py b/addons/crm_project_issue/__openerp__.py index 89ef20a655e..e50a6dbfa2a 100644 --- a/addons/crm_project_issue/__openerp__.py +++ b/addons/crm_project_issue/__openerp__.py @@ -13,8 +13,7 @@ CRM Project Issues Link module to map leads and issues """, 'data': [ - 'project_issue_view.xml', - 'crm_lead_view.xml', + 'project_issue_view.xml' ], 'depends' : ['crm', 'project_issue'], 'installable': True, diff --git a/addons/crm_project_issue/project_issue.py b/addons/crm_project_issue/project_issue.py index 9409aeb51ae..8e7a0733932 100644 --- a/addons/crm_project_issue/project_issue.py +++ b/addons/crm_project_issue/project_issue.py @@ -1,14 +1,36 @@ from openerp.osv import osv, fields +class crm_lead_to_project_issue_wizard(osv.TransientModel): + """ wizard to convert a Lead into a Project Issue and move the Mail Thread """ -class project_issue(osv.Model): - _inherit = 'project.issue' + def action_lead_to_project_issue(self, cr, uid, ids, context=None): + # get the wizards + wizards = self.browse(cr, uid, ids, context=context) + lead_model = self.pool.get("crm.lead") + issue_model = self.pool.get("project.issue") + + for wizard in wizards: + # get the lead to transform + lead = lead_model.browse(cr, uid, wizard.lead_id.id, context=context) + # create new project.issue + vals = {} + vals["name"] = lead.name + vals["description"] = lead.description + vals["email_from"] = lead.email_from + vals["partner_id"] = lead.partner_id.id + vals["project_id"] = wizard.project_id.id + issue_id = issue_model.create(cr, uid, vals, context=None) + # move the mail thread + lead_model.transform_model_messages(cr, uid, wizard.lead_id.id, issue_id, "project.issue", context=context) + # delete the lead + lead_model.unlink(cr, uid, [wizard.lead_id.id], context=None) + return False + + + _name = "crm.lead2projectissue.wizard" _columns = { - 'lead_id': fields.many2one('crm.lead', ondelete='set null', string="Related lead"), - } - - _defaults = { - + "lead_id" : fields.many2one("crm.lead","Lead", domain=[("type","=","lead")]), + "project_id" : fields.many2one("project.project", "Project", domain=[("use_issues","=",True)]) } \ No newline at end of file diff --git a/addons/crm_project_issue/project_issue_view.xml b/addons/crm_project_issue/project_issue_view.xml index 18a03b5a2c1..57cf256bdd3 100644 --- a/addons/crm_project_issue/project_issue_view.xml +++ b/addons/crm_project_issue/project_issue_view.xml @@ -1,17 +1,44 @@ - + - - - - project.issue.form - project.issue - - - - - - - + - + + + CRM - Leads Form + crm.lead + + + +