From 8bc8d7e1ebf134188f249588074e909ff7ac299e Mon Sep 17 00:00:00 2001 From: Olivier Laurent Date: Wed, 17 Dec 2008 10:18:58 +0100 Subject: [PATCH 001/124] Fixed: zero divison error bzr revid: olt@tinyerp.com-20081217091858-u3mpm5lj6qrlpgtt --- addons/crm/report/report_businessopp.py | 34 +++++++++++++++---------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/addons/crm/report/report_businessopp.py b/addons/crm/report/report_businessopp.py index bb2663a09a0..a351379bd6b 100644 --- a/addons/crm/report/report_businessopp.py +++ b/addons/crm/report/report_businessopp.py @@ -1,7 +1,7 @@ # -*- encoding: utf-8 -*- ############################################################################## # -# OpenERP, Open Source Management Solution +# OpenERP, Open Source Management Solution # Copyright (C) 2004-2008 Tiny SPRL (). All Rights Reserved # $Id$ # @@ -30,7 +30,7 @@ import StringIO import tools import pooler -from report.render import render +from report.render import render from report.interface import report_int from pychart import * @@ -43,7 +43,7 @@ class external_pdf(render): render.__init__(self) self.pdf = pdf self.output_type='pdf' - + def _render(self): return self.pdf @@ -64,13 +64,13 @@ class report_custom(report_int): cost = row['planned_cost'] or 0 revenue = row['planned_revenue'] or 0 userid = row['user_id'] or 0 - + benefit = revenue - cost if benefit > maxbenef: maxbenef = benefit if benefit < minbenef: minbenef = benefit - + tuple = (proba * 100, benefit) responsible_data.setdefault(userid, []) responsible_data[userid].append(tuple) @@ -82,19 +82,19 @@ class report_custom(report_int): minbenef -= maxbenef * 0.05 maxbenef *= 1.2 - + ratio = 0.5 minmaxdiff2 = (maxbenef - minbenef)/2 - + for l in responsible_data.itervalues(): for i in range(len(l)): percent, benef = l[i] proba = percent/100 current_ratio = 1 + (ratio-1) * proba - + newbenef = minmaxdiff2 + ((benef - minbenef - minmaxdiff2) * current_ratio) - + l[i] = (percent, newbenef) #TODO: @@ -103,23 +103,29 @@ class report_custom(report_int): pdf_string = StringIO.StringIO() can = canvas.init(fname=pdf_string, format='pdf') - + chart_object.set_defaults(line_plot.T, line_style=None) - + xaxis = axis.X(label=None, format="%d%%", tic_interval=20) yaxis = axis.Y() + x_range_a, x_range_b = (0,100) + y_range_a, y_range_b = (minbenef, maxbenef) + if y_range_a == 0.0: + y_range_a += 0.0001 + ar = area.T( size = (300,200), y_grid_interval = 10000, y_grid_style=None, - x_range = (0,100), - y_range = (minbenef, maxbenef), + x_range = (x_range_a, x_range_b), + y_range = (y_range_a, y_range_b), x_axis = xaxis, y_axis = None, legend = legend.T() ) + #import pydb; pydb.debugger() for k, d in responsible_data.iteritems(): fill = fill_style.Plain(bgcolor=color.T(r=random.random(), g=random.random(), b=random.random())) tick = tick_mark.Square(size=6, fill_style=fill) @@ -131,7 +137,7 @@ class report_custom(report_int): ar = area.T(legend = legend.T(), size = (200,100), loc=(100,250), - x_grid_interval = lambda min, max: [40,60,80,100], + x_grid_interval = lambda min, max: [40,60,80,100], x_grid_style=line_style.gray70_dash1, x_range = (33, 100), x_axis = axis.X(label=None, minor_tic_interval=lambda min,max: [50, 70, 90], format=lambda x: ""), From 24a02a61dc2bd8a9aa68ccff6c9f7a30cc9ae1f7 Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Wed, 17 Dec 2008 10:25:54 +0100 Subject: [PATCH 002/124] [FIX] fix crash when updating crm_configuration module bzr revid: christophe@cobalt-20081217092554-71f72u61bp5rbpil --- addons/crm_configuration/report/crm_report.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/addons/crm_configuration/report/crm_report.py b/addons/crm_configuration/report/crm_report.py index 775eb7ec5cc..156f7c21a44 100644 --- a/addons/crm_configuration/report/crm_report.py +++ b/addons/crm_configuration/report/crm_report.py @@ -28,6 +28,13 @@ AVAILABLE_STATES = [ ('done', 'Closed'), ('pending','Pending') ] + +def drop_view_if_exists(cr, viewname): + cr.execute("select count(1) from pg_class where relkind=%s and relname=%s", ('v', viewname,)) + if cr.fetchone(): + cr.execute("DROP view %s" % (viewname,)) + cr.commit() + class report_crm_case_section_categ2(osv.osv): _name = "report.crm.case.section.categ2" _description = "Cases by section and category2" @@ -46,8 +53,9 @@ class report_crm_case_section_categ2(osv.osv): _order = 'category2_id, section_id' def init(self, cr): + drop_view_if_exists(cr, "report_crm_case_section_categ2") cr.execute(""" - create or replace view report_crm_case_section_categ2 as ( + create view report_crm_case_section_categ2 as ( select min(c.id) as id, to_char(c.create_date,'YYYY-MM')||'-01' as name, @@ -84,8 +92,9 @@ class report_crm_case_section_stage(osv.osv): _order = 'stage_id, section_id' def init(self, cr): + drop_view_if_exists(cr, "report_crm_case_section_stage") cr.execute(""" - create or replace view report_crm_case_section_stage as ( + create view report_crm_case_section_stage as ( select min(c.id) as id, to_char(c.create_date,'YYYY-MM')||'-01' as name, @@ -120,8 +129,9 @@ class report_crm_case_section_categ_stage(osv.osv): _order = 'stage_id, section_id, categ_id' def init(self, cr): + drop_view_if_exists(cr, "report_crm_case_section_categ_stage") cr.execute(""" - create or replace view report_crm_case_section_categ_stage as ( + create view report_crm_case_section_categ_stage as ( select min(c.id) as id, to_char(c.create_date,'YYYY-MM')||'-01' as name, @@ -157,8 +167,9 @@ class report_crm_case_section_categ_categ2(osv.osv): _order = 'section_id, categ_id, category2_id' def init(self, cr): + drop_view_if_exists(cr, "report_crm_case_section_categ_categ2") cr.execute(""" - create or replace view report_crm_case_section_categ_categ2 as ( + create view report_crm_case_section_categ_categ2 as ( select min(c.id) as id, to_char(c.create_date, 'YYYY-MM')||'-01' as name, From ddfaa6678f2c5e79256a995a829b546a8b6f18a3 Mon Sep 17 00:00:00 2001 From: Olivier Laurent Date: Wed, 17 Dec 2008 10:37:31 +0100 Subject: [PATCH 003/124] 'order.partner_id.property_account_tax' does not exists anymore -> now using 'fiscal position' bzr revid: olt@tinyerp.com-20081217093731-f0gcwsi8356pzbv3 --- addons/point_of_sale/pos.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/addons/point_of_sale/pos.py b/addons/point_of_sale/pos.py index f7d88253590..6d77cb35e78 100644 --- a/addons/point_of_sale/pos.py +++ b/addons/point_of_sale/pos.py @@ -60,7 +60,9 @@ class pos_order(osv.osv): res = dict(cr.fetchall()) for rec in self.browse(cr, uid, ids, context): - if rec.partner_id and rec.partner_id.property_account_tax: + if rec.partner_id \ + and rec.partner_id.property_account_position \ + and rec.partner_id.property_account_position.tax_ids: res[rec.id] = res[rec.id] - rec.amount_tax return res From 269e7a6ec154fe2c88830446ad7321ae5d39fd65 Mon Sep 17 00:00:00 2001 From: hmo-tinyerp <> Date: Wed, 17 Dec 2008 15:13:42 +0530 Subject: [PATCH 004/124] fixed bug:308803 bzr revid: hmo-tinyerp-20081217094342-qlzormyrn7kjupnv --- addons/sale/stock.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/sale/stock.py b/addons/sale/stock.py index 79cd9a22e51..0c6ec645150 100644 --- a/addons/sale/stock.py +++ b/addons/sale/stock.py @@ -99,7 +99,7 @@ class stock_picking(osv.osv): sale_line_obj = self.pool.get('sale.order.line') if move_line.sale_line_id: sale_line_obj.write(cursor, user, [move_line.sale_line_id.id], {'invoiced':True, - 'invoice_lines': [(6, 0, [invoice_line_id])], + 'invoice_lines': [(4, invoice_line_id)], }) return super(stock_picking, self)._invoice_line_hook(cursor, user, move_line, invoice_line_id) From b035f7169269cffded32c889cb8b3630ae2ca35c Mon Sep 17 00:00:00 2001 From: Mustufa Rangwala Date: Wed, 17 Dec 2008 18:18:00 +0530 Subject: [PATCH 005/124] bug fix on membership bzr revid: mra@tinyerp.com-20081217124800-6nrloa8zxdo8s0zo --- addons/membership/membership.py | 81 +++++++++++-------- .../membership/wizard/invoice_membership.py | 17 ++-- 2 files changed, 58 insertions(+), 40 deletions(-) diff --git a/addons/membership/membership.py b/addons/membership/membership.py index a1480201dc8..ed034f7a59d 100644 --- a/addons/membership/membership.py +++ b/addons/membership/membership.py @@ -1,7 +1,7 @@ # -*- encoding: utf-8 -*- ############################################################################## # -# OpenERP, Open Source Management Solution +# OpenERP, Open Source Management Solution # Copyright (C) 2004-2008 Tiny SPRL (). All Rights Reserved # $Id$ # @@ -225,11 +225,11 @@ membership_line() class Partner(osv.osv): '''Partner''' - def _membership_state_search_inv(self, cr, uid, ids, context=None): - data_inv = self.pool.get('account.invoice').browse(cr, uid, ids, context) + def _get_partner_id(self, cr, uid, ids, context=None): + data_inv = self.pool.get('membership.membership_line').browse(cr, uid, ids, context) list_partner = [] for data in data_inv: - list_partner.append(data.partner_id.id) + list_partner.append(data.partner.id) return list_partner def _membership_state(self, cr, uid, ids, name, args, context=None): @@ -237,7 +237,6 @@ class Partner(osv.osv): for id in ids: res[id] = 'none' today = time.strftime('%Y-%m-%d') - for id in ids: partner_data = self.browse(cr,uid,id) if partner_data.membership_cancel and today > partner_data.membership_cancel: @@ -437,7 +436,8 @@ class Partner(osv.osv): # 'membership_state': fields.function(_membership_state, method=True, string='Current membership state', # type='selection', selection=STATE, fnct_search=_membership_state_search), 'membership_state': fields.function(_membership_state, method=True, string='Current membership state', - type='selection',selection=STATE,store={'account.invoice':(_membership_state_search_inv,['state'], 10)}), + type='selection',selection=STATE,store={'membership.membership_line':(_get_partner_id,['state'], 10), + 'res.partner':(lambda self,cr,uid,ids,c={}:ids, ['free_member'], 10)}), # 'associate_member': fields.many2one('res.partner', 'Associate member'), 'free_member': fields.boolean('Free member'), 'membership_start': fields.function(_membership_start, method=True, @@ -501,36 +501,53 @@ class Invoice(osv.osv): _inherit = 'account.invoice' - - def action_move_create(self, cr, uid, ids, context=None): - '''Create membership.membership_line if the product is for membership''' - if context is None: - context = {} + def create(self, cr, uid, vals, context={}): + result = super(Invoice, self).create(cr, uid, vals, context) + a = self.browse(cr, uid, result) member_line_obj = self.pool.get('membership.membership_line') - partner_obj = self.pool.get('res.partner') - for invoice in self.browse(cr, uid, ids): - - # fetch already existing member lines - former_mlines = member_line_obj.search(cr,uid, - [('account_invoice_line','in', - [ l.id for l in invoice.invoice_line])], context) - # empty them : - if former_mlines: - member_line_obj.write(cr,uid,former_mlines, {'account_invoice_line':False}, context) - - for line in invoice.invoice_line: - if line.product_id and line.product_id.membership: - date_from = line.product_id.membership_date_from - date_to = line.product_id.membership_date_to - if invoice.date_invoice > date_from and invoice.date_invoice < date_to: - date_from = invoice.date_invoice - member_line_obj.create(cr, uid, { - 'partner': invoice.partner_id.id, + for i in a.invoice_line: + if i.product_id and i.product_id.membership: + date_from = i.product_id.membership_date_from + date_to = i.product_id.membership_date_to + if a.date_invoice > date_from and a.date_invoice < date_to: + date_from = a.date_invoice + line_id = member_line_obj.create(cr, uid, { + 'partner': a.partner_id.id, 'date_from': date_from, 'date_to': date_to, - 'account_invoice_line': line.id, + 'account_invoice_line': i.id, }) - return super(Invoice, self).action_move_create(cr, uid, ids, context) + return result + +# def action_move_create(self, cr, uid, ids, context=None): +# '''Create membership.membership_line if the product is for membership''' +# if context is None: +# context = {} +# member_line_obj = self.pool.get('membership.membership_line') +# partner_obj = self.pool.get('res.partner') +# for invoice in self.browse(cr, uid, ids): +# +# # fetch already existing member lines +# former_mlines = member_line_obj.search(cr,uid, +# [('account_invoice_line','in', +# [ l.id for l in invoice.invoice_line])], context) +# # empty them : +# if former_mlines: +# member_line_obj.write(cr,uid,former_mlines, {'account_invoice_line':False}, context) +# +# for line in invoice.invoice_line: +# if line.product_id and line.product_id.membership: +# date_from = line.product_id.membership_date_from +# date_to = line.product_id.membership_date_to +# if invoice.date_invoice > date_from and invoice.date_invoice < date_to: +# date_from = invoice.date_invoice +# line_id = member_line_obj.create(cr, uid, { +# 'partner': invoice.partner_id.id, +# 'date_from': date_from, +# 'date_to': date_to, +# 'account_invoice_line': line.id, +# }) +# return super(Invoice, self).action_move_create(cr, uid, ids, context) def action_cancel(self, cr, uid, ids, context=None): '''Create a 'date_cancel' on the membership_line object''' diff --git a/addons/membership/wizard/invoice_membership.py b/addons/membership/wizard/invoice_membership.py index abf8ca40f4a..b3e326930e6 100644 --- a/addons/membership/wizard/invoice_membership.py +++ b/addons/membership/wizard/invoice_membership.py @@ -1,7 +1,7 @@ # -*- encoding: utf-8 -*- ############################################################################## # -# OpenERP, Open Source Management Solution +# OpenERP, Open Source Management Solution # Copyright (C) 2004-2008 Tiny SPRL (). All Rights Reserved # $Id$ # @@ -60,15 +60,8 @@ def _invoice_membership(self, cr, uid, data, context): for partner_id in partner_ids: account_id = partner_obj.read(cr, uid, partner_id, ['property_account_receivable'])['property_account_receivable'][0] - invoice_id = invoice_obj.create(cr, uid, { - 'partner_id' : partner_id, - 'address_invoice_id': partner_address_ids[partner_id]['id'], - 'account_id': account_id, - } - ) line_value = { - 'invoice_id' : invoice_id, 'product_id' : product_id, } @@ -81,12 +74,20 @@ def _invoice_membership(self, cr, uid, data, context): tax_tab = [(6, 0, line_value['invoice_line_tax_id'])] line_value['invoice_line_tax_id'] = tax_tab invoice_line_id = invoice_line_obj.create(cr, uid, line_value) + invoice_id = invoice_obj.create(cr, uid, { + 'partner_id' : partner_id, + 'address_invoice_id': partner_address_ids[partner_id]['id'], + 'account_id': account_id, + 'invoice_line':[(6,0,[invoice_line_id])] + } + ) invoice_list.append(invoice_id) if line_value['invoice_line_tax_id']: invoice_obj.write(cr, uid, [invoice_id], {'tax_line':tax_tab}) tax_value = invoice_tax_obj.compute(cr, uid, invoice_id).values()[0] invoice_tax_obj.create(cr, uid, tax_value) + value = { 'domain': [ ('id', 'in', invoice_list), From e421e22896d51fcde62567cabd6ee2f38d7306d7 Mon Sep 17 00:00:00 2001 From: Olivier Laurent Date: Wed, 17 Dec 2008 14:05:14 +0100 Subject: [PATCH 006/124] Merged the Launchpad translations with the Bazaar po files bzr revid: olt@tinyerp.com-20081217130514-le0f8okf9q0hzrzn --- addons/account/i18n/fr_FR.po | 221 +++++++++++++++++++---------------- 1 file changed, 122 insertions(+), 99 deletions(-) diff --git a/addons/account/i18n/fr_FR.po b/addons/account/i18n/fr_FR.po index 8f2141f970b..e9eaac4adc8 100644 --- a/addons/account/i18n/fr_FR.po +++ b/addons/account/i18n/fr_FR.po @@ -8,7 +8,9 @@ msgstr "" "Report-Msgid-Bugs-To: support@openerp.com\n" "POT-Creation-Date: 2008-11-28 16:57:27+0000\n" "PO-Revision-Date: 2008-11-28 16:57:27+0000\n" -"Last-Translator: <>\n" +"POT-Creation-Date: 2008-11-28 17:09+0000\n" +"PO-Revision-Date: 2008-12-04 14:33+0000\n" +"Last-Translator: Christophe Chauvet - http://www.syleam.fr/ \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -17,10 +19,10 @@ msgstr "" "X-Generator: Launchpad (build Unknown)\n" #. module: account -#, python-format #: code:addons/account/account.py:0 +#, python-format msgid "Integrity Error !" -msgstr "" +msgstr "Erreur d'Intégrité !" #. module: account #: view:account.move:0 @@ -64,10 +66,14 @@ msgid "Asset" msgstr "Actif (avoirs)" #. module: account -#, python-format #: code:addons/account/wizard/wizard_validate_account_move.py:0 -msgid "Specified Journal does not have any account move entries in draft state for this period" +#, python-format +msgid "" +"Specified Journal does not have any account move entries in draft state for " +"this period" msgstr "" +"Le Journal Spécifié ne possède aucune écriture de compte à l'état brouillon pour " +"cette période" #. module: account #: selection:account.tax,tax_group:0 @@ -100,12 +106,12 @@ msgstr "Nouvelle facture client" #. module: account #: view:account.account:0 msgid "Account Statistics" -msgstr "" +msgstr "Statistiques du Compte" #. module: account #: wizard_field:account.general.ledger.report,checktype,date_from:0 msgid " Start date" -msgstr "" +msgstr " Date de début" #. module: account #: field:account.account,parent_id:0 @@ -116,12 +122,12 @@ msgstr "Parent" #. module: account #: selection:account.move,type:0 msgid "Journal Voucher" -msgstr "" +msgstr "Pièce Justificative" #. module: account #: field:account.invoice,residual:0 msgid "Residual" -msgstr "" +msgstr "Résiduel" #. module: account #: field:account.subscription,date_start:0 @@ -129,15 +135,15 @@ msgid "Starting date" msgstr "Début de la période" #. module: account -#, python-format #: code:addons/account/wizard/wizard_refund.py:0 +#, python-format msgid "Can not %s draft invoice." -msgstr "" +msgstr "Impossible de %s une facture brouillon." #. module: account #: wizard_field:account.general.ledger.report,checktype,sortbydate:0 msgid "Sort by:" -msgstr "" +msgstr "Trier sur:" #. module: account #: model:ir.actions.wizard,name:account.wizard_unreconcile_select @@ -181,7 +187,7 @@ msgstr "Quantité" #. module: account #: view:account.move:0 msgid "Total Credit" -msgstr "" +msgstr "Crédit Total" #. module: account #: field:account.analytic.line,product_uom_id:0 @@ -192,13 +198,13 @@ msgstr "UdM" #. module: account #: rml:account.account.balance:0 msgid "Account Balance -" -msgstr "" +msgstr "Balance du Compte -" #. module: account #: model:ir.actions.wizard,name:account.wizard_general_journal #: model:ir.ui.menu,name:account.menu_general_journal msgid "Print General journal" -msgstr "" +msgstr "Imprimer le Journal Général" #. module: account #: rml:account.third_party_ledger:0 @@ -224,8 +230,8 @@ msgid "Compute Code (if type=code)" msgstr "Code de Calcul (si type=code)" #. module: account -#, python-format #: code:addons/account/account_move_line.py:0 +#, python-format msgid "You have to provide an account for the write off entry !" msgstr "" @@ -243,7 +249,7 @@ msgstr "Echéancier" #. module: account #: model:ir.ui.menu,name:account.menu_finance_recurrent_entries msgid "Recurrent Entries" -msgstr "" +msgstr "Écritures récurrentes" #. module: account #: rml:account.invoice:0 @@ -273,17 +279,17 @@ msgstr "Taxes fournisseurs" #. module: account #: view:account.move:0 msgid "Total Debit" -msgstr "" +msgstr "Débit Total" #. module: account #: rml:account.tax.code.entries:0 msgid "Accounting Entries-" -msgstr "" +msgstr "Écritures Comptable" #. module: account #: selection:account.move,type:0 msgid "Bank Receipt" -msgstr "" +msgstr "Reçu Bancaire" #. module: account #: rml:account.vat.declaration:0 @@ -297,16 +303,16 @@ msgid "Fixed" msgstr "Fixe" #. module: account -#, python-format #: code:addons/account/invoice.py:0 +#, python-format msgid "Warning !" -msgstr "" +msgstr "Avertissement !" #. module: account -#, python-format #: code:addons/account/account.py:0 +#, python-format msgid "You can not delete posted movement: \"%s\"!" -msgstr "" +msgstr "Vous ne pouvez pas effacer de mouvement posté: \"%s\" !" #. module: account #: wizard_view:account.analytic.account.analytic.check.report,init:0 @@ -365,15 +371,15 @@ msgid "Tax" msgstr "Impôts et taxes" #. module: account -#, python-format #: code:addons/account/account_move_line.py:0 +#, python-format msgid "No analytic journal !" -msgstr "" +msgstr "Pas de journal analytique !" #. module: account #: rml:account.general.journal:0 msgid "Debit Trans." -msgstr "" +msgstr "Débit Trans." #. module: account #: field:account.analytic.line,account_id:0 @@ -408,7 +414,7 @@ msgstr "Partenaire" #. module: account #: field:account.fiscal.position.account,account_src_id:0 msgid "Account Source" -msgstr "" +msgstr "Source Comptable" #. module: account #: field:account.journal,update_posted:0 @@ -419,13 +425,13 @@ msgstr "Autoriser l'annulation des entrées" #: model:process.transition,name:account.process_transition_paymentorderbank0 #: model:process.transition,name:account.process_transition_paymentorderreconcilation0 msgid "Payment Reconcilation" -msgstr "" +msgstr "Réconciliation du Paiement" #. module: account -#, python-format #: code:addons/account/account_move_line.py:0 +#, python-format msgid "Wrong Accounting Entry!" -msgstr "" +msgstr "Écriture Comptable Incorrecte !" #. module: account #: model:ir.actions.act_window,name:account.act_acc_analytic_acc_5_report_hr_timesheet_invoice_journal @@ -479,15 +485,15 @@ msgid "State" msgstr "État" #. module: account -#, python-format #: code:addons/account/account_move_line.py:0 +#, python-format msgid "Entry is already reconciled" -msgstr "" +msgstr "L'Écriture est déjà réconciliée" #. module: account #: view:account.bank.statement:0 msgid "Import Invoice" -msgstr "" +msgstr "Importer la Facture" #. module: account #: help:account.tax,base_code_id:0 @@ -510,7 +516,7 @@ msgstr "Calcul particulier" #. module: account #: model:process.transition,note:account.process_transition_confirmstatementfromdraft0 msgid "Confirm statement with/without reconciliation from draft statement" -msgstr "" +msgstr "Veuillez confirmer le relevé avec/sans réconciliation du relevé brouillon" #. module: account #: wizard_view:account.move.bank.reconcile,init:0 @@ -628,8 +634,8 @@ msgid "Mvt" msgstr "" #. module: account -#, python-format #: code:addons/account/account_move_line.py:0 +#, python-format msgid "You can not use this general account in this journal !" msgstr "" @@ -671,8 +677,8 @@ msgid "Contact" msgstr "Contact" #. module: account -#, python-format #: code:addons/account/account.py:0 +#, python-format msgid "You can not validate a non balanced entry !" msgstr "" @@ -710,12 +716,13 @@ msgid "Start of period" msgstr "Début de la période" #. module: account -#, python-format #: code:addons/account/account_move_line.py:0 +#, python-format msgid "You can not add/modify entries in a closed journal." msgstr "" #. module: account +#: code:addons/account/account_move_line.py:0 #, python-format msgid "" "You can not do this modification on a reconciled entry ! Please note that " @@ -764,8 +771,8 @@ msgid "_Customer invoices" msgstr "" #. module: account -#, python-format #: code:addons/account/invoice.py:0 +#, python-format msgid "You must first select a partner !" msgstr "" @@ -788,8 +795,8 @@ msgid "Tax Code Sign" msgstr "Facteur multiplicateur" #. module: account -#, python-format #: code:addons/account/account_bank_statement.py:0 +#, python-format msgid "Account move line \"%s\" is not valid" msgstr "" @@ -995,8 +1002,8 @@ msgid "Fiscal Positions" msgstr "" #. module: account -#, python-format #: code:addons/account/account_move_line.py:0 +#, python-format msgid "Both Credit and Debit cannot be zero!" msgstr "" @@ -1160,7 +1167,7 @@ msgstr "Montant payé" #. module: account #: selection:account.account.type,sign:0 msgid "Positive" -msgstr "" +msgstr "Positif" #. module: account #: wizard_view:account.open_closed_fiscalyear,init:0 @@ -1325,9 +1332,10 @@ msgid "Reconcile With Write-Off" msgstr "" #. module: account -#, python-format #: code:addons/account/account_bank_statement.py:0 -msgid "The expected balance (%.2f) is different than the computed one. (%.2f)" +#, python-format +msgid "" +"The expected balance (%.2f) is different than the computed one. (%.2f)" msgstr "" #. module: account @@ -1426,9 +1434,11 @@ msgid "Analytic lines" msgstr "Lignes analytiques" #. module: account -#, python-format #: code:addons/account/account_move_line.py:0 -msgid "You can not do this modification on a confirmed entry ! Please note that you can just change some non important fields !" +#, python-format +msgid "" +"You can not do this modification on a confirmed entry ! Please note that you " +"can just change some non important fields !" msgstr "" #. module: account @@ -1498,7 +1508,7 @@ msgstr "" #. module: account #: field:account.chart.template,property_account_receivable:0 msgid "Receivable Account" -msgstr "" +msgstr "Compte Recevable" #. module: account #: wizard_view:account.move.line.reconcile,init_partial:0 @@ -1557,7 +1567,7 @@ msgstr "Creer periodes par trimestre" #. module: account #: wizard_view:account.general.journal.report,init:0 msgid "Print General Journal" -msgstr "" +msgstr "Imprimer le Journal Général" #. module: account #: model:ir.actions.act_window,name:account.action_account_chart_template_form @@ -1575,11 +1585,11 @@ msgstr "Transactions" #: model:ir.ui.menu,name:account.menu_wizard #: view:wizard.multi.charts.accounts:0 msgid "Generate Chart of Accounts from a Chart Template" -msgstr "" +msgstr "Générer le Plan de Comptes à partir d'un Modèle de Plan" #. module: account -#, python-format #: code:addons/account/account_bank_statement.py:0 +#, python-format msgid "The statement balance is incorrect !\n" msgstr "" @@ -1702,8 +1712,8 @@ msgid "Starting Balance" msgstr "Solde de début" #. module: account -#, python-format #: code:addons/account/invoice.py:0 +#, python-format msgid "No Partner Defined !" msgstr "" @@ -1721,13 +1731,13 @@ msgid "Unreconciliation" msgstr "Déréconciliation" #. module: account -#, python-format #: code:addons/account/invoice.py:0 #: code:addons/account/account_move_line.py:0 #: code:addons/account/account.py:0 #: code:addons/account/wizard/wizard_open_closed_fiscalyear.py:0 #: code:addons/account/wizard/wizard_fiscalyear_close.py:0 #: code:addons/account/wizard/wizard_journal.py:0 +#, python-format msgid "UserError" msgstr "" @@ -1785,7 +1795,9 @@ msgstr "Ré-Ouvrir" #. module: account #: help:account.invoice,number:0 -msgid "Uniq number of the invoice, computed automatically when the invoice is created." +msgid "" +"Uniq number of the invoice, computed automatically when the invoice is " +"created." msgstr "" #. module: account @@ -1850,8 +1862,8 @@ msgid "Account code" msgstr "Code du compte" #. module: account -#, python-format #: code:addons/account/account_move_line.py:0 +#, python-format msgid "You can not use an inactive account!" msgstr "" @@ -1880,7 +1892,9 @@ msgstr "Journal des ajustements" #. module: account #: help:res.partner,property_account_position:0 -msgid "The fiscal position will determine taxes and the accounts used for the the partner." +msgid "" +"The fiscal position will determine taxes and the accounts used for the the " +"partner." msgstr "" #. module: account @@ -1889,8 +1903,8 @@ msgid "Account Manager" msgstr "Comptable" #. module: account -#, python-format #: code:addons/account/account_move_line.py:0 +#, python-format msgid "Entries are not of the same account or already reconciled ! " msgstr "" @@ -2022,8 +2036,8 @@ msgid "Total amount this customer owns you." msgstr "" #. module: account -#, python-format #: code:addons/account/invoice.py:0 +#, python-format msgid "Invalid action !" msgstr "" @@ -2093,8 +2107,8 @@ msgid "Journal-Period Name" msgstr "Nom de la période du journal" #. module: account -#, python-format #: code:addons/account/wizard/wizard_fiscalyear_close.py:0 +#, python-format msgid "There are no periods defined on New Fiscal Year." msgstr "" @@ -2267,8 +2281,8 @@ msgid "Root Account" msgstr "Compte Racine" #. module: account -#, python-format #: code:addons/account/account_bank_statement.py:0 +#, python-format msgid "Configration Error !" msgstr "" @@ -2315,8 +2329,8 @@ msgid "x Checks Journal" msgstr "" #. module: account -#, python-format #: code:addons/account/wizard/wizard_pay_invoice.py:0 +#, python-format msgid "Your journal must have a default credit and debit account." msgstr "" @@ -2369,9 +2383,11 @@ msgid "Date" msgstr "Date" #. module: account -#, python-format #: code:addons/account/account.py:0 -msgid "No period defined for this date !\nPlease create a fiscal year." +#, python-format +msgid "" +"No period defined for this date !\n" +"Please create a fiscal year." msgstr "" #. module: account @@ -2397,8 +2413,8 @@ msgid "Statement Entries" msgstr "" #. module: account -#, python-format #: code:addons/account/wizard/wizard_fiscalyear_close.py:0 +#, python-format msgid "The journal must have default credit and debit account" msgstr "" @@ -2433,12 +2449,14 @@ msgstr "Réconciliation automatique" #. module: account #: constraint:account.period:0 -msgid "Error ! The date duration of the Period(s) should be within the limit of the Fiscal year. " +msgid "" +"Error ! The date duration of the Period(s) should be within the limit of the " +"Fiscal year. " msgstr "" #. module: account -#, python-format #: code:addons/account/account_move_line.py:0 +#, python-format msgid "Some entries are already reconciled !" msgstr "" @@ -2510,8 +2528,8 @@ msgid "Print Central journal" msgstr "" #. module: account -#, python-format #: code:addons/account/invoice.py:0 +#, python-format msgid "No Analytic Journal !" msgstr "" @@ -2636,7 +2654,9 @@ msgstr "Annuler" #. module: account #: help:account.account.type,sign:0 -msgid "Allows to change the displayed amount of the balance in the reports, in order to see positive results instead of negative ones in expenses accounts." +msgid "" +"Allows to change the displayed amount of the balance in the reports, in " +"order to see positive results instead of negative ones in expenses accounts." msgstr "" #. module: account @@ -2700,8 +2720,8 @@ msgstr "" "est important." #. module: account -#, python-format #: code:addons/account/account_move_line.py:0 +#, python-format msgid "Already Reconciled" msgstr "" @@ -2734,9 +2754,11 @@ msgid "In dispute" msgstr "En litige" #. module: account -#, python-format #: code:addons/account/account.py:0 -msgid "No fiscal year defined for this date !\nPlease create one." +#, python-format +msgid "" +"No fiscal year defined for this date !\n" +"Please create one." msgstr "" #. module: account @@ -2755,8 +2777,8 @@ msgid "Power" msgstr "Puissance" #. module: account -#, python-format #: code:addons/account/account_bank_statement.py:0 +#, python-format msgid "The account entries lines are not in valid state." msgstr "" @@ -2802,8 +2824,8 @@ msgid "O_k" msgstr "" #. module: account -#, python-format #: code:addons/account/wizard/wizard_fiscalyear_close.py:0 +#, python-format msgid "Closing of fiscal year canceled, please check the box !" msgstr "" @@ -2966,8 +2988,8 @@ msgid "Supplier Refund" msgstr "Note de Crédit Fournisseur" #. module: account -#, python-format #: code:addons/account/account_bank_statement.py:0 +#, python-format msgid "Unable to reconcile entry \"%s\": %.2f" msgstr "" @@ -2977,8 +2999,8 @@ msgid "Ending Balance" msgstr "Solde final" #. module: account -#, python-format #: code:addons/account/account_move_line.py:0 +#, python-format msgid "Please set an analytic journal on this financial journal !" msgstr "" @@ -3028,8 +3050,8 @@ msgid "Analytic Journal -" msgstr "" #. module: account -#, python-format #: code:addons/account/account.py:0 +#, python-format msgid "EXJ" msgstr "" @@ -3050,10 +3072,10 @@ msgid "Draft Customer Refunds" msgstr "Note de Crédit Client Brouillon" #. module: account -#, python-format #: code:addons/account/account.py:0 +#, python-format msgid "Sales Journal" -msgstr "" +msgstr "Journal des ventes" #. module: account #: field:account.journal.column,readonly:0 @@ -3156,8 +3178,8 @@ msgid "(" msgstr "(" #. module: account -#, python-format #: code:addons/account/account.py:0 +#, python-format msgid "You can not modify/delete a journal with entries for this period !" msgstr "" @@ -3284,8 +3306,8 @@ msgid "Taxes" msgstr "Taxes" #. module: account -#, python-format #: code:addons/account/account.py:0 +#, python-format msgid "BNK" msgstr "" @@ -3311,15 +3333,15 @@ msgid "Templates for Accounts" msgstr "Modèles pour les Comptes" #. module: account -#, python-format #: code:addons/account/account_move_line.py:0 #: code:addons/account/account_analytic_line.py:0 +#, python-format msgid "Entries: " msgstr "" #. module: account -#, python-format #: code:addons/account/account_move_line.py:0 +#, python-format msgid "The account is not defined to be reconcile !" msgstr "" @@ -3361,8 +3383,8 @@ msgid "30 Days End of Month" msgstr "" #. module: account -#, python-format #: code:addons/account/account.py:0 +#, python-format msgid "Couldn't create move between different companies" msgstr "" @@ -3406,8 +3428,8 @@ msgid "Bank Information" msgstr "" #. module: account -#, python-format #: code:addons/account/account_move_line.py:0 +#, python-format msgid "Entry \"%s\" is not valid !" msgstr "" @@ -3562,13 +3584,13 @@ msgid "Central Journal" msgstr "Journal centralisé" #. module: account -#, python-format #: code:addons/account/account_move_line.py:0 #: code:addons/account/account_analytic_line.py:0 #: code:addons/account/account_bank_statement.py:0 #: code:addons/account/account.py:0 #: code:addons/account/wizard/wizard_pay_invoice.py:0 #: code:addons/account/wizard/wizard_refund.py:0 +#, python-format msgid "Error !" msgstr "" @@ -3635,8 +3657,8 @@ msgid "Project line" msgstr "Ligne de projet" #. module: account -#, python-format #: code:addons/account/account.py:0 +#, python-format msgid "SAJ" msgstr "" @@ -3758,9 +3780,9 @@ msgid "Invoice Date" msgstr "" #. module: account -#, python-format #: code:addons/account/wizard/wizard_open_closed_fiscalyear.py:0 #: code:addons/account/wizard/wizard_fiscalyear_close.py:0 +#, python-format msgid "The journal must have centralised counterpart" msgstr "" @@ -3783,8 +3805,8 @@ msgid "Open for unreconciliation" msgstr "Ouvrir pour déréconciliation" #. module: account -#, python-format #: code:addons/account/invoice.py:0 +#, python-format msgid "Bad total !" msgstr "" @@ -3896,8 +3918,8 @@ msgid "Active" msgstr "Actif" #. module: account -#, python-format #: code:addons/account/account.py:0 +#, python-format msgid "Purchase Journal" msgstr "" @@ -4073,8 +4095,8 @@ msgid "Payable Limit" msgstr "Limite de paiement" #. module: account -#, python-format #: code:addons/account/invoice.py:0 +#, python-format msgid "Global taxes defined, but not in invoice lines !" msgstr "" @@ -4149,7 +4171,7 @@ msgstr "Facture" #: selection:account.analytic.account,state:0 #: selection:account.invoice,state:0 msgid "Open" -msgstr "Ouvrir" +msgstr "Ouverte" #. module: account #: model:ir.ui.menu,name:account.next_id_29 @@ -4410,9 +4432,10 @@ msgid "JNRL" msgstr "" #. module: account -#, python-format #: code:addons/account/wizard/wizard_fiscalyear_close.py:0 -msgid "The new fiscal year should have a journal for new entries define on it" +#, python-format +msgid "" +"The new fiscal year should have a journal for new entries define on it" msgstr "" #. module: account @@ -4435,7 +4458,7 @@ msgstr "Recevables & payables" #. module: account #: rml:account.general.ledger:0 msgid "General Ledger -" -msgstr "" +msgstr "Grand livre -" #. module: account #: field:account.analytic.account,date_start:0 @@ -4529,8 +4552,8 @@ msgid "Entries Encoding by Move" msgstr "" #. module: account -#, python-format #: code:addons/account/account.py:0 +#, python-format msgid "You can not deactivate an account that contains account moves." msgstr "" @@ -4754,9 +4777,9 @@ msgid "The optionnal other currency if it is a multi-currency entry." msgstr "L'autre devise optionnelle si c'est une entrée multi-devise." #. module: account -#, python-format #: code:addons/account/account_move_line.py:0 #: code:addons/account/wizard/wizard_validate_account_move.py:0 +#, python-format msgid "Warning" msgstr "" @@ -4766,8 +4789,8 @@ msgid "Skip" msgstr "" #. module: account -#, python-format #: code:addons/account/wizard/wizard_open_closed_fiscalyear.py:0 +#, python-format msgid "No journal for ending writings have been defined for the fiscal year" msgstr "" @@ -4836,8 +4859,8 @@ msgid "Supplier Invoice" msgstr "Facture fournisseur" #. module: account -#, python-format #: code:addons/account/account_bank_statement.py:0 +#, python-format msgid "Please verify that an account is defined in the journal." msgstr "" @@ -5171,8 +5194,8 @@ msgid "Sign on Reports" msgstr "" #. module: account -#, python-format #: code:addons/account/wizard/wizard_journal.py:0 +#, python-format msgid "This period is already closed !" msgstr "" @@ -5271,8 +5294,8 @@ msgid "Open Entries" msgstr "" #. module: account -#, python-format #: code:addons/account/account_move_line.py:0 +#, python-format msgid "Bad account!" msgstr "" From c421435ffc2171c6320910626443af8ea5ffdcd8 Mon Sep 17 00:00:00 2001 From: Olivier Laurent Date: Wed, 17 Dec 2008 14:13:39 +0100 Subject: [PATCH 007/124] Merged the Launchpad translations with the Bazaar po files bzr revid: olt@tinyerp.com-20081217131339-utr5287sx9iakiu0 --- addons/sale/i18n/fr_FR.po | 156 +++++++++++++++++++++++++++----------- 1 file changed, 112 insertions(+), 44 deletions(-) diff --git a/addons/sale/i18n/fr_FR.po b/addons/sale/i18n/fr_FR.po index 502646bb939..75e1619af82 100644 --- a/addons/sale/i18n/fr_FR.po +++ b/addons/sale/i18n/fr_FR.po @@ -8,12 +8,15 @@ msgstr "" "Report-Msgid-Bugs-To: support@openerp.com\n" "POT-Creation-Date: 2008-11-28 16:57:27+0000\n" "PO-Revision-Date: 2008-11-28 16:57:27+0000\n" -"Last-Translator: <>\n" +"POT-Creation-Date: 2008-11-28 17:09+0000\n" +"PO-Revision-Date: 2008-10-13 16:22+0000\n" +"Last-Translator: Olivier Laurent \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" -"Plural-Forms: \n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2008-12-16 11:00+0000\n" +"X-Generator: Launchpad (build Unknown)\n" #. module: sale #: rml:sale.shipping:0 @@ -95,8 +98,10 @@ msgstr "Exception de facture" #. module: sale #: help:sale.order,picking_ids:0 -msgid "This is the list of picking list that have been generated for this invoice" -msgstr "C'est le liste de liste de picking qui ont été généré pour cette facture" +msgid "" +"This is the list of picking list that have been generated for this invoice" +msgstr "" +"C'est la liste de liste de picking qui a été générée pour cette facture" #. module: sale #: view:sale.order:0 @@ -130,7 +135,9 @@ msgstr "Montant" #. module: sale #: model:process.transition,note:sale.process_transition_confirmquotation0 -msgid "Whenever confirm button is clicked, the draft state is moved to manual. that is, quotation is moved to sale order." +msgid "" +"Whenever confirm button is clicked, the draft state is moved to manual. that " +"is, quotation is moved to sale order." msgstr "" #. module: sale @@ -177,8 +184,8 @@ msgid "Sale Order" msgstr "Commande client" #. module: sale -#, python-format #: code:addons/sale/sale.py:0 +#, python-format msgid "You must first cancel all packings attached to this sale order." msgstr "" @@ -189,8 +196,8 @@ msgid "Taxes" msgstr "Taxes" #. module: sale -#, python-format #: code:addons/sale/sale.py:0 +#, python-format msgid "Invalid action !" msgstr "" @@ -234,7 +241,9 @@ msgstr "Creer les factures" #. module: sale #: model:process.transition,note:sale.process_transition_deliver0 -msgid "Confirming the packing list moves them to delivery order. This can be done by clicking on 'Validate' button." +msgid "" +"Confirming the packing list moves them to delivery order. This can be done " +"by clicking on 'Validate' button." msgstr "" #. module: sale @@ -275,8 +284,19 @@ msgstr "Méthode d'appro." #. module: sale #: help:sale.order,state:0 -msgid "Gives the state of the quotation or sale order. The exception state is automatically set when a cancel operation occurs in the invoice validation (Invoice Exception) or in the packing list process (Shipping Exception). The 'Waiting Schedule' state is set when the invoice is confirmed but waiting for the scheduler to be on the date 'Date Ordered'." -msgstr "Donne l'état du devis ou de la commande. L'état d'exception est automatiquement défini quand une opération d'annulation arrive dans la validation de facture (Exception de facture) ou dans le processus de colisage (Exception d'expédition). L'état 'En attente de planninfication' est défini lorsque la facture est confirmée mais en attente que le plannificateur soit à la date 'Date commandée'." +msgid "" +"Gives the state of the quotation or sale order. The exception state is " +"automatically set when a cancel operation occurs in the invoice validation " +"(Invoice Exception) or in the packing list process (Shipping Exception). The " +"'Waiting Schedule' state is set when the invoice is confirmed but waiting " +"for the scheduler to be on the date 'Date Ordered'." +msgstr "" +"Donne l'état du devis ou de la commande. L'état d'exception est " +"automatiquement défini quand une opération d'annulation arrive dans la " +"validation de facture (Exception de facture) ou dans le processus de " +"colisage (Exception d'expédition). L'état 'En attente de planninfication' " +"est défini lorsque la facture est confirmée mais en attente que le " +"plannificateur soit à la date 'Date commandée'." #. module: sale #: rml:sale.order:0 @@ -295,9 +315,11 @@ msgid "Order Line" msgstr "Commande client" #. module: sale -#, python-format #: code:addons/sale/wizard/make_invoice_advance.py:0 -msgid "You cannot make an advance on a sale order that is defined as 'Automatic Invoice after delivery'." +#, python-format +msgid "" +"You cannot make an advance on a sale order that is defined as 'Automatic " +"Invoice after delivery'." msgstr "" #. module: sale @@ -376,7 +398,9 @@ msgstr "Montant non-taxé" #. module: sale #: model:process.transition,note:sale.process_transition_packing0 -msgid "Packing list is created when 'Assign' is being clicked after confirming the sale order. This transaction moves the sale order to packing list." +msgid "" +"Packing list is created when 'Assign' is being clicked after confirming the " +"sale order. This transaction moves the sale order to packing list." msgstr "" #. module: sale @@ -392,12 +416,14 @@ msgstr "Adresse de livraison :" #. module: sale #: model:process.transition,note:sale.process_transition_invoiceafterdelivery0 -msgid "When you select Shipping Ploicy = 'Automatic Invoice after delivery' , it will automatic create after delivery." +msgid "" +"When you select Shipping Ploicy = 'Automatic Invoice after delivery' , it " +"will automatic create after delivery." msgstr "" #. module: sale -#, python-format #: code:addons/sale/sale.py:0 +#, python-format msgid "Error !" msgstr "" @@ -424,8 +450,8 @@ msgid "Sales Order Lines" msgstr "Lignes de ventes" #. module: sale -#, python-format #: code:addons/sale/sale.py:0 +#, python-format msgid "You must first cancel all invoices attached to this sale order." msgstr "" @@ -481,7 +507,7 @@ msgstr "Configuration" #. module: sale #: constraint:ir.ui.view:0 msgid "Invalid XML for View Architecture!" -msgstr "XML non valide pour l'architecture de la vue" +msgstr "XML non valide pour l'architecture de la vue!" #. module: sale #: field:sale.order,invoice_ids:0 @@ -522,16 +548,29 @@ msgstr "Manuel en cours" #. module: sale #: help:sale.order,order_policy:0 -msgid "The Shipping Policy is used to synchronise invoice and delivery operations.\n" -" - The 'Pay before delivery' choice will first generate the invoice and then generate the packing order after the payment of this invoice.\n" -" - The 'Shipping & Manual Invoice' will create the packing order directly and wait for the user to manually click on the 'Invoice' button to generate the draft invoice.\n" -" - The 'Invoice after delivery' choice will generate the draft invoice after the packing list have been finished.\n" -" - The 'Invoice from the packings' choice is used to create an invoice during the packing process." -msgstr "La Politique de Livraison est utilisée pour synchroniser les factures et les opérations de livraison.\n" -" - le choix \"Payer avant livraison\" générera d'abord les factures puis générera la commande de colisage après le paiement de cette facture.\n" -" - \"Livraison & Factures manuelles\" créera la commande de colisage directement et attendra que l'utilisateur clique manuellement sur le bouton 'Facture' pour générer la facture brouillon.\n" -" - \"Facture après Livraison\" générera la facture brouillon après que la liste des colisage soit terminée. \n" -" - \"Facture d'après Colisage\" est utilisé pour créer la facture pendant le processus de colisage." +msgid "" +"The Shipping Policy is used to synchronise invoice and delivery operations.\n" +" - The 'Pay before delivery' choice will first generate the invoice and " +"then generate the packing order after the payment of this invoice.\n" +" - The 'Shipping & Manual Invoice' will create the packing order directly " +"and wait for the user to manually click on the 'Invoice' button to generate " +"the draft invoice.\n" +" - The 'Invoice after delivery' choice will generate the draft invoice " +"after the packing list have been finished.\n" +" - The 'Invoice from the packings' choice is used to create an invoice " +"during the packing process." +msgstr "" +"La Politique de Livraison est utilisée pour synchroniser les factures et les " +"opérations de livraison.\n" +" - le choix \"Payer avant livraison\" générera d'abord les factures puis " +"générera la commande de colisage après le paiement de cette facture.\n" +" - \"Livraison & Factures manuelles\" créera la commande de colisage " +"directement et attendra que l'utilisateur clique manuellement sur le bouton " +"'Facture' pour générer la facture brouillon.\n" +" - \"Facture après Livraison\" générera la facture brouillon après que la " +"liste des colisage soit terminée. \n" +" - \"Facture d'après Colisage\" est utilisé pour créer la facture pendant " +"le processus de colisage." #. module: sale #: field:sale.shop,payment_account_id:0 @@ -583,8 +622,8 @@ msgid "Net Price" msgstr "Prix net" #. module: sale -#, python-format #: code:addons/sale/sale.py:0 +#, python-format msgid "invalid mode for test_state" msgstr "" @@ -615,8 +654,8 @@ msgid "Shipping Default Policy" msgstr "" #. module: sale -#, python-format #: code:addons/sale/sale.py:0 +#, python-format msgid "Could not cancel sale order !" msgstr "" @@ -647,8 +686,14 @@ msgstr "Vendeur" #. module: sale #: help:sale.order,invoice_ids:0 -msgid "This is the list of invoices that have been generated for this sale order. The same sale order may have been invoiced in several times (by line for example)." -msgstr "C'est la liste des factures qui ont étées générées pour cette commande. Le même commande peut avoir été facturé en plusieurs fois (par lignes par example)." +msgid "" +"This is the list of invoices that have been generated for this sale order. " +"The same sale order may have been invoiced in several times (by line for " +"example)." +msgstr "" +"C'est la liste des factures qui ont étées générées pour cette commande. Le " +"même commande peut avoir été facturé en plusieurs fois (par lignes par " +"example)." #. module: sale #: rml:sale.order:0 @@ -708,8 +753,17 @@ msgstr "Brouillon" #. module: sale #: help:sale.order,invoice_quantity:0 -msgid "The sale order will automatically create the invoice proposition (draft invoice). Ordered and delivered quantities may not be the same. You have to choose if you invoice based on ordered or shipped quantities. If the product is a service, shipped quantities means hours spent on the associated tasks." -msgstr "La commande créera une proposition de facturation (facture brouillon). Les quantités commandées et facturées peuvent ne pas être les mêmes. Vous devez choisir si vous facturez sur base des quantités commandées ou expédiées. Si le produit est un service, les quantitées expédiées signifies les heures dépensées aux tâches associées." +msgid "" +"The sale order will automatically create the invoice proposition (draft " +"invoice). Ordered and delivered quantities may not be the same. You have to " +"choose if you invoice based on ordered or shipped quantities. If the product " +"is a service, shipped quantities means hours spent on the associated tasks." +msgstr "" +"La commande créera une proposition de facturation (facture brouillon). Les " +"quantités commandées et facturées peuvent ne pas être les mêmes. Vous devez " +"choisir si vous facturez sur base des quantités commandées ou expédiées. Si " +"le produit est un service, les quantitées expédiées signifies les heures " +"dépensées aux tâches associées." #. module: sale #: rml:sale.shipping:0 @@ -779,12 +833,14 @@ msgstr "Commandes de Ventes" #. module: sale #: help:sale.order,picking_policy:0 -msgid "If you don't have enough stock available to deliver all at once, do you accept partial shippings or not." +msgid "" +"If you don't have enough stock available to deliver all at once, do you " +"accept partial shippings or not." msgstr "" #. module: sale -#, python-format #: code:addons/sale/sale.py:0 +#, python-format msgid "Cannot delete Sale Order(s) which are already confirmed !" msgstr "" @@ -864,8 +920,8 @@ msgid "Payment before delivery" msgstr "Paiement avant livraison" #. module: sale -#, python-format #: code:addons/sale/wizard/make_invoice_advance.py:0 +#, python-format msgid "Error" msgstr "" @@ -1014,8 +1070,11 @@ msgstr "" #. module: sale #: constraint:ir.model:0 -msgid "The Object name must start with x_ and not contain any special character !" -msgstr "Le nom de l'objet doit commencer avec x_ et ne pas contenir de charactères spéciaux !" +msgid "" +"The Object name must start with x_ and not contain any special character !" +msgstr "" +"Le nom de l'objet doit commencer avec x_ et ne pas contenir de charactères " +"spéciaux !" #. module: sale #: model:process.transition,note:sale.process_transition_saleinvoice0 @@ -1034,7 +1093,9 @@ msgstr "Désignation manuelle" #. module: sale #: model:process.transition,note:sale.process_transition_invoice0 -msgid "Invoice is created when 'Create Invoice' is being clicked after confirming the sale order. This transaction moves the sale order to invoices." +msgid "" +"Invoice is created when 'Create Invoice' is being clicked after confirming " +"the sale order. This transaction moves the sale order to invoices." msgstr "" #. module: sale @@ -1138,8 +1199,8 @@ msgid "Error: Invalid ean code" msgstr "Erreur: code EAN invalide" #. module: sale -#, python-format #: code:addons/sale/sale.py:0 +#, python-format msgid "Could not cancel this sale order !" msgstr "" @@ -1173,7 +1234,8 @@ msgstr "Notes" #. module: sale #: help:sale.order,partner_order_id:0 -msgid "The name and address of the contact that requested the order or quotation." +msgid "" +"The name and address of the contact that requested the order or quotation." msgstr "Le nom et l'adresse du contacte ayant demandé le devis." #. module: sale @@ -1236,7 +1298,11 @@ msgstr "" #. module: sale #: help:sale.config.picking_policy,step:0 -msgid "By default, Open ERP is able to manage complex routing and paths of products in your warehouse and partner locations. This will configure the most common and simple methods to deliver products to the customer in one or two operations by the worker." +msgid "" +"By default, Open ERP is able to manage complex routing and paths of products " +"in your warehouse and partner locations. This will configure the most common " +"and simple methods to deliver products to the customer in one or two " +"operations by the worker." msgstr "" #. module: sale @@ -1271,7 +1337,9 @@ msgstr "Condition de paiement" #. module: sale #: model:process.transition,note:sale.process_transition_saleorderprocurement0 -msgid "In sale order , procuerement for each line and it comes into the procurement order" +msgid "" +"In sale order , procuerement for each line and it comes into the procurement " +"order" msgstr "" #. module: sale From 75f4b7356811715865428dac78a616b314e52f22 Mon Sep 17 00:00:00 2001 From: Mustufa Rangwala Date: Wed, 17 Dec 2008 18:58:36 +0530 Subject: [PATCH 008/124] bug fix on membership bzr revid: mra@tinyerp.com-20081217132836-xntal19ugo9kne82 --- addons/membership/membership.py | 131 +++++++++++++++++--------------- 1 file changed, 70 insertions(+), 61 deletions(-) diff --git a/addons/membership/membership.py b/addons/membership/membership.py index ed034f7a59d..69fedf4f12a 100644 --- a/addons/membership/membership.py +++ b/addons/membership/membership.py @@ -333,24 +333,24 @@ class Partner(osv.osv): res[partner.id] = False return res - def _membership_start_search(self, cr, uid, obj, name, args): - '''Search on membership start date''' - if not len(args): - return [] - where = ' AND '.join(['date_from '+x[1]+' \''+str(x[2])+'\'' - for x in args]) - cr.execute('SELECT partner, MIN(date_from) \ - FROM ( \ - SELECT partner, MIN(date_from) AS date_from \ - FROM membership_membership_line \ - GROUP BY partner \ - ) AS foo \ - WHERE '+where+' \ - GROUP BY partner') - res = cr.fetchall() - if not res: - return [('id', '=', '0')] - return [('id', 'in', [x[0] for x in res])] +# def _membership_start_search(self, cr, uid, obj, name, args): +# '''Search on membership start date''' +# if not len(args): +# return [] +# where = ' AND '.join(['date_from '+x[1]+' \''+str(x[2])+'\'' +# for x in args]) +# cr.execute('SELECT partner, MIN(date_from) \ +# FROM ( \ +# SELECT partner, MIN(date_from) AS date_from \ +# FROM membership_membership_line \ +# GROUP BY partner \ +# ) AS foo \ +# WHERE '+where+' \ +# GROUP BY partner') +# res = cr.fetchall() +# if not res: +# return [('id', '=', '0')] +# return [('id', 'in', [x[0] for x in res])] def _membership_stop(self, cr, uid, ids, name, args, context=None): '''Return the stop date of membership''' @@ -372,25 +372,25 @@ class Partner(osv.osv): else: res[partner.id] = False return res - - def _membership_stop_search(self, cr, uid, obj, name, args): - '''Search on membership stop date''' - if not len(args): - return [] - where = ' AND '.join(['date_to '+x[1]+' \''+str(x[2])+'\'' - for x in args]) - cr.execute('SELECT partner, MAX(date_to) \ - FROM ( \ - SELECT partner, MAX(date_to) AS date_to \ - FROM membership_membership_line \ - GROUP BY partner \ - ) AS foo \ - WHERE '+where+' \ - GROUP BY partner') - res = cr.fetchall() - if not res: - return [('id', '=', '0')] - return [('id', 'in', [x[0] for x in res])] +# +# def _membership_stop_search(self, cr, uid, obj, name, args): +# '''Search on membership stop date''' +# if not len(args): +# return [] +# where = ' AND '.join(['date_to '+x[1]+' \''+str(x[2])+'\'' +# for x in args]) +# cr.execute('SELECT partner, MAX(date_to) \ +# FROM ( \ +# SELECT partner, MAX(date_to) AS date_to \ +# FROM membership_membership_line \ +# GROUP BY partner \ +# ) AS foo \ +# WHERE '+where+' \ +# GROUP BY partner') +# res = cr.fetchall() +# if not res: +# return [('id', '=', '0')] +# return [('id', 'in', [x[0] for x in res])] def _membership_cancel(self, cr, uid, ids, name, args, context=None): '''Return the cancel date of membership''' @@ -406,24 +406,24 @@ class Partner(osv.osv): res[partner_id] = False return res - def _membership_cancel_search(self, cr, uid, obj, name, args): - '''Search on membership cancel date''' - if not len(args): - return [] - where = ' AND '.join(['date_cancel '+x[1]+' \''+str(x[2])+'\'' - for x in args]) - cr.execute('SELECT partner, MIN(date_cancel) \ - FROM ( \ - SELECT partner, MIN(date_cancel) AS date_cancel \ - FROM membership_membership_line \ - GROUP BY partner \ - ) AS foo \ - WHERE '+where+' \ - GROUP BY partner') - res = cr.fetchall() - if not res: - return [('id', '=', '0')] - return [('id', 'in', [x[0] for x in res])] +# def _membership_cancel_search(self, cr, uid, obj, name, args): +# '''Search on membership cancel date''' +# if not len(args): +# return [] +# where = ' AND '.join(['date_cancel '+x[1]+' \''+str(x[2])+'\'' +# for x in args]) +# cr.execute('SELECT partner, MIN(date_cancel) \ +# FROM ( \ +# SELECT partner, MIN(date_cancel) AS date_cancel \ +# FROM membership_membership_line \ +# GROUP BY partner \ +# ) AS foo \ +# WHERE '+where+' \ +# GROUP BY partner') +# res = cr.fetchall() +# if not res: +# return [('id', '=', '0')] +# return [('id', 'in', [x[0] for x in res])] @@ -440,15 +440,24 @@ class Partner(osv.osv): 'res.partner':(lambda self,cr,uid,ids,c={}:ids, ['free_member'], 10)}), # 'associate_member': fields.many2one('res.partner', 'Associate member'), 'free_member': fields.boolean('Free member'), +# 'membership_start': fields.function(_membership_start, method=True, +# string='Start membership date', type='date', +# fnct_search=_membership_start_search), 'membership_start': fields.function(_membership_start, method=True, - string='Start membership date', type='date', - fnct_search=_membership_start_search), + string='Start membership date', type='date',store={'membership.membership_line':(_get_partner_id,['state'], 10), + 'res.partner':(lambda self,cr,uid,ids,c={}:ids, ['free_member'], 10)}), +# 'membership_stop': fields.function(_membership_stop, method=True, +# string='Stop membership date', type='date', +# fnct_search=_membership_stop_search), 'membership_stop': fields.function(_membership_stop, method=True, - string='Stop membership date', type='date', - fnct_search=_membership_stop_search), + string='Stop membership date', type='date',store={'membership.membership_line':(_get_partner_id,['state'], 10), + 'res.partner':(lambda self,cr,uid,ids,c={}:ids, ['free_member'], 10)}), +# 'membership_cancel': fields.function(_membership_cancel, method=True, +# string='Cancel membership date', type='date', +# fnct_search=_membership_cancel_search), 'membership_cancel': fields.function(_membership_cancel, method=True, - string='Cancel membership date', type='date', - fnct_search=_membership_cancel_search), + string='Cancel membership date', type='date',store={'membership.membership_line':(_get_partner_id,['state'], 10), + 'res.partner':(lambda self,cr,uid,ids,c={}:ids, ['free_member'], 10)}), } _defaults = { 'free_member': lambda *a: False, From 34eff0dd3c3de835c7a67a95c6d8464493fd9076 Mon Sep 17 00:00:00 2001 From: Sofia Date: Wed, 17 Dec 2008 19:14:41 +0530 Subject: [PATCH 009/124] changed the date_start of tasks if the project's deadline is changed bzr revid: sahibsofia@gmail.com-20081217134441-q9cx9zhaua2i4mn8 --- addons/project_retro_planning/project_retro_planning.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/addons/project_retro_planning/project_retro_planning.py b/addons/project_retro_planning/project_retro_planning.py index c3bbac6c0cf..e9e0f8483f6 100644 --- a/addons/project_retro_planning/project_retro_planning.py +++ b/addons/project_retro_planning/project_retro_planning.py @@ -37,9 +37,12 @@ class project_project(osv.osv): if prj.date_end: d= date(*time.strptime(prj.date_end,'%Y-%m-%d')[:3]) for task in prj.tasks: + start_dt = (datetime(*time.strptime(task.date_start,'%Y-%m-%d %H:%M:%S')[:6])+(c-d)).strftime('%Y-%m-%d %H:%M:%S') if task.date_deadline: - f = (datetime(*time.strptime(task.date_deadline,'%Y-%m-%d %H:%M:%S')[:6])+(c-d)).strftime('%Y-%m-%d %H:%M:%S') - self.pool.get('project.task').write(cr,uid,task.id,{'date_deadline':f}) + deadline_dt = (datetime(*time.strptime(task.date_deadline,'%Y-%m-%d %H:%M:%S')[:6])+(c-d)).strftime('%Y-%m-%d %H:%M:%S') + self.pool.get('project.task').write(cr,uid,task.id,{'date_start':start_dt, 'date_deadline':deadline_dt}) + else: + self.pool.get('project.task').write(cr,uid,task.id,{'date_start':start_dt}) return super(project_project,self).write(cr, uid, ids,vals, *args, **kwargs) project_project() From 5b090582b62739c6929b3292d83e772017126d68 Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Wed, 17 Dec 2008 14:52:42 +0100 Subject: [PATCH 010/124] [FIX] drop_view_if_exists bzr revid: stephane@tinyerp.com-20081217135242-c9cf4w9ouamepjwu --- addons/crm_configuration/report/crm_report.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/crm_configuration/report/crm_report.py b/addons/crm_configuration/report/crm_report.py index 156f7c21a44..8a76d2de4f7 100644 --- a/addons/crm_configuration/report/crm_report.py +++ b/addons/crm_configuration/report/crm_report.py @@ -31,7 +31,7 @@ AVAILABLE_STATES = [ def drop_view_if_exists(cr, viewname): cr.execute("select count(1) from pg_class where relkind=%s and relname=%s", ('v', viewname,)) - if cr.fetchone(): + if cr.fetchone()[0]: cr.execute("DROP view %s" % (viewname,)) cr.commit() From 3484fb13396bc1c93f609938b5486b590ae90ac7 Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Wed, 17 Dec 2008 14:53:56 +0100 Subject: [PATCH 011/124] [FIX] Remove the executable flag bzr revid: stephane@tinyerp.com-20081217135356-rhpews5tf9mjdcd4 --- addons/account/report/account_balance.py | 0 addons/account/report/account_balance.rml | 0 addons/account/report/aged_trial_balance.py | 0 addons/account/report/aged_trial_balance.rml | 0 addons/account/report/general_ledger.py | 0 addons/account/report/general_ledger.rml | 0 addons/account/report/general_ledger_landscape.py | 0 addons/account/report/tax_report.py | 0 addons/account/report/tax_report.rml | 0 addons/account/report/third_party_ledger.py | 0 addons/account/report/third_party_ledger.rml | 0 11 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 addons/account/report/account_balance.py mode change 100755 => 100644 addons/account/report/account_balance.rml mode change 100755 => 100644 addons/account/report/aged_trial_balance.py mode change 100755 => 100644 addons/account/report/aged_trial_balance.rml mode change 100755 => 100644 addons/account/report/general_ledger.py mode change 100755 => 100644 addons/account/report/general_ledger.rml mode change 100755 => 100644 addons/account/report/general_ledger_landscape.py mode change 100755 => 100644 addons/account/report/tax_report.py mode change 100755 => 100644 addons/account/report/tax_report.rml mode change 100755 => 100644 addons/account/report/third_party_ledger.py mode change 100755 => 100644 addons/account/report/third_party_ledger.rml diff --git a/addons/account/report/account_balance.py b/addons/account/report/account_balance.py old mode 100755 new mode 100644 diff --git a/addons/account/report/account_balance.rml b/addons/account/report/account_balance.rml old mode 100755 new mode 100644 diff --git a/addons/account/report/aged_trial_balance.py b/addons/account/report/aged_trial_balance.py old mode 100755 new mode 100644 diff --git a/addons/account/report/aged_trial_balance.rml b/addons/account/report/aged_trial_balance.rml old mode 100755 new mode 100644 diff --git a/addons/account/report/general_ledger.py b/addons/account/report/general_ledger.py old mode 100755 new mode 100644 diff --git a/addons/account/report/general_ledger.rml b/addons/account/report/general_ledger.rml old mode 100755 new mode 100644 diff --git a/addons/account/report/general_ledger_landscape.py b/addons/account/report/general_ledger_landscape.py old mode 100755 new mode 100644 diff --git a/addons/account/report/tax_report.py b/addons/account/report/tax_report.py old mode 100755 new mode 100644 diff --git a/addons/account/report/tax_report.rml b/addons/account/report/tax_report.rml old mode 100755 new mode 100644 diff --git a/addons/account/report/third_party_ledger.py b/addons/account/report/third_party_ledger.py old mode 100755 new mode 100644 diff --git a/addons/account/report/third_party_ledger.rml b/addons/account/report/third_party_ledger.rml old mode 100755 new mode 100644 From 6232b371fe17164ae90b3db7aa88adbb5fe29703 Mon Sep 17 00:00:00 2001 From: qdp Date: Wed, 17 Dec 2008 18:10:57 +0100 Subject: [PATCH 012/124] *reindented bzr revid: qdp@tinyerp.com-20081217171057-jzag2xjt3eg4n0xr --- addons/l10n_be/wizard/partner_vat_listing.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/l10n_be/wizard/partner_vat_listing.py b/addons/l10n_be/wizard/partner_vat_listing.py index 9e76d79efb5..85b562f2777 100644 --- a/addons/l10n_be/wizard/partner_vat_listing.py +++ b/addons/l10n_be/wizard/partner_vat_listing.py @@ -46,9 +46,9 @@ fields = { } msg_form = """
- - - + + + """ msg_fields = { From 503a081c9d83c479d9832979418fadfe8b81813d Mon Sep 17 00:00:00 2001 From: qdp Date: Wed, 17 Dec 2008 18:12:44 +0100 Subject: [PATCH 013/124] *base_module_quality: * added a configuration file * added possiblity to define tests on installed module only or no * cleaned * improved bzr revid: qdp@tinyerp.com-20081217171244-x8rnbx32yd2bj3v3 --- .../base_module_quality.py | 31 +++++++++--- .../pylint_test/pylint_test.py | 36 +++++++------ .../pylint_test/pylint_test_config.txt | 5 +- .../speed_test/speed_test.py | 7 ++- .../wizard/module_quality_check.py | 50 +++++++++++-------- 5 files changed, 80 insertions(+), 49 deletions(-) diff --git a/addons/base_module_quality/base_module_quality.py b/addons/base_module_quality/base_module_quality.py index 13b9de20ce4..2965ad41f16 100644 --- a/addons/base_module_quality/base_module_quality.py +++ b/addons/base_module_quality/base_module_quality.py @@ -20,21 +20,38 @@ # ############################################################################## -import netsvc -from osv import fields, osv class abstract_quality_check(object): ''' This Class provide... ''' - _score = 0.0 - _result = "" - _result_details = "" + #This float have to store the rating of the module. + #Used to compute the final score (average of all scores). + score = 0.0 - def __init__(self, module_path=""): + #This char have to store the result. + #Used to display the result of the test. + result = "" + + #This char have to store the result with more details. + #Used to provide more details if necessary. + result_details = "" + + #This bool defines if the test can be run only if the module is installed. + #True => the module have to be installed. + #False => the module can be uninstalled. + bool_installed_only = True + + def __init__(self): ''' - this method should do the test and fill the _score, _result and _result_details var + this method should initialize the var + ''' + raise 'Not Implemented' + + def run_test(self, module_path=""): + ''' + this method should do the test and fill the score, result and result_details var ''' raise 'Not Implemented' diff --git a/addons/base_module_quality/pylint_test/pylint_test.py b/addons/base_module_quality/pylint_test/pylint_test.py index 1d46830f646..bb31eef5e3a 100644 --- a/addons/base_module_quality/pylint_test/pylint_test.py +++ b/addons/base_module_quality/pylint_test/pylint_test.py @@ -20,8 +20,7 @@ # ############################################################################## -import netsvc -from osv import fields, osv + import os from tools import config @@ -30,8 +29,8 @@ from base_module_quality import base_module_quality class quality_test(base_module_quality.abstract_quality_check): - def __init__(self, module_path): - self._result = """ + def __init__(self): + self.result = """ Pylint Test: ------------ @@ -39,36 +38,41 @@ Pylint Test: """ + self.bool_installed_only = False + return None + + def run_test(self, module_path): config_file_path = config['addons_path']+'/base_module_quality/pylint_test/pylint_test_config.txt' list_files = os.listdir(module_path) - new_list = [] - subfolder = {} for i in list_files: path = os.path.join(module_path, i) if os.path.isdir(path): for j in os.listdir(path): list_files.append(os.path.join(i, j)) - dict_files = {} - n =0 + n = 0 score = 0.0 - print list_files for file in list_files: if file.split('.')[-1] == 'py' and not file.endswith('__init__.py') and not file.endswith('__terp__.py'): file_path = os.path.join(module_path, file) - res = os.popen('pylint --rcfile='+config_file_path+' '+file_path).read() + res = os.popen('pylint --rcfile=' + config_file_path + ' ' + file_path).read() n += 1 leftchar = -1 while res[leftchar:leftchar+1] != ' ' and leftchar-1 <= 0: - leftchar -=1 + leftchar -= 1 rightchar = -10 while res[rightchar:rightchar+1] != '/' and rightchar+1 <= 0: - rightchar +=1 + rightchar += 1 - score += float(res[leftchar+1:rightchar]) - self._result_details += res - self._result += file+": "+ res[leftchar+1:rightchar]+"/10\n" - self._score = score / n + try: + score += float(res[leftchar+1:rightchar]) + self.result += file + ": " + res[leftchar+1:rightchar] + "/10\n" + except: + score += 0 + self.result += file + ": Unable to parse the result. Check the details.\n" + + self.result_details += res + self.score = n and score / n or score return None diff --git a/addons/base_module_quality/pylint_test/pylint_test_config.txt b/addons/base_module_quality/pylint_test/pylint_test_config.txt index db975430f08..1997cce14ad 100644 --- a/addons/base_module_quality/pylint_test/pylint_test_config.txt +++ b/addons/base_module_quality/pylint_test/pylint_test_config.txt @@ -56,8 +56,7 @@ load-plugins= #enable-msg= # Disable the message(s) with the given id(s). -#disable-msg= - +disable-msg=C0103,F0401,E0611,R0903,W0232,W0102,E1002,R0913,R0904 [REPORTS] @@ -66,7 +65,7 @@ load-plugins= output-format=text # Include message's id in output -include-ids=no +include-ids=yes # Put messages in a separate file for each module / package specified on the # command line instead of printing them on stdout. Reports (if any) will be diff --git a/addons/base_module_quality/speed_test/speed_test.py b/addons/base_module_quality/speed_test/speed_test.py index ca9a93b09f7..89479ddf18b 100644 --- a/addons/base_module_quality/speed_test/speed_test.py +++ b/addons/base_module_quality/speed_test/speed_test.py @@ -30,8 +30,8 @@ from base_module_quality import base_module_quality class quality_test(base_module_quality.abstract_quality_check): - def __init__(self, module_path): - self._result = """ + def __init__(self): + self.result = """ Speed Test: ------------ @@ -41,8 +41,11 @@ Speed Test: to be continued... """ + self.bool_installed_only = True return None + def run_test(self, module_path): + return None # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/base_module_quality/wizard/module_quality_check.py b/addons/base_module_quality/wizard/module_quality_check.py index 61cc031261a..9a5ec9391dd 100644 --- a/addons/base_module_quality/wizard/module_quality_check.py +++ b/addons/base_module_quality/wizard/module_quality_check.py @@ -21,14 +21,20 @@ ############################################################################## import wizard import pooler -import osv -import netsvc -import sys import tools import os +#TODO: (utiliser les nouveaux wizards pour heriter la vue et rajouter un onglet par test?) +#TODO: configure pylint +#TODO: implement the speed test +#TODO: implement the simple test +#TODO: add cheks: do the class quality_check inherits the class abstract_quality_check? +#TODO: improve translability + + +#To keep or not? to be discussed... #~ form_check = ''' #~
#~ @@ -50,47 +56,49 @@ view_form = """ """ -#TODO: utiliser les nouveaux wizards pour heriter la vue et rajouter un onglet par test? -#TODO: remove the first screen which is unused + view_field = { "general_info": {'type': 'text', 'string': 'General Info', 'readonly':True}, } - - class wiz_quality_check(wizard.interface): - def _check(self, cr, uid, data, context): + def _check(self, cr, uid, data, context={}): string_ret = "" from tools import config - list_folders=os.listdir(config['addons_path']+'/base_module_quality/') + pool = pooler.get_pool(cr.dbname) + module_data = pool.get('ir.module.module').browse(cr, uid, data['ids']) + + list_folders = os.listdir(config['addons_path']+'/base_module_quality/') for item in list_folders: path = config['addons_path']+'/base_module_quality/'+item - if os.path.exists(path+'/'+item+'.py') and item not in ['report','wizard', 'security']: - pool=pooler.get_pool(cr.dbname) - module_data = pool.get('ir.module.module').browse(cr, uid, data['ids']) - + if os.path.exists(path+'/'+item+'.py') and item not in ['report', 'wizard', 'security']: ad = tools.config['addons_path'] module_path = os.path.join(ad, module_data[0].name) - - from base_module_quality import base_module_quality - - item2='base_module_quality.'+item+'.'+item + item2 = 'base_module_quality.'+item+'.'+item x = __import__(item2) - x2 = getattr(x,item) - x3 = getattr(x2,item) - val = x3.quality_test(str(module_path)) + x2 = getattr(x, item) + x3 = getattr(x2, item) + val = x3.quality_test() + if not val.bool_installed_only or module_data[0].state == "installed": + val.run_test(str(module_path)) + else: + val.result += "The module has to be installed before running this test." - string_ret += val._result + string_ret += val.result + print val.result_details return {'general_info':string_ret} states = { + +#To keep or not? to be discussed... + #~ 'init': { #~ 'actions': [], #~ 'result': {'type':'form', 'arch':form_check, 'fields':fields_check, 'state':[('end','Cancel'),('do','Do Test')]} From eb158f7b856b1c45e0e6538f80fe227a5d167ce1 Mon Sep 17 00:00:00 2001 From: Mustufa Rangwala Date: Thu, 18 Dec 2008 11:24:34 +0530 Subject: [PATCH 014/124] membership bzr revid: mra@tinyerp.com-20081218055434-vkdzytreej82eecn --- addons/membership/membership.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/addons/membership/membership.py b/addons/membership/membership.py index 69fedf4f12a..c192d77534a 100644 --- a/addons/membership/membership.py +++ b/addons/membership/membership.py @@ -512,19 +512,19 @@ class Invoice(osv.osv): def create(self, cr, uid, vals, context={}): result = super(Invoice, self).create(cr, uid, vals, context) - a = self.browse(cr, uid, result) + invoice = self.browse(cr, uid, result) member_line_obj = self.pool.get('membership.membership_line') - for i in a.invoice_line: - if i.product_id and i.product_id.membership: - date_from = i.product_id.membership_date_from - date_to = i.product_id.membership_date_to - if a.date_invoice > date_from and a.date_invoice < date_to: - date_from = a.date_invoice + for line in invoice.invoice_line: + if line.product_id and line.product_id.membership: + date_from = line.product_id.membership_date_from + date_to = line.product_id.membership_date_to + if invoice.date_invoice > date_from and invoice.date_invoice < date_to: + date_from = invoice.date_invoice line_id = member_line_obj.create(cr, uid, { - 'partner': a.partner_id.id, + 'partner': invoice.partner_id.id, 'date_from': date_from, 'date_to': date_to, - 'account_invoice_line': i.id, + 'account_invoice_line': line.id, }) return result From 07d43fcd2c9d2ea115f75623e1eae184b12f2a6d Mon Sep 17 00:00:00 2001 From: Mustufa Rangwala Date: Thu, 18 Dec 2008 12:25:42 +0530 Subject: [PATCH 015/124] bug fix on membership bzr revid: mra@tinyerp.com-20081218065542-kt19wqabq9mpnvoz --- addons/membership/membership.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/addons/membership/membership.py b/addons/membership/membership.py index c192d77534a..167e0bcfb87 100644 --- a/addons/membership/membership.py +++ b/addons/membership/membership.py @@ -232,6 +232,13 @@ class Partner(osv.osv): list_partner.append(data.partner.id) return list_partner + def _get_invoice_partner(self, cr, uid, ids, context=None): + data_inv = self.pool.get('account.invoice').browse(cr, uid, ids, context) + list_partner = [] + for data in data_inv: + list_partner.append(data.partner_id.id) + return list_partner + def _membership_state(self, cr, uid, ids, name, args, context=None): res = {} for id in ids: @@ -436,7 +443,8 @@ class Partner(osv.osv): # 'membership_state': fields.function(_membership_state, method=True, string='Current membership state', # type='selection', selection=STATE, fnct_search=_membership_state_search), 'membership_state': fields.function(_membership_state, method=True, string='Current membership state', - type='selection',selection=STATE,store={'membership.membership_line':(_get_partner_id,['state'], 10), + type='selection',selection=STATE,store={'account.invoice':(_get_invoice_partner,['state'], 10), + 'membership.membership_line':(_get_partner_id,['state'], 10), 'res.partner':(lambda self,cr,uid,ids,c={}:ids, ['free_member'], 10)}), # 'associate_member': fields.many2one('res.partner', 'Associate member'), 'free_member': fields.boolean('Free member'), @@ -444,19 +452,22 @@ class Partner(osv.osv): # string='Start membership date', type='date', # fnct_search=_membership_start_search), 'membership_start': fields.function(_membership_start, method=True, - string='Start membership date', type='date',store={'membership.membership_line':(_get_partner_id,['state'], 10), + string='Start membership date', type='date',store={'account.invoice':(_get_invoice_partner,['state'], 10), + 'membership.membership_line':(_get_partner_id,['state'], 10), 'res.partner':(lambda self,cr,uid,ids,c={}:ids, ['free_member'], 10)}), # 'membership_stop': fields.function(_membership_stop, method=True, # string='Stop membership date', type='date', # fnct_search=_membership_stop_search), 'membership_stop': fields.function(_membership_stop, method=True, - string='Stop membership date', type='date',store={'membership.membership_line':(_get_partner_id,['state'], 10), + string='Stop membership date', type='date',store={'account.invoice':(_get_invoice_partner,['state'], 10), + 'membership.membership_line':(_get_partner_id,['state'], 10), 'res.partner':(lambda self,cr,uid,ids,c={}:ids, ['free_member'], 10)}), # 'membership_cancel': fields.function(_membership_cancel, method=True, # string='Cancel membership date', type='date', # fnct_search=_membership_cancel_search), 'membership_cancel': fields.function(_membership_cancel, method=True, - string='Cancel membership date', type='date',store={'membership.membership_line':(_get_partner_id,['state'], 10), + string='Cancel membership date', type='date',store={'account.invoice':(_get_invoice_partner,['state'], 10), + 'membership.membership_line':(_get_partner_id,['state'], 10), 'res.partner':(lambda self,cr,uid,ids,c={}:ids, ['free_member'], 10)}), } _defaults = { From 8c916ea21182f96a08497c51e7f624c6eff763c7 Mon Sep 17 00:00:00 2001 From: hmo-tinyerp <> Date: Thu, 18 Dec 2008 14:25:57 +0530 Subject: [PATCH 016/124] fixed bug #301684 : soved unicode problem in DMS bzr revid: hmo-tinyerp-20081218085557-hfch2bn7i33ub7rf --- addons/document/document.py | 10 +++++----- addons/document/ftpserver/__init__.py | 2 +- addons/document/ftpserver/abstracted_fs.py | 4 ++-- addons/document/ftpserver/ftpserver.py | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/addons/document/document.py b/addons/document/document.py index 92b49a1b520..b8b053eb8b4 100644 --- a/addons/document/document.py +++ b/addons/document/document.py @@ -107,7 +107,7 @@ class node_class(object): where.append( ('parent_id','=',self.object.id) ) where.append( ('res_id','=',False) ) if nodename: - where.append( (fobj._rec_name,'=',nodename) ) + where.append( (fobj._rec_name,'=like',nodename) ) ids = fobj.search(self.cr, self.uid, where+[ ('parent_id','=',self.object and self.object.id or False) ], context=self.context) if self.object and self.root and (self.object.type=='ressource'): ids += fobj.search(self.cr, self.uid, where+[ ('parent_id','=',False) ], context=self.context) @@ -118,7 +118,7 @@ class node_class(object): pool = pooler.get_pool(self.cr.dbname) where = [] if nodename: - where.append(('name','=',nodename)) + where.append(('name','=like',nodename)) if (self.object and self.object.type=='directory') or not self.object2: where.append(('parent_id','=',self.object and self.object.id or False)) else: @@ -144,7 +144,7 @@ class node_class(object): fobj = pool.get('ir.attachment') vargs = [('parent_id','=',False),('res_id','=',False)] if nodename: - vargs.append(('name','=',nodename)) + vargs.append(('name','=like',nodename)) file_ids=fobj.search(self.cr,self.uid,vargs) res = fobj.browse(self.cr, self.uid, file_ids, context=self.context) @@ -174,7 +174,7 @@ class node_class(object): for invalid in INVALID_CHARS: if nodename.find(INVALID_CHARS[invalid]) : nodename=nodename.replace(INVALID_CHARS[invalid],invalid) - where.append(('name','=',nodename)) + where.append(('name','=like',nodename)) ids = obj.search(self.cr, self.uid, where, self.context) res = obj.browse(self.cr, self.uid, ids,self.context) for r in res: @@ -290,7 +290,7 @@ class document_directory(osv.osv): def _get_childs(self, cr, uid, node, nodename=False, context={}): where = [] if nodename: - where.append(('name','=',nodename)) + where.append(('name','=like',nodename)) if object: where.append(('parent_id','=',object.id)) ids = self.search(cr, uid, where, context) diff --git a/addons/document/ftpserver/__init__.py b/addons/document/ftpserver/__init__.py index 3856c5d47e1..dcac53d6061 100644 --- a/addons/document/ftpserver/__init__.py +++ b/addons/document/ftpserver/__init__.py @@ -9,7 +9,7 @@ PORT = config.get('ftp_server_port', 8021) HOST = '' class ftp_server(threading.Thread): - def log(self, level, message): + def log(self, level, message): logger = netsvc.Logger() logger.notifyChannel('FTP', level, message) diff --git a/addons/document/ftpserver/abstracted_fs.py b/addons/document/ftpserver/abstracted_fs.py index 69aecb284c4..fe64ab44063 100644 --- a/addons/document/ftpserver/abstracted_fs.py +++ b/addons/document/ftpserver/abstracted_fs.py @@ -150,7 +150,7 @@ class abstracted_fs: # Ok def fs2ftp(self, node): - res = node and ('/' + node.cr.dbname + '/' + node.path) or '/' + res = node and ('/' + node.cr.dbname + '/' + node.path.encode('ascii','replace').replace('?','_')) or '/' return res # Ok @@ -688,7 +688,7 @@ class abstracted_fs: # formatting is matched with proftpd ls output yield "%s %3s %-8s %-8s %8s %s %s\r\n" %(perms, nlinks, uname, gname, - size, mtime, file.path.encode('ascii','replace').split('/')[-1]) + size, mtime, file.path.encode('ascii','replace').replace('?','_').split('/')[-1]) # Ok def format_mlsx(self, basedir, listing, perms, facts, ignore_err=True): diff --git a/addons/document/ftpserver/ftpserver.py b/addons/document/ftpserver/ftpserver.py index f8af54fbb1a..07f60344b74 100644 --- a/addons/document/ftpserver/ftpserver.py +++ b/addons/document/ftpserver/ftpserver.py @@ -1768,7 +1768,7 @@ class FTPHandler(asynchat.async_chat): self.__out_dtp_queue = (data, isproducer, file) def log(self, msg): - """Log a message, including additional identifying session data.""" + """Log a message, including additional identifying session data.""" log("[%s]@%s:%s %s" %(self.username, self.remote_ip, self.remote_port, msg)) From 90b8def6d956427e60b600f1d6701c3703bfe9cf Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Thu, 18 Dec 2008 11:54:15 +0100 Subject: [PATCH 017/124] [FIX] Burndown Chart bzr revid: stephane@tinyerp.com-20081218105415-xmlha3ggtp5ahdhl --- addons/scrum/report/task_burndown.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/addons/scrum/report/task_burndown.py b/addons/scrum/report/task_burndown.py index 0730352f9bf..4a09428ba5f 100644 --- a/addons/scrum/report/task_burndown.py +++ b/addons/scrum/report/task_burndown.py @@ -99,19 +99,24 @@ class report_tasks(report_int): int_to_date = lambda x: '/a60{}'+DateTime.localtime(x).strftime('%d %m %Y') def _interval_get(*args): - result = [] + result = set() for i in range(20): d = DateTime.localtime(datas[0][0] + (((datas[-1][0]-datas[0][0])/20)*(i+1))) res = DateTime.DateTime(d.year, d.month, d.day).ticks() - if (not result) or result[-1]<>res: - result.append(res) - return result + result.add(res) + + return list(result) + + if datas[-1][0] == datas[0][0]: + x_range = (datas[0][0],datas[-1][0]+1) + else: + x_range = (datas[0][0],datas[-1][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"), x_grid_interval=_interval_get, - x_range = (datas[0][0],datas[-1][0]), + x_range = x_range, y_range = (0,max_hour), legend = None, size = (680,450)) From 1c4534fa75d06c1fa8734afce39b0783936c0ed1 Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Thu, 18 Dec 2008 15:02:48 +0100 Subject: [PATCH 018/124] [FIX] Drop the view if exists lp bug: https://launchpad.net/bugs/309331 fixed bzr revid: stephane@tinyerp.com-20081218140248-v63zqpaofph4ool4 --- .../account_analytic_analysis.py | 3 ++- addons/crm_configuration/report/crm_report.py | 8 +------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/addons/account_analytic_analysis/account_analytic_analysis.py b/addons/account_analytic_analysis/account_analytic_analysis.py index d08aba68947..60b3d9c2920 100644 --- a/addons/account_analytic_analysis/account_analytic_analysis.py +++ b/addons/account_analytic_analysis/account_analytic_analysis.py @@ -617,8 +617,9 @@ class account_analytic_account_summary_month(osv.osv): string='Total Time'), 'month': fields.char('Month', size=25, readonly=True), } + def init(self, cr): - cr.execute('DROP VIEW IF EXISTS account_analytic_analysis_summary_month') + cr.drop_view_if_exists('account_analytic_analysis_summary_month') cr.execute('CREATE VIEW account_analytic_analysis_summary_month AS (' \ 'SELECT ' \ '(TO_NUMBER(TO_CHAR(d.month, \'YYYYMM\'), \'999999\') + (d.account_id * 1000000))::integer AS id, ' \ diff --git a/addons/crm_configuration/report/crm_report.py b/addons/crm_configuration/report/crm_report.py index 8a76d2de4f7..6b602e8e59a 100644 --- a/addons/crm_configuration/report/crm_report.py +++ b/addons/crm_configuration/report/crm_report.py @@ -29,12 +29,6 @@ AVAILABLE_STATES = [ ('pending','Pending') ] -def drop_view_if_exists(cr, viewname): - cr.execute("select count(1) from pg_class where relkind=%s and relname=%s", ('v', viewname,)) - if cr.fetchone()[0]: - cr.execute("DROP view %s" % (viewname,)) - cr.commit() - class report_crm_case_section_categ2(osv.osv): _name = "report.crm.case.section.categ2" _description = "Cases by section and category2" @@ -53,7 +47,7 @@ class report_crm_case_section_categ2(osv.osv): _order = 'category2_id, section_id' def init(self, cr): - drop_view_if_exists(cr, "report_crm_case_section_categ2") + cr.drop_view_if_exists("report_crm_case_section_categ2") cr.execute(""" create view report_crm_case_section_categ2 as ( select From 6875763f601a0ddc092362e6ef9587a45020471c Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Thu, 18 Dec 2008 15:35:37 +0100 Subject: [PATCH 019/124] [FIX] An analytic journal is not mandatory on a financial journal lp bug: https://launchpad.net/bugs/309344 fixed bzr revid: stephane@tinyerp.com-20081218143537-u4bl6w0p291q4t85 --- addons/account/account_move_line.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/account/account_move_line.py b/addons/account/account_move_line.py index a805f83f64b..233eaf84de4 100644 --- a/addons/account/account_move_line.py +++ b/addons/account/account_move_line.py @@ -857,8 +857,8 @@ class account_move_line(osv.osv): 'journal_id': journal.analytic_journal_id.id, 'ref': vals['ref'], })] - else: - raise osv.except_osv(_('No analytic journal !'), _('Please set an analytic journal on this financial journal !')) + #else: + # raise osv.except_osv(_('No analytic journal !'), _('Please set an analytic journal on this financial journal !')) #if not 'currency_id' in vals: # vals['currency_id'] = account.company_id.currency_id.id From 4043a46f65de2e3c8d56116c02a4df82b4c8403f Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Thu, 18 Dec 2008 15:39:05 +0100 Subject: [PATCH 020/124] [FIX] Check if account_id if present lp bug: https://launchpad.net/bugs/309337 fixed bzr revid: stephane@tinyerp.com-20081218143905-uwv9umr7mss0dlb9 --- addons/account/account_move_line.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/account/account_move_line.py b/addons/account/account_move_line.py index 233eaf84de4..f32d150906d 100644 --- a/addons/account/account_move_line.py +++ b/addons/account/account_move_line.py @@ -466,7 +466,7 @@ class account_move_line(osv.osv): val['account_id'] = id2 elif jt=='purchase': val['account_id'] = id1 - if val['account_id']: + if val.get('account_id', False): d = self.onchange_account_id(cr, uid, ids, val['account_id']) val.update(d['value']) return {'value':val} From ef3beeae56603bcbd064f7091a2bd87834c0355f Mon Sep 17 00:00:00 2001 From: qdp Date: Thu, 18 Dec 2008 15:50:50 +0100 Subject: [PATCH 021/124] *bugfix bzr revid: qdp@tinyerp.com-20081218145050-fgwnkm5qhdnc7kpe --- addons/account_budget/crossovered_budget.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/account_budget/crossovered_budget.py b/addons/account_budget/crossovered_budget.py index 752e8c82694..6a78b317ea8 100644 --- a/addons/account_budget/crossovered_budget.py +++ b/addons/account_budget/crossovered_budget.py @@ -168,7 +168,7 @@ class crossovered_budget_lines(osv.osv): date_from = context['wizard_date_from'] if context.has_key('wizard_date_to'): date_to = context['wizard_date_to'] - cr.execute('select sum(amount) from account_analytic_line where account_id=%s and (date between to_date(%s,'yyyy-mm-dd') and to_date(%s,'yyyy-mm-dd')) and general_account_id in (%s)', (line.analytic_account_id.id,date_from,date_to,acc_ids)) + cr.execute("select sum(amount) from account_analytic_line where account_id=%s and (date between to_date(%s,'yyyy-mm-dd') and to_date(%s,'yyyy-mm-dd')) and general_account_id in (%s)", (line.analytic_account_id.id,date_from,date_to,acc_ids)) result=cr.fetchone()[0] if result==None: result=0.00 From 643d5f87bd28e1d67c9fa1643cb5c45aa9d04195 Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Thu, 18 Dec 2008 17:07:09 +0100 Subject: [PATCH 022/124] [FIX] Use the cursor.drop_view_if_exists lp bug: https://launchpad.net/bugs/309331 fixed bzr revid: stephane@tinyerp.com-20081218160709-bg3wqmp54df2chhv --- addons/crm_configuration/report/crm_report.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/crm_configuration/report/crm_report.py b/addons/crm_configuration/report/crm_report.py index 6b602e8e59a..772a5c3c7a8 100644 --- a/addons/crm_configuration/report/crm_report.py +++ b/addons/crm_configuration/report/crm_report.py @@ -86,7 +86,7 @@ class report_crm_case_section_stage(osv.osv): _order = 'stage_id, section_id' def init(self, cr): - drop_view_if_exists(cr, "report_crm_case_section_stage") + cr.drop_view_if_exists("report_crm_case_section_stage") cr.execute(""" create view report_crm_case_section_stage as ( select @@ -123,7 +123,7 @@ class report_crm_case_section_categ_stage(osv.osv): _order = 'stage_id, section_id, categ_id' def init(self, cr): - drop_view_if_exists(cr, "report_crm_case_section_categ_stage") + cr.drop_view_if_exists("report_crm_case_section_categ_stage") cr.execute(""" create view report_crm_case_section_categ_stage as ( select @@ -161,7 +161,7 @@ class report_crm_case_section_categ_categ2(osv.osv): _order = 'section_id, categ_id, category2_id' def init(self, cr): - drop_view_if_exists(cr, "report_crm_case_section_categ_categ2") + cr.drop_view_if_exists("report_crm_case_section_categ_categ2") cr.execute(""" create view report_crm_case_section_categ_categ2 as ( select From d8727111a67176e0ac9360fece92f81d6a602832 Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Thu, 18 Dec 2008 17:13:19 +0100 Subject: [PATCH 023/124] [IMP] Use the Cursor from sql_db bzr revid: stephane@tinyerp.com-20081218161319-bo4jn6ouum0qy32y --- bin/sql_db.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bin/sql_db.py b/bin/sql_db.py index 5cbe3e7420a..1d5bfce89e7 100644 --- a/bin/sql_db.py +++ b/bin/sql_db.py @@ -136,10 +136,10 @@ class Cursor(object): return res def drop_view_if_exists(self, viewname): - self._obj.execute("select count(1) from pg_class where relkind=%s and relname=%s", ('v', viewname,)) - if self._obj.fetchone()[0]: - self._obj.execute("DROP view %s" % (viewname,)) - self._obj.commit() + self.execute("select count(1) from pg_class where relkind=%s and relname=%s", ('v', viewname,)) + if self.fetchone()[0]: + self.execute("DROP view %s" % (viewname,)) + self.commit() def print_log(self): def process(type): From 9d5e63474ae54d580692d4116f7b1239c0ffe065 Mon Sep 17 00:00:00 2001 From: Fabien Pinckaers Date: Thu, 18 Dec 2008 18:57:56 +0100 Subject: [PATCH 024/124] improved_view bzr revid: fp@tinyerp.com-20081218175756-r430xwaweyysjfth --- addons/stock/stock_view.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml index e45732b4ae3..20aa537f08b 100644 --- a/addons/stock/stock_view.xml +++ b/addons/stock/stock_view.xml @@ -73,7 +73,7 @@
- Physical Inventory + Periodical Inventory ir.actions.act_window stock.inventory form @@ -82,7 +82,7 @@ - Draft Physical Inventories + Draft Periodical Inventories ir.actions.act_window stock.inventory form @@ -90,7 +90,7 @@ - New Physical Inventory + New Periodical Inventory ir.actions.act_window stock.inventory form From f4ea93ce26e355651557363c6260598b8ed4e326 Mon Sep 17 00:00:00 2001 From: Fabien Pinckaers Date: Thu, 18 Dec 2008 19:01:54 +0100 Subject: [PATCH 025/124] improved_views bzr revid: fp@tinyerp.com-20081218180154-zbq0h2iecaiuqdkp --- bin/addons/base/base_update.xml | 4 ++-- bin/addons/base/ir/ir.xml | 16 ++++++++-------- bin/osv/fields.py | 1 - 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/bin/addons/base/base_update.xml b/bin/addons/base/base_update.xml index 49bc289f337..7e0ee6e5219 100644 --- a/bin/addons/base/base_update.xml +++ b/bin/addons/base/base_update.xml @@ -257,13 +257,14 @@ + + Create User Create your users. You will be able to assign groups to users. Groups define the access rights of each users on the different objects of the system. - open 10 @@ -275,7 +276,6 @@ the simplified interface, which has less options and fields but is easier to understand. You will be able to switch to the extended view later.
- open 5 diff --git a/bin/addons/base/ir/ir.xml b/bin/addons/base/ir/ir.xml index b757dd163a5..c3987d05fa7 100644 --- a/bin/addons/base/ir/ir.xml +++ b/bin/addons/base/ir/ir.xml @@ -1154,7 +1154,7 @@ - + @@ -1273,28 +1273,28 @@ - + ir.actions.todo - Config Wizard Steps + Config Wizard Steps tree - + - + ir.actions.todo - Config Wizard Steps + Config Wizard Steps form
- + @@ -1307,7 +1307,7 @@ ir.actions.todo form - [('type','=','configure')] + [('type','=','configure')] diff --git a/bin/osv/fields.py b/bin/osv/fields.py index f692fc4c53a..e09010bb7f5 100644 --- a/bin/osv/fields.py +++ b/bin/osv/fields.py @@ -426,7 +426,6 @@ class one2many(_column): context = {} if not values: return - _table = obj.pool.get(self._obj)._table obj = obj.pool.get(self._obj) for act in values: From cfd194c028656a56db5e226bc35255ce26b65fe1 Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Thu, 18 Dec 2008 19:13:41 +0100 Subject: [PATCH 026/124] [REF] Refactoring bzr revid: stephane@tinyerp.com-20081218181341-dshfntv4olwgcbyx --- bin/netsvc.py | 72 +++++++++++++++-------------------- bin/openerp-server.py | 4 -- bin/ssl/SecureXMLRPCServer.py | 4 +- 3 files changed, 33 insertions(+), 47 deletions(-) diff --git a/bin/netsvc.py b/bin/netsvc.py index 7496a9703c0..56a4837ada6 100644 --- a/bin/netsvc.py +++ b/bin/netsvc.py @@ -24,7 +24,10 @@ import time import threading -import SimpleXMLRPCServer, signal, sys, xmlrpclib +import SimpleXMLRPCServer +import signal +import sys +import xmlrpclib import SocketServer import socket import logging @@ -249,23 +252,6 @@ class Agent(object): timer.cancel() quit = classmethod(quit) - -class RpcGateway(object): - def __init__(self, name): - self.name = name - - -class Dispatcher(object): - def __init__(self): - pass - - def monitor(self, signal): - pass - - def run(self): - pass - - class xmlrpc(object): class RpcGateway(object): def __init__(self, name): @@ -273,22 +259,30 @@ class xmlrpc(object): class GenericXMLRPCRequestHandler: + def log(self, title, msg): + from pprint import pformat + Logger().notifyChannel('XMLRPC-%s' % title, LOG_DEBUG_RPC, pformat(msg)) + def _dispatch(self, method, params): -# print 'TERP-CALL : ',method, params import traceback + traceback.print_stack() try: + self.log('method', method) + self.log('params', params) n = self.path.split("/")[-1] s = LocalService(n) m = getattr(s, method) s._service._response = None r = m(*params) + self.log('result', r) res = s._service._response - if res != None: + if res is not None: r = res + self.log('res',r) return r except Exception, e: - tb_s = reduce(lambda x, y: x+y, traceback.format_exception( - sys.exc_type, sys.exc_value, sys.exc_traceback)) + self.log('exception', e) + tb_s = reduce(lambda x, y: x+y, traceback.format_exception(sys.exc_type, sys.exc_value, sys.exc_traceback)) s = str(e) import tools if tools.config['debug_mode']: @@ -297,22 +291,7 @@ class GenericXMLRPCRequestHandler: pdb.post_mortem(tb) raise xmlrpclib.Fault(s, tb_s) - -class SimpleXMLRPCRequestHandler(GenericXMLRPCRequestHandler, SimpleXMLRPCServer.SimpleXMLRPCRequestHandler): - SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.rpc_paths = get_rpc_paths() - -class SimpleThreadedXMLRPCServer(SocketServer.ThreadingMixIn, SimpleXMLRPCServer.SimpleXMLRPCServer): - - def server_bind(self): - try: - self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - SimpleXMLRPCServer.SimpleXMLRPCServer.server_bind(self) - except: - Logger().notifyChannel('init', LOG_CRITICAL, 'Address already in use') - sys.exit(1) - class HttpDaemon(threading.Thread): - def __init__(self, interface, port, secure=False): threading.Thread.__init__(self) self.__port = port @@ -330,14 +309,23 @@ class HttpDaemon(threading.Thread): self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) SecureXMLRPCServer.SecureXMLRPCServer.server_bind(self) except: - sys.stderr.write("ERROR: address already in use\n") + Logger().notifyChannel('init', LOG_CRITICAL, 'Address already in use') sys.exit(1) - self.server = SecureThreadedXMLRPCServer((interface, port), - SecureXMLRPCRequestHandler, 0) + self.server = SecureThreadedXMLRPCServer((interface, port), SecureXMLRPCRequestHandler, 0) else: - self.server = SimpleThreadedXMLRPCServer((interface, port), - SimpleXMLRPCRequestHandler, 0) + class SimpleXMLRPCRequestHandler(GenericXMLRPCRequestHandler, SimpleXMLRPCServer.SimpleXMLRPCRequestHandler): + SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.rpc_paths = get_rpc_paths() + + class SimpleThreadedXMLRPCServer(SocketServer.ThreadingMixIn, SimpleXMLRPCServer.SimpleXMLRPCServer): + def server_bind(self): + try: + self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + SimpleXMLRPCServer.SimpleXMLRPCServer.server_bind(self) + except: + Logger().notifyChannel('init', LOG_CRITICAL, 'Address already in use') + sys.exit(1) + self.server = SimpleThreadedXMLRPCServer((interface, port), SimpleXMLRPCRequestHandler, 0) def attach(self, path, gw): pass diff --git a/bin/openerp-server.py b/bin/openerp-server.py index f52d8415d6d..951b994d9b7 100755 --- a/bin/openerp-server.py +++ b/bin/openerp-server.py @@ -76,9 +76,6 @@ if sys.platform == 'win32': #---------------------------------------------------------- logger.notifyChannel("objects", netsvc.LOG_INFO, 'initialising distributed objects services') -dispatcher = netsvc.Dispatcher() -dispatcher.monitor(signal.SIGINT) - #--------------------------------------------------------------- # connect to the database and initialize it with base if needed #--------------------------------------------------------------- @@ -214,7 +211,6 @@ if tools.config['netrpc']: tinySocket.start() if tools.config['xmlrpc']: httpd.start() -#dispatcher.run() while True: time.sleep(1) diff --git a/bin/ssl/SecureXMLRPCServer.py b/bin/ssl/SecureXMLRPCServer.py index e8493ba6adb..bdcf11d4fc2 100644 --- a/bin/ssl/SecureXMLRPCServer.py +++ b/bin/ssl/SecureXMLRPCServer.py @@ -32,7 +32,9 @@ This code is in the public domain and is provided AS-IS WITH NO WARRANTY WHATSOEVER. """ import SocketServer -import os, socket, sys +import os +import socket +import sys import SimpleXMLRPCServer from OpenSSL import SSL From c8727c26aa871723d5aad46fcdca80599178226a Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Thu, 18 Dec 2008 20:00:07 +0100 Subject: [PATCH 027/124] [REF] PEP8 bzr revid: stephane@tinyerp.com-20081218190007-otkpkslf4y88k1c6 --- bin/service/web_services.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/bin/service/web_services.py b/bin/service/web_services.py index 07fdd7412f9..580f9ca6c16 100644 --- a/bin/service/web_services.py +++ b/bin/service/web_services.py @@ -20,20 +20,23 @@ # ############################################################################## -import base64, os, string - -import netsvc -import pooler, security, ir, tools +import base64 import logging - -import threading, thread - +import os +import security +import string +import thread +import threading import time -import addons -import sql_db from tools.translate import _ +import addons +import ir +import netsvc +import pooler import release +import sql_db +import tools logging.basicConfig() From 20e82c3cf91b23fe25bddf80b008e45e59fb387d Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Thu, 18 Dec 2008 20:13:14 +0100 Subject: [PATCH 028/124] [REF] Refactoring bzr revid: stephane@tinyerp.com-20081218191314-jono5ck1rucut52p --- bin/netsvc.py | 64 +++++++++++++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/bin/netsvc.py b/bin/netsvc.py index 56a4837ada6..8e74b9346a9 100644 --- a/bin/netsvc.py +++ b/bin/netsvc.py @@ -144,8 +144,6 @@ def service_exist(name): return (name in _service) and bool(_service[name]) -def get_rpc_paths(): - return map(lambda s: '/xmlrpc/%s' % s, _service) LOG_DEBUG_RPC = 'debug_rpc' @@ -291,41 +289,47 @@ class GenericXMLRPCRequestHandler: pdb.post_mortem(tb) raise xmlrpclib.Fault(s, tb_s) + +#### XML-RPC SSL #### +from ssl import SecureXMLRPCServer +class SecureXMLRPCRequestHandler(GenericXMLRPCRequestHandler, SecureXMLRPCServer.SecureXMLRPCRequestHandler): + SecureXMLRPCServer.SecureXMLRPCRequestHandler.rpc_paths = map(lambda s: '/xmlrpc/%s' % s, _service) + +class SecureThreadedXMLRPCServer(SocketServer.ThreadingMixIn, SecureXMLRPCServer.SecureXMLRPCServer): + def server_bind(self): + try: + self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + SecureXMLRPCServer.SecureXMLRPCServer.server_bind(self) + except: + Logger().notifyChannel('init', LOG_CRITICAL, 'Address already in use') + sys.exit(1) + +#### XML-RPC #### +class SimpleXMLRPCRequestHandler(GenericXMLRPCRequestHandler, SimpleXMLRPCServer.SimpleXMLRPCRequestHandler): + SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.rpc_paths = map(lambda s: '/xmlrpc/%s' % s, _service) + +class SimpleThreadedXMLRPCServer(SocketServer.ThreadingMixIn, SimpleXMLRPCServer.SimpleXMLRPCServer): + def server_bind(self): + try: + self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + SimpleXMLRPCServer.SimpleXMLRPCServer.server_bind(self) + except: + Logger().notifyChannel('init', LOG_CRITICAL, 'Address already in use') + sys.exit(1) + class HttpDaemon(threading.Thread): def __init__(self, interface, port, secure=False): threading.Thread.__init__(self) self.__port = port self.__interface = interface self.secure = secure - if secure: - from ssl import SecureXMLRPCServer - - class SecureXMLRPCRequestHandler(GenericXMLRPCRequestHandler, SecureXMLRPCServer.SecureXMLRPCRequestHandler): - SecureXMLRPCServer.SecureXMLRPCRequestHandler.rpc_paths = get_rpc_paths() - - class SecureThreadedXMLRPCServer(SocketServer.ThreadingMixIn, SecureXMLRPCServer.SecureXMLRPCServer): - def server_bind(self): - try: - self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - SecureXMLRPCServer.SecureXMLRPCServer.server_bind(self) - except: - Logger().notifyChannel('init', LOG_CRITICAL, 'Address already in use') - sys.exit(1) - - self.server = SecureThreadedXMLRPCServer((interface, port), SecureXMLRPCRequestHandler, 0) + if self.secure: + handler_class = SecureXMLRPCRequestHandler + server_class = SecureThreadedXMLRPCServer else: - class SimpleXMLRPCRequestHandler(GenericXMLRPCRequestHandler, SimpleXMLRPCServer.SimpleXMLRPCRequestHandler): - SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.rpc_paths = get_rpc_paths() - - class SimpleThreadedXMLRPCServer(SocketServer.ThreadingMixIn, SimpleXMLRPCServer.SimpleXMLRPCServer): - def server_bind(self): - try: - self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - SimpleXMLRPCServer.SimpleXMLRPCServer.server_bind(self) - except: - Logger().notifyChannel('init', LOG_CRITICAL, 'Address already in use') - sys.exit(1) - self.server = SimpleThreadedXMLRPCServer((interface, port), SimpleXMLRPCRequestHandler, 0) + handler_class = SimpleXMLRPCRequestHandler + server_class = SimpleThreadedXMLRPCServer + self.server = server_class((interface, port), handler_class, 0) def attach(self, path, gw): pass From c843e6a8c216f7630952e71a6862605deec7b162 Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Thu, 18 Dec 2008 20:18:26 +0100 Subject: [PATCH 029/124] [REF] Refactoring bzr revid: stephane@tinyerp.com-20081218191826-9s3ubtahbnj120eq --- bin/netsvc.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/bin/netsvc.py b/bin/netsvc.py index 8e74b9346a9..3edf977624f 100644 --- a/bin/netsvc.py +++ b/bin/netsvc.py @@ -263,7 +263,6 @@ class GenericXMLRPCRequestHandler: def _dispatch(self, method, params): import traceback - traceback.print_stack() try: self.log('method', method) self.log('params', params) @@ -337,16 +336,11 @@ class HttpDaemon(threading.Thread): def stop(self): self.running = False if os.name != 'nt': - if hasattr(socket, 'SHUT_RDWR'): - if self.secure: - self.server.socket.sock_shutdown(socket.SHUT_RDWR) - else: - self.server.socket.shutdown(socket.SHUT_RDWR) + value = hasattr(socket, 'SHUT_RDWR') and socket.SHUT_RDWR or 2 + if self.secure: + self.server.socket.sock_shutdown(value) else: - if self.secure: - self.server.socket.sock_shutdown(2) - else: - self.server.socket.shutdown(2) + self.server.socket.shutdown(value) self.server.socket.close() def run(self): From 6cede6020bd662b891a88099ce6b900eb5476e2c Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Thu, 18 Dec 2008 20:32:25 +0100 Subject: [PATCH 030/124] [REF] Remove unused code bzr revid: stephane@tinyerp.com-20081218193225-k517sb10l4qdzrbk --- bin/netsvc.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/bin/netsvc.py b/bin/netsvc.py index 3edf977624f..4143092eabe 100644 --- a/bin/netsvc.py +++ b/bin/netsvc.py @@ -134,18 +134,9 @@ class LocalService(Service): Logger().notifyChannel('module', LOG_ERROR, 'This service does not exists: %s' % (str(keyError),) ) raise - - -class ServiceUnavailable(Exception): - pass - - def service_exist(name): return (name in _service) and bool(_service[name]) - - - LOG_DEBUG_RPC = 'debug_rpc' LOG_DEBUG = 'debug' LOG_INFO = 'info' @@ -255,7 +246,6 @@ class xmlrpc(object): def __init__(self, name): self.name = name - class GenericXMLRPCRequestHandler: def log(self, title, msg): from pprint import pformat From 242b3c53c29e6895662eddfa388cc150c1884d55 Mon Sep 17 00:00:00 2001 From: Fabien Pinckaers Date: Thu, 18 Dec 2008 20:39:18 +0100 Subject: [PATCH 031/124] improved_spped bzr revid: fp@tinyerp.com-20081218193918-zgfe299e76ljku6q --- addons/product/product.py | 17 ++++++++++------- addons/sale/product.py | 2 ++ addons/stock/product.py | 19 +++++++++++++++---- addons/stock/product_view.xml | 2 -- 4 files changed, 27 insertions(+), 13 deletions(-) diff --git a/addons/product/product.py b/addons/product/product.py index 74d9549a78c..35d0bb4182e 100644 --- a/addons/product/product.py +++ b/addons/product/product.py @@ -109,17 +109,20 @@ class product_uom(osv.osv): from_unit, to_unit = uoms[0], uoms[-1] else: from_unit, to_unit = uoms[-1], uoms[0] + return self._compute_qty_obj(cr, uid, from_unit, qty, to_unit) + + def _compute_qty_obj(self, cr, uid, from_unit, qty, to_unit, context={}): if from_unit.category_id.id <> to_unit.category_id.id: return qty - if from_unit['factor_inv_data']: - amount = qty * from_unit['factor_inv_data'] + if from_unit.factor_inv_data: + amount = qty * from_unit.factor_inv_data else: - amount = qty / from_unit['factor'] - if to_uom_id: - if to_unit['factor_inv_data']: - amount = rounding(amount / to_unit['factor_inv_data'], to_unit['rounding']) + amount = qty / from_unit.factor + if to_unit: + if to_unit.factor_inv_data: + amount = rounding(amount / to_unit.factor_inv_data, to_unit.rounding) else: - amount = rounding(amount * to_unit['factor'], to_unit['rounding']) + amount = rounding(amount * to_unit.factor, to_unit.rounding) return amount def _compute_price(self, cr, uid, from_uom_id, price, to_uom_id=False): diff --git a/addons/sale/product.py b/addons/sale/product.py index 661dee6fa85..403f10be577 100644 --- a/addons/sale/product.py +++ b/addons/sale/product.py @@ -57,11 +57,13 @@ class product_product(osv.osv): _pricelist_calculate, method=True, string='Sale Pricelists', + store=True, type="text"), 'pricelist_purchase':fields.function( _pricelist_calculate, method=True, string='Purchase Pricelists', + store=True, type="text"), } diff --git a/addons/stock/product.py b/addons/stock/product.py index b43275b7961..97197f606f7 100644 --- a/addons/stock/product.py +++ b/addons/stock/product.py @@ -71,9 +71,11 @@ class product_product(osv.osv): states_str = ','.join(map(lambda s: "'%s'" % s, states)) + uoms_o = {} product2uom = {} for product in self.browse(cr, uid, ids, context=context): product2uom[product.id] = product.uom_id.id + uoms_o[product.uom_id.id] = product.uom_id prod_ids_str = ','.join(map(str, ids)) location_ids_str = ','.join(map(str, location_ids)) @@ -115,13 +117,22 @@ class product_product(osv.osv): ) results2 = cr.fetchall() uom_obj = self.pool.get('product.uom') + uoms = map(lambda x: x[2], results) + map(lambda x: x[2], results2) + if context.get('uom', False): + uoms += [context['uom']] + + uoms = filter(lambda x: x not in uoms_o.keys(), uoms) + if uoms: + uoms = uom_obj.browse(cr, uid, list(set(uoms)), context=context) + for o in uoms: + uoms_o[o.id] = o for amount, prod_id, prod_uom in results: - amount = uom_obj._compute_qty(cr, uid, prod_uom, amount, - context.get('uom', False) or product2uom[prod_id]) + amount = uom_obj._compute_qty_obj(cr, uid, uoms_o[prod_uom], amount, + uoms_o[context.get('uom', False) or product2uom[prod_id]]) res[prod_id] += amount for amount, prod_id, prod_uom in results2: - amount = uom_obj._compute_qty(cr, uid, prod_uom, amount, - context.get('uom', False) or product2uom[prod_id]) + amount = uom_obj._compute_qty_obj(cr, uid, uoms_o[prod_uom], amount, + uoms_o[context.get('uom', False) or product2uom[prod_id]]) res[prod_id] -= amount return res diff --git a/addons/stock/product_view.xml b/addons/stock/product_view.xml index c82391a2df2..3b49f0749f7 100644 --- a/addons/stock/product_view.xml +++ b/addons/stock/product_view.xml @@ -67,8 +67,6 @@ - - From 0d7928187bd25ecc284753e6abd2b5215b53949e Mon Sep 17 00:00:00 2001 From: Fabien Pinckaers Date: Thu, 18 Dec 2008 20:41:14 +0100 Subject: [PATCH 032/124] improved_cache_system bzr revid: fp@tinyerp.com-20081218194114-luni7m4gly8zsrdb --- bin/addons/base/ir/ir_translation.py | 1 + bin/tools/misc.py | 51 ++++++++++++++++++++++------ 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/bin/addons/base/ir/ir_translation.py b/bin/addons/base/ir/ir_translation.py index 0e9e28ddeed..f5beb9475b5 100644 --- a/bin/addons/base/ir/ir_translation.py +++ b/bin/addons/base/ir/ir_translation.py @@ -79,6 +79,7 @@ class ir_translation(osv.osv): cr.execute('CREATE INDEX ir_translation_lts ON ir_translation (lang, type, src)') cr.commit() + @tools.cache(skiparg=3) def _get_ids(self, cr, uid, name, tt, lang, ids): translations = {} if ids: diff --git a/bin/tools/misc.py b/bin/tools/misc.py index ebf0606601d..7936db55c00 100644 --- a/bin/tools/misc.py +++ b/bin/tools/misc.py @@ -542,11 +542,20 @@ class cache(object): self.timeout = timeout self.skiparg = skiparg self.multi = multi + self.lasttime = time.time() self.cache = {} def __call__(self, fn): arg_names = inspect.getargspec(fn)[0][self.skiparg:] + def cached_result(self2, cr=None, *args, **kwargs): + if time.time()-self.timeout > self.lasttime: + self.lasttime = time.time() + t = time.time()-self.timeout + for key in self.cache: + if self.cache[key][1] Date: Thu, 18 Dec 2008 20:54:16 +0100 Subject: [PATCH 033/124] modifs bzr revid: fp@tinyerp.com-20081218195416-c58rua8iy1z5jqcj --- addons/sale/product_view.xml | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/addons/sale/product_view.xml b/addons/sale/product_view.xml index f61788dee04..f7bfdcd7395 100644 --- a/addons/sale/product_view.xml +++ b/addons/sale/product_view.xml @@ -2,22 +2,6 @@ - - view.product.pricelists.function.form.inherit - product.product - form - - - - - - - - - - - - From 65f7d198ec8502225be2259964b0bd3b288e7e99 Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Thu, 18 Dec 2008 21:28:01 +0100 Subject: [PATCH 034/124] [IMP] I don't like the duplicated code bzr revid: christophe@taupe-20081218202801-xnin2g0yd2njwmk9 --- bin/netsvc.py | 53 ++++++++++++++++++--------------------------------- 1 file changed, 19 insertions(+), 34 deletions(-) diff --git a/bin/netsvc.py b/bin/netsvc.py index 4143092eabe..90b9659b456 100644 --- a/bin/netsvc.py +++ b/bin/netsvc.py @@ -25,6 +25,8 @@ import time import threading import SimpleXMLRPCServer +from ssl import SecureXMLRPCServer + import signal import sys import xmlrpclib @@ -279,46 +281,29 @@ class GenericXMLRPCRequestHandler: raise xmlrpclib.Fault(s, tb_s) -#### XML-RPC SSL #### -from ssl import SecureXMLRPCServer -class SecureXMLRPCRequestHandler(GenericXMLRPCRequestHandler, SecureXMLRPCServer.SecureXMLRPCRequestHandler): - SecureXMLRPCServer.SecureXMLRPCRequestHandler.rpc_paths = map(lambda s: '/xmlrpc/%s' % s, _service) - -class SecureThreadedXMLRPCServer(SocketServer.ThreadingMixIn, SecureXMLRPCServer.SecureXMLRPCServer): - def server_bind(self): - try: - self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - SecureXMLRPCServer.SecureXMLRPCServer.server_bind(self) - except: - Logger().notifyChannel('init', LOG_CRITICAL, 'Address already in use') - sys.exit(1) - -#### XML-RPC #### -class SimpleXMLRPCRequestHandler(GenericXMLRPCRequestHandler, SimpleXMLRPCServer.SimpleXMLRPCRequestHandler): - SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.rpc_paths = map(lambda s: '/xmlrpc/%s' % s, _service) - -class SimpleThreadedXMLRPCServer(SocketServer.ThreadingMixIn, SimpleXMLRPCServer.SimpleXMLRPCServer): - def server_bind(self): - try: - self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - SimpleXMLRPCServer.SimpleXMLRPCServer.server_bind(self) - except: - Logger().notifyChannel('init', LOG_CRITICAL, 'Address already in use') - sys.exit(1) class HttpDaemon(threading.Thread): def __init__(self, interface, port, secure=False): threading.Thread.__init__(self) self.__port = port self.__interface = interface - self.secure = secure - if self.secure: - handler_class = SecureXMLRPCRequestHandler - server_class = SecureThreadedXMLRPCServer - else: - handler_class = SimpleXMLRPCRequestHandler - server_class = SimpleThreadedXMLRPCServer - self.server = server_class((interface, port), handler_class, 0) + self.secure = bool(secure) + + base_handler_class = [SimpleXMLRPCServer.SimpleXMLRPCRequestHandler, SecureXMLRPCServer.SecureXMLRPCRequestHandler][self.secure] + class OpenERPXMLRPCRequestHandler(GenericXMLRPCRequestHandler, base_handler_class): + base_handler_class.rpc_paths = map(lambda s: '/xmlrpc/%s' % s, _service) + + base_server_class = [SimpleXMLRPCServer.SimpleXMLRPCServer, SecureXMLRPCServer.SecureXMLRPCServer][self.secure] + class OpenERPThreadedXMLRPCServer(SocketServer.ThreadingMixIn, base_server_class): + def server_bind(self): + try: + self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + base_server_class.server_bind(self) + except: + Logger().notifyChannel('init', LOG_CRITICAL, 'Address already in use') + sys.exit(1) + + self.server = OpenERPThreadedXMLRPCServer((interface, port), OpenERPXMLRPCRequestHandler, 0) def attach(self, path, gw): pass From 07f14f56139731fb2c3d774aff14b85fcd91ae5e Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Thu, 18 Dec 2008 22:36:30 +0100 Subject: [PATCH 035/124] [IMP] Use the logger bzr revid: stephane@tinyerp.com-20081218213630-i4e0noy12vobjfyw --- bin/openerp-server.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/bin/openerp-server.py b/bin/openerp-server.py index 951b994d9b7..e0621a87d86 100755 --- a/bin/openerp-server.py +++ b/bin/openerp-server.py @@ -159,7 +159,13 @@ if tools.config['xmlrpc']: interface = tools.config["interface"] secure = tools.config["secure"] - httpd = netsvc.HttpDaemon(interface, port, secure) + import OpenSSL + + try: + httpd = netsvc.HttpDaemon(interface, port, secure) + except OpenSSL.SSL.Error, error: + logger.notifyChannel('xml-rpc-ssl', netsvc.LOG_CRITICAL, "Can't load the certificate and/or the private key files" ) + sys.exit(1) if tools.config["xmlrpc"]: xml_gw = netsvc.xmlrpc.RpcGateway('web-services') From 70bd7ea91ad6e7217f3dac583f102b23a6e3f408 Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Thu, 18 Dec 2008 22:48:31 +0100 Subject: [PATCH 036/124] [REF] Rename the variables bzr revid: stephane@tinyerp.com-20081218214831-hbje1kxhmkblz82i --- bin/netsvc.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/bin/netsvc.py b/bin/netsvc.py index 90b9659b456..ced46c4aaa1 100644 --- a/bin/netsvc.py +++ b/bin/netsvc.py @@ -365,16 +365,17 @@ class TinySocketClientThread(threading.Thread): return False try: self.log(msg) - s = LocalService(msg[0]) - m = getattr(s, msg[1]) - s._service._response = None - r = m(*msg[2:]) - res = s._service._response + service = LocalService(msg[0]) + method = getattr(service, msg[1]) + service._service._response = None + result_from_method = method(*msg[2:]) + res = service._service._response if res != None: - r = res - self.log(r) - ts.mysend(r) + result_from_method = res + self.log(result_from_method) + ts.mysend(result_from_method) except Exception, e: + print repr(e) tb_s = reduce(lambda x, y: x+y, traceback.format_exception(sys.exc_type, sys.exc_value, sys.exc_traceback)) import tools if tools.config['debug_mode']: From 12e2aef08c9511356d241be6c9a1451da8e1993c Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Fri, 19 Dec 2008 00:54:33 +0100 Subject: [PATCH 037/124] [FIX] XML-RPC SSL bzr revid: stephane@tinyerp.com-20081218235433-cnsc5a4iyfzqvbdx --- bin/netsvc.py | 79 +++++++++++-------- bin/ssl/SecureXMLRPCServer.py | 139 ---------------------------------- bin/ssl/__init__.py | 27 ------- bin/ssl/server.cert | 14 ---- bin/ssl/server.pkey | 15 ---- 5 files changed, 48 insertions(+), 226 deletions(-) delete mode 100644 bin/ssl/SecureXMLRPCServer.py delete mode 100644 bin/ssl/__init__.py delete mode 100644 bin/ssl/server.cert delete mode 100644 bin/ssl/server.pkey diff --git a/bin/netsvc.py b/bin/netsvc.py index ced46c4aaa1..888117ba639 100644 --- a/bin/netsvc.py +++ b/bin/netsvc.py @@ -21,27 +21,23 @@ # ############################################################################## -import time -import threading - import SimpleXMLRPCServer -from ssl import SecureXMLRPCServer - -import signal -import sys -import xmlrpclib import SocketServer -import socket import logging import logging.handlers import os +import signal +import socket +import sys +import threading +import time +import xmlrpclib _service = {} _group = {} _res_id = 1 _res = {} - class ServiceEndPointCall(object): def __init__(self, id, method): self._id = id @@ -280,7 +276,45 @@ class GenericXMLRPCRequestHandler: pdb.post_mortem(tb) raise xmlrpclib.Fault(s, tb_s) +# refactoring from Tryton (B2CK, Cedric Krier, Bertrand Chenal) +class SSLSocket(object): + def __init__(self, socket): + if not hasattr(socket, 'sock_shutdown'): + from OpenSSL import SSL + ctx = SSL.Context(SSL.SSLv23_METHOD) + ctx.use_privatekey_file('server.pkey') + ctx.use_certificate_file('server.cert') + self.socket = SSL.Connection(ctx, socket) + else: + self.socket = socket + def shutdown(self, how): + return self.socket.sock_shutdown(how) + + def __getattr__(self, name): + return getattr(self.socket, name) + +class SimpleXMLRPCRequestHandler(GenericXMLRPCRequestHandler, SimpleXMLRPCServer.SimpleXMLRPCRequestHandler): + rpc_paths = map(lambda s: '/xmlrpc/%s' % s, _service) + +class SecureXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): + def setup(self): + self.connection = SSLSocket(self.request) + self.rfile = socket._fileobject(self.request, "rb", self.rbufsize) + self.wfile = socket._fileobject(self.request, "wb", self.wbufsize) + +class SimpleThreadedXMLRPCServer(SocketServer.ThreadingMixIn, SimpleXMLRPCServer.SimpleXMLRPCServer): + def server_bind(self): + self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + SimpleXMLRPCServer.SimpleXMLRPCServer.server_bind(self) + +class SecureThreadedXMLRPCServer(SimpleThreadedXMLRPCServer): + def __init__(self, server_address, HandlerClass, logRequests=1): + SimpleThreadedXMLRPCServer.__init__(self, server_address, HandlerClass, logRequests) + self.socket = SSLSocket(socket.socket(self.address_family, self.socket_type)) + self.server_bind() + self.server_activate() +# end of refactoring from Tryton class HttpDaemon(threading.Thread): def __init__(self, interface, port, secure=False): @@ -288,22 +322,9 @@ class HttpDaemon(threading.Thread): self.__port = port self.__interface = interface self.secure = bool(secure) - - base_handler_class = [SimpleXMLRPCServer.SimpleXMLRPCRequestHandler, SecureXMLRPCServer.SecureXMLRPCRequestHandler][self.secure] - class OpenERPXMLRPCRequestHandler(GenericXMLRPCRequestHandler, base_handler_class): - base_handler_class.rpc_paths = map(lambda s: '/xmlrpc/%s' % s, _service) - - base_server_class = [SimpleXMLRPCServer.SimpleXMLRPCServer, SecureXMLRPCServer.SecureXMLRPCServer][self.secure] - class OpenERPThreadedXMLRPCServer(SocketServer.ThreadingMixIn, base_server_class): - def server_bind(self): - try: - self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - base_server_class.server_bind(self) - except: - Logger().notifyChannel('init', LOG_CRITICAL, 'Address already in use') - sys.exit(1) - - self.server = OpenERPThreadedXMLRPCServer((interface, port), OpenERPXMLRPCRequestHandler, 0) + handler_class = (SimpleXMLRPCRequestHandler, SecureXMLRPCRequestHandler)[self.secure] + server_class = (SimpleThreadedXMLRPCServer, SecureThreadedXMLRPCServer)[self.secure] + self.server = server_class((interface, port), handler_class, 0) def attach(self, path, gw): pass @@ -311,11 +332,7 @@ class HttpDaemon(threading.Thread): def stop(self): self.running = False if os.name != 'nt': - value = hasattr(socket, 'SHUT_RDWR') and socket.SHUT_RDWR or 2 - if self.secure: - self.server.socket.sock_shutdown(value) - else: - self.server.socket.shutdown(value) + self.server.socket.shutdown( hasattr(socket, 'SHUT_RDWR') and socket.SHUT_RDWR or 2 ) self.server.socket.close() def run(self): diff --git a/bin/ssl/SecureXMLRPCServer.py b/bin/ssl/SecureXMLRPCServer.py deleted file mode 100644 index bdcf11d4fc2..00000000000 --- a/bin/ssl/SecureXMLRPCServer.py +++ /dev/null @@ -1,139 +0,0 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2008 Tiny SPRL (). All Rights Reserved -# $Id$ -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -############################################################################## -""" -SecureXMLRPCServer module using pyOpenSSL 0.5 -Extremely kludgey code written 0907.2002 -by Michal Wallace ( http://www.sabren.net/ ) - -This acts as a drop-in replacement for -SimpleXMLRPCServer from the standard python -library. - -This code is in the public domain and is -provided AS-IS WITH NO WARRANTY WHATSOEVER. -""" -import SocketServer -import os -import socket -import sys -import SimpleXMLRPCServer -from OpenSSL import SSL - - -class SSLBugFix: - """ - SSL Connection tends to die on sendall, - so I use send() as a workaround. This is - called by socket._fileobject, which is needed - so SocketServer (and kids) can treat the connection - as a regular file. - """ - def __init__(self, conn): - """ - For some reason, I can't subclass Connection, - so I'm making a proxy, instead. - """ - self.__dict__["conn"] = conn - def __getattr__(self,name): - return getattr(self.__dict__["conn"], name) - def __setattr__(self,name, value): - setattr(self.__dict__["conn"], name, value) - - -# def sendall(self, data): -# """ -# This is the bugfix. Connection.sendall() segfaults -# on socket._fileobject.flush(), so just rewire it -# to use send() instead. -# """ -# self.__dict__["conn"].send(data) - - def shutdown(self, how=1): - """ - This isn't part of the bugfix. SimpleXMLRpcServer.doPOST - calls shutdown(1), and Connection.shutdown() doesn't take - an argument. So we just discard it: - """ - self.__dict__["conn"].shutdown() - - def accept(self): - """ - This is the other part of the shutdown() workaround. - Since servers create new sockets, we have to infect - them with our magic. :) - """ - c, a = self.__dict__["conn"].accept() - return (SSLBugFix(c), a) - - - -class SecureTCPServer(SocketServer.TCPServer): - """ - Just like TCPServer, but use a socket. - This really ought to let you specify the key and certificate files. - """ - def __init__(self, server_address, RequestHandlerClass): - SocketServer.BaseServer.__init__(self, server_address, RequestHandlerClass) - - ## Same as normal, but make it secure: - ctx = SSL.Context(SSL.SSLv23_METHOD) - ctx.set_options(SSL.OP_NO_SSLv2) - - dir = os.path.join(os.getcwd(), os.path.dirname(sys.argv[0])) - ctx.use_privatekey_file (os.path.join(dir, 'server.pkey')) - ctx.use_certificate_file(os.path.join(dir, 'server.cert')) - - self.socket = SSLBugFix(SSL.Connection(ctx, socket.socket(self.address_family, - self.socket_type))) - self.server_bind() - self.server_activate() - - -class SecureXMLRPCRequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler): - def setup(self): - """ - We need to use socket._fileobject Because SSL.Connection - doesn't have a 'dup'. Not exactly sure WHY this is, but - this is backed up by comments in socket.py and SSL/connection.c - """ - self.connection = self.request # for doPOST - self.rfile = socket._fileobject(self.request, "rb", self.rbufsize) - self.wfile = socket._fileobject(self.request, "wb", self.wbufsize) - - -class SecureXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer, SecureTCPServer): - def __init__(self, addr, - requestHandler=SecureXMLRPCRequestHandler, - logRequests=1): - """ - This is the exact same code as SimpleXMLRPCServer.__init__ - except it calls SecureTCPServer.__init__ instead of plain - old TCPServer.__init__ - """ - self.funcs = {} - self.logRequests = logRequests - self.instance = None - SecureTCPServer.__init__(self, addr, requestHandler) - - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - diff --git a/bin/ssl/__init__.py b/bin/ssl/__init__.py deleted file mode 100644 index 613a9cff196..00000000000 --- a/bin/ssl/__init__.py +++ /dev/null @@ -1,27 +0,0 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2008 Tiny SPRL (). All Rights Reserved -# $Id$ -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -############################################################################## - - -import SecureXMLRPCServer - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - diff --git a/bin/ssl/server.cert b/bin/ssl/server.cert deleted file mode 100644 index de04f1ca33d..00000000000 --- a/bin/ssl/server.cert +++ /dev/null @@ -1,14 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICNDCCAZ0CAQEwDQYJKoZIhvcNAQEEBQAweTEQMA4GA1UEChMHVGlueUVSUDEM -MAoGA1UECxMDRVJQMRkwFwYJKoZIhvcNAQkBFgpmcEB0aW55LmJlMRAwDgYDVQQH -EwdXYWxoYWluMQswCQYDVQQIEwJCVzELMAkGA1UEBhMCQkUxEDAOBgNVBAMTB1Rp -bnlFUlAwHhcNMDYwNTI0MDgzODUxWhcNMDcwNTI0MDgzODUxWjBMMQswCQYDVQQG -EwJCRTELMAkGA1UECBMCQlcxEDAOBgNVBAoTB1RpbnlFUlAxDDAKBgNVBAsTA0VS -UDEQMA4GA1UEAxMHVGlueUVSUDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA -xzIDlU2PrczPsgXtxCskYxuwMPgNCNSCBfWsUZ9nJzlZfRAEXEq4LxaTPIgkzkIF -82bmJLgFz6/CyCFid4mkBLQBj30Opp2Vco39WRncNKHKxbk+/wZpZtQ0bSpvf+F4 -MBqCLldYIqsoyenombVCb8X62IUu0ENF1wR22owvyKcCAwEAATANBgkqhkiG9w0B -AQQFAAOBgQB2yUqJ3gbQ8I6rcmaVJlcLDHfC5w1Jr1cUzcJevOPh3wygSZYYoUoe -yeYlzEag/DpPSHyRiJJVOKdiwU0yfmZPhfDNtDiBr47bz8qzIsYq5VeMmSeXrq/f -AA3iI4xE8YFzJHWtiBCqqyUok+j9pVad7iV7+UVIePHZLEkGGWIjDA== ------END CERTIFICATE----- diff --git a/bin/ssl/server.pkey b/bin/ssl/server.pkey deleted file mode 100644 index 1b1b7d63942..00000000000 --- a/bin/ssl/server.pkey +++ /dev/null @@ -1,15 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIICXAIBAAKBgQDHMgOVTY+tzM+yBe3EKyRjG7Aw+A0I1IIF9axRn2cnOVl9EARc -SrgvFpM8iCTOQgXzZuYkuAXPr8LIIWJ3iaQEtAGPfQ6mnZVyjf1ZGdw0ocrFuT7/ -Bmlm1DRtKm9/4XgwGoIuV1giqyjJ6eiZtUJvxfrYhS7QQ0XXBHbajC/IpwIDAQAB -AoGAVwAxMHS/3FkoHckZICT3r5HYUosEpmaqo4+5w6yrkSYrP8RPI0A/UdG6XSXZ -bXzIvJakzkTRxPQvTtnF+A/V4rF9hxwB8cGXSywv5eDGmZ91qIsxY7Sv99VqSKNH -dNr9aZHloTvI51e/oramIJ/O3A+TbAS5i+u1DJC2IIFJcAECQQD8iRPTlPIqzjYD -Lg7KYGvwW9TE4ONAhC86kJbzV5o3amlV5duJgnkl/mNlfN1ihA7f3Gx9dfCjfRKp -V1rcjtCBAkEAye2aMw2v1m+MEqcPxyTUzVf5Y8BIXWbk15T43czXec9YclZSOBCX -Dgv4a3Fk+yxQUE0cZUH0U4FJq6mTgpuFJwJASFqZ9KATNlJ4xTZ4BGHV6zrUXkg0 -tDJrObNdnID37XKulW7TFLXuMgWNwvEgmO5POLJ13whglubp5tzhapn8gQJAJz9Z -U0b7wFAaB54VAP31ppvMy0iaSB0xqX05CdNAplpYtJB2lpMS6RYGiMuXdwJb8d+q -/ztcg8aDTSw+kYoszQJBAPBrt694VkGT1k9Be6e5wyVDrE05bkHhFxPk/HMeWMDX -sZqHPs9vVaLBqu/uU84FdwRMOV71RG90g6eUEl7HWsg= ------END RSA PRIVATE KEY----- From 67f925966793c7479adde74b764743144bd42c23 Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Fri, 19 Dec 2008 01:00:49 +0100 Subject: [PATCH 038/124] [IMP] Check SSL bzr revid: stephane@tinyerp.com-20081219000049-zj6nvc7lbd8hs51j --- bin/tools/config.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/bin/tools/config.py b/bin/tools/config.py index e93bf7aec37..ff4568dd848 100644 --- a/bin/tools/config.py +++ b/bin/tools/config.py @@ -28,6 +28,15 @@ import netsvc import logging import release +def check_ssl(): + try: + from OpenSSL import SSL + import socket + + return hasattr(socket, 'ssl') + except: + return False + class configmanager(object): def __init__(self, fname=None): self.options = { @@ -58,7 +67,6 @@ class configmanager(object): 'import_partial': "", 'pidfile': None, 'logfile': None, - 'secure': False, 'smtp_server': 'localhost', 'smtp_user': False, 'smtp_port':25, @@ -69,7 +77,11 @@ class configmanager(object): 'log_level': logging.INFO, 'assert_exit_level': logging.WARNING, # level above which a failed assert will be raise } - + + hasSSL = check_ssl() + if hasSSL: + self.options['secure'] = False + loglevels = dict([(getattr(netsvc, 'LOG_%s' % x), getattr(logging, x)) for x in ('CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG', 'DEBUG_RPC')]) version = "%s %s" % (release.description, release.version) @@ -96,7 +108,8 @@ class configmanager(object): parser.add_option('--debug', dest='debug_mode', action='store_true', default=False, help='enable debug mode') parser.add_option('--log-level', dest='log_level', type='choice', choices=loglevels.keys(), help='specify the level of the logging. Accepted values: ' + str(loglevels.keys())) parser.add_option("--assert-exit-level", dest='assert_exit_level', type="choice", choices=loglevels.keys(), help="specify the level at which a failed assertion will stop the server. Accepted values: " + str(loglevels.keys())) - parser.add_option("-S", "--secure", dest="secure", action="store_true", help="launch server over https instead of http", default=False) + if hasSSL: + parser.add_option("-S", "--secure", dest="secure", action="store_true", help="launch server over https instead of http", default=False) parser.add_option('--email-from', dest='email_from', default='', help='specify the SMTP email address for sending email') parser.add_option('--smtp', dest='smtp_server', default='', help='specify the SMTP server for sending email') From a30219ad25caafd33a837c3d71f1bc0bcfd91067 Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Fri, 19 Dec 2008 01:06:50 +0100 Subject: [PATCH 039/124] [FIX] Use secure if necessary bzr revid: stephane@tinyerp.com-20081219000650-h454lhyj9juz0t25 --- bin/tools/config.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/bin/tools/config.py b/bin/tools/config.py index ff4568dd848..30f4902cb73 100644 --- a/bin/tools/config.py +++ b/bin/tools/config.py @@ -170,9 +170,16 @@ class configmanager(object): # the same for the pidfile if self.options['pidfile'] in ('None', 'False'): self.options['pidfile'] = False - - for arg in ('interface', 'port', 'db_name', 'db_user', 'db_password', 'db_host', - 'db_port', 'logfile', 'pidfile', 'secure', 'smtp_ssl', 'smtp_port', 'email_from', 'smtp_server', 'smtp_user', 'smtp_password', 'price_accuracy', 'netinterface', 'netport', 'db_maxconn', 'import_partial', 'addons_path'): + + keys = ['interface', 'port', 'db_name', 'db_user', 'db_password', 'db_host', + 'db_port', 'logfile', 'pidfile', 'smtp_ssl', 'smtp_port', + 'email_from', 'smtp_server', 'smtp_user', 'smtp_password', 'price_accuracy', + 'netinterface', 'netport', 'db_maxconn', 'import_partial', 'addons_path'] + + if hasSSL: + keys.append('secure') + + for arg in keys: if getattr(opt, arg): self.options[arg] = getattr(opt, arg) From 4007fbd321452eef5911b917b329bd9c423e8891 Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Fri, 19 Dec 2008 01:25:59 +0100 Subject: [PATCH 040/124] [FIX] SSL bzr revid: stephane@tinyerp.com-20081219002559-1hj909l5d2l0bphb --- bin/tools/config.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/bin/tools/config.py b/bin/tools/config.py index 30f4902cb73..595953e4ab6 100644 --- a/bin/tools/config.py +++ b/bin/tools/config.py @@ -73,14 +73,12 @@ class configmanager(object): 'smtp_password': False, 'stop_after_init': False, # this will stop the server after initialization 'price_accuracy': 2, - + 'secure' : False, 'log_level': logging.INFO, 'assert_exit_level': logging.WARNING, # level above which a failed assert will be raise } hasSSL = check_ssl() - if hasSSL: - self.options['secure'] = False loglevels = dict([(getattr(netsvc, 'LOG_%s' % x), getattr(logging, x)) for x in ('CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG', 'DEBUG_RPC')]) From d8f6486bee8dc0eccb3fa7e8d2d270ff990cde95 Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Fri, 19 Dec 2008 01:37:50 +0100 Subject: [PATCH 041/124] [IMP] Group for the smtp configuration bzr revid: stephane@tinyerp.com-20081219003750-46tbdlmrhusdur8j --- bin/tools/config.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/bin/tools/config.py b/bin/tools/config.py index 595953e4ab6..4f57bd8c216 100644 --- a/bin/tools/config.py +++ b/bin/tools/config.py @@ -109,13 +109,15 @@ class configmanager(object): if hasSSL: parser.add_option("-S", "--secure", dest="secure", action="store_true", help="launch server over https instead of http", default=False) - parser.add_option('--email-from', dest='email_from', default='', help='specify the SMTP email address for sending email') - parser.add_option('--smtp', dest='smtp_server', default='', help='specify the SMTP server for sending email') - parser.add_option('--smtp-port', dest='smtp_port', default='25', help='specify the SMTP port') - parser.add_option('--smtp-ssl', dest='smtp_ssl', default='', help='specify the SMTP server support SSL or not') - parser.add_option('--smtp-user', dest='smtp_user', default='', help='specify the SMTP username for sending email') - parser.add_option('--smtp-password', dest='smtp_password', default='', help='specify the SMTP password for sending email') - parser.add_option('--price_accuracy', dest='price_accuracy', default='2', help='specify the price accuracy') + group = optparse.OptionGroup(parser, "SMTP Configuration") + group.add_option('--email-from', dest='email_from', default='', help='specify the SMTP email address for sending email') + group.add_option('--smtp', dest='smtp_server', default='', help='specify the SMTP server for sending email') + group.add_option('--smtp-port', dest='smtp_port', default='25', help='specify the SMTP port') + group.add_option('--smtp-ssl', dest='smtp_ssl', default='', help='specify the SMTP server support SSL or not') + group.add_option('--smtp-user', dest='smtp_user', default='', help='specify the SMTP username for sending email') + group.add_option('--smtp-password', dest='smtp_password', default='', help='specify the SMTP password for sending email') + group.add_option('--price_accuracy', dest='price_accuracy', default='2', help='specify the price accuracy') + parser.add_option_group(group) group = optparse.OptionGroup(parser, "Modules related options") group.add_option("-g", "--upgrade", action="store_true", dest="upgrade", default=False, help="Upgrade/install/uninstall modules") From 9e195a07dc5dc17116bbca481c18fff2ab84378d Mon Sep 17 00:00:00 2001 From: Mantavya Gajjar Date: Fri, 19 Dec 2008 11:07:16 +0530 Subject: [PATCH 042/124] improvements in the server action labels, views, and some conditions for the required fields bzr revid: mga@tinyerp.com-20081219053716-f4bzc5xy4qxgly55 --- bin/addons/base/base_data.xml | 1 + bin/addons/base/ir/ir.xml | 35 ++++++++++++-------------------- bin/addons/base/ir/ir_actions.py | 6 +++--- 3 files changed, 17 insertions(+), 25 deletions(-) diff --git a/bin/addons/base/base_data.xml b/bin/addons/base/base_data.xml index 4777b7ea4f0..442147434bd 100644 --- a/bin/addons/base/base_data.xml +++ b/bin/addons/base/base_data.xml @@ -2877,5 +2877,6 @@ Tiny sprl + diff --git a/bin/addons/base/ir/ir.xml b/bin/addons/base/ir/ir.xml index c3987d05fa7..f935a4801b8 100644 --- a/bin/addons/base/ir/ir.xml +++ b/bin/addons/base/ir/ir.xml @@ -1153,40 +1153,35 @@ - - - - - + + + - - - + + + - - - - + + + - - - - + + - @@ -1206,21 +1201,17 @@ - - - - - diff --git a/bin/addons/base/ir/ir_actions.py b/bin/addons/base/ir/ir_actions.py index d8b24c86787..24c99e18d69 100644 --- a/bin/addons/base/ir/ir_actions.py +++ b/bin/addons/base/ir/ir_actions.py @@ -364,7 +364,7 @@ server_object_lines() # Actions that are run on the server side # class actions_server(osv.osv): - + def _select_signals(self, cr, uid, context={}): cr.execute("select distinct t.signal as key, t.signal || ' - [ ' || w.osv || ' ] ' as val from wkf w, wkf_activity a, wkf_transition t "\ " where w.id = a.wkf_id " \ @@ -376,14 +376,14 @@ class actions_server(osv.osv): if not rs[0] == None and not rs[1] == None: res.append(rs) return res - + _name = 'ir.actions.server' _table = 'ir_act_server' _sequence = 'ir_actions_id_seq' _order = 'sequence' _columns = { 'name': fields.char('Action Name', required=True, size=64), - 'condition' : fields.char('Condition', size=256), + 'condition' : fields.char('Condition', size=256, required=True), 'sub_condition' : fields.char('Condition', size=256), 'state': fields.selection([ ('client_action','Client Action'), From 334794fd299d37ad2b504ac10060a46cbc286b5b Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Fri, 19 Dec 2008 07:22:08 +0100 Subject: [PATCH 043/124] [FIX] Remove the ssl directory from the setup.py lp bug: https://launchpad.net/bugs/309575 fixed bzr revid: stephane@tinyerp.com-20081219062208-o4l0j7vdeosy3pjs --- setup.py | 1 - 1 file changed, 1 deletion(-) diff --git a/setup.py b/setup.py index d7de94a7850..4854daa0c8d 100755 --- a/setup.py +++ b/setup.py @@ -155,7 +155,6 @@ setup(name = name, 'openerp-server.addons', 'openerp-server.ir', 'openerp-server.osv', - 'openerp-server.ssl', 'openerp-server.service', 'openerp-server.tools', 'openerp-server.report', From 61caf30b11064086a58ef83cba8da1494b7986fc Mon Sep 17 00:00:00 2001 From: hmo-tinyerp <> Date: Fri, 19 Dec 2008 15:08:03 +0530 Subject: [PATCH 044/124] replaced '=like' with 'like' to search name of node' bzr revid: hmo-tinyerp-20081219093803-w242aqj3cyuwvmds --- addons/document/document.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/addons/document/document.py b/addons/document/document.py index b8b053eb8b4..d6a87f374a8 100644 --- a/addons/document/document.py +++ b/addons/document/document.py @@ -107,7 +107,7 @@ class node_class(object): where.append( ('parent_id','=',self.object.id) ) where.append( ('res_id','=',False) ) if nodename: - where.append( (fobj._rec_name,'=like',nodename) ) + where.append( (fobj._rec_name,'like',nodename) ) ids = fobj.search(self.cr, self.uid, where+[ ('parent_id','=',self.object and self.object.id or False) ], context=self.context) if self.object and self.root and (self.object.type=='ressource'): ids += fobj.search(self.cr, self.uid, where+[ ('parent_id','=',False) ], context=self.context) @@ -118,7 +118,7 @@ class node_class(object): pool = pooler.get_pool(self.cr.dbname) where = [] if nodename: - where.append(('name','=like',nodename)) + where.append(('name','like',nodename)) if (self.object and self.object.type=='directory') or not self.object2: where.append(('parent_id','=',self.object and self.object.id or False)) else: @@ -144,7 +144,7 @@ class node_class(object): fobj = pool.get('ir.attachment') vargs = [('parent_id','=',False),('res_id','=',False)] if nodename: - vargs.append(('name','=like',nodename)) + vargs.append(('name','like',nodename)) file_ids=fobj.search(self.cr,self.uid,vargs) res = fobj.browse(self.cr, self.uid, file_ids, context=self.context) @@ -174,7 +174,7 @@ class node_class(object): for invalid in INVALID_CHARS: if nodename.find(INVALID_CHARS[invalid]) : nodename=nodename.replace(INVALID_CHARS[invalid],invalid) - where.append(('name','=like',nodename)) + where.append(('name','like',nodename)) ids = obj.search(self.cr, self.uid, where, self.context) res = obj.browse(self.cr, self.uid, ids,self.context) for r in res: @@ -290,7 +290,7 @@ class document_directory(osv.osv): def _get_childs(self, cr, uid, node, nodename=False, context={}): where = [] if nodename: - where.append(('name','=like',nodename)) + where.append(('name','like',nodename)) if object: where.append(('parent_id','=',object.id)) ids = self.search(cr, uid, where, context) From 5091bcea36e39cd4483f9f1692599680f0913e21 Mon Sep 17 00:00:00 2001 From: Mantavya Gajjar Date: Fri, 19 Dec 2008 15:51:11 +0530 Subject: [PATCH 045/124] write a help fields to all fields in the server action bzr revid: mga@tinyerp.com-20081219102111-s5lsj8yi7i9mague --- bin/addons/base/ir/ir_actions.py | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/bin/addons/base/ir/ir_actions.py b/bin/addons/base/ir/ir_actions.py index 24c99e18d69..93b10ba469a 100644 --- a/bin/addons/base/ir/ir_actions.py +++ b/bin/addons/base/ir/ir_actions.py @@ -382,8 +382,8 @@ class actions_server(osv.osv): _sequence = 'ir_actions_id_seq' _order = 'sequence' _columns = { - 'name': fields.char('Action Name', required=True, size=64), - 'condition' : fields.char('Condition', size=256, required=True), + 'name': fields.char('Action Name', required=True, size=64, help="Easy to Refer action by name i.e. One Sales Order -> Many Invoice"), + 'condition' : fields.char('Condition', size=256, required=True, help="Condition that is to be test before execute action, i.e : object.list_price > object.cost_price"), 'sub_condition' : fields.char('Condition', size=256), 'state': fields.selection([ ('client_action','Client Action'), @@ -396,18 +396,18 @@ class actions_server(osv.osv): ('object_create','Create Object'), ('object_write','Write Object'), ('other','Multi Actions'), - ], 'Action Type', required=True, size=32), - 'code':fields.text('Python Code'), - 'sequence': fields.integer('Sequence'), - 'model_id': fields.many2one('ir.model', 'Object', required=True), - 'action_id': fields.many2one('ir.actions.actions', 'Client Action'), - 'trigger_name': fields.selection(_select_signals, string='Trigger Name', size=128), - 'wkf_model_id': fields.many2one('ir.model', 'Workflow on'), - 'trigger_obj_id': fields.many2one('ir.model.fields','Trigger On'), - 'email': fields.char('Email Address', size=512), - 'subject': fields.char('Subject', size=1024, translate=True), - 'message': fields.text('Message', translate=True), - 'mobile': fields.char('Mobile No', size=512), + ], 'Action Type', required=True, size=32, help="Type of the Action that is to be execute"), + 'code':fields.text('Python Code', help="python code to be execute"), + 'sequence': fields.integer('Sequence', help="Important when you deal with the multi action, the execution order will be decided based on this, low number higher priority"), + 'model_id': fields.many2one('ir.model', 'Object', required=True, help="select the obect on which the action will work (read, write, create)"), + 'action_id': fields.many2one('ir.actions.actions', 'Client Action', help="Select the Ation Window, Report, Wizard to be execute"), + 'trigger_name': fields.selection(_select_signals, string='Trigger Name', size=128, help="Select the Signal name that is to be "), + 'wkf_model_id': fields.many2one('ir.model', 'Workflow on', help="Workflow to be execute on which model"), + 'trigger_obj_id': fields.many2one('ir.model.fields','Trigger On', help="select the object from the model on which the workflow will execute"), + 'email': fields.char('Email Address', size=512, help="provides the fiels that will refer to the tiny to fetch the email address, i.e. you select the invoice, then `object.invoice_address_id.email` is the field which give the correct address"), + 'subject': fields.char('Subject', size=1024, translate=True, help="Specify the subject, you can use the fields from the object. like `Hello [[ object.partner_id.name ]]`"), + 'message': fields.text('Message', translate=True, help="Specify the Message, you can use the fields from the object. like `Dear [[ object.partner_id.name ]]`"), + 'mobile': fields.char('Mobile No', size=512, help="provides the fiels that will refer to the tiny to fetch the mobile number, i.e. you select the invoice, then `object.invoice_address_id.mobile` is the field which give the correct mobile number"), 'sms': fields.char('SMS', size=160, translate=True), 'child_ids': fields.many2many('ir.actions.server', 'rel_server_actions', 'server_id', 'action_id', 'Others Actions'), 'usage': fields.char('Action Usage', size=32), @@ -416,8 +416,8 @@ class actions_server(osv.osv): 'fields_lines': fields.one2many('ir.server.object.lines', 'server_id', 'Fields Mapping'), 'record_id':fields.many2one('ir.model.fields', 'Create Id', help="Provide the field name from where the record id stores after the create operations, if its empty, you can not track the new record"), 'write_id':fields.char('Write Id', size=256, help="Provide the field name from where the record id refer for the write operation, if its empty it will refer to the active id of the object"), - 'loop_action':fields.many2one('ir.actions.server', 'Loop Action'), - 'expression':fields.char('Loop Expression', size=512), + 'loop_action':fields.many2one('ir.actions.server', 'Loop Action', help="select the action, which will be executes"), + 'expression':fields.char('Loop Expression', size=512, help="enter the field/expression that will return the list, i.e. select the sale order in Object, and we can have loop on sales order line. Expression = `object.order_line`"), } _defaults = { 'state': lambda *a: 'dummy', From 732284076cf81a478ee1f75acf63690738f1bcfd Mon Sep 17 00:00:00 2001 From: hmo-tinyerp <> Date: Fri, 19 Dec 2008 16:00:32 +0530 Subject: [PATCH 046/124] now binary datas of file will not store in db. removed store=True in datas field of ir.attachment object bzr revid: hmo-tinyerp-20081219103032-fmodunl65i800ol8 --- addons/document/document.py | 82 +++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 44 deletions(-) diff --git a/addons/document/document.py b/addons/document/document.py index d6a87f374a8..75cbdeb2797 100644 --- a/addons/document/document.py +++ b/addons/document/document.py @@ -485,19 +485,15 @@ class document_file(osv.osv): _inherit = 'ir.attachment' def _data_get(self, cr, uid, ids, name, arg, context): result = {} - cr.execute('select id,store_method,datas,store_fname,link from ir_attachment where id in ('+','.join(map(str,ids))+')') - for id,m,d,r,l in cr.fetchall(): - if m=='db': - result[id] = d - elif m=='fs': - try: - path = os.path.join(os.getcwd(), 'filestore', cr.dbname) - value = file(os.path.join(path,r), 'rb').read() - result[id] = base64.encodestring(value) - except: - result[id]='' - else: - result[id] = '' + cr.execute('select id,store_fname,link from ir_attachment where id in ('+','.join(map(str,ids))+')') + for id,r,l in cr.fetchall(): + try: + path = os.path.join(os.getcwd(), 'filestore', cr.dbname) + value = file(os.path.join(path,r), 'rb').read() + result[id] = base64.encodestring(value) + except: + result[id]='' + if context.get('bin_size', False): result[id] = tools.human_size(len(result[id])) @@ -509,26 +505,24 @@ class document_file(osv.osv): def _data_set(self, cr, obj, id, name, value, uid=None, context={}): if not value: return True - if (not context) or context.get('store_method','fs')=='fs': - path = os.path.join(os.getcwd(), "filestore", cr.dbname) - if not os.path.isdir(path): - os.makedirs(path) - flag = None - # This can be improved - for dirs in os.listdir(path): - if os.path.isdir(os.path.join(path,dirs)) and len(os.listdir(os.path.join(path,dirs)))<4000: - flag = dirs - break - flag = flag or create_directory(path) - filename = random_name() - fname = os.path.join(path, flag, filename) - fp = file(fname,'wb') - v = base64.decodestring(value) - fp.write(v) - filesize = os.stat(fname).st_size - cr.execute('update ir_attachment set store_fname=%s,store_method=%s,file_size=%s where id=%s', (os.path.join(flag,filename),'fs',len(v),id)) - else: - cr.execute('update ir_attachment set datas=%s,store_method=%s where id=%s', (Binary(value),'db',id)) + #if (not context) or context.get('store_method','fs')=='fs': + path = os.path.join(os.getcwd(), "filestore", cr.dbname) + if not os.path.isdir(path): + os.makedirs(path) + flag = None + # This can be improved + for dirs in os.listdir(path): + if os.path.isdir(os.path.join(path,dirs)) and len(os.listdir(os.path.join(path,dirs)))<4000: + flag = dirs + break + flag = flag or create_directory(path) + filename = random_name() + fname = os.path.join(path, flag, filename) + fp = file(fname,'wb') + v = base64.decodestring(value) + fp.write(v) + filesize = os.stat(fname).st_size + cr.execute('update ir_attachment set store_fname=%s,store_method=%s,file_size=%s where id=%s', (os.path.join(flag,filename),'fs',len(v),id)) return True _columns = { @@ -543,7 +537,7 @@ class document_file(osv.osv): 'create_date': fields.datetime('Date Created', readonly=True), 'create_uid': fields.many2one('res.users', 'Creator', readonly=True), 'store_method': fields.selection([('db','Database'),('fs','Filesystem'),('link','Link')], "Storing Method"), - 'datas': fields.function(_data_get,method=True,store=True,fnct_inv=_data_set,string='File Content',type="binary"), + 'datas': fields.function(_data_get,method=True,fnct_inv=_data_set,string='File Content',type="binary"), 'store_fname': fields.char('Stored Filename', size=200), 'res_model': fields.char('Attached Model', size=64), #res_model 'res_id': fields.integer('Attached ID'), #res_id @@ -595,8 +589,8 @@ class document_file(osv.osv): cr.commit() try: for f in self.browse(cr, uid, ids, context=context): - if 'datas' not in vals: - vals['datas']=f.datas + #if 'datas' not in vals: + # vals['datas']=f.datas res = content_index(base64.decodestring(vals['datas']), f.datas_fname, f.file_type or None) super(document_file,self).write(cr, uid, ids, { 'index_content': res @@ -635,11 +629,11 @@ class document_file(osv.osv): vals['partner_id']=obj['partner_id'] datas=None - if vals.get('datas',False) and vals.get('link',False) : + if vals.get('link',False) : import urllib datas=base64.encodestring(urllib.urlopen(vals['link']).read()) else: - datas=vals['datas'] + datas=vals.get('datas',False) vals['file_size']= len(datas) if not self._check_duplication(cr,uid,vals): raise except_orm('ValidateError', 'File name must be unique!') @@ -657,12 +651,12 @@ class document_file(osv.osv): def unlink(self,cr, uid, ids, context={}): for f in self.browse(cr, uid, ids, context): - if f.store_method=='fs': - try: - path = os.path.join(os.getcwd(), cr.dbname, 'filestore',f.store_fname) - os.unlink(path) - except: - pass + #if f.store_method=='fs': + try: + path = os.path.join(os.getcwd(), cr.dbname, 'filestore',f.store_fname) + os.unlink(path) + except: + pass return super(document_file, self).unlink(cr, uid, ids, context) document_file() From a47b0aa239704a14c9f4bb8189787e552f312e04 Mon Sep 17 00:00:00 2001 From: Mantavya Gajjar Date: Fri, 19 Dec 2008 16:17:12 +0530 Subject: [PATCH 047/124] merging from the trunk, and small change in the view bzr revid: mga@tinyerp.com-20081219104712-yiovfbb2jddnhu62 --- bin/addons/base/ir/ir.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bin/addons/base/ir/ir.xml b/bin/addons/base/ir/ir.xml index 1b7028e50aa..1490c7a1f2c 100644 --- a/bin/addons/base/ir/ir.xml +++ b/bin/addons/base/ir/ir.xml @@ -1152,7 +1152,7 @@ - + @@ -1228,6 +1228,7 @@ + From 2b237494176535d00942b765c9c8bc1beb991986 Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Fri, 19 Dec 2008 11:55:28 +0100 Subject: [PATCH 048/124] [FIX] OpenSSL is no longer required bzr revid: christophe@cobalt-20081219105528-geqgxmzdx9grz34t --- bin/netsvc.py | 16 +++++++++++++++- bin/openerp-server.py | 17 +++++------------ 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/bin/netsvc.py b/bin/netsvc.py index 888117ba639..cf24ac6a571 100644 --- a/bin/netsvc.py +++ b/bin/netsvc.py @@ -324,7 +324,21 @@ class HttpDaemon(threading.Thread): self.secure = bool(secure) handler_class = (SimpleXMLRPCRequestHandler, SecureXMLRPCRequestHandler)[self.secure] server_class = (SimpleThreadedXMLRPCServer, SecureThreadedXMLRPCServer)[self.secure] - self.server = server_class((interface, port), handler_class, 0) + + if self.secure: + from OpenSSL.SSL import Error as SSLError + else: + class SSLError(Exception): pass + + try: + self.server = server_class((interface, port), handler_class, 0) + except SSLError, e: + Logger().notifyChannel('xml-rpc-ssl', LOG_CRITICAL, "Can't load the certificate and/or the private key files") + sys.exit(1) + except Exception, e: + Logger().notifyChannel('xml-rpc', LOG_CRITICAL, "Error occur when strarting the server daemon: %s" % (e,)) + sys.exit(1) + def attach(self, path, gw): pass diff --git a/bin/openerp-server.py b/bin/openerp-server.py index e0621a87d86..943f13be25b 100755 --- a/bin/openerp-server.py +++ b/bin/openerp-server.py @@ -154,23 +154,16 @@ if tools.config['xmlrpc']: try: port = int(tools.config["port"]) except Exception: - logger.notifyChannel("init", netsvc.LOG_ERROR, "invalid port '%s'!" % (tools.config["port"],)) + logger.notifyChannel("init", netsvc.LOG_CRITICAL, "invalid port: %r" % (tools.config["port"],)) sys.exit(1) interface = tools.config["interface"] secure = tools.config["secure"] - import OpenSSL + httpd = netsvc.HttpDaemon(interface, port, secure) - try: - httpd = netsvc.HttpDaemon(interface, port, secure) - except OpenSSL.SSL.Error, error: - logger.notifyChannel('xml-rpc-ssl', netsvc.LOG_CRITICAL, "Can't load the certificate and/or the private key files" ) - sys.exit(1) - - if tools.config["xmlrpc"]: - xml_gw = netsvc.xmlrpc.RpcGateway('web-services') - httpd.attach("/xmlrpc", xml_gw) - logger.notifyChannel("web-services", netsvc.LOG_INFO, "starting XML-RPC%s services, port %s" % ((tools.config['secure'] and ' Secure' or ''), port)) + xml_gw = netsvc.xmlrpc.RpcGateway('web-services') + httpd.attach("/xmlrpc", xml_gw) + logger.notifyChannel("web-services", netsvc.LOG_INFO, "starting XML-RPC%s services, port %s" % ((tools.config['secure'] and ' Secure' or ''), port)) # #if tools.config["soap"]: From 7f0db457eeaaea08e0e4dd7032aa3006cddee486 Mon Sep 17 00:00:00 2001 From: Mantavya Gajjar Date: Fri, 19 Dec 2008 16:37:46 +0530 Subject: [PATCH 049/124] fix the problem for the rng rules now we can have tabpos in notebook lp bug: https://launchpad.net/bugs/309648 fixed bzr revid: mga@tinyerp.com-20081219110746-qjuz7tdtf9njfn4v --- bin/addons/base/rng/view.rng | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/addons/base/rng/view.rng b/bin/addons/base/rng/view.rng index e40f178d69f..5496f8b16a2 100644 --- a/bin/addons/base/rng/view.rng +++ b/bin/addons/base/rng/view.rng @@ -156,6 +156,7 @@ + From 959ee2e194266866caad4da9d571c5e23c58242a Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Fri, 19 Dec 2008 12:53:35 +0100 Subject: [PATCH 050/124] [IMP] do no create unnecessary cursors bzr revid: christophe@cobalt-20081219115335-z10tva73hsiwg8nk --- .../base/module/wizard/wizard_module_upgrade.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/bin/addons/base/module/wizard/wizard_module_upgrade.py b/bin/addons/base/module/wizard/wizard_module_upgrade.py index 782457c00fd..f689b88c566 100644 --- a/bin/addons/base/module/wizard/wizard_module_upgrade.py +++ b/bin/addons/base/module/wizard/wizard_module_upgrade.py @@ -65,8 +65,7 @@ class wizard_info_get(wizard.interface): 'module_download': '\n'.join(url)} def _check_upgrade_module(self,cr,uid,data,context): - db, pool = pooler.get_db_and_pool(cr.dbname) - cr = db.cursor() + pool = pooler.get_pool(cr.dbname) mod_obj = pool.get('ir.module.module') ids = mod_obj.search(cr, uid, [ ('state', 'in', ['to upgrade', 'to remove', 'to install'])]) @@ -76,8 +75,7 @@ class wizard_info_get(wizard.interface): return 'end' def _upgrade_module(self, cr, uid, data, context): - db, pool = pooler.get_db_and_pool(cr.dbname) - cr = db.cursor() + pool = pooler.get_pool(cr.dbname) mod_obj = pool.get('ir.module.module') ids = mod_obj.search(cr, uid, [('state', 'in', ['to upgrade', 'to remove', 'to install'])]) unmet_packages = [] @@ -158,8 +156,7 @@ class wizard_info_get_simple(wizard.interface): 'module_download': '\n'.join(url)} def _check_upgrade_module(self,cr,uid,data,context): - db, pool = pooler.get_db_and_pool(cr.dbname) - cr = db.cursor() + pool = pooler.get_pool(cr.dbname) mod_obj = pool.get('ir.module.module') ids = mod_obj.search(cr, uid, [ ('state', 'in', ['to upgrade', 'to remove', 'to install'])]) @@ -169,8 +166,7 @@ class wizard_info_get_simple(wizard.interface): return 'end' def _upgrade_module(self, cr, uid, data, context): - db, pool = pooler.get_db_and_pool(cr.dbname) - cr = db.cursor() + pool = pooler.get_pool(cr.dbname) mod_obj = pool.get('ir.module.module') ids = mod_obj.search(cr, uid, [('state', 'in', ['to upgrade', 'to remove', 'to install'])]) unmet_packages = [] From 045b32b7b065d72a21ed4ec15d2ca70993b99283 Mon Sep 17 00:00:00 2001 From: Mustufa Rangwala Date: Fri, 19 Dec 2008 17:50:49 +0530 Subject: [PATCH 051/124] added method_test on base_module_quality bzr revid: mra@tinyerp.com-20081219122049-heky9f41aljdf142 --- .../method_test/__init__.py | 24 ++++++ .../method_test/method_test.py | 82 +++++++++++++++++++ .../wizard/module_quality_check.py | 28 ++----- 3 files changed, 113 insertions(+), 21 deletions(-) create mode 100644 addons/base_module_quality/method_test/__init__.py create mode 100644 addons/base_module_quality/method_test/method_test.py diff --git a/addons/base_module_quality/method_test/__init__.py b/addons/base_module_quality/method_test/__init__.py new file mode 100644 index 00000000000..79850888f41 --- /dev/null +++ b/addons/base_module_quality/method_test/__init__.py @@ -0,0 +1,24 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2008 Tiny SPRL (). All Rights Reserved +# $Id$ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +############################################################################## + + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/base_module_quality/method_test/method_test.py b/addons/base_module_quality/method_test/method_test.py new file mode 100644 index 00000000000..84f3f167247 --- /dev/null +++ b/addons/base_module_quality/method_test/method_test.py @@ -0,0 +1,82 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2008 Tiny SPRL (). All Rights Reserved +# $Id$ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +############################################################################## + + +import os +from tools import config + +from base_module_quality import base_module_quality +import pooler + +class quality_test(base_module_quality.abstract_quality_check): + + def __init__(self): + self.result = """ +Method Test: +------------ + + This test checks if the class method has exception or not. + + +""" + self.bool_installed_only = False + return None + + def run_test(self, module_path, module_name=None, cr=None, uid=None): + pool = pooler.get_pool(cr.dbname) + ids2 = pool.get('ir.model.data').search(cr, uid, [('module','=', module_name), ('model','=','ir.model')]) + obj_list = [] + for mod in pool.get('ir.model.data').browse(cr, uid, ids2): + object_name = mod.name.split('_') + object_name.pop(0) + object_name = '.'.join(object_name) + obj_list.append(str(object_name)) + result={} + self.result += "Module Name:" + module_name + '\n' + '===============\n' + for obj in obj_list: + temp=[] + try: + res = pool.get(obj).search(cr, uid, []) + temp.append('Ok') + except: + temp.append('Exception') + try: + res1 = pool.get(obj).fields_view_get(cr, uid,) + temp.append('Ok') + except: + temp.append('Exception') + try: + res2 = pool.get(obj).read(cr, uid, []) + temp.append('Ok') + except: + temp.append('Exception') + result[obj] = temp + self.result+=("%-40s %-12s \t %-16s %-12s")%('Object Name'.ljust(40),'search','fields_view_get','read') + self.result+='\n' + for res in result: + self.result+=("%-40s %-12s \t %-16s \t %-12s")%(res.ljust(40),result[res][0],result[res][1],result[res][2]) + self.result+="\n" + return None + + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: + diff --git a/addons/base_module_quality/wizard/module_quality_check.py b/addons/base_module_quality/wizard/module_quality_check.py index 9a5ec9391dd..da067551e6d 100644 --- a/addons/base_module_quality/wizard/module_quality_check.py +++ b/addons/base_module_quality/wizard/module_quality_check.py @@ -30,29 +30,17 @@ import os #TODO: configure pylint #TODO: implement the speed test #TODO: implement the simple test -#TODO: add cheks: do the class quality_check inherits the class abstract_quality_check? +#TODO: add cheks: do the class quality_check inherits the class abstract_quality_check? #TODO: improve translability #To keep or not? to be discussed... -#~ form_check = ''' -#~
- #~ -#~ ''' - -#~ fields_check = { - #~ 'test': { - #~ 'string':'Tests', 'type':'selection', 'required':True, - #~ 'selection': [('pylint', 'Pylint'), ('othertest','other')], - #~ 'default': lambda *args: 'pylint' - #~ }, - #~ } view_form = """
- +
""" @@ -71,8 +59,8 @@ class wiz_quality_check(wizard.interface): from tools import config pool = pooler.get_pool(cr.dbname) module_data = pool.get('ir.module.module').browse(cr, uid, data['ids']) - list_folders = os.listdir(config['addons_path']+'/base_module_quality/') + module_name = module_data[0].name for item in list_folders: path = config['addons_path']+'/base_module_quality/'+item if os.path.exists(path+'/'+item+'.py') and item not in ['report', 'wizard', 'security']: @@ -83,18 +71,16 @@ class wiz_quality_check(wizard.interface): x2 = getattr(x, item) x3 = getattr(x2, item) val = x3.quality_test() - if not val.bool_installed_only or module_data[0].state == "installed": + if (not val.bool_installed_only or module_data[0].state == "installed") and item == 'method_test': + val.run_test(str(module_path), module_name, cr, uid) + elif not val.bool_installed_only or module_data[0].state == "installed" : val.run_test(str(module_path)) else: val.result += "The module has to be installed before running this test." - string_ret += val.result - print val.result_details return {'general_info':string_ret} - - states = { #To keep or not? to be discussed... @@ -107,8 +93,8 @@ class wiz_quality_check(wizard.interface): 'actions': [_check], 'result': {'type':'form', 'arch':view_form, 'fields':view_field, 'state':[('end','Ok')]}, }, + } - } wiz_quality_check('base.module.quality') # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: From 57801a9d60f775ec1ef4ee414ccab3d5874851cd Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Fri, 19 Dec 2008 13:49:07 +0100 Subject: [PATCH 052/124] [FIX] Add some files bzr revid: stephane@tinyerp.com-20081219124907-38g1q2r0895mr2ho --- MANIFEST.in | 2 ++ setup.py | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/MANIFEST.in b/MANIFEST.in index 7d853e57b3c..b342fcecefe 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,6 @@ include README +include bin/server.cert +include bin/server.pkey recursive-include doc * recursive-include man * recursive-include bin *xml *xsl *sql *rml *sxw *csv *rng diff --git a/setup.py b/setup.py index 4854daa0c8d..1db7e07914a 100755 --- a/setup.py +++ b/setup.py @@ -85,6 +85,9 @@ def data_files(): os.chdir('..') for (dp,dn,names) in os.walk('doc'): files.append((dp, map(lambda x: opj(dp, x), names))) + files.append(('.', [opj('bin', 'import_xml.rng'), + opj('bin', 'server.pkey'), + opj('bin', 'server.cert')])) else: man_directory = opj('share', 'man') files.append((opj(man_directory, 'man1'), ['man/openerp-server.1'])) @@ -132,7 +135,8 @@ options = { "packages": ["lxml", "lxml.builder", "lxml._elementpath", "lxml.etree", "lxml.objectify", "decimal", "xml", "xml.dom", "xml.xpath", "encodings","mx.DateTime","wizard","pychart","PIL", "pyparsing", - "pydot","asyncore","asynchat", "reportlab", "vobject", "HTMLParser"], + "pydot","asyncore","asynchat", "reportlab", "vobject", + "HTMLParser", "OpenSSL", "select"], "excludes" : ["Tkconstants","Tkinter","tcl"], } } From 643441fa49daa3dcab47fee8ff82985ff86be3dd Mon Sep 17 00:00:00 2001 From: Amit Mendapara Date: Fri, 19 Dec 2008 18:37:58 +0530 Subject: [PATCH 053/124] * Fixed ir_model_field (custom reference field) bzr revid: ame@tinyerp.com-20081219130758-2xfdw1jogpl21io6 --- bin/addons/base/ir/ir.xml | 8 ++++---- bin/osv/orm.py | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/bin/addons/base/ir/ir.xml b/bin/addons/base/ir/ir.xml index 1490c7a1f2c..2d08ca75e26 100644 --- a/bin/addons/base/ir/ir.xml +++ b/bin/addons/base/ir/ir.xml @@ -704,8 +704,8 @@ 'readonly': [('ttype','!=','one2many'), ('ttype','!=','many2one'), ('ttype','!=','many2many')]}"/> - - + + @@ -782,8 +782,8 @@ - - + + diff --git a/bin/osv/orm.py b/bin/osv/orm.py index 9b3487d71df..23c8efab6ff 100644 --- a/bin/osv/orm.py +++ b/bin/osv/orm.py @@ -1715,8 +1715,11 @@ class orm(orm_template): 'translate': (field['translate']), #'select': int(field['select_level']) } + if field['ttype'] == 'selection': self._columns[field['name']] = getattr(fields, field['ttype'])(eval(field['selection']), **attrs) + elif field['ttype'] == 'reference': + self._columns[field['name']] = getattr(fields, field['ttype'])(selection=eval(field['selection']), **attrs) elif field['ttype'] == 'many2one': self._columns[field['name']] = getattr(fields, field['ttype'])(field['relation'], **attrs) elif field['ttype'] == 'one2many': From aee47aa5e2eddc8972f163d79e545d1fe6967324 Mon Sep 17 00:00:00 2001 From: Mantavya Gajjar Date: Fri, 19 Dec 2008 18:42:35 +0530 Subject: [PATCH 054/124] now its possible to have the dynamic currency on the product label * add new field called company_id this will be appear on the form in extended view only lp bug: https://launchpad.net/bugs/309565 fixed bzr revid: mga@tinyerp.com-20081219131235-4ixr7lkboozsuofe --- addons/product/product.py | 6 +++++- addons/product/product_view.xml | 1 + addons/product/report/product_label.xml | 1 + addons/product/report/product_label.xsl | 2 +- 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/addons/product/product.py b/addons/product/product.py index 35d0bb4182e..06343eda249 100644 --- a/addons/product/product.py +++ b/addons/product/product.py @@ -271,8 +271,9 @@ class product_template(osv.osv): 'loc_rack': fields.char('Rack', size=16), 'loc_row': fields.char('Row', size=16), 'loc_case': fields.char('Case', size=16), + 'company_id': fields.many2one('res.company', 'Company'), } - + def _get_uom_id(self, cr, uid, *args): cr.execute('select id from product_uom order by id limit 1') res = cr.fetchone() @@ -284,6 +285,9 @@ class product_template(osv.osv): return False _defaults = { + 'company_id': lambda self, cr, uid, context: \ + self.pool.get('res.users').browse(cr, uid, uid, + context=context).company_id.id, 'type': lambda *a: 'product', 'list_price': lambda *a: 1, 'cost_method': lambda *a: 'standard', diff --git a/addons/product/product_view.xml b/addons/product/product_view.xml index fa9ff515aef..1aacaa39691 100644 --- a/addons/product/product_view.xml +++ b/addons/product/product_view.xml @@ -101,6 +101,7 @@ +
diff --git a/addons/product/report/product_label.xml b/addons/product/report/product_label.xml index ba7d202cb81..beb8d22d6e2 100644 --- a/addons/product/report/product_label.xml +++ b/addons/product/report/product_label.xml @@ -6,5 +6,6 @@ + diff --git a/addons/product/report/product_label.xsl b/addons/product/report/product_label.xsl index 2df7e8d3e2c..f76cea07e94 100644 --- a/addons/product/report/product_label.xsl +++ b/addons/product/report/product_label.xsl @@ -66,7 +66,7 @@ - EUR + From bbb26dacc11d15bfb3e2d37d41473829868e91e5 Mon Sep 17 00:00:00 2001 From: Mantavya Gajjar Date: Fri, 19 Dec 2008 19:04:45 +0530 Subject: [PATCH 055/124] add confirm attribute to the button bzr revid: mga@tinyerp.com-20081219133445-jpo3zj3jnwp2jcwo --- bin/addons/base/rng/view.rng | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/addons/base/rng/view.rng b/bin/addons/base/rng/view.rng index 5496f8b16a2..6996a2fedb1 100644 --- a/bin/addons/base/rng/view.rng +++ b/bin/addons/base/rng/view.rng @@ -336,6 +336,7 @@ + From d1b708e379c30bd0792ed56b953965ac6802a373 Mon Sep 17 00:00:00 2001 From: hmo-tinyerp <> Date: Fri, 19 Dec 2008 19:21:02 +0530 Subject: [PATCH 056/124] * add picking_id in list view & form view of stock move and can be able to cancel stock move line in packing form bzr revid: hmo-tinyerp-20081219135102-mrf5fl593gazsehc --- addons/stock/stock_view.xml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml index 20aa537f08b..f8f3837e06b 100644 --- a/addons/stock/stock_view.xml +++ b/addons/stock/stock_view.xml @@ -553,6 +553,7 @@